v7‰PNG  IHDR Ÿ f Õ†C1 sRGB ®Îé gAMA ± üa pHYs à ÃÇo¨d GIDATx^íÜL”÷ð÷Yçªö("Bh_ò«®¸¢§q5kÖ*:þ0A­ºšÖ¥]VkJ¢M»¶f¸±8\k2íll£1]q®ÙÔ‚ÆT PK\*  helpdesk/db.xmlnu[
PK\W֨ $helpdesk/library/HelpdeskMessage.phpnu[_ticket)) { $this->_ticket = $this->getDi()->helpdeskTicketTable->load($this->ticket_id); } return $this->_ticket; } public function setAttachments($attachments) { $this->attachments = $this->serializeIds($attachments); } public function getAttachments() { return $this->unserializeIds($this->attachments); } public function loadGetAttachments() { if (is_null($this->_attachments)) $this->_attachments = $this->getDi()->uploadTable->loadIds($this->getAttachments()); return $this->_attachments; } public function delete() { foreach ($this->loadGetAttachments() as $att) { /* @var $att Upload */ if ($att->prefix == Bootstrap_Helpdesk::ATTACHMENT_UPLOAD_PREFIX) $att->delete(); } parent::delete(); } } class HelpdeskMessageTable extends Am_Table { protected $_key = 'message_id'; protected $_table = '?_helpdesk_message'; protected $_recordClass = 'HelpdeskMessage'; public function insert(array $values, $returnInserted = false) { if (empty($values['dattm'])) $values['dattm'] = $this->getDi()->sqlDateTime; return parent::insert($values, $returnInserted); } function selectLast($num) { return $this->selectObjects("SELECT m.*, u.user_id, u.name_f AS u_name_f, u.name_l AS u_name_l, u.login AS u_login, u.email AS u_email, a.admin_id, a.name_f AS a_name_f, a.name_l AS a_name_l, a.login AS a_login, a.email AS a_email, t.ticket_mask as ticket_mask, t.subject as subject FROM ?_helpdesk_message m LEFT JOIN ?_helpdesk_ticket t USING (ticket_id) LEFT JOIN ?_user u ON t.user_id = u.user_id LEFT JOIN ?_admin a ON m.admin_id = a.admin_id ORDER BY m.dattm DESC LIMIT ?d", $num); } }PK\ wgg%helpdesk/library/HelpdeskCategory.phpnu[getTable()->getName(); $max = $this->getAdapter()->selectCell("SELECT MAX(sort_order) FROM {$table_name}"); $this->sort_order = $max + 1; return parent::insert($reload); } public function delete() { $ret = parent::delete(); $table_name = $this->getTable()->getName(); $this->getAdapter()->query("UPDATE {$table_name} SET sort_order=sort_order-1 WHERE sort_order>?", $this->sort_order); return $ret; } } class HelpdeskCategoryTable extends Am_Table { protected $_key = 'category_id'; protected $_table = '?_helpdesk_category'; protected $_recordClass = 'HelpdeskCategory'; function getOptions($include_disabled=false) { return $this->getAdapter()->selectCol("SELECT category_id AS ARRAY_KEY, title FROM ?_helpdesk_category WHERE 1 {AND is_disabled=?} ORDER BY sort_order", $include_disabled ? DBSIMPLE_SKIP : 0); } }PK\62 helpdesk/library/HelpdeskFaq.phpnu[getTable()->getName(); $max = $this->getAdapter()->selectCell("SELECT MAX(sort_order) FROM {$table_name}"); $this->sort_order = $max + 1; return parent::insert($reload); } public function delete() { $ret = parent::delete(); $table_name = $this->getTable()->getName(); $this->getAdapter()->query("UPDATE {$table_name} SET sort_order=sort_order-1 WHERE sort_order>?", $this->sort_order); return $ret; } } class HelpdeskFaqTable extends Am_Table { protected $_key = 'faq_id'; protected $_table = '?_helpdesk_faq'; protected $_recordClass = 'HelpdeskFaq'; function getCategories() { return $this->_db->selectCol("SELECT DISTINCT category, category AS ? FROM ?_helpdesk_faq WHERE category IS NOT NULL ORDER BY category", DBSIMPLE_ARRAY_KEY); } } PK\rN&2'helpdesk/library/Am/Report/Helpdesk.phpnu[title = ___('Count of User Messages in Helpdesk'); } public function getPointField() { return 'hm.dattm'; } /** @return Am_Query */ public function getQuery() { $q = new Am_Query($this->getDi()->helpdeskMessageTable, 'hm'); $q->clearFields(); $q->addField('COUNT(message_id)', 'cnt'); $q->addWhere('admin_id IS NULL'); return $q; } function getLines() { $ret = array(); $ret[] = new Am_Report_Line('cnt', ___('Count of Messages')); return $ret; } }PK\b!4helpdesk/library/Am/Helpdesk/Strategy/Admin/User.phpnu[getDi()->router;; return $router->assemble(array( 'module' => 'helpdesk', 'controller' => $this->getControllerName(), 'user_id' => $this->getUserId() ) + $params, $route, true); } public function setUserId($user_id) { $this->user_id = $user_id; } public function getUserId() { return $this->user_id; } public function createNewTicketForm() { $form = parent::createNewTicketForm(); $user = $this->getDi()->userTable->load($this->getUserId()); $text = HTML_QuickForm2_Factory::createElement('html', 'loginOrEmail'); $text->setLabel(___('User')) ->setHtml(sprintf('
%s %s (%s)
', $user->name_f, $user->name_l, $user->login )); $text->toggleFrozen(true); $form->insertBefore($text, $form->getElementById('loginOrEmail')); $form->removeChild( $form->getElementById('loginOrEmail') ); $loginOrEmail = HTML_QuickForm2_Factory::createElement('hidden', 'loginOrEmail'); $loginOrEmail->setValue($user->login); $form->addElement($loginOrEmail); $user_id = HTML_QuickForm2_Factory::createElement('hidden', 'user_id'); $user_id->setValue($user->pk()); $form->addElement($user_id); return $form; } } PK\YT.helpdesk/library/Am/Helpdesk/Strategy/User.phpnu[_identity = $user_id ? $user_id : $this->getDi()->auth->getUserId(); } public function isMessageAvalable($message) { return!($message->type == 'comment' && $message->admin_id); } public function isMessageForReply($message) { if ($message->type == 'comment') { return false; } else { return (boolean) $message->admin_id; } } public function fillUpMessageIdentity($message) { return $message; } public function fillUpTicketIdentity($ticket, $request) { $ticket->user_id = $this->getIdentity(); return $ticket; } public function getTicketStatusAfterReply($message) { if ($message->type == 'comment') { return $message->getTicket()->status; } else { return 'awaiting_admin_response'; } } public function onAfterInsertMessage($message, $ticket) { if ($this->getDi()->config->get('helpdesk.notify_new_message_admin', 1)) { $user = $this->getUser($message->getTicket()->user_id); $recepients[] = Am_Mail_Template::TO_ADMIN; $exists = array($this->getDi()->config->get('admin_email') => 1); if (($owner = $message->getTicket()->getOwner()) && !isset($exists[$owner->email])) { $recepients[] = $owner; $exists[$owner->email] = 1; } foreach ($message->getTicket()->getWatchers() as $w) { if (!isset($exists[$w->email])) { $recepients[] = $w; $exists[$w->email] = 1; } } foreach ($recepients as $recepient) { if ($et = Am_Mail_Template::load('helpdesk.notify_new_message_admin')) { $et->setTicket($message->getTicket()); $et->setUser($user); $et->setMessage($message); $et->setUrl($this->getDi()->url('helpdesk/admin/ticket/'.$message->getTicket()->ticket_mask,null,false,true)); $et->send($recepient); } } } } public function onAfterInsertTicket($ticket) { if ($this->getDi()->config->get('helpdesk.new_ticket')) { $user = $this->getUser($ticket->user_id); if ($user->unsubscribed) return; $et = Am_Mail_Template::load('helpdesk.new_ticket', $user->lang); if ($et) { $et->setTicket($ticket); $et->setUser($user); $et->setUrl(sprintf('%s/helpdesk/ticket/%s', $this->getDi()->config->get('root_surl'), $ticket->ticket_mask) ); $et->send($user); } } } public function onViewTicket($ticket) { if ($ticket->has_new) { $ticket->updateQuick('has_new', 0); } } public function getAdminName($message) { if ($this->getDi()->modules->get('helpdesk')->getConfig('disclosure_admin')) { $admin = $this->getAdmin($message->admin_id); return $admin ? $admin->getName() : ___('Administrator'); } else { return ___('Administrator'); } } public function getTemplatePath() { return 'helpdesk'; } public function getIdentity() { return $this->_identity; } public function canViewTicket($ticket) { return $ticket->user_id == $this->getIdentity(); } public function canViewMessage($message) { return $message->getTicket()->user_id == $this->getIdentity(); } public function canEditTicket($ticket) { return $ticket->user_id == $this->getIdentity() && $ticket->status != HelpdeskTicket::STATUS_CLOSED; } public function canEditMessage($message) { return $message->type == 'comment' && ($message->getTicket()->user_id == $this->getIdentity()); } public function canUseSnippets() { return false; } public function canUseFaq() { return false; } public function canEditOwner($ticket) { return false; } public function canEditWatcher($ticket) { return false; } public function canViewOwner($ticket) { return false; } public function canEditCategory($ticket) { return false; } public function createForm() { $form = new Am_Form(); $form->addCsrf(); $form->setAttribute('class', 'am-helpdesk-form'); return $form; } function getCategoryOptions() { $op = $this->getDi()->helpdeskCategoryTable->getOptions(); $user = $this->getUser($this->getIdentity()); foreach (array_keys($op) as $id) { if (!$this->getDi()->resourceAccessTable->userHasAccess($user, $id, HelpdeskCategory::ACCESS_TYPE)) { unset($op[$id]); } } return $op; } public function createNewTicketForm() { $form = parent::createNewTicketForm(); if ($this->getDi()->helpdeskFaqTable->countBy()) { $id = $form->getId(); $s_url = json_encode($this->getDi()->url('helpdesk/faq/suggest',null,false)); $form->addScript()->setScript(<<'); } jQuery("#am-helpdesk-faq-q-result").empty(); return; } jQuery.get($s_url, {q:jQuery(this).val()}, function(html){ jQuery("#am-helpdesk-faq-q-result").empty().append(html); }) return false; }); CUT ); } return $form; } public function addUpload($form) { if (!$this->getDi()->modules->get('helpdesk')->getConfig('does_not_allow_attachments')) { $t = Am_Html::escape(___('Add Attachments')); $form->addHtml()->setHtml(<<$t CUT ); $form->addUpload('attachments', array('multiple' => 1), array('prefix' => Bootstrap_Helpdesk::ATTACHMENT_UPLOAD_PREFIX, 'secure' => true)) ->setLabel(___('Attachments')) ->setJsOptions(<<assembleUrl(array( 'ticket' => $ticket->ticket_mask ), 'helpdesk-ticket'); } public function newUrl() { return $this->assembleUrl(array(), 'helpdesk-new'); } protected function getControllerName() { return 'index'; } }PK\vxZZ2helpdesk/library/Am/Helpdesk/Strategy/Abstract.phpnu[_di = $di; } /** * @return Am_Di */ protected function getDi() { return $this->_di; } function onAfterInsertTicket($ticket) { } public function assembleUrl($params, $route = 'default') { $router = $this->getDi()->router;; return $router->assemble(array( 'module' => 'helpdesk', 'controller' => $this->getControllerName(), ) + $params, $route, true); } abstract public function ticketUrl($ticket); abstract public function newUrl(); /** * @return Am_Helpdesk_Strategy_Abstract */ public static function create(Am_Di $di) { return defined('AM_ADMIN') ? ($di->request->getControllerName() == 'admin-user' ? new Am_Helpdesk_Strategy_Admin_User($di) : new Am_Helpdesk_Strategy_Admin($di) ) : new Am_Helpdesk_Strategy_User($di); } function getCategoryOptions() { return $this->getDi()->helpdeskCategoryTable->getOptions(); } /** * @return Am_Form */ public function createNewTicketForm() { $form = $this->createForm(); if ($options = $this->getCategoryOptions()) { $form->addAdvradio('category_id') ->setLabel(___('Category of question')) ->loadOptions($options) ->addRule('required'); $fields = $this->getDi()->helpdeskTicketTable->customFields()->getAll(); foreach ($this->getDi()->helpdeskCategoryTable->findByIsDisabled(0) as $c) { foreach (Am_Record::unserializeList($c->fields) as $fn) { if (isset($fields[$fn])) { $fields[$fn]->name = sprintf('category[%d][%s]', $c->pk(), $_ = $fields[$fn]->name); $fields[$fn]->addToQF2($form, array(), array(), HTML_QuickForm2_Rule::ONBLUR_CLIENT); $fields[$fn]->name = $_; } } } $form->addScript() ->setScript(<<getDi()->helpdeskTicketTable->customFields()->getAll()) { foreach ($fields as $field) { $field->name = sprintf('additional[%s]', $_ = $field->name); $field->addToQF2($form, array(), array(), HTML_QuickForm2_Rule::ONBLUR_CLIENT); $field->name = $_; } } $subject = $form->addText('subject', array('class' => 'row-wide el-wide')) ->setLabel(___('Subject')); $subject->addRule('required'); $subject->addRule('maxlength', ___('Your subject is too verbose'), 255); $subject->addRule('nonempty', ___('Subject can not be empty')); $content = $form->addTextarea('content', array('class' => 'row-wide el-wide', 'rows' => 12)) ->setLabel(___('Message')); $content->addRule('required'); $content->addRule('nonempty', ___('Message can not be empty')); $this->addUpload($form); return $form; } function isShowAvatar() { return $this->getDi()->modules->get('helpdesk')->getConfig('show_gravatar') || ($this->getDi()->plugins_misc->isEnabled('avatar') && $this->getDi()->modules->get('helpdesk')->getConfig('show_avatar')); } public function getAvatar($message) { if ($this->getDi()->plugins_misc->isEnabled('avatar') && $this->getDi()->modules->get('helpdesk')->getConfig('show_avatar')) { if ($message->admin_id) { return $this->getAdminAvatar($message); } else { return $this->getUserAvatar($message); } } elseif ($this->getDi()->modules->get('helpdesk')->getConfig('show_gravatar')) { if ($message->admin_id) { return $this->getAdminGravatar($message); } else { return $this->getUserGravatar($message); } } else { return ''; } } public function getAdminGravatar($message) { $admin = $this->getAdmin($message->admin_id); return $admin ? sprintf('', '//www.gravatar.com/avatar/' . md5(strtolower(trim($admin->email))) . '?s=40&d=mm') : ''; } public function getUserGravatar($message) { $user = $this->getUser($message->getTicket()->user_id); return $user ? sprintf('', '//www.gravatar.com/avatar/' . md5(strtolower(trim($user->email))) . '?s=40&d=mm') : ''; } public function getAdminAvatar($message) { $admin = $this->getAdmin($message->admin_id); return $admin ? sprintf('', $this->getDi()->url('misc/avatar/' . $admin->avatar)) : ''; } public function getUserAvatar($message) { $user = $this->getUser($message->getTicket()->user_id); return $user ? sprintf('', $this->getDi()->url('misc/avatar/' . $user->avatar)) : ''; } public function getName($message) { return $message->admin_id ? $this->getAdminName($message) : $this->getUserName($message); } public function getUserName($message) { $user = $this->getUser($message->getTicket()->user_id); $name = trim("{$user->name_f} {$user->name_l}"); return sprintf('%s%s', $user->login, $name ? sprintf(' (%s)', $name) : '' ); } protected function getAdmin($admin_id) { return $this->getDi()->adminTable->load($admin_id, false); } protected function getUser($user_id) { return $this->getDi()->userTable->load($user_id); } }PK\| /helpdesk/library/Am/Helpdesk/Strategy/Admin.phpnu[type == 'comment' && !$message->admin_id); } public function isMessageForReply($message) { if ($message->type == 'comment') { return false; } else { return!$message->admin_id; } } public function fillUpMessageIdentity($message) { $message->admin_id = $this->getIdentity(); return $message; } public function fillUpTicketIdentity($ticket, $request) { //loginOrEmail was already validated in form //and we must find user with such login or email //in any case $user = $this->getDi()->userTable->findFirstByLogin($request->get('loginOrEmail')); if (!$user) { $user = $this->getDi()->userTable->findFirstByEmail($request->get('loginOrEmail')); } $ticket->user_id = $user->user_id; return $ticket; } public function getTicketStatusAfterReply($message) { if ($message->type == 'comment') { return $message->getTicket()->status; } else { return 'awaiting_user_response'; } } public function onAfterInsertMessage($message, $ticket) { if ($message->type == 'message') { $ticket->updateQuick('has_new', 1); } if ($message->type == 'message' && $this->getDi()->config->get('helpdesk.notify_new_message', 1)) { $user = $this->getUser($message->getTicket()->user_id); if ($user->unsubscribed) return; $et = Am_Mail_Template::load('helpdesk.notify_new_message', $user->lang); if ($et) { $et->setTicket($message->getTicket()); $et->setUser($user); $et->setMessage($message); $et->setUrl($this->getDi()->url('helpdesk/ticket/'.$message->getTicket()->ticket_mask,null,false,true)); $et->send($user); } } } public function onViewTicket($ticket) { //nop } /** * @return Am_Form */ public function createNewTicketForm() { $form = parent::createNewTicketForm(); $element = HTML_QuickForm2_Factory::createElement('text', 'loginOrEmail'); $element->setId('loginOrEmail') ->setLabel(___('Username/Email')) ->addRule('callback', ___('Can not find user with such username or email'), array($this, 'checkUser')); //prepend element to form $formElements = $form->getElements(); $form->insertBefore($element, $formElements[0]); $from = HTML_QuickForm2_Factory::createElement('select', 'from'); $from->setLabel(___('Create ticket as')); $from->loadOptions(array( 'admin' => ___('Admin'), 'user' => ___('Customer') )); $form->insertBefore($from, $element); $form->addScript('script')->setScript(<<getId(); $snippets = ___('Snippets'); $form->addScript('snippets')->setScript(<<
$snippets') jQuery('#snippets-link').bind('click', function(){ var \$this = jQuery(this); var div = jQuery('
'); div.load(amUrl('/helpdesk/admin/p/view/displaysnippets'), {}, function(){ div.dialog({ autoOpen: true, modal : true, title : "", width : 700, position : ['center', 'center'] }); div.find('.grid-wrap').bind('load', function() { jQuery(this).find('a.am-helpdesk-insert-snippet').unbind().click(function(){ var \$target = \$this.closest('div.am-form').find('textarea[name=content]'); \$target.insertAtCaret(jQuery(this).data('snippet-content')) div.dialog('close'); }) }) }) }) CUT ); return $form; } public function addUpload($form) { $t = Am_Html::escape(___('Add Attachments')); $form->addHtml()->setHtml(<<$t CUT ); $form->addUpload('attachments', array('multiple' => 1), array('prefix' => Bootstrap_Helpdesk::ADMIN_ATTACHMENT_UPLOAD_PREFIX, 'secure' => true)) ->setLabel(___('Attachments')); } public function getAdminName($message) { $admin = $this->getAdmin($message->admin_id); return $admin ? $admin->login : ___('Administrator has been removed, id [%d]', $message->admin_id); } public function getTemplatePath() { return 'admin/helpdesk'; } public function getIdentity() { $admin = $this->getDi()->authAdmin->getUser(); return $admin->pk(); } public function canViewTicket($ticket) { return true; } public function canViewMessage($message) { return true; } public function canEditTicket($ticket) { return true; } public function canEditMessage($message) { return ($message->type == 'comment' && (boolean) $message->admin_id) || ($this->getDi()->modules->get('helpdesk')->getConfig('can_edit') && $message->admin_id && $this->getDi()->authAdmin->getUserId() == $message->admin_id && $message->dattm > sqlTime('-5 minute') ); } public function canUseSnippets() { return true; } public function canUseFaq() { return true; } public function canEditOwner($ticket) { return true; } public function canEditWatcher($ticket) { return true; } public function canViewOwner($ticket) { return true; } public function canEditCategory($ticket) { return true; } public function checkUser($loginOrEmail) { $user = $this->getDi()->userTable->findFirstByLogin($loginOrEmail); if (!$user) { $user = $this->getDi()->userTable->findFirstByEmail($loginOrEmail); } return (boolean) $user; } public function createForm() { $form = new Am_Form_Admin(); $form->setAttribute('class', 'am-helpdesk-form'); return $form; } public function ticketUrl($ticket) { return $this->assembleUrl(array( 'ticket' => $ticket->ticket_mask ), 'helpdesk-ticket-admin'); } public function newUrl() { return $this->assembleUrl(array(), 'helpdesk-new-admin'); } protected function getControllerName() { return 'admin'; } }PK\ެLcYcY+helpdesk/library/Am/Helpdesk/Controller.phpnu[hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_ID); } public function init() { $this->strategy = $this->getDi()->helpdeskStrategy; $type = defined('AM_ADMIN') ? 'admin' : 'user'; $this->getView()->headLink()->appendStylesheet($this->getView()->_scriptCss('helpdesk-' . $type . '.css')); $this->getView()->registerHelper(new Am_View_Helper_HelpdeskGetTicketField($this->getDi()->helpdeskTicketTable->customFields()->getAll()), 'helpdeskGetTicketField'); parent::init(); } protected function isGridRequest($gridId) { foreach ($this->getRequest()->getParams() as $key => $val) if (substr($key, 0, strlen($gridId)) == $gridId) return true; return false; } public function newAction() { if (!$this->getModule()->getConfig('live')) return; Zend_Session::writeClose(); set_time_limit(0); while (@ob_end_clean()); $message = $this->getDi()->helpdeskMessageTable->load($this->getDi()->security->reveal($this->getParam('id'))); if (!$this->strategy->canViewMessage($message)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $ticket = $message->getTicket(); if (!$this->strategy->canViewTicket($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } while (!($messages = $this->getDi()->helpdeskMessageTable->selectObjects("SELECT * " . "FROM ?_helpdesk_message WHERE ticket_id=? AND message_id>? ORDER BY message_id DESC", $ticket->pk(), $message->pk() ))) { sleep(2); } $this->strategy->onViewTicket($ticket); $out = ''; $message_id = null; $this->view->strategy = $this->strategy; $this->view->ticket = $ticket; foreach ($messages as $message) { $message_id = $message_id ?: $message->pk(); $this->view->message = $message; $out .= $this->view->render($this->strategy->getTemplatePath() . '/_message.phtml'); } $url = json_encode($this->strategy->newUrl(). '?' . http_build_query(array( 'id' => $this->getDi()->security->obfuscate($message_id)))); $html = json_encode($out); echo <<getDi()->helpdeskMessageTable->load($this->getDi()->security->reveal($this->getParam('message_id'))); if (!$this->strategy->canViewMessage($message)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $upload = $this->getDi()->uploadTable->load($this->getDi()->security->reveal($this->getParam('id'))); if (!in_array($upload->pk(), $message->getAttachments())) { throw new Am_Exception_AccessDenied(___('Access Denied')); } if (!in_array($upload->prefix, array( Bootstrap_Helpdesk::ATTACHMENT_UPLOAD_PREFIX, Bootstrap_Helpdesk::ADMIN_ATTACHMENT_UPLOAD_PREFIX))) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $this->_helper->sendFile($upload->getFullPath(), $upload->mime, array( 'filename' => $upload->getName() )); } public function surrenderAction() { $ticketIdentity = $this->getParam('ticket'); $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); if (!$this->strategy->canEditOwner($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } if ($ticket->owner_id == $this->strategy->getIdentity()) { $ticket->owner_id = null; $ticket->save(); } $this->redirectTicket($ticket); } public function takeAction() { $ticketIdentity = $this->getParam('ticket'); $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); if (!$this->strategy->canEditOwner($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $id = $this->getParam('id'); $id = $id ? $this->getDi()->security->reveal($id) : $this->strategy->getIdentity(); $ticket->owner_id = $id; $ticket->save(); if (($this->strategy->getIdentity() != $id) && $this->getModule()->getConfig('notify_assign')) { $admin = $this->getDi()->adminTable->load($id); $et = Am_Mail_Template::load('helpdesk.notify_assign'); $et->setTicket($ticket); $et->setAdmin($admin); $et->setUrl($this->getDi()->url('helpdesk/admin/ticket/'.$ticket->ticket_mask,null,false,2)); $et->send($admin->email); } $this->redirectTicket($ticket); } public function editcategoryAction() { $ticketIdentity = $this->getParam('ticket'); $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); if (!$this->strategy->canEditCategory($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $ticket->category_id = $this->getDi()->security->reveal($this->getParam('id')); $ticket->save(); $this->redirectTicket($ticket); } public function lockAction() { if (defined('AM_ADMIN') && AM_ADMIN) { $ticketIdentity = $this->getParam('ticket'); /* @var $ticket HelpdeskTicket */ $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); $ticket->lock($this->getDi()->authAdmin->getUser()); } } public function viewAction() { $ticketIdentity = $this->getParam('ticket'); $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); if (!$this->strategy->canViewTicket($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $this->strategy->onViewTicket($ticket); $grid = new Am_Helpdesk_Grid_Admin($this->getRequest(), $this->getView()); $grid->getDataSource()->getDataSourceQuery()->addWhere('m.user_id=?d', $ticket->user_id); $grid->actionsClear(); $grid->removeField('m_login'); $grid->removeField('avatar'); $grid->removeField('gravatar'); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, function(& $ret, $record) use ($ticket) { if ($record->pk() == $ticket->pk()) $ret['class'] = isset($ret['class']) ? $ret['class'] . ' emphase' : 'emphase'; }); if ($this->getDi()->helpdeskTicketTable->countByUserId($ticket->user_id) < 10) { $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, function(&$out, $g){ $out = preg_replace('/.*?/is', '', $out); }); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TITLE, function(&$out, $g){ $out = ''; }); } $grid->isAjax($this->isAjax() && $this->isGridRequest('_admin')); if ($grid->isAjax()) { echo $grid->run(); return; } $category = $ticket->getCategory(); $t = $this->getView(); $t->assign('ticket', $ticket); $t->assign('category', $category); $t->assign('user', $ticket->getUser()); $t->assign('strategy', $this->strategy); $t->assign('historyGrid', $grid->render()); $t->assign('customFields', $this->getDi()->helpdeskTicketTable->customFields()->getAll()); $content = $t->render($this->strategy->getTemplatePath() . '/ticket.phtml'); if ($this->_request->isXmlHttpRequest()) { header('Content-type: text/html; charset=UTF-8'); echo $content; } else { $this->view->assign('content', $content); $this->view->display($this->strategy->getTemplatePath() . '/index.phtml'); } } public function replyAction() { $ticket = $this->getDi()->helpdeskTicketTable->load($this->getParam('ticket')); if (!$this->strategy->canEditTicket($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $message = null; $type = $this->getParam('type', 'message'); if ($message_id = $this->getDi()->security->reveal($this->getParam('message_id'))) { $message = $this->getDi()->helpdeskMessageTable->load($message_id); switch ($type) { case 'message' : if (!$this->strategy->canViewMessage($message)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } break; case 'comment' : if (!$this->strategy->canEditMessage($message)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } break; default : throw new Am_Exception_InputError('Unknown message type : ' . $type); } } /* @var $replyForm Am_Form */ $replyForm = $this->getReplyForm( $this->getParam('ticket'), $message, $type ); if ($this->isPost()) { $replyForm->setDataSources(array($this->getRequest())); $values = $replyForm->getValue(); $message_id = $this->getParam('message_id', null); $message_id = $message_id ? $this->getDi()->security->reveal($message_id) : $message_id; $this->reply($ticket, $message_id, $values); $this->getRequest()->set('ticket', $ticket->ticket_mask); if ($this->_request->isXmlHttpRequest()) { return; } else { return $this->redirectTicket($ticket); } } $content = (string) $replyForm; if ($this->_request->isXmlHttpRequest()) { header('Content-type: text/html; charset=UTF-8'); echo $content; } else { $this->view->assign('content', $content); $this->view->display($this->strategy->getTemplatePath() . '/index.phtml'); } } public function changestatusAction() { $ticketIdentity = $this->getParam('ticket'); $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); if (!$this->strategy->canEditTicket($ticket)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $ticket->status = $this->getParam('status'); $ticket->save(); return $this->redirectTicket($ticket); } public function displaysnippetsAction() { if (!$this->strategy->canUseSnippets()) { throw new Am_Exception_AccessDenied(); } $ticket = $this->getDi()->helpdeskTicketTable->load($this->getParam('ticket'), false); $tpl = null; if ($ticket) { $tpl = new Am_SimpleTemplate; $tpl->assign('user', $ticket->getUser()); } $ds = new Am_Query($this->getDi()->helpdeskSnippetTable); $grid = new Am_Grid_Editable('_snippet', ___('Snippets'), $ds, $this->getRequest(), $this->view, $this->getDi()); $grid->addField('title', ___('Title'))->setRenderFunction( function ($record, $fieldName, $grid) use ($tpl) { $c = $record->content; if ($tpl) { $c = $tpl->render($c); } return sprintf('%s', Am_Html::escape($c), Am_Html::escape($record->title)); }); $grid->setForm(array($this, 'createForm')); $grid->actionGet('insert')->setTarget(null); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID); $grid->isAjax($this->isAjax() && $this->isGridRequest('_snippet')); echo $grid->run(); } public function displayfaqAction() { if (!$this->strategy->canUseFaq()) { throw new Am_Exception_AccessDenied(); } $ds = new Am_Query($this->getDi()->helpdeskFaqTable); $grid = new Am_Grid_ReadOnly('_helpdesk_faq', ___('FAQ'), $ds, $this->getRequest(), $this->view, $this->getDi()); $grid->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderFaqTitle')); $grid->addField('category', ___('Category')); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID); $grid->isAjax($this->isAjax() && $this->isGridRequest('_helpdesk_faq')); echo $grid->run(); } public function displayassignAction() { if (!$this->strategy->canEditOwner(null)) { throw new Am_Exception_AccessDenied(); } $ds = new Am_Query($this->getDi()->adminTable); $grid = new Am_Grid_ReadOnly('_helpdesk_assign', ___('Admins'), $ds, $this->getRequest(), $this->view, $this->getDi()); $grid->addField('login', ___('Name'))->setRenderFunction(array($this, 'renderAssignTitle')); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID); $grid->isAjax($this->isAjax() && $this->isGridRequest('_helpdesk_assign')); echo $grid->run(); } public function displayeditcategoryAction() { if (!$this->strategy->canEditCategory(null)) { throw new Am_Exception_AccessDenied(); } $ds = new Am_Query($this->getDi()->helpdeskCategoryTable); $grid = new Am_Grid_ReadOnly('_helpdesk_category', ___('Categories'), $ds, $this->getRequest(), $this->view, $this->getDi()); $grid->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderEditCategoryTitle')); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_ID); $grid->isAjax($this->isAjax() && $this->isGridRequest('_helpdesk_category')); echo $grid->run(); } public function editwatcherAction() { $ticketIdentity = $this->getParam('ticket'); $ticket = $this->getDi()->helpdeskTicketTable->load($ticketIdentity); if (!$this->strategy->canEditWatcher($ticket)) { throw new Am_Exception_AccessDenied(); } $options = array(); foreach (Am_Di::getInstance()->adminTable->findBy() as $admin) { $options[$admin->pk()] = sprintf('%s (%s %s)', $admin->login, $admin->name_f, $admin->name_l); } $form = new Am_Form_Admin; $form->addMagicSelect('watcher_ids') ->setLabel(___("Watchers\n" . 'notify the following admins ' . 'about new messages in this ticket')) ->loadOptions($options); $form->addHidden('ticket') ->setValue($ticketIdentity); $form->addSaveButton(); if (!$form->isSubmitted()) { $form->setDataSources(array(new HTML_QuickForm2_DataSource_Array(array( 'watcher_ids' => explode(',', $ticket->watcher_ids) )))); } if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); $ticket->watcher_ids = implode(",", $vars['watcher_ids']); $ticket->save(); if (!$this->_request->isXmlHttpRequest()) { return $this->redirectTicket($ticket); } } echo $form; } public function renderFaqTitle($record, $fieldName, $grid) { return sprintf('%s', $this->getDi()->rurl('helpdesk/faq/i/'.urlencode($record->title)), Am_Html::escape($record->title)); } public function renderAssignTitle($record, $fieldName, $grid) { return sprintf('%s', $this->getDi()->app->obfuscate($record->pk()), Am_Html::escape(sprintf('%s (%s %s)', $record->login, $record->name_f, $record->name_l))); } public function renderEditCategoryTitle($record, $fieldName, $grid) { return sprintf('%s', $this->getDi()->app->obfuscate($record->pk()), Am_Html::escape($record->title)); } public function createForm() { $form = new Am_Form_Admin(); $form->addText('title', array('class' => 'el-wide')) ->setLabel(___('Title')) ->addRule('required'); $form->addTextarea('content', array('class' => 'el-wide', 'rows' => 10)) ->setLabel(___('Content')) ->addRule('required'); return $form; } protected function redirectTicket($ticket) { $url = $this->strategy->ticketUrl($ticket); $this->_response->redirectLocation($url); } private function editMessage($message_id, $value) { $message = $this->getDi()->helpdeskMessageTable->load($message_id); if (!$this->strategy->canEditMessage($message)) { throw new Am_Exception_AccessDenied(___('Access Denied')); } $message->content = $value['content']; $message->save(); } private function addMessage($ticket, $value) { $message = $this->getDi()->helpdeskMessageRecord; $message->content = $value['content']; $message->ticket_id = $ticket->ticket_id; $message->type = $value['type']; $message->setAttachments($value['attachments']); $message = $this->strategy->fillUpMessageIdentity($message); $message->save(); $this->strategy->onAfterInsertMessage($message, $ticket); $ticket->status = $this->strategy->getTicketStatusAfterReply($message); $ticket->updated = $this->getDi()->sqlDateTime; $ticket->save(); if (isset($value['_close']) && $value['_close'] && $this->strategy->caneditTicket($ticket)) { $ticket->status = HelpdeskTicket::STATUS_CLOSED; $ticket->save(); } } private function reply($ticket, $message_id, $values) { if ($message_id) { $this->editMessage($message_id, $values); } else { $this->addMessage($ticket, $values); } } private function getReplyForm($ticket, $message = null, $type = 'message') { $content = ''; $form = $this->strategy->createForm(); if (!is_null($message) && $type == 'message') { if (!$this->getModule()->getConfig('does_not_quote_in_reply')) { $content = explode("\n", $message->content); $content = array_map(function($v) { return '>'.$v; }, $content); $content = "\n\n" . implode("\n", $content); } } elseif (!is_null($message) && $type == 'comment') { $content = $message->content; $form->addHidden('message_id') ->setValue($this->getDi()->app->obfuscate($message->message_id)); } if ($type == 'message' && defined('AM_ADMIN') && $this->getModule()->getConfig('add_signature')) { $content = "\n\n" . $this->expandPlaceholders($this->getModule()->getConfig('signature')) . $content; } $form->addHidden('type') ->setValue($type); $row_num = min(15, count(explode("\n", $content))+1); $form->addTextarea('content', array('rows' => $row_num, 'class' => 'no-label el-wide', 'placeholder' => $type == 'comment' ? ___('Write your comment...') : ___('Write your reply...'))) ->setValue($content) ->addRule('required'); $form->setAction($this->strategy->assembleUrl(array( 'page_id' => 'view', 'action' => 'reply', 'ticket' => $ticket, 'type' => $type ), 'inside-pages')); if ($type != 'comment') { $this->strategy->addUpload($form); } if ($this->strategy->canEditTicket($ticket)) { $form->addAdvCheckbox('_close', null, array('content' => ___('Close This Ticket After Response'))); } $btns = $form->addGroup(); $btns->setSeparator(' '); $btns->addSubmit('submit', array('value' => ___('Send Message'))); $btns->addInputButton('discard', array('value' => ___('Discard'))); return $form; } protected function expandPlaceholders($text) { $admin = $this->getDi()->authAdmin->getUser(); return str_replace(array( '%name_f%', '%name_l%' ), array( $admin->name_f, $admin->name_l ), $text); } } class Am_View_Helper_HelpdeskGetTicketField extends Zend_View_Helper_Abstract { protected $customFields = array(); function __construct($customFields) { $this->customFields = $customFields; } public function helpdeskGetTicketField(HelpdeskTicket $ticket, $field_name) { return $this->formatValue($this->getValue($ticket, $field_name), $field_name); } protected function getValue(HelpdeskTicket $ticket, $field_name) { return $this->customFields[$field_name]->sql ? $ticket->{$field_name} : $ticket->data()->get($field_name); } protected function formatValue($val, $field_name) { if (isset($this->customFields[$field_name])) { $field = $this->customFields[$field_name]; switch($field->getType()) { case 'date': $res = amDate($val); break; case 'select': case 'radio': case 'checkbox': case 'multi_select': $val = (array)$val; foreach ($val as $k=>$v) $val[$k] = @$field->options[$v]; $res = implode(", ", $val); break; default: $res = $val; } } else { $res = $val; } return $res; } }PK\{\r1r1%helpdesk/library/Am/Helpdesk/Grid.phpnu[status = HelpdeskTicket::STATUS_CLOSED; $record->save(); } } class Am_Grid_Editable_Helpdesk extends Am_Grid_Editable { protected $foundRowsBeforeFilter = 0; protected $eventId = 'gridHelpdesk'; function init() { $this->foundRowsBeforeFilter = $this->dataSource->getFoundRows(); $this->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, array($this, 'skipTable')); } function renderFilter() { if ($this->foundRowsBeforeFilter) { return parent::renderFilter(); } } function skipTable(& $out) { if (!$this->foundRowsBeforeFilter) { $out = ''; } } public function getPermissionId() { return Bootstrap_Helpdesk::ADMIN_PERM_ID; } } class Am_Grid_Filter_Helpdesk extends Am_Grid_Filter_Abstract { protected $language = null; protected $varList = array('filter_q', 'has_new'); protected function applyFilter() { $query = $this->grid->getDataSource()->getDataSourceQuery(); if ($filter = $this->getParam('filter_q')) { $condition = new Am_Query_Condition_Field('subject', 'LIKE', '%' . $filter . '%'); $condition->_or(new Am_Query_Condition_Field('ticket_mask', 'LIKE', '%' . $filter . '%')); $query->add($condition); } if ($this->getParam('has_new')) { $query->addWhere('t.has_new=?', 1); } } function renderInputs() { $filter = $this->renderInputText(array( 'placeholder' => ___('Subject or Ticket#'), 'name' => 'filter_q')); return $filter; } function getTitle() { return ''; } } class Am_Grid_Filter_Helpdesk_Adv extends Am_Grid_Filter_Helpdesk { protected $language = null; protected $varList = array('filter_q', 'filter_c', 'has_new'); protected function applyFilter() { parent::applyFilter(); $query = $this->grid->getDataSource()->getDataSourceQuery(); if ($filter = $this->getParam('filter_c')) { $query->addWhere('t.category_id=?', $filter); } } function renderInputs() { $filter = parent::renderInputs(); $categoryOptions = Am_Di::getInstance()->helpdeskCategoryTable->getOptions(); if ($categoryOptions) { $categoryOptions = array('' => ___('All Categories')) + $categoryOptions; $filter .= ' '; $filter .= $this->renderInputSelect('filter_c', $categoryOptions); } return $filter; } function getTitle() { return ''; } } class Am_Grid_Filter_Helpdesk_Adv_WithStatus extends Am_Grid_Filter_Helpdesk_Adv { protected $varList = array('filter_q', 'filter_s', 'filter_c', 'has_new'); protected function applyFilter() { parent::applyFilter(); $query = $this->grid->getDataSource()->getDataSourceQuery(); if ($filter = $this->getParam('filter_s')) { $query->addWhere('t.status IN (?a)', $filter); } } function renderInputs() { $categoryOptions = Am_Di::getInstance()->helpdeskCategoryTable->getOptions(); $width = $categoryOptions ? '45' : '90'; $filter = $this->renderInputText(array( 'placeholder' => ___('Subject or Ticket#'), 'name' => 'filter_q', 'style' => "width:$width%")); if ($categoryOptions) { $categoryOptions = array('' => ___('All Categories')) + $categoryOptions; $filter .= ' '; $filter .= $this->renderInputSelect('filter_c', $categoryOptions, array( 'style' => "width:$width%" )); } $statusOptions = HelpdeskTicket::getStatusOptions(); unset($statusOptions[HelpdeskTicket::STATUS_CLOSED]); $filter .= '
'; $filter .= $this->renderInputCheckboxes('filter_s', $statusOptions); return $filter; } } class Am_Grid_Action_Ticket extends Am_Grid_Action_Abstract { protected $type = self::NORECORD; // this action does not operate on existing records protected $strategy = null; public function __construct($id = null, $title = null) { $this->title = ___('Submit New Ticket'); parent::__construct($id, $title); } public function run() { $form = $this->grid->getForm(); if ($form->isSubmitted() && $form->validate()) { $values = $form->getValue(); if (defined('AM_ADMIN') && AM_ADMIN && isset($values['from']) && $values['from'] == 'user') { $user = Am_Di::getInstance()->userTable->findFirstByLogin($values['loginOrEmail']); if (!$user) $user = Am_Di::getInstance()->userTable->findFirstByEmail($values['loginOrEmail']); if (!$user) throw new Am_Exception_InputError("User not found with username or email equal to {$values['loginOrEmail']}"); $this->switchStrategy(new Am_Helpdesk_Strategy_User(Am_Di::getInstance(), $user->pk())); } $ticket = Am_Di::getInstance()->helpdeskTicketRecord; if (isset($values['category_id']) && isset($values['category'][$values['category_id']])) { $ticket->setForInsert($values['category'][$values['category_id']]); } elseif (isset($values['additional'])) { $ticket->setForInsert($values['additional']); } $ticket->subject = $values['subject']; $ticket->created = Am_Di::getInstance()->sqlDateTime; $ticket->updated = Am_Di::getInstance()->sqlDateTime; $ticket->category_id = isset($values['category_id']) ? $values['category_id'] : null; if (($category = $ticket->getCategory()) && ($category->owner_id || $category->watcher_ids)) { $ticket->owner_id = $category->owner_id; $ticket->watcher_ids = $category->watcher_ids; } $ticket = $this->getStrategy()->fillUpTicketIdentity($ticket, $this->grid->getCompleteRequest()); // mask will be generated on insertion $ticket->insert(); $this->getStrategy()->onAfterInsertTicket($ticket); $content = $values['content']; if (defined('AM_ADMIN') && AM_ADMIN) { $user = $ticket->getUser(); $tpl = new Am_SimpleTemplate; $tpl->assign('user', $user); $content = $tpl->render($content); } $message = Am_Di::getInstance()->helpdeskMessageRecord; $message->content = $content; $message->ticket_id = $ticket->pk(); $message->dattm = Am_Di::getInstance()->sqlDateTime; $message = $this->getStrategy()->fillUpMessageIdentity($message); $message->setAttachments(@$values['attachments']); $message->insert(); $this->getStrategy()->onAfterInsertMessage($message, $ticket); $this->restoreStrategy(); echo $this->renderTicketSubmited($ticket); } else { echo $this->renderTitle(); echo $form; } } /** @return Am_Helpdesk_Strategy_Abstract */ protected function getStrategy() { return is_null($this->strategy) ? Am_Di::getInstance()->helpdeskStrategy : $this->strategy; } public function switchStrategy(Am_Helpdesk_Strategy_Abstract $strategy) { $this->strategy = $strategy; } public function restoreStrategy() { if (!is_null($this->strategy)) { $this->strategy = null; } } protected function renderTicketSubmited($ticket) { $out = sprintf('

%s

', ___('Ticket has been submited')); $out .= sprintf('

%s #%s

', ___('Reference number is:'), $this->getStrategy()->ticketUrl($ticket), $ticket->ticket_mask ); return $out; } } abstract class Am_Helpdesk_Grid extends Am_Grid_Editable_Helpdesk { public function __construct(Am_Mvc_Request $request, Am_View $view) { $id = explode('_', get_class($this)); $id = strtolower(array_pop($id)); parent::__construct('_' . $id, $this->getGridTitle(), $this->createDs(), $request, $view); if ($f = $this->createFilter()) { $this->setFilter($f); } $this->setRecordTitle(array($this, 'getTicketRecordTitle')); } protected function createFilter() { return new Am_Grid_Filter_Helpdesk_Adv_WithStatus; } abstract function getStatusIconId($id, $record); public function getTicketRecordTitle(HelpdeskTicket $ticket = null) { return $ticket ? sprintf('%s (#%s: %s)', ___('Ticket'), $ticket->ticket_mask, $ticket->subject) : ___('Ticket'); } public function cbGetTrAttribs(& $ret, $record) { if ($this->isNotImportant($record)) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } protected function isNotImportant($record) { return false; } public function initActions() { //nop } public function createForm() { return $this->getDi()->helpdeskStrategy->createNewTicketForm(); } public function renderSubject($r) { $url = $this->getDi()->helpdeskStrategy->ticketUrl($r); $category = $r->category_id && $r->c_title ? sprintf('
%s', Am_Html::escape($r->c_title)) : ''; return sprintf('%s %d %s%s', $url, Am_Html::escape($r->subject), $r->msg_cnt, Am_Html::escape(mb_substr(preg_replace('/(\s{2,})/m', ' ', strip_tags(trim($r->msg_last))), 0, 70)) . '…', $category ); } public function renderStatus($record) { $statusOptions = HelpdeskTicket::getStatusOptions(); list($status) = explode('_', $record->status); $status = $this->getStatusIconId($status, $record); return sprintf('%s', $this->getDi()->view->icon($status, $statusOptions[$record->status]) ); } public function renderTime($record, $fieldName) { return sprintf('', amDatetime($record->$fieldName), date('c', amstrtotime($record->$fieldName)), $this->getView()->getElapsedTime($record->$fieldName)); } public function renderUser($record, $fieldName) { $name = trim("{$record->m_name_f} {$record->m_name_l}"); return sprintf('%s%s', $this->getView()->userUrl($record->user_id), $record->m_login, $name ? sprintf(' (%s)', Am_Html::escape($name)) : '' ); } protected function createDS() { $query = new Am_Query(Am_Di::getInstance()->helpdeskTicketTable); $query->addField('COUNT(msg.message_id)', 'msg_cnt') ->addField('(SELECT content FROM ?_helpdesk_message ' . 'WHERE ticket_id = t.ticket_id ' . 'ORDER BY dattm DESC LIMIT 1)', 'msg_last') ->addField('m.login AS m_login') ->addField('m.name_f AS m_name_f') ->addField('m.name_l AS m_name_l') ->addField('m.email AS m_email') ->leftJoin('?_helpdesk_message', 'msg', 'msg.ticket_id=t.ticket_id') ->addWhere('msg.type=?', 'message') ->leftJoin('?_user', 'm', 't.user_id=m.user_id') ->leftJoin('?_helpdesk_category', 'c', 't.category_id=c.category_id') ->addField('c.title', 'c_title') ->addOrder('updated', true); if (Am_Di::getInstance()->plugins_misc->isEnabled('avatar')) { $query->addField('m.avatar', 'm_avatar'); } return $query; } public function getGridTitle() { return ___('Tickets'); } }PK\]NN5helpdesk/library/Am/Helpdesk/Grid/Admin/Dashboard.phpnu[addWhere('t.status<>?', HelpdeskTicket::STATUS_CLOSED); return $q; } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Ticket()); $this->actionAdd(new Am_Grid_Action_Delete()); if ($cnt = $this->getDi()->helpdeskTicketTable->countByStatus(HelpdeskTicket::STATUS_CLOSED)) { $this->actionAdd(new Am_Grid_Action_Url('archive', ___('Closed Tickets') . " ($cnt)", $this->getDi()->url('helpdesk/admin/archive'))) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setTarget('_top') ->setCssClass('link'); } } }PK\I;$  3helpdesk/library/Am/Helpdesk/Grid/Admin/Archive.phpnu[addWhere('t.status=?', HelpdeskTicket::STATUS_CLOSED); return $q; } public function getGridTitle() { return ___('Archive'); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Delete()); $this->actionDelete('ticket'); if ($cnt = $this->getDi()->helpdeskTicketTable->countBy(array( 'status' => '<>' . HelpdeskTicket::STATUS_CLOSED))) { $this->actionAdd(new Am_Grid_Action_Url('dashboard', ___('Dashboard') . " ($cnt)", $this->getDi()->url('helpdesk/admin'))) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setTarget('_top') ->setCssClass('link'); } } } PK\VIMj j +helpdesk/library/Am/Helpdesk/Grid/Admin.phpnu[getDataSource(); $ds->leftJoin('?_admin', 'a', 't.owner_id=a.admin_id') ->addField("CONCAT(a.login, ' (',a.name_f, ' ', a.name_l, ')')", 'owner'); if ($this->getDi()->plugins_misc->isEnabled('avatar') && $this->getDi()->modules->get('helpdesk')->getConfig('show_avatar')) { $this->addField(new Am_Grid_Field('avatar', '', false, '', array($this, 'renderAvatar'), '1%')); } elseif ($this->getDi()->modules->get('helpdesk')->getConfig('show_gravatar')) { $this->addField(new Am_Grid_Field('gravatar', '', false, '', array($this, 'renderGravatar'), '1%')); } $this->addField(new Am_Grid_Field('m_login', ___('User'), true, '', array($this, 'renderUser'))); $this->addField(new Am_Grid_Field('subject', ___('Subject'), true, '', array($this, 'renderSubject'))); $this->addField(new Am_Grid_Field_Date('created', ___('Created')))->setFormatDate(); $this->addField(new Am_Grid_Field('updated', ___('Updated'), true, '', array($this, 'renderTime'))); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_helpdesk_ticket WHERE owner_id IS NOT NULL")) { $this->addField(new Am_Grid_Field('owner_id', ___('Owner'), true, '', array($this, 'renderOwner'))); } $this->addField(new Am_Grid_Field('ticket_mask', ___('Ticket#'), true)); $this->addField(new Am_Grid_Field('status', ___('Status'), true, '', array($this, 'renderStatus'), '1%')); $this->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'cbGetTrAttribs')); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Delete); $this->actionAdd(new Am_Grid_Action_Group_CloseTicket); $this->actionAdd(new Am_Grid_Action_Group_Delete); } public function getStatusIconId($id, $record) { return ($id == 'awaiting' && $record->status == HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE ? $id . '-me' : $id); } public function renderOwner($record) { return $record->owner_id ? sprintf('%s', Am_Html::escape(str_replace(' ( )', '', $record->owner))) : ''; } public function renderGravatar($record) { return sprintf('
', '//www.gravatar.com/avatar/' . md5(strtolower(trim($record->m_email))) . '?s=40&d=mm'); } public function renderAvatar($record) { return sprintf('
', $this->getDi()->url('misc/avatar/' . $record->m_avatar)); } protected function isNotImportant($record) { return $record->status == HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE; } }PK\">~(helpdesk/library/Am/View/Helper/Skip.phpnu[ $v) { if (preg_match('/^\s*>\s*>/', trim($v))) { $s_arr[$k] = 1; } else { $s_arr[$k] = 0; } } //add one none skiped line at the end //in order to resolve problem if last line should be skiped too $arr[] = ''; $arr = array_map(array('Am_Html', 'escape'), $arr); $s_arr[] = 0; //remove empty lines beetween skiped lines $prev = 0; $empty_lines = array(); foreach ($s_arr as $k => $v) { if (trim($arr[$k]) == '') { $empty_lines[] = $k; } elseif ($v && $prev) { foreach ($empty_lines as $key) { $s_arr[$key] = 1; } $empty_lines = array(); $prev = 1; } elseif ($v) { $empty_lines = array(); $prev = 1; } else { $prev = 0; } } //skip $skiped = 0; $skiped_lines = array(); $label_lines_skipped = ___('lines skipped'); foreach ($s_arr as $k => $v) { if ($v) { $skiped_lines[] = $arr[$k]; if (!$skiped) { $first_skiped_line = $k; } else { unset($arr[$k]); } $skiped++; } elseif ($skiped) { $arr[$first_skiped_line] = '
...' . $skiped . ' ' . $label_lines_skipped . '...
' . implode("\n", $skiped_lines) . '
'; $skiped = 0; $skiped_lines = array(); } } $string = implode("\n", $arr); return $string; } }PK\گu;;.helpdesk/library/Am/View/Helper/Hyperlinks.phpnu[".?,)]{0,1}(\s|$))|(&(quot|gt);))#i'; return preg_replace($pattern, '$1$3', $string); } }PK\mhelpdesk/library/SetupForms.phpnu[setTitle(___('Helpdesk')); $this->data['help-id'] = 'Setup/Helpdesk'; } function initElements() { $fieldSetNotifications = $this->addFieldset() ->setLabel(___('Notifications')); $fieldSetNotifications->addElement('email_checkbox', 'helpdesk.notify_new_message', null, array('help-id' => '#Enabling.2FDisabling_Customer_Notifications')) ->setLabel(___("Send Notification about New Messages to Customer\n" . "aMember will email a notification to user " . "each time admin responds to a user ticket")); $this->setDefault('helpdesk.notify_new_message', 1); $fieldSetNotifications->addElement('email_checkbox', 'helpdesk.notify_new_message_admin') ->setLabel(___("Send Notification about New Messages to Admin\n" . "aMember will email a notification to admin " . "each time user responds to a ticket")); $this->setDefault('helpdesk.notify_new_message_admin', 1); $fieldSetNotifications->addElement('email_checkbox', 'helpdesk.new_ticket') ->setLabel(___("New Ticket Autoresponder to Customer\n" . "aMember will email an autoresponder to user " . "each time user create new ticket")); $fieldSetNotifications->addElement('email_checkbox', 'helpdesk.notify_assign') ->setLabel(___("Send Notification When Ticket is Assigned to Admin\n" . "aMember will email a notification to admin " . "each time ticket is assigned to him")); $fieldSetConversation = $this->addFieldset() ->setLabel(___('Conversation')); $fieldSetConversation->addAdvCheckbox('helpdesk.can_edit') ->setLabel(___("Admin Can Edit His Messages\n" . "within 5 minutes after post")); $fieldSetConversation->addAdvCheckbox('helpdesk.add_signature') ->setLabel(___('Add Signature to Response')); $fieldSetConversation->addTextarea('helpdesk.signature', array('rows'=>3, 'class'=>'el-wide')) ->setLabel(___("Signature Text\n" . "You can use the following placeholders %name_f%, %name_l% " . "it will be expanded to first and last name of admin in operation")); $this->addScript('script') ->setScript(<<addAdvCheckbox('helpdesk.disclosure_admin') ->setLabel(___("Disclosure Admin real name in user interface\n" . "otherwise only word Administrator is shown")); $fieldSetConversation->addAdvCheckbox('helpdesk.does_not_quote_in_reply') ->setLabel(___('Does Not Quote Message in Reply')); $fieldSetConversation->addAdvCheckbox('helpdesk.does_not_allow_attachments') ->setLabel(___('Does Not Allow to Upload Attachments for Users')); $gr = $fieldSetConversation->addGroup() ->setLabel(___("Autoclose Tickets Due to Inactivity")); $gr->addAdvCheckbox('helpdesk.autoclose') ->setId('helpdesk_autoclose'); $gr->addStatic()->setContent(sprintf(' %s ', ___("after"))); $gr->addText('helpdesk.autoclose_period', array('class'=>'helpdesk_autoclose_hours', 'size' => 3, 'placeholder'=>70)); $gr->addStatic()->setContent(sprintf(' %s ', ___("hours"))); $fieldSetConversation->addElement('email_checkbox', 'helpdesk.notify_autoclose') ->setLabel(___("Send Autoclose Notification to User\n" . "aMember will email an autoresponder to user " . "when ticket is closed due to inactivity")); $this->addScript()->setScript(<<addFieldset() ->setLabel(___('Features')); $fieldSetFeatures->addAdvCheckbox('helpdesk.live') ->setLabel(___("Enable Live Conversation (experimental)\n" . "update conversation instantly without page reload (can consume more server resources)")); $fieldSetFeatures->addAdvCheckbox('helpdesk.show_gravatar') ->setId('gravatar') ->setLabel(___("Show Gravatars in Ticket Conversation\n" . 'more details about gravatar can be found %shere%s', '', '')); if (Am_Di::getInstance()->plugins_misc->isEnabled('avatar')) { $fieldSetFeatures->addAdvCheckbox('helpdesk.show_avatar') ->setId('avatar') ->setLabel(___("Show Avatars in Ticket Conversation\n" . 'this option has priority over gravatar if enabled')); $this->addScript()->setScript(<<addAdvCheckbox('helpdesk.does_not_require_login') ->setLabel(___("Does Not Require Login to Access FAQ Section\n" . 'make it public')); $fieldSetFeatures->addAdvCheckbox('helpdesk.does_not_show_faq_tab') ->setLabel(___('Does Not Show FAQ Tab in Member Area')); $fieldSetFeatures->addAdvCheckbox('helpdesk.show_faq_search') ->setLabel(___('Show Search Function in FAQ')); $this->addHtmlEditor('helpdesk.intro', null, array('showInPopup' => true)) ->setLabel(___("Intro Text on Helpdesk Page")); $this->setDefault('helpdesk.intro', 'We answer customer tickets Mon-Fri, 10am - 5pm EST. You can also call us by phone if you have an urgent question.'); } } PK\[JFF#helpdesk/library/HelpdeskTicket.phpnu[ ___('New'), 'awaiting_admin_response' => ___('Awaiting Admin Response'), 'awaiting_user_response' => ___('Awaiting User Response'), 'closed' => ___('Closed') ); } public function getMessages() { return $this->getDi()->helpdeskMessageTable->findBy( array('ticket_id' => $this->pk()), null, null, "dattm DESC"); } /** * @return User */ public function getUser() { return $this->getDi()->userTable->load($this->user_id); } /** * @return Admin */ public function getOwner() { return $this->owner_id ? $this->getDi()->adminTable->load($this->owner_id, false) : null; } public function getWatchers() { $res = array(); foreach (explode(',', $this->watcher_ids) as $id) { if ($id && $admin = $this->getDi()->adminTable->load($id, false)) { $res[] = $admin; } } return $res; } /** * @return HelpdeskCategory */ public function getCategory() { return $this->category_id ? $this->getDi()->helpdeskCategoryTable->load($this->category_id, false) : null; } public function isLocked(Admin $admin) { return $this->lock_until && ($this->lock_until > sqlTime('now')) && ($this->lock_admin_id != $admin->pk()); } public function lock(Admin $admin) { $this->updateQuick(array( 'lock_until' => sqlTime('+2 minutes'), 'lock_admin_id' => $admin->pk(), 'lock_admin' => sprintf('%s (%s %s)', $admin->login, $admin->name_f, $admin->name_l) )); } protected function _generateMask() { if (!empty($this->ticket_mask)) return; $this->ticket_mask = $this->getDi()->security->randomString(3, 'ABCDEFGJIKLMNOPQRSTUVWXYZ') . '-' . rand(100000, 999999); } /** * before record insertion generate new ticket mask. if the generated mask is not unique, * try 20 times to generate new mask, then throw exception * @return type */ public function insert($reload = true) { $event = new Am_Event(Bootstrap_Helpdesk::EVENT_TICKET_BEFORE_INSERT, array( 'ticket' => $this )); $this->getDi()->hook->call($event); $maxAttempts = 20; for ($i = 0; $i <= $maxAttempts; $i++) { try { $this->_generateMask(); parent::insert($reload); $event = new Am_Event(Bootstrap_Helpdesk::EVENT_TICKET_AFTER_INSERT, array( 'ticket' => $this )); $this->getDi()->hook->call($event); return $this; } catch (Am_Exception_Db_NotUnique $e) { if ($i >= $maxAttempts) throw new Am_Exception_InternalError("Could not generate new ticket mask after [$i] attempts"); $this->ticket_mask = null; } } } public function delete() { foreach ($this->getMessages() as $msg) { $msg->delete(); } parent::delete(); } } class HelpdeskTicketTable extends Am_Table_WithData { protected $_key = 'ticket_id'; protected $_table = '?_helpdesk_ticket'; protected $_recordClass = 'HelpdeskTicket'; public function insert(array $values, $returnInserted = false) { if (empty($values['created'])) $values['created'] = $this->getDi()->sqlDateTime; return parent::insert($values, $returnInserted); } public function load($keyOrTicketId, $throwExceptions = true) { if (preg_match('/^\d+$/', trim($keyOrTicketId), $matches)) return parent::load($matches[0], $throwExceptions); else { $keyOrTicketId = filterId($keyOrTicketId); $found = $this->findFirstByTicketMask($keyOrTicketId); if (!$found && $throwExceptions) throw new Am_Exception_InternalError("Ticket with mask [$keyOrTicketId] not found"); return $found; } } public function clearOld($date) { foreach ($this->findByUpdated('<' . $date) AS $ticket) { $ticket->delete(); } } }PK\r$helpdesk/library/HelpdeskSnippet.phpnu[ helpdesk.notify_new_message 1 en text %site_title%: New Message for Your Ticket [#%ticket.ticket_mask%] You have received a new message in helpdesk for your ticket [%ticket.subject%] Follow a link below to view this message: %url% helpdesk.notify_new_message_admin 2 en text %site_title%: New Message for Ticket [#%ticket.ticket_mask%] You have received a new message in helpdesk for ticket [%ticket.subject%] Follow a link below to view this message: %url% helpdesk.new_ticket 1 en text %site_title%: New Ticket [#%ticket.ticket_mask%] You created ticket [%ticket.subject%] in our helpdesk system. Thank you for your enquiry. We will respond within 24 hours. Follow a link below to view your ticket: %url% helpdesk.notify_assign 2 en text %site_title%: Ticket [#%ticket.ticket_mask%] is assigned to you Ticket [%ticket.subject%] is assigned to you. Follow a link below to view this ticket: %url% helpdesk.notify_autoclose 1 en text %site_title%: Ticket [#%ticket.ticket_mask%] has been closed automatically Your ticket [%ticket.subject%] has been closed automatically due to inactivity. If the issue hasn't been resolved to your satisfaction yet please let us know. Follow a link below to view this ticket: %url% PK\"/k^L^Lhelpdesk/Bootstrap.phpnu[getDi()->uploadTable->defineUsage(self::ATTACHMENT_UPLOAD_PREFIX, 'helpdesk_message', 'attachments', UploadTable::STORE_IMPLODE, "Ticket [%ticket_id%]", '/helpdesk/admin/p/index/index'); $this->getDi()->uploadTable->defineUsage(self::ADMIN_ATTACHMENT_UPLOAD_PREFIX, 'helpdesk_message', 'attachments', UploadTable::STORE_IMPLODE, "Ticket [%ticket_id%]", '/helpdesk/admin/p/index/index'); } function renderNotification() { if ($user_id = $this->getDi()->auth->getUserId()) { $cnt = $this->getDi()->db->selectCell("SELECT COUNT(ticket_id) FROM ?_helpdesk_ticket WHERE has_new=? AND user_id=?", 1, $user_id); if ($cnt) { return '
' . ___('You have %s%d ticket(s)%s that require your attention', sprintf('', $this->getDi()->url('helpdesk',array('_user_has_new'=>1))), $cnt, '') . '
'; } } } function onSetupEmailTemplateTypes(Am_Event $event) { $ticket = array( 'ticket.ticket_mask' => 'Ticket Mask', 'ticket.subject' => 'Ticket Subject', ); $event->addReturn(array( 'id' => 'helpdesk.notify_new_message', 'title' => 'Notify New Message', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'vars' => $ticket + array('url' => 'Url of Page with Message', 'user'), ), 'helpdesk.notify_new_message'); $event->addReturn(array( 'id' => 'helpdesk.notify_new_message', 'title' => 'Notify New Message', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'isAdmin' => true, 'vars' => $ticket + array('url' => 'Url of Page with Message', 'user'), ), 'helpdesk.notify_new_message_admin'); $event->addReturn(array( 'id' => 'helpdesk.new_ticket', 'title' => 'Autoresponder New Ticket', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'vars' => $ticket + array('url' => 'Url of Page with Ticket', 'user'), ), 'helpdesk.new_ticket'); $event->addReturn(array( 'id' => 'helpdesk.notify_assign', 'title' => 'Notify Ticket is Assigned to Admin', 'mailPeriodic' => Am_Mail::ADMIN_REQUESTED, 'vars' => $ticket + array('url' => 'Url of Page with Ticket', 'admin'), 'isAdmin' => true, ), 'helpdesk.notify_assign'); $event->addReturn(array( 'id' => 'helpdesk.notify_autoclose', 'title' => 'Notify User about Ticket Autoclose', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'vars' => array('user') + $ticket + array('url' => 'Url of Page with Ticket'), ), 'helpdesk.notify_autoclose'); } function onGetUploadPrefixList(Am_Event $event) { $event->addReturn(array( Am_Upload_Acl::IDENTITY_TYPE_ADMIN => array( self::ADMIN_PERM_ID => Am_Upload_Acl::ACCESS_ALL ) ), self::ADMIN_ATTACHMENT_UPLOAD_PREFIX); if (!$this->getConfig('does_not_allow_attachments')) { $event->addReturn(array( Am_Upload_Acl::IDENTITY_TYPE_ADMIN => array( self::ADMIN_PERM_ID => Am_Upload_Acl::ACCESS_ALL ), Am_Upload_Acl::IDENTITY_TYPE_USER => Am_Upload_Acl::ACCESS_WRITE | Am_Upload_Acl::ACCESS_READ_OWN ), self::ATTACHMENT_UPLOAD_PREFIX); } } function onLoadAdminDashboardWidgets(Am_Event $event) { $event->addReturn(new Am_Widget('helpdesk-messages', ___('Last Messages in Helpdesk'), array($this, 'renderWidget'), Am_Widget::TARGET_ANY, array($this, 'createWidgetConfigForm'), self::ADMIN_PERM_ID)); } function onAdminAfterDelete(Am_Event $e) { $this->getDi()->db->query("UPDATE ?_helpdesk_ticket SET owner_id = NULL WHERE owner_id=?", $e->getAdmin()->pk()); $this->getDi()->db->query("UPDATE ?_helpdesk_ticket SET lock_admin_id = NULL, lock_admin = NULL, lock_until = NULL WHERE lock_admin_id=?", $e->getAdmin()->pk()); } function createWidgetConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Messages to display')) ->setValue(5); return $form; } function renderWidget(Am_View $view, $config = null) { $view->num = is_null($config) ? 5 : $config['num']; return $view->render('admin/helpdesk/widget/messages.phtml'); } function onClearItems(Am_Event $event) { $event->addReturn(array( 'method' => array($this->getDi()->helpdeskTicketTable, 'clearOld'), 'title' => 'Helpdesk Tickets', 'desc' => 'records with last update date early than Date to Purge' ), 'helpdesk_tickets'); } function onAdminNotice(Am_Event $e) { /* @var $admin Admin */ $admin = $this->getDi()->authAdmin->getUser(); if (!$admin->hasPermission(self::ADMIN_PERM_ID)) return; $cnt = $this->getDi()->helpdeskTicketTable ->countByStatus(array( HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE, HelpdeskTicket::STATUS_NEW)); if ($cnt) { $e->addReturn(___('You have %s%d ticket(s)%s that require your attention', sprintf('', $this->getDi()->url('helpdesk/admin?_dashboard_filter_s[]=new&_dashboard_filter_s[]=awaiting_admin_response')), $cnt, '')); } } function onUserMerge(Am_Event $event) { $target = $event->getTarget(); $source = $event->getSource(); $this->getDi()->db->query('UPDATE ?_helpdesk_ticket SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); } function onAdminMenu(Am_Event $event) { $cntMy = $this->getDi()->helpdeskTicketTable->countBy(array( 'owner_id' => $this->getDi()->authAdmin->getUserId(), 'status' => array( HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE, HelpdeskTicket::STATUS_NEW))); $cntDashboard = $this->getDi()->helpdeskTicketTable ->countByStatus(array( HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE, HelpdeskTicket::STATUS_NEW)); $event->getMenu()->addPage(array( 'label' => ___('Helpdesk'), 'uri' => '#', 'id' => 'helpdesk', 'resource' => self::ADMIN_PERM_ID, 'pages' => array( array( 'label' => ___('Dashboard') . ($cntDashboard ? " (($cntDashboard))" : ''), 'controller' => 'admin', 'action' => 'index', 'module' => 'helpdesk', 'id' => 'helpdesk-ticket', 'resource' => self::ADMIN_PERM_ID ), array( 'label' => ___('My Tickets') . ($cntMy ? " (($cntMy))" : ''), 'controller' => 'admin-my', 'action' => 'index', 'module' => 'helpdesk', 'id' => 'helpdesk-ticket-my', 'resource' => self::ADMIN_PERM_ID ), array( 'label' => ___('Categories'), 'controller' => 'admin-category', 'action' => 'index', 'module' => 'helpdesk', 'id' => 'helpdesk-category', 'resource' => self::ADMIN_PERM_CATEGORY ), array( 'label' => ___('Fields'), 'controller' => 'admin-fields', 'action' => 'index', 'module' => 'helpdesk', 'id' => 'helpdesk-fields', 'resource' => self::ADMIN_PERM_CATEGORY ), array( 'label' => ___('FAQ'), 'controller' => 'admin-faq', 'action' => 'index', 'module' => 'helpdesk', 'id' => 'helpdesk-faq', 'resource' => self::ADMIN_PERM_FAQ )) )); } function onUserMenu(Am_Event $event) { $page = $helpdeskPage = array( 'id' => 'helpdesk', 'label' => ___('Helpdesk'), 'controller' => 'index', 'action' => 'index', 'module' => 'helpdesk', 'order' => 600, ); if (!$this->getConfig('does_not_show_faq_tab') && $this->getDi()->helpdeskFaqTable->countBy()) { $page = array( 'id' => 'helpdesk-root', 'label' => ___('Support'), 'uri' => 'javascript:;', 'order' => 600, 'pages' => array( $helpdeskPage, array( 'id' => 'helpdesk-faq', 'label' => ___('FAQ'), 'controller' => 'faq', 'action' => 'index', 'module' => 'helpdesk', 'order' => 601, ) ) ); } $event->getMenu()->addPage($page); } function onUserTabs(Am_Event_UserTabs $event) { extract($this->getDi()->db->selectRow("SELECT COUNT(*) AS cnt_all, COUNT(IF(status IN ('new', 'awaiting_admin_response'), ticket_id, NULL)) AS cnt_open FROM ?_helpdesk_ticket WHERE user_id=?", $event->getUserId())); $event->getTabs()->addPage(array( 'id' => 'helpdesk', 'module' => 'helpdesk', 'controller' => 'admin-user', 'action' => 'index', 'params' => array( 'user_id' => $event->getUserId() ), 'label' => ___('Tickets') . sprintf(' (%s)', $cnt_all ? $cnt_open . '/' . $cnt_all: 0), 'order' => 1000, 'resource' => self::ADMIN_PERM_ID, )); } function onGetPermissionsList(Am_Event $event) { $event->addReturn(___('Helpdesk: Can operate with helpdesk tickets'), self::ADMIN_PERM_ID); $event->addReturn(___('Helpdesk: FAQ'), self::ADMIN_PERM_FAQ); $event->addReturn(___('Helpdesk: Categories'), self::ADMIN_PERM_CATEGORY); } function onUserAfterDelete(Am_Event_UserAfterDelete $event) { $this->getDi()->db->query("DELETE FROM ?_helpdesk_message WHERE ticket_id IN (SELECT ticket_id FROM ?_helpdesk_ticket WHERE user_id=?)", $event->getUser()->user_id); $this->getDi()->db->query("DELETE FROM ?_helpdesk_ticket WHERE user_id=?", $event->getUser()->user_id); } function onHourly() { if ($this->getConfig('autoclose')) { $period = $this->getConfig('autoclose_period', 72); $thresholdDate = sqlTime("-$period hours"); foreach($this->getDi()->db->selectPage($total, " SELECT * FROM ?_helpdesk_ticket WHERE status=? AND updated < ? ", HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE, $thresholdDate) as $row) { $ticket = $this->getDi()->helpdeskTicketRecord->fromRow($row); $ticket->status = HelpdeskTicket::STATUS_CLOSED; $ticket->updated = $this->getDi()->sqlDateTime; $ticket->save(); $user = $ticket->getUser(); if ($this->getConfig('notify_autoclose')) { $et = Am_Mail_Template::load('helpdesk.notify_autoclose', $user->lang); $et->setUser($user); $et->setTicket($ticket); $et->setUrl($this->getDi()->url('helpdesk/ticket/'.$ticket->ticket_mask,null,false,true)); $et->send($user); } } } } function onInitFinished() { $this->getDi()->blocks->add(new Am_Block('member/main/top', null, 'helpdesk-notification', null, array($this, 'renderNotification'))); $this->getDi()->register('helpdeskStrategy', 'Am_Helpdesk_Strategy_Abstract') ->setConstructor('create') ->setArguments(array($this->getDi())); $router = $this->getDi()->router;; $router->addRoute('helpdesk-item', new Am_Mvc_Router_Route( 'helpdesk/faq/i/:title', array( 'module' => 'helpdesk', 'controller' => 'faq', 'action' => 'item' ) )); $router->addRoute('helpdesk-category', new Am_Mvc_Router_Route( 'helpdesk/faq/c/:cat', array( 'module' => 'helpdesk', 'controller' => 'faq', 'action' => 'index' ) )); $router->addRoute('helpdesk-ticket', new Am_Mvc_Router_Route( 'helpdesk/ticket/:ticket', array( 'module' => 'helpdesk', 'controller' => 'index', 'action' => 'view', 'page_id' => 'view' ) )); $router->addRoute('helpdesk-ticket-admin', new Am_Mvc_Router_Route( 'helpdesk/admin/ticket/:ticket', array( 'module' => 'helpdesk', 'controller' => 'admin', 'action' => 'view', 'page_id' => 'view' ) )); $router->addRoute('helpdesk-new', new Am_Mvc_Router_Route( 'helpdesk/ticket/new', array( 'module' => 'helpdesk', 'controller' => 'index', 'action' => 'new', 'page_id' => 'view' ) )); $router->addRoute('helpdesk-new-admin', new Am_Mvc_Router_Route( 'helpdesk/admin/ticket/new', array( 'module' => 'helpdesk', 'controller' => 'admin', 'action' => 'new', 'page_id' => 'view' ) )); } function onBuildDemo(Am_Event $event) { $subjects = array( 'Please help', 'Urgent question', 'I have a problem', 'Important question', 'Pre-sale inquiry', ); $questions = array( "My website is now working. Can you help?", "I have a problem with website script.\nWhere can I find documentation?", "I am unable to place an order, my credit card is not accepted.", ); $answers = array( "Please call us to phone# 1-800-222-3334", "We are looking to your problem, and it will be resolved within 4 hours", ); $user = $event->getUser(); $now = $this->getDi()->time; $added = amstrtotime($user->added); /* @var $user User */ while (rand(0, 10) < 4) { $created = min($now, $added + rand(60, $now - $added)); $ticket = $this->getDi()->helpdeskTicketRecord; $ticket->status = HelpdeskTicket::STATUS_AWAITING_ADMIN_RESPONSE; $ticket->subject = $subjects[rand(0, count($subjects) - 1)]; $ticket->user_id = $user->pk(); $ticket->created = sqlTime($created); $ticket->updated = sqlTime($created); $ticket->insert(); // $msg = $this->getDi()->helpdeskMessageRecord; $msg->content = $questions[rand(0, count($questions) - 1)]; $msg->type = 'message'; $msg->ticket_id = $ticket->pk(); $msg->dattm = sqlTime($created); $msg->insert(); // if (rand(0, 10) < 6) { $msg = $this->getDi()->helpdeskMessageRecord; $msg->content = $answers[rand(0, count($answers) - 1)]; $msg->type = 'message'; $msg->ticket_id = $ticket->pk(); $msg->dattm = sqlTime(min($created + rand(60, 3600 * 24), $now)); $msg->admin_id = $this->getDi()->adminTable->findFirstBy()->pk(); $msg->insert(); if (rand(0, 10) < 6) $ticket->status = HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE; else $ticket->status = HelpdeskTicket::STATUS_CLOSED; $ticket->updated = $msg->dattm; $ticket->update(); } } } function onLoadReports() { require_once 'Am/Report/Helpdesk.php'; } function onDbUpgrade(Am_Event $e) { if (version_compare($e->getVersion(), '4.2.20') < 0) { echo "Fix FAQ categories..."; if (ob_get_level ()) ob_end_flush(); $this->getDi()->db->query("UPDATE ?_helpdesk_faq SET category=? WHERE category=?", null, ''); echo "Done
\n"; echo "Add default Order to Helpdesk FAQ..."; $this->getDi()->db->query("SET @i = 0"); $this->getDi()->db->query("UPDATE ?_helpdesk_faq SET sort_order=(@i:=@i+1)"); echo "Done
\n"; echo "Add default Order to Helpdesk Categories..."; $this->getDi()->db->query("SET @i = 0"); $this->getDi()->db->query("UPDATE ?_helpdesk_category SET sort_order=(@i:=@i+1)"); echo "Done
\n"; } if (version_compare($e->getVersion(), '5.0.5') <= 0) { echo "Update Ticket Status..."; $this->getDi()->db->query("UPDATE ?_helpdesk_ticket SET has_new=1 WHERE status IN (?a)", array(HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE)); echo "Done
\n"; } if (version_compare($e->getVersion(), '5.1.6') <= 0) { if (!$this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_access WHERE resource_type=?", HelpdeskCategory::ACCESS_TYPE)) { //idempotent action echo "Setup Default Protection for Categories..."; foreach($this->getDi()->helpdeskCategoryTable->findBy() as $cat) { $this->getDi()->resourceAccessTable ->setAccess($cat->pk(), HelpdeskCategory::ACCESS_TYPE, array( ResourceAccess::FN_FREE => array( json_encode(array( 'start' => null, 'stop' => null, 'text' => ___('Free Access') ))) )); } echo "Done
\n"; } } } }PK\mJ$helpdesk/module.xmlnu[ helpdesk Helpdesk Customer support helpdesk 5.0.6 PK\}0.helpdesk/controllers/AdminFieldsController.phpnu[hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_CATEGORY); } protected function getTable() { return $this->getDi()->helpdeskTicketTable; } public function createGrid() { $grid = parent::createGrid(); $grid->addCallback(Am_Grid_Editable::CB_AFTER_DELETE, array($this, 'afterDelete')); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_CATEGORY); return $grid; } public function createForm() { $form = new Am_Form_Admin_CustomField_Ticket($this->grid->getRecord()); $form->setTable($this->getTable()); return $form; } public function afterDelete($record) { foreach ($this->getDi()->helpdeskCategoryTable->findBy(array()) as $c) { $fields = $c->unserializeList($c->fields); if (in_array($record->name, $fields)) { $fields = array_diff($fields, array($record->name)); $c->fields = $c->serializeList($fields); $c->save(); } } } }PK\LEE*helpdesk/controllers/AdminMyController.phpnu[addWhere('t.owner_id=?d', Am_Di::getInstance()->authAdmin->getUserId()); $q->addWhere('t.status<>?', HelpdeskTicket::STATUS_CLOSED); return $q; } public function getGridTitle() { return ___('Tickets Assigned to Me'); } public function initGridFields() { parent::initGridFields(); $this->removeField('owner_id'); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Delete()); } } class Helpdesk_AdminMyController extends Am_Mvc_Controller_Pages { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_ID); } function preDispatch() { $this->view->headLink()->appendStylesheet($this->view->_scriptCss('helpdesk-admin.css')); $this->setActiveMenu('helpdesk-ticket-my'); parent::preDispatch(); } public function initPages() { $this->addPage('Am_Helpdesk_Grid_My', 'index', ___('Tickets')) ->addPage(array($this, 'createController'), 'view', ___('Conversation')); } public function renderTabs() { return ''; } public function createController($id, $title, $grid) { return new Am_Helpdesk_Controller($grid->getRequest(), $grid->getResponse(), $this->_invokeArgs); } }PK\'ʀ &helpdesk/controllers/FaqController.phpnu[getModule()->getConfig('does_not_require_login')) { $this->getDi()->auth->requireLogin($this->getDi()->url('helpdesk/faq',null,false,2)); } $this->view->headLink()->appendStylesheet($this->view->_scriptCss('helpdesk-user.css')); if ($this->getDi()->auth->getUser() && ($page = $this->getDi()->navigationUser->findOneBy('id', 'helpdesk-faq'))) { $page->setActive(true); } parent::preDispatch(); } public function indexAction() { $this->view->categories = $this->getDi()->helpdeskFaqTable->getCategories(); $this->view->catActive = $this->getParam('cat'); $this->view->faq = $this->getDi()->helpdeskFaqTable->findBy(array( 'category' => $this->getParam('cat', null)), null, null, 'sort_order'); if ($this->getParam('cat')) { $this->view->getHelper('breadcrumbs')->setPath(array($this->getDi()->url('helpdesk/faq',null,false) => ___('FAQ'))); } $this->view->display('helpdesk/faq.phtml'); } public function itemAction() { $path = array($this->getDi()->url('helpdesk/faq',null,false) => ___('FAQ')); $faq = $this->getDi()->helpdeskFaqTable->findFirstByTitle($this->getParam('title')); if ($faq->category) { $path[$this->getDi()->url('helpdesk/faq/c/' . urldecode($faq->category),null,false)] = $faq->category; } $this->view->getHelper('breadcrumbs')->setPath($path); $this->view->faq = $faq; $this->view->display('helpdesk/faq-item.phtml'); } public function searchAction() { $result = $this->getDi()->db->selectPage($total, "SELECT * FROM ?_helpdesk_faq WHERE MATCH(`title`,`content`) AGAINST (? IN NATURAL LANGUAGE MODE) LIMIT 10", $this->getParam('q')); $items = array(); foreach ($result as $row) $items[] = $this->getDi()->helpdeskFaqTable->createRecord($row); $this->view->items = $items; $this->view->display('helpdesk/_search-result.phtml'); } public function suggestAction() { $result = $this->getDi()->db->selectPage($total, "SELECT * FROM ?_helpdesk_faq WHERE MATCH(`title`,`content`) AGAINST (? IN NATURAL LANGUAGE MODE) LIMIT 10", $this->getParam('q')); $items = array(); foreach ($result as $row) $items[] = $this->getDi()->helpdeskFaqTable->createRecord($row); $this->view->items = $items; $this->view->display('helpdesk/_suggest.phtml'); } }PK\-a+helpdesk/controllers/AdminFaqController.phpnu[helpdeskFaqTable->getCategories()); $catoptions = array_merge(array('' => ___('-- Without A Category --')), $catoptions); $this->addSelect('category', array(), array('intrinsic_validation' => false, 'options' => $catoptions)) ->setLabel('Category'); $label_add_category = ___('add category'); $label_title_error = ___('Enter title for your new category'); $this->addScript() ->setScript(<< $label_add_category")); jQuery("select[name='category']").change(function(){ jQuery(this).toggle(jQuery(this).find('option').length > 1); }).change(); jQuery(document).on('click',"a#add-category", function(){ var ret = prompt("$label_title_error", ""); if (!ret) return; var \$sel = jQuery("select#category").append( jQuery("").val(ret).html(ret)); \$sel.val(ret).change(); }); }) CUT ); $this->addText('title', array('class' => 'el-wide')) ->setLabel(___('Title')); $this->addHtmlEditor('content') ->setLabel(___('Content')); } } class Am_Grid_Filter_HelpdeskFaq extends Am_Grid_Filter_Abstract { public function getTitle() { return ___('Filter By Title or Category'); } protected function applyFilter() { if ($this->isFiltered()) { $q = $this->grid->getDataSource(); /* @var $q Am_Query */ $q->addWhere('title LIKE ? OR category LIKE ?', '%' . $this->vars['filter'] . '%', '%' . $this->vars['filter'] . '%'); } } public function renderInputs() { return $this->renderInputText(); } } class Am_Grid_Action_EditFaqCategory extends Am_Grid_Action_Abstract { protected $type = self::NORECORD; protected $url; protected $attributes = array( 'target' => '_top' ); public function getUrl($record = null, $id = null) { return Am_Di::getInstance()->url('helpdesk/admin-faq/category',null,false); } public function run() { //nop } } class Am_Grid_Action_Back extends Am_Grid_Action_Abstract { protected $type = self::NORECORD; protected $url; protected $attributes = array( 'target' => '_top' ); public function getUrl($record = null, $id = null) { return Am_Di::getInstance()->url('helpdesk/admin-faq',null,false); } public function run() { //nop } } class Am_Grid_DataSource_FaqCategory extends Am_Grid_DataSource_Array { public function updateRecord($record, $valuesFromForm) { Am_Di::getInstance()->db->query('UPDATE ?_helpdesk_faq SET category=? WHERE category=?', $valuesFromForm['name'], $record->name); } } class Helpdesk_AdminFaqController extends Am_Mvc_Controller_Grid { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_FAQ); } public function createGrid() { $ds = new Am_Query($this->getDi()->helpdeskFaqTable); $ds->setOrder('sort_order'); $grid = new Am_Grid_Editable('_helpdesk_faq', ___('FAQ'), $ds, $this->_request, $this->view); $grid->addField(new Am_Grid_Field('title', ___('Title'), true, '', null, '50%')); $grid->addField(new Am_Grid_Field('category', ___('Category'))); $grid->addField('_link', ___('Link'), false)->setRenderFunction(array($this, 'renderLink')); $grid->setForm('Am_Form_Admin_HelpdeskFaq'); $grid->setFilter(new Am_Grid_Filter_HelpdeskFaq()); $grid->addCallback(Am_Grid_Editable::CB_VALUES_FROM_FORM, array($this, 'valuesFromForm')); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_FAQ); $grid->actionAdd(new Am_Grid_Action_Sort_HelpdeskFaq()); if ($this->getDi()->helpdeskFaqTable->getCategories()) { $grid->actionAdd(new Am_Grid_Action_EditFaqCategory('faq-edit-category', ___('Edit Categories'))) ->setCssClass('link'); } return $grid; } public function categoryAction() { $ret = array(); foreach ($this->getDi()->helpdeskFaqTable->getCategories() as $category) { $cat = new stdClass(); $cat->name = $category; $ret[] = $cat; } $ds = new Am_Grid_DataSource_FaqCategory($ret); $grid = new Am_Grid_Editable('_helpdesk_faq_category', ___('Categories'), $ds, $this->_request, $this->view); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_FAQ); $grid->addField(new Am_Grid_Field('name', ___('Title'))); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_Back('faq-edit-category-back', ___('Back to FAQ List'))) ->setCssClass('link'); $grid->actionAdd(new Am_Grid_Action_LiveEdit('name')); $grid->runWithLayout('admin/layout.phtml'); } public function valuesFromForm(& $ret, HelpdeskFaq $record) { if (!isset($ret['category']) || !$ret['category']) $ret['category'] = null; } public function renderLink(Am_Record $record) { $url = Am_Di::getInstance()->url('helpdesk/faq/i/'.urlencode($record->title)); return $this->renderTd(sprintf('%s', $url, ___('link')), false); } } class Am_Grid_Action_Sort_HelpdeskFaq extends Am_Grid_Action_Sort_Abstract { protected function setSortBetween($item, $after, $before) { $this->_simpleSort(Am_Di::getInstance()->helpdeskFaqTable, $item, $after, $before); } }PK\8 z0helpdesk/controllers/AdminCategoryController.phpnu[addText('title', array('size' => 40)) ->setLabel(___('Title')); $options = array(); foreach (Am_Di::getInstance()->adminTable->findBy() as $admin) { $options[$admin->pk()] = sprintf('%s (%s %s)', $admin->login, $admin->name_f, $admin->name_l); } $this->addSelect('owner_id') ->setLabel(___("Owner\n". 'set the following admin as owner of ticket')) ->loadOptions(array('' => '') + $options); $this->addMagicSelect('watcher_ids') ->setLabel(___("Watchers\n" . 'notify the following admins ' . 'about new messages in this category')) ->loadOptions($options); $options = array(); foreach(Am_Di::getInstance()->helpdeskTicketTable->customFields()->getAll() as $f) { $options[$f->getName()] = $f->title; } $url = Am_Di::getInstance()->url('helpdesk/admin-fields'); $this->addSortableMagicSelect('fields') ->setLabel(___("Fields\n" . "You can add new fields %shere%s", '', '')) ->loadOptions($options); $this->addElement(new Am_Form_Element_ResourceAccess) ->setName('_access') ->setLabel(___("Access Permissions\n" . 'this category will be available only for users ' . 'with proper access permission')) ->setAttribute('without_free_without_login', 'true'); } } class Am_Grid_Action_Sort_HelpdeskCategory extends Am_Grid_Action_Sort_Abstract { protected function setSortBetween($item, $after, $before) { $this->_simpleSort(Am_Di::getInstance()->helpdeskCategoryTable, $item, $after, $before); } } class Helpdesk_AdminCategoryController extends Am_Mvc_Controller_Grid { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_CATEGORY); } public function preDispatch() { parent::preDispatch(); $this->view->headScript()->appendFile($this->view->_scriptJs("resourceaccess.js")); } public function createGrid() { $ds = new Am_Query($this->getDi()->helpdeskCategoryTable); $ds->leftJoin('?_admin', 'a', 't.owner_id=a.admin_id') ->addField("CONCAT(a.login, ' (',a.name_f, ' ', a.name_l, ')')", 'owner'); $ds->setOrder('sort_order'); $grid = new Am_Grid_Editable('_helpdesk_category', ___("Ticket Categories"), $ds, $this->_request, $this->view); $grid->addField(new Am_Grid_Field('title', ___('Title'))); $grid->addField(new Am_Grid_Field('fields', ___('Fields'))) ->setGetFunction(function($r, $grid, $fieldname, $field){ return implode(', ', $r->unserializeList($r->{$fieldname})); }); $grid->addField(new Am_Grid_Field('owner_id', ___('Owner'), true, '', array($this, 'renderOwner'))); $grid->addField(new Am_Grid_Field_IsDisabled); $grid->setForm('Am_Form_Admin_HelpdeskCategory'); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_SAVE, array($this, 'beforeSave')); $grid->setPermissionId(Bootstrap_Helpdesk::ADMIN_PERM_CATEGORY); $grid->actionAdd(new Am_Grid_Action_Sort_HelpdeskCategory()); $grid->setFormValueCallback('watcher_ids', array('RECORD', 'unserializeIds'), array('RECORD', 'serializeIds')); $grid->setFormValueCallback('fields', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->addCallback(Am_Grid_Editable::CB_AFTER_DELETE, array($this, 'afterDelete')); $grid->addCallback(Am_Grid_Editable::CB_AFTER_SAVE, array($this, 'afterSave')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); return $grid; } public function renderOwner($record) { return $record->owner_id ? sprintf('%s', Am_Html::escape($record->owner)) : ''; } public function beforeSave(& $values, $record) { $values['owner_id'] = $values['owner_id'] ? $values['owner_id'] : null; } public function valuesToForm(& $ret, $record) { $ret['_access'] = $record->isLoaded() ? $this->getDi()->resourceAccessTable->getAccessList($record->pk(), HelpdeskCategory::ACCESS_TYPE) : array( ResourceAccess::FN_FREE => array( json_encode(array( 'start' => null, 'stop' => null, 'text' => ___('Free Access') )))); } public function afterSave(array & $values, $record) { $this->getDi()->resourceAccessTable->setAccess($record->pk(), HelpdeskCategory::ACCESS_TYPE, $values['_access']); } public function afterDelete($record) { $this->getDi()->resourceAccessTable->clearAccess($record->pk(), HelpdeskCategory::ACCESS_TYPE); } }PK\(helpdesk/controllers/AdminController.phpnu[hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_ID); } function preDispatch() { $this->view->headLink()->appendStylesheet($this->view->_scriptCss('helpdesk-admin.css')); $this->setActiveMenu('helpdesk-ticket'); parent::preDispatch(); } public function initPages() { $this->addPage('Am_Helpdesk_Grid_Admin_Dashboard', 'index', ___('Tickets')) ->addPage(array($this, 'createController'), 'view', ___('Conversation')); } public function renderTabs() { return ''; } public function createController($id, $title, $grid) { return new Am_Helpdesk_Controller($grid->getRequest(), $grid->getResponse(), $this->_invokeArgs); } public function archiveAction() { $grid = new Am_Helpdesk_Grid_Admin_Archive($this->getRequest(), $this->view); $grid->runWithLayout('admin/layout.phtml'); } }PK\a,helpdesk/controllers/AdminUserController.phpnu[user_id = $this->getCompleteRequest()->get('user_id', 0); if ($this->user_id) { $this->getDataSource()->getDataSourceQuery()->addWhere('t.user_id=?d', $this->user_id); } } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Ticket()); } } class Helpdesk_AdminUserController extends Am_Mvc_Controller_Pages { protected $layout = 'admin/user-layout.phtml'; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Bootstrap_Helpdesk::ADMIN_PERM_ID); } function preDispatch() { $this->getDi()->navigationUserTabs->setActive('helpdesk'); $this->getDi()->helpdeskStrategy->setUserId( $this->getRequest()->getParam('user_id', 0) ); $this->view->headLink()->appendStylesheet($this->view->_scriptCss('helpdesk-admin.css')); $this->setActiveMenu('users-browse'); parent::preDispatch(); } public function initPages() { $this->addPage('Am_Helpdesk_Grid_UserTab', 'index', ___('Tickets')) ->addPage(array($this, 'createController'), 'view', ___('Conversation')); } public function renderTabs() { return ''; } public function createController($id, $title, $grid) { return new Am_Helpdesk_Controller($grid->getRequest(), $grid->getResponse(), $this->_invokeArgs); } }PK\v v (helpdesk/controllers/IndexController.phpnu[addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, function(&$attrs, $r){ if ($r->has_new) { $attrs['class'] = isset($attrs['class']) ? $attrs['class'] . ' emphase' : 'emphase'; } }); $uid = $this->getDi()->auth->getUserId(); if ($this->getDi()->helpdeskTicketTable->countByUserId($uid) < 10) { $this->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, function(&$out, $g){ $out = preg_replace('/.*?/is', '', $out); }); } parent::init(); } public function initGridFields() { $this->addField(new Am_Grid_Field('subject', ___('Subject'), true, '', array($this, 'renderSubject'))); $this->addField(new Am_Grid_Field('updated', ___('Updated'), true, '', array($this, 'renderTime'))); $this->addField(new Am_Grid_Field('ticket_mask', '#', true)); $this->addField(new Am_Grid_Field('status', ___('Status'), true, '', array($this, 'renderStatus'), '1%')); $this->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'cbGetTrAttribs')); } protected function createFilter() { return new Am_Grid_Filter_Helpdesk; } public function getStatusIconId($id, $record) { return $id == 'awaiting' && $record->status == HelpdeskTicket::STATUS_AWAITING_USER_RESPONSE ? $id . '-me' : $id; } protected function isNotImportant($record) { return $record->status == HelpdeskTicket::STATUS_CLOSED; } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Ticket()); } public function createDs() { $query = parent::createDS(); $query->addWhere('t.user_id=?', Am_Di::getInstance()->auth->getUserId() ); return $query; } } class Helpdesk_IndexController extends Am_Mvc_Controller_Pages { protected $layout = 'member/layout.phtml'; function preDispatch() { $this->getDi()->auth->requireLogin($this->getDi()->url('helpdesk',null,false,2)); $this->view->headLink()->appendStylesheet($this->view->_scriptCss('helpdesk-user.css')); $this->view->headScript()->appendFile($this->view->_scriptJs('jquery/jquery.form.js')); if ($page = $this->getDi()->navigationUser->findOneBy('id', 'helpdesk')) { $page->setActive(true); } parent::preDispatch(); } public function initPages() { $this->addPage('Am_Helpdesk_Grid_User', 'index', ___('Tickets')) ->addPage(array($this, 'createController'), 'view', ___('Conversation')); } public function renderTabs() { $intro = $this->getDi()->config->get('helpdesk.intro'); return $intro ? sprintf('
%s
', $intro) : ''; } public function createController($id, $title, $grid) { return new Am_Helpdesk_Controller($grid->getRequest(), $grid->getResponse(), $this->_invokeArgs); } }PK\+O &helpdesk/views/helpdesk/_message.phtmlnu[isMessageAvalable($message)) : ?> loadGetAttachments(); ?>
name;}, $uploads))); ?>" src="_scriptImg('attachment.png')) ?>" />
isShowAvatar()) :?>
getAvatar($message); ?>
getName($message)) ?> · , content))), 0, 120)) ?>…
hyperlinks($this->skip($message->content)) ?>
    loadGetAttachments() as $upload) : ?>
  • name) ?> (getSizeReadable()) ?>)
canEditMessage($message)) : ?>
isMessageForReply($message) && $strategy->canEditTicket($ticket)) : ?>
_script($strategy->getTemplatePath() . '/_reply-panel.phtml'); ?>
PK\8*helpdesk/views/helpdesk/_reply-panel.phtmlnu[
canUseSnippets() || $strategy->canUseFaq()) : ?>
canUseSnippets()): ?>
canUseFaq()): ?>
PK\aOO!helpdesk/views/helpdesk/faq.phtmlnu[setLayout('member/layout.phtml'); /* @var $di Am_Di */ $di; ?> modules->get('helpdesk')->getConfig('show_faq_search')) : ?> render('helpdesk/_search-form.phtml') ?>
PK\p<,helpdesk/views/helpdesk/_search-result.phtmlnu[PK\ZXX&helpdesk/views/helpdesk/faq-item.phtmlnu[title; $this->setLayout('member/layout.phtml'); echo $faq->content;PK\hnqq&helpdesk/views/helpdesk/_suggest.phtmlnu[ PK\~)vv#helpdesk/views/helpdesk/index.phtmlnu[layoutNoTitle = true; if ($this->switchLayout) { $this->setLayout($this->switchLayout); } echo @$content;PK\r!X1helpdesk/views/helpdesk/_select-status-form.phtmlnu[
formSelect('status', $ticket->status, null, HelpdeskTicket::getStatusOptions()) ?>
PK\i3*helpdesk/views/helpdesk/_search-form.phtmlnu[
PK\c NN$helpdesk/views/helpdesk/ticket.phtmlnu[modules->loadGet('helpdesk')->getConfig('live'); ?>

subject) ?> #ticket_mask) ?> · title) ?>

isLocked($di->authAdmin->getUser())) : ?>
  • lock_admin); ?>
_script($strategy->getTemplatePath() . '/_history.phtml'); ?> comment) : ?>
comment) ?>
    $field) : ?> helpdeskGetTicketField($ticket, $fn)) : ?>
  • title) ?>:
_script($strategy->getTemplatePath() . '/_select-status-form.phtml'); } ?>
: created)) ?> owner_id && $strategy->canViewOwner($ticket)) : ?> getOwner() ?> : name_f || $owner->name_l) : ?> login) ?> (name_f $owner->name_l")) ?>) login) ?>
canEditTicket($ticket)) : ?>
status == HelpdeskTicket::STATUS_CLOSED) : ?>
canEditOwner($ticket)) : ?> owner_id && $ticket->owner_id == $di->authAdmin->getUserId()) : ?>
owner_id): ?>
canEditWatcher($ticket)) : ?>
canEditCategory($ticket) && $di->helpdeskCategoryTable->getOptions(true)) : ?>
_script($strategy->getTemplatePath() . '/_reply-panel.phtml'); ?>
getMessages() as $message) { if (!$js_added && $isLive) { $js = json_encode($strategy->newUrl() . '?' . http_build_query(array( 'id' => $this->obfuscate($message->pk()) ))); $this->placeholder("head-finish")->append(<< jQuery(function(){ amHelpdeskUpdate($js); }); CUT ); $js_added = true; } include $this->_script($strategy->getTemplatePath() . '/_message.phtml'); } ?>
PK\+helpdesk/views/public/css/helpdesk-user.cssnu[/* Helpdesk FAQ */ .am-helpdesk-faq-list { margin-left: 2em; } .am-helpdesk-faq-list .am-helpdesk-faq-list-item { list-style: decimal; padding-bottom: 0.5em; } .am-helpdesk-faq-search-result { padding-top: 1em; } /* Helpdesk */ .am-helpdesk { width: 100%; display: inline-block; text-align: left; margin-top: 0.5em; } .am-helpdesk h3 { text-align: left; padding-top: 0; margin-top: 0; } /* Ticket */ .am-helpdesk-ticket { margin-bottom: 0.5em; } .am-helpdesk-ticket .am-helpdesk-ticket-info { padding: 0.4em 0; } .am-helpdesk-ticket-header { overflow: hidden; } .am-helpdesk-ticket-status { float: right; } .am-helpdesk-ticket-actions-conteiner { overflow: hidden; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: #ccc 1px solid; margin-top: 0.5em; } .am-helpdesk-ticket-actions { overflow: hidden; } .am-helpdesk-ticket-action { display: inline-block; padding: 0.5em; -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .am-helpdesk-ticket-action.am-helpdesk-action-active { background-color: #dbdbdb; } .am-helpdesk-ticket-action-fold-all { padding-left: 0.5em; line-height: 0.6em; font-size: 1.3em; float: right; } .am-helpdesk-ticket-action-fold-all a { text-decoration: none; } .am-helpdesk-ticket-fields { padding-bottom: 0.5em; } /* Reply Panel */ .am-helpdesk-reply-panel { padding: 0.5em; background: #dbdbdb; display: none; -moz-border-radius: 0 0 3px 3px; -webkit-border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px; } .am-helpdesk-reply-panel-tools { overflow: hidden; padding: 0.5em 0; } .am-helpdesk-reply-panel-tool { float: left; padding-right: 0.5em; } .am-helpdesk-reply-panel-content .am-form div.row.no-label .element { padding: 0 0 0.5em; } .am-helpdesk-reply-panel-content .am-form div.row.no-label .element textarea { font-family: monospace; line-height: 140%; resize: vertical; border: none; padding: 1em; } .am-helpdesk-reply-panel-content .am-form div.row.no-label .element textarea:focus { background: white; border: none; } .am-helpdesk-reply-panel-content .am-form { margin: 0; } .am-helpdesk-reply-panel-content .am-form form { background: none; border: 0; box-shadow: none; } .am-helpdesk-reply-panel-content .am-form div.row { border: 0; } .am-helpdesk-reply-panel-content .am-form .element-title, .am-helpdesk-reply-panel-content .am-form .element { padding-top: 0.4em; padding-bottom: 0.4em; } .am-helpdesk-reply-panel-content .am-form #row-attachments-0 { display: none; } .am-helpdesk-form #row-attachments-0 { display: none; } /* Message */ .am-helpdesk-message { margin-bottom: 0.5em; border-radius: 3px; border: #dbdbdb 1px solid; } .am-helpdesk-message.am-helpdesk-message-inbound { background: #fff9ea; } .am-helpdesk-message.am-helpdesk-message-outbound { background: #fff; } .am-helpdesk-message.am-helpdesk-message-comment { background: #e8f5e9; } .am-helpdesk-message-brief { display: none; } .am-helpdesk-message-has-attachments { float: right; } .am-helpdesk-message-closed .am-helpdesk-message-brief { display: inline; } .am-helpdesk-message-closed .am-helpdesk-message-full { display: none; } .am-helpdesk-message-closed .am-helpdesk-message-header { opacity: 1; } .am-helpdesk-message-outbound.am-helpdesk-message-closed .am-helpdesk-message-header { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .am-helpdesk-message-header { -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; padding: 0.5em; margin: 0; overflow: hidden; opacity: 0.8; } .am-helpdesk-message-author { font-weight: bold; } .am-helpdesk-message-author-avatar { float: left; width: 40px; height: 40px; overflow: hidden; border-radius: 50%; margin-right: 1em; } .am-helpdesk-message-content { padding: 0.5em; margin: 0; } .am-helpdesk-message-content pre { color: #4d4948; margin: 0; white-space: pre-wrap; word-wrap: break-word; line-height: 150%; font-family: monospace; font-size: 12px; } .am-helpdesk ul.am-helpdesk-message-attachments { margin: 0.5em 0 0; } .am-helpdesk ul.am-helpdesk-message-attachments li.am-helpdesk-message-attachments-item { list-style-type: none; } .am-helpdesk ul.am-helpdesk-message-attachments li.am-helpdesk-message-attachments-item:before { content: "\2013\00a0"; } .am-helpdesk-message-action { display: inline-block; padding: 0.5em; -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .am-helpdesk-message-action.am-helpdesk-action-active { background-color: #dbdbdb; } .am-helpdesk-message-action-fold { padding-left: 0.5em; line-height: 0.6em; font-size: 1.3em; float: right; } .am-helpdesk-message-action-fold a { text-decoration: none; } /* History */ .am-helpdesk-history { border-bottom: 1px solid #a1a1a1; margin-bottom: 0.5em; } .am-helpdesk-history h1 { font-size: 1.4rem; margin-bottom: 0.5em; } .am-helpdesk-history-content { display: none; border-top: 1px solid #a1a1a1; padding-top: 0.5em; } .am-helpdesk-history-title { overflow: hidden; margin-bottom: 0.5em; } .am-helpdesk-history-title-action { float: right; } .am-helpdesk-history-title-action a { display: block; padding-right: 10px; background: url("../img/arrow.png") no-repeat center right; } ul.am-helpdesk-faq-cat .am-helpdesk-faq-cat-item { list-style-type: none; } .am-helpdesk-grid-msg-cnt { background: #babec0; color: white; padding: 1px 4px; font-size: 10px; line-height: 1; text-transform: uppercase; border-radius: 6px; } .am-helpdesk-grid-msg { color: #888; } PK\ib,helpdesk/views/public/css/helpdesk-admin.cssnu[/* Helpdesk */ .am-helpdesk { width: 100%; display: inline-block; text-align: left; margin-top: 0.5em; } .am-helpdesk h3 { text-align: left; padding-top: 0; margin-top: 0; } /* Ticket */ .am-helpdesk-ticket { margin-bottom: 0.5em; } .am-helpdesk-ticket .am-helpdesk-ticket-info { padding: 0.4em 0; } .am-helpdesk-ticket-header { overflow: hidden; } .am-helpdesk-ticket-status { float: right; } .am-helpdesk-ticket-actions-conteiner { overflow: hidden; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: #ccc 1px solid; margin-top: 0.5em; } .am-helpdesk-ticket-actions { overflow: hidden; } .am-helpdesk-ticket-action { display: inline-block; padding: 0.5em; -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .am-helpdesk-ticket-action.am-helpdesk-action-active { background-color: #dbdbdb; } .am-helpdesk-ticket-action-fold-all { padding-left: 0.5em; line-height: 0.6em; font-size: 1.3em; float: right; } .am-helpdesk-ticket-action-fold-all a { text-decoration: none; } .am-helpdesk-ticket-fields { padding-bottom: 0.5em; } /* Reply Panel */ .am-helpdesk-reply-panel { padding: 0.5em; background: #dbdbdb; display: none; -moz-border-radius: 0 0 3px 3px; -webkit-border-radius: 0 0 3px 3px; border-radius: 0 0 3px 3px; } .am-helpdesk-reply-panel-tools { overflow: hidden; padding: 0.5em 0; } .am-helpdesk-reply-panel-tool { float: left; padding-right: 0.5em; } .am-helpdesk-reply-panel-content .am-form div.row.no-label .element { padding: 0 0 0.5em; } .am-helpdesk-reply-panel-content .am-form div.row.no-label .element textarea { font-family: monospace; line-height: 140%; resize: vertical; border: none; padding: 1em; } .am-helpdesk-reply-panel-content .am-form div.row.no-label .element textarea:focus { background: white; border: none; } .am-helpdesk-reply-panel-content .am-form { margin: 0; } .am-helpdesk-reply-panel-content .am-form form { background: none; border: 0; box-shadow: none; } .am-helpdesk-reply-panel-content .am-form div.row { border: 0; } .am-helpdesk-reply-panel-content .am-form .element-title, .am-helpdesk-reply-panel-content .am-form .element { padding-top: 0.4em; padding-bottom: 0.4em; } .am-helpdesk-reply-panel-content .am-form #row-attachments-0 { display: none; } .am-helpdesk-form #row-attachments-0 { display: none; } /* Message */ .am-helpdesk-message { margin-bottom: 0.5em; border-radius: 3px; border: #dbdbdb 1px solid; } .am-helpdesk-message.am-helpdesk-message-inbound { background: #fff9ea; } .am-helpdesk-message.am-helpdesk-message-outbound { background: #fff; } .am-helpdesk-message.am-helpdesk-message-comment { background: #e8f5e9; } .am-helpdesk-message-brief { display: none; } .am-helpdesk-message-has-attachments { float: right; } .am-helpdesk-message-closed .am-helpdesk-message-brief { display: inline; } .am-helpdesk-message-closed .am-helpdesk-message-full { display: none; } .am-helpdesk-message-closed .am-helpdesk-message-header { opacity: 1; } .am-helpdesk-message-outbound.am-helpdesk-message-closed .am-helpdesk-message-header { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .am-helpdesk-message-header { -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; padding: 0.5em; margin: 0; overflow: hidden; opacity: 0.8; } .am-helpdesk-message-author { font-weight: bold; } .am-helpdesk-message-author-avatar { float: left; width: 40px; height: 40px; overflow: hidden; border-radius: 50%; margin-right: 1em; } .am-helpdesk-message-content { padding: 0.5em; margin: 0; } .am-helpdesk-message-content pre { color: #4d4948; margin: 0; white-space: pre-wrap; word-wrap: break-word; line-height: 150%; font-family: monospace; font-size: 12px; } .am-helpdesk ul.am-helpdesk-message-attachments { margin: 0.5em 0 0; } .am-helpdesk ul.am-helpdesk-message-attachments li.am-helpdesk-message-attachments-item { list-style-type: none; } .am-helpdesk ul.am-helpdesk-message-attachments li.am-helpdesk-message-attachments-item:before { content: "\2013\00a0"; } .am-helpdesk-message-action { display: inline-block; padding: 0.5em; -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .am-helpdesk-message-action.am-helpdesk-action-active { background-color: #dbdbdb; } .am-helpdesk-message-action-fold { padding-left: 0.5em; line-height: 0.6em; font-size: 1.3em; float: right; } .am-helpdesk-message-action-fold a { text-decoration: none; } /* History */ .am-helpdesk-history { border-bottom: 1px solid #a1a1a1; margin-bottom: 0.5em; } .am-helpdesk-history h1 { font-size: 1.4rem; margin-bottom: 0.5em; } .am-helpdesk-history-content { display: none; border-top: 1px solid #a1a1a1; padding-top: 0.5em; } .am-helpdesk-history-title { overflow: hidden; margin-bottom: 0.5em; } .am-helpdesk-history-title-action { float: right; } .am-helpdesk-history-title-action a { display: block; padding-right: 10px; background: url("../img/arrow.png") no-repeat center right; } ul.am-helpdesk-faq-cat .am-helpdesk-faq-cat-item { list-style-type: none; } .am-helpdesk-grid-msg-cnt { background: #babec0; color: white; padding: 1px 4px; font-size: 10px; line-height: 1; text-transform: uppercase; border-radius: 6px; } .am-helpdesk-grid-msg { color: #888; } PK\Sm isMessageAvalable($message)) : ?>
[]
modules->get('helpdesk')->getConfig('show_gravatar')) :?>
admin_id) { echo $strategy->getAdminGravatar($message); } else { echo $strategy->getUserGravatar($message); } ?>
admin_id) { p($strategy->getAdminName($message)); } else { p($strategy->getUserName($message)); } ?>,
hyperlinks($this->skip($message->content)) ?>
loadGetAttachments() as $upload) : ?> – name) ?> (getSizeReadable()) ?>)
type == 'comment') : ?>
isMessageForReply($message) && $strategy->canEditTicket($ticket)) : ?>
_script($strategy->getTemplatePath() . '/_reply-panel.phtml'); ?>
PK\80helpdesk/views/admin/helpdesk/_reply-panel.phtmlnu[
canUseSnippets() || $strategy->canUseFaq()) : ?>
canUseSnippets()): ?>
canUseFaq()): ?>
PK\9_ 3helpdesk/views/admin/helpdesk/widget/messages.phtmlnu[helpdeskMessageTable->selectLast($num); ?>

admin_id) : ?> a_name_f || $m->a_name_l) : ?> a_name_f) ?> a_name_l) ?> (a_login) ?>) a_login) ?> u_name_f || $m->u_name_l) : ?> u_name_f) ?> u_name_l) ?> (u_login) ?>) u_login) ?> · · subject) ?>

PK\~)vv)helpdesk/views/admin/helpdesk/index.phtmlnu[layoutNoTitle = true; if ($this->switchLayout) { $this->setLayout($this->switchLayout); } echo @$content;PK\aap,helpdesk/views/admin/helpdesk/_history.phtmlnu[
login) ?> getName())) : ?> (getName()) ?>) productTable->getProductTitles($user->getActiveProductIds()))) ?>
PK\r!X7helpdesk/views/admin/helpdesk/_select-status-form.phtmlnu[
formSelect('status', $ticket->status, null, HelpdeskTicket::getStatusOptions()) ?>
PK\D::*helpdesk/views/admin/helpdesk/ticket.phtmlnu[layoutNoTitle = true ?>

()

isLocked($di->authAdmin->getUser())) : ?>
  • lock_admin); ?>
login) ?> (getName()) ?>)
comment) : ?>
comment) ?>
_script($strategy->getTemplatePath() . '/_select-status-form.phtml'); } ?>

subject) ?> [#ticket_mask) ?>] title) ?> created)) ?>

owner_id && $strategy->canViewOwner($ticket)) : ?> getOwner() ?>

Owner: login) ?> (name_f) ?> name_l) ?>)

canEditTicket($ticket)) : ?>
status == HelpdeskTicket::STATUS_CLOSED) : ?>
canEditOwner($ticket)) : ?> owner_id && $ticket->owner_id == $di->authAdmin->getUserId()) : ?>
owner_id): ?>
canEditCategory($ticket) && $di->helpdeskCategoryTable->getOptions(true)) : ?>
[]
_script($strategy->getTemplatePath() . '/_reply-panel.phtml'); ?>
getMessages() as $message) { include $this->_script($strategy->getTemplatePath() . '/_message.phtml'); } ?>
PK\ 88configs/key-dist.phpnu[ array( 'mysql' => array( 'db' => 'ajtDemoMemPro', 'user' => 'ajtDemoMemProusr', 'pass' => '~9Z1bk5j!C', 'host' => 'localhost', 'prefix' => 'ajt_am_', 'port' => '', ), ), ); PK\Ĺconfigs/site-dist.jsnu[/** * You can place your custom JS scripts here * it is better to write everything custom here * because this file won't be replaced during upgrade * Don't forget to rename this file to "site.js" */PK\17Dconfigs/config-dist.phpnu[ array( 'mysql' => array( 'db' => '@DB_MYSQL_DB@', 'user' => '@DB_MYSQL_USER@', 'pass' => '@DB_MYSQL_PASS@', 'host' => '@DB_MYSQL_HOST@', 'prefix' => '@DB_MYSQL_PREFIX@', 'port' => '@DB_MYSQL_PORT@', ), ), ); PK\default/db.xmlnu[
INSERT INTO ?_admin (login, pass, email, super_user, name_f, name_l) VALUES ('@ADMIN_LOGIN@', '@ADMIN_PASS@', '@ADMIN_EMAIL@', 1, '', '');
1 Default Billing Plan 1.11 1d 99999 2.22 2d USD 0
ALTER TABLE ?_email_template_layout AUTO_INCREMENT = 101; 1 Default User Layout Dear %user.name_f% %user.name_l%, %content% -- Best Regards, %site_title% %root_url% 2 Default Admin Layout Dear Administrator, %content% -- Best Regards, %site_title% %root_url% 3 Default Affiliate Layout Dear %affiliate.name_f% %affiliate.name_l%, %content% -- Best Regards, %site_title% %root_url%
Sample Subscription this is a sample subscription type payment,product USD 1 1
Signup Form customer signup/payment form default [{"id":"product-0","class":"product"},{"id":"paysystem","class":"paysystem"},{"id":"name","class":"name","hide-if-logged-in":true},{"id":"email","class":"email","hide-if-logged-in":true},{"id":"login","class":"login","hide-if-logged-in":true},{"id":"password","class":"password","hide-if-logged-in":true}] signup,member signup 1 Create Customer Profile shopping cart signup form [{"id":"name","class":"name","hide-if-logged-in":true},{"id":"email","class":"email","hide-if-logged-in":true},{"id":"login","class":"login","hide-if-logged-in":true},{"id":"password","class":"password","hide-if-logged-in":true}] cart 2 Customer Profile customer profile form default [{"id":"name","class":"name","hide-if-logged-in":true},{"id":"email","class":"email","hide-if-logged-in":true},{"id":"new-password","class":"new-password"}] profile profile 3 Affiliate Signup Form affiliate signup form [{"id":"name","class":"name","hide":"1"},{"id":"email","class":"email","hide":true},{"id":"login","class":"login","hide":true},{"id":"password","class":"password","hide":true},{"id":"address","class":"address","hide":"1","config":{"fields":{"street":1,"city":1,"country":1,"state":1,"zip":1}}},{"id":"payout","class":"payout"}] aff 4
PK\p{v?.<.<default/email-templates.xmlnu[ bruteforce_notify 2 en text %site_title%: Bruteforce Attack Detected Bruteforce Attack Detected. IP: %ip% Last Used Login: %login% send_security_code 1 en text %site_title%: Password Recovery You have requested your log in information. Your User ID: %user.login% Follow a link below to change your password: %url% This link will be active %hours% hour(s). send_security_code_admin 2 en text %site_title%: Password Recovery You have requested your admin log in information. Your User ID: %user.login% Follow a link below to change your password: %url% This link will be active %hours% hour(s). send_password_admin 2 en text %site_title%: New Admin Password You have requested to reset your access credentials. Your User ID: %user.login% New Password: %pass% Please login to admin control panel at: %root_url%/admin/ profile_changed 2 en text %site_title%: User profile has been changed User has changed profile. User details: Username: %user.login% Email: %user.email% Name: %user.name_f% %user.name_l% Changed fields: %changes% manually_approve 1 en text %site_title%: Your signup is pending Thank you for subscribing! We review all payments manually, so your payment status is pending. You will receive email when your account will be approved. Thank you for your patience. invoice_approval_wait_user 1 en text %site_title%: Your payment is under review Thank you for subscribing! We review all payments manually, so your payment status is pending. You will receive email when your payment will be approved. Thank you for your patience. invoice_pay_link 1 en text %site_title%: New Invoice %message% Follow a link below to pay Invoice: %url% %invoice_text% Invoice is valid until: %invoice.due_date|date% invoice_approved_user 1 en text %site_title%: Your payment was approved! Thank you for subscribing! Your payment was approved by our staff. Your User ID: %user.login% Log-on to your member pages at: %root_url%/member mail_cancel_admin 2 en text %site_title%: User subscription cancelled User %user.login%, "%user.name_f% %user.name_l%" <%user.email%> has cancelled recurring subscription #%invoice.invoice_id% to product %product.title%. mail_cancel_member 1 en text %site_title%: Subscription cancelled Your subscription to "%product.title%" cancelled. Feel free to subscribe again, you can do it here: %root_url%/member send_payment_admin 2 en text %site_title%: *** New Payment Payment Amount: %payment.amount% %payment.currency% Payment Reference: %payment.receipt_id% %invoice_text% User details: Username: %user.login% Email: %user.email% Name: %user.name_f% %user.name_l% registration_mail 1 en text %site_title%: Registration Thank you for registration on %site_title%! Your User ID: %user.login% Your Password: %password% Log-on to your member pages at: %root_url%/member registration_mail_admin 2 en text %site_title%: User Registration changepass_mail 1 en text %site_title%: Password Change You changed password on %site_title%! Your User ID: %user.login% Your Password: %password% Log-on to your member pages at: %root_url%/member send_signup_mail 1 en text %site_title%: Membership Information Thank you for subscribing on %site_title%! Your User ID: %user.login% Log-on to your member pages at: %root_url%/member send_payment_mail 1 en text %site_title%: Payment Receipt Thank you for your order. You may find order details below: Payment Amount: %payment.amount% %payment.currency% Payment Reference: %payment.receipt_id% %invoice_text% verify_email_signup 1 en text %site_title%: Account Verification You (or someone else) has just registered an account on %site_title%. Clicking on the link below will activate the account: %url% verify_email_profile 1 en text %site_title%: Account Verification You (or someone else) has just changed email address in your account on %site_title%. Clicking on the link below will approve this change: %url% Please note that email address will be changed in your profile only if you will click on above link. If you didn't request email address change just disregard this message. send_free_payment_admin 2 en text %site_title%: *** New Free Signup %invoice_text% User details: Username: %user.login% Email: %user.email% Name: %user.name_f% %user.name_l% manually_approve_admin 2 en text %site_title%: Your approval required New signup completed and is awaiting your approval. Please log into aMember CP %root_url%/admin/ and then click the following link: %root_url%/admin-users?_u_a=edit&_u_id=%user.user_id% User details: Username: %user.login% Email: %user.email% Name: %user.name_f% %user.name_l% invoice_approval_wait_admin 2 en text %site_title%: Your approval required New signup completed and is awaiting your approval. Please log into aMember CP %root_url%/admin/ and then click the following link: %root_url%/admin-user-payments/index/user_id/%user.user_id% User details: Username: %user.login% Email: %user.email% Name: %user.name_f% %user.name_l% max_ip_actions_admin 2 en text %site_title%: Account Sharing Violation Detected There is an automated message from %site_title%. An account violation has been detected for the following customer: User details: Username: %user.login% Email: %user.email% Name: %user.name_f% %user.name_l% %userlocked% It has reached configured limit of %maxipcount% IP within %maxipperiod% minutes. Please login into aMember CP and review his access log. If it looks like a script mistake, you may disable sharing violation checking for this user in the "User Profile", or disable it globally at aMember CP -> Configuration -> Setup/Configuration -> Login Page by setting "if customer uses more than IP" to something like "99999". max_ip_actions_user 1 en text %site_title%: Account Sharing Violation Detected There is an automated message from %site_title%. An account violation has been detected. %userlocked% It has reached configured limit of %maxipcount% IP within %maxipperiod% minutes. mail_upgraded_cancel_member 1 en text %site_title%: Subscription cancelled due to Upgrade Your subscription to "%product.title%" cancelled due to Upgrade. %root_url%/member admin_cancel_upgraded_invoice 2 en text %site_title%: Cancel Upgraded Invoice Your customer %user.login% "%user.name_f% %user.name_l%" <%user.email%> recently changed his subscription to new payment plan. Unfortunately, the payment system does not allow to cancel previous subscription automatically. Please cancel previous user recurring subscription manually: Payment System: %invoice.paysys_id% aMember Invoice Id: %invoice.public_id% Subscription Reference: %subscr_id% admin_refund_upgraded_invoice 2 en text %site_title%: Refund Upgraded Invoice Your customer %user.login% "%user.name_f% %user.name_l%" <%user.email%> recently changed his subscription to new payment plan. aMember has done calculations and it is necessary to refund amount of money to the customer. Unfortunaetly, the payment system does not allow to process refunds automatically. Please process refund manually via payment system control panel: Payment System: %invoice.paysys_id% Last Payment Reference: %subscr_id% Amount to refund: %refund_amount% %invoice.currency% aMember Invoice Id: %invoice.public_id% PK\Ouidefault/themes-admin/readme.txtnu[folder for admin themesPK\fhh6default/themes-admin/sample/public/css/admin-theme.cssnu[/* This CSS is included after admin.css and you can override anything here */ body { color: purple; } PK\ĉ3S S (default/controllers/BackupController.phpnu[getDi()->modules->isEnabled('cc')) { $this->getDi()->errorLogTable->log(___('Online backup is disabled if you have CC payment plugins enabled. Use offline backup instead')); return; } if (!($f = $this->getDi()->config->get('email_backup_frequency'))) { throw new Am_Exception_InternalError('Email Backup feature is disabled at Setup/Configuration -> Advanced'); } $key = $this->getParam('k'); if ($key != $this->getDi()->security->siteHash('backup-cron', 10)) { throw new Am_Exception_AccessDenied('Incorrect Access Key'); } $last_runned = $this->getDi()->store->get('cron-backup-last-run'); if (!$last_runned) $last_runned = strtotime('-10 days'); $d_diff = date('d') - date('d', $last_runned); $w_diff = date('W') - date('W', $last_runned); if (($d_diff && $f == 'd') || ($w_diff && $f == 'w')) { $this->execute(); } } function execute() { $stream = fopen('php://temp', 'w+b'); if (!$stream) throw new Am_Exception_InternalError('Could not open php://temp stream'); $bp = $this->getDi()->backupProcessor; $bp->run($stream); rewind($stream); $dat = date('Y_m_d-Hi'); $host = strtolower(preg_replace('/[^a-zA-Z0-9\.]/', '', preg_replace('/^www\./', '', $_SERVER['HTTP_HOST']))); $fn = "am-$host-$dat.sql"; $filename = $bp->isGzip() ? "$fn.gz" : $fn; $mimeType = $bp->isGzip() ? 'application/x-gzip' : 'text/sql'; $m = $this->getDi()->mail; $m->addTo($this->getDi()->config->get('email_backup_address')) ->setSubject($this->getDi()->config->get('site_title') . ': Backup ' . amDatetime('now')) ->setFrom($this->getDi()->config->get('admin_email')) ->setBodyText(sprintf(<<getDi()->config->get('site_title'), $this->getDi()->config->get('root_url'), amDatetime('now'))); $m->createAttachment($stream, $mimeType, Zend_Mime::DISPOSITION_ATTACHMENT, Zend_Mime::ENCODING_BASE64, $filename); $m->setPeriodic(Am_Mail::ADMIN_REQUESTED); $m->send(); $this->getDi()->adminLogTable->log('Email backup to ' . $this->getDi()->config->get('email_backup_address')); $this->getDi()->store->set('cron-backup-last-run', $this->getDi()->time); } }PK\Q(default/controllers/ThanksController.phpnu[getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $id = filterId(urldecode($this->_request->get('id'))); if (empty($id)) $id = filterId(@urldecode(@$_GET['id'])); $this->invoice = null; if ($id) { $this->invoice = $this->getDi()->invoiceTable->findBySecureId($id, 'THANKS'); if (!$this->invoice) throw new Am_Exception_InputError(___("Invoice #%s not found", $id)); $tm = max($this->invoice->tm_started, $this->invoice->tm_added); if (($this->getDi()->time - strtotime($tm)) > 48*3600) throw new Am_Exception_InputError(___("Link expired")); // Clean signup_member_login and signup_member_id to avoid duplicate signups with the same email address. $this->getSession()->signup_member_id = null; $this->getSession()->signup_member_login = null; $this->view->invoice = $this->invoice; foreach ($this->invoice->getPaymentRecords() as $p) { $this->view->payment = $p; } if (!$this->invoice->tm_started) { $this->view->show_waiting = true; $this->view->refreshTime = "00:10 ".___("seconds"); } $this->view->script = $this->getJs(10); } $this->getDi()->hook->call(Am_Event::THANKS_PAGE, array( 'controller' => $this, 'invoice' => $this->invoice, )); $this->view->layoutNoMenu = true; $this->view->display('thanks.phtml'); } function getJs($seconds) { return <<remove = (bool)$removeGroup; parent::__construct( !$removeGroup ? "user-assign-group" : "user-remove-group", !$removeGroup ? ___("Assign Group") : ___("Remove Group") ); } public function renderConfirmationForm($btn = "Yes, assign", $addHtml = null) { $select = sprintf('

'.PHP_EOL, $this->grid->getId(), Am_Html::renderOptions(Am_Di::getInstance()->userGroupTable->getSelectOptions()) ); return parent::renderConfirmationForm($this->remove ? ___("Yes, remove group") : ___("Yes, assign group"), $select); } /** * @param int $id * @param User $record */ public function handleRecord($id, $record) { $group_id = $this->grid->getRequest()->getInt('_group_id'); if (!$group_id) throw new Am_Exception_InternalError("_group_id empty"); $groups = $record->getGroups(); if ($this->remove) { if (!in_array($group_id, $groups)) return; foreach ($groups as $k => $id) if ($id == $group_id) unset($groups[$k]); } else { if (in_array($group_id, $groups)) return; $groups[] = $group_id; } $record->setGroups($groups); } } class Am_Grid_Action_Group_PasswordConfirmedDelete extends Am_Grid_Action_Group_Delete { public function __construct($id = null, $title = null) { parent::__construct($id, $title); $this->setTarget('_top'); } public function renderConfirmationForm($btn = null, $addHtml = null) { if (!$this->getSession()->login_ok) $addHtml = ___('Enter admin password for confirmation') . ":


" . $addHtml; else $addHtml = null; return parent::renderConfirmationForm($btn, $addHtml); } public function run() { if (!$this->getSession()->login_ok) { $admin_pass = $this->grid->getCompleteRequest()->getPost('_admin_pass'); if (!$admin_pass) { echo $this->renderConfirmation(); return; } elseif (!$this->grid->getDi()->authAdmin->getUser()->checkPassword($admin_pass)) { echo "
".___('The password is entered incorrectly')."
"; echo $this->renderConfirmation(); return; } } $this->getSession()->login_ok = true; return parent::run(); } function getSession() { static $session; if ($session) return $session; $session = new Zend_Session_Namespace('am_admin_users_delete'); $session->setExpirationSeconds(3600); return $session; } } class Am_Form_Admin_User extends Am_Form_Admin { /** @var User */ protected $record; function __construct($record) { $this->record = $record; parent::__construct('user'); } function setDataSources(array $datasources) { if(!Am_Di::getInstance()->config->get('manually_approve')) array_unshift($datasources, new HTML_QuickForm2_DataSource_Array(array('is_approved' =>1))); parent::setDataSources($datasources); } function checkUniqLogin($login) { if (!preg_match(Am_Di::getInstance()->userTable->getLoginRegex(), $login)) return ___('Username contains invalid characters - please use digits, letters, dash and underscore'); // We need to check login only when user is not exists, or when he change his username. $user_id = $this->record ? $this->record->pk() : null; if(!$user_id || (strcasecmp($this->record->login, $login)!==0)) if (!$this->record->getTable()->checkUniqLogin($login, $user_id)) return ___('Username %s is already taken. Please choose another username', Am_Html::escape($login)); } function checkUniqEmail(array $group) { $email = $group['email']; if (!Am_Validate::email($email)) return ___('Please enter valid Email'); // Do the same for email if case there are plugins that use email as username. // We need to check email only when user is not exists, or when he change his email. $user_id = $this->record ? $this->record->pk() : null; if(!$user_id || (strcasecmp($this->record->email, $email)!==0)) if (!$this->record->getTable()->checkUniqEmail($email, $user_id)) return ___('An account with the same email already exists.'); } function init() { if ($this->record->isLoaded()) { $url = Am_Di::getInstance()->url('admin-users/data/user_id/'.$this->record->pk()); $label = Am_Html::escape(___('Attached User Data (XML)')); $this->addEpilog(<< $label CUT ); } if ($this->record->isLoaded() && $this->record->is_locked == 0 && $this->record->disable_lock_until && $this->record->disable_lock_until > Am_Di::getInstance()->sqlDateTime) { $this->addStatic(null, array('class' => 'row-wide')) ->setContent('
' . ___('Auto-locking for this customer is temporary disabled until %s', amDatetime($this->record->disable_lock_until)) . '
'); } elseif ($this->record->isLoaded() && $this->record->is_locked == 0) { $r = Am_Di::getInstance()->accessLogTable->findFirstByUserId($this->record->pk(), 'time DESC'); if ($r && Am_Di::getInstance()->accessLogTable->isIpCountExceeded($this->record->pk(), $r->remote_addr)) { $url = Am_Di::getInstance()->url('admin-setup/loginpage'); $url_disable = Am_Di::getInstance()->url('admin-users/disable-auto-lock', array( 'id' => $this->record->pk(), 'b' => $_SERVER['REQUEST_URI'] )); $this->addStatic(null, array('class' => 'row-wide')) ->setContent('
' . ___('This user exceeded %sAccount Sharing Prevention%s limits and temporarily locked.', "", '') . ' ' . ___('You can temporary %sdisable auto-locking for this customer for 1 day%s and allow access for his account.', "", '') . '
'); } } /* General Settings */ $fieldSet = $this->addFieldset('general', array('id'=>'general')) ->setLabel(___('General')); $login = $fieldSet->addText('login', array('class' => 'el-wide')) ->setLabel(___('Username')) ->setId('login'); $login->addRule('required'); $login->addRule('callback2', '-error-', array($this, 'checkUniqLogin')); if ($this->record->isLoaded()) { $countSameIp = Am_Di::getInstance()->userTable->countBy(array( 'remote_addr' => $this->record->remote_addr, 'user_id' => '<>'.$this->record->pk())); $ban = Am_Di::getInstance()->banTable->findBan(array( 'ip' => $this->record->remote_addr )); $banInfoHtml = $ban ? sprintf('%s', Am_Html::escape(___('This IP is Banned'))) : (Am_Di::getInstance()->authAdmin->getUser()->hasPermission(Am_Auth_Admin::PERM_BAN) ? sprintf('%s', Am_Di::getInstance()->url('admin-ban', array( '_ip_a' => 'insert', '_ip_b' => Am_Di::getInstance()->view->userUrl($this->record->pk()), 'value' => $this->record->remote_addr, 'comment' => sprintf('%s (%s %s)', $this->record->login, $this->record->name_f, $this->record->name_l))), Am_Html::escape(___('Block This IP Address'))) : ''); $fieldSet->addStatic('_signup_info', null, array('label' => ___('Signup Info')))->setContent( sprintf('
%s%s%s %s
%s', $this->record->remote_addr, ($this->record->user_agent ? sprintf(' (%s…)', Am_Html::escape($this->record->user_agent), Am_Html::escape(trim(substr($this->record->user_agent,0,12)))) : ''), ___(' at '), Am_Di::getInstance()->view->getElapsedTime($this->record->added), date('c', amstrtotime($this->record->added)), amDatetime($this->record->added), $banInfoHtml, $countSameIp ? '
' . ___('There is %s users with same registration IP Address', '' . $countSameIp . '') . '
' : '') ); $ban = Am_Di::getInstance()->banTable->findBan(array( 'ip' => $this->record->last_ip )); $banInfoHtml = $ban ? sprintf(' %s', Am_Html::escape(___('This IP is Banned'))) : (Am_Di::getInstance()->authAdmin->getUser()->hasPermission(Am_Auth_Admin::PERM_BAN) ? sprintf(' %s', Am_Di::getInstance()->url('admin-ban', array( '_ip_a' => 'insert', '_ip_b' => Am_Di::getInstance()->view->userUrl($this->record->pk()), 'value' => $this->record->last_ip, 'comment' => sprintf('%s (%s %s)', $this->record->login, $this->record->name_f, $this->record->name_l))), Am_Html::escape(___('Block This IP Address'))) : ''); $fieldSet->addStatic('_signin_info', null, array('label' => ___('Last Signin Info')))->setContent( sprintf("
%s
", $this->record->last_login ? sprintf('%s%s%s %s', $this->record->last_ip, ($this->record->last_user_agent ? sprintf(' (%s…)', Am_Html::escape($this->record->last_user_agent), Am_Html::escape(trim(substr($this->record->last_user_agent,0,12)))) : ''), ___(' at '), Am_Di::getInstance()->view->getElapsedTime($this->record->last_login), date('c', amstrtotime($this->record->last_login)), amDatetime($this->record->last_login), $banInfoHtml) : ___('Never')) ); } $fieldSet->addTextarea('comment', array('class' => 'el-wide', 'id' => 'comment')) ->setLabel(___('Comment')); //$pass0 = $gr->addElement('password', '_pass0', array('size' => 20)); //$pass0->addRule('eq', 'Password confirmation must be equal to Password', $pass); if (!$this->record->isLoaded()) { $pass = $fieldSet->addPassword('_pass', array('autocomplete'=>'off'))->setLabel(___('Password')); $pass->addRule('required'); } else { $g = $fieldSet->addGroup() ->setLabel(___('Password')); $g->addHtml()->setHtml('' . ___('change') . '
'); $g->addPassword('_pass', array('autocomplete'=>'off'))->setLabel(___('Password')); $g->addHtml()->setHtml('
'); } $nameField = $fieldSet->addGroup('', array('id' => 'name'), array('label' => ___("Name\n" . "First and Last name"))); $nameField->setSeparator(' '); $nameField->addText('name_f', array('size'=>15)); $nameField->addText('name_l', array('size'=>15)); $gr = $fieldSet->addGroup('', array('class' => 'row-required'))->setLabel(___('E-Mail Address')); $gr->setSeparator(' '); $gr->addText('email', array('size' => 30))->addRule('required'); $gr->addRule('callback2', '-error-', array($this, 'checkUniqEmail')); if ($this->record && $this->record->isLoaded()) { $resendText = Am_Html::escape(___('Resend Signup E-Mail')); $sending = Am_Html::escape(___('sending')); $sent = Am_Html::escape(___('sent successfully')); $id = $this->record->pk(); $gr->addStatic()->setContent(<< CUT ); } $fieldSet->addAdvRadio('is_locked', array('id' => 'is_locked', )) ->loadOptions(array( '' => 'No', '1' => ''.___('Yes, locked').'', '-1' => ''.___('Disable auto-locking for this customer').'', ))->setLabel(___('Permanently Locked')); $fieldSet->addAdvCheckbox('is_approved', array('id' => 'is_approved')) ->setLabel(___('Is Approved')); $fieldSet->addAdvRadio('unsubscribed', array('id' => 'unsubscribed')) ->setLabel(___("Is Unsubscribed? if enabled, this will unsubscribe the customer from: * messages that you send from aMember Cp, * autoresponder messages, * subscription expiration notices")) ->loadOptions(array( '' => ___('No'), '1' => ___('Yes, do not e-mail this customer for any reasons'), )); $fieldSet->addCategory('_groups', array('id' => 'usergroups'), array( 'base_url' => 'admin-user-groups', 'link_title' => ___('Edit Groups'), 'title' => ___('User Groups'), 'options' => Am_Di::getInstance()->userGroupTable->getOptions())) ->setLabel(___('User Groups')); $this->addText('phone')->setLabel(___('Phone Number')); $this->insertAdditionalFields(); $this->insertAddressFields(); } function addSaveButton($title = null) { if (!$this->record->isLoaded()) { $group = $this->addGroup(); $group->addStatic()->setContent('

', Am_Html::escape(___('Send Registration E-Mail to this user')))); $group->addElement(parent::addSaveButton($title)); } else { parent::addSaveButton($title); } } function insertAddressFields() { $fieldSet = $this->addAdvFieldset('address', array('id' => 'address_info')) ->setLabel(___('Address Info')); $fieldSet->addText('street', array('class' => 'el-wide'))->setLabel(___('Street Address')); $fieldSet->addText('street2', array('class' => 'el-wide'))->setLabel(___('Street Address (Second Line)')); $fieldSet->addText('city', array('class' => 'el-wide'))->setLabel(___('City')); $fieldSet->addText('zip')->setLabel(___('ZIP Code')); $fieldSet->addSelect('country')->setLabel(___('Country')) ->setId('f_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $group = $fieldSet->addGroup()->setLabel(___('State')); $state =$group->addSelect('state', '', array('intrinsic_validation'=>false)) ->setId('f_state'); /* @var $state HTML_QuickForm2_Select */ $state->addFilter(array($this, '_filterState')); if (!empty($this->record->country)) $state->loadOptions(Am_Di::getInstance()->stateTable->getOptions($this->record->country, true)); $group->addText('state')->setId('t_state')->setAttribute('disabled', 'disabled'); } public function _filterState($state) { return preg_replace('#[^A-Za-z0-9-]#', '', $state); } function insertAdditionalFields() { $fields = Am_Di::getInstance()->userTable->customFields()->getAll(); $c = $this; if (count($fields)>5) { $c = $this->addAdvFieldset('additional') ->setLabel(___('Additional Fields')); } uksort($fields, array(Am_Di::getInstance()->userTable, 'sortCustomFields')); $exclude = array(); foreach ($fields as $k => $f) if (!in_array($f->name, $exclude) && strpos($f->name, 'aff_')!==0) $el = $f->addToQf2($c); } protected function renderClientRules(HTML_QuickForm2_JavascriptBuilder $builder) { $generate = ___("generate"); $builder->addElementJavascript(<<$generate"); jQuery("a#generate-pass").click(function(){ if (pass0.attr("type")!="text") { pass0.replaceWith(""); pass0 = jQuery("input#_pass-0"); } var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz"; var pass = ""; var len = 9; for(i=0;isetTarget('_top'); } public function handleRecord($id, $record) { //nop } public function doRun(array $ids) { if ($ids[0] == self::ALL) { $search = $this->grid->getDataSource()->serialize(); } else { $q = new Am_Query_User; $q->setPrefix('search'); $vars = array(); $vars['search']['member_id_filter']['val'] = implode(',', $ids); $q->setFromRequest($vars); $search = $q->serialize(); } $this->grid->redirect($this->grid->getDi()->url('admin-email', array('search-type'=>'advanced','search'=>$search),false)); } } class Am_Grid_Action_Group_MassSubscribe extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; protected $form; protected $_vars, $_products; public function __construct() { parent::__construct('mass_subscribe', ___('Mass Subscribe')); $this->setTarget('_top'); } public function handleRecord($id, $record) { switch ($this->_vars['action']) { case 'access' : switch($this->_vars['access_type']) { case 'exact' : $begin_date = $this->_vars['begine_date']; $expire_date = $this->_vars['expire_date']; break; case 'period' : $invoice = $this->grid->getDi()->invoiceRecord; $invoice->setUser($this->grid->getDi()->userTable->load($id)); $product = $this->grid->getDi()->productTable->load($this->_vars['product_id']); $begin_date = $product->calculateStartDate($this->grid->getDi()->sqlDate, $invoice); $p = new Am_Period($this->_vars['period']); $expire_date = $p->addTo($begin_date); break; } $a = $this->grid->getDi()->accessRecord; $a->begin_date = $begin_date; $a->expire_date = $expire_date; $a->product_id = $this->_vars['product_id']; $a->user_id = $id; $a->comment = $this->_vars['comment']; $a->insert(); break; case 'payment' : $invoice = $this->grid->getDi()->invoiceRecord; $invoice->user_id = $id; $invoice->add($this->grid->getDi()->productTable->load($this->_vars['product_id'])); $items = $invoice->getItems(); $item = $items[0]; $item->first_price = $item->first_total = $this->_vars['amount']; $item->second_price = $item->second_total = 0; $item->rebill_times = 0; $item->second_period = null; $invoice->first_subtotal = $invoice->first_total = $this->_vars['amount']; $invoice->second_subtotal = $invoice->second_total = 0; $invoice->rebill_times = 0; $invoice->second_period = null; $invoice->first_period = $item->first_period; $invoice->paysys_id = $this->_vars['paysys_id']; $invoice->comment = $this->_vars['comment'] ? $this->_vars['comment'] : 'mass-subscribe'; $invoice->save(); $tr = new Am_Paysystem_Transaction_Manual($this->grid->getDi()->plugins_payment->loadGet($invoice->paysys_id)); $tr->setAmount($this->_vars['amount']); $tr->setTime(new DateTime($this->_vars['dattm'])); $tr->setReceiptId('ms-'. uniqid() . '-' . $invoice->pk()); if ($this->_vars['amount']) { $invoice->addPayment($tr); } else { $invoice->addAccessPeriod($tr); } break; } } public function getForm() { if (!$this->form) { $id = $this->grid->getId(); $this->form = new Am_Form_Admin; $sel = $this->form->addSelect($id . '_product_id')->setLabel(___('Product')); $sel->loadOptions(Am_Di::getInstance()->productTable->getOptions(false)); $sel->addRule('required'); $actionElName = $id.'_action'; $this->form->addAdvRadio($actionElName) ->setLabel('Action') ->loadOptions(array( 'access' => ___('Add only Access Records'), 'payment' => ___('Add Invoice and Payment/Access Manually') )); $fs = $this->form->addFieldset(null, array('id' => 'action-access')); $accessTypeElName = $id.'_access_type'; $fs->addAdvRadio($accessTypeElName) ->setLabel(___('Access Period')) ->loadOptions(array( 'exact' => ___('Specify Exact Dates'), 'period' => ___('Extend Existing Subscription Period') )); $dates = $fs->addGroup() ->setLabel(___('Start and Expiration Dates')) ->setId('period-exact'); $dates->setSeparator(' '); $dates->addDate($id.'_begine_date'); $dates->addDate($id.'_expire_date'); $fs->addPeriod($id.'_period') ->setLabel(___('Period')) ->setId('period-rules'); $this->form->addScript() ->setScript(<<form->addFieldset(null, array('id' => 'action-payment')); $fs->addSelect($id.'_paysys_id') ->setLabel(___("Payment System")) ->loadOptions($this->grid->getDi()->paysystemList->getOptions()); $fs->addText($id.'_amount') ->setlabel(___('Amount')); $fs->addDate($id.'_dattm') ->setLabel(___("Date Of Transaction")); $this->form->addText($id.'_comment', array('class'=>'el-wide')) ->setLabel(___("Comment\nfor admin reference")); $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( $accessTypeElName => 'exact', $id.'_dattm' => $this->grid->getDi()->sqlDate, $actionElName => 'access'))); $this->form->addSaveButton(___('Mass Subscribe')); } return $this->form; } public function renderConfirmationForm($btn = null, $addHtml = null) { $this->getForm(); $vars = $this->grid->getCompleteRequest()->toArray(); $vars[$this->grid->getId() . '_confirm'] = 'yes'; foreach ($vars as $k => $v) if ($this->form->getElementsByName($k)) unset($vars[$k]); foreach(Am_Html::getArrayOfInputHiddens($vars) as $k => $v) $this->form->addHidden($k)->setvalue($v); $url_yes = $this->grid->makeUrl(null); $this->form->setAction($url_yes); echo $this->renderTitle(); echo (string)$this->form; } public function run() { if (!$this->getForm()->validate()) { echo $this->renderConfirmationForm(); } else { $prefix = $this->grid->getId().'_'; foreach ($this->getForm()->getValue() as $k => $v) { if (strpos($k, $prefix)===0) $this->_vars[substr($k, strlen($prefix))] = $v; } // disable emailing Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null); return parent::run(); } } } class Am_Grid_Action_Merge extends Am_Grid_Action_Abstract { protected $title = "Merge %s"; protected $privilege = 'merge'; function run() { $form = new Am_Form_Admin('form-grid-merge'); $form->setAttribute('name', 'merge'); $user = $this->grid->getRecord(); $login = $form->addText('login'); $login->setId('login') ->setLabel(___("Username of Source User\nmove information from this user to target user, this user will be deleted")); $login->addRule('callback', ___('Can not find user with such username'), array($this, 'checkUser')); $login->addRule('callback', ___('You can not merge user with itself'), array($this, 'checkIdenticalUser')); $target = $form->addStatic() ->setContent(sprintf('
%s
', Am_Html::escape($user->login))); $target->setLabel(___("Target User\nmove information to")); $script = <<addStatic('', array('class' => 'no-label'))->setContent( '
' . ___("WARNING! Once [Merge] button clicked, all invoices, payments, logs\n". "and other information regarding 'Source User' will be moved\n". "to the 'Target User' account. 'Source User' account will be deleted.\n". "There is no way to undo this operation!") . '
' ); $form->addScript('script')->setScript($script); foreach ($this->grid->getVariablesList() as $k) { $form->addHidden($this->grid->getId() . '_' . $k)->setValue($this->grid->getRequest()->get($k, "")); } $form->addSaveButton(___("Merge")); $form->setDataSources(array($this->grid->getCompleteRequest())); if ($form->isSubmitted() && $form->validate()) { $values = $form->getValue(); $this->merge($this->grid->getRecord(), Am_Di::getInstance()->userTable->findFirstByLogin($values['login'])); $this->grid->redirectBack(); } else { echo $this->renderTitle(); echo $form; } } public function checkUser($login) { $user = Am_Di::getInstance()->userTable->findFirstByLogin($login); return (boolean)$user; } public function checkIdenticalUser($login) { $user = Am_Di::getInstance()->userTable->findFirstByLogin($login); return $user->pk() != $this->grid->getRecord()->pk(); } protected function merge(User $target, User $source) { //module should throw Exception in case of merge is not possible $event = new Am_Event(Am_Event::USER_BEFORE_MERGE, array( 'target' => $target, 'source' => $source )); $this->getDi()->hook->call(Am_Event::USER_BEFORE_MERGE, $event); $this->getDi()->db->query('UPDATE ?_access SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_access_log SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_invoice SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_invoice_log SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_invoice_payment SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_invoice_refund SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); // $this->getDi()->db->query('UPDATE ?_admin_log SET record_id=? WHERE record_id=? // AND tablename=?', // $target->pk(), $source->pk(), 'user'); $this->getDi()->db->query('UPDATE ?_coupon_batch SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_file_download SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $this->getDi()->db->query('UPDATE ?_upload SET user_id=? WHERE user_id=?', $target->pk(), $source->pk()); $event = new Am_Event(Am_Event::USER_MERGE, array( 'target' => $target, 'source' => $source )); $this->getDi()->hook->call(Am_Event::USER_MERGE, $event); $source->delete(); $target->save(); $target->checkSubscriptions(true); $this->log(___('Merge with user %s <%s> (%s) [#%d]', $source->getName(), $source->email, $source->login, $source->pk())); } /** * @return Am_Di */ protected function getDi() { return Am_Di::getInstance(); } } class Am_Grid_Action_LoginAs extends Am_Grid_Action_Url { protected $privilege = 'login-as'; } class Am_Grid_Filter_User extends Am_Grid_Filter_Abstract { protected $title; public function __construct() { $this->title = ''; parent::__construct(); } public function getVariablesList() { $ret = parent::getVariablesList(); $ret[] = 'search'; $ret[] = 'search_load'; return $ret; } protected function applyFilter() { // done in initFilter } protected function renderButton() { $title = Am_Html::escape(___('Advanced Search')); return parent::renderButton(). "$title"; } public function renderFilter() { $query = $this->grid->getDataSource(); $conditions = $query->getConditions(); $title = ""; if (count($conditions)>1 || (count($conditions)==1 && !$conditions[0] instanceof Am_Query_User_Condition_Filter)) { $selfUrl = $this->grid->escape($this->grid->makeUrl(null)); if ($name = Am_Html::escape($query->getName())) { $deleteConfirm = json_encode(___("Delete Saved Search?")); $desc = "".___("Saved Search") . ": $name"; $root = Am_Di::getInstance()->url(''); $id = $this->grid->getRequest()->getInt('search_load'); $desc .= " ".___("Delete").""; } else { $desc = "".___("Filter").": "; $desc .= $query->getDescription(); $desc .= " ".___("Save This Search").""; } $title = "
" . $desc . '
'; } $filter = parent::renderFilter(); $filter = preg_match('#(
)(.*)$#is', $filter, $matches); return $matches[1] . $title . $matches[2]; } public function renderInputs() { return $this->renderInputText(array( 'name' => 'filter', 'size' => 40, 'placeholder' => ___("Login/Name/Email/Invoice/Receipt/IP"))); } public function initFilter(Am_Grid_ReadOnly $grid) { parent::initFilter($grid); $query = $grid->getDataSource(); $query->setPrefix('_u_search'); /* @var $query Am_Query_User */ if ($id = $grid->getCompleteRequest()->getInt('_search_del')){ $query->deleteSaved($id); Am_Mvc_Response::redirectLocation($this->getDi()->url('admin-users',null,false)); exit(); } elseif ($id = $grid->getRequest()->getInt('search_load')){ $query->load($id); } elseif (is_string($this->vars['filter']) && $this->vars['filter']){ $cond = new Am_Query_User_Condition_Filter(); $cond->setFromRequest(array('filter' => array('val' => $this->vars['filter']))); $event = new Am_Event(Am_Event::ADMIN_USERS_FILTER_INIT, array( 'query' => $query, 'filter' => $this->vars['filter'] )); $event->setReturn($cond); Am_Di::getInstance()->hook->call($event); $query->add($event->getReturn()); } else { $query->setFromRequest($grid->getCompleteRequest()); } } public function isFiltered() { return (bool)$this->grid->getDataSource()->getConditions(); } } class Am_Grid_Field_Decorator_Additional extends Am_Grid_Field_Decorator_Abstract { /** @var Am_CustomField */ protected $f; function __construct(Am_CustomField $f) { $this->f = $f; } function render(& $out, $obj, $controller) { $field = $this->f; $val = $field->valueFromTable($out); switch($field->getType()) { case 'date': $res = amDate($val); break; case 'select': case 'radio': case 'checkbox': case 'multi_select': $val = (array)$val; foreach ($val as $k=>$v) $val[$k] = @$field->options[$v]; $res = implode(", ", $val); break; default: $res = $val; } $out = $controller->renderTd($res); } } class AdminUsersController extends Am_Mvc_Controller_Grid { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission('grid_u'); } public function preDispatch() { parent::preDispatch(); $this->setActiveMenu($this->getParam('_u_a')=='insert' ? 'users-insert' : 'users-browse'); } function dataAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_u', 'browse'); $user = $this->getDi()->userTable->load($this->_request->getInt('user_id')); $this->getResponse()->setHeader('Content-type', 'text/xml'); $x = new XMLWriter(); $x->openMemory(); $x->setIndent(true); $x->startElement('user-data-items'); $this->writeEl($x, $user->data()->getAll()); $x->endElement(); echo $x->flush(); } function writeEl(XMLWriter $x, $val) { if (is_scalar($val)) { $x->text($val); } elseif(is_array($val)) { foreach ($val as $k => $v) { $x->startElement('item'); $x->writeAttribute('name', $k); $this->writeEl($x, $v); $x->endElement(); } } } public function disableAutoLockAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_u', 'edit'); $id = $this->getParam('id'); $user = $this->getDi()->userTable->load($id); if (!$user) throw new Am_Exception_InputError; $user->updateQuick('disable_lock_until', sqlTime('+1 day')); $b = $this->getParam('b', $this->view->userUrl($user->pk())); $this->_response->redirectLocation($b); } public function deleteAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_u', 'delete'); if ($this->getRequest()->isPost()) { $user = $this->getDi()->userTable->load($this->getParam('id')); $user->delete(); $this->getDi()->adminLogTable->log( sprintf('%s (%s, %s, %s)', ___('Delete User'), $user->getName(), $user->login, $user->email), 'grid_u', $user->pk()); $this->_response->redirectLocation($this->getDi()->url('admin-users',null,false)); } else { $this->view->user = $this->getDi()->userTable->load($this->getParam('id')); $this->view->display('admin/user-delete.phtml'); } } public function getNotConfirmedCount() { return $this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_store WHERE name LIKE 'signup_record-%' AND CHAR_LENGTH(blob_value)>10 AND expires>?", $this->getDi()->sqlDateTime); } public function notConfirmedAction() { $arr = array(); foreach ($this->getDi()->db->select("SELECT `blob_value`, expires FROM ?_store WHERE name LIKE 'signup_record-%' AND CHAR_LENGTH(blob_value)>10 AND expires>?", $this->getDi()->sqlDateTime) as $row) { $v = unserialize($row['blob_value']); $rec = array(); foreach ($v['values'] as $page) { $rec = array_merge($rec, $page); } $rec['expires'] = $row['expires']; $link = Am_Html::escape($v['opaque']['ConfirmUrl']); $rec['link'] = 'Give this link to customer if e-mail confirmation has not been received:'. '

' . $link . '

'; if (empty($rec['login'])) $rec['login'] = null; if (empty($rec['name_f'])) $rec['name_f'] = null; if (empty($rec['name_l'])) $rec['name_l'] = null; $arr[] = (object)$rec; } $ds = new Am_Grid_DataSource_Array($arr); $grid = new Am_Grid_Editable('_usernc', ___("Not Confirmed Users"), $ds, $this->_request, $this->view, $this->getDi()); $grid->setPermissionId('grid_u'); $grid->addField('login', ___('Username')); $grid->addField('email', ___('E-Mail')); $grid->addField('name_f', ___('First Name')); $grid->addField('name_l', ___('Last Name')); $grid->addField(new Am_Grid_Field_Date('expires', ___('Expires')))->setFormatDate(); $grid->addField(new Am_Grid_Field_Expandable('link', ___('Link')))->setEscape(false); $grid->actionsClear(); $this->view->content = $grid->runWithLayout('admin/layout.phtml'); } public function autocompleteAction() { $term = '%' . $this->getParam('term') . '%'; if (!$term) return null; $q = new Am_Query($this->getDi()->userTable); $q->addWhere('(t.login LIKE ?) OR (t.email LIKE ?) OR (t.name_f LIKE ?) OR (t.name_l LIKE ?)', $term, $term, $term, $term); $this->getDi()->hook->call(Am_Event::ADMIN_USERS_AUTOCOMPLETE, array( 'query' => $q, 'term' => $term )); $qq = $q->query(0, 10); $ret = array(); while ($r = $this->getDi()->db->fetchRow($qq)) { $ret[] = array ( 'label' => sprintf('%s / "%s" <%s>', $r['login'], $r['name_f'] . ' ' . $r['name_l'], $r['email']), 'value' => $r['login'], 'url' => $this->view->userUrl($r['user_id']) ); } if ($q->getFoundRows() > 10) $ret[] = array( 'label' => sprintf("... %d more rows found ...", $q->getFoundRows() - 10), 'value' => null, 'url' => $this->url('admin-users', array('_u_filter' => $this->getParam('term')), false) ); $this->_response->ajaxResponse($ret); } public function indexAction() { if (in_array($this->grid->getCurrentAction(), array('edit','insert'))) $this->layout = 'admin/user-layout.phtml'; parent::indexAction(); } public function createGrid() { $ds = new Am_Query_User; $datetime = $this->getDi()->sqlDate; $ds->addField("concat(u.name_f, ' ', u.name_l)", '_name') ->addField('(SELECT COUNT(p.invoice_payment_id) FROM ?_invoice_payment p WHERE p.user_id = u.user_id)', '_payments_count') ->addField('(SELECT ROUND(SUM((p.amount - IFNULL(p.refund_amount, 0))/p.base_currency_multi), 2) FROM ?_invoice_payment p WHERE p.user_id = u.user_id)', '_payments_sum') ->addField("(SELECT MAX(expire_date) FROM ?_access ac WHERE ac.user_id = u.user_id)", '_expire') ->addField("(SELECT GROUP_CONCAT(title SEPARATOR ', ') FROM ?_access ac LEFT JOIN ?_product p USING (product_id) WHERE ac.user_id = u.user_id AND ac.begin_date<='$datetime' AND ac.expire_date>='$datetime')", '_products') ->addField("(SELECT GROUP_CONCAT(title SEPARATOR ', ') FROM ?_user_user_group uug LEFT JOIN ?_user_group ug USING (user_group_id) WHERE uug.user_id = u.user_id)", '_ugroup'); $ds->setOrder("login"); $grid = new Am_Grid_Editable('_u', ___("Browse Users"), $ds, $this->_request, $this->view); $grid->setRecordTitle(array($this, 'getRecordTitle')); $_ = $grid->addField(new Am_Grid_Field('login', ___('Username'), true)); if ($this->getDi()->authAdmin->getUser()->hasPermission('grid_u', 'edit')) { $_->setRenderFunction(array($this, 'renderLogin')); } $grid->addField(new Am_Grid_Field('_name', ___('Name'), true)); $grid->addField(new Am_Grid_Field('email', ___('E-Mail Address'), true)) ->setRenderFunction(array($this, 'renderEmail')); $grid->addField(new Am_Grid_Field('_payments_sum', ___('Payments'), true, null, array($this, 'renderPayments'))); $grid->addField('status', ___('Status'), true)->setRenderFunction(array($this, 'renderStatus')); $grid->actionAdd($this->createActionExport()); $grid->actionGet('edit')->setTarget('_top')->showFormAfterSave(true); $grid->actionGet('insert')->setTarget('_top')->showFormAfterSave(true); $grid->setForm(array($this, 'createForm')); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_SAVE, array($this, 'beforeSave')); $grid->addCallback(Am_Grid_Editable::CB_AFTER_SAVE, array($this, 'afterSave')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_Editable::CB_RENDER_STATIC, array($this, 'renderStatic')); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'getTrAttribs')); $grid->actionAdd($this->createActionCustomize()); $grid->actionAdd(new Am_Grid_Action_Group_Callback('lock', ___("Lock"), array($this, 'lockUser'))); $grid->actionAdd(new Am_Grid_Action_Group_Callback('unlock', ___("Unlock"), array($this, 'unlockUser'))); $grid->actionAdd(new Am_Grid_Action_Group_Callback('approve', ___("Approve"), array($this, 'approveUser'))); $grid->actionAdd(new Am_Grid_Action_Group_Callback('unsubscribe', ___("Unsubscribe from All Emails"), array($this, 'unsubscribeUser'))); $grid->actionAdd(new Am_Grid_Action_Group_EmailUsers()); $grid->actionAdd(new Am_Grid_Action_Group_MassSubscribe()); $grid->actionAdd(new Am_Grid_Action_Group_PasswordConfirmedDelete()); $grid->actionDelete('delete'); $grid->actionAdd(new Am_Grid_Action_LoginAs('login', ___('Login as User'), '__ROOT__/admin-users/login-as?id=__ID__'))->setTarget('_blank'); $grid->actionAdd(new Am_Grid_Action_Delete()); $grid->actionAdd(new Am_Grid_Action_Merge()); $grid->actionAdd(new Am_Grid_Action_Group_UserAssignGroup(false)); $grid->actionAdd(new Am_Grid_Action_Group_UserAssignGroup(true)); $nc_count = $this->getDi()->cache->load('getNotConfirmedCount'); if ($nc_count === false) { $nc_count = $this->getNotConfirmedCount(); $this->getDi()->cache->save($nc_count, 'getNotConfirmedCount', array(), 60); } if ($nc_count) { $grid->actionAdd(new Am_Grid_Action_Url('not-confirmed', ___("Not Confirmed Users") . " ($nc_count)", $this->getDi()->url('admin-users/not-confirmed',null,false))) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setCssClass('link') ->setTarget('_top'); } $grid->actionAdd(new Am_Grid_Action_Url('import', ___('Import Users'), 'admin-import')) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setTarget('_top') ->setCssClass('link') ->setPrivilegeId('insert'); $grid->setFilter(new Am_Grid_Filter_User()); $grid->setEventId('gridUser'); return $grid; } public function getRecordTitle(User $user = null) { return $user ? sprintf('%s - %s', ___('User'), implode(", ", array_filter(array($user->getName(), $user->login, $user->email)))) : ___('User'); } public function getTrAttribs(& $ret, $record) { if ($record->isLocked() || (!$record->isApproved())) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } protected function createActionCustomize() { $stateTitleField = new Am_Grid_Field('state_title', ___('State Title'), false); $stateTitleField->setGetFunction(array($this, 'getStateTitle')); $countryTitleField = new Am_Grid_Field('country_title', ___('Country Title'), false); $countryTitleField->setGetFunction(array($this, 'getCountryTitle')); $lastSigninInfoField = new Am_Grid_Field('last_signin', ___('Last Signin Info'), false); $lastSigninInfoField->setGetFunction(array($this, 'getLastSigninInfo')); $gravatarField = new Am_Grid_Field('gravatar', ___('Gravatar'), false, null, array($this, 'renderGravatar'), '1%'); $expireField = new Am_Grid_Field_Date('_expire', ___('Expire')); $expireField->setFormatDate(); $productsField = new Am_Grid_Field_Expandable('_products', ___('Active Subscriptions')); $productsField->setPlaceholder(Am_Grid_Field_Expandable::PLACEHOLDER_SELF_TRUNCATE_END) ->setMaxLength(50) ->setGetFunction(function($r, $g, $f) { return strip_tags($r->$f); }); $userGroupField = new Am_Grid_Field('_ugroup', ___('User Groups'), false); $isAffField = new Am_Grid_Field_Enum('is_affiliate', ___('Is Affiliate?')); $isAffField->setTranslations(array(0 => ___('No'), 1 => ___('Yes'), 2 => ___('Yes'))); $action = new Am_Grid_Action_Customize(); $action->addField(new Am_Grid_Field('user_id', '#', true, '', null, '1%')) ->addField(new Am_Grid_Field('name_f', ___('First Name'))) ->addField(new Am_Grid_Field('name_l', ___('Last Name'))) ->addField(new Am_Grid_Field('street', ___('Street'))) ->addField(new Am_Grid_Field('street2', ___('Street (Second Line)'))) ->addField(new Am_Grid_Field('city', ___('City'))) ->addField(new Am_Grid_Field('state', ___('State'))) ->addField($stateTitleField) ->addField(new Am_Grid_Field('zip', ___('ZIP Code'))) ->addField(new Am_Grid_Field('country', ___('Country'))) ->addField($countryTitleField) ->addField(new Am_Grid_Field('phone', ___('Phone'))) ->addField(new Am_Grid_Field_Date('added', ___('Added'))) ->addField($productsField) ->addField($userGroupField) ->addField(new Am_Grid_Field('status', ___('Status'))) ->addField(new Am_Grid_Field('unsubscribed', ___('Unsubscribed'))) ->addField(new Am_Grid_Field('lang', ___('Language'))) ->addField(new Am_Grid_Field('is_locked', ___('Is Locked'))) ->addField(new Am_Grid_Field('comment', ___('Comment'))) ->addField(new Am_Grid_Field('aff_id', ___('Affiliate Id#'))) ->addField($isAffField) ->addField($expireField) ->addField($lastSigninInfoField) ->addField($gravatarField); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { $f = $field->sql ? new Am_Grid_Field($field->name, $field->title) : new Am_Grid_Field_Data($field->name, $field->title, false); $f->addDecorator(new Am_Grid_Field_Decorator_Additional($field)); $f->setRenderFunction(array($this, 'renderAdditional')); $action->addField($f); } } return $action; } function renderAdditional($record, $fieldName, $controller, $field) { //@see Am_Grid_Field_Decorator_Additional return $field->get($record, $controller, $fieldName); } function renderGravatar($record, $fieldName, $controller, $field) { return sprintf('
', '//www.gravatar.com/avatar/' . md5(strtolower(trim($record->email))) . '?s=40&d=mm'); } function renderEmail($record, $fieldName, $controller, $field) { return $controller->renderTd(sprintf('%s', $this->getDi()->url("admin-email", array( 'search-type'=>'advanced', 'search'=>json_encode(array('member_id_filter'=>array('val'=>$record->pk()))) ) ), $this->escape($record->email)), false); } protected function createActionExport() { $stateTitleField = new Am_Grid_Field('state_title', ___('State Title')); $stateTitleField->setGetFunction(array($this, 'getStateTitle')); $countryTitleField = new Am_Grid_Field('country_title', ___('Country Title')); $countryTitleField->setGetFunction(array($this, 'getCountryTitle')); $lastSigninInfoField = new Am_Grid_Field('last_signin', ___('Last Signin Info')); $lastSigninInfoField->setGetFunction(array($this, 'getLastSigninInfo')); $action = new Am_Grid_Action_Export(); $action->addField(new Am_Grid_Field('user_id', ___('User Id'))) ->addField(new Am_Grid_Field('login', ___('Username'))) ->addField(new Am_Grid_Field('email', ___('Email'))) ->addField(new Am_Grid_Field('pass', ___('Password Hash'))) ->addField(new Am_Grid_Field('name_f', ___('First Name'))) ->addField(new Am_Grid_Field('name_l', ___('Last Name'))) ->addField(new Am_Grid_Field('street', ___('Street'))) ->addField(new Am_Grid_Field('street2', ___('Street (Second Line)'))) ->addField(new Am_Grid_Field('city', ___('City'))) ->addField(new Am_Grid_Field('state', ___('State'))) ->addField($stateTitleField) ->addField(new Am_Grid_Field('zip', ___('ZIP Code'))) ->addField(new Am_Grid_Field('country', ___('Country'))) ->addField($countryTitleField) ->addField(new Am_Grid_Field('phone', ___('Phone'))) ->addField(new Am_Grid_Field('added', ___('Added'))) ->addField(new Am_Grid_Field('status', ___('Status'))) ->addField(new Am_Grid_Field('_ugroup', ___('User Groups'))) ->addField(new Am_Grid_Field('_products', ___('Active Subscriptions'))) ->addField(new Am_Grid_Field('unsubscribed', ___('Unsubscribed'))) ->addField(new Am_Grid_Field('lang', ___('Language'))) ->addField(new Am_Grid_Field('is_locked', ___('Is Locked'))) ->addField(new Am_Grid_Field('comment', ___('Comment'))) ->addField(new Am_Grid_Field('aff_id', ___('Affiliate Id#'))) ->addField(new Am_Grid_Field('_payments_sum', ___('Payments (amount of all payments made by user minus refunds)'))) ->addField(new Am_Grid_Field('_expire', ___('Expire (maximum expiration date)'))) ->addField($lastSigninInfoField); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { if ($field->sql) { if(in_array($field->type, array('multi_select','checkbox'))){ $f = new Am_Grid_Field($field->name, $field->title . ' (Value)'); $f->setGetFunction(array($this,'getMultiSelect')); $action->addField($f); $op = $field->options; $fn = $field->name; $f = new Am_Grid_Field($field->name . '_label', $field->title . ' (Label)'); $f->setGetFunction(function($obj, $controller, $field=null) use ($op, $fn){ return implode(',', array_map(function($el) use ($op) { return isset($op[$el]) ? $op[$el] : $el; }, (array)$obj->{$fn})); }); $action->addField($f); } else { $action->addField(new Am_Grid_Field($field->name, $field->title)); } } else { if(in_array($field->type, array('multi_select','checkbox'))){ //we use trailing __blob to distinguish multi select fields from data table $mfield = new Am_Grid_Field($field->name . '__blob', $field->title . ' (Value)'); $mfield->setGetFunction(array($this,'getMultiSelect')); $action->addField($mfield); $op = $field->options; $fn = $field->name . '__blob'; $f = new Am_Grid_Field($field->name . '_label__blob', $field->title . ' (Label)'); $f->setGetFunction(function($obj, $controller, $field=null) use ($op, $fn){ return implode(',', array_map(function($el) use ($op) { return isset($op[$el]) ? $op[$el] : $el; }, (array)@unserialize($obj->{$fn}))); }); $action->addField($f); } else //we use trailing __ to distinguish fields from data table $action->addField(new Am_Grid_Field($field->name . '__', $field->title)); } } } $action->setGetDataSourceFunc(array($this, 'getDS')); return $action; } function getStateTitle($obj, $controller, $field=null) { return $this->getDi()->stateTable->getTitleByCode($obj->country, $obj->state); } function getCountryTitle($obj, $controller, $field=null) { return $this->getDi()->countryTable->getTitleByCode($obj->country); } function getLastSigninInfo($obj, $controller, $field=null) { return $obj->last_login ? $obj->last_ip . ___(' at ') . amDatetime($obj->last_login) : ___('Never'); } function getMultiSelect($obj, $controller, $field=null) { return implode(',', is_array($obj->{$field}) ? $obj->{$field} : (array)@unserialize($obj->{$field})); } public function getDS(Am_Query $ds, $fields) { $i = 0; //join only selected fields foreach ($fields as $field) { $fn = $field->getFieldName(); if (substr($fn, -6) == '__blob') { //multi select field from data table $i++; $field_name = substr($fn, 0, strlen($fn)-6); $ds = $ds->leftJoin("?_data", "d$i", "u.user_id = d$i.id AND d$i.table='user' AND d$i.key='$field_name'") ->addField("d$i.blob", $fn); } if (substr($fn, -2) == '__') { //field from data table $i++; $field_name = substr($fn, 0, strlen($fn)-2); $ds = $ds->leftJoin("?_data", "d$i", "u.user_id = d$i.id AND d$i.table='user' AND d$i.key='$field_name'") ->addField("d$i.value", $fn); } } return $ds; } public function renderStatic(& $out, Am_Grid_Editable $grid) { $hidden = Am_Html::renderArrayAsInputHiddens($grid->getFilter()->getAllButFilterVars()); $out .= "\n" . $grid->getDataSource()->renderForm($hidden) . "\n"; "\n"; } public function lockUser($id, User $user) { $user->lock(true); } public function unlockUser($id, User $user) { $user->lock(false); } public function subscribeUser($id, User $user) { $user->unsubscribed = 0; $user->save(); } public function unsubscribeUser($id, User $user) { $user->unsubscribed = 1; $user->save(); } public function approveUser($id, User $user) { $user->approve(); } function renderLogin($record) { $icons = ""; if ($record->isLocked()) $icons .= $this->view->icon('user-locked', ___('User is locked')); if (!$record->isApproved()) $icons .= $this->view->icon('user-not-approved', ___('User is not approved')); if ($icons) $icons = '
' . $icons . '
'; return $this->renderTd(sprintf('%s%s', $icons, $this->escape($this->grid->getActionUrl('edit', $record->user_id)), $this->escape($record->login)), false); } function renderStatus(User $record) { $text = ""; switch ($record->status) { case User::STATUS_PENDING: if ($record->_payments_count) { if ((float)$record->_payments_sum > 0) { $text = '' . ___('Future') . ''; } else { $text = '' . ___('Refunded') . ''; } } else { $text = '' . ___('Pending') . ''; } break; case User::STATUS_ACTIVE: $text = '' . ___('Active') . ''; break; case User::STATUS_EXPIRED: $text = '' . ___('Expired') . ''; break; } return $this->renderTd($text, false); } function renderPayments(User $record) { if ($record->_payments_count) { $curr = new Am_Currency(); $curr->setValue($record->_payments_sum); $text = $record->_payments_count . ' - ' . $curr->toString(); $link = $this->getDi()->url("admin-user-payments/index/user_id/{$record->user_id}"); $text = sprintf('%s', $link, $text); } else { $text = ___('Never'); } return sprintf('%s', $text); } function createForm() { return new Am_Form_Admin_User($this->grid->getRecord()); } function saveSearchAction() { $q = new Am_Query_User(); $search = $this->_request->get('search'); $q->unserialize($search['serialized']); if (!$q->getConditions()) throw new Am_Exception_InputError("Wrong parameters passed: no conditions : " . htmlentities($this->_request->search['serialized'])); if (!strlen($this->getParam('name'))) throw new Am_Exception_InputError(___("No search name passed")); $name = $this->getParam('name'); $id = $q->setName($name)->save(); $this->_response->redirectLocation($this->getDi()->url('admin-users',array('_u_search_load'=>$id),false)); } function valuesToForm(& $values, User $record) { $values['_groups'] = $record->getGroups(); } function beforeSave(array &$values, User $record) { if (!empty($values['_pass'])) $record->setPass($values['_pass']); if (!$record->isLoaded()) $record->is_approved = 1; } function afterSave(array &$values, User $record) { if(($this->grid->getCurrentAction() == 'insert') && @$values['_registration_mail']) { $record->sendRegistrationEmail(); } $record->setGroups(array_filter((array)@$values['_groups'])); //bind upload ids to current user $upload_ids = array(); foreach ($this->getDi()->userTable->customFields()->getAll() as $f) { if (in_array($f->type, array('upload', 'multi_upload'))) { $upload_ids = array_merge($upload_ids, (array)($f->sql ? $record->{$f->name} : $record->data()->get($f->name))); } } if ($upload_ids) { $this->getDi()->db->query(<<pk(), $this->getDi()->authAdmin->getUserId(), $upload_ids); } // if ($this->grid->hasPermission(null, 'edit')) // { // $this->_response->redirectLocation($this->getView()->userUrl($record->pk())); // exit(); // } } function loginAsAction() { if (!$this->getDi()->authAdmin->getUser()->hasPermission('grid_u', 'login-as')) throw new Am_Exception_AccessDenied(); $id = $this->getInt('id'); if (!$id) throw new Am_Exception_InputError("Empty or no id passed"); $user = $this->getDi()->userTable->load($id); $adapter = new Am_Auth_Adapter_User($user); $this->getDi()->auth->login($adapter, $this->getRequest()->getClientIp(), false); $this->_response->redirectLocation($this->getUrl('member', "index", null)); } function accessLogAction() { require_once dirname(__FILE__) . '/AdminLogsController.php'; $c = new AdminLogsController($this->getRequest(), $this->getResponse(), $this->getInvokeArgs()); $grid = $c->createAccess(); $grid->removeField('member_login'); $grid->getDataSource()->addWhere('t.user_id=?d', (int)$this->getParam('user_id')); $grid->runWithLayout('admin/user-layout.phtml'); } function mailQueueAction() { require_once dirname(__FILE__) . '/AdminLogsController.php'; $c = new AdminLogsController($this->getRequest(), $this->getResponse(), $this->getInvokeArgs()); $grid = $c->createMailQueue(); $user = $this->getDi()->userTable->load($this->getParam('user_id')); $grid->getDataSource()->addWhere('t.recipients LIKE ?', $user->email); $grid->runWithLayout('admin/user-layout.phtml'); } function notApprovedAction() { $this->_redirect('admin-users?_u_search[field-is_approved][val]=0'); } function resendSignupEmailAction() { $id = $this->_request->getInt('id'); if (!$id) throw new Am_Exception_InputError("Empty id"); $user = $this->getDi()->userTable->load($id); $user->sendSignupEmail(); $this->_response->ajaxResponse(array('success' => true)); } } PK\TuGG-default/controllers/AdminImportController.phpnu[hasPermission(Am_Auth_Admin::PERM_IMPORT); } public function backAction() { // dummy - @see _runAction } public function preDispatch() { // Try to set any available english UTF-8 locale. Required for fgetcsv function to parse UTF-8 content. setlocale(LC_ALL, 'C.UTF-8', 'en_US.UTF-8', 'C'); Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null); } public function _runAction($action) { //handle back action here //unset session variable for current step //change action name //go to process in normal way if ($action == 'backAction') { switch ($this->session->step) { case 2 : if (@$this->session->uploadSerialized) { $this->upload->unserialize($this->session->uploadSerialized); $this->upload->removeFiles(); } unset($this->session->path); unset($this->session->fieldsMap); unset($this->session->importOptions); $action = 'indexAction'; break; case 3 : unset($this->session->fieldsValue); $action = 'assignAction'; break; case 4 : $action = 'defineAction'; break; } $this->getRequest()->setActionName(str_replace('Action', '', $action)); } parent::_runAction($action); } public function init() { if (!$this->getDi()->uploadAcl->checkPermission('import', Am_Upload_Acl::ACCESS_WRITE, $this->getDi()->authAdmin->getUser())) { throw new Am_Exception_AccessDenied(); } $this->session = new Zend_Session_Namespace('amember_import'); $this->log = Import_Log::getInstance(); $this->upload = new Am_Upload($this->getDi()); $this->upload->setPrefix('import')->setTemp(3600); if ($this->session->path) { $this->dataSource = new Import_DataSource($this->session->path); if (isset($this->session->importOptions['delim'])) { $this->dataSource->setDelim($this->session->importOptions['delim']); } } $this->addImportFields(); } public function indexAction() { $this->cleanup(); if (!is_null($this->getParam('_h_p'))) { print ($this->view->importHistory = $this->createDemoHistoryGrid()->render()); return; } $this->view->importHistory = $this->createDemoHistoryGrid()->render(); $this->session->step = 1; $form = $this->getForm(self::FORM_UPLOAD); if ($this->isPost() && $form->isSubmitted() && $this->upload->processSubmit('file') && $files = $this->upload->getUploads()) { $file = $files[0]; $this->session->uploadSerialized = $this->upload->serialize(); $this->session->path = $file->getFullPath(); $this->dataSource = new Import_DataSource($this->session->path); $this->assignAction(); } else { $this->session->unsetAll(); $this->view->title = ___('Import: Step 1 of 4'); $this->view->form = $form; $this->view->display('admin/import/index.phtml'); } } public function assignAction() { $this->session->step = 2; $form = $this->getForm(self::FORM_ASSIGN); $submited = $form->isSubmitted(); if ($submited) { $this->session->importOptions['skip'] = $this->getParam('skip', 0); $this->session->importOptions['add_subscription'] = $this->getParam('add_subscription', 0); $this->session->importOptions['add_encrypted_pass'] = $this->getParam('add_encrypted_pass', 0); $this->session->importOptions['encrypted_pass_format'] = $this->getParam('encrypted_pass_format'); $this->session->importOptions['delim'] = $this->getParam('delim'); if ($delimCode = $this->session->importOptions['delim']) { $this->dataSource->setDelim($delimCode); } $this->session->fieldsMap = $this->getFieldsMapFromRequest(); //some import fields can be not applicable with new configuration $this->clearImportFields(); $this->addImportFields(); //recreate form with new configuration $form = $this->getForm(self::FORM_ASSIGN, $recreate = true, $force_submited = true); } if ($this->_request->isXmlHttpRequest()) { echo $this->renderAssignTable(); exit; } if ($submited && !($error = $this->validateAssign())) { $this->defineAction(); } else { $table = $this->renderAssignTable(); if (isset($error) && $error) { $this->view->error = $error; } $this->view->title = ___('Import: Step 2 of 4'); $this->view->table = $table; $this->view->display('admin/import/assign.phtml'); } } protected function validateAssign() { $error = array(); $fildsToAssign = array(); foreach ($this->getImportFields(self::FIELD_TYPE_USER) as $field) { if ($field->isRequired() && $field->isMustBeAssigned() && !$field->isAssigned()) { $fildsToAssign[] = $field->getTitle(); } } if (isset($this->session->importOptions['add_subscription']) && 1 == $this->session->importOptions['add_subscription']) { foreach ($this->getImportFields(array(self::FIELD_TYPE_ACCESS, self::FIELD_TYPE_SUBSCRIPTION)) as $field) { if ($field->isRequired() && $field->isMustBeAssigned() && !$field->isAssigned()) { $fildsToAssign[] = $field->getTitle(); } } } if (isset($this->session->importOptions['add_ecrypted_pass']) && 1 == $this->session->importOptions['add_ecrypted_pass']) { foreach ($this->getImportFields(self::FIELD_TYPE_ENCRYPTED_PASS) as $field) { if ($field->isRequired() && $field->isMustBeAssigned() && !$field->isAssigned()) { $fildsToAssign[] = $field->getTitle(); } } } if (count($fildsToAssign)) { $error[] = ___('Please assign the following fields: ') . implode(', ', $fildsToAssign); } //lets check if one field was assigned to more than one column $fieldsDoubleAssigned = array(); $alreadyAssigned = array(); foreach ($this->getRequest()->getParams() as $key => $fieldId) { if (strpos($key, 'FIELD') !== 0 || !$fieldId) continue; if (in_array($fieldId, $alreadyAssigned)) { $field = $this->getImportField($fieldId); if (!$field) { $field = $this->getImportField($fieldId, self::FIELD_TYPE_ACCESS); } if (!$field) { $field = $this->getImportField($fieldId, self::FIELD_TYPE_SUBSCRIPTION); } if (!$field) { $field = $this->getImportField($fieldId, self::FIELD_TYPE_ENCRYPTED_PASS); } $fieldsDoubleAssigned[] = $field->getTitle(); } else { array_push($alreadyAssigned, $fieldId); } } if (count($fieldsDoubleAssigned)) { $error[] = ___('One field can be assigned to one column only, you assigned following fields to several columns: ') . implode(', ', $fieldsDoubleAssigned); } return $error; } public function defineAction() { $this->session->step = 3; $this->session->importOptions['skip_invoice'] = $this->getParam('_skip_invoice', 0); $form = $this->getForm(self::FORM_DEFINE); if ($form->isSubmitted()) { $this->session->fieldsValue = $form->getValue(); } $table = $this->renderPreviewTable(); if ($this->_request->isXmlHttpRequest()) { echo $table . '
' . $form; exit; } if ($form->isSubmitted() && $form->validate()) { $this->confirmAction(); } else { $this->view->title = ___('Import: Step 3 of 4'); $this->view->table = $table; $this->view->form = $form; $this->view->display('admin/import/define.phtml'); } } public function confirmAction() { $this->session->step = 4; $form = $this->getForm(self::FORM_CONFIRM); if ($form->isSubmitted()) { $this->session->mode = $this->getParam('mode', self::MODE_SKIP); $this->log->clearLog(); $this->importAction(); } else { $this->view->title = ___('Import: Step 4 of 4'); $this->view->table = $this->renderPreviewTable(); $this->view->form = $form; $this->view->display('admin/import/confirm.phtml'); } } public function doImport(& $context, $batch) { if ($lineParsed = $this->dataSource->getNextLineParsed()) { $this->importLine($lineParsed); $this->updateImportHistory(); return false; } return true; } public function importAction() { $this->getDi()->hook->toggleDisableAll(true); $this->dataSource->setOffset($this->getStartOffset()); if (!$this->getStartOffset()) { //first chunk $this->session->timeStart = time(); if ($this->session->importOptions['skip']) { $this->dataSource->getNextLineParsed(); //skip first line; } if ($this->session->importOptions['add_encrypted_pass']) { Am_Config::saveValue('allow_auth_by_savedpass', 1); } } $batch = new Am_BatchProcessor(array($this, 'doImport')); $context = null; if (!$batch->run($context)) { $this->sendRedirect(); } $this->updateImportHistory(true); if (@$this->session->uploadSerialized) { $this->upload->unserialize($this->session->uploadSerialized); $this->upload->removeFiles(); } $this->reportAction(); } public function reportAction() { $this->view->stat = $this->log->getStat(); $this->view->import_id = $this->getID(); $this->view->errors = $this->log->getErrors(); $this->view->skip = $this->log->getSkip(); $interval = time() - $this->session->timeStart; $duration = array(); $duration['hrs'] = floor($interval / 3600); $duration['min'] = floor(($interval - $duration['hrs'] * 3600) / 60); $duration['sec'] = $interval - $duration['hrs'] * 3600 - $duration['min'] * 60; $this->view->duration = sprintf("%02d:%02d:%02d", $duration['hrs'], $duration['min'], $duration['sec'] ); $this->view->display('admin/import/report.phtml'); $this->cleanup(); } protected function cleanup() { if ($this->dataSource) unset($this->dataSource); $uploads = $this->upload->getUploads(); foreach ($uploads as $file) { $file->delete(); } $this->session->unsetAll(); } public function deleteAction() { $this->session->unsetAll(); $this->session->proccessed = 0; $this->session->lastUserId = 0; $query = new Am_Query($this->getDi()->userTable); $this->session->total = $query->getFoundRows(); $this->session->params = array(); $this->session->params['import-id'] = $this->getRequest()->getParam('id'); if (!$this->session->params['import-id']) { throw new Am_Exception_InputError('import-id is undefined'); } $this->sendDelRedirect(); } function deleteUser(& $context, $batch) { $count = 10; $query = new Am_Query($this->getDi()->userTable); $query = $query->addOrder('user_id')->addWhere('user_id>?', $this->session->lastUserId); $users = $query->selectPageRecords(0, $count); $moreToProcess = false; foreach ($users as $user) { $importId = $user->data()->get('import-id'); $this->session->lastUserId = $user->pk(); if ($importId && $importId == $this->session->params['import-id']) { $user->delete(); } $this->session->proccessed++; $moreToProcess = true; } return!$moreToProcess; } function doDeleteAction() { $batch = new Am_BatchProcessor(array($this, 'deleteUser')); $context = null; if (!$batch->run($context)) { $this->sendDelRedirect(); } $this->delImportHistory($this->session->params['import-id']); $this->session->unsetAll(); $this->_redirect('admin-import'); } function renderGridTitle($record) { return $record->completed ? sprintf('%s', ___('You have imported %d customers', $record->user_count) ) : sprintf('%s', ___('Import of data was terminated while processing. Anyway some data was imported.') ); } public function createDemoHistoryGrid() { $records = $this->getDi()->store->getBlob('import-records'); $records = $records ? unserialize($records) : array(); $ds = new Am_Grid_DataSource_Array($records); $ds->setOrder('date', true); $grid = new Am_Grid_Editable('_h', ___('Import History'), $ds, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_IMPORT); $grid->addField(new Am_Grid_Field_Date('date', ___('Date'), false, '', null, '10%')) ->setFormatDate(); $urlTpl = $this->getDi()->url('admin-users', array( '_u_search' => array( 'import' => array( 'id' => '__ID__' ) ) ), false); $urlTpl = str_replace('__ID__', '{id}', $urlTpl); $grid->addField('id', '#', false, '', null, '10%') ->addDecorator(new Am_Grid_Field_Decorator_Link($urlTpl)); $grid->addField(new Am_Grid_Field('title', ___('Title'), false, '', array($this, 'renderGridTitle'))); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_ImportDel); return $grid; } protected function sendDelRedirect() { $proccessed = $this->session->proccessed; $total = $this->session->total; $this->redirectHtml($this->getUrl('admin-import', 'do-delete'), ___('Clean up data. Please wait...'), ___('Clean up...'), false, $proccessed, $total); } protected function updateImportHistory($completed = false) { $records = $this->getDi()->store->getBlob('import-records'); $records = $records ? unserialize($records) : array(); $record = new stdClass(); $record->date = $this->getDi()->sqlDate; $record->user_count = $this->log->getStat(Import_Log::TYPE_SUCCESS); $record->id = $this->getID(); $record->can_be_canceled = ($this->session->mode == self::MODE_SKIP); $record->completed = $completed; $records[$this->getID()] = $record; $this->getDi()->store->setBlob('import-records', serialize($records)); } protected function delImportHistory($importId) { $records = $this->getDi()->store->getBlob('import-records'); $records = $records ? unserialize($records) : array(); unset($records[$importId]); $this->getDi()->store->setBlob('import-records', serialize($records)); } protected function sendRedirect() { $this->session->offset = $this->dataSource->getOffset(); $proccessed = $this->log->getStat(Import_Log::TYPE_PROCCESSED); $total = $this->dataSource->getEstimateTotalLines($proccessed); $this->redirectHtml($this->getUrl('admin-import', 'import'), ___('Import data. Please wait...'), ___('Import...'), false, $proccessed, $total); } protected function getID() { if (!$this->session->ID) { $this->session->ID = sprintf('I-%s', strtoupper($this->getDi()->security->randomString(6))); } return $this->session->ID; } protected function importLine($lineParsed) { $this->log->touchStat(Import_Log::TYPE_PROCCESSED); $record = $this->createUserRecord($lineParsed); $skip_user_fields = array(); $skip_add_encrypted_pass = false; if ($record->isLoaded()) { switch ($this->session->mode) { case self::MODE_OVERWRITE : $record->delete(); $record = $this->createUserRecord($lineParsed); break; case self::MODE_UPDATE : break; case self::MODE_UPDATE_LEAVE_PASSWORD : $skip_user_fields = array('pass'); $skip_add_encrypted_pass = true; break; case self::MODE_SKIP : $this->log->touchStat(Import_Log::TYPE_SKIP); $this->log->logSkip($lineParsed); return false; default: throw new Am_Exception_InternalError('Unknown mode [' . $this->mode . '] in class ' . __CLASS__); } } foreach ($this->getImportFields(self::FIELD_TYPE_USER) as $field) { if (in_array($field->getName(), $skip_user_fields)) continue; $field->setValueForRecord($record, $lineParsed); } try { $record->comment = "Imported (import #" . $this->getID() . ")"; $record->data()->set('import-id', $this->getID()); $record->data()->set('signup_email_sent', 1); $record->save(); $this->log->touchStat(Import_Log::TYPE_SUCCESS); if ($this->session->importOptions['add_subscription']) { $this->addSub($record, $lineParsed); $record->checkSubscriptions(true); } if ($this->session->importOptions['add_encrypted_pass'] && !$skip_add_encrypted_pass) { $this->addEncryptedPass($record, $lineParsed, $this->session->importOptions['encrypted_pass_format']); } return $record->pk(); } catch (Exception $e) { $this->log->touchStat(Import_Log::TYPE_ERROR); $this->log->logError($e->getMessage(), $lineParsed); return false; } } protected function createUserRecord($lineParsed) { $record = null; if (!$record) { $loginField = $this->getImportField('login'); if ($login = $loginField->getValue($lineParsed)) { $record = $this->getDi()->userTable->findFirstByLogin($login); } } if (!$record) { $emailField = $this->getImportField('email'); if ($email = $emailField->getValue($lineParsed)) { $record = $this->getDi()->userTable->findFirstByEmail($email); } } if (!$record) { $record = $this->getDi()->userRecord; } return $record; } protected function addSub(Am_Record $user, $lineParsed) { $user_id = $user->pk(); $product = $this->getDi()->productTable->load( $this->getImportField('product_id', self::FIELD_TYPE_ACCESS)->getValue($lineParsed), false ); if (!$product) return; if(!@$this->session->importOptions['skip_invoice']) { $invoice = $this->getDi()->invoiceRecord; $invoice->tm_added = $invoice->tm_started = $this->getImportField('begin_date', self::FIELD_TYPE_ACCESS)->getValue($lineParsed); $invoice->user_id = $user_id; $invoice->paysys_id = $this->getImportField('paysys_id', self::FIELD_TYPE_SUBSCRIPTION)->getValue($lineParsed); $invoice->currency = Am_Currency::getDefault(); $invoice->add($product); $items = $invoice->getItems(); $invoice->calculate(); $items[0]->first_price = $items[0]->first_total = $invoice->first_subtotal = $invoice->first_total = $this->getImportField('amount', self::FIELD_TYPE_SUBSCRIPTION)->getValue($lineParsed); $invoice->save(); if ($external_id = $this->getImportField('invoice_external_id', self::FIELD_TYPE_SUBSCRIPTION)->getValue($lineParsed)) $invoice->data()->set('external_id', $external_id)->update(); $payment = null; if ($amount = $this->getImportField('amount', self::FIELD_TYPE_SUBSCRIPTION)->getValue($lineParsed)) { $payment = $this->getDi()->invoicePaymentRecord; $payment->amount = $amount; $payment->user_id = $user_id; $payment->paysys_id = $this->getImportField('paysys_id', self::FIELD_TYPE_SUBSCRIPTION)->getValue($lineParsed); $payment->invoice_id = $invoice->pk(); $payment->receipt_id = $this->getImportField('receipt_id', self::FIELD_TYPE_SUBSCRIPTION)->getValue($lineParsed); $payment->transaction_id = $this->getID(); $payment->currency = $invoice->currency; $payment->dattm = $this->getImportField('begin_date', self::FIELD_TYPE_ACCESS)->getValue($lineParsed); if (empty($payment->dattm)) { $payment->dattm = $this->getDi()->sqlDateTime; // fallback to import time } $payment->save(); } } $access = $this->getDi()->accessRecord; $access->begin_date = $this->getImportField('begin_date', self::FIELD_TYPE_ACCESS)->getValue($lineParsed); $access->expire_date = $this->getImportField('expire_date', self::FIELD_TYPE_ACCESS)->getValue($lineParsed); $access->user_id = $user_id; $access->product_id = $product->pk(); $access->invoice_id = !empty($invoice) ? $invoice->pk() : null; $access->invoice_payment_id = !empty($payment) ? $payment->pk() : null; $access->transaction_id = $this->getID(); $access->save(); if(!@$this->session->importOptions['skip_invoice']) { $invoice->updateStatus(); if ($invoice->status == Invoice::RECURRING_ACTIVE) $invoice->recalculateRebillDate(); } } protected function addEncryptedPass(Am_Record $user, $lineParsed, $format) { $user_id = $user->pk(); if ($format == SavedPassTable::PASSWORD_PHPASS) { /* Special Case for Native aMember Hash Format */ $field = $this->getImportField('pass', self::FIELD_TYPE_ENCRYPTED_PASS); $user->updateQuick('pass', $field->getValue($lineParsed)); } else { $savedPass = $this->getDi()->savedPassTable->findFirstBy(array( 'user_id' => $user_id, 'format' => $format )); if (!$savedPass) { $savedPass = $this->getDi()->savedPassRecord; $savedPass->format = $format; $savedPass->user_id = $user_id; } foreach ($this->getImportFields(self::FIELD_TYPE_ENCRYPTED_PASS) as $field) { $field->setValueForRecord($savedPass, $lineParsed); } $savedPass->save(); } $user->data()->set(Am_Protect_Databased::USER_NEED_SETPASS, 1); $user->save(); } protected static function getImportModeOptions() { return array( self::MODE_SKIP => ___('Skip Line if Exist User with Same Login'), self::MODE_UPDATE => ___('Update User if Exist User with Same Login'), self::MODE_UPDATE_LEAVE_PASSWORD => ___('Update User if Exist User with Same Login (Do Not Overwrite Existing Password)'), self::MODE_OVERWRITE => ___('Overwrite User if Exist User with Same Login') ); } protected function getEncryptedPassFormatOptions() { $types = array( SavedPassTable::PASSWORD_PHPASS => 'aMember', SavedPassTable::PASSWORD_CRYPT => SavedPassTable::PASSWORD_CRYPT, SavedPassTable::PASSWORD_MD5_MD5_PASS_SALT => SavedPassTable::PASSWORD_MD5_MD5_PASS_SALT ); foreach ($this->getDi()->plugins_protect->loadEnabled()->getAllEnabled() as $pl) { $format = $pl->getPasswordFormat(); if ($format === null) continue; $types[$format] = isset($types[$format]) ? $types[$format] . ', ' . $pl->getTitle() : $pl->getTitle(); } return $types; } protected function getFieldsMapFromRequest() { $fieldsMap = array(); for ($i = 0; $i < $this->dataSource->getColNum(); $i++) { $fieldName = $this->getParam('FIELD' . $i); $fieldsMap[$fieldName] = $i; } return $fieldsMap; } protected function getRequestVarsFromFieldsMap() { $vars = array(); $fieldsMap = isset($this->session->fieldsMap) ? $this->session->fieldsMap : array(); foreach ($fieldsMap as $k => $v) { $vars['FIELD' . $v] = $k; } return $vars; } protected function getRequestVarsFromImportOptions() { $result = array(); if (!isset($this->session->importOptions)) { return $result; } $options = array('skip', 'add_subscription', 'add_encrypted_pass', 'encrypted_pass_format', 'delim'); foreach ($options as $opName) { if (isset($this->session->importOptions[$opName])) { $result[$opName] = $this->session->importOptions[$opName]; } } return $result; } protected function getRequestVarsFromFieldsValue() { if (!isset($this->session->fieldsValue)) { return array(); } else { return $this->session->fieldsValue; } } protected function addImportField(Import_Field $field, $type = self::FIELD_TYPE_USER) { $field->setSession($this->session); $field->setDi($this->getDi()); $this->importFields[$type][$field->getName()] = $field; } protected function getImportFields($type = self::FIELD_TYPE_USER) { if(!is_array($type)) $type = array($type); $ret = array(); foreach($type as $key) $ret+= $this->importFields[$key]; return $ret; } protected function getSubscriptionImportFields() { return $this->getImportFields( (isset($this->session->importOptions['skip_invoice']) && $this->session->importOptions['skip_invoice']) ? array(self::FIELD_TYPE_ACCESS) : array(self::FIELD_TYPE_ACCESS, self::FIELD_TYPE_SUBSCRIPTION) ); } /** * @param string $fieldName * @param enum $type * @return Import_Field */ protected function getImportField($fieldName, $type = self::FIELD_TYPE_USER) { return isset($this->importFields[$type][$fieldName]) ? $this->importFields[$type][$fieldName] : null; } protected function clearImportFields() { unset($this->importFields); } protected function addImportFields() { //User Fields $this->addImportField(new Import_Field('email', ___('Email'), true)); if (!@$this->session->importOptions['add_encrypted_pass']) { $this->addImportField(new Import_Field_UserPass('pass', 'Password', true)); } $this->addImportField(new Import_Field('name_f', ___('First Name'))); $this->addImportField(new Import_Field('name_l', ___('Last Name'))); $this->addImportField(new Import_Field_UserLogin('login', ___('Username'), true)); $this->addImportField(new Import_Field_WithFixed('phone', ___('Phone'))); $this->addImportField(new Import_Field('street', ___('Street'))); $this->addImportField(new Import_Field('street2', ___('Street (Second Line)'))); $this->addImportField(new Import_Field('city', ___('City'))); $this->addImportField(new Import_Field_State('state', ___('State'))); $this->addImportField(new Import_Field_Country('country', ___('Country'))); $this->addImportField(new Import_Field('zip', ___('Zip Code'))); $this->addImportField(new Import_Field('tax_id', ___('VatId'))); $this->addImportField(new Import_Field('remote_addr', ___('User IP address'))); $this->addImportField(new Import_Field('comment', ___('Comment'))); $this->addImportField(new Import_Field('unsubscribed', ___('Is Unsubscribed? (0 - No, 1 - Yes)'))); $this->addImportField(new Import_Field('is_affiliate', ___('Is Affiliate? (0 - No, 1 - Yes)'))); $this->addImportField(new Import_Field('aff_id', ___('Affiliate Id'))); $this->addImportField(new Import_Field_Data('external_id', 'Member External ID')); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { if ($field->sql) { if ($field->type == 'date') { $this->addImportField(new Import_Field_Date($field->name, $field->title)); } elseif(in_array($field->type, array('multi_select', 'checkbox'))) { $this->addImportField(new Import_Field_Multiselect($field->name, $field->title)); } else { $this->addImportField(new Import_Field($field->name, $field->title)); } } else { if ($field->type == 'date') { $this->addImportField(new Import_Field_Data_Date($field->name, $field->title)); } elseif (in_array($field->type, array('multi_select', 'checkbox'))) { $this->addImportField(new Import_Field_Data_Multiselect($field->name, $field->title)); } else { $this->addImportField(new Import_Field_Data($field->name, $field->title)); } } } } //Subscription Fields $this->addImportField(new Import_Field_SubProduct('product_id', ___('Subscription (Either ID or Title)'), true), self::FIELD_TYPE_ACCESS); $this->addImportField(new Import_Field_SubPaysystem('paysys_id', ___('Paysystem'), true), self::FIELD_TYPE_SUBSCRIPTION); $this->addImportField(new Import_Field_WithFixed('receipt_id', ___('Receipt'), true), self::FIELD_TYPE_SUBSCRIPTION); $this->addImportField(new Import_Field_WithFixed('amount', ___('Payment Amount'), true), self::FIELD_TYPE_SUBSCRIPTION); $this->addImportField(new Import_Field_Date('begin_date', ___('Subscription Begin Date'), true), self::FIELD_TYPE_ACCESS); $this->addImportField(new Import_Field_Date('expire_date', ___('Subscription Expire Date'), true), self::FIELD_TYPE_ACCESS); $this->addImportField(new Import_Field_Data('invoice_external_id', 'Invoice External ID'), self::FIELD_TYPE_SUBSCRIPTION); //Encrypted Pass Fields $this->addImportField(new Import_Field('pass', ___('Hash'), true), self::FIELD_TYPE_ENCRYPTED_PASS); $this->addImportField(new Import_Field('salt', ___('Salt'), true), self::FIELD_TYPE_ENCRYPTED_PASS); } private function getStartOffset() { if (isset($this->session->offset)) { return $this->session->offset; } else { return 0; } } protected function getFieldOptions($type = self::FIELD_TYPE_USER) { $options = array(); foreach ($this->getImportFields($type) as $field) { if ($field->isForAssign()) { $options[$field->getName()] = $field->getTitle(); } } return $options; } protected function loadFieldsOptions($fSelect, $add_subscription=0, $add_encrypted_pass=0) { $fSelect->addOption('', ''); if ($add_subscription || $add_encrypted_pass) { $optUser = $fSelect->addOptgroup(___('User')); foreach ($this->getFieldOptions(self::FIELD_TYPE_USER) as $key => $value) { $optUser->addOption($value, $key); } if ($add_subscription) { $optSub = $fSelect->addOptgroup(___('Subscription')); foreach ($this->getFieldOptions(array(self::FIELD_TYPE_ACCESS, self::FIELD_TYPE_SUBSCRIPTION)) as $key => $value) { $optSub->addOption($value, $key); } } if ($add_encrypted_pass) { $optSub = $fSelect->addOptgroup(___('Encrypted Password')); foreach ($this->getFieldOptions(self::FIELD_TYPE_ENCRYPTED_PASS) as $key => $value) { $optSub->addOption($value, $key); } } } else { $fSelect->loadOptions(array('' => '') + $this->getFieldOptions()); } } private function getForm($name, $recreate = false, $force_submited = false) { $propertyName = $name . 'Form'; $methodName = 'create' . ucfirst($name) . 'Form'; if (!$this->$propertyName || $recreate) { $this->$propertyName = $this->$methodName($force_submited); } return $this->$propertyName; } protected function createAssignForm($force_submited = false) { $form = new Am_Form_Admin('assign'); $form->setAction($this->getUrl(null, 'assign')); $form->addElement('checkbox', 'skip') ->setLabel(___('Skip First Line')) ->setId('skip'); $form->addElement('checkbox', 'add_subscription') ->setLabel('' . ___('Add Subscription') . '') ->setId('add_subscription'); $form->addElement('checkbox', 'add_encrypted_pass') ->setLabel('' . ___('Import Encrypted Password') . '') ->setId('add_encrypted_pass'); $form->addElement('select', 'encrypted_pass_format') ->loadOptions($this->getEncryptedPassFormatOptions()) ->setId('encrypted_pass_format'); $form->addElement('select', 'delim') ->setLabel(___('Delimiter')) ->loadOptions(Import_DataSource::getDelimOptions()) ->setId('delim'); $form->addElement('submit', '_submit_', array('value' => ___('Next'))) ->setId('_submit_'); for ($i = 0; $i < $this->dataSource->getColNum(); $i++) { $fSelect = $form->addSelect('FIELD' . $i, array('class' => 'csv-fields')) ->setId('FIELD' . $i); } if ($force_submited || $form->isSubmitted()) { $form->setDataSources(array( $this->getRequest() )); } else { $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array(array( 'delim' => $this->dataSource->getDelim(Import_DataSource::DELIM_CODE) ) + $this->getRequestVarsFromFieldsMap() + $this->getRequestVarsFromImportOptions() ) )); } $formValues = $form->getValue(); $add_subscription = @$formValues['add_subscription']; $add_encrypted_pass = @$formValues['add_encrypted_pass']; for ($i = 0; $i < $this->dataSource->getColNum(); $i++) { $fSelect = $form->getElementsByName('FIELD' . $i); $this->loadFieldsOptions($fSelect[0], $add_subscription, $add_encrypted_pass); } return $form; } protected function createDefineForm($force_submited = false) { $form = new Am_Form_Admin('commit'); $form->setAction($this->getUrl(null, 'define')); $fieldset = $form->addElement('fieldset', 'user') ->setLabel(___('User')); foreach ($this->getImportFields() as $field) { $field->buildForm($fieldset); } if ($this->session->importOptions['add_subscription']) { $fieldset = $form->addElement('fieldset', 'subscription') ->setLabel(___('Subscription')); $fieldset->addAdvCheckbox('_skip_invoice')->setLabel(___('Do not create invoice. Add only access record')); foreach ($this->getSubscriptionImportFields() as $field) { $field->buildForm($fieldset); } } if ($this->session->importOptions['add_encrypted_pass']) { $fieldset = $form->addElement('fieldset', 'encrypted_pass') ->setLabel(___('Encrypted Pass')); foreach ($this->getImportFields(self::FIELD_TYPE_ENCRYPTED_PASS) as $field) { $field->buildForm($fieldset); } } $group = $form->addGroup(); $group->setSeparator(' '); $group->addElement('inputbutton', 'back', array('value' => ___('Back'))) ->setId('back'); $group->addElement('submit', '_submit_', array('value' => ___('Next'))) ->setId('_submit_'); if ($force_submited || $form->isSubmitted()) { $form->setDataSources(array($this->getRequest())); } else { $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array($this->getRequestVarsFromFieldsValue()) )); } return $form; } protected function createConfirmForm($force_submited = false) { $form = new Am_Form_Admin('confirm'); $form->setAction($this->getUrl(null, 'confirm')); $form->addAdvRadio('mode') ->setLabel(___('Import Mode')) ->loadOptions(self::getImportModeOptions()) ->setValue(self::MODE_SKIP); $group = $form->addGroup(); $group->setSeparator(' '); $group->addElement('inputbutton', 'back', array('value' => ___('Back'))) ->setId('back'); $group->addElement('submit', '_submit_', array('value' => ___('Do Import'))) ->setId('_submit_'); if ($force_submited || $form->isSubmitted()) { $form->setDataSources(array($this->getRequest())); } else { $form->setDataSources(array(new HTML_QuickForm2_DataSource_Array(array()))); } return $form; } protected function createUploadForm($force_submited = false) { $form = new Am_Form_Admin('upload'); $form->setAction($this->getUrl(null, '')); $form->setAttribute('enctype', 'multipart/form-data'); $file = $form->addElement('file', 'file[]') ->setLabel(___('File')); $file->setAttribute('class', 'styled'); $file->addRule('required', ___('This field is a requried field')); $form->addElement('submit', '_submit_', array('value' => ___('Next'))); return $form; } protected function getAssignFormRendered() { $form = $this->getForm(self::FORM_ASSIGN); $renderer = HTML_QuickForm2_Renderer::factory('array'); $form->render($renderer); $form = $renderer->toArray(); $elements = array(); foreach ($form['elements'] as $element) { $elements[$element['id']] = $element; } $form['elements'] = $elements; return $form; } protected function renderAssignTable() { $form = $this->getAssignFormRendered(); $linesParsed = $this->dataSource->getFirstLinesParsed(10); if (!count($linesParsed)) { return sprintf('
  • %s
', ___('No one line found in the file. It looks like file is empty. You can go back and try another file.')); } $out = sprintf('
', $form['attributes']); $out .= '
'; $out .= $form['elements']['add_encrypted_pass']['label'] . ': ' . $form['elements']['add_encrypted_pass']['html']; if ($this->session->importOptions['add_encrypted_pass']) { $out .= '
'; $out .= $form['elements']['encrypted_pass_format']['html']; } $out .= '
'; $out .= $form['elements']['add_subscription']['label'] . ': ' . $form['elements']['add_subscription']['html']; $out .= '
'; $out .= $form['elements']['skip']['label'] . ': ' . $form['elements']['skip']['html']; $out .= '
'; $out .= $form['elements']['delim']['label'] . ': ' . $form['elements']['delim']['html']; $out .= '
'; $out .= '
'; $out .= ''; $out .= ''; for ($i = 0; $i < $this->dataSource->getColNum(); $i++) { $out .= sprintf('', $form['elements']['FIELD' . $i]['html']); } $out .= ''; foreach ($linesParsed as $lineNum => $lineParsed) { $out .= ''; foreach ($lineParsed as $colNum => $value) { $out .= sprintf('', 'FIELD' . $colNum, $value); } $out .= ''; } $out .= '
%s
' . $lineNum . '%s
'; $out .= '
'; $out .= '
'; $out .= '
'; $out .= sprintf(' ', ___('Back')); $out .= $form['elements']['_submit_']['html']; $out .= implode('', $form['hidden']); $out .= '
'; $out .= '
'; return $out; } protected function renderPreviewTable() { $out = '
'; $out .= ''; $out .= ''; $importFields = $this->getImportFields(); foreach ($importFields as $field) { if ($field->isForImport()) { $out .= sprintf('%s', ($field->isRequired() && !$field->isDefined()) ? ' class="required"' : '', $field->getTitle() ); } } if ($this->session->importOptions['add_subscription']) { $importSubFields = $this->getSubscriptionImportFields(); foreach ($importSubFields as $field) { if ($field->isForImport()) { $out .= sprintf('%s', ($field->isRequired() && !$field->isDefined()) ? ' class="required"' : '', $field->getTitle() ); } } } if ($this->session->importOptions['add_encrypted_pass']) { $importEncryptedFields = $this->getImportFields(self::FIELD_TYPE_ENCRYPTED_PASS); foreach ($importEncryptedFields as $field) { if ($field->isForImport()) { $out .= sprintf('%s', ($field->isRequired() && !$field->isDefined()) ? ' class="required"' : '', $field->getTitle() ); } } } $out .= ''; $linesParsed = $this->dataSource->getFirstLinesParsed(10); if ($this->session->importOptions['skip']) { unset($linesParsed[0]); } foreach ($linesParsed as $lineNum => $lineParsed) { $out .= ''; $dummyUser = $this->getDi()->userRecord; foreach ($importFields as $field) { if ($field->isForImport()) { $field->setValueForRecord($dummyUser, $lineParsed); $out .= sprintf('', $field->getReadableValue($lineParsed, $dummyUser)); } } if ($this->session->importOptions['add_subscription']) { $importSubFields = $this->getSubscriptionImportFields(); foreach ($importSubFields as $field) { if ($field->isForImport()) { $out .= sprintf('', $field->getReadableValue($lineParsed)); } } } if ($this->session->importOptions['add_encrypted_pass']) { $importPassFields = $this->getImportFields(self::FIELD_TYPE_ENCRYPTED_PASS); foreach ($importPassFields as $field) { if ($field->isForImport()) { $out .= sprintf('', $field->getReadableValue($lineParsed)); } } } $out .= ''; } $out .= '
' . $lineNum . '%s%s%s
'; $out .= '
'; return $out; } } class Import_Field { protected $title; protected $name; protected $isRequired = false; /** @var Zend_Session_Namespace */ protected $session = null; //field can be fetched from CSV file protected $isForAssign = true; protected $isMustBeAssigned = true; /** @var Am_Di */ protected $di; public function __construct($name, $title, $isRequired = false) { $this->name = $name; $this->title = $title; $this->isRequired = $isRequired; } public function setDi(Am_Di $di) { $this->di = $di; } /** * @return Am_Di */ public function getDi() { return $this->di; } public function setSession(Zend_Session_Namespace $session) { $this->session = $session; } public function buildForm(HTML_QuickForm2_Container $form) { if (!$this->isAssigned()) { $this->_buildForm($form); } } protected function _buildForm(HTML_QuickForm2_Container $form) { //nop } public function isAssigned() { return isset($this->session->fieldsMap[$this->getName()]); } //field can be fetched from CSV file public function isForAssign() { return $this->isForAssign; } public function isRequired() { return $this->isRequired; } //field should be used in import process (Required or Defined) public function isForImport() { return $this->isRequired() || ($this->isAssigned() || $this->isDefined()); } public function isDefined() { //try to guess if this field is defined //getValue should return non empty value //in this case static $dummyArray; if (!is_array($dummyArray)) { $dummyArray = range(1, 30); } return!('' === $this->getValue($dummyArray)); } //this field can be fetched only from CSV file public function isMustBeAssigned() { return $this->isMustBeAssigned; } public function getAssignedIndex() { if (isset($this->session->fieldsMap[$this->getName()])) { return $this->session->fieldsMap[$this->getName()]; } else { return false; } } public function getName() { return $this->name; } public function getTitle() { return $this->title; } public function setValueForRecord($record, $lineParsed) { if ($this->isForImport()) { $this->_setValueForRecord($record, $this->getValue($lineParsed, $record)); } } protected function _setValueForRecord($record, $value) { $record->{$this->getName()} = $value; } public function getValue($lineParsed, $partialRecord = null) { if ($this->isAssigned()) { return trim($lineParsed[$this->getAssignedIndex()]); } else { return ''; } } public function getReadableValue($lineParsed, $partialRecord = null) { return $this->getValue($lineParsed, $partialRecord); } } class Import_Field_WithFixed extends Import_Field { protected $isMustBeAssigned = false; protected function _buildForm(HTML_QuickForm2_Container $form) { $el = $form->addText('field_' . $this->getName(), array('class' => 'fixed')) ->setLabel($this->getTitle()); if ($this->isRequired()) { $el->addRule('required', ___('This field is a requried field')); } } public function getValue($lineParsed, $partialRecord=null) { if ($this->isAssigned()) { return parent::getValue($lineParsed, $partialRecord); } elseif (isset($this->session->fieldsValue['field_' . $this->getName()])) { return $this->session->fieldsValue['field_' . $this->getName()]; } else { return ''; } } } class Import_Field_Date extends Import_Field { protected $isMustBeAssigned = false; protected function _buildForm(HTML_QuickForm2_Container $form) { $el = $form->addDate('field_' . $this->getName(), array('class' => 'fixed')) ->setLabel($this->getTitle()); if ($this->isRequired()) { $el->addRule('required', ___('This field is a requried field')); } } public function getValue($lineParsed, $partialRecord = null) { $rawValue = $this->getRawValue($lineParsed, $partialRecord); return $rawValue ? date('Y-m-d', amstrtotime($rawValue)) : ''; } protected function getRawValue($lineParsed, $partialRecord = null) { if ($this->isAssigned()) { return parent::getValue($lineParsed, $partialRecord); } else { return (isset($this->session->fieldsValue['field_' . $this->getName()])) ? $this->session->fieldsValue['field_' . $this->getName()] : ''; } } public function getReadableValue($lineParsed, $partialRecord = null) { if ($date = $this->getValue($lineParsed, $partialRecord)) { return amDate($date); } else { return ''; } } } class Import_Field_State extends Import_Field { static $stateOptions; public function getReadableValue($lineParsed, $partialRecord = null) { $state = $this->getValue($lineParsed, $partialRecord); $stateOptions = $this->getStateOptions(); if (isset($stateOptions[$state])) { return $stateOptions[$state]; } else { return $state; } } private function getStateOptions() { if (is_null(self::$stateOptions)) { $res = $this->getDi()->db->selectCol("SELECT state as ARRAY_KEY, CASE WHEN tag<0 THEN CONCAT(title, ' (disabled)') ELSE title END FROM ?_state"); self::$stateOptions = $res; } return self::$stateOptions; } } class Import_Field_Country extends Import_Field { static $countryOptions; public function getReadableValue($lineParsed, $partialRecord = null) { $country = $this->getValue($lineParsed, $partialRecord); $countryOptions = $this->getCountryOptions(); if (isset($countryOptions[$country])) { return $countryOptions[$country]; } else { return ''; } } private function getCountryOptions() { if (is_null(self::$countryOptions)) { self::$countryOptions = $this->getDi()->countryTable->getOptions(); } return self::$countryOptions; } } class Import_Field_SubProduct extends Import_Field { protected $isMustBeAssigned = false; protected static $productOptions = null; protected static $productIndex = null; static function id($id) { if (is_null(self::$productIndex)) { self::$productIndex = Am_Di::getInstance()->db ->selectCol('SELECT product_id, title AS ARRAY_KEY ' . 'FROM ?_product'); } return is_numeric($id) ? $id : (isset(self::$productIndex[$id]) ? self::$productIndex[$id] : ''); } protected function _buildForm(HTML_QuickForm2_Container $form) { $el = $form->addElement('select', 'field_' . $this->getName()) ->setLabel($this->getTitle()) ->loadOptions($this->getProductOptions()); if ($this->isRequired()) { $el->addRule('required', ___('This field is a requried field')); } } public function getValue($lineParsed, $partialRecord = null) { if ($this->isAssigned()) { return self::id(parent::getValue($lineParsed, $partialRecord)); } elseif (isset($this->session->fieldsValue['field_' . $this->getName()])) { return $this->session->fieldsValue['field_' . $this->getName()]; } else { return ''; } } public function getReadableValue($lineParsed, $partialRecord = null) { $product_id = $this->getValue($lineParsed, $partialRecord); $productOptions = $this->getProductOptions(); if (isset($productOptions[$product_id])) { return $productOptions[$product_id]; } else { return ''; } } private function getProductOptions() { if (is_null(self::$productOptions)) { self::$productOptions = $this->getDi()->productTable->getOptions(); } return self::$productOptions; } } class Import_Field_SubPaysystem extends Import_Field { protected $isMustBeAssigned = false; protected $isForAssign = true; private static $paysystemOptions = null; protected function _buildForm(HTML_QuickForm2_Container $form) { $el = $form->addElement('select', 'field_' . $this->getName()) ->setLabel($this->getTitle()) ->loadOptions($this->getPaysystemOptions()); if ($this->isRequired()) { $el->addRule('required', ___('This field is a requried field')); } } public function getValue($lineParsed, $partialRecord = null) { if ($this->isAssigned()) { return parent::getValue($lineParsed, $partialRecord); } elseif (isset($this->session->fieldsValue['field_' . $this->getName()])) { return $this->session->fieldsValue['field_' . $this->getName()]; } else { return ''; } } public function getReadableValue($lineParsed, $partialRecord = null) { $paysys_id = $this->getValue($lineParsed, $partialRecord); $paysystemOptions = $this->getPaysystemOptions(); if (isset($paysystemOptions[$paysys_id])) { return $paysystemOptions[$paysys_id]; } else { return ''; } } private function getPaysystemOptions() { if (is_null(self::$paysystemOptions)) { self::$paysystemOptions = $this->getDi()->paysystemList->getOptions(); } return self::$paysystemOptions; } } class Import_Field_Multiselect extends Import_Field { protected function _setValueForRecord($record, $value) { $record->{$this->getName()} = preg_split('/[:,]/', $value); } } class Import_Field_Data extends Import_Field { protected function _setValueForRecord($record, $value) { $record->data()->set($this->getName(), $value); } } class Import_Field_Data_Date extends Import_Field_Date { protected function _setValueForRecord($record, $value) { $record->data()->set($this->getName(), $value); } } class Import_Field_Data_Multiselect extends Import_Field { protected function _setValueForRecord($record, $value) { $record->data()->set($this->getName(), preg_split('/[:,]/', $value)); } } class Import_Field_UserPass extends Import_Field { const KEY_FIXED = 'FIXED'; const KEY_GENERATE = 'GENERATE'; protected $isMustBeAssigned = false; protected function _buildForm(HTML_QuickForm2_Container $form) { $fieldGroup = $form->addElement('group', 'field_' . $this->getName()) ->setLabel($this->getTitle()); $fieldGroup->addElement('select', 'type') ->loadOptions( array( self::KEY_GENERATE => 'Generate', self::KEY_FIXED => 'Fixed' ) ); $fieldGroup->addElement('text', 'fixed', array('class' => 'fixed')); if ($this->isRequired()) { $fieldGroup->addRule('required', ___('This field is a requried field')); } } protected function _setValueForRecord($record, $value) { $record->setPass($value); } public function getValue($lineParsed, $partialRecord=null) { if ($this->isAssigned()) { return parent::getValue($lineParsed, $partialRecord); } elseif (self::KEY_FIXED == $this->session->fieldsValue['field_' . $this->getName()]['type']) { return $this->session->fieldsValue['field_' . $this->getName()]['fixed']; } else { return $this->getDi()->security->randomString(8); } } public function setValueForRecord($record, $lineParsed) { //user already exists in database //so we do not generate new password for him //but admin still can assign new password while import if (!$this->isAssigned() && @$record->pass) return; parent::setValueForRecord($record, $lineParsed); } } class Import_Field_UserLogin extends Import_Field { protected $isMustBeAssigned = false; protected function _buildForm(HTML_QuickForm2_Container $form) { $form->addElement('static', 'field_' . $this->getName()) ->setLabel($this->getTitle()) ->setContent(sprintf("
%s
", ___('Generated'))); } public function getValue($lineParsed, $partialRecord = null) { /* @var $partialRecord User */ if ($this->isAssigned()) { return parent::getValue($lineParsed, $partialRecord); } else { if ($partialRecord) { $partialRecord->generateLogin(); return $partialRecord->login; } else { return $this->getDi()->security->randomString(8); } } } public function setValueForRecord($record, $lineParsed) { //user already exists in database and found by email address //so we do not want to overwrite his login with autogenerated value but we //still use new value for login if it is fetched from file if (!$this->isAssigned() && @$record->login) return; parent::setValueForRecord($record, $lineParsed); } } class Import_DataSource { const MAX_LINE_LENGTH = 4096; const DELIM_SEMICOLON = 1; const DELIM_COMMA = 2; const DELIM_SPACE = 3; const DELIM_TABULATION = 4; const DELIM_VALUE = 1; const DELIM_CODE = 2; protected $filePointerIterator = null; protected $filePointer = null; protected $colNum = null; protected $delimCode = null; protected $firstLineRaw = null; protected $firstLineParsed = null; public function __construct($path) { $this->filePointer = fopen($path, 'r'); $this->filePointerIterator = fopen($path, 'r'); } public function __destruct() { fclose($this->filePointer); fclose($this->filePointerIterator); } public function getOffset() { return ftell($this->filePointerIterator); } public function setOffset($offset = 0) { fseek($this->filePointerIterator, $offset); } public function rewind() { $this->setOffset(0); } public function getDelim($mode = self::DELIM_VALUE) { if (is_null($this->delimCode)) { $this->delimCode = $this->guessDelim(); } switch ($mode) { case self::DELIM_VALUE : return self::getDelimByCode($this->delimCode); case self::DELIM_CODE : return $this->delimCode; default : throw new Am_Exception_InputError( ___('Unknown mode [%s] in %s->%s', $mode, __CLASS__, __METHOD__)); } } public function setDelim($delimCode) { $this->delimCode = $delimCode; //remove cached values that depends on delimiter $this->colNum = null; $this->firstLineParsed = null; } public function getNextLineParsed($pointer=null, $normalize = true) { $pointer = $pointer ? $pointer : $this->filePointerIterator; $res = $this->_getNextLineParsed($pointer); if ($res === false || !is_array($res)) return false; if (is_null($res[0])) return $this->getNextLineParsed($pointer, $normalize); return $normalize ? $this->normalizeLineParsed($res) : $res; } protected function _getNextLineParsed($pointer) { if (feof($pointer)) { return false; } else { return fgetcsv($pointer, self::MAX_LINE_LENGTH, $this->getDelim()); } } public function getFirstLineParsed($normalize = true) { if (!$this->firstLineParsed) { fseek($this->filePointer, 0); $this->firstLineParsed = $this->getNextLineParsed($this->filePointer, $normalize); } return $this->firstLineParsed; } public function getFirstLinesParsed($num, $normalize = true) { $result = array(); fseek($this->filePointer, 0); for ($i = 0; $i < $num; $i++) { $res = $this->getNextLineParsed($this->filePointer, $normalize); if (!$res) { break; } $result[$i] = $res; } return $result; } public function getColNum() { if (!$this->colNum) { $this->colNum = count((array) $this->getFirstLineParsed(false)); } return $this->colNum; } public static function getDelimOptions() { return array( self::DELIM_SEMICOLON => ___('Semicolon'), self::DELIM_COMMA => ___('Comma'), self::DELIM_SPACE => ___('Space'), self::DELIM_TABULATION => ___('Tabulation') ); } public function getEstimateTotalLines($proccessed) { $perLine = round($this->getOffset() / $proccessed); $total = round($this->getFileSize() / $perLine); return $total; } protected function getFirstLineRaw() { if (!$this->firstLineRaw) { fseek($this->filePointer, 0); $this->firstLineRaw = trim(fgets($this->filePointer)); } return $this->firstLineRaw; } private function getFileSize() { $stat = fstat($this->filePointer); return $stat['size']; } protected function normalizeLineParsed($lineParsed) { $result = (array) $lineParsed; if (count($lineParsed) > $this->getColNum()) { $result = array_slice($result, 0, $this->getColNum()); } elseif (count($lineParsed) < $this->getColNum()) { $result = array_pad($result, $this->getColNum(), ''); } return $result; } protected static function getDelimMap() { return array( self::DELIM_SEMICOLON => ';', self::DELIM_COMMA => ',', self::DELIM_SPACE => ' ', self::DELIM_TABULATION => "\t" ); } protected static function getDelimByCode($delimCode) { $map = self::getDelimMap(); if (!isset($map[$delimCode])) { throw new Am_Exception_InputError('Unknown delim code [' . $delimCode . ']'); } return $map[$delimCode]; } protected function guessDelim() { foreach (self::getDelimMap() as $delimCode => $delim) { if (count(explode($delim, $this->getFirstLineRaw())) >= 3) { return $delimCode; } } return self::DELIM_SEMICOLON; } } class Import_Log { const TYPE_SKIP = 1; const TYPE_ERROR = 2; const TYPE_SUCCESS = 3; const TYPE_PROCCESSED = 4; const MAX_ERRORS_LOG = 15; const MAX_SKIP_LOG = 15; /** @var Zend_Session_Namespace */ protected $session; protected static $instance = null; protected function __construct() { $this->session = new Zend_Session_Namespace('amember_import_log'); } public static function getInstance() { if (!self::$instance) { self::$instance = new self(); } return self::$instance; } public function touchStat($type) { if (!isset($this->session->stat) || !is_array($this->session->stat)) { $this->session->stat = array( self::TYPE_SKIP => 0, self::TYPE_ERROR => 0, self::TYPE_SUCCESS => 0, self::TYPE_PROCCESSED => 0 ); } $this->session->stat[$type]++; } public function getStat($type = null) { if (is_null($type)) { return $this->session->stat; } if (isset($this->session->stat[$type])) { return $this->session->stat[$type]; } else { return 0; } } public function logError($message, $lineParsed) { if (!isset($this->session->errors)) { $this->session->errors = array(); } if (count($this->session->errors) >= self::MAX_ERRORS_LOG) { return; } $error = array(); $error['msg'] = $message; $error['lineParsed'] = $lineParsed; $this->session->errors[] = $error; } public function logSkip($lineParsed) { if (!isset($this->session->skip)) { $this->session->skip = array(); } if (count($this->session->skip) >= self::MAX_SKIP_LOG) { return; } $this->session->skip[] = $lineParsed; } public function clearLog() { $this->session->errors = array(); $this->session->skip = array(); $this->session->stat = null; } public function getErrors() { if (!isset($this->session->errors)) { $this->session->errors = array(); } return $this->session->errors; } public function getSkip() { if (!isset($this->session->skip)) { $this->session->skip = array(); } return $this->session->skip; } } class Am_Grid_Action_ImportDel extends Am_Grid_Action_Abstract { protected $title = 'Delete'; protected $id = "delete"; public function __construct() { parent::__construct(); $this->setTarget('_top'); } public function run() { //nop } public function getUrl($record = null, $id = null) { return $this->grid->getDi()->url('admin-import/delete',array('id' => $record->id), false); } public function isAvailable($record) { return $record->can_be_canceled; } } PK\"b&770default/controllers/AdminSavedFormController.phpnu[grid->getRecord(); $record->generateCode(); $vars = $record->toRow(); unset($vars['saved_form_id']); unset($vars['default_for']); $vars['title'] = ___('Copy of') . ' ' . $record->title; $back = @$_SERVER['HTTP_X_REQUESTED_WITH']; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $request = new Am_Mvc_Request($vars + array($this->grid->getId() . '_a' => 'insert-' . $record->type, $this->grid->getId() . '_b' => $this->grid->getBackUrl()), Am_Mvc_Request::METHOD_POST); $controller = new AdminSavedFormController($request, new Am_Mvc_Response(), array('di' => Am_Di::getInstance())); $request->setModuleName('default') ->setControllerName('admin-saved-form') ->setActionName('index') ->setDispatched(true); $controller->dispatch('indexAction'); $response = $controller->getResponse(); $response->sendResponse(); $_SERVER['HTTP_X_REQUESTED_WITH'] = $back; } } class Am_Grid_Action_Sort_SavedForm extends Am_Grid_Action_Sort_Abstract { protected function setSortBetween($item, $after, $before) { $this->_simpleSort(Am_Di::getInstance()->savedFormTable, $item, $after, $before); } } class Am_Form_Admin_SavedForm extends Am_Form_Admin { /** @var SavedForm */ protected $record; /** @var Am_Form_Element_BricksEditor */ protected $brickEditor; public function __construct(SavedForm $record) { $this->record = $record; parent::__construct(); } public function init() { parent::init(); $typeDef = $this->record->getTypeDef(); $type = $this->addSelect('type', null, array('options' => Am_Di::getInstance()->savedFormTable->getTypeOptions())); $type->setLabel(___('Form Type')); if (!empty($this->record->type)) $type->toggleFrozen(true); $title = $this->addText('title', array('class' => 'el-wide'))->setLabel( ___("Custom Signup Form Title\n". "keep empty to use default title")); $comment = $this->addText('comment', array('class' => 'el-wide')) ->setLabel( ___("Comment\nfor admin reference")); if ($this->record->isSignup() || $this->record->isProfile()) { if (!empty($typeDef['generateCode'])) { $code = $this->addText('code') ->setLabel(___("Secret Code\n". "if form is not choosen as default, this code\n". "(inside URL) will be necessary to open form")) ->addRule('regex', ___('Value must be alpha-numeric'), '/[a-zA-Z0-9_]/'); } } if ($this->record->type == SavedForm::T_SIGNUP || $this->record->type == SavedForm::T_PROFILE) { $this->addAdvCheckbox('hide') ->setLabel(___("Hide from Menu\n" . "do not include link to this form in members menu")); } $this->brickEditor = $this->addElement(new Am_Form_Element_BricksEditor('fields', array(), $this->record->createForm())) ->setLabel(___('Fields')); if ($this->record->isSignup()) { $this->addSelect('tpl') ->setLabel(___("Template\nalternative template for signup page"). "\n" . ___("aMember will look for templates in [application/default/views/signup/] folder\n". "and in theme's [signup/] folder\n". "and template filename must start with [signup]")) ->loadOptions($this->getSignupTemplates()); } $fs = $this->addAdvFieldset('meta', array('id'=>'meta')) ->setLabel(___('Meta Data')); $fs->addText('meta_title', array('class' => 'el-wide')) ->setLabel(___('Title')); $fs->addText('meta_keywords', array('class' => 'el-wide')) ->setLabel(___('Keywords')); $fs->addText('meta_description', array('class' => 'el-wide')) ->setLabel(___('Description')); $gr = $fs->addGroup()->setLabel(___("Robots\n" . "instructions for search engines")); $gr->setSeparator(' '); $gr->addCheckbox('meta_robots[]', array('value' => 'noindex'), array('content' => 'noindex')); $gr->addCheckbox('meta_robots[]', array('value' => 'nofollow'), array('content' => 'nofollow')); $gr->addCheckbox('meta_robots[]', array('value' => 'noarchive'), array('content' => 'noarchive')); $gr->addFilter('array_filter'); } public function render(HTML_QuickForm2_Renderer $renderer) { return parent::render($renderer); } static function getSignupTemplates() { $folders = array( AM_APPLICATION_PATH . '/default/views/' => 1, AM_APPLICATION_PATH . '/default/themes/' . Am_Di::getInstance()->config->get('theme') => 2, ); if(Am_Di::getInstance()->config->get('protect.wordpress.use_wordpress_theme')) { $path = defined("TEMPLATEPATH") ? TEMPLATEPATH : 'default'; $path_parts = preg_split('/[\/\\\]/', $path); $path = array_pop($path_parts); if (file_exists(AM_APPLICATION_PATH . '/default/plugins/protect/wordpress/' . $path)) { $path = $path; } else if (preg_match("/^([a-zA-Z]+)/", $path, $regs) && file_exists(AM_APPLICATION_PATH . '/default/plugins/protect/wordpress/' . $regs[1])) { $path = $regs[1]; } else { $path = false; } if($path) $folders[AM_APPLICATION_PATH . '/default/plugins/protect/wordpress/' . $path] = 3; } $ret = array(); foreach (array_keys($folders) as $f) { foreach ((array)glob($f . '/signup/signup*.phtml') as $file) { if (!strlen($file)) continue; $file = basename($file); $ret[$file == 'signup.phtml' ? null : $file] = $file; } } return $ret; } public function renderEpilog() { return $this->brickEditor->renderConfigForms(); } } class AdminSavedFormController extends Am_Mvc_Controller_Grid { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_FORM); } function init() { if (!class_exists('Am_Form_Brick', false)) { class_exists('Am_Form_Brick', true); Am_Di::getInstance()->hook->call(Am_Event::LOAD_BRICKS); } parent::init(); } public function createGrid() { $this->view->headScript()->appendFile($this->view->_scriptJs("jquery/jquery.json.js")); $table = $this->getDi()->savedFormTable; $ds = new Am_Query($table); $ds->addWhere('`type` in (?a)', array_keys($table->getTypeDefs())); $ds->addOrderRaw("sort_order"); $grid = new Am_Grid_Editable('_s', ___('Forms Editor'), $ds, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_FORM); $grid->setEventId('gridSavedForm'); $grid->setForm(array($this, 'createForm')); $grid->setRecordTitle(' '); $grid->addField(SavedForm::D_SIGNUP, ___('Default Signup'), false) ->setWidth('5%') ->setRenderFunction(array($this, 'renderSignupDefault')); $grid->addField(SavedForm::D_MEMBER, ___('Default for Members'), false) ->setWidth('5%') ->setRenderFunction(array($this, 'renderSignupDefault')); $grid->addField(SavedForm::D_PROFILE, ___('Default for Profile'), false) ->setWidth('5%') ->setRenderFunction(array($this, 'renderProfileDefault')); $grid->addField('hide', ___('Hide')); $existingTypes = $this->getDi()->savedFormTable->getExistingTypes(); $grid->actionGet('edit')->setTarget('_top'); $grid->actionDelete('insert'); foreach ($this->getDi()->savedFormTable->getTypeDefs() as $type => $typeDef) { if (!empty($typeDef['isSingle']) && in_array($type, $existingTypes)) continue; $grid->actionAdd(new Am_Grid_Action_Insert('insert-'.$type)) ->addUrlParam('type', $type)->setTitle(___('New %s', $typeDef['title'])); } $grid->addCallback(Am_Grid_Editable::CB_BEFORE_SAVE, array($this, 'beforeSave')); $grid->addField(new Am_Grid_Field('type', ___('Type'))); $grid->addField(new Am_Grid_Field('title', ___('Title'))); $grid->addField(new Am_Grid_Field('comment', ___('Comment'))); $grid->addField(new Am_Grid_Field('url', ___('URL'), false)) ->setRenderFunction(array($this, 'renderUrl')); $grid->actionGet('delete') ->setIsAvailableCallback(function($r) {return $r->canDelete();}); $grid->actionAdd(new Am_Grid_Action_CopySavedForm()) ->setIsAvailableCallback(function($r) {return !$r->isSingle();}); $grid->setFormValueCallback('meta_robots', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_STATIC, function(& $out, $grid) { $out .= << jQuery('.grid-wrap').on('change', 'input.set-default', function(){ jQuery(this).closest("form").submit(); }); CUT; }); $grid->actionAdd(new Am_Grid_Action_LiveCheckbox('hide')) ->setIsAvailableCallback(function($r) { return $r->type == SavedForm::T_SIGNUP || $r->type == SavedForm::T_PROFILE; }); $grid->actionAdd(new Am_Grid_Action_Sort_SavedForm); $grid->setFilter(new Am_Grid_Filter_Text(___('Title/Comment/Code'), array( 'title' => 'LIKE', 'comment' => 'LIKE', 'code' => 'LIKE' ))); return $grid; } public function beforeSave(array & $values) { $fields = json_decode($values['fields'],true); foreach($fields as &$f) if(isset($f['labels'])) foreach($f['labels'] as $k=>$l) $f['labels'][$k] = preg_replace("/\r\n/","\n",$l); $values['fields'] = json_encode($fields); if (($values['type'] == 'signup') && !strlen($values['code'])) { $values['code'] = $this->getDi()->security->randomString(8); } } public function renderDefault(SavedForm $record, $field, $type) { $html = ""; if ($record->type == $type) { $checked = $record->isDefault($field) ? "checked='checked'" : ""; $html = sprintf('
', $this->getDi()->url('admin-saved-form/set-default'), $field, $record->saved_form_id, $checked); } return $this->renderTd($html, false); } public function renderSignupDefault(SavedForm $record, $field) { return $this->renderDefault($record, $field, SavedForm::T_SIGNUP); } public function renderProfileDefault(SavedForm $record, $field) { return $this->renderDefault($record, $field, SavedForm::T_PROFILE); } public function setDefaultAction() { foreach ($this->getRequest()->getPost('default') as $d => $id) $this->getDi()->savedFormTable->setDefault($d, $id); $this->_redirect('admin-saved-form'); } public function createForm() { $record = $this->grid->getRecord(); $post = $this->grid->getCompleteRequest()->getPost(); if (!$record->isLoaded()) { if ($type = $this->_request->getFiltered('type')) $record->type = $type; if ($record->type && empty($post['type'])) // form was not submitted yet $record->setDefaults(); } $form = new Am_Form_Admin_SavedForm($record); $form->addRule('callback', '-error-', array($this, 'validate')); return $form; } public function renderUrl(SavedForm $record) { $content = sprintf('%s', $record->getUrl(ROOT_URL . '/'), $record->getUrl("")); return $this->renderTd($content, false); } function validate(array $value) { /// check for unique code $el = $this->grid->getForm()->getElementById('code-0'); if ($el && strlen($code = $el->getValue())) { if ($id = $this->getDi()->db->selectCell("SELECT saved_form_id FROM ?_saved_form WHERE code=? AND saved_form_id<>?d AND type=?", $code, (int)@$value['_s_id'], $value['type'])) { $code = $this->escape($code); $el->setError(___('The code [%s] is already used by signup form #%s, please choose another code', $code, $id)); return false; } } return true; } }PK\lI:::(default/controllers/SignupController.phpnu[hook->call(Am_Event::LOAD_BRICKS); } parent::init(); } function loadForm() { if ($c = $this->getFiltered('c')) { if ($c == 'cart') { if ($this->_request->getParam('amember_redirect_url')) $this->getSession()->redirectUrl = $this->_request->getParam('amember_redirect_url'); if($this->getDi()->auth->getUser() != null) { $url = $this->getSession()->redirectUrl; $this->getSession()->redirectUrl = ''; $this->_redirect($url); } else { $this->record = $this->getDi()->savedFormTable->getByType(SavedForm::T_CART); } } else { $this->record = $this->getDi()->savedFormTable->findFirstBy(array( 'code' => $c, 'type' => SavedForm::T_SIGNUP, )); } } else { $this->record = $this->getDi()->savedFormTable->getDefault ( $this->getDi()->auth->getUserId() ? SavedForm::D_MEMBER : SavedForm::D_SIGNUP ); } // call a hook to allow load another form $event = new Am_Event(Am_Event::LOAD_SIGNUP_FORM, array( 'request' => $this->_request, 'user' => $this->getDi()->auth->getUser(), )); $event->setReturn($this->record); $this->getDi()->hook->call($event); $this->record = $event->getReturn(); if (!$this->record) { $this->getDi()->errorLogTable->log("Wrong signup form code - the form does not exists. Redirect Customer to default form. Referrer: " . $this->getRequest()->getHeader('REFERER')); $this->redirect('/signup', array('code'=>302)); } /* @var $this->record SavedForm */ if (!$this->record->isSignup()) throw new Am_Exception_InputError("Wrong signup form loaded [$this->record->saved_form_id] - it is not a signup form!"); if ($this->record->meta_title) $this->view->meta_title = $this->record->meta_title; if ($this->record->meta_keywords) $this->view->headMeta()->setName('keywords', $this->record->meta_keywords); if ($this->record->meta_description) $this->view->headMeta()->setName('description', $this->record->meta_description); if ($this->record->meta_robots) $this->view->headMeta()->setName('robots', $this->record->meta_robots); $this->view->code = $this->record->code; $this->view->record = $this->record; } function indexAction() { /* * First check user's login. user can be logged in plugin or user's login info can be in cookies. * Result does not matter here so skip it; */ if(!$this->getDi()->auth->getUserId() && $this->_request->isGet()) $this->getDi()->auth->checkExternalLogin($this->_request); /*==TRIAL_SPLASH==*/ if (!$this->getDi()->auth->getUserId() && $this->getDi()->config->get('signup_disable')) { $e = new Am_Exception_InputError(___('New Signups are Disabled')); $e->setLogError(false); throw $e; } $this->loadForm(); $this->view->title = $this->record->title; $this->form = new Am_Form_Signup(); $this->form->setParentController($this); $this->form->initFromSavedForm($this->record); try { $this->form->run(); } catch (Am_Exception_QuietError $e){ $e->setPublicTitle($this->record->title); throw $e; } } function display(Am_Form $form, $pageTitle) { $this->view->form = $form; $this->view->title = $pageTitle ?: $this->record->title; $this->view->display($this->record->tpl ? ('signup/' . basename($this->record->tpl)) : 'signup/signup.phtml'); } function autoLoginIfNecessary() { if (($this->getConfig('auto_login_after_signup') || ($this->record->type == SavedForm::T_CART)) && $this->user->isApproved()) { $this->user->refresh(); $adapter = new Am_Auth_Adapter_User($this->user); $this->getDi()->auth->login($adapter, $this->getRequest()->getClientIp(), false); } } function process(array $vars, $name, HTML_QuickForm2_Controller_Page $page) { $this->getDi()->hook->call(Am_Event::SIGNUP_PAGE_BEFORE_PROCESS, array( 'vars' => $vars, 'savedForm' => $this->record )); $this->vars = $vars; // do actions here $this->user = $this->getDi()->auth->getUser(); if ($this->getSession()->signup_member_id && $this->getSession()->signup_member_login) { $user = $this->getDi()->userTable->load((int)$this->getSession()->signup_member_id, false); if ($user && ((($this->getDi()->time - strtotime($user->added)) < 24*3600) && ($user->status == User::STATUS_PENDING))) { // prevent attacks as if someone has got ability to set signup_member_id to session if ($this->getSession()->signup_member_login == $user->login) { /// there is a potential problem /// because user password is not updated second time - @todo $this->user = $user; $this->autoLoginIfNecessary(); } else { $this->getSession()->signup_member_id = null; $this->getSession()->signup_member_login = null; } } else { $this->getSession()->signup_member_id = null; } } $event = new Am_Event(Am_Event::SIGNUP_LOAD_USER, array( 'vars' => $vars, 'savedForm' => $this->record )); $event->setReturn($this->user); $this->getDi()->hook->call($event); $this->user = $event->getReturn(); if (!$this->user) { $this->user = $this->getDi()->userRecord; $this->user->setForInsert($this->vars); // vars are filtered by the form ! if (empty($this->user->login)) $this->user->generateLogin(); if (empty($this->vars['pass'])) { $this->user->generatePassword(); } else { $this->user->setPass($this->vars['pass']); } if (empty($this->user->lang)) $this->user->lang = $this->getDi()->locale->getLanguage(); $this->user->saved_form_id = $this->record->pk(); $this->user->insert(); $this->getSession()->signup_member_id = $this->user->pk(); $this->getSession()->signup_member_login = $this->user->login; $this->autoLoginIfNecessary(); // user inserted $this->getDi()->hook->call(Am_Event::SIGNUP_USER_ADDED, array( 'vars' => $this->vars, 'user' => $this->user, 'form' => $this->form, 'savedForm' => $this->record )); if ($this->getDi()->config->get('registration_mail')) $this->user->sendRegistrationEmail(); if ($this->getDi()->config->get('registration_mail_admin')) $this->user->sendRegistrationToAdminEmail(); if(!$this->user->isApproved()) $this->user->sendNotApprovedEmail(); } else { if ($this->record->isCart()) { $url = $this->getSession()->redirectUrl; $this->getSession()->redirectUrl = ''; $this->_redirect($url ? urldecode($url) : $this->getDi()->url('cart',null,false), array('prependBase' => false)); } unset($this->vars['pass']); unset($this->vars['login']); unset($this->vars['email']); $this->user->setForUpdate($this->vars)->update(); // user updated $this->getDi()->hook->call(Am_Event::SIGNUP_USER_UPDATED, array( 'vars' => $this->vars, 'user' => $this->user, 'form' => $this->form, 'savedForm' => $this->record )); } // keep reference to e-mail confirmation link so it still working after signup if (!empty($this->vars['code'])) { $this->getDi()->store->setBlob(Am_Form_Signup_Action_SendEmailCode::STORE_PREFIX . $this->vars['code'], $this->user->pk(), '+7 days'); } if ($this->record->isCart()) { $url = $this->getSession()->redirectUrl; $this->getSession()->redirectUrl = ''; $this->_redirect($url ? urldecode($url) : $this->getDi()->url('cart',null,false), array('prependBase' => false)); return true; } /// now the ordering process $invoice = $this->getDi()->invoiceRecord; $invoice->saved_form_id = $this->record->pk(); $this->getDi()->hook->call(Am_Event::INVOICE_SIGNUP, array( 'vars' => $this->vars, 'user' => $this->user, 'form' => $this->form, 'invoice' => $invoice, 'savedForm' => $this->record )); $invoice->setUser($this->user); foreach ($this->vars as $k => $v) { if (strpos($k, 'product_id')===0) foreach ((array)$this->vars[$k] as $product_id) { @list($product_id, $plan_id, $qty) = explode('-', $product_id, 3); $product_id = (int)$product_id; if (!$product_id) continue; $p = $this->getDi()->productTable->load($product_id); if ($plan_id > 0) $p->setBillingPlan(intval($plan_id)); $qty = (int)$qty; if (!$p->getBillingPlan()->variable_qty || ($qty <= 0)) $qty = 1; $options = array(); if (!empty($this->vars['productOption']["$product_id-$plan_id"])) { $options = $this->vars['productOption']["$product_id-$plan_id"][0]; } $prOpt = $p->getOptions(true); foreach ($options as $k => $v) { $options[$k] = array('value' => $v, 'optionLabel' => $prOpt[$k]->title, 'valueLabel' => $prOpt[$k]->getOptionLabel($v)); } $invoice->add($p, $qty, $options); } } $event = new Am_Event(Am_Event::SIGNUP_INVOICE_ITEMS, array( 'vars' => $this->vars, 'form' => $this->form, 'invoice' => $invoice, 'savedForm' => $this->record )); $this->getDi()->hook->call($event); $invoice = $event->getReturn() ?: $invoice; if (!$invoice->getItems()) { $this->form->getSessionContainer()->destroy(); $this->_redirect('login'); return true; } if (!empty($this->vars['coupon'])) { $invoice->setCouponCode($this->vars['coupon']); $invoice->validateCoupon(); } $invoice->calculate(); $invoice->setPaysystem(isset($this->vars['paysys_id']) ? $this->vars['paysys_id'] : 'free'); $err = $invoice->validate(); if ($err) throw new Am_Exception_InputError($err[0]); if (!empty($this->vars['coupon']) && !(float)$invoice->first_discount && !(float)$invoice->second_discount) { $coupon = $this->getDi()->couponTable->findFirstByCode($this->vars['coupon']); $batch = $coupon->getBatch(); if ($batch->discount > 0) { $page = $this->form->findPageByElementName('coupon'); if (!$page) throw new Am_Exception_InternalError('Coupon brick is not found but coupon code presents in request'); list($el) = $page->getForm()->getElementsByName('coupon'); $el->setError(___('The coupon entered is not valid with any product(s) being purchased. No discount will be applied')); //now active datasource is datasource of current page //retrieve datasource for page with coupon element from //session and set it to form to populate it correctly $values = $page->getController()->getSessionContainer()->getValues($page->getForm()->getId()); $page->getForm()->setDataSources(array( new HTML_QuickForm2_DataSource_Array($values) )); $page->handle('display'); return false; } } $invoice->insert(); $this->getDi()->hook->call(Am_Event::INVOICE_BEFORE_PAYMENT_SIGNUP, array( 'vars' => $this->vars, 'form' => $this->form, 'invoice' => $invoice, 'savedForm' => $this->record )); try { $payProcess = new Am_Paysystem_PayProcessMediator($this, $invoice); $result = $payProcess->process(); } catch (Am_Exception_Redirect $e) { $this->form->getSessionContainer()->destroy(); $invoice->refresh(); if ($invoice->isCompleted()) { // relogin customer if free subscription was ok $this->autoLoginIfNecessary(); } throw $e; } // if we got back here, there was an error in payment! /** @todo offer payment method if previous failed */ $page = $this->form->findPageByElementName('paysys_id'); if (!$page) $page = $this->form->getFirstPage(); // just display first page foreach ($page->getForm()->getElementsByName('paysys_id') as $el) $el->setValue(null)->setError(current($result->getErrorMessages())); $page->handle('display'); return false; } function getCurrentUrl() { $c = $this->getFiltered('c'); return $this->_request->getScheme() . '://' . $this->_request->getHttpHost() . $this->_request->getBaseUrl() . '/' . $this->_request->getControllerName() . ($c ? "/$c" : ''); } public function getForm() { return $this->form; } }PK\Ҫ5,[,[Adefault/controllers/AdminImportWordpressMemberMouseController.phpnu[db_wordpress = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $order) { $this->user = $user; $this->order = $order; return $this->doWork(); } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='wmm:id'"); } return @$cache[$pid]; } protected function insertAccess($access, $invoice_id=null, $payment_id=null) { $a = $this->getDi()->accessRecord; $a->setDisableHooks(); $a->user_id = $this->user->user_id; $a->begin_date = $access['access_start_date']; $a->expire_date = $access['access_end_date']; if (!is_null($invoice_id)) { $a->invoice_id = $invoice_id; } if (!is_null($payment_id)) { $a->invoice_payment_id = $payment_id; } $a->product_id = $access['product_id']; $a->insert(); } } class InvoiceCreator_Paypal extends InvoiceCreator_Abstract { function doWork() { /*@var $product Product*/ if(!($product = Am_Di::getInstance()->productTable->load($this->_translateProduct($this->order['item_id']), false))) return; /*@var $invoice Invoice*/ $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $invoice->public_id = $this->order['iid']; /*@var $item InvoiceItem*/ $item = $invoice->createItem($product); $item->qty = $this->order['quantity']; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'paypal'; $invoice->tm_added = $this->order['date_added']; $invoice->tm_started = $this->order['date_added']; $invoice->calculate(); $invoice->insert(); $payments = $this->db_wordpress->select(" SELECT txn_id, subscr_id, received, txn_type, ipn_content FROM mm_paypal_ipn_log WHERE order_id = ?d AND (payment_status = ? OR txn_type = ?) ", $this->order['order_id'], 'Completed', 'subscr_cancel'); $cnt = 0; foreach ($payments as $p) { $invoice->data()->set('external_id', $p['subscr_id']); if($p['txn_type'] == 'subscr_cancel') { $invoice->tm_cancelled = $p['received']; $invoice->status = Invoice::RECURRING_CANCELLED; continue; } $data = unserialize($p['ipn_content']); $amount = ($a = $data['mc_gross']) ? $a : $data['payment_gross']; /*@var $payment InvoicePayment*/ $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $data['mc_currency']; $payment->amount = moneyRound($amount); $payment->paysys_id = 'paypal'; $payment->dattm = $p['received']; $payment->receipt_id = $p['subscr_id']; $payment->transaction_id = 'import-paypal-' . $p['txn_id']; $payment->insert(); // access $start = sqlDate($p['received']); $period = new Am_Period($cnt ? $invoice->second_period : $invoice->first_period); $expire = $period->addTo($start); $access = array( 'product_id' => $product->pk(), 'access_start_date' => $start, 'access_end_date' => $expire, ); $this->insertAccess($access, $invoice->pk(), $payment->pk()); $cnt++; } $invoice->update(); $this->user->checkSubscriptions(); } } class InvoiceCreator_AuthorizeCim extends InvoiceCreator_Abstract { function doWork() { /*@var $product Product*/ if(!($product = Am_Di::getInstance()->productTable->load($this->_translateProduct($this->order['item_id']), false))) return; /*@var $invoice Invoice*/ $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $invoice->public_id = $this->order['iid']; /*@var $item InvoiceItem*/ $item = $invoice->createItem($product); $item->qty = $this->order['quantity']; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'authorize-cim'; $invoice->tm_added = $this->order['date_added']; $invoice->tm_started = $this->order['date_added']; $invoice->calculate(); $invoice->insert(); $payments = $this->db_wordpress->select(" SELECT id, charge_id, amount, transaction_date FROM mm_authorizenet_cim_charges WHERE order_id = ?d ", $this->order['order_id']); $cnt = 0; foreach ($payments as $p) { /*@var $payment InvoicePayment*/ $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = moneyRound($p['amount']); $payment->paysys_id = 'authorize-cim'; $payment->dattm = $p['transaction_date']; $payment->receipt_id = $p['charge_id']; $payment->transaction_id = 'import-authorizecim-' . $p['charge_id']; $payment->insert(); $r = $this->db_wordpress->selectRow(" SELECT tl2.transaction_date, tl2.amount FROM mm_transaction_log tl1 LEFT JOIN mm_transaction_log tl2 ON tl1.refund_id = tl2.id WHERE tl1.payment_service_id = ?d AND tl1.payment_service_detail_id = ?d ", 3, $p['id']); // 3 - auth-cim if(!empty($r['transaction_date'])) { /*@var $refund InvoiceRefund*/ $refund = $this->getDi()->invoiceRefundRecord; $refund->invoice_id = $invoice->pk(); $refund->user_id = $this->user->pk(); $refund->paysys_id = $invoice->paysys_id; $refund->receipt_id = $refund->transaction_id = "refunded-" . $p['charge_id']; $refund->dattm = $r['transaction_date']; $refund->currency = $invoice->currency; $refund->amount = moneyRound($r['amount']); $refund->insert(); $invoice->updateQuick(array('tm_cancelled' => $r['transaction_date'], 'status' => Invoice::RECURRING_CANCELLED)); } else { $start = sqlDate($p['transaction_date']); $period = new Am_Period($cnt ? $invoice->second_period : $invoice->first_period); $expire = $period->addTo($start); $access = array( 'product_id' => $product->pk(), 'access_start_date' => $start, 'access_end_date' => $expire, ); $this->insertAccess($access, $invoice->pk(), $payment->pk()); } $cnt++; } $invoice->update(); $this->user->checkSubscriptions(); } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_wordpress; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_wordpress, array $options = array()) { $this->db_wordpress = $db_wordpress; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='wmm:id'"); $q = $this->db_wordpress->queryResultOnly("SELECT * FROM mm_products"); while ($r = $this->db_wordpress->fetchRow($q)) { if (in_array($r['id'], $importedProducts)) continue; $context++; $p = $this->getDi()->productRecord; $p->title = $r['name']; $p->description = $r['description']; $p->currency = $r['currency']; $p->is_disabled = $r['status'] ? 1 : 0; $p->data()->set('wmm:id', $r['id']); $p->insert(); /*@var $bp BillingPlan*/ $bp = $p->createBillingPlan(); $bp->title = 'default'; if($r['has_trial']) { $bp->first_price = moneyRound($r['trial_amount']); $bp->first_period = $this->parsePeriod($r['trial_duration'], $r['trial_frequency']); } else { $bp->first_price = moneyRound($r['price']); $bp->first_period = ($r['rebill_period'] && $r['rebill_frequency']) ? $this->parsePeriod($r['rebill_period'], $r['rebill_frequency']) : Am_Period::MAX_SQL_DATE; } if($r['rebill_period'] && $r['rebill_frequency']) { $bp->rebill_times = ($r['do_limit_payments']) ? $r['number_of_payments'] : IProduct::RECURRING_REBILLS; $bp->second_price = moneyRound($r['price']); $bp->second_period = $this->parsePeriod($r['rebill_period'], $r['rebill_frequency']); } $bp->insert(); } return true; } protected function parsePeriod($count, $unit) { $c = $count; switch ($unit) { case 'days': $u = 'd'; break; case 'weeks': $c *= 7; $u = 'd'; break; case 'months': $u = 'm'; break; case 'years': $u = 'y'; break; default : throw new Am_Exception_InputError("Unknown period unit [{$unit}]"); } return $c . $u; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { $maxImported = (int) $this->getDi()->db->selectCell(" SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='wmm:id' ORDER BY `id` DESC LIMIT 1 "); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_wordpress->queryResultOnly(" SELECT u.*, um1.meta_value as first_name, um2.meta_value as last_name, accl.authnet_customer_id, accl.authnet_payment_id FROM ?_users u LEFT JOIN ?_usermeta um1 on u.ID = um1.user_id and um1.meta_key = 'first_name' LEFT JOIN ?_usermeta um2 on u.ID = um2.user_id and um2.meta_key = 'last_name' LEFT JOIN mm_authorizenet_cim_customer_links accl on u.ID = accl.membermouse_customer_id WHERE u.ID > ?d ORDER BY u.ID {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_wordpress->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->email = $r['user_email']; $u->added = $r['user_registered']; $u->login = $r['user_login']; $u->name_f = (string)$r['first_name']; $u->name_l = (string)$r['last_name']; $u->is_approved = 1; $u->data()->set('wmm:id', $r['ID']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time if($cid = $r['authnet_customer_id']) $u->data()->set('authorize_cim_user_profile_id', $cid); if($pid = $r['authnet_payment_id']) $u->data()->set('authorize_cim_payment_profile_id', $pid); $u->pass = $r['user_pass']; try { $u->insert(); if($cid || $pid) { $storedCc = $this->getDi()->CcRecordRecord; $storedCc->user_id = $u->pk(); $storedCc->cc_expire = '1237'; $storedCc->cc_number = '0000000000000000'; $storedCc->cc = $storedCc->maskCc($storedCc->cc_number); $storedCc->insert(); } $this->insertPayments($r['ID'], $u); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
\n"; } } return true; } function insertPayments($id, User $u) { $orders = $this->db_wordpress->select(" SELECT o.id as order_id, o.order_number as iid, o.payment_id, o.date_added, oi.item_id, oi.quantity FROM mm_orders o LEFT JOIN mm_order_items oi ON oi.order_id=o.id WHERE oi.item_id > 0 AND o.payment_id IN (?a) AND o.user_id = ?d ", array(1,3), $id); foreach ($orders as $order) { switch ($order['payment_id']) { case 1: InvoiceCreator_Abstract::factory('paypal', $this->db_wordpress)->process($u, $order); break; case 3: InvoiceCreator_Abstract::factory('authorize-cim', $this->db_wordpress)->process($u, $order); break; default: break; } } } } class AdminImportWordpressMemberMouseController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_wordpress; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->wordpress_db = null; $this->getSession()->wordpress_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->wordpress_import = null; } if (!$this->getSession()->wordpress_db) return $this->askDbSettings(); $this->db_wordpress = Am_Db::connect($this->getSession()->wordpress_db); if (!$this->getSession()->wordpress_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->wordpress_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_wordpress, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from Wordpress Member Mouse Plugin"; $this->view->content .= "

Continue to import other information"; $this->view->content .= "

Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->wordpress_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-wordpress-member-mouse", array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->wordpress_import = array( 'import' => $val['import'], 'user' => @$val['user'], 'pr_link' => @$val['pr_link'], ); $this->_redirect('admin-import-wordpress-member-mouse'); return; } } $this->view->title = "Import Wordpress Member Mouse Plugin Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='wmm:id'"); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM mm_products"); if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); if ($imported_products) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='wmm:id'"); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

"); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

# of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->wordpress_db = $this->form->getValue(); $this->_redirect('admin-import-wordpress-member-mouse'); } else { $this->view->title = "Import Wordpress Membership Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('Wordpress MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('Wordpress MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('Wordpress MySQL Password'); $form->addText('db')->setLabel('Wordpress MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('Wordpress Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'wp_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_users LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } PK\**default/controllers/SendpassController.phpnu[getFiltered(self::SECURITY_VAR)) { if ($this->checkCode($code, $user)) { $this->doChangePass($user, $code); } else { throw new Am_Exception_InputError(___('Security code is either invalid or expired')); } } else { $this->doSend(); } } public function doSend() { $res = array(); if (Am_Recaptcha::isConfigured() && $this->getDi()->config->get('recaptcha')) { $res['recaptcha_key'] = $this->getDi()->recaptcha->getPublicKey(); } do { if (Am_Recaptcha::isConfigured() && $this->getDi()->config->get('recaptcha') && !$this->getDi()->recaptcha->validate($this->getParam('g-recaptcha-response'))) { $ok = false; $text = ___('Anti Spam check failed'); break; } $login = trim($this->getParam('login')); $user = $this->getDi()->userTable->findFirstByLogin($login); if (!$user) $user = $this->getDi()->userTable->findFirstByEmail($login); if (!$user) { $title = ___('Lost Password Sending Error'); $text = ___('The information you have entered is incorrect. ' . 'Username [%s] does not exist in database', $this->getEscaped('login')); $ok = false; break; } if ($error = $this->checkLimits($user)) { $title = ___('Lost Password Sending Error'); $text = $error; $ok = false; break; } $this->sendSecurityCode($user); $title = ___('Lost Password Sent'); $text = ___('Your password has been e-mailed to you. ' . 'Please check your mailbox'); $ok = true; } while (false); if ($this->_request->isXmlHttpRequest()) { $res['ok'] = $ok; $res['error'] = array($text); return $this->_response->ajaxResponse($res); } $this->view->title = $title; $this->view->content = $text; $this->view->display('layout.phtml'); } public function doChangePass(User $user, $code) { $form = $this->createForm(); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( self::SECURITY_VAR => $code, 'login' => $user->login ))); if ($form->isSubmitted() && $form->validate()) { $user->setPass($this->getParam('pass0')); $user->save(); $this->getDi()->store->delete(self::STORE_PREFIX . $code); $msg = ___('Your password has been changed successfully. ' . 'You can %slogin to your account%s with new password.', sprintf('', $this->getDi()->url('login')), ''); $this->view->title = ___('Change Password'); $this->view->content = <<$msg
CUT; $this->view->display('layout.phtml'); } else { $this->view->form = $form; $this->view->display('changepass.phtml'); } } protected function createForm() { $form = new Am_Form(); $form->addCsrf(); $form->addText('login', array('disabled'=>'disabled')) ->setLabel(___('Username')); $pass0 = $form->addPassword('pass0') ->setLabel(___('New Password')); $pass0->addRule('minlength', ___('The password should be at least %d characters long', $this->getDi()->config->get('pass_min_length', 4)), $this->getDi()->config->get('pass_min_length', 4)); $pass0->addRule('maxlength', ___('Your password is too long'), $this->getDi()->config->get('pass_max_length', 32)); $pass0->addRule('required', 'This field is required'); if ($this->getDi()->config->get('require_strong_password')) { $pass0->addRule('regex', ___('Password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars'), $this->getDi()->userTable->getStrongPasswordRegex()); } $pass1 = $form->addPassword('pass1') ->setLabel(___('Confirm Password')); $pass1->addRule('eq', ___('Passwords do not match'), $pass0); $form->addHidden(self::SECURITY_VAR); $form->addSaveButton(___('Change Password')); return $form; } protected function checkLimits(User $user) { // Check limits by email. $attempt = $this->getDi()->store->get('remind-password_' . $user->email); if ($attempt>=2) { return ___('The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying'); } $this->getDi()->store->set('remind-password_' . $user->email, ++$attempt, '+3 hours'); // Check limits by IP address. $attempt_ip = $this->getDi()->store->get('remind-password_ip_' . $this->getRequest()->getClientIp(true)); if ($attempt_ip>=5) { return ___('Too many Lost Password requests. Please wait 180 minutes for retrying'); } $this->getDi()->store->set('remind-password_ip_' . $this->getRequest()->getClientIp(true), ++$attempt_ip, '+3 hours'); } protected function checkCode($code, &$user) { $data = $this->getDi()->store->get(self::STORE_PREFIX . $code); if (!$data) return false; list($user_id, $pass, $email) = explode('-', $data, 3); $user = $this->getDi()->userTable->load($user_id); if ($user->pass != $pass || $user->email != $email) return false; return true; } protected function sendSecurityCode(User $user) { $security_code = $this->getDi()->security->randomString(16); $et = Am_Mail_Template::load('send_security_code', $user->lang, true); $et->setUser($user); $et->setUrl(sprintf('%s/sendpass?%s=%s', ROOT_SURL, self::SECURITY_VAR, $security_code) ); $et->setHours(self::EXPIRATION_PERIOD); $et->send($user); $data = array( $user->pk(), $user->pass, $user->email ); $this->getDi()->store->set(self::STORE_PREFIX . $security_code, implode('-', $data), '+'.self::EXPIRATION_PERIOD.' hours'); } } PK\#3XTXTDdefault/controllers/AdminImportWordpressOptimizeMemberController.phpnu[db_wordpress = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $r) { $times = unserialize($r['wp_optimizemember_paid_registration_times']); $max = max($times); foreach ($times as $level => $time) { if(!($pid = $this->_translateProduct($level))) continue; $bpId = Am_Di::getInstance()->productTable->load($pid)->default_billing_plan_id; $fisrtPeriod = Am_Di::getInstance()->billingPlanTable->load($bpId)->first_period; $period = new Am_Period($fisrtPeriod); $this->payment[$pid] = array( 'start' => sqlTime($time), 'stop' => $period->addTo(sqlTime($time)) ); if($time == $max) { $lastProduct = $pid; } } $this->payment[$lastProduct]['subscr_id'] = $r['wp_optimizemember_subscr_id']; $this->user = $user; return $this->doWork(); } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='wom:id'"); } return @$cache[$pid]; } protected function insertAccess($access, $invoice_id=null, $payment_id=null) { $a = $this->getDi()->accessRecord; $a->user_id = $this->user->user_id; $a->setDisableHooks(); $a->begin_date = $access['access_start_date']; $a->expire_date = $access['access_end_date']; if (!is_null($invoice_id)) { $a->invoice_id = $invoice_id; } if (!is_null($payment_id)) { $a->invoice_payment_id = $payment_id; } $a->product_id = $access['product_id']; $a->insert(); } } class InvoiceCreator_Manual extends InvoiceCreator_Abstract { function doWork() { foreach ($this->payment as $pid => $arr) { $access = array( 'product_id' => $pid, 'access_start_date' => $arr['start'], 'access_end_date' => $arr['stop'], ); $this->insertAccess($access); } $this->user->checkSubscriptions(); } } class InvoiceCreator_Paypal extends InvoiceCreator_Abstract { function doWork() { foreach ($this->payment as $pid => $arr) { if(empty($arr['subscr_id'])) { $access = array( 'product_id' => $pid, 'access_start_date' => $arr['start'], 'access_end_date' => $arr['stop'], ); $this->insertAccess($access); } else { $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($pid)); $item->qty = 1; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'paypal'; $invoice->tm_added = $arr['start']; $invoice->tm_started = $arr['start']; $invoice->calculate(); $invoice->data()->set('external_id', $arr['subscr_id']); $invoice->insert(); $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = $invoice->first_total; $payment->paysys_id = 'paypal'; $payment->dattm = $arr['start']; $payment->receipt_id = $arr['subscr_id']; $payment->transaction_id = 'import-paypal-' . mt_rand(10000, 99999); $payment->insert(); $access = array( 'product_id' => $pid, 'access_start_date' => $arr['start'], 'access_end_date' => $arr['stop'], ); $this->insertAccess($access, $invoice->pk(), $payment->pk()); } } $this->user->checkSubscriptions(); } } class InvoiceCreator_Stripe extends InvoiceCreator_Abstract { function doWork() { foreach ($this->payment as $pid => $arr) { if(empty($arr['subscr_id'])) { $access = array( 'product_id' => $pid, 'access_start_date' => $arr['start'], 'access_end_date' => $arr['stop'], ); $this->insertAccess($access); } else { $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($pid)); $item->qty = 1; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'stripe'; $invoice->tm_added = $arr['start']; $invoice->tm_started = $arr['start']; $invoice->calculate(); $invoice->data()->set('stripe_token', $arr['subscr_id']); $invoice->insert(); $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = $invoice->first_total; $payment->paysys_id = 'paypal'; $payment->dattm = $arr['start']; $payment->receipt_id = $arr['subscr_id']; $payment->transaction_id = 'import-paypal-' . mt_rand(10000, 99999); $payment->insert(); $access = array( 'product_id' => $pid, 'access_start_date' => $arr['start'], 'access_end_date' => $arr['stop'], ); $this->insertAccess($access, $invoice->pk(), $payment->pk()); } } $this->user->checkSubscriptions(); } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_wordpress; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_wordpress, array $options = array()) { $this->db_wordpress = $db_wordpress; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='wom:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_wordpress->queryResultOnly(" SELECT u.*, um1.meta_value as first_name, um2.meta_value as last_name, um3.meta_value as wp_optimizemember_subscr_gateway, um4.meta_value as wp_optimizemember_subscr_id, um5.meta_value as wp_optimizemember_paid_registration_times FROM ?_users u LEFT JOIN ?_usermeta um1 on u.ID = um1.user_id and um1.meta_key = 'first_name' LEFT JOIN ?_usermeta um2 on u.ID = um2.user_id and um2.meta_key = 'last_name' LEFT JOIN ?_usermeta um3 on u.ID = um3.user_id and um3.meta_key = 'wp_optimizemember_subscr_gateway' LEFT JOIN ?_usermeta um4 on u.ID = um4.user_id and um4.meta_key = 'wp_optimizemember_subscr_id' LEFT JOIN ?_usermeta um5 on u.ID = um5.user_id and um5.meta_key = 'wp_optimizemember_paid_registration_times' WHERE u.ID > ?d ORDER BY u.ID {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_wordpress->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->email = $r['user_email']; $u->added = $r['user_registered']; $u->login = $r['user_login']; $u->name_f = (string)$r['first_name']; $u->name_l = (string)$r['last_name']; $u->is_approved = 1; $u->data()->set('wom:id', $r['ID']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time $u->pass = $r['user_pass']; if(@$this->options['keep_user_id']){ $u->disableInsertPkCheck(true); $u->user_id = $r['ID']; } try { if(@$this->options['keep_user_id']) $u->insert(false)->refresh(); else $u->insert(); if($r['wp_optimizemember_subscr_gateway']) { InvoiceCreator_Abstract::factory($r['wp_optimizemember_subscr_gateway'], $this->db_wordpress)->process($u, $r); }elseif ($r['wp_optimizemember_paid_registration_times']) { InvoiceCreator_Abstract::factory('Manual', $this->db_wordpress)->process($u, $r); } $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
\n"; } } return true; } } class AdminImportWordpressOptimizeMemberController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_wordpress; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->wordpress_db = null; $this->getSession()->wordpress_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->wordpress_import = null; } if (!$this->getSession()->wordpress_db) return $this->askDbSettings(); $this->db_wordpress = Am_Db::connect($this->getSession()->wordpress_db); if (!$this->getSession()->wordpress_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->wordpress_import; $import = $this->_request->getFiltered('i', $importSettings['import']); if($import == 'product') { foreach ($importSettings['pr_link'] as $wom => $am) { if($am) { $this->getDi()->productTable->load($am)->data()->set('wom:id', $wom)->update(); $done++; } } $this->view->title = "Product Linking Finished"; $this->view->content = "$done records linked from Wordpress Optimize Member Plugin"; $this->view->content .= "

Continue to import other information"; $this->view->display('admin/layout.phtml'); $this->getSession()->wordpress_import = null; return; } $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_wordpress, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from Wordpress Optimize Member Plugin"; $this->view->content .= "

Continue to import other information"; $this->view->content .= "

Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->wordpress_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-wordpress-optimize-member", array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->wordpress_import = array( 'import' => $val['import'], 'user' => @$val['user'], 'pr_link' => @$val['pr_link'], ); $this->_redirect('admin-import-wordpress-optimize-member'); return; } } $this->view->title = "Import Wordpress Optimize Member Plugin Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='wom:id'"); $wopCfg = $this->db_wordpress->selectCell("SELECT option_value FROM ?_options WHERE option_name = ?", 'ws_plugin__optimizemember_options'); $wopCfg = unserialize($wopCfg); if(is_array($wopCfg)) { $amProducts = array('' => '-- Please Select --') + $this->getDi()->productTable->getOptions(); $womProducts = array(); for($i = 0; $i <= 10; $i++) { $womProducts['level' . ($i ? $i : '')] = $wopCfg['level' . $i . '_label']; } if ($imported_products) { $cb = $form->addStatic()->setContent("Linked"); } else { $cb = $form->addRadio('import', array('value' => 'product')); foreach ($womProducts as $key => $value) { $form->addSelect("pr_link[" . $key . "]") ->setLabel($value) ->loadOptions($amProducts); } $form->addRule('callback2', '-error-', array($this, 'validateForm')); } $cb->setLabel('Link Products'); } if (!is_array($wopCfg) || $imported_products) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='wom:id'"); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

"); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

# of users (keep empty to import all) '); $cb->addInteger('user[count]'); $cb->addStatic()->setContent('
Keep the same user IDs'); $keep_id_chkbox = $cb->addCheckbox('user[keep_user_id]'); if($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_user")){ $keep_id_chkbox->setAttribute('disabled'); $cb->addStatic() ->setContent('User database have records already. Please use Clean Up if you want to keep the same user IDs'); } } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } public function validateForm($vars) { if($vars['import'] == 'product') foreach ($vars['pr_link'] as $v) if($v) return null; return "It's required to link Wordpress Optimize Member products with aMember products"; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->wordpress_db = $this->form->getValue(); $this->_redirect('admin-import-wordpress-optimize-member'); } else { $this->view->title = "Import Wordpress Membership Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('Wordpress MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('Wordpress MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('Wordpress MySQL Password'); $form->addText('db')->setLabel('Wordpress MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('Wordpress Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'wp_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_users LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } PK\Lx%%)default/controllers/ProfileController.phpnu[hook->call(Am_Event::LOAD_BRICKS); } parent::init(); } function preDispatch() { if ($this->getRequest()->getActionName() != 'confirm-email') { $this->getDi()->auth->requireLogin($this->getDi()->url('profile',null,false)); $this->user = $this->getDi()->userTable->load($this->getDi()->auth->getUserId()); $this->view->assign('user', $this->user->toArray()); $this->user_id = $this->user->user_id; } } function emailChangesToAdmin() { if(!$this->getDi()->config->get('profile_changed',0)) return; $changes = ''; $olduser = $this->getDi()->userTable->load($this->user->user_id)->toArray(); foreach($this->user->toArray() as $k => $v){ if($k=='pass') continue; if(($o=$olduser[$k])!=$v) { is_scalar($o) || ($o = serialize($o)); is_scalar($v) || ($v = serialize($v)); $changes.="- $k: $o\n"; $changes.="+ $k: $v\n"; } } if(!strlen($changes)) return; $et = Am_Mail_Template::load('profile_changed'); $et->setChanges($changes); $et->setUser($this->user); $et->sendAdmin(); } function indexAction() { $this->form = new Am_Form_Profile(); $this->form->addCsrf(); if ($c = $this->getFiltered('c')) { $record = $this->getDi()->savedFormTable->findFirstBy(array( 'code' => $c, 'type' => SavedForm::T_PROFILE, )); } else { $record = $this->getDi()->savedFormTable->getDefault(SavedForm::D_PROFILE); } $event = new Am_Event(Am_Event::LOAD_PROFILE_FORM, array( 'request' => $this->_request, 'user' => $this->getDi()->auth->getUser(), )); $event->setReturn($record); $this->getDi()->hook->call($event); $record = $event->getReturn(); if (!$record) throw new Am_Exception_Configuration("No profile form configured"); if ($record->meta_title) $this->view->meta_title = $record->meta_title; if ($record->meta_keywords) $this->view->headMeta()->setName('keywords', $record->meta_keywords); if ($record->meta_description) $this->view->headMeta()->setName('description', $record->meta_description); if ($record->meta_robots) $this->view->headMeta()->setName('robots', $record->meta_robots); $this->view->code = $record->code; $this->view->record = $record; $this->form->initFromSavedForm($record); $this->form->setUser($this->user); $u = $this->user->toArray(); unset($u['pass']); $dataSources = array( new HTML_QuickForm2_DataSource_Array($u) ); if ($this->form->isSubmitted()) { array_unshift($dataSources, $this->_request); } $this->form->setDataSources($dataSources); if ($this->form->isSubmitted() && $this->form->validate()) { $oldUser = clone $this->user; $oldUser->toggleFrozen(true); $vars = $this->form->getValue(); unset($vars['user_id']); if (!empty($vars['pass'])) $this->user->setPass($vars['pass']); unset($vars['pass']); $ve = $this->handleEmail($record, $vars) ? 1 : 0; $u = $this->user->setForUpdate($vars); $this->emailChangesToAdmin(); $u->update(); $this->getDi()->hook->call(Am_Event::PROFILE_USER_UPDATED, array( 'vars' => $vars, 'oldUser' => $oldUser, 'user' => $u, 'form' => $this->form, 'savedForm' => $record )); $this->getDi()->auth->setUser($u); $msg = $ve ? ___('Verification email has been sent to your address. E-mail will be changed in your account after confirmation') : ___('Your profile has been updated successfully'); return $this->_response->redirectLocation($this->_request->assembleUrl(false,true) . '?_msg='. urlencode($msg)); } $this->view->title = $record->title; $this->view->form = $this->form; $this->view->display('member/profile.phtml'); } public function confirmEmailAction() { $di = $this->getDi(); /* @var $user User */ $em = $this->getRequest()->getParam('em'); list($user_id, $code) = explode('-', $em); if (!$user_id = $this->getDi()->security->reveal($user_id)) { throw new Am_Exception_InputError(___('Link is either expired or invalid')); } $data = $this->getDi()->store->getBlob(self::SECURITY_CODE_STORE_PREFIX . $user_id); if (!$data) { throw new Am_Exception_InputError(___('Security code is invalid')); } $data = unserialize($data); $user = $this->getDi()->userTable->load($user_id); if ($user && //user exist $data['security_code'] && //security code exist ($data['security_code'] == $code)) {//security code is valid $form = new Am_Form; $form->addCsrf(); $form->addHidden('em')->setValue($this->getRequest()->getParam('em')); $form->addHtml() ->setHtml(Am_Html::escape($user->login)) ->setLabel(___('Username')); $form->addHtml() ->setHtml(Am_Html::escape($data['email'])) ->setLabel(___('New Email')); $form->addPassword('_pass') ->setLabel("Password\nplease enter your password to confirm email change") ->addRule('required') ->addRule('callback2', null, function($v) use ($user, $di) { $protector = new Am_Auth_BruteforceProtector( $di->db, $di->config->get('protect.php_include.bruteforce_count', 5), $di->config->get('protect.php_include.bruteforce_delay', 120), Am_Auth_BruteforceProtector::TYPE_USER); if ($wait = $protector->loginAllowed($_SERVER['REMOTE_ADDR'])) { return ___('Please wait %d seconds before next attempt', $wait); } if (!$user->checkPassword($v)) { $protector->reportFailure($_SERVER['REMOTE_ADDR']); return ___('Current password entered incorrectly, please try again'); } }); $form->addSaveButton(___('Confirm')); if ($form->isSubmitted() && $form->validate()) { $user->email = $data['email']; $user->save(); $this->getDi()->store->delete(self::SECURITY_CODE_STORE_PREFIX . $user_id); $url = $this->getUrl('member', 'index'); $this->_response->redirectLocation($url); } else { $this->view->title = ___('Email change confirmation'); $this->view->layoutNoMenu = true; $this->view->content = (string) $form; $this->view->display('layout.phtml'); } } else { throw new Am_Exception_FatalError(___('Security code is invalid')); } } protected function handleEmail(SavedForm $form, & $vars) { /* @var $user User */ $user = $this->user; $bricks = $form->getBricks(); foreach ($bricks as $brick) { if ($brick->getClass() == 'email' && $brick->getConfig('validate') && $vars['email'] != $user->email) { $code = $this->getDi()->security->randomString(self::EMAIL_CODE_LEN); $data = array( 'security_code' => $code, 'email' => $vars['email'] ); $this->getDi()->store->setBlob( self::SECURITY_CODE_STORE_PREFIX . $this->user_id, serialize($data), sqlTime(Am_Di::getInstance()->time + self::SECURITY_CODE_EXPIRE * 3600) ); $tpl = Am_Mail_Template::load('verify_email_profile', get_first($user->lang, Am_Di::getInstance()->app->getDefaultLocale(false)), true); $cur_email = $user->email; $user->email = $vars['email']; $tpl->setUser($user); $tpl->setCode($code); $tpl->setUrl( $this->getDi()->url('profile/confirm-email', array('em'=>$this->getDi()->security->obfuscate($user->pk()) . '-' . $code) , false, true) ); $tpl->send($user); $user->email = $cur_email; unset($vars['email']); return true; } } return false; } }PK\۞ )default/controllers/ContentController.phpnu[_helper->addHelper($v); } /** * Serve file download */ function fAction() { $f = $this->loadWithAccessCheck($this->getDi()->fileTable, $id = $this->getInt('id')); // download limits works for user access only and not for guest access if ($this->getDi()->auth->getUserId()) { if (!$this->getDi()->fileDownloadTable->checkLimits($this->getDi()->auth->getUser(), $f)) { throw new Am_Exception_AccessDenied(___('Download limit exceeded for this file')); } $this->getDi()->fileDownloadTable->logDownload($this->getDi()->auth->getUser(), $f, $this->getRequest()->getClientIp()); } if ($path = $f->getFullPath()) { @ini_set('zlib.output_compression', 'Off'); // for IE $this->_helper->sendFile($path, $f->getMime(), array( //'cache'=>array('max-age'=>3600), 'filename' => $f->getDisplayFilename(), 'file_id' => $f->pk() )); } else $this->_response->redirectLocation($f->getProtectedUrl(600)); } /** * Display saved page */ function pAction() { $page = ($path = $this->getParam('path')) ? $this->getDi()->pageTable->findFirstByPath($path): null; $p = $this->loadWithAccessCheck($this->getDi()->pageTable, $page ? $page->pk() : $this->getInt('id')); if ($mp = $this->getDi()->navigationUser->findOneById("page-{$p->pk()}")) { $mp->setActive(true); } echo $p->render($this->view, $this->getDi()->auth->getUserId() ? $this->getDi()->auth->getUser() : null, !$this->getRequest()->isXmlHttpRequest()); } /** * Display allowed content within category * */ function cAction() { if (!$this->getDi()->auth->getUserId()) { $this->_redirect('login?amember_redirect_url=' . urlencode($this->_request->assembleUrl(false,true))); } /* @var $cat ResourceCategory */ $cat = $this->getDi()->resourceCategoryTable->load($this->getParam('id')); if ($this->getParam('title') != $cat->title) { throw new Am_Exception_InputError; } $this->view->resources = $cat->getAllowedResources($this->getDi()->user); $this->view->category = $cat; $this->view->display('member/category.phtml'); } function loadWithAccessCheck(ResourceAbstractTable $table, $id) { if ($id<=0) throw new Am_Exception_InputError(___('Wrong link - no id passed')); $p = $table->load($id); if (!$this->getDi()->auth->getUserId()) // not logged-in { if ($p->hasAccess(null)) // guest access allowed? return $p; // then process $this->_redirect('login?amember_redirect_url=' . urlencode($this->_request->assembleUrl(false, true))); } if (!$p->hasAccess($this->getDi()->user)) { if(!empty($p->no_access_url)) $this->_redirect($p->no_access_url); else $this->_redirect('no-access/content/'.sprintf('?id=%d&type=%s', $id, $table->getName(true))); } return $p; } }PK\@@2default/controllers/AdminPluginMakerController.phpnu[isSuper(); } public function getSession() { if (empty($this->session)) $this->session = new Zend_Session_Namespace('amember_plugin_maker'); return $this->session; } function indexAction() { $controller = new HTML_QuickForm2_Controller('plugin_maker'); $controller->addPage(new Am_Form_Controller_Page_PluginMaker_Mysql(new Am_Form('mysql'))); $controller->addPage(new Am_Form_Controller_Page_PluginMaker_Plugin(new Am_Form('plugin'))); $controller->addPage(new Am_Form_Controller_Page_PluginMaker_Tables(new Am_Form('tables'))); $controller->addPage(new Am_Form_Controller_Page_PluginMaker_Columns(new Am_Form('columns'))); $controller->addPage(new Am_Form_Controller_Page_PluginMaker_Display(new Am_Form('display'))); $controller->addHandler('next', new HTML_QuickForm2_Controller_Action_Next()); $controller->addHandler('back', new HTML_QuickForm2_Controller_Action_Back()); $controller->addHandler('jump', new HTML_QuickForm2_Controller_Action_Jump()); ob_start(); $controller->run(); $this->view->content = ob_get_clean(); $this->view->title = "Integration Plugin Maker"; $this->view->display('admin/layout.phtml'); } function getMysqlInfo() { $this->getSession()->unsetAll(); $form = $this->createMysqlForm(); if (!$form->isSubmitted() || !$form->validate()) { $this->view->content = (string)$form; } else { $this->getSession()->info = $form->getValue(); return $this->selectTables(); } } function selectColumns() { $tables = $this->getSession()->tables; $db = $this->getDb(); $db->setPrefix($tables['prefix']); // user table if (!$tables['user']) throw new Am_Exception_InputError("No user table selected"); $cols = $this->getDi()->db->selectCol("SHOW COLUMNS FROM ?_{$tables['user']}"); $out = "

Select Tables Field Mapping

"; $out .= "

User Table

"; $out .= ""; foreach ($cols as $c) { $out .= ""; } $out .= ""; foreach ($db->select("SELECT * FROM ?_{$tables['user']}") as $r) { $out .= ""; foreach ($r as $c => $v) $out .= "\n"; $out .= "\n"; } $out .= "
$c
" . Am_Html::escape($v) . "
\n"; } function selectTables() { if ($this->_getParam('tables') == 1) { $tables = array( 'user' => $this->_getParam('user'), 'group' => $this->_getParam('group'), 'usergroup' => $this->_getParam('usergroup'), 'prefix' => $this->_getParam('prefix') ); $tables['user'] = preg_replace('/^' . preg_quote($tables['prefix']) . '/', '', $tables['user']); $tables['group'] = preg_replace('/^' . preg_quote($tables['prefix']) . '/', '', $tables['group']); $tables['usergroup'] = preg_replace('/^' . preg_quote($tables['prefix']) . '/', '', $tables['usergroup']); $this->getSession()->tables = $tables; return $this->selectColumns(); } $out .= "
"; $out .= "\n"; $this->view->content = $out; } function getDb(array $info = null) { if (empty($info)) $info = $this->getSession()->info; if (empty($this->db)) $this->db = Am_Db::connect($info); return $this->db; } } class Am_Form_Controller_Page_PluginMaker_Display extends HTML_QuickForm2_Controller_Page { protected function populateForm() { $info = $this->getController()->getValue(); foreach ($info as $k=>$v) if ($k[0] == '_') unset($info[$k]); if (@$info['table_prefix']) foreach ($info['table'] as & $v) $v = preg_replace('/^'.preg_quote($info['table_prefix']).'/', '', $v); $userFields = array(); $guessFields = array(); foreach ($info['field']['user'] as $fn => $a) { if (empty($a['field'])) continue; $guessFields[] = $fn; $expr = $a['field']; if ($expr == 'string') $expr = var_export(':'.$a['text'], true); elseif ($expr == 'expr') $expr = '"!'.$a['text'].'"'; $userFields[] = "array($expr, '$fn'),"; } $view = new Am_View(); $view->assign($info); $view->assign('guessFields', $guessFields); $view->assign('userFields', $userFields); $cnt = "

Plugin Template Generated

"; $cnt .= "Put the following code to application/default/plugins/protect/{$info['plugin']}.php and start customization"; $cnt .= "
\n"; $cnt .= highlight_string($view->render('admin/plugin-template.phtml'), true); $cnt .= "
"; $el = $this->form->addStatic(null, array('class'=>'no-label'))->setContent($cnt); $gr = $this->form->addGroup(null, array('class' => 'no-label', 'style' => 'text-align:center')); $gr->addSubmit($this->getButtonName('back'), array('value'=>'Back')); $page = $this; while ($p = $page->getController()->previousPage($page)) $page = $p; $gr->addSubmit($page->getButtonName('jump'), array('value'=>'Start Over')); } } class Am_Form_Controller_Page_PluginMaker_Mysql extends HTML_QuickForm2_Controller_Page { protected function populateForm() { $this->getController()->destroySessionContainer(); $this->form->addStatic('Enter third-party plugin database connection details'); $this->form->addText('host')->setLabel('MySQL Hostname')->addRule('required'); $this->form->addText('port')->setLabel('MySQL Port'); $this->form->addText('user')->setLabel('MySQL Username')->addRule('required'); $this->form->addPassword('pass')->setLabel('MySQL Password'); $this->form->addText('db')->setLabel('MySQL Database')->addRule('required'); $this->form->addSubmit($this->getButtonName('next'), array('value'=>'Next')); $this->form->addRule('callback2', '-', array($this, 'validateMysql')); $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array(array('port' => 3606))); } function validateMysql(array $info) { try { Am_Db::connect($info); } catch (Am_Exception_Db $e) { return "Wrong info: " . $e->getMessage(); } } } class Am_Form_Controller_Page_PluginMaker_Plugin extends HTML_QuickForm2_Controller_Page { protected function populateForm() { $this->form->addText('plugin')->setLabel('Plugin Id') ->addRule('required') ->addRule('regex', 'Must match regex /[a-z][a-z0-9-]+/', '/^[a-z][a-z0-9-]+$/'); $sel = $this->form->addSelect('password_type')->setLabel('Password Type'); $sel->addOption('-- Select --', ''); $sel->addRule('required'); $class = new ReflectionClass('SavedPassTable'); foreach ($class->getConstants() as $k => $v) if (strpos($k, 'PASSWORD')===0) $sel->addOption('SavedPassTable::'.$k . ' ('.$v.')', 'SavedPassTable::'.$k); $sel->addOption('Custom (define method)', 'custom'); $sel = $this->form->addSelect('group_mode')->setLabel('Group Mode'); $sel->addOption('-- Select --', ''); $sel->addRule('required'); $class = new ReflectionClass('Am_Protect_Databased'); foreach ($class->getConstants() as $k => $v) if (strpos($k, 'GROUP_')===0) $sel->addOption($class->getName().'::'.$k, $class->getName().'::'.$k); $gr = $this->form->addGroup(null, array('class' => 'no-label', 'style' => 'text-align:center')); $gr->addSubmit($this->getButtonName('back'), array('value'=>'Start Over')); $gr->addSubmit($this->getButtonName('next'), array('value'=>'Next')); } } class Am_Form_Controller_Page_PluginMaker_Tables extends HTML_QuickForm2_Controller_Page { protected function populateForm() { $info = $this->getController()->getValue(); $db = Am_Db::connect($info); $tables = $db->selectCol("SHOW TABLES"); $tables = array_merge(array('' => '-- Select --'), array_combine($tables, $tables)); $this->form->addSelect('table[user]')->setLabel('User Table') ->loadOptions($tables)->addRule('required'); if ($info['group_mode'] != 'Am_Protect_Databased::GROUP_NONE') { $this->form->addSelect('table[group]')->setLabel('Groups Table') ->loadOptions($tables)->addRule('required'); if ($info['group_mode'] != 'Am_Protect_Databased::GROUP_SINGLE') $this->form->addSelect('table[usergroup]')->setLabel('User<->Group Relation Table (optional)') ->loadOptions($tables); } $this->form->addSelect('table[session]')->setLabel('Session Storage Table (optional)') ->loadOptions($tables); $prefixes = $this->findPrefixes($tables); $options = @array_merge(array('' => 'No Prefix'), @array_combine($prefixes, $prefixes)); $this->form->addSelect('table_prefix')->setLabel('Tables Prefix')->loadOptions((array)$options); $gr = $this->form->addGroup(null, array('class' => 'no-label', 'style' => 'text-align:center')); $gr->addSubmit($this->getButtonName('back'), array('value'=>'Back')); $gr->addSubmit($this->getButtonName('next'), array('value'=>'Next')); } /** * find most possible prefixes */ function findPrefixes(array $tables) { $found = array(); foreach ($tables as $t) { $a = explode('_', $t); if (count($a)>1) { @$found[$a[0] . '_']++; } } return array_keys($found); } } class Am_Form_Controller_Page_PluginMaker_Columns extends HTML_QuickForm2_Controller_Page { public function addTable($name, Am_Table $table, $title, array $options) { $fs = $this->form->addFieldset()->setLabel($title . ' Columns: ' . $table->getName(true)); $sampleRows = $table->getAdapter()->select("SELECT * FROM ?# LIMIT ?d,3", $table->getName(true), max($table->countBy() - 3, 0)); $key = null; foreach ($table->getFields() as $fieldName => $f) { if ($f->key == 'PRI') $key = $fieldName; unset($f->field); unset($f->null); $gr = $fs->addGroup('field['.$name . ']['.$fieldName.']') ->setLabel($fieldName . "\n". implode(' ', get_object_vars($f))); if ($fieldName != $key) { $options = array_merge(array('' => '-- Select --'), $options); $gr->addSelect('field', array('class' => 'field'))->loadOptions($options); $gr->addText('text', array('size'=>'40', 'style' => 'display:none')); } $sample = "
"; foreach ($sampleRows as $r) { $v = Am_Html::escape($r[$fieldName]); if (strlen($v) > 60) $v = substr($v, 0, 60) . '...cut'; $sample .= $v . "
"; } $sample .= "
"; $gr->addStatic()->setContent($sample); } if (!$key) $key = current($table->getFields(true)); $this->form->addHidden('key['.$name.']')->setValue($key); } public function addFieldSelect($name, Am_Table $table, $title, array $options) { $fs = $this->form->addFieldset()->setLabel($title . ' Columns: ' . $table->getName(true)); $sampleRows = $table->getAdapter()->select("SELECT * FROM ?# LIMIT ?d,3", $table->getName(true), max($table->countBy() - 3, 0)); $sample = "
"; foreach ($sampleRows as $r) { $sample .= nl2br(Am_Html::escape(substr(print_r($r, true), 0, 1024))) . "\n"; } $sample .= "
"; $fs->addStatic()->setLabel('Sample Rows')->setContent($sample); $fields = $table->getFields(true); $fields = array_merge(array(''), $fields); foreach ($options as $k => $v) { $el = $fs->addSelect('field['.$name . ']['.$k.']')->setLabel($v) ->loadOptions(array_combine($fields, $fields)); if (!in_array($k,array('Am_Protect_SessionTable::FIELD_UID', 'Am_Protect_SessionTable::FIELD_IP', 'Am_Protect_SessionTable::FIELD_UA', 'Am_Protect_SessionTable::FIELD_CREATED', 'Am_Protect_SessionTable::FIELD_CHANGED'))) $el->addRule('required'); } } protected function populateForm() { $info = $this->getController()->getValue(); $db = Am_Db::connect($info); $tables = array(); foreach ($info['table'] as $k => $v) { if (!empty($v)) $tables[$k] = new Am_Table($db, $v); } /// user table $userOptions = array('expr' => 'PHP Expression', 'string' => 'PHP String'); $class = new ReflectionClass('Am_Protect_Table'); foreach ($class->getConstants() as $k => $v) { if (strpos($k, 'FIELD_')!==0) continue; $userOptions[$class->getName() . '::' . $k] = $class->getName() . ':' . $k; } $this->addTable('user', $tables['user'], 'User Table', $userOptions); /// group table if (!empty($tables['group'])) { $groupOptions = array( 'id' => 'Group ID', 'title' => 'Group Title', ); $this->addFieldSelect('group', $tables['group'], 'Group Table', $groupOptions); } /// user <-> group table if (!empty($tables['usergroup'])) { $usergroupOptions = array( 'Am_Protect_Table::GROUP_UID' => 'User ID', 'Am_Protect_Table::GROUP_GID' => 'Group ID', ); $this->addFieldSelect('usergroup', $tables['usergroup'], 'User<->Group Table', $usergroupOptions); } /// session table if (!empty($tables['session'])) { $sessionOptions = array( 'Am_Protect_SessionTable::FIELD_SID' => 'Session ID', 'Am_Protect_SessionTable::FIELD_UID' => 'User ID', 'Am_Protect_SessionTable::FIELD_IP' => 'IP Address', 'Am_Protect_SessionTable::FIELD_UA' => 'User Agent', 'Am_Protect_SessionTable::FIELD_CREATED' => 'Created', 'Am_Protect_SessionTable::FIELD_CHANGED' => 'Changed', ); $this->addTable('session', $tables['session'], 'Session Table', $sessionOptions); } $this->form->addScript()->setScript(<<form->addGroup(null, array('class' => 'no-label', 'style' => 'text-align:center')); $gr->addSubmit($this->getButtonName('back'), array('value'=>'Back')); $gr->addSubmit($this->getButtonName('next'), array('value'=>'Next')); } } PK\DcAA1default/controllers/AdminUserGroupsController.phpnu[hasPermission('grid_u'); } protected function getTable() { return $this->getDi()->userGroupTable; } protected function getNote() { return ___('aMember does not respect group hierarchy. Each group is absolutely independent. You can use hierarchy only to organize your groups.'); } protected function getTitle() { return ___('User Groups'); } } PK\(default/controllers/DirectController.phpnu[_request->getUserParam('plugin_id')); $this->_request->setActionName(filterId($this->_request->getActionName())); if (!$pluginId) throw new Am_Exception_InputError("Internal Error: wrong URL used - no plugin id"); $type = $this->_request->getUserParam('type'); if (!$this->getDi()->plugins->offsetGet($type)) throw new Am_Exception_InternalError("Wrong [type] requested"); $pluginMgr = $this->getDi()->plugins[$type]; if (!$pluginMgr->isEnabled($pluginId)) throw new Am_Exception_InputError("The [$pluginId] plugin is disabled"); $ps = $pluginMgr->loadGet($pluginId); if (!$ps->isConfigured()) throw new Am_Exception_Configuration("The plugin [$pluginId] is not configured, directAction failed"); return $ps->directAction($this->_request, $this->_response, $this->_invokeArgs); } }PK\B880default/controllers/AdminBuildDemoController.phpnu[setTarget('_top'); } public function getUrl($record = null, $id = null) { return $this->grid->getDi()->url('admin-build-demo/delete', array('id' => $record->id)); } public function run() { //nop } } class Am_Form_Admin_BuildDemoForm extends Am_Form_Admin { function init() { $this->addText('users_count') ->setLabel(___('Generate Users Count')) ->setValue(100); $this->addText('email_domain') ->setLabel(___("Email Domain\nused to generate email address for users")) ->setValue('cgi-central.int'); if ($this->isProductsExists()) { $this->addCheckbox('do_not_generate_products', array('checked'=>'checked')) ->setLabel( ___("Do not generate products\n". "use existing products for demo records") ) ->setId('form-do-not-generate-products'); $this->addMagicSelect('product_ids') ->setLabel(___("Use the following product for demo users\n" . 'keep it empty to use any products')) ->setId('form-product_ids') ->loadOptions(Am_Di::getInstance()->productTable->getOptions()); $this->addScript('script') ->setScript(<<addText('products_count', array('size'=>3)) ->setLabel(___('Generate Products Count')) ->setValue(3) ->setId('form-products-count'); $gr = $this->addGroup()->setLabel(___('Invoices Per User')); $gr->addText('invoices_per_user', array('size'=>3)) ->setValue(2); $gr->addStatic()->setContent(' +/- '); $gr->addText('invoices_per_user_variation', array('size'=>3)) ->setValue(1); $gr = $this->addGroup()->setLabel(___('Products Per Invoice')); $gr->addText('products_per_invoice', array('size'=>3))->setValue(2); $gr->addStatic()->setContent(' +/- '); $gr->addText('products_per_invoice_variation', array('size'=>3))->setValue(1); $gr = $this->addGroup() ->setLabel(___('Period')); $gr->setSeparator(' '); $gr->addDate('date_begin', array('size'=>8)) ->setValue(sqlDate('-60 days')); $gr->addDate('date_end', array('size'=>8)) ->setValue(sqlDate('now')); parent::init(); $this->addSaveButton(___('Generate')); } function isProductsExists() { return (boolean)Am_Di::getInstance()->productTable->count(); } } class AdminBuildDemoController extends Am_Mvc_Controller { /** @var Zend_Session_Namespace */ protected $session; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_BUILD_DEMO); } public function init() { $this->session = new Zend_Session_Namespace('amember_build_demo'); foreach ($this->getDi()->plugins_protect->loadEnabled()->getAllEnabled() as $pl) $pl->destroy(); } function indexAction() { $this->view->title = ___('Build Demo'); $this->session->unsetAll(); $form = new Am_Form_Admin_BuildDemoForm(); if ($form->isSubmitted()) { $form->setDataSources(array( $this->getRequest() )); } if ($form->isSubmitted() && $form->validate()) { $values = $form->getValue(); $this->session->params = array(); $this->session->params['email_domain'] = $values['email_domain']; $this->session->params['users_count'] = $values['users_count']; $this->session->params['products_count'] = $values['products_count']; $this->session->params['invoices_per_user'] = $values['invoices_per_user']; $this->session->params['invoices_per_user_variation'] = $values['invoices_per_user_variation']; $this->session->params['products_per_invoice'] = $values['products_per_invoice']; $this->session->params['products_per_invoice_variation'] = $values['products_per_invoice_variation']; $this->session->params['product_ids'] = isset($values['product_ids']) ? $values['product_ids'] : null; $this->session->params['date_begin'] = amstrtotime($values['date_begin']); $this->session->params['date_end'] = amstrtotime($values['date_end']); $this->session->proccessed = 0; $this->updateDemoHistory(); if (@$values['do_not_generate_products']) { $this->session->params['products_count'] = 0; $this->readProductsToSession(); } else { $this->generateProducts(); } $this->sendRedirect(); } $this->view->form = $form; $this->view->content = (string)$form . $this->createDemoHistoryGrid()->render(); $this->view->display('admin/layout.phtml'); } function renderGridTitle($record) { return $record->completed ? sprintf('%s', ___('You have generated %d demo products and %d demo customers', $record->products_count, $record->user_count) ) : sprintf('%s', ___('Generation of demo data was terminated while processing. Not all records were created.') ); } public function createDemoHistoryGrid() { $records = $this->getDi()->store->getBlob('demo-builder-records'); $records = $records ? unserialize($records) : array(); $ds = new Am_Grid_DataSource_Array($records); $grid = new Am_Grid_Editable('_h', ___('Demo History'), $ds, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_BUILD_DEMO); $grid->addField(new Am_Grid_Field_Date('date', 'Date', false, '', null, '10%')) ->setFormatDate(); $grid->addField(new Am_Grid_Field('title', 'Title', false, '', array($this, 'renderGridTitle'), '90%')); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_DemoDel); return $grid; } public function generateUser(& $context, $batch) { $payplugin = $context['payplugin']; $demoBuilder = new Am_DemoBuilder($this->getDi(), $this->getID()); $added = mt_rand($this->session->params['date_begin'], $this->session->params['date_end']); $user = $demoBuilder->createUser($this->session->params['email_domain'], $added); $this->getDi()->hook->call(Am_Event::BUILD_DEMO, array( 'user' => $user, 'demoId' => $this->getID(), 'usersCreated' => $this->session->processed, 'usersTotal' => $this->session->params['users_count'], )); $user->save(); $demoBuilder->createInvoices($user, $payplugin, $this->session->productIds, $this->session->params['invoices_per_user'], $this->session->params['invoices_per_user_variation'], $this->session->params['products_per_invoice'], $this->session->params['products_per_invoice_variation'], $added, $this->session->params['date_end']); $demoBuilder->createNotes($user, $added, $this->session->params['date_end']); $user = null; unset($user); $this->session->proccessed++; return $this->session->proccessed >= $this->session->params['users_count']; } public function doAction() { // disable all emails Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); $payplugin = null; foreach ($this->getDi()->plugins_payment->getEnabled() as $pl) { if ($pl == 'free') continue; $payplugin = $this->getDi()->plugins_payment->loadGet($pl); break; } if (empty($payplugin)) throw new Am_Exception_InputError('No payment plugins enabled. Visit [aMember Cp -> Setup/Configuration -> Plugins] and enable one'); $batch = new Am_BatchProcessor(array($this, 'generateUser')); $context = array( 'payplugin' => $payplugin ); if (!$batch->run($context)) { $this->sendRedirect(); } $this->updateDemoHistory(true); $this->session->unsetAll(); $this->_redirect('admin-build-demo'); } public function deleteAction() { $this->session->unsetAll(); $this->session->proccessed = 0; $this->session->lastUserId = 0; $query = new Am_Query(Am_Di::getInstance()->userTable); $this->session->total = $query->getFoundRows(); $this->session->params = array(); $this->session->params['demo-id'] = $this->getRequest()->getParam('id'); if (!$this->session->params['demo-id']) { throw new Am_Exception_InputError('demo-id is undefined'); } $this->deleteProducts($this->session->params['demo-id']); $this->deleteProductCategories($this->session->params['demo-id']); $this->sendDelRedirect(); } function deleteUser(& $context, $batch) { $count = 10; $query = new Am_Query(Am_Di::getInstance()->userTable); $query = $query->addOrder('user_id')->addWhere('user_id>?', $this->session->lastUserId); $users = $query->selectPageRecords(0, $count); $moreToProcess = false; foreach ($users as $user) { $demoId = $user->data()->get('demo-id'); $this->session->lastUserId = $user->pk(); if ($demoId && $demoId == $this->session->params['demo-id']) { $user->delete(); } $this->session->proccessed++; $moreToProcess = true; } return !$moreToProcess; } function doDeleteAction() { $batch = new Am_BatchProcessor(array($this, 'deleteUser')); $context = null; if (!$batch->run($context)) { $this->sendDelRedirect(); } $this->delDemoHistory($this->session->params['demo-id']); $this->session->unsetAll(); $this->_redirect('admin-build-demo'); } protected function updateDemoHistory($completed = false) { $records = $this->getDi()->store->getBlob('demo-builder-records'); $records = $records ? unserialize($records) : array(); $record = new stdClass(); $record->date = $this->getDi()->sqlDate; $record->user_count = $this->session->proccessed; $record->products_count = $this->session->params['products_count']; $record->id = $this->getID(); $record->completed = $completed; $records[$this->getID()] = $record; $this->getDi()->store->setBlob('demo-builder-records', serialize($records)); } protected function delDemoHistory($demoId) { $records = $this->getDi()->store->getBlob('demo-builder-records'); $records = $records ? unserialize($records) : array(); unset($records[$demoId]); $this->getDi()->store->setBlob('demo-builder-records', serialize($records)); } protected function deleteProducts($demoId) { foreach ($this->getDi()->productTable->getOptions() as $product_id => $title) { $product = $this->getDi()->productTable->load($product_id); $prDemoId = $product->data()->get('demo-id'); if ($prDemoId == $demoId) { $product->delete(); } } return; } protected function deleteProductCategories($demoId) { $query = new Am_Query(new ProductCategoryTable); $query->add(new Am_Query_Condition_Field('code', 'LIKE', $demoId.':%')); $count = $query->getFoundRows() ? $query->getFoundRows() : 1; foreach($query->selectPageRecords(0, $count) as $pCategory) { $pCategory->delete(); } } protected function readProductsToSession() { foreach ($this->getDi()->productTable->findBy() as $p) { if ($this->session->params['product_ids'] && !in_array($p->pk(), $this->session->params['product_ids'])) continue; $this->session->productIds[$p->pk()] = $p->pk(); } } protected function generateProducts() { $demoBuilder = new Am_DemoBuilder($this->getDi(), $this->getID()); $this->session->productIds = $demoBuilder->createProducts( $this->session->params['products_count'], 2); } protected function sendRedirect() { $proccessed = $this->session->proccessed; $total = $this->session->params['users_count']; $this->redirectHtml($this->getUrl('admin-build-demo', 'do'), ___('Building demo records').". " .___('Please wait')."...", ___('Build Demo'), false, $proccessed, $total); } protected function sendDelRedirect() { $proccessed = $this->session->proccessed; $total = $this->session->total; $this->redirectHtml($this->getUrl('admin-build-demo', 'do-delete'), ___('Cleaning up').". ". ___('Please wait')."...", ___('Cleanup'), false, $proccessed, $total); } protected function getID() { if (!$this->session->ID) { $this->session->ID = md5(mktime() . rand(0, 999)); } return $this->session->ID; } }PK\A/a/a.default/controllers/AdminContentController.phpnu[remove = (bool) $removeGroup; parent::__construct( !$removeGroup ? "content-assign-category" : "content-remove-category", !$removeGroup ? ___("Assign Category") : ___("Remove Category") ); } public function renderConfirmationForm($btn = "Yes, assign", $addHtml = null) { $select = sprintf('

' . PHP_EOL, $this->grid->getId(), Am_Html::renderOptions(Am_Di::getInstance()->resourceCategoryTable->getOptions()) ); return parent::renderConfirmationForm($this->remove ? ___("Yes, remove category") : ___("Yes, assign category"), $select); } /** * @param int $id * @param User $record */ public function handleRecord($id, $record) { $group_id = $this->grid->getRequest()->getInt('_group_id'); if (!$group_id) throw new Am_Exception_InternalError("_group_id empty"); $groups = $record->getCategories(); if ($this->remove) { if (!in_array($group_id, $groups)) return; foreach ($groups as $k => $id) if ($id == $group_id) unset($groups[$k]); } else { if (in_array($group_id, $groups)) return; $groups[] = $group_id; } $record->setCategories($groups); } } class Am_Grid_Action_Group_ContentSetAccessPermission extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; protected $form; protected $_vars, $_products; public function __construct() { parent::__construct('set_p', ___('Set Access Permissions')); $this->setTarget('_top'); } public function handleRecord($id, $record) { $record->setAccess($this->_vars['access']); } public function getForm() { if (!$this->form) { $id = $this->grid->getId(); $this->form = new Am_Form_Admin; $this->form->addElement(new Am_Form_Element_ResourceAccess)->setName($id . '_access')->setLabel(___('Access Permissions')); $this->form->addSaveButton(___('Set Access Permissions')); } return $this->form; } public function renderConfirmationForm($btn = null, $addHtml = null) { $this->getForm(); $vars = $this->grid->getCompleteRequest()->toArray(); $vars[$this->grid->getId() . '_confirm'] = 'yes'; foreach ($vars as $k => $v) if ($this->form->getElementsByName($k)) unset($vars[$k]); foreach(Am_Html::getArrayOfInputHiddens($vars) as $k => $v) $this->form->addHidden($k)->setValue($v); $url_yes = $this->grid->makeUrl(null); $this->form->setAction($url_yes); echo $this->renderTitle(); echo (string)$this->form; } public function run() { if (!$this->getForm()->validate()) { echo $this->renderConfirmationForm(); } else { $prefix = $this->grid->getId().'_'; foreach ($this->getForm()->getValue() as $k => $v) { if (strpos($k, $prefix)===0) $this->_vars[substr($k, strlen($prefix))] = $v; } return parent::run(); } } } abstract class Am_Grid_Filter_Content extends Am_Grid_Filter_Abstract { protected $varList = array('filter_q', 'filter_a'); protected function applyFilter() { $query = $this->grid->getDataSource()->getDataSourceQuery(); if ($filter = $this->getParam('filter_q')) { $condition = null; foreach($this->getSearchFields() as $f) { $c = new Am_Query_Condition_Field($f, 'LIKE', '%' . $filter . '%'); $condition = $condition ? $condition->_or($c) : $c; } $query->add($condition); } if ($filter = $this->getParam('filter_a')) { $r = $this->grid->getDataSource()->createRecord(); $key_name = $r->getTable()->getKeyField(); $resource_type = $r->getAccessType(); if (preg_match('/^c([0-9]+)$/', $filter, $m)) { $ctp = Am_Di::getInstance()->productCategoryTable->getCategoryProducts(); $product = $ctp[$m[1]]; $category = array($m[1]); } else { $p = Am_Di::getInstance()->productTable->load($filter); $category = $p->getCategories(); $product = array($filter); } $product[] = -1; $category[] = -1; $query->leftJoin('?_resource_access', 'ra', "t.$key_name=ra.resource_id AND ra.resource_type='$resource_type'") ->addWhere('(ra.fn = ? AND ra.id IN (?a)) OR (ra.fn = ? AND ra.id IN (?a))', 'product_id', $product, 'product_category_id', $category); } } function renderInputs() { $filter = ''; if($this->getSearchFields() != null) { $filter .= $this->renderInputText(array( 'name' => 'filter_q', 'placeholder' => $this->getPlaceholder())); $filter .= ' '; } $pCatOptions = Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions(); $pOptions = Am_Di::getInstance()->productTable->getOptions(); $options = array(); if ($pCatOptions) { foreach ($pCatOptions as $k => $v) { unset($pCatOptions[$k]); $pCatOptions['c'.$k] = $v; } $options = array( ___('Product Categories') => $pCatOptions, ___('Products') => $pOptions ); } else { $options = $pOptions; } $filter .= $this->renderInputSelect('filter_a', array('' => ___('-- Filter by Product --')) + $options); return $filter; } function getTitle() { return; } abstract function getPlaceholder(); abstract function getSearchFields(); } class Am_Grid_Filter_Content_All extends Am_Grid_Filter_Content { public function getPlaceholder() { return ''; } public function getSearchFields() { return null; } } class Am_Grid_Filter_Content_Email extends Am_Grid_Filter_Content { function getSearchFields() { return array('subject'); } function getPlaceholder() { return ___('Subject'); } } class Am_Grid_Filter_Content_Folder extends Am_Grid_Filter_Content { function getSearchFields() { return array('title', 'url', 'path'); } function getPlaceholder() { return ___('Title/URL/Path'); } } class Am_Grid_Filter_Content_Common extends Am_Grid_Filter_Content { function getSearchFields() { return array('title'); } function getPlaceholder() { return ___('Title'); } } class Am_Grid_Filter_Content_Integration extends Am_Grid_Filter_Content { function getSearchFields() { return array('plugin'); } function getPlaceholder() { return ___('Plugin Id'); } } class Am_Grid_Action_EmailPreview extends Am_Grid_Action_Abstract { protected $type = Am_Grid_Action_Abstract::SINGLE; public function run() { if ($this->grid->getRequest()->getParam('preview')) { $session = new Zend_Session_Namespace('email_preview'); echo $session->output; exit; } $f = $this->createForm(); $f->setDataSources(array($this->grid->getCompleteRequest())); echo $this->renderTitle(); if ($f->isSubmitted() && $f->validate() && $this->process($f)) return; echo $f; } function process(Am_Form $f) { $vars = $f->getValue(); $user = Am_Di::getInstance()->userTable->findFirstByLogin($vars['user']); if (!$user) { list($el) = $f->getElementsByName('user'); $el->setError(___('User %s not found', $vars['user'])); return false; } $product = Am_Di::getInstance()->productTable->load($vars['product_id']); $template = $this->grid->getRecord(); $mail = Am_Mail_Template::createFromEmailTemplate($template); switch ($template->name) { case EmailTemplate::AUTORESPONDER: $mail->setLast_product_title($product->title); break; case EmailTemplate::EXPIRE: $mail->setProduct_title($product->title); $mail->setExpires($vars['expires']); break; case EmailTemplate::PRODUCTWELCOME: $invoice = Am_Di::getInstance()->invoiceRecord; $invoice->toggleFrozen(true); $invoice->invoice_id = 'ID'; $invoice->public_id = 'PUBLIC ID'; $invoice->setUser($user); $invoice->add($product); $invoice->calculate(); /* @var $payment InvoicePayment */ $payment = Am_Di::getInstance()->invoicePaymentRecord; $payment->toggleFrozen(true); $payment->amount = $invoice->first_total; $payment->currency = $invoice->currency; $payment->receipt_id = 'RECEIPT_ID'; $mail->setInvoice($invoice); $mail->setPayment($payment); $mail->setLast_product_title($product->title); break; case EmailTemplate::PAYMENT: $invoice = Am_Di::getInstance()->invoiceRecord; $invoice->toggleFrozen(true); $invoice->invoice_id = 'ID'; $invoice->public_id = 'PUBLIC ID'; $invoice->setUser($user); $invoice->add($product); $invoice->calculate(); /* @var $payment InvoicePayment */ $payment = Am_Di::getInstance()->invoicePaymentRecord; $payment->toggleFrozen(true); $payment->invoice_payment_id = -1; $payment->invoice_id = -1; $payment->dattm = sqlTime('now'); $payment->amount = $invoice->first_total; $payment->currency = $invoice->currency; $payment->receipt_id = 'RECEIPT_ID'; $payment->_setInvoice($invoice); $mail->setInvoice($invoice); $mail->setPayment($payment); $mail->setInvoice_text($invoice->render('', $payment)); $mail->setInvoice_html($invoice->renderHtml($payment)); $mail->setInvoice_items($invoice->getItems()); $mail->setProduct($product); break; default: throw new Am_Exception_InternalError(sprintf('Unknown email template name [%s]', $template->name)); } $mail->setUser($user); $mail->send($user, new Am_Mail_Transport_Null()); if ($template->format == 'text') { printf('
%s: %s
%s
', ___('Subject'), Am_Html::escape($this->getSubject($mail)), '100%', Am_Html::escape($mail->getMail()->getBodyText()->getRawContent())); } else { $session = new Zend_Session_Namespace('email_preview'); $session->output = $mail->getMail()->getBodyHtml()->getRawContent(); printf('
%s: %s
', ___('Subject'), Am_Html::escape($this->getSubject($mail)), '100%', Am_Di::getInstance()->url('default/admin-content/p/emails',array( '_emails_a' => 'preview', '_emails_id' => 67, // ???? '_emails_preview' => 1, ))); } return true; } protected function getSubject($mail) { $subject = $mail->getMail()->getSubject(); if (strpos($subject, '=?') === 0) $subject = mb_decode_mimeheader($subject); return $subject; } protected function createForm() { $f = new Am_Form_Admin; $f->addText('user')->setLabel(___('Enter username of existing user')) ->addRule('required'); $f->addSelect('product_id') ->setLabel(___('Product')) ->loadOptions(Am_Di::getInstance()->productTable->getOptions()); $f->addScript()->setScript(<<grid->getRecord(); if ($tmp->name == EmailTemplate::EXPIRE) { $f->addDate('expires') ->setLabel(___('Expiration Date')) ->addRule('required'); } $f->addSaveButton(___('Preview')); foreach ($this->grid->getVariablesList() as $k) { $kk = $this->grid->getId() . '_' . $k; if ($v = @$_REQUEST[$kk]) $f->addHidden($kk)->setValue($v); } return $f; } } class Am_Grid_Action_PagePreview extends Am_Grid_Action_Abstract { protected $type = Am_Grid_Action_Abstract::SINGLE; public function run() { $f = $this->createForm(); $f->setDataSources(array($this->grid->getCompleteRequest())); if ($f->isSubmitted() && $f->validate() && $this->process($f)) return; echo $this->renderTitle(); echo $f; } function process(Am_Form $f) { $vars = $f->getValue(); $user = Am_Di::getInstance()->userTable->findFirstByLogin($vars['user']); if (!$user) { list($el) = $f->getElementsByName('user'); $el->setError(___('User %s not found', $vars['user'])); return false; } $page = $this->grid->getRecord(); echo $page->render(Am_Di::getInstance()->view, $user); exit; } protected function createForm() { $f = new Am_Form_Admin; $f->addText('user')->setLabel(___('Enter username of existing user')) ->addRule('required'); $f->addScript()->setScript(<<addSaveButton(___('Preview')); foreach ($this->grid->getVariablesList() as $k) { $kk = $this->grid->getId() . '_' . $k; if ($v = @$_REQUEST[$kk]) $f->addHidden($kk)->setValue($v); } return $f; } } class Am_Form_Element_PlayerConfig extends HTML_QuickForm2_Element { protected $value; /* @var HTML_QuickForm2_Element_InputHidden */ protected $elHidden; /* @var HTML_QuickForm2_Element_Select */ protected $elSelect; public function __construct($name = null, $attributes = null, array $data = array()) { $this->elHidden = new HTML_QuickForm2_Element_InputHidden($name); $this->elHidden->setContainer($this->getContainer()); $this->elSelect = new HTML_QuickForm2_Element_Select('__' . $name); $this->elSelect->loadOptions(array( '--global--' => ___('Use Global Settings'), '--custom--' => ___('Use Custom Settings') ) ); $this->addPresets($this->elSelect); parent::__construct($name, $attributes, $data); } public function getType() { return 'player-config'; } public function getRawValue() { return $this->elHidden->getRawValue(); } public function updateValue() { $this->elHidden->setContainer($this->getContainer()); $this->elHidden->updateValue(); $this->setValue($this->elHidden->getRawValue()); } public function setValue($value) { if (!$value) { $this->elSelect->setValue('--global--'); } elseif (@unserialize($value)) { $this->elSelect->setValue('--custom--'); } else { $this->elSelect->setValue($value); } $this->elHidden->setValue($value); } public function __toString() { return sprintf('
%s%s
', $this->elHidden, $this->elSelect, ___('Edit'), ___('Delete Preset'), ___('Save As Preset')) . ""; } protected function addPresets(HTML_QuickForm2_Element_Select $select) { $result = array(); $presets = Am_Di::getInstance()->store->getBlob('flowplayer-presets'); $presets = $presets ? unserialize($presets) : array(); foreach ($presets as $id => $preset) { $select->addOption($preset['name'], $id, array('data-config' => serialize($preset['config']))); } } } class Am_Form_Element_DownloadLimit extends HTML_QuickForm2_Element { protected $value = array(); /* @var HTML_QuickForm2_Element_InputText */ protected $elText; /* @var HTML_QuickForm2_Element_Select */ protected $elSelect; /* @var Am_Form_Element_AdvCheckbox */ protected $elCheckbox; public function __construct($name = null, $attributes = null, array $data = array()) { $this->elText = new HTML_QuickForm2_Element_InputText("__limit_" . $name, array('class' => 'download-limit-limit', 'size' => 4)); $this->elText->setValue(5); //Default $this->elSelect = new HTML_QuickForm2_Element_Select("__period_" . $name, array('class' => 'download-limit-period')); $this->elSelect->loadOptions(array( FileDownloadTable::PERIOD_HOUR => ___('Hour'), FileDownloadTable::PERIOD_DAY => ___('Day'), FileDownloadTable::PERIOD_WEEK => ___('Week'), FileDownloadTable::PERIOD_MONTH => ___('Month'), FileDownloadTable::PERIOD_YEAR => ___('Year'), FileDownloadTable::PERIOD_ALL => ___('All Subscription Period') ) )->setValue(FileDownloadTable::PERIOD_MONTH); //Default $this->elCheckbox = new Am_Form_Element_AdvCheckbox("__enable_" . $name, array('class' => 'download-limit-enable')); parent::__construct($name, $attributes, $data); } public function getType() { return 'download-limit'; } public function updateValue() { $this->elText->setContainer($this->getContainer()); $this->elText->updateValue(); $this->elSelect->setContainer($this->getContainer()); $this->elSelect->updateValue(); $this->elCheckbox->setContainer($this->getContainer()); $this->elCheckbox->updateValue(); parent::updateValue(); } public function getRawValue() { return $this->elCheckbox->getValue() ? sprintf('%d:%d', $this->elText->getValue(), $this->elSelect->getValue()) : ''; } public function setValue($value) { if (!$value) { $this->elCheckbox->setValue(0); } else { $this->elCheckbox->setValue(1); list($limit, $period) = explode(':', $value); $this->elText->setValue($limit); $this->elSelect->setValue($period); } } public function __toString() { $name = Am_Html::escape($this->getName()); $ret = "
\n"; $ret .= $this->elCheckbox; $ret .= ' '; $ret .= ___('allow max'); $ret .= ' ' . (string) $this->elText . ' '; $ret .= ___('downloads within'); $ret .= ' ' . (string) $this->elSelect . ' '; $ret .= ___('during subscription period'); $ret .= "\n"; $ret .= "
"; $ret .= " "; return $ret; } } class Am_Form_Element_ResourceAccess extends HTML_QuickForm2_Element { protected $value = array(); public function getType() { return 'resource-access'; } public function getRawValue() { return $this->value; } public function setValue($value) { $this->value = $value; } public function __toString() { $name = Am_Html::escape($this->getName()); $ret = "
"; if (!$this->getAttribute('without_free')) { $ret .= "\n"; $ret .= ___('Choose Products and/or Product Categories that allows access') . "
\n"; $ret .= ___('or %smake access free%s', "", '') . "

\n"; } $select = new HTML_QuickForm2_Element_Select(null, array('class' => 'access-items am-combobox-fixed')); $select->addOption(___('Please select an item...'), ''); $g = $select->addOptgroup(___('Product Categories'), array('class' => 'product_category_id', 'data-text' => ___("Category"))); $g->addOption(___('Any Product'), '-1', array('style' => 'font-weight: bold')); foreach (Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions() as $k => $v) { $g->addOption($v, "product_category_id$k"); } $g = $select->addOptgroup(___('Products'), array('class' => 'product_id', 'data-text' => ___("Product"))); foreach (Am_Di::getInstance()->productTable->getOptions() as $k => $v) { $g->addOption($v, "product_id$k"); } if (!$this->getAttribute('without_user_group_id') && ($op = Am_Di::getInstance()->userGroupTable->getOptions())) { $g = $select->addOptgroup(___('User Groups'), array('class' => 'user_group_id', 'data-text' => ___("User Group"))); foreach ($op as $k => $v) { $g->addOption($v, "user_group_id$k"); } } $ret .= (string) $select; foreach (Am_Di::getInstance()->resourceAccessTable->getFnValues() as $k) $ret .= "
"; $ret .= "
\n"; $hide_free_without_login = (bool) $this->getAttribute('without_free_without_login'); $ret .= "
"; $without_period = $this->getAttribute('without_period') ? 'true' : 'false'; $ret .= " "; return $ret; } } class Am_Grid_Editable_Files extends Am_Grid_Editable_Content { public function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->addCallback(self::CB_AFTER_DELETE, array($this, 'afterDelete')); $this->addCallback(self::CB_AFTER_SAVE, array($this, 'dropCache')); $this->addCallback(self::CB_AFTER_DELETE, array($this, 'dropCache')); $this->addCallback(self::CB_VALUES_FROM_FORM, array($this, '_valuesFromForm')); $this->setFilter(new Am_Grid_Filter_Content_Common); } public function _valuesFromForm(& $values) { $path = $values['path']; $values['mime'] = is_numeric($path) ? $this->getDi()->uploadTable->load($path)->getType() : Upload::getMimeType($path); } public function _valuesToForm(array & $values, Am_Record $record) { if ($record->isLoaded()) { $values['_category'] = $record->getCategories(); } parent::_valuesToForm($values, $record); } public function afterInsert(array & $values, ResourceAbstract $record) { $record->setCategories(empty($values['_category']) ? array() : $values['_category']); parent::afterInsert($values, $record); } protected function dropCache() { $this->getDi()->cache->clean(); } protected function afterDelete(File $record, $grid) { if (ctype_digit($record->path) && !$this->getDi()->fileTable->countBy(array('path' => $record->path))) { $this->getDi()->uploadTable->load($record->path)->delete(); } } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(false)); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(true)); $this->actionAdd(new Am_Grid_Action_Group_ContentSetAccessPermission); $this->actionAdd(new Am_Grid_Action_Group_Delete); } protected function initGridFields() { $this->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderAccessTitle')); $this->addField('path', ___('Filename'))->setRenderFunction(array($this, 'renderPath')); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_resource_category WHERE resource_type=?", 'file')) { $this->addField(new Am_Grid_Field('rgroup', ___('Categories'), false))->setRenderFunction(array($this, 'renderCategory')); } parent::initGridFields(); } protected function createAdapter() { return new Am_Query(Am_Di::getInstance()->fileTable); } function createForm() { $form = new Am_Form_Admin; $form->setAttribute('enctype', 'multipart/form-data'); $form->setAttribute('target', '_top'); $maxFileSize = Am_Storage_File::getSizeReadable( min(Am_Storage_File::getSizeBytes(ini_get('post_max_size')), Am_Storage_File::getSizeBytes(ini_get('upload_max_filesize')))); $el = $form->addElement(new Am_Form_Element_Upload('path', array(), array('prefix' => 'downloads'))) ->setLabel(___("File\n(max filesize %s)", $maxFileSize))->setId('form-path'); $jsOptions = <<setJsOptions($jsOptions); $form->addScript()->setScript(<<addRule('required', ___('File is required')); $form->addText('title', array('class' => 'el-wide translate'))->setLabel(___('Title'))->addRule('required', 'This field is required'); $form->addText('desc', array('class' => 'el-wide translate'))->setLabel(___('Description')); $form->addAdvCheckbox('hide')->setLabel(___("Hide from Dashboard\n" . "do not display this item link in members dashboard\n This doesn't remove link from category.")); $form->addElement(new Am_Form_Element_DownloadLimit('download_limit'))->setLabel(___('Limit Downloads Count')); $form->addElement(new Am_Form_Element_ResourceAccess)->setName('_access')->setLabel(___('Access Permissions')); $form->addText('no_access_url', array('class' => 'el-wide')) ->setLabel(___("No Access URL\ncustomer without required access will be redirected to this url, leave empty if you want to redirect to default 'No access' page")); $this->addCategoryToForm($form); return $form; } } class Am_Grid_Editable_Pages extends Am_Grid_Editable_Content { public function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->addCallback(self::CB_VALUES_FROM_FORM, array($this, '_valuesFromForm')); $this->setFilter(new Am_Grid_Filter_Content_Common); $this->setFormValueCallback('meta_robots', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); } public function _valuesToForm(array & $values, Am_Record $record) { if ($record->isLoaded()) { $values['_category'] = $record->getCategories(); } parent::_valuesToForm($values, $record); } public function afterInsert(array & $values, ResourceAbstract $record) { $record->setCategories(empty($values['_category']) ? array() : $values['_category']); parent::afterInsert($values, $record); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_PagePreview('preview', ___('Preview'))); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(false)); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(true)); $this->actionAdd(new Am_Grid_Action_Group_ContentSetAccessPermission); $this->actionAdd(new Am_Grid_Action_Group_Delete); } protected function initGridFields() { $this->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderAccessTitle')); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_resource_category WHERE resource_type=?", 'page')) { $this->addField(new Am_Grid_Field('rgroup', ___('Categories'), false))->setRenderFunction(array($this, 'renderCategory')); } parent::initGridFields(); } protected function createAdapter() { return new Am_Query(Am_Di::getInstance()->pageTable); } function createForm() { $form = new Am_Form_Admin; $form->addText('title', array('class' => 'el-wide translate')) ->setLabel(___('Title')) ->addRule('required', 'This field is required'); $form->addText('desc', array('class' => 'el-wide translate')) ->setLabel(___('Description')); $form->addAdvCheckbox('onmenu') ->setLabel(___('Add to Menu')); $form->addText('path', array('class' => 'el-wide')) ->setId('page-path') ->setLabel(___("Path\n" . 'will be used to construct user-friendly url, in case of you leave ' . 'it empty aMember will use id of this page to do it')) ->addRule('callback2', null, array($this, 'checkPath')); $page_url = $this->getDi()->rurl('page/'); $form->addStatic() ->setLabel(___('Permalink')) ->setContent(<< CUT ); $form->addScript() ->setScript(<<addAdvCheckbox('hide')->setLabel(___("Hide from Dashboard\n" . "do not display this item link in members area")); $placeholder_items =& $options['placeholder_items']; foreach ($this->getUserTagOptions() as $k => $v) { $placeholder_items[] = array($v, $k); } $form->addHtmlEditor('html') ->setMceOptions($options); $form->addAdvCheckbox('use_layout') ->setId('use-layout') ->setLabel(___("Display inside layout\nWhen displaying to customer, will the\nheader/footer from current theme be displayed?")); $form->addSelect('tpl') ->setId('use-layout-tpl') ->setLabel(___("Template\nalternative template for this page") . "\n" . ___("aMember will look for templates in [application/default/views/] folder\n" . "and in theme's [/] folder\n" . "and template filename must start with [layout]")) ->loadOptions($this->getTemplateOptions()); $form->addScript() ->setScript(<<addElement(new Am_Form_Element_ResourceAccess)->setName('_access')->setLabel(___('Access Permissions')); $form->addText('no_access_url', array('class' => 'el-wide')) ->setLabel(___("No Access URL\ncustomer without required access will be redirected to this url, leave empty if you want to redirect to default 'No access' page")); $this->addCategoryToForm($form); $fs = $form->addAdvFieldset('meta', array('id'=>'meta')) ->setLabel(___('Meta Data')); $fs->addText('meta_title', array('class' => 'el-wide')) ->setLabel(___('Title')); $fs->addText('meta_keywords', array('class' => 'el-wide')) ->setLabel(___('Keywords')); $fs->addText('meta_description', array('class' => 'el-wide')) ->setLabel(___('Description')); $gr = $fs->addGroup()->setLabel(___("Robots\n" . "instructions for search engines")); $gr->setSeparator(' '); $gr->addCheckbox('meta_robots[]', array('value' => 'noindex'), array('content' => 'noindex')); $gr->addCheckbox('meta_robots[]', array('value' => 'nofollow'), array('content' => 'nofollow')); $gr->addCheckbox('meta_robots[]', array('value' => 'noarchive'), array('content' => 'noarchive')); $gr->addFilter('array_filter'); return $form; } function checkPath($v, $e) { $r = $this->getRecord(); $found = $this->getDi()->db->selectCell('SELECT COUNT(*) FROm ?_page WHERE path=? {AND page_id<>?}', $v, $r->isLoaded() ? $r->pk() : DBSIMPLE_SKIP); return $found ? ___('Path should be unique') : null; } function getUserTagOptions() { $tagOptions = array( '%user.name_f%' => 'User First Name', '%user.name_l%' => 'User Last Name', '%user.login%' => 'Username', '%user.email%' => 'E-Mail', '%user.user_id%' => 'User Internal ID#', '%user.street%' => 'User Street', '%user.street2%' => 'User Street (Second Line)', '%user.city%' => 'User City', '%user.state%' => 'User State', '%user.zip%' => 'User ZIP', '%user.country%' => 'User Country', '%user.status%' => 'User Status (0-pending, 1-active, 2-expired)' ); foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (@$field->sql && @$field->from_config) { $tagOptions['%user.' . $field->name . '%'] = 'User ' . $field->title; } } return $tagOptions; } function _valuesFromForm(& $vals, $record) { if (!$vals['path']) $vals['path'] = null; if (!$vals['tpl']) $vals['tpl'] = null; } } class Am_Grid_Editable_Links extends Am_Grid_Editable_Content { public function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->setFilter(new Am_Grid_Filter_Content_Common); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(false)); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(true)); $this->actionAdd(new Am_Grid_Action_Group_Delete); $this->actionAdd(new Am_Grid_Action_Group_ContentSetAccessPermission); } protected function initGridFields() { $this->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderAccessTitle')); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_resource_category WHERE resource_type=?", 'link')) { $this->addField(new Am_Grid_Field('rgroup', ___('Categories'), false))->setRenderFunction(array($this, 'renderCategory')); } parent::initGridFields(); } protected function createAdapter() { return new Am_Query(Am_Di::getInstance()->linkTable); } public function _valuesToForm(array & $values, Am_Record $record) { if ($record->isLoaded()) { $values['_category'] = $record->getCategories(); } parent::_valuesToForm($values, $record); } public function afterInsert(array & $values, ResourceAbstract $record) { $record->setCategories(empty($values['_category']) ? array() : $values['_category']); parent::afterInsert($values, $record); } function createForm() { $form = new Am_Form_Admin; $form->addText('title', array('class' => 'el-wide translate'))->setLabel(___('Title'))->addRule('required'); $form->addText('desc', array('class' => 'el-wide translate'))->setLabel(___('Description')); $form->addText('url', array('class' => 'el-wide'))->setLabel(___('URL'))->addRule('required'); $form->addAdvCheckbox('onmenu') ->setLabel(___('Add to Menu')); $form->addAdvCheckbox('hide')->setLabel(___("Hide from Dashboard\n" . "do not display this item link in members area")); $form->addElement(new Am_Form_Element_ResourceAccess)->setName('_access') ->setLabel(___('Access Permissions')) ->setAttribute('without_free_without_login', 'true'); $this->addCategoryToForm($form); return $form; } public function renderContent() { return '
' . ___("IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member's area.") . '
' . parent::renderContent(); } } class Am_Grid_Editable_Integrations extends Am_Grid_Editable_Content { public function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->setFilter(new Am_Grid_Filter_Content_Integration); } public function init() { parent::init(); $this->addCallback(self::CB_VALUES_FROM_FORM, array($this, '_valuesFromForm')); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Group_Delete); } public function createAdapter() { return new Am_Query(Am_Di::getInstance()->integrationTable); } protected function initGridFields() { $this->addField('plugin', ___('Plugin'))->setRenderFunction(array($this, 'renderPluginTitle')); $this->addField('resource', ___('Resource'), false)->setRenderFunction(array($this, 'renderResourceTitle')); parent::initGridFields(); $this->removeField('_link'); } public function renderPluginTitle(Am_Record $r) { return $this->renderTd($r->plugin); } public function renderResourceTitle(Am_Record $r) { try { $pl = Am_Di::getInstance()->plugins_protect->get($r->plugin); } catch (Am_Exception_InternalError $e) { $pl = null; } $config = unserialize($r->vars); $s = $pl ? $pl->getIntegrationSettingDescription($config) : Am_Protect_Abstract::static_getIntegrationDescription($config); return $this->renderTd($s); } public function getGridPageTitle() { return ___("Integration plugins"); } function createForm() { $form = new Am_Form_Admin; $plugins = $form->addSelect('plugin')->setLabel(___('Plugin')); $plugins->addRule('required'); $plugins->addOption('*** ' . ___('Select a plugin') . ' ***', ''); foreach (Am_Di::getInstance()->plugins_protect->getAllEnabled() as $plugin) { if (!$plugin->isConfigured()) continue; $group = $form->addFieldset($plugin->getId())->setId('headrow-' . $plugin->getId()); $group->setLabel($plugin->getTitle()); $plugin->getIntegrationFormElements($group); // add id[...] around the element name foreach ($group->getElements() as $el) $el->setName('_plugins[' . $plugin->getId() . '][' . $el->getName() . ']'); if (!$group->count()) $form->removeChild($group); else $plugins->addOption($plugin->getTitle(), $plugin->getId()); } $group = $form->addFieldset('access')->setLabel(___('Access')); $group->addElement(new Am_Form_Element_ResourceAccess) ->setName('_access') ->setLabel(___('Access Permissions')) ->setAttribute('without_period', 'true') ->setAttribute('without_free', 'true') ->setAttribute('without_free_without_login', 'true'); $form->addScript()->setScript(<< $v) $vars['_plugins'][$vars['plugin']][$k] = $v; } parent::_valuesToForm($vars, $record); } } class Am_Grid_Editable_Folders extends Am_Grid_Editable_Content { public function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->setFilter(new Am_Grid_Filter_Content_Folder()); $this->setFormValueCallback('options', function($val) {return explode(' ', $val);}, function($val) {return implode(' ', $val);}); } public function _valuesToForm(array & $values, Am_Record $record) { if ($record->isLoaded()) { $values['_category'] = $record->getCategories(); } parent::_valuesToForm($values, $record); } public function init() { parent::init(); $this->addCallback(self::CB_AFTER_UPDATE, array($this, 'afterUpdate')); $this->addCallback(self::CB_AFTER_DELETE, array($this, 'afterDelete')); } public function validatePath($path) { if (!is_dir($path)) return ___('Wrong path: not a folder: %s', htmlentities($path)); if (!is_writeable($path)) return ___('Specified folder is not writable - please chmod the folder to 777, so aMember can write .htaccess file for folder protection'); if ((!$this->getRecord()->isLoaded() || $this->getRecord()->path != $path) && $this->getDi()->folderTable->findFirstByPath($path)) return ___('Specified folder is already protected. Please alter existing record or choose another folder.'); } function createForm() { $form = new Am_Form_Admin; $title = $form->addText('title', array('class' => 'el-wide translate', ))->setLabel(___("Title\ndisplayed to customers")); $title->addRule('required'); $form->addText('desc', array('class' => 'el-wide translate'))->setLabel(___('Description')); $form->addAdvCheckbox('hide')->setLabel(___("Hide from Dashboard\n" . "do not display this item link in members area")); $path = $form->addText('path')->setLabel(___('Path to Folder'))->setAttribute('size', 50)->addClass('dir-browser'); $path->addRule('required'); $path->addRule('callback2', '-- Wrong path --', array($this, 'validatePath')); $url = $form->addGroup()->setLabel(___('Folder URL')); $url->addRule('required'); $url->addText('url')->setAttribute('size', 50)->setId('url'); $url->addHtml()->setHtml(' ' . ___('open in new window') . ''); $methods = array( 'new-rewrite' => ___('New Rewrite'), 'htpasswd' => ___('Traditional .htpasswd'), ); foreach ($methods as $k => $v) if (!Am_Di::getInstance()->plugins_protect->isEnabled($k)) unset($methods[$k]); $method = $form->addAdvRadio('method')->setLabel(___('Protection Method')); $method->addRule('required'); $method->loadOptions($methods); if (count($methods) == 0) { throw new Am_Exception_InputError(___('No protection plugins enabled, please enable new-rewrite or htpasswd at aMember CP -> Setup -> Plugins')); } elseif (count($methods) == 1) { $method->setValue(key($methods))->toggleFrozen(true); } $form->addElement(new Am_Form_Element_ResourceAccess) ->setName('_access') ->setLabel(___('Access Permissions')) ->setAttribute('without_free_without_login', 'true'); $form->addScript('script')->setScript(' jQuery(function(){ jQuery(".dir-browser").dirBrowser({ urlField : "#url", rootUrl : ' . json_encode($this->getDi()->url('',null,false)) . ', }); jQuery("#test-url-link").click(function() { var href = jQuery("input", jQuery(this).parent()).val(); if (href) window.open(href , "test-url", ""); }); }); '); $form->addText('no_access_url', array('class' => 'el-wide')) ->setLabel(___("No Access URL\ncustomer without required access will be redirected to this url, leave empty if you want to redirect to default 'No access' page")); $gr = $form->addGroup('options') ->setLabel(___('Folder Options')); $gr->setSeparator("
"); foreach (array( '+Indexes' => ___('Directory Listings') ) as $k => $v) { $gr->addAdvCheckbox(null, array('value' => $k))->setContent($v); } $gr->addHidden(null, array('value' => '')); $gr->addFilter('array_filter'); $this->addCategoryToForm($form); return $form; } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(false)); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(true)); $this->actionAdd(new Am_Grid_Action_Group_Delete); } protected function initGridFields() { $this->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderAccessTitle')); $this->addField('path', ___('Path/URL'))->setRenderFunction(array($this, 'renderPathUrl')); $this->addField('method', ___('Protection Method')); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_resource_category WHERE resource_type=?", 'folder')) { $this->addField(new Am_Grid_Field('rgroup', ___('Categories'), false))->setRenderFunction(array($this, 'renderCategory')); } parent::initGridFields(); } public function renderPathUrl(Folder $f) { $url = Am_Html::escape($f->url); return $this->renderTd( Am_Html::escape($f->path) . "
" . "$url", false); } protected function createAdapter() { return new Am_Query(Am_Di::getInstance()->folderTable); } public function getGridPageTitle() { return ___("Folders"); } public function getHtaccessRewriteFile(Folder $folder) { if (AM_WIN) $rd = str_replace("\\", '/', $this->getDi()->data_dir); else $rd = $this->getDi()->data_dir; $options = $folder->options; $no_access_url = $this->getDi()->url('no-access/folder/id/'.$folder->folder_id,null,false,2); $new_rewrite_url = $this->getDi()->url('protect/new-rewrite',null,false,2); $no_access_rule = "RewriteRule ^(.*)$ {$no_access_url}?url=%{REQUEST_URI}?%{QUERY_STRING}&host=%{HTTP_HOST}&ssl=%{HTTPS} [L,R]"; // B flag requires APACHE 2.2 // older version causes 500 error code // define('AMEMBER_OLD_APACHE',true); can be added into config.php if(!defined('AMEMBER_OLD_APACHE')) $bflag = <<folder_id&url=%{REQUEST_URI}?%1&host=%{HTTP_HOST}&ssl=%{HTTPS} [L,R,B] BFLN; else $bflag = <<folder_id&url=%{REQUEST_URI}?%{QUERY_STRING}&host=%{HTTP_HOST}&ssl=%{HTTPS} [L,R] BFLO; return <<folder_id} -f RewriteRule ^(.*)\$ - [S=3] # if cookie is set but folder file does not exists, user has no access to given folder RewriteCond %{HTTP_COOKIE} amember_nr=([a-zA-Z0-9]+) RewriteCond $rd/new-rewrite/%1-{$folder->folder_id} !-f $no_access_rule ## if user is not authorized, redirect to login page # BrowserMatch "MSIE" force-no-vary RewriteCond %{QUERY_STRING} (.+) $bflag RewriteRule ^(.*)$ $new_rewrite_url?f=$folder->folder_id&url=%{REQUEST_URI}&host=%{HTTP_HOST}&ssl=%{HTTPS} [L,R] ########### AMEMBER FINISH #################### CUT; } public function getHtaccessHtpasswdFile(Folder $folder) { $rd = $this->getDi()->data_dir; $options = $folder->options ? "Options $folder->options" : ''; $require = ''; if (!$folder->hasAnyProducts()) $require = 'valid-user'; else $require = 'group FOLDER_' . $folder->folder_id; // $redirect = ROOT_SURL . "/no-access?folder_id={$folder->folder_id}"; // ErrorDocument 401 $redirect return <<method) { case 'new-rewrite': $ht = $this->getHtaccessRewriteFile($folder); break; case 'htpasswd': $ht = $this->getHtaccessHtpasswdFile($folder); break; default: throw new Am_Exception_InternalError(___('Unknown protection method')); } $htaccess_path = $folder->path . '/' . '.htaccess'; if (file_exists($htaccess_path)) { $content = file_get_contents($htaccess_path); $new_content = preg_replace('/#+\sAMEMBER START.+AMEMBER FINISH\s#+/ms', $ht, $content, 1, $found); if (!$found) $new_content = $ht . "\n\n" . $content; } else { $new_content = $ht . "\n\n"; } if (!file_put_contents($htaccess_path, $new_content)) throw new Am_Exception_InputError(___('Could not write file [%s] - check file permissions and make sure it is writeable', $htaccess_path)); } public function unprotectFolder(Folder $folder) { $htaccess_path = $folder->path . '/.htaccess'; if (!is_dir($folder->path)) { trigger_error(___('Could not open folder [%s] to remove .htaccess from it. Do it manually', $folder->path), E_USER_WARNING); return; } $content = file_get_contents($htaccess_path); $content = preg_replace('/^\s*\#+\sAMEMBER START.+AMEMBER FINISH\s#+\s*/s', '', $content); if (!trim($content)) { if (!unlink($folder->path . '/.htaccess')) trigger_error(___('File [%s] cannot be deleted - remove it manually to unprotect folder', $htaccess_path), E_USER_WARNING); } else { if(!file_put_contents($htaccess_path, $content)) trigger_error(___('File [%s] cannot be deleted - remove it manually to unprotect folder', $htaccess_path), E_USER_WARNING); } } public function afterInsert(array &$values, ResourceAbstract $record) { $record->setCategories(empty($values['_category']) ? array() : $values['_category']); parent::afterInsert($values, $record); $this->protectFolder($record); } public function afterUpdate(array &$values, ResourceAbstract $record) { $this->protectFolder($record); } public function afterDelete($record) { $this->unprotectFolder($record); } public function renderContent() { return '
' . ___("After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file") . '
' . parent::renderContent(); } } class Am_Grid_Editable_Emails extends Am_Grid_Editable_Content { protected $comment = array(); public function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->setFilter(new Am_Grid_Filter_Content_Email); } public function init() { $this->comment = array( EmailTemplate::PAYMENT => ___('Payment email will be automatically sent after payment received. Payment email will not be sent if:
  • User has unsubscribed from e-mail messages
'), EmailTemplate::PRODUCTWELCOME => ___('Product welcome email will be automatically sent immediately after payment received. Product welcome email will not be sent if:
  • User has unsubscribed from e-mail messages
'), EmailTemplate::AUTORESPONDER => ___('Autoresponder message will be automatically sent by cron job when configured conditions met. If you set message to be sent after payment, it will be sent immediately after payment received. Auto-responder message will not be sent if:
  • User has unsubscribed from e-mail messages
'), EmailTemplate::EXPIRE => ___('Expiration message will be sent when configured conditions met. Additional restrictions applies to do not sent unnecessary e-mails. Expiration message will not be sent if:
  • User has other active products with the same renewal group
  • User has unsubscribed from e-mail messages
') ); parent::init(); $this->addCallback(self::CB_VALUES_FROM_FORM, array($this, '_valuesFromForm')); } public function initActions() { parent::initActions(); $this->actionDelete('insert'); $this->actionAdd($a0 = new Am_Grid_Action_Insert('insert-' . EmailTemplate::AUTORESPONDER, ___('New Autoresponder'))); $a0->addUrlParam('name', EmailTemplate::AUTORESPONDER); $this->actionAdd($a1 = new Am_Grid_Action_Insert('insert-' . EmailTemplate::EXPIRE, ___('New Expiration E-Mail'))); $a1->addUrlParam('name', EmailTemplate::EXPIRE); $this->actionAdd($a2 = new Am_Grid_Action_Insert('insert-' . EmailTemplate::PRODUCTWELCOME, ___('New Product Welcome E-Mail'))); $a2->addUrlParam('name', EmailTemplate::PRODUCTWELCOME); $this->actionAdd($a3 = new Am_Grid_Action_Insert('insert-' . EmailTemplate::PAYMENT, ___('New Payment E-Mail'))); $a3->addUrlParam('name', EmailTemplate::PAYMENT); $this->actionAdd(new Am_Grid_Action_EmailPreview('preview', ___('Preview'))); $this->actionAdd(new Am_Grid_Action_Group_Delete); } protected function createAdapter() { $ds = new Am_Query(Am_Di::getInstance()->emailTemplateTable); $ds->addWhere('name IN (?a)', array(EmailTemplate::AUTORESPONDER, EmailTemplate::EXPIRE, EmailTemplate::PRODUCTWELCOME, EmailTemplate::PAYMENT)); return $ds; } protected function initGridFields() { $this->addField('name', ___('Name')); $this->addField('recipient_emails', ___('Recipients'), true, '', array($this, 'getRecipients')); $this->addField('day', ___('Send'))->setGetFunction(array($this, 'getDay')); $this->addField('subject', ___('Subject'))->addDecorator(new Am_Grid_Field_Decorator_Shorten(30)); parent::initGridFields(); $this->removeField('_link'); } public function getDay(EmailTemplate $record) { switch ($record->name) { case EmailTemplate::AUTORESPONDER: return ($record->day > 1) ? ___("%d-th subscription day", $record->day) : ___("immediately after subscription is started"); break; case EmailTemplate::EXPIRE: switch (true) { case $record->day > 0: return ___("%d days after expiration", $record->day); case $record->day < 0: return ___("%d days before expiration", -$record->day); case $record->day == 0: return ___("on expiration day"); } break; case EmailTemplate::PAYMENT: switch (true) { case $record->day > 0: return ___("%d days in advance of recurring payment", $record->day); case $record->day < 0: return ___("%d days after payment", -$record->day); case $record->day == 0: return ___("immediately after payment"); } break; case EmailTemplate::PRODUCTWELCOME: return ___("immediately after product is purchased"); break; } } public function getRecipients(EmailTemplate $record) { $recipients = array(); if ($record->recipient_user) $recipients[] = "User"; if ($record->recipient_aff) $recipients[] = "Affiliate"; if ($record->recipient_admin) $recipients[] = "Admin"; if ($record->recipient_emails) $recipients[] = $record->recipient_emails; return sprintf('%s', implode(', ', $recipients)); } public function createForm() { $form = new Am_Form_Admin; $record = $this->getRecord(); $name = empty($record->name) ? $this->getCompleteRequest()->getFiltered('name') : $record->name; $form->addHidden('name'); $form->addStatic()->setContent(nl2br($this->comment[$name]))->setLabel(___('Description')); $form->addStatic()->setLabel(___('E-Mail Type'))->setContent($name); if ($options = $this->getDi()->emailTemplateLayoutTable->getOptions()) { $form->addSelect('email_template_layout_id') ->setLabel(___('Layout')) ->loadOptions(array(''=>___('No Layout')) + $options); } $form->addSelect('reply_to') ->loadOptions($this->getReplyToOptions()) ->setLabel(___("Reply To\n" . "mailbox for replies to message")); $recipient = $form->addGroup(null)->setLabel(___('Recipients')); $recipient->setSeparator('
'); $recipient->addAdvCheckbox('recipient_user') ->setContent(___('User Email')); if ($this->getDi()->modules->isEnabled('aff')) { $recipient->addAdvCheckbox('recipient_aff') ->setContent(___('Affiliate Email')); } $recipient->addAdvCheckbox('recipient_admin') ->setContent(___('Admin Email')); $recipient->addAdvCheckbox('recipient_other', array('id' => 'checkbox-recipient-other')) ->setContent(___('Other')); $form->addText('recipient_emails', array('class' => 'el-wide', 'id' => 'input-recipient-emails', 'placeholder' => ___('Email Addresses Separated by Comma'))) ->setLabel(___('Emails')) ->addRule('callback2', ___('Please enter valid e-mail addresses'), array($this, 'validateOtherEmails')); $form->addText('bcc', array('class' => 'el-wide', 'placeholder' => ___('Email Addresses Separated by Comma'))) ->setLabel(___("BCC\n" . "blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients")) ->addRule('callback', ___('Please enter valid e-mail addresses'), array('Am_Validate', 'emails')); $form->addScript()->setScript(<<addElement(new Am_Form_Element_MailEditor($name, array('upload-prefix' => 'email-messages'))); switch ($name) { case EmailTemplate::AUTORESPONDER: $access_desc = ___('Send E-Mail if customer has subscription (required)'); break; case EmailTemplate::EXPIRE: $access_desc = ___('Send E-Mail when subscription expires (required)'); break; case EmailTemplate::PRODUCTWELCOME: $access_desc = ___('Send E-Mail when the next subscription is started (required)'); break; case EmailTemplate::PAYMENT: $access_desc = ___('Send E-Mail if invoice has the following subscriptions (required)'); break; } if ($name == EmailTemplate::EXPIRE) { $gr = $form->addGroup() ->setLabel($access_desc) ->setSeparator('
'); $access_el = $gr->addElement(new Am_Form_Element_ResourceAccess('_access')) ->setAttribute('without_period', true) ->setAttribute('without_free', true) ->setAttribute('without_user_group_id', true); $gr->addAdvCheckbox('recurring', null, array('content' => ___('send this message even if customer has active recurring subscription for matched product'))); } else { $access_el = $form->addElement(new Am_Form_Element_ResourceAccess('_access')) ->setLabel($access_desc) ->setAttribute('without_period', true) ->setAttribute('without_free', true) ->setAttribute('without_user_group_id', true); } $group = $form->addGroup() ->setLabel(___('Send E-Mail only if customer has no subscription (optional)')); $group->setSeparator('
'); $select = $group->addMagicSelect('_not_conditions', array('class'=>'am-combobox')); $this->addCategoriesProductsList($select); $group->addAdvCheckbox('not_conditions_expired')->setContent(___('check expired subscriptions too')); $group->addAdvCheckbox('not_conditions_future')->setContent(___('check future subscriptions too')); if ($name != EmailTemplate::PRODUCTWELCOME) { $group = $form->addGroup('day')->setLabel(___('Send E-Mail Message')); switch ($name) { case EmailTemplate::AUTORESPONDER: $options = array('' => ___('..th subscription day (starts from 2)'), '1' => ___('immediately after subscription is started')); break; case EmailTemplate::EXPIRE: $options = array('-' => ___('days before expiration'), '0' => ___('on expiration day'), '+' => ___('days after expiration')); break; case EmailTemplate::PAYMENT: $options = array('+' => ___('days in advance of recurring payment'), '0' => ___('immediately after payment'), '-' => ___('days after payment')); break; } $group->addInteger('count', array('size' => 3, 'id' => 'days-count')); $group->addSelect('type', array('id' => 'days-type'))->loadOptions($options); $group->addScript()->setScript(<<getDi()->config->get('send_pdf_invoice') && ($name == EmailTemplate::PAYMENT)) { $form->addAdvCheckbox('attach_pdf_invoice', array(), array( 'content' => ___('Attach PDF Invoice') )); } return $form; } protected function getReplyToOptions() { $op = array(); $op[''] = Am_Html::escape(sprintf('%s <%s>', $this->getDi()->config->get('admin_email_name', $this->getDi()->config->get('site_title')), $this->getDi()->config->get('admin_email_from', $this->getDi()->config->get('admin_email')))); foreach (Am_Di::getInstance()->adminTable->findBy() as $admin) { $op[$admin->pk()] = Am_Html::escape(sprintf('%s <%s>', $admin->getName(), $admin->email)); } return $op; } function validateOtherEmails($val, $el) { $vars = $el->getContainer()->getValue(); if ($vars['recipient_other'] == 1) { if (!strlen($vars['recipient_emails'])) return ___('Please enter one or more email'); if (!Am_Validate::emails($val)) return ___('Please enter valid e-mail addresses'); } } function addCategoriesProductsList(HTML_QuickForm2_Element_Select $select) { $g = $select->addOptgroup(___('Product Categories'), array('class' => 'product_category_id', 'data-text' => ___("Category"))); $g->addOption(___('Any Product'), 'c-1', array('style' => 'font-weight: bold')); foreach ($this->getDi()->productCategoryTable->getAdminSelectOptions() as $k => $v) { $g->addOption($v, 'c' . $k); } $g = $select->addOptgroup(___('Products'), array('class' => 'product_id', 'data-text' => ___("Product"))); foreach ($this->getDi()->productTable->getOptions() as $k => $v) { $g->addOption($v, 'p' . $k); } } public function _valuesToForm(array &$values, Am_Record $record) { parent::_valuesToForm($values, $record); switch (get_first(@$values['name'], @$_GET['name'])) { case EmailTemplate::AUTORESPONDER : $values['day'] = (empty($values['day']) || ($values['day'] == 1)) ? array('count' => 1, 'type' => '1') : array('count' => $values['day'], 'type' => ''); break; case EmailTemplate::EXPIRE : $day = @$values['day']; $values['day'] = array('count' => $day, 'type' => ''); if ($day > 0) $values['day']['type'] = '+'; elseif ($day < 0) { $values['day']['type'] = '-'; $values['day']['count'] = -$day; } else $values['day']['type'] = '0'; break; case EmailTemplate::PAYMENT : $day = @$values['day']; $values['day'] = array('count' => $day, 'type' => ''); if ($day > 0) $values['day']['type'] = '+'; elseif ($day < 0) { $values['day']['type'] = '-'; $values['day']['count'] = -$day; } else $values['day']['type'] = '0'; break; } $values['attachments'] = explode(',', @$values['attachments']); $values['_not_conditions'] = explode(',', @$values['not_conditions']); if (!empty($values['recipient_emails'])) { $values['recipient_other'] = 1; } if (!$record->isLoaded()) { $values['recipient_user'] = 1; $values['format'] = 'html'; } } public function _valuesFromForm(array &$values) { if (!$values['reply_to']) { $values['reply_to'] = null; } if (!$values['email_template_layout_id']) { $values['email_template_layout_id'] = null; } switch ($values['day']['type']) { case '0': $values['day'] = 0; break; case '1': $values['day'] = 1; break; case '': case '+': $values['day'] = (int) $values['day']['count']; break; case '-': $values['day'] = - $values['day']['count']; break; } $values['attachments'] = implode(',', @$values['attachments']); /////// foreach (array('free', 'free_without_login', 'product_category_id', 'product_id') as $key) { if (!empty($values['_access'][$key])) foreach ($values['_access'][$key] as & $item) { if (is_string($item)) $item = json_decode($item, true); $item['start'] = $item['stop'] = $values['day'] . 'd'; } } $values['_not_conditions'] = array_filter(array_map('filterId', $values['_not_conditions'])); $values['not_conditions'] = implode(',', $values['_not_conditions']); if (!$values['recipient_other']) $values['recipient_emails'] = null; unset($values['recipient_other']); } public function getProducts(ResourceAbstract $resource) { $s = ""; foreach ($resource->getAccessList() as $access) $s .= sprintf("%s %s %s
\n", $access->getClass(), $access->getTitle(), ""); return $s; } } class Am_Grid_Editable_Video extends Am_Grid_Editable_Content { function __construct(Am_Mvc_Request $request, Am_View $view) { parent::__construct($request, $view); $this->addCallback(self::CB_VALUES_FROM_FORM, array($this, '_valuesFromForm')); $this->setFilter(new Am_Grid_Filter_Content_Common); $this->setFormValueCallback('meta_robots', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); } public function initActions() { parent::initActions(); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(false)); $this->actionAdd(new Am_Grid_Action_Group_ContentAssignCategory(true)); $this->actionAdd(new Am_Grid_Action_Group_ContentSetAccessPermission); $this->actionAdd(new Am_Grid_Action_Group_Delete); } protected function initGridFields() { $this->addField('title', ___('Title'))->setRenderFunction(array($this, 'renderAccessTitle')); $this->addField('path', ___('Filename'))->setRenderFunction(array($this, 'renderPath')); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_resource_category WHERE resource_type=?", 'video')) { $this->addField(new Am_Grid_Field('rgroup', ___('Categories'), false))->setRenderFunction(array($this, 'renderCategory')); } $this->addField(new Am_Grid_Field_Expandable('_code', ___('JavaScript Code'))) ->setGetFunction(array($this, 'renderJsCode')); parent::initGridFields(); } protected function _valuesFromForm(& $values) { $path = $values['path']; $values['mime'] = is_numeric($path) ? $this->getDi()->uploadTable->load($path)->getType() : Upload::getMimeType($path); if (!$values['tpl']) $values['tpl'] = null; } public function _valuesToForm(array & $values, Am_Record $record) { if ($record->isLoaded()) { $values['_category'] = $record->getCategories(); } parent::_valuesToForm($values, $record); } public function afterInsert(array & $values, ResourceAbstract $record) { $record->setCategories(empty($values['_category']) ? array() : $values['_category']); parent::afterInsert($values, $record); } public function renderJsCode(Video $video) { $type = $video->mime == 'audio/mpeg' ? 'audio' : 'video'; $width = 550; $height = $type == 'video' ? 330 : 30; $url = $this->getDi()->url($type.'/js/id/'.$video->video_id,null,false,2); $cnt = << CUT; return "
" . Am_Html::escape($cnt) . "
"; } protected function createAdapter() { return new Am_Query(Am_Di::getInstance()->videoTable); } function createForm() { $form = new Am_Form_Admin; $form->setAttribute('enctype', 'multipart/form-data'); $form->setAttribute('target', '_top'); $maxFileSize = min(ini_get('post_max_size'), ini_get('upload_max_filesize')); $el = $form->addElement(new Am_Form_Element_Upload('path', array(), array('prefix' => 'video'))) ->setLabel(___("Video/Audio File\n". "(max upload size %s)\n". "You can use this feature only for video and\naudio formats that %ssupported by %s%s", $maxFileSize, ($this->getDi()->config->get('video_player', 'Flowplayer') == 'Flowplayer') ? '' : '', ($this->getDi()->config->get('video_player', 'Flowplayer') == 'Flowplayer') ? 'Flowplayer' : 'JWPlayer', '')) ->setId('form-path'); $jsOptions = <<setJsOptions($jsOptions); $form->addScript()->setScript(<<addRule('required'); $form->addUpload('poster_id', null, array('prefix' => 'video-poster')) ->setLabel(___("Poster Image\n" . "applicable only for video files")); $form->addUpload('cc_id', null, array('prefix' => 'video-cc')) ->setLabel(___("Closed Captions\n" . "file must be in SRT format, applicable only for video files")); $form->addText('title', array('class' => 'el-wide translate'))->setLabel(___('Title'))->addRule('required', 'This field is required'); $form->addText('desc', array('class' => 'el-wide translate'))->setLabel(___('Description')); $form->addAdvCheckbox('hide')->setLabel(___("Hide from Dashboard\n" . "do not display this item link in members area")); $form->addElement(new Am_Form_Element_PlayerConfig('config')) ->setLabel(___("Player Configuration\n" . 'this option is applied only for video files')); $form->addSelect('tpl') ->setLabel(___("Template\nalternative template for this video\n" . "aMember will look for templates in [application/default/views/] folder\n" . "and in theme's [/] folder\n" . "and template filename must start with [layout]")) ->loadOptions($this->getTemplateOptions()); $form->addElement(new Am_Form_Element_ResourceAccess)->setName('_access') ->setLabel(___('Access Permissions')); $form->addText('no_access_url', array('class' => 'el-wide')) ->setLabel(___("No Access URL\n" . "customer without required access will see link to this url in " . "the player window\nleave empty if you want to redirect to " . "default 'No access' page")); $this->addCategoryToForm($form); $fs = $form->addAdvFieldset('meta', array('id'=>'meta')) ->setLabel(___('Meta Data')); $fs->addText('meta_title', array('class' => 'el-wide')) ->setLabel(___('Title')); $fs->addText('meta_keywords', array('class' => 'el-wide')) ->setLabel(___('Keywords')); $fs->addText('meta_description', array('class' => 'el-wide')) ->setLabel(___('Description')); $gr = $fs->addGroup()->setLabel(___("Robots\n" . "instructions for search engines")); $gr->setSeparator(' '); $gr->addCheckbox('meta_robots[]', array('value' => 'noindex'), array('content' => 'noindex')); $gr->addCheckbox('meta_robots[]', array('value' => 'nofollow'), array('content' => 'nofollow')); $gr->addCheckbox('meta_robots[]', array('value' => 'noarchive'), array('content' => 'noarchive')); $gr->addFilter('array_filter'); $form->addEpilog('
' . ___('In case of video do not start play before full download and you use mp4 format more possible that metadata (moov atom) is located at the end of file. There is special programs that allow to relocate this metadata to the beginning of your file and allow play video before full download (On Linux mashine you can use qt-faststart utility to do it). Also your video editor can has option to locate metadata at beginning of file (something like FastStart or Web Optimized option). You need to relocate metadata for this file and reupload it to aMember. You can use such utilites as AtomicParsley or similar to check your file structure.') . '
'); return $form; } public function renderContent() { return $this->getPlayerInfo() . parent::renderContent(); } function getPlayerInfo() { $out = ""; foreach (array( '/default/views/public/js/flowplayer/flowplayer.js', '/default/views/public/js/flowplayer/flowplayer.swf', '/default/views/public/js/flowplayer/flowplayer.controls.swf', '/default/views/public/js/flowplayer/flowplayer.audio.swf') as $file) { if (!file_exists($fn = AM_APPLICATION_PATH . $file)) $out .= ___('Please upload file [%s]
', $fn); } if ($out) { $out = '
' . ___('To starting sharing media files, you have to download either free or commercial version of FlowPlayer
') . $out . '
'; } return $out; } } class Am_Grid_Editable_ContentAll extends Am_Grid_Editable { protected $_cat_options = null; public function __construct(Am_Mvc_Request $request, Am_View $view) { $di = Am_Di::getInstance(); $ds = null; $i = 0; $key = null; foreach ($di->resourceAccessTable->getAccessTables() as $k => $t) { $q = new Am_Query($t); $q->clearFields(); if (empty($key)) $key = $t->getKeyField(); $q->addField($t->getKeyField(), $key); $type = $t->getAccessType(); $q->addField("'$type'", 'resource_type'); $q->addField($t->getTitleField(), 'title'); $q->addField($q->escape($t->getAccessTitle()), 'type_title'); $q->addField($q->escape($t->getPageId()), 'page_id'); $q->addField("(SELECT GROUP_CONCAT(resource_category_id SEPARATOR ',') FROM ?_resource_resource_category rrc WHERE" . " resource_id=$key AND resource_type='$type' GROUP BY resource_id)", 'cat_id'); if ($t instanceof EmailTemplateTable) $q->addWhere('name IN (?a)', array(EmailTemplate::AUTORESPONDER, EmailTemplate::EXPIRE)); if (empty($ds)) $ds = $q; else $ds->addUnion($q); } // yes we need that subquery in subquery to mask field names // to get access of fields of main query (!) $ds->addOrderRaw("(SELECT _sort_order FROM ( SELECT sort_order as _sort_order, resource_type as _resource_type, resource_id as _resource_id FROM ?_resource_access_sort ras) AS _ras WHERE _resource_id=$key AND _resource_type=resource_type LIMIT 1), $key, resource_type"); parent::__construct('_all', ___('All Content'), $ds, $request, $view, $di); $this->addField('type_title', ___('Type')); $this->addField('title', ___('Title')); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_resource_category")) { $this->addField(new Am_Grid_Field('rgroup', ___('Categories'), false))->setRenderFunction(array($this, 'renderCategory')); } $this->actionDelete('insert'); $this->actionDelete('edit'); $this->actionDelete('delete'); $this->setFilter(new Am_Grid_Filter_Content_All); $di = $this->getDi(); $this->actionAdd(new Am_Grid_Action_ContentAllEdit('edit', ___('Edit'), '')) ->setIsAvailableCallback(function($r) use ($di) { return $di->authAdmin->getUser()->hasPermission('grid_' . $r->page_id, 'edit'); }); $this->actionAdd(new Am_Grid_Action_SortContent()); } public function renderCategory(Am_Record $r, $fieldname, Am_Grid_ReadOnly $grid, $field) { $res = array(); if (is_null($this->_cat_options)) { $this->_cat_options = $this->getDi()->resourceCategoryTable->getOptions(); } foreach (explode(',', $r->cat_id) as $resc_id) { if ($resc_id) $res[] = $this->_cat_options[$resc_id]; } return $this->renderTd(implode(', ', $res)); } } class Am_Grid_Action_SortContent extends Am_Grid_Action_Sort_Abstract { protected $privilege = 'edit'; protected function getRecordParams($obj) { $id = $obj->pk(); $type = $obj->get('resource_type'); if (!$type) $type = $this->grid->getDataSource()->createRecord()->getAccessType(); return array( 'id' => $id, 'type' => $type ); } protected function setSortBetween($item, $after, $before) { $move_after = $after ? $after['id'] : null; $move_after_type = $after ? $after['type'] : null; $move_before = $before ? $before['id'] : null; $move_before_type = $before ? $before['type'] : null; $accessTables = Am_Di::getInstance()->resourceAccessTable->getAccessTables(); $record = $accessTables[$item['type']]->load($item['id']); $record->setSortBetween($move_after, $move_before, $move_after_type, $move_before_type); } } class Am_Grid_Action_ContentAllEdit extends Am_Grid_Action_Abstract { protected $privilege = 'edit'; protected $url; public function __construct($id, $title, $url) { $this->id = $id; $this->title = $title; $this->url = $url; parent::__construct(); $this->setTarget('_top'); } public function getUrl($record = null, $id = null) { $id = $record->pk(); $page_id = $record->page_id; $back_url = Am_Html::escape($this->grid->getBackUrl()); return Am_Di::getInstance()->url("default/admin-content/p/$page_id/index", array("_{$page_id}_a"=>'edit',"_{$page_id}_b"=>$back_url,"_{$page_id}_id"=>$id),false); } public function run() { //nop } } class AdminContentController extends Am_Mvc_Controller_Pages { public function checkAdminPermissions(Admin $admin) { return true; } public function preDispatch() { parent::preDispatch(); $this->view->headScript()->appendFile($this->view->_scriptJs("resourceaccess.js")); $this->view->headScript()->appendFile($this->view->_scriptJs("player-config.js")); } public function initPages() { if (empty($this->getSession()->admin_content_sort_checked)) { // dirty hack - we are checking that all content records have sort order $count = 0; foreach ($this->getDi()->resourceAccessTable->getAccessTables() as $k => $table) $count += $table->countBy(); $countSort = $this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_resource_access_sort"); if ($countSort != $count) $this->getDi()->resourceAccessTable->syncSortOrder(); $this->getSession()->admin_content_sort_checked = 1; } // foreach ($this->getDi()->resourceAccessTable->getAccessTables() as $k => $table) { if (!$this->getDi()->authAdmin->getUser()->hasPermission('grid_' . $table->getPageId())) continue; /* @var $table ResourceAbstractTable */ $page_id = $table->getPageId(); $this->addPage('Am_Grid_Editable_' . ucfirst($page_id), $page_id, $table->getAccessTitle()); } if ($this->getDi()->authAdmin->getUser()->hasPermission('grid_all')) { $this->addPage('Am_Grid_Editable_ContentAll', 'all', ___('All')); } } public function renderPage(Am_Mvc_Controller_Pages_Page $page) { $this->setActiveMenu($page->getId() == 'all' ? 'content' : 'content-' . $page->getId()); return parent::renderPage($page); } } PK\5Ejwjw/default/controllers/AdminPaymentsController.phpnu[vars['filter'] as $v) if ($v) return true; } public function setDateField($dateField) { $this->dateField = $dateField; } protected function applyFilter() { class_exists('Am_Form', true); $filter = (array) $this->vars['filter']; $q = $this->grid->getDataSource(); $dateField = $this->vars['filter']['datf']; if (!array_key_exists($dateField, $this->getDateFieldOptions())) throw new Am_Exception_InternalError(sprintf('Unknown date field [%s] submitted in %s::%s', $dateField, __CLASS__, __METHOD__)); /* @var $q Am_Query */ if ($filter['dat1']) $q->addWhere("t.$dateField >= ?", Am_Form_Element_Date::createFromFormat(null, $filter['dat1'])->format('Y-m-d 00:00:00')); if ($filter['dat2']) $q->addWhere("t.$dateField <= ?", Am_Form_Element_Date::createFromFormat(null, $filter['dat2'])->format('Y-m-d 23:59:59')); if (@$filter['text']) { switch (@$filter['type']) { case 'invoice': if ($q->getTableName() == '?_invoice') { $q->leftJoin('?_invoice_payment', 'p'); $q->leftJoin('?_invoice_refund', 'rf'); $q->addWhere('(t.invoice_id=? OR t.public_id=? OR p.display_invoice_id=? or rf.display_invoice_id=?)', $filter['text'], $filter['text'], $filter['text'], $filter['text']); } else { $q->addWhere('(t.invoice_id=? OR t.invoice_public_id=? or t.display_invoice_id=?)', $filter['text'], $filter['text'], $filter['text']); } break; case 'login': $q->addWhere('login=?', $filter['text']); break; case 'name': $q->addWhere("name_f LIKE ? OR name_l LIKE ? OR CONCAT(name_f, ' ', name_l) LIKE ? OR CONCAT(name_l, ' ', name_f) LIKE ?", '%' . $filter['text'] . '%', '%' . $filter['text'] . '%', '%' . $filter['text'] . '%', '%' . $filter['text'] . '%'); break; case 'receipt': if ($q->getTableName() == '?_invoice') { $q->leftJoin('?_invoice_payment', 'p'); } $q->addWhere('receipt_id LIKE ?', '%' . $filter['text'] . '%'); break; case 'coupon': if ($q->getTableName() != '?_invoice') { $q->leftJoin('?_invoice', 'i', 't.invoice_id=i.invoice_id'); } $q->addWhere('coupon_code=?', $filter['text']); break; } } if (@$filter['product_id']) { $q->leftJoin('?_invoice_item', 'ii', 't.invoice_id=ii.invoice_id') ->addWhere('ii.item_type=?', 'product') ->addWhere('ii.item_id in (?a)', $filter['product_id']); } if (@$filter['paysys_id']) $q->addWhere('paysys_id in (?a)', $filter['paysys_id']); } public function renderInputs() { $prefix = $this->grid->getId(); $filter = (array) $this->vars['filter']; $filter['datf'] = Am_Html::escape(@$filter['datf']); $filter['dat1'] = Am_Html::escape(@$filter['dat1']); $filter['dat2'] = Am_Html::escape(@$filter['dat2']); $filter['text'] = Am_Html::escape(@$filter['text']); $pOptions = array(); $pOptions = $pOptions + Am_Di::getInstance()->productTable->getOptions(); $pOptions = Am_Html::renderOptions( $pOptions, @$filter['product_id'] ); $paysysOptions = array(); $paysysOptions = $paysysOptions + Am_Di::getInstance()->paysystemList->getOptions(); $paysysOptions = Am_Html::renderOptions( $paysysOptions, @$filter['paysys_id'] ); $options = Am_Html::renderOptions(array( 'invoice' => ___('Invoice Number'), 'receipt' => ___('Payment Receipt'), 'login' => ___('Username'), 'name' => ___('Name'), 'coupon' => ___('Coupon Code') ), @$filter['type']); $dOptions = $this->getDateFieldOptions(); if (count($dOptions) === 1) { $dSelect = sprintf('%s: ', current($dOptions), $prefix, key($dOptions)); } else { $dSelect = sprintf('', $prefix, Am_Html::renderOptions($dOptions, @$filter['datf'])); } $start = ___('Start Date'); $end = ___('End Date'); $offer_product = '-' . ___('Filter by Product') . '-'; $offer_paysys = '-' . ___('Filter by Paysystem') . '-'; return <<
$dSelect
CUT; } public function getDateFieldOptions() { return array('dattm' => ___('Payment Date')); } public function renderStatic() { return << jQuery(function(){ jQuery(document).ajaxComplete(function(){ jQuery('input.datepicker').datepicker({ defaultDate: window.uiDefaultDate, dateFormat:window.uiDateFormat, changeMonth: true, changeYear: true }).datepicker("refresh"); }); }); CUT; } } class Am_Grid_Filter_Payments extends Am_Grid_Filter_Payments_Abstract { public function renderInputs() { return parent::renderInputs() . '
' . $this->renderDontShowRefunded(); } public function renderDontShowRefunded() { $filter = (array) $this->vars['filter']; return sprintf('', $this->grid->getId(), $this->grid->getId(), (@$this->vars['filter']['dont_show_refunded'] == 1 ? 'checked' : ''), Am_Html::escape(___('do not show refunded payments')) ); } protected function applyFilter() { parent::applyFilter(); $filter = (array) $this->vars['filter']; $q = $this->grid->getDataSource(); if (@$filter['dont_show_refunded']) $q->addWhere('t.refund_dattm IS NULL'); } } class Am_Grid_Filter_Invoices extends Am_Grid_Filter_Payments_Abstract { public function renderInputs() { return parent::renderInputs() . '
' . $this->renderAdditioanlInputs(); } protected function renderAdditioanlInputs() { $filter = (array) $this->vars['filter']; $prefix = $this->grid->getId(); $statusOptions = array(); foreach (Invoice::$statusText as $k => $v) { $statusOptions[$k] = ___($v); } $statusOptions = Am_Html::renderOptions( $statusOptions, @$filter['status'] ); $offer_status = '-' . ___('Filter by Status') . '-'; $status = << $statusOptions CUT; $pending = sprintf('', $this->grid->getId(), $this->grid->getId(), (@$this->vars['filter']['dont_show_pending'] == 1 ? 'checked' : ''), Am_Html::escape(___('do not show pending invoices')) ); $active = sprintf('', $this->grid->getId(), $this->grid->getId(), (@$this->vars['filter']['show_only_active'] == 1 ? 'checked' : ''), Am_Html::escape(___('show only invoices with active access')) ); return << $status
$pending
$active
CUT; } protected function applyFilter() { parent::applyFilter(); $filter = (array) $this->vars['filter']; $q = $this->grid->getDataSource(); if (@$filter['dont_show_pending']) $q->addWhere('t.status<>?', Invoice::PENDING); if(@$filter['show_only_active']) { $q->addField('count(a.access_id)', 'access_count'); $curdate = Am_Di::getInstance()->sqlDate; $q->leftJoin('?_access', 'a', "a.invoice_id=t.invoice_id and a.begin_date<='{$curdate}' and a.expire_date>='{$curdate}'"); $q->addHaving('access_count>0'); } if (isset($filter['status']) && $filter['status']) { $q->addWhere('t.status IN (?a)', $filter['status']); } } public function getDateFieldOptions() { return array( 'tm_added' => ___('Added'), 'tm_started' => ___('Started'), 'tm_cancelled' => ___('Cancelled'), 'rebill_date' => ___('Rebill Date') ); } } class Am_Grid_Filter_Refunds extends Am_Grid_Filter_Payments_Abstract { public function getDateFieldOptions() { return array('dattm' => ___('Refund Date')); } } class AdminPaymentsController extends Am_Mvc_Controller_Pages { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission('grid_payment') || $admin->hasPermission('grid_invoice'); } public function initPages() { $admin = $this->getDi()->authAdmin->getUser(); if ($admin->hasPermission('grid_payment')) $this->addPage(array($this, 'createPaymentsPage'), 'index', ___('Payment')); if ($admin->hasPermission('grid_payment')) $this->addPage(array($this, 'createRefundsPage'), 'refunds', ___('Refund')); if ($admin->hasPermission('grid_invoice')) { $this->addPage(array($this, 'createInvoicesPage'), 'invoices', ___('Invoice')); if ($this->getDi()->config->get('manually_approve_invoice')) $this->addPage(array($this, 'createInvoicesPage'), 'not-approved', ___('Not Approved')); } } function createPaymentsPage() { $totalFields = array(); $query = new Am_Query($this->getDi()->invoicePaymentTable); $query->leftJoin('?_user', 'm', 'm.user_id=t.user_id') ->addField("(SELECT GROUP_CONCAT(item_title SEPARATOR ', ') FROM ?_invoice_item WHERE invoice_id=t.invoice_id)", 'items') ->addField('m.login', 'login') ->addField('m.email', 'email') ->addField('m.street', 'street') ->addField('m.street2', 'street2') ->addField('m.city', 'city') ->addField('m.state', 'state') ->addField('m.country', 'country') ->addField('m.phone', 'phone') ->addField('m.zip', 'zip') ->addField("CONCAT(m.name_f,' ',m.name_l)", 'name') ->addField('m.name_f') ->addField('m.name_l') ->addField('DATE(dattm)', 'date') ->addField('t.invoice_public_id', 'public_id'); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { if ($field->sql) { $query->addField('m.'.$field->name, $field->name); } } } $query->setOrder("invoice_payment_id", "desc"); $grid = new Am_Grid_Editable('_payment', ___('Payments'), $query, $this->_request, $this->view); $grid->actionsClear(); $grid->addField(new Am_Grid_Field_Date('dattm', ___('Date/Time'))); $grid->addField('invoice_id', ___('Invoice')) ->setGetFunction(array($this, '_getInvoiceNum')) ->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-user-payments/index/user_id/{user_id}#invoice-{invoice_id}', '_top')); if ($this->getDi()->plugins_tax->isEnabled('vat2015') && $this->getDi()->plugins_tax->loadGet('vat2015')->getConfig('sequential')) { $grid->addField('display_invoice_id', ___('Invoice Number')); if ($this->getDi()->authAdmin->getUser()->isSuper()) { $grid->actionAdd(new Am_Grid_Action_LiveEdit('display_invoice_id')); } } $grid->addField('receipt_id', ___('Receipt')); $grid->addField('paysys_id', ___('Payment System')); array_push($totalFields, $grid->addField('amount', ___('Amount'), true, 'right') ->setGetFunction(array($this, 'getAmount'))); if ($this->getDi()->plugins_tax->getEnabled()) { array_push($totalFields, $grid->addField('tax', ___('Tax'), true, 'right') ->setGetFunction(array($this, 'getTax'))); } $grid->addField(new Am_Grid_Field_Expandable('refund_amount', ___('Refunded'))) ->setPlaceholder(function($amt, $r){ return sprintf('%s', Am_Currency::render($amt, $r->currency)); }) ->setAjax($this->getDi()->url('admin-payments/get-refunds?id={invoice_payment_id}',null,false)) ->setIsNeedExpandFunction(function($val, $obj, $field, $fieldObj){ return !is_null($obj->$field); }); $grid->addField('items', ___('Items')); $grid->addField('login', ___('Username'))->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-users?_u_a=edit&_u_b={THIS_URL}&_u_id={user_id}', '_top') ); $grid->addField('name', ___('Name')); $grid->setFilter(new Am_Grid_Filter_Payments); $action = new Am_Grid_Action_Export(); $action->addField(new Am_Grid_Field('dattm', ___('Date/Time'))) ->addField(new Am_Grid_Field('date', ___('Date'))) ->addField(new Am_Grid_Field('receipt_id', ___('Receipt'))) ->addField(new Am_Grid_Field('paysys_id', ___('Payment System'))) ->addField(new Am_Grid_Field('amount', ___('Amount'))) ->addField(new Am_Grid_Field('tax', ___('Tax'))) ->addField(new Am_Grid_Field('refund_dattm', ___('Refunded Date/Time'))) ->addField(new Am_Grid_Field('refund_amount', ___('Refunded Amount'))) ->addField(new Am_Grid_Field('items', ___('Items'))) ->addField(new Am_Grid_Field('invoice_id', ___('Invoice (Internal Id)'))) ->addField(new Am_Grid_Field('public_id', ___('Invoice (Public Id)'))) ->addField(new Am_Grid_Field('display_invoice_id', ___('Invoice (Sequential Receipt Number)'))); $this->addUserFields($action); $grid->actionAdd($action); if ($this->getDi()->config->get('send_pdf_invoice')) { $grid->actionAdd(new Am_Grid_Action_ExportPdf); } $action = $grid->actionAdd(new Am_Grid_Action_Total()); foreach ($totalFields as $f) { $action->addField($f, 'ROUND(%s / t.base_currency_multi, 2)'); } $grid->setEventId('gridPayment'); return $grid; } function getRefundsAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_payment'); $out = ''; foreach ($this->getDi()->invoiceRefundTable->findByInvoicePaymentId($this->getParam('id')) as $r) { switch ($r->refund_type) { case InvoiceRefund::VOID : $type = ___('void'); break; case InvoiceRefund::CHARGEBACK : $type = ___('chargeback'); break; default : $type = ___('refund'); } $out .= sprintf('%s%s%s%s', amDatetime($r->dattm), Am_Html::escape($r->receipt_id), Am_Currency::render($r->amount, $r->currency), Am_Html::escape($type)); } echo sprintf('
%s
', $out); } function getMultiSelect($obj, $controller, $field=null) { return implode(',', (array)@unserialize($obj->{$field})); } function getStateTitle($obj, $controller, $field=null) { return $this->getDi()->stateTable->getTitleByCode($obj->country, $obj->state); } function getCountryTitle($obj, $controller, $field=null) { return $this->getDi()->countryTable->getTitleByCode($obj->country); } function createRefundsPage() { $query = new Am_Query($this->getDi()->invoiceRefundTable); $query->leftJoin('?_user', 'm', 'm.user_id=t.user_id') ->addField("(SELECT GROUP_CONCAT(item_title SEPARATOR ', ') FROM ?_invoice_item WHERE invoice_id=t.invoice_id)", 'items') ->addField('m.login', 'login') ->addField('m.email', 'email') ->addField('m.street', 'street') ->addField('m.street2', 'street2') ->addField('m.city', 'city') ->addField('m.state', 'state') ->addField('m.country', 'country') ->addField('m.phone', 'phone') ->addField('m.zip', 'zip') ->addField("concat(m.name_f,' ',m.name_l)", 'name') ->addField('m.name_f') ->addField('m.name_l') ->addField('DATE(dattm)', 'date') ->addField('t.invoice_public_id', 'public_id'); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { if ($field->sql) { $query->addField('m.'.$field->name, $field->name); } } } $query->setOrder("invoice_payment_id", "desc"); $grid = new Am_Grid_Editable('_refund', ___('Refunds'), $query, $this->_request, $this->view); $grid->setPermissionId('grid_payment'); $grid->actionsClear(); $grid->addField(new Am_Grid_Field_Date('dattm', ___('Date/Time'))); $grid->addField('invoice_id', ___('Invoice')) ->setGetFunction(array($this, '_getInvoiceNum')) ->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-user-payments/index/user_id/{user_id}#invoice-{invoice_id}', '_top')); $grid->addField('receipt_id', ___('Receipt')); $grid->addField('paysys_id', ___('Payment System')); $fieldAmount = $grid->addField('amount', ___('Amount'), true, 'right') ->setGetFunction(array($this, 'getAmount')); $grid->addField('items', ___('Items')); $grid->addField('login', ___('Username'))->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-users?_u_a=edit&_u_b={THIS_URL}&_u_id={user_id}', '_top') ); $grid->addField('name', ___('Name')); $grid->setFilter(new Am_Grid_Filter_Refunds); $action = new Am_Grid_Action_Export(); $action->addField(new Am_Grid_Field('dattm', ___('Date/Time'))) ->addField(new Am_Grid_Field('date', ___('Date'))) ->addField(new Am_Grid_Field('receipt_id', ___('Receipt'))) ->addField(new Am_Grid_Field('paysys_id', ___('Payment System'))) ->addField(new Am_Grid_Field('amount', ___('Amount'))) ->addField(new Am_Grid_Field('items', ___('Items'))) ->addField(new Am_Grid_Field('invoice_id', ___('Invoice (Internal Id)'))) ->addField(new Am_Grid_Field('public_id', ___('Invoice (Public Id)'))) ->addField(new Am_Grid_Field('display_invoice_id', ___('Refund (Sequential Receipt Number)'))); $this->addUserFields($action); $grid->actionAdd($action); if ($this->getDi()->config->get('send_pdf_invoice')) { $grid->actionAdd(new Am_Grid_Action_ExportPdf); } $action = $grid->actionAdd(new Am_Grid_Action_Total()); $action->addField($fieldAmount, 'ROUND(%s / t.base_currency_multi, 2)'); $grid->setEventId('gridRefund'); return $grid; } function getAmount(Am_Record $p) { return Am_Currency::render($p->amount, $p->currency); } function getTax(InvoicePayment $p) { return Am_Currency::render($p->tax, $p->currency); } function _getInvoiceNum(Am_Record $invoice) { return $invoice->invoice_id . '/' . $invoice->public_id; } function createInvoicesPage($page) { $query = new Am_Query($this->getDi()->invoiceTable); if ($page == 'not-approved') $query->addWhere('is_confirmed<1'); $query->leftJoin('?_user', 'm', 'm.user_id=t.user_id') ->addField("(SELECT GROUP_CONCAT(item_title SEPARATOR ', ') FROM ?_invoice_item WHERE invoice_id=t.invoice_id)", 'items') ->addField('m.login', 'login') ->addField('m.email', 'email') ->addField('m.street', 'street') ->addField('m.street2', 'street2') ->addField('m.city', 'city') ->addField('m.state', 'state') ->addField('m.country', 'country') ->addField('m.phone', 'phone') ->addField('m.zip', 'zip') ->addField("concat(m.name_f,' ',m.name_l)", 'name') ->addField('m.name_f') ->addField('m.name_l') ->addField('DATE(tm_started)', 'date'); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { if ($field->sql) { $query->addField('m.'.$field->name, $field->name); } } } $query->setOrder("invoice_id", "desc"); $grid = new Am_Grid_Editable('_invoice', ___('Invoices'), $query, $this->_request, $this->view); $grid->setRecordTitle(array($this, 'getInvoiceRecordTitle')); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_Delete())->setTarget('_top'); $grid->addField(new Am_Grid_Field_Date('tm_added', ___('Added'))); $grid->addField('invoice_id', ___('Invoice'))->setGetFunction(array($this, '_getInvoiceNum'))->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-user-payments/index/user_id/{user_id}#invoice-{invoice_id}', '_top') ); $grid->addField('status', ___('Status'))->setRenderFunction(array($this, 'renderInvoiceStatus')); $grid->addField('paysys_id', ___('Payment System')); $grid->addField('_total', ___('Billing Terms'), false)->setGetFunction(array($this, 'getInvoiceTotal')); $grid->addField(new Am_Grid_Field_Date('rebill_date', ___('Rebill Date')))->setFormatDate(); $grid->addField('items', ___('Items')); $grid->addField('login', ___('Username'))->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-users?_u_a=edit&_u_b={THIS_URL}&_u_id={user_id}', '_top') ); $grid->addField('name', ___('Name')); $filter = new Am_Grid_Filter_Invoices(); $grid->setFilter($filter); $termsField = new Am_Grid_Field('_total', ___('Billing Terms')); $termsField->setGetFunction(array($this, 'getInvoiceTotal')); $action = new Am_Grid_Action_Export(); $action->addField(new Am_Grid_Field('tm_started', ___('Date/Time'))) ->addField(new Am_Grid_Field('date', ___('Date'))) ->addField(new Am_Grid_Field('rebill_date', ___('Rebill Date'))) ->addField(new Am_Grid_Field('invoice_id', ___('Invoice (Internal Id)'))) ->addField(new Am_Grid_Field('public_id', ___('Invoice (Public Id)'))) ->addField(new Am_Grid_Field('status', ___('Status'))) ->addField($termsField) ->addField(new Am_Grid_Field('paysys_id', ___('Payment System'))) ->addField(new Am_Grid_Field('first_total', ___('First Total'))) ->addField(new Am_Grid_Field('first_tax', ___('First Tax'))) ->addField(new Am_Grid_Field('item_title', ___('Product Title'))) ->addField(new Am_Grid_Field('coupon_code', ___('Coupon'))); $this->addUserFields($action); $action->setGetDataSourceFunc(array($this, 'getExportDs')); $grid->actionAdd($action); if ($this->getDi()->config->get('manually_approve_invoice')) $grid->actionAdd(new Am_Grid_Action_Group_Callback('approve', ___("Approve"), array($this, 'approveInvoice'))); $grid->setEventId('gridInvoice'); return $grid; } public function addUserFields(Am_Grid_Action_Export $action) { $stateTitleField = new Am_Grid_Field('state_title', ___('State Title')); $stateTitleField->setGetFunction(array($this, 'getStateTitle')); $countryTitleField = new Am_Grid_Field('country_title', ___('Country Title')); $countryTitleField->setGetFunction(array($this, 'getCountryTitle')); $action->addField(new Am_Grid_Field('email', ___('Email'))) ->addField(new Am_Grid_Field('login', ___('Username'))) ->addField(new Am_Grid_Field('name', ___('Name'))) ->addField(new Am_Grid_Field('name_f', ___('First Name'))) ->addField(new Am_Grid_Field('name_l', ___('Last Name'))) ->addField(new Am_Grid_Field('street', ___('Street'))) ->addField(new Am_Grid_Field('street2', ___('Street2'))) ->addField(new Am_Grid_Field('city', ___('City'))) ->addField(new Am_Grid_Field('state', ___('State'))) ->addField($stateTitleField) ->addField(new Am_Grid_Field('country', ___('Country'))) ->addField($countryTitleField) ->addField(new Am_Grid_Field('phone', ___('Phone'))) ->addField(new Am_Grid_Field('zip', ___('Zip Code'))); //Additional Fields foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) { if ($field->sql) { if(in_array($field->type, array('multi_select','checkbox'))){ $f = new Am_Grid_Field($field->name, $field->title . ' (Value)'); $f->setGetFunction(array($this,'getMultiSelect')); $action->addField($f); $op = $field->options; $fn = $field->name; $f = new Am_Grid_Field($field->name . '_label', $field->title . ' (Label)'); $f->setGetFunction(function($obj, $controller, $field=null) use ($op, $fn){ return implode(',', array_map(function($el) use ($op) { return isset($op[$el]) ? $op[$el] : $el; }, (array)@unserialize($obj->{$fn}))); }); $action->addField($f); } else { $action->addField(new Am_Grid_Field($field->name, $field->title)); } } } } } public function getInvoiceRecordTitle(Invoice $invoice = null) { return $invoice ? sprintf('%s (%s/%s, %s: %s)', ___('Invoice'), $invoice->pk(), $invoice->public_id, ___('Billing Terms'), new Am_TermsText($invoice)) : ___('Invoice'); } public function getExportDs(Am_Query $ds) { return $ds->leftJoin('?_invoice_item', 'iititle', 'iititle.invoice_id=t.invoice_id') ->addField('iititle.item_title', 'item_title'); } public function getInvoiceTotal(Invoice $invoice) { return $invoice->getTerms(); } public function renderInvoiceStatus(Invoice $invoice) { return '' . $invoice->getStatusTextColor() . ''; } public function approveInvoice($id, Invoice $invoice) { $invoice->approve(); } }PK\D..0default/controllers/AdminCountriesController.phpnu[vars['s']) { $cond = $this->vars['s'] > 0 ? '>=' : '<'; $this->grid->getDataSource()->getDataSourceQuery() ->addWhere("tag $cond 0"); } } public function renderInputs() { return $this->renderInputText() . ' ' . $this->renderInputSelect('s', array( '' => ___('Filter by Status'), -1 => ___('Disabled'), 1 => ___('Enabled') )); } } class Am_Grid_Action_Group_CountryStateEnable extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; protected $enable = true; public function __construct($enable = true) { $this->enable = (bool) $enable; parent::__construct($enable ? "enable" : "disable", $enable ? ___("Enable") : ___("Disable")); } public function handleRecord($id, $record) { if ($this->enable) { if ($record->tag < 0) { $record->updateQuick('tag', -1 * $record->tag); } } else { if ($record->tag >= 0) { $record->updateQuick('tag', $record->tag ? -1 * $record->tag : -1); } } } } class AdminCountriesController extends Am_Mvc_Controller_Grid { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_COUNTRY_STATE); } function createForm() { $form = new Am_Form_Admin; $form->addInteger("tag")->setLabel(___("Sort order"))->addRule('required'); $form->addAdvCheckbox('_is_disabled')->setLabel(___('Is Disabled?')); $form->addText("title")->setLabel(___("Title"))->addRule('required'); return $form; } public function createGrid() { $ds = new Am_Query($this->getDi()->countryTable); $ds->addField('ABS(tag)', 'tag_abs') ->setOrderRaw('tag_abs desc, title'); $grid = new Am_Grid_Editable('_c', ___("Browse Countries"), $ds, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_COUNTRY_STATE); $grid->addField(new Am_Grid_Field('tag_abs', ___('Sort Order'), true, null, null, '10%')); $grid->addField(new Am_Grid_Field('title', ___('Title'), true)); $grid->addField(new Am_Grid_Field('country', ___('Code'), true)); $grid->setForm(array($this, 'createForm')); $grid->actionAdd(new Am_Grid_Action_Url('states', ___('Edit States'), 'admin-states?country={country}'))->setTarget('_top'); $grid->actionDelete('delete'); $grid->actionDelete('insert'); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this,'getTrAttribs')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_FROM_FORM, array($this, 'valuesFromForm')); $grid->actionAdd(new Am_Grid_Action_LiveEdit('title')); $grid->actionAdd(new Am_Grid_Action_Group_CountryStateEnable(false)); $grid->actionAdd(new Am_Grid_Action_Group_CountryStateEnable(true)); $grid->setFilter(new Am_Grid_Filter_CountryState(' ', array('title' => 'LIKE'), array('placeholder' => ___('Counrty Title')))); return $grid; } function valuesToForm(& $values, Country $record) { if($record->tag < 0) { $values['_is_disabled'] = 1; $values['tag']*=-1; } else { $values['_is_disabled'] = 0; } } function valuesFromForm(& $values, Country $record) { if($values['_is_disabled']) { $values['tag'] = ($values['tag'] ? $values['tag']*-1 : -1); } } public function getTrAttribs(& $ret, $record) { if ($record->tag < 0) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } }PK\"u<&default/controllers/AjaxController.phpnu[getRequest()->isXmlHttpRequest()) { throw new Am_Exception_InputError; } } function ajaxError($msg) { $this->_response->ajaxResponse(array('msg' => $msg)); } function ajaxGetStates($vars) { return $this->_response->ajaxResponse($this->getDi()->stateTable->getOptions($vars['country'])); } function ajaxCheckUniqLogin($vars) { $user_id = $this->getDi()->auth->getUserId(); if (!$user_id) { $user_id = $this->getDi()->session->signup_member_id; } $login = $vars['login']; $msg = null; if (!$this->getDi()->userTable->checkUniqLogin($login, $user_id)) { $msg = ___('Username %s is already taken. Please choose another username', Am_Html::escape($login)); } if (!$msg) { $msg = $this->getDi()->banTable->checkBan(array('login'=>$login)); } return $this->_response->ajaxResponse($msg ? $msg : true); } function ajaxCheckUniqEmail($vars) { $user_id = $this->getDi()->auth->getUserId(); if (!$user_id) { $user_id = $this->getDi()->session->signup_member_id; } $email = $vars['email']; $msg = null; if(isset($vars['_url'])) { $url = $vars['_url']; } else { $url = $this->getDi()->url('member'); } if (!$this->getDi()->userTable->checkUniqEmail($email, $user_id)) $msg = ___('An account with the same email already exists.').'
'. ___('Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login','','','
'); if (!$msg) { $msg = $this->getDi()->banTable->checkBan(array('email'=>$email)); } if (!$msg && !Am_Validate::email($email)) { $msg = ___('Please enter valid Email'); } return $this->_response->ajaxResponse($msg ? $msg : true); } function ajaxCheckCoupon($vars) { if (!$vars['coupon']) return $this->_response->ajaxResponse(true); $user_id = $this->getDi()->auth->getUserId(); if (!$user_id) $user_id = $this->getDi()->session->signup_member_id; $coupon = $this->getDi()->couponTable->findFirstByCode($vars['coupon']); $msg = $coupon ? $coupon->validate($user_id) : ___('No coupons found with such coupon code'); return $this->_response->ajaxResponse(is_null($msg) ? true : $msg); } function indexAction() { $vars = $this->_request->toArray(); switch ($this->_request->getFiltered('do')){ case 'get_states': $this->ajaxGetStates($vars); break; case 'check_uniq_login': $this->ajaxCheckUniqLogin($vars); break; case 'check_uniq_email': $this->ajaxCheckUniqEmail($vars); break; case 'check_coupon': $this->ajaxCheckCoupon($vars); break; default: $this->ajaxError('Unknown Request: ' . $vars['do']); } } function invoiceSummaryAction() { $invoice = $this->getDi()->invoiceRecord; $vars = $this->getRequest()->getParams(); if(!$user = $this->getDi()->auth->getUser()) { $user = $this->getDi()->userRecord; $user->user_id = -1; } $user->toggleFrozen(true); if($vars['country']) { $user->country = $vars['country']; } if($vars['state']) { $user->state = $vars['state']; } if($vars['zip']) { $user->zip = $vars['zip']; } if (isset($vars['tax_id'])) { $user->tax_id = $vars['tax_id']; } $invoice->setUser($user); $param = array(); $page_current = $this->getRequest()->getParam('_save_'); $vars_added = false; foreach ($_SESSION['amember']['_signup_container']['values'] as $page => $v) { if ($page == $page_current) { $v = array_merge($v, $vars); $vars_added = true; } $param = array_merge($param, $v); } $vars = $vars_added ? $param : array_merge($param, $vars); foreach ($vars as $k => $v) { if (strpos($k, 'product_id')===0) { foreach ((array)$vars[$k] as $key => $product_id) { if (substr($key, 0, 4) == '_qty') continue; @list($product_id, $plan_id, $qty) = explode('-', $product_id, 3); $qty_key = sprintf('_qty-%d-%d', $product_id, $plan_id); if (isset($vars[$k][$qty_key])) $qty = $vars[$k][$qty_key]; $product_id = (int)$product_id; if (!$product_id) continue; $p = $this->getDi()->productTable->load($product_id); if ($plan_id > 0) $p->setBillingPlan(intval($plan_id)); $qty = (int)$qty; if (!$p->getBillingPlan()->variable_qty || ($qty <= 0)) $qty = 1; $plan_id = $p->getBillingPlan()->pk(); $options = array(); if (!empty($vars['productOption']["$product_id-$plan_id"])) { $options = $vars['productOption']["$product_id-$plan_id"][0]; } $prOpt = $p->getOptions(true); foreach ($options as $opk => $opv) { $options[$opk] = array('value' => $opv, 'optionLabel' => $prOpt[$opk]->title, 'valueLabel' => $prOpt[$opk]->getOptionLabel($opv)); } $invoice->add($p, $qty, $options); } } } if (!empty($vars['coupon'])) { $invoice->setCouponCode($vars['coupon']); $invoice->validateCoupon(); } $this->_handleDonation($invoice, $vars); $invoice->calculate(); $v = $this->getDi()->view; $v->invoice = $invoice; $v->display('_invoice-summary.phtml'); } function _handleDonation(Invoice $invoice, $vars) { //we take into account only first period - it is just preview foreach ($invoice->getItems() as $item) { if ($item->item_type == 'product' && isset($vars['donation'][$item->item_id])) { if (!$vars['donation'][$item->item_id] && !$vars['donation_allow_free'][$item->item_id]) { $invoice->deleteItem($item); } else { $item->first_price = $vars['donation'][$item->item_id]; $item->data()->set('orig_first_price', $item->first_price); } } } } function unsubscribedAction() { $v = $this->_request->getPost('unsubscribed'); if (strlen($v) != 1) throw new Am_Exception_InputError("Wrong input"); $v = ($v > 0) ? 1 : 0; if (($s = $this->getFiltered('s')) && ($e = $this->getParam('e')) && Am_Mail::validateUnsubscribeLink($e, $s)) { $user = $this->getDi()->userTable->findFirstByEmail($e); } else { $user = $this->getDi()->user; } if (!$user) return $this->ajaxError(___('You must be logged-in to run this action')); if ($user->unsubscribed != $v) { $user->set('unsubscribed', $v)->update(); $this->getDi()->hook->call(Am_Event::USER_UNSUBSCRIBED_CHANGED, array('user'=>$user, 'unsubscribed' => $v)); } $this->_response->ajaxResponse(array('status' => 'OK', 'value' => $v)); } }PK\*< 7default/controllers/AdminCurrencyExchangeController.phpnu[getParam('filter'); if (!empty($filter['currency'])) { $this->grid->getDataSource()->addWhere('currency=?', $filter['currency']); } } public function renderInputs() { $gridId = $this->grid->getId(); $options = array_merge(array(''=>''), Am_Currency::getSupportedCurrencies()); array_remove_value($options, Am_Currency::getDefault()); $filter = $this->getParam('filter'); return sprintf("\n", Am_Html::renderOptions($options, @$filter['currency'])); } } class AdminCurrencyExchangeController extends Am_Mvc_Controller_Grid { public function checkAdminPermissions(Admin $admin) { return $admin->isSuper(); } public function createGrid() { $grid = new Am_Grid_Editable('_curr', ___('Currency Exchange Rates'), new Am_Query($this->getDi()->currencyExchangeTable), $this->_request, $this->view); $grid->setFilter(new Am_Grid_Filter_CurrencyExchange); $grid->addField('currency', ___('Currency')); $grid->addField(new Am_Grid_Field_Date('date', ___('Date')))->setFormatDate(); $grid->addField('rate', ___('Exchange Rate')); $grid->setForm(array($this, 'createForm')); return $grid; } public function createForm() { $form = new Am_Form_Admin; $options = Am_Currency::getSupportedCurrencies(); array_remove_value($options, Am_Currency::getDefault()); $sel = $form->addSelect('currency', array('class' => 'am-combobox')) ->setLabel(___('Currency')) ->loadOptions($options) ->addRule('required'); $date = $form->addDate('date')->setLabel(___('Date')) ->addRule('required') ->addRule('callback2', "--wrong date--", array($this, 'checkDate')); $rate = $form->addText('rate', array('length' => 8)) ->setLabel(___("Exchange Rate\nenter cost of 1 (one) %s", Am_Currency::getDefault())) ->addRule('required'); return $form; } public function checkDate($date) { if ($date < $this->getDi()->sqlDate) return ___('You can not set up exchange rate for past.'); } } PK\6G1default/controllers/AdminTransLocalController.phpnu[_createGrid(___('Local Translations')); } protected function createDS($language) { return new Am_Grid_DataSource_Array_Trans_Local($language); } public function getTransAction() { echo json_encode( $this->getTrans($this->getRequest()->getParam('text')) ); } protected function getTransStat($text) { $res = $this->getTrans($text); $total = count($this->getDi()->config->get('lang.enabled'))-1; $stat = array ( 'total' => ($total < 0 ? 0 : $total), 'translated' => 0 ); $default = $this->getDi()->config->get('lang.default', 'en'); foreach ($res as $lang => $trans) { if (trim($trans) && $lang!=$default) { $stat['translated']++; } } return $stat; } public function updateTransAction() { foreach ($this->getRequest()->getParam('trans') as $lang => $trans) { $toReplace = array(); $toReplace[$this->getRequest()->getParam('text')] = $trans; $this->getDi()->translationTable->replaceTranslation($toReplace, $lang); } Zend_Translate::hasCache() && Zend_Translate::clearCache(); } public function synchronizeAction() { $text = $this->getRequest()->getParam('text'); $res = array( 'form' => $this->getTransForm($text), 'stat' => $this->getTransStat($text) ); $this->_response->ajaxResponse( $res ); } public function synchronizeBatchAction() { $text = $this->getRequest()->getParam('text'); $res = array(); foreach ($text as $t) { $res[$t] = array( 'form' => $this->getTransForm($t), 'stat' => $this->getTransStat($t) ); } $this->_response->ajaxResponse( $res ); } protected function getTransForm($text) { $trans = $this->getTrans($text); $lgList = $this->getDi()->languagesListUser; $form = new Am_Form_Admin(); $form->setAction($this->getUrl(null, 'update-trans')); $default = $this->getDi()->config->get('lang.default', 'en'); $form->addStatic('text_default')->setContent( sprintf("
%s
", $this->escape($text)) ); foreach ($trans as $lg=>$t) { if ($lg!=$default) { $form->addElement('textarea', 'trans[' . $lg . ']', array('class' => 'el-wide')) ->setLabel($lgList[$lg]) ->setValue($t); } } $form->addElement('hidden', 'text') ->setValue($text); return (string)$form; } protected function getTrans($text) { $result = array(); $langs = $this->getDi()->config->get('lang.enabled', array()); $tDataSource = new TranslationDataSource_DB(); foreach ($langs as $lg) { $td = $tDataSource->getTranslationData($lg); $result[$lg] = (isset($td[$text])) ? $td[$text] : ''; } return $result; } }PK\)y /default/controllers/AdminProductsController.phpnu[hasPermission('grid_product'); } public function __construct($plans) { $this->plans = (array) $plans; parent::__construct('admin-product'); } function addBillingPlans() { if (!$plans = $this->plans) { $plans[] = array( 'title' => ___('Default Billing Plan'), 'plan_id' => 0, 'currency' => Am_Currency::getDefault() ); } $plans[] = array( 'title' => 'TEMPLATE', 'plan_id' => 'TPL', 'currency' => Am_Currency::getDefault() ); $this->addRaw() ->setContent('
'); foreach ($plans as $plan) { $fieldSet = $this->addElement('fieldset', '', array('id' => 'plan-' . $plan['plan_id'], 'class' => 'billing-plan')) ->setLabel('' . ($plan['title'] ? $plan['title'] : "title - click to edit") . '' . sprintf(' ', $plan['plan_id'], Am_Html::escape($plan['title']))); $this->addBillingPlanElements($fieldSet, $plan['plan_id']); } $this->addRaw() ->setContent('
'); $this->addScript() ->setScript(<<addSelect("{$prefix}currency{$suffix}") ->setLabel(___("Currency\n" . 'you can choose from list of currencies supported by paysystems')) ->loadOptions(Am_Currency::getSupportedCurrencies()); $gr = $fieldSet->addGroup() ->setLabel(___("First Price\n" . "price of first period of subscription")); $firstPrice = $gr->addText($prefix . 'first_price' . $suffix, array('size'=>7)); $firstPrice->addRule('gte', ___('must be equal or greather than 0'), 0.0) ->addRule('regex', ___('must be a number in format 99 or 99.99'), '/^(\d+(\.\d+)?|)$/'); $gr->addStatic() ->setContent(' '); $firstPeriod = $fieldSet->addPeriod($prefix . 'first_period' . $suffix) ->setLabel(___('First Period')); $group = $fieldSet->addGroup()->setLabel( ___("Rebill Times\n" . "This is the number of payments which\n" . "will occur at the Second Price")); $group->setSeparator(' '); $sel = $group->addSelect($prefix . '_rebill_times' . $suffix)->setId('s_rebill_times'); $sel->addOption(___('No more charges'), 0); $sel->addOption(___('Charge Second Price Once'), 1); $sel->addOption(___('Charge Second Price x Times'), 'x'); $sel->addOption(___('Rebill Second Price until cancelled'), IProduct::RECURRING_REBILLS); $txt = $group->addText($prefix . 'rebill_times' . $suffix, array('size' => 3, 'maxlength' => 6))->setId('t_rebill_times'); $gr = $fieldSet->addGroup() ->setLabel( ___("Second Price\n" . "price that must be billed for second and\n" . "the following periods of subscription")); $secondPrice = $gr->addText($prefix . 'second_price' . $suffix, array('size'=>7)); $secondPrice->addRule('gte', ___('must be equal or greather than 0.0'), 0.0) ->addRule('regex', ___('must be a number in format 99 or 99.99'), '/^\d+(\.\d+)?$/'); $gr->addStatic() ->setContent(' '); $secondPeriod = $fieldSet->addPeriod($prefix . 'second_period' . $suffix) ->setLabel(___('Second Period')); $secondPeriod = $fieldSet->addText($prefix . 'terms' . $suffix, array('size' => 40, 'class' => 'translate')) ->setLabel(___("Terms Text\nautomatically calculated if empty")); $fs = $fieldSet->addGroup() ->setLabel(___("Quantity\ndefault - 1, normally you do not need to change it\nFirst and Second Price is the total for specified qty")); $fs->setSeparator(' '); $fs->addInteger($prefix . 'qty' . $suffix, array('placeholder' => 1, 'size'=>3)); $fs->addCheckbox($prefix . 'variable_qty' . $suffix, array('class' => 'variable_qty')) ->setContent(___('allow user to change quantity')); if (Am_Di::getInstance()->config->get('product_paysystem')) { $fieldSet->addMagicSelect($prefix . 'paysys_id' . $suffix) ->setLabel(___("Payment System\n" . "Choose payment system to be used with this product")) ->loadOptions(Am_Di::getInstance()->paysystemList->getOptions()); } foreach (Am_Di::getInstance()->billingPlanTable->customFields()->getAll() as $k => $f) { $el = $f->addToQf2($fieldSet); $el->setName($prefix . $el->getName() . $suffix); } } function checkBillingPlanExists(array $vals) { foreach ($vals['_plan'] as $k => $v) { if ($k === 'TPL') continue; if (strlen($v['first_price']) && strlen($v['first_period'])) return true; } return false; } function init() { $this->addElement('hidden', 'product_id'); $this->addRule('callback', ___('At least one billing plan must be added'), array($this, 'checkBillingPlanExists')); /* General Settings */ $fieldSet = $this->addElement('fieldset', 'general') ->setLabel(___('General Settings')); $fieldSet->addText('title', array('size' => 40, 'class' => 'translate')) ->setLabel(___('Title')) ->addRule('required'); $fieldSet->addTextarea('description', array('class' => 'translate')) ->setLabel(___( "Description\n" . "displayed to visitors on order page below the title")) ->setAttribute('cols', 40)->setAttribute('rows', 2); $fieldSet->addTextarea('comment', array('class' => 'el-wide')) ->setLabel(___("Comment\nfor admin reference")) ->setAttribute('rows', 2); $fieldSet->addCategory('_categories', null, array( 'base_url' => 'admin-product-categories', 'link_title' => ___('Edit Categories'), 'title' => ___('Product Categories'), 'options' => Am_Di::getInstance()->productCategoryTable->getOptions())) ->setLabel(___('Product Categories')); /* Billing Settings */ $fieldSet = $this->addElement('fieldset', 'billing', array('id' =>'billing')) ->setLabel(___('Billing')); if (Am_Di::getInstance()->plugins_tax->getEnabled()) { $fieldSet->addAdvCheckbox('tax_group', array('value' => IProduct::ALL_TAX)) ->setLabel(___('Apply Tax?')); } $this->addBillingPlans(); /* Product availability */ $fieldSet = $this->addAdvFieldset('avail') ->setLabel(___('Product Availability')); $this->insertAvailablilityFields($fieldSet); $sdGroup = $fieldSet->addGroup()->setLabel(___( "Start Date Calculation\n" . "rules for subscription start date calculation.\n" . "MAX date from alternatives will be chosen.\n" . "This settings has no effect for recurring subscriptions")); $sd = $sdGroup->addSelect('start_date', array('multiple' => 'mutliple', 'id' => 'start-date-edit',)); $sd->loadOptions(array( Product::SD_PRODUCT => ___('Last existing subscription date of this product'), Product::SD_GROUP => ___('Last expiration date in the renewal group'), Product::SD_FIXED => ___('Fixed date'), Product::SD_PAYMENT => ___('Payment date'), ___('Nearest') => array( Product::SD_WEEKDAY_SUN => ___('Nearest Sunday'), Product::SD_WEEKDAY_MON => ___('Nearest Monday'), Product::SD_WEEKDAY_TUE => ___('Nearest Tuesday'), Product::SD_WEEKDAY_WED => ___('Nearest Wednesday'), Product::SD_WEEKDAY_THU => ___('Nearest Thursday'), Product::SD_WEEKDAY_FRI => ___('Nearest Friday'), Product::SD_WEEKDAY_SAT => ___('Nearest Saturday'), Product::SD_MONTH_1 => ___('Nearest 1st Day of Month'), Product::SD_MONTH_15 => ___('Nearest 15th Day of Month') ) )); $sdGroup->addDate('start_date_fixed', array('style' => 'display:none; font-size: xx-small')); $rgroups = Am_Di::getInstance()->productTable->getRenewalGroups(); $roptions = array('' => ___('-- Please Select --')); if ($rgroups) { $roptions = $roptions + array_filter($rgroups); } $fieldSet->addSelect('renewal_group', array(), array('intrinsic_validation' => false, 'options' => $roptions)) ->setLabel(___("Renewal Group\n" . "Allows you to set up sequential or parallel subscription periods. " . "Subscriptions from the same group will begin at the end of " . "subscriptions from the same group. Subscriptions from different " . "groups can run side-by-side")); /* Additional Options */ $this->insertAdditionalFields(); $this->insertOptions(); } function insertOptions() { $fs = $this->addAdvFieldset('options') ->setLabel(___('Product Options')); $fs1 = $fs->addGroup('', array('id' => 'am-product-option-group-TPL', 'class' => 'no-label',)); $types = Am_Html::renderOptions(array( '' => '', 'text' => ___('Text'), 'select' => ___('Select (Single Value)'), 'multi_select' => ___('Select (Multiple Values)'), 'textarea' => ___('TextArea'), 'radio' => ___('RadioButtons'), 'checkbox' => ___('CheckBoxes'), 'date' => ___('Date'), // 'upload' => ___('Upload'), // not implemented yet // 'multi_upload' => ___('Multi Upload'), )); $title = ___("Title"); $required = ___("Required") ; $edit_options = ___("Edit Options"); $sort_img = Am_Html::escape(Am_Di::getInstance()->view->_scriptImg('sortable.png')); $fs1->addHtml()->setHtml( << [X]       $required   CUT ); $fs->addHtml(null, array('class' => 'no-label'))->setHtml(''.___('Add Option').''); $fs->addHidden('_options', array('id' => 'am-product-options-hidden')); } function insertAvailablilityFields($fieldSet) { $fieldSet->addAdvCheckbox('is_disabled')->setLabel(___("Is Disabled?\n" . "disable product ordering, hide it from signup and renewal forms")); // add require another subscription field $require_options = array(/* '' => "Don't require anything (default)" */); $prevent_options = array(/* '' => "Don't prevent anything (default)" */); foreach (Am_Di::getInstance()->productTable->getOptions() as $id => $title) { $title = Am_Html::escape($title); $require_options['ACTIVE-' . $id] = ___('ACTIVE %s', $title); $require_options['EXPIRED-' . $id] = ___('EXPIRED %s', $title); $prevent_options['ACTIVE-' . $id] = ___('ACTIVE %s', $title); $prevent_options['EXPIRED-' . $id] = ___('EXPIRED %s', $title); } $require_group_options = array(); $prevent_group_options = array(); foreach (Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions() as $id => $title) { $title = Am_Html::escape($title); $require_group_options['CATEGORY-ACTIVE-' . $id] = ___('ACTIVE category %s', '"' . $title . '"'); $require_group_options['CATEGORY-EXPIRED-' . $id] = ___('EXPIRED category %s', '"' . $title . '"'); $prevent_group_options['CATEGORY-ACTIVE-' . $id] = ___('ACTIVE category %s', '"' . $title . '"'); $prevent_group_options['CATEGORY-EXPIRED-' . $id] = ___('EXPIRED category %s', '"' . $title . '"'); } if (count($require_group_options)) { $rOptions = array( ___('Products') => $require_options, ___('Product Categories') => $require_group_options ); $pOptions = array( ___('Products') => $prevent_options, ___('Product Categories') => $prevent_group_options ); } else { $rOptions = $require_options; $pOptions = $prevent_options; } $fieldSet->addMagicSelect('require_other', array('multiple' => 'multiple', 'class' => 'magicselect am-combobox-fixed')) ->setLabel(___("To order this product user must have an\n" . "when user orders this subscription, it will be checked\n" . "that user has one from the following subscriptions" )) ->loadOptions($rOptions); $fieldSet->addMagicSelect('prevent_if_other', array('multiple' => 'multiple', 'class' => 'magicselect am-combobox-fixed')) ->setLabel(___("Disallow ordering of this product if user has\n" . "when user orders this subscription, it will be checked\n" . "that he has no any from the following subscriptions" )) ->loadOptions($pOptions); } function insertAdditionalFields() { $fields = Am_Di::getInstance()->productTable->customFields()->getAll(); $exclude = array(); foreach ($fields as $k => $f) if (!in_array($f->name, $exclude)) $el = $f->addToQf2($this->getAdditionalFieldSet()); } function getAdditionalFieldSet() { $fieldSet = $this->getElementById('additional'); if (!$fieldSet) { $fieldSet = $this->addElement('fieldset', 'additional') ->setId('additional') ->setLabel(___('Additional')); } return $fieldSet; } } class Am_Grid_Filter_Product extends Am_Grid_Filter_Abstract { protected function applyFilter() { $query = $this->grid->getDataSource(); if ($s = @$this->vars['filter']['text']) { $query->add(new Am_Query_Condition_Field('title', 'LIKE', '%' . $s . '%')) ->_or(new Am_Query_Condition_Field('product_id', '=', $s)); } if ($category_id = @$this->vars['filter']['category_id']) { $query->leftJoin("?_product_product_category", "ppc"); $query->addWhere("ppc.product_category_id=?d", $category_id); } if (@$this->vars['filter']['dont_show_disabled']) { $query->addWhere("t.is_disabled=0"); } } public function renderInputs() { $options = array('' => '-' . ___('Filter by Category') . '-'); $options = $options + Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions( array(ProductCategoryTable::COUNT => true)); $options = Am_Html::renderOptions( $options, @$this->vars['filter']['category_id'] ); $out = sprintf(' ' . PHP_EOL, $options); $this->attributes['value'] = (string) $this->vars['filter']['text']; $out .= $this->renderInputText('filter[text]'); $out .= '
' . $this->renderShowDisabled(); return $out; } public function renderShowDisabled() { return sprintf('', $this->grid->getId(), $this->grid->getId(), (@$this->vars['filter']['dont_show_disabled'] == 1 ? 'checked' : ''), Am_Html::escape(___('do not show disabled products')) ); } } class Am_Grid_Action_Group_ProductAssignCategory extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; protected $remove = false; public function __construct($removeCategory = false) { $this->remove = (bool) $removeCategory; parent::__construct( !$removeCategory ? "product-assign-category" : "product-remove-category", !$removeCategory ? ___("Assign Category") : ___("Remove Category") ); } public function renderConfirmationForm($btn = "Yes, assign", $page = null, $addHtml = null) { $select = sprintf('

' . PHP_EOL, $this->grid->getId(), Am_Html::renderOptions(Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions()) ); return parent::renderConfirmationForm($this->remove ? ___("Yes, remove category") : ___("Yes, assign category"), $select); } /** * @param int $id * @param Product $record */ public function handleRecord($id, $record) { $category_id = $this->grid->getRequest()->getInt('category_id'); if (!$category_id) throw new Am_Exception_InternalError("category_id empty"); $categories = $record->getCategories(); if ($this->remove) { if (!in_array($category_id, $categories)) return; foreach ($categories as $k => $id) if ($id == $category_id) unset($categories[$k]); } else { if (in_array($category_id, $categories)) return; $categories[] = $category_id; } $record->setCategories($categories); } } class Am_Grid_Action_Group_ChangeOrder extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; public function renderConfirmationForm($btn = "Yes, assign", $addHtml = null) { $select = sprintf('%s

'.PHP_EOL, ___('Put Chosen Products After'), $this->grid->getId(), Am_Html::renderOptions(Am_Di::getInstance()->productTable->getOptions()) ); return parent::renderConfirmationForm(___("Change Order"), $select); } /** * @param int $id * @param User $record */ public function handleRecord($id, $record) { $ids = $this->getIds(); $after = null; foreach ($ids as $k => $v) { if ($v == $id) { $after = isset($ids[$k-1]) ? $ids[$k-1] : $this->grid->getRequest()->getInt('_product_id'); break; } } if (!$after) return; $this->_simpleSort(Am_Di::getInstance()->productTable, array('id' => $id), array('id'=>$after)); } } class Am_Grid_Action_Group_ProductEnable extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; protected $enable = true; public function __construct($enable = true) { $this->enable = (bool) $enable; parent::__construct( $enable ? "product-enable" : "product-disable", $enable ? ___("Enable") : ___("Disable") ); } /** * @param int $id * @param Product $record */ public function handleRecord($id, $record) { $record->updateQuick('is_disabled', !$this->enable); } } class Am_Grid_Action_Group_Archive extends Am_Grid_Action_Group_Abstract { protected $needConfirmation = true; protected $archive = true; public function __construct($archive = true) { $this->archive = (bool) $archive; parent::__construct( $archive ? "product-archive" : "product-unarchive", $archive ? ___("Delete") : ___("Restore") ); } /** * @param int $id * @param Product $record */ public function handleRecord($id, $record) { $record->updateQuick('is_archived', $this->archive); } } class Am_Grid_Action_Archive extends Am_Grid_Action_Abstract { protected $privilege = 'delete'; protected $title; protected $archive = true; public function __construct($id = null, $archive = true) { $this->archive = (bool) $archive; $this->title = ($archive) ? ___("Delete %s") : ___("Restore %s"); $this->attributes['data-confirm'] = ($archive) ? ___("Do you really want to delete product?") : ___("Do you really want to restore product?"); parent::__construct($id); } public function run() { $this->grid->getRecord()->updateQuick('is_archived', $this->archive); $this->grid->redirectBack(); } } class Am_Grid_Action_CopyProduct extends Am_Grid_Action_Abstract { protected $id = 'copy'; protected $privilege = 'insert'; public function run() { $record = $this->grid->getRecord(); $vars = $record->toRow(); unset($vars['product_id']); $vars['title'] = ___('Copy of') . ' ' . $record->title; $back = @$_SERVER['HTTP_X_REQUESTED_WITH']; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $controller = new AdminProductsController_Copy(new Am_Mvc_Request(), new Am_Mvc_Response(), array('di' => Am_Di::getInstance())); $controller->valuesToForm($vars, $record); $plan = array(); $plan_map = array(); foreach ($vars['_plan'] as $p) { $id = is_null($id) ? 0 : time() . rand(100, 999); $plan_map[$p['plan_id']] = $id; $p['plan_id'] = $id; $plan[$id] = $p; } $vars['_plan'] = $plan; $controller->setPlan($plan); $opts = array(); foreach ($record->getOptions() as $opt) { $_ = $opt->toArray(); $_['product_option_id'] = null; $_['product_id'] = null; $_['options'] = json_decode($_['options'], true); if (isset($_['options']['prices'])) { foreach ($_['options']['prices'] as $opVal => $priceMap) { $newPriceMap = array(); foreach ($priceMap as $bp_id => $price) { $newPriceMap[$plan_map[$bp_id]] = $price; } $_['options']['prices'][$opVal] = $newPriceMap; } } $_['options'] = json_encode($_['options']); $opts[] = $_; } $vars['_options'] = json_encode(array('options' => $opts)); $request = new Am_Mvc_Request($vars + array($this->grid->getId() . '_a' => 'insert', $this->grid->getId() . '_b' => $this->grid->getBackUrl()), Am_Mvc_Request::METHOD_POST); $controller->setRequest($request); $request->setModuleName('default') ->setControllerName('admin-products') ->setActionName('index') ->setDispatched(true); $controller->dispatch('indexAction'); $response = $controller->getResponse(); $response->sendResponse(); $_SERVER['HTTP_X_REQUESTED_WITH'] = $back; } } class Am_Grid_Action_Sort_Product extends Am_Grid_Action_Sort_Abstract { protected function setSortBetween($item, $after, $before) { $this->_simpleSort(Am_Di::getInstance()->productTable, $item, $after, $before); } } class AdminProductsController extends Am_Mvc_Controller_Grid { public function preDispatch() { parent::preDispatch(); $this->getDi()->billingPlanTable->toggleProductCache(false); $this->getDi()->productTable->toggleCache(false); } public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission('grid_product'); } public function archivedAction() { $ds = new Am_Query($this->getDi()->productTable); $ds->addWhere('t.is_archived = ?', 1); $ds->addOrder('sort_order')->addOrder('title'); $grid = new Am_Grid_Editable('_product', ___("Archive"), $ds, $this->_request, $this->view); $grid->setRecordTitle(___('Product')); $grid->addField(new Am_Grid_Field('product_id', '#', true, '', null, '1%')); $grid->addField(new Am_Grid_Field('title', ___('Title'), true, '', null, '30%')) ->setGetFunction(function($r, $g, $f) { return strip_tags($r->$f); }); $grid->addField(new Am_Grid_Field('terms', ___('Billing Terms'), false))->setRenderFunction(array($this, 'renderTerms')); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_Url('edit', ___('Edit Product'), $this->getDi()->url('admin-products', array( '_product_a' => 'edit', '_product_b' => $this->getDi()->url('admin-products/archived'), '_product_id' => '__ID__' ))))->setTarget('_top'); $grid->actionAdd(new Am_Grid_Action_Delete('delete','Delete permanently')); $grid->actionAdd(new Am_Grid_Action_Archive('product-restore', 0)); $grid->actionAdd(new Am_Grid_Action_Group_Delete('group-delete','Delete permanently')); $grid->actionAdd(new Am_Grid_Action_Group_Archive(false)); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'getTrAttribs')); $grid->setFilter(new Am_Grid_Filter_Product); $unar_count = $this->getArchivedCount(); $grid->actionAdd(new Am_Grid_Action_Url('unarchived', ___("Live Products") . " ($unar_count)", '__ROOT__/admin-products')) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setCssClass('link') ->setTarget('_top'); $this->view->content = $grid->runWithLayout('admin/layout.phtml'); } public function createGrid() { $ds = new Am_Query($this->getDi()->productTable); $ds->addWhere('t.is_archived = ?', 0); $ds->addOrder('sort_order')->addOrder('title'); $grid = new Am_Grid_Editable('_product', ___("Products"), $ds, $this->_request, $this->view); $grid->setRecordTitle(___('Product')); $grid->actionAdd(new Am_Grid_Action_Group_ProductEnable(false)); $grid->actionAdd(new Am_Grid_Action_Group_ProductEnable(true)); $grid->actionAdd(new Am_Grid_Action_Group_ProductAssignCategory(false)); $grid->actionAdd(new Am_Grid_Action_Group_ProductAssignCategory(true)); $grid->actionAdd(new Am_Grid_Action_Group_ChangeOrder) ->setTitle(___('Change Order')); $grid->actionAdd(new Am_Grid_Action_Group_Archive(true)); $grid->addField(new Am_Grid_Field('product_id', '#', true, '', null, '1%')); $grid->addField(new Am_Grid_Field('title', ___('Title'), true, '', null, '30%')) ->setGetFunction(function($r, $g, $f) { return strip_tags($r->$f); }); if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_product_product_category")) { $grid->addField(new Am_Grid_Field('pgroup', ___('Product Categories'), false))->setRenderFunction(array($this, 'renderPGroup'))->addDecorator(new Am_Grid_Field_Decorator_Shorten(50)); } $grid->addField(new Am_Grid_Field('terms', ___('Billing Terms'), false))->setRenderFunction(array($this, 'renderTerms')); if ($this->getDi()->plugins_tax->getEnabled()) { $grid->addField(new Am_Grid_Field('tax_group', ___('Tax'))); $grid->actionAdd(new Am_Grid_Action_LiveCheckbox('tax_group')) ->setValue(IProduct::ALL_TAX) ->setEmptyValue(IProduct::NO_TAX); } $grid->actionGet('edit')->setTarget('_top'); $grid->actionDelete('delete'); $grid->actionAdd(new Am_Grid_Action_Archive('delete', 1)); $grid->actionAdd(new Am_Grid_Action_LiveEdit('title')); $grid->actionAdd(new Am_Grid_Action_Sort_Product()); $grid->setFormValueCallback('start_date', array('RECORD', 'getStartDate'), array('RECORD', 'setStartDate')); $grid->setFormValueCallback('require_other', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->setFormValueCallback('prevent_if_other', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->addCallback(Am_Grid_Editable::CB_AFTER_SAVE, array($this, 'afterSave')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'getTrAttribs')); $grid->setForm(array($this, 'createForm')); $grid->setFilter(new Am_Grid_Filter_Product); $grid->setEventId('gridProduct'); $grid->actionAdd(new Am_Grid_Action_Url('categories', ___('Edit Categories'), '__ROOT__/admin-product-categories')) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setTarget('_top') ->setCssClass('link') ->setPrivilegeId('edit'); $grid->actionAdd(new Am_Grid_Action_Url('upgrades', ___('Manage Product Upgrade Paths'), '__ROOT__/admin-products/upgrades')) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setTarget('_top') ->setCssClass('link') ->setPrivilegeId('edit'); $grid->actionAdd(new Am_Grid_Action_CopyProduct())->setTarget('_top'); $ar_count = $this->getArchivedCount(1); if ($ar_count) { $grid->actionAdd(new Am_Grid_Action_Url('archived', ___("Archive") . " ($ar_count)", '__ROOT__/admin-products/archived')) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setTarget('_top') ->setCssClass('link') ->setPrivilegeId('browse'); } return $grid; } public function getArchivedCount($is_archived = 0) { return $this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_product WHERE is_archived = ?", $is_archived); } public function getTrAttribs(& $ret, $record) { if ($record->is_disabled) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } function renderPGroup(Product $p) { $res = array(); $options = $this->getDi()->productCategoryTable->getAdminSelectOptions(); foreach ($p->getCategories() as $pc_id) { $res[] = $options[$pc_id]; } return $this->renderTd(implode(", ", $res)); } function renderTerms(Product $record) { if (!$record->getBillingPlan(false)) return; $product_paysystem = $this->getDi()->config->get('product_paysystem'); $plans = $record->getBillingPlans(); $t = array(); foreach ($plans as $plan) { $term = sprintf(count($plans) > 1 && $plan->pk() == $record->default_billing_plan_id ? '%s' : '%s', $this->escape($plan->getTerms())); if ($product_paysystem && $plan->paysys_id) { $term .= sprintf(' (%s)', $plan->paysys_id); } $t[] = $term; } $t = implode('
', $t); return $this->renderTd($t, false); } function createForm() { $record = $this->grid->getRecord(); $plans = array(); foreach ($record->getBillingPlans() as $plan) $plans[$plan->pk()] = $plan->toArray(); $form = new Am_Form_Admin_Product($plans); return $form; } function valuesToForm(& $ret, Product $record) { $ret['_plan'] = array( 'TPL' => array( 'currency' => Am_Currency::getDefault() ), 0 => array( 'currency' => Am_Currency::getDefault() ), ); if ($record->isLoaded()) { $ret['_categories'] = $record->getCategories(); $ret['_plan'] = array(); foreach ($record->getBillingPlans() as $plan) { $arr = $plan->toArray(); $arr['paysys_id'] = !empty($arr['paysys_id']) ? explode(',', $arr['paysys_id']) : array(); if (!empty($arr['rebill_times'])) { $arr['_rebill_times'] = $arr['rebill_times']; if (!in_array($arr['rebill_times'], array(0, 1, IProduct::RECURRING_REBILLS))) $arr['_rebill_times'] = 'x'; } foreach (array('first_period', 'second_period') as $f) { if (array_key_exists($f, $arr)) { $arr[$f] = new Am_Period($arr[$f]); } } $ret['_plan'][$plan->pk()] = $arr; } $ret['_plan']['TPL']['currency'] = Am_Currency::getDefault(); // $opts = array(); foreach ($record->getOptions() as $opt) $opts[] = $opt->toArray(); $ret['_options'] = json_encode(array('options' => $opts)); } else { $ret['_options'] = json_encode(array('options' => array())); } } public function afterSave(array &$values, Product $product) { $this->updatePlansFromRequest($product, $values, $product->getBillingPlans()); $this->updateOptionsFromRequest($product, $values, $product->getBillingPlans(), $product->getOptions()); $product->setCategories(empty($values['_categories']) ? array() : $values['_categories']); } /** @return array BillingPlan including existing, $toDelete - but existing not found in request */ public function updatePlansFromRequest(Product $record, $values, $existing = array()) { // we access "POST" directly here as there is no access to new added // fields from the form! $plans = $_POST['_plan']; unset($plans['TPL']); //we should use output of getValue to set additional fields //in order to value be correct foreach ($plans as $k => $plan) { $form = new Am_Form_Admin(); foreach ($this->getDi()->billingPlanTable->customFields()->getAll() as $f) { $f->addToQf2($form); } $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array($plan) )); $plans[$k] = array_merge($plan, $form->getValue()); } $sort = 0; foreach ($plans as $k => & $arr) { if (Am_Di::getInstance()->config->get('product_paysystem')) { $arr['paysys_id'] = implode(',', isset($arr['paysys_id']) ? $arr['paysys_id'] : array()); } if ($arr['_rebill_times'] != 'x') $arr['rebill_times'] = $arr['_rebill_times']; try { $p = new Am_Period($arr['first_period']['c'], $arr['first_period']['u']); $arr['first_period'] = (string) $p; } catch (Am_Exception_InternalError $e) { unset($plans[$k]); continue; } try { $p = new Am_Period($arr['second_period']['c'], $arr['second_period']['u']); $arr['second_period'] = (string) $p; } catch (Am_Exception_InternalError $e) { $arr['second_period'] = ''; } if (empty($arr['variable_qty'])) $arr['variable_qty'] = 0; if (empty($arr['qty'])) $arr['qty'] = 1; if ($arr['rebill_times'] == 0) { $arr['second_price'] = null; $arr['second_period'] = null; } $arr['sort_order'] = $sort++; } foreach ($existing as $k => $plan) if (empty($plans[$plan->pk()])) { $plan->delete(); } else { $plan->setForUpdate($plans[$plan->pk()]); $plan->update(); unset($plans[$plan->pk()]); } $plan_map = array(); foreach ($plans as $id => $a) { $plan = $this->getDi()->billingPlanRecord; $plan->setForInsert($a); $plan->product_id = $record->pk(); $plan->insert(); $plan_map[$id] = $plan->pk(); } //replace temporary billing plan id with actual ones $options = json_decode($_POST['_options'], true); foreach ($options['options'] as & $_) { if (isset($_['options'])) { $_['options'] = json_decode($_['options'], true); if (isset($_['options']['prices'])) { foreach ($_['options']['prices'] as $opVal => $priceMap) { $newPriceMap = array(); foreach ($priceMap as $bp_id => $price) { $newPriceMap[isset($plan_map[$bp_id]) ? $plan_map[$bp_id] : $bp_id] = $price; } $_['options']['prices'][$opVal] = $newPriceMap; } } $_['options'] = json_encode($_['options']); } } $_POST['_options'] = json_encode($options); //end // temp. stub $record->updateQuick('default_billing_plan_id', $this->getDi()->db->selectCell( "SELECT MIN(plan_id) FROM ?_billing_plan WHERE product_id=?d AND (disabled IS NULL OR disabled = 0)", $record->product_id)); } public function updateOptionsFromRequest(Product $record, $values, $plans, $existing = array()) { // we access "POST" directly here as there is no access to new added // fields from the form! $options = json_decode($_POST['_options'], true); $sort = 0; foreach ($options['options'] as &$option) $option['sort_order'] = $sort++; if (!is_array($options['options'])) return; // something is wrong! // first update existing options foreach ($existing as $extId => $extOpt) foreach ($options['options'] as $k => $a) { if ($a['product_option_id'] != $extOpt->pk()) continue; // update found existing option if (empty($a['name'])) $a['name'] = $a['title']; $extOpt->setForUpdate($a); $extOpt->product_id = $record->pk(); $extOpt->update(); unset($existing[$extId]); unset($options['options'][$k]); } // insert not found options foreach ($options['options'] as $k => $a) { $op = $this->getDi()->productOptionTable->createRecord(); if (empty($a['name'])) $a['name'] = $a['title']; unset($a['product_option_id']); $op->setForInsert($a); $op->product_id = $record->pk(); $op->insert(); } // delete removed options - we unset all that we found earlier foreach ($existing as $extOpt) $extOpt->delete(); } public function upgradesAction() { $billingTableRecords = $this->getDi()->billingPlanTable->findBy(); $productOptions = $this->getDi()->productTable->getOptions(); $planOptions = array(); foreach ($billingTableRecords as $bp) { if (!isset($productOptions[$bp->product_id])) continue; /* @var $bp BillingPlan */ if (!$terms = $bp->terms) { $tt = new Am_TermsText($bp); $terms = $tt->getString(); } $planOptions[$bp->pk()] = $productOptions[$bp->product_id] . '/' . $bp->title . ' (' . $terms . ')'; } $ds = new Am_Query($this->getDi()->productUpgradeTable); $grid = new Am_Grid_Editable('_upgrades', ___("Product Upgrades"), $ds, $this->_request, $this->view); $grid->setPermissionId('grid_product'); $grid->_planOptions = $planOptions; $grid->addField(new Am_Grid_Field_Enum('from_billing_plan_id', ___('Upgrade From')))->setTranslations($planOptions); $grid->addField(new Am_Grid_Field_Enum('to_billing_plan_id', ___('Upgrade To')))->setTranslations($planOptions); $grid->addField('surcharge', ___('Surcharge'))->setGetFunction(function($r) {return Am_Currency::render($r->surcharge);}); $grid->setForm(array($this, 'createUpgradesForm')); $grid->runWithLayout('admin/layout.phtml'); } public function createUpgradesForm(Am_Grid_Editable $grid) { $form = new Am_Form_Admin; $options = $grid->_planOptions; $from = $form->addSelect('from_billing_plan_id', null, array('options' => $options))->setLabel(___('Upgrade From')); $to = $form->addSelect('to_billing_plan_id', null, array('options' => $options))->setLabel(___('Upgrade To')); $to->addRule('neq', ___('[From] and [To] billing plans must not be equal'), $from); $form->addText('surcharge', array('placeholder' => '0.0'))->setLabel(___( "Surcharge\nto be additionally charged when customer moves [From]->[To] plan\naMember will not charge First Price on upgrade, use Surcharge instead")); $el = $form->addAdvRadio('type')->setLabel(___('Upgrade Price Calculation Type')); $el->addOption(<<Default - Unused amount from previous subscription will be applied as discount to new one CUT , ProductUpgrade::TYPE_DEFAULT); $el->addOption(<<Flat - User only pay flat rate on upgrade (Surcharge amount) CUT , ProductUpgrade::TYPE_FLAT); return $form; } public function init() { parent::init(); $this->view->headStyle()->appendStyle(" #plan-TPL { display: none; } "); $this->view->headScript()->appendFile($this->view->_scriptJs("adminproduct.js")); $this->view->headScript()->appendFile($this->view->_scriptJs("ckeditor/ckeditor.js")); $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); } } class AdminProductsController_Copy extends AdminProductsController { protected $plan = array(); function setPlan($plan) { $this->plan = $plan; } function createForm() { return new Am_Form_Admin_Product($this->plan); } function valuesToForm(& $ret, Product $record) { parent::valuesToForm($ret, $record); unset($ret['_options']); } } PK\bJ] -default/controllers/CustomFieldController.phpnu[getTable()->syncSortOrder(); parent::indexAction(); } public function parseCsvAction() { $this->_response->ajaxResponse(array_map('str_getcsv', array_map('trim', explode("\n", $this->getParam('csv', ''))))); } public function createGrid() { $table = $this->getTable(); $fields = $table->customFields()->getAll(); uksort($fields, array($table, 'sortCustomFields')); $ds = new Am_Grid_DataSource_CustomField($fields, $table); $grid = new Am_Grid_Editable('_f', ___('Additional Fields'), $ds, $this->_request, $this->view); $grid->addField(new Am_Grid_Field('name', ___('Name'), true, '', null, '10%')); $grid->addField(new Am_Grid_Field('title', ___('Title'), true, '', null, '20%')); $grid->addField(new Am_Grid_Field('sql', ___('Field Type'), true, '', null, '10%')) ->setRenderFunction(array($this, 'renderFieldType')); $grid->addField(new Am_Grid_Field('type', ___('Display Type'), true, '', null, '10%')); $grid->addField(new Am_Grid_Field('description', ___('Description'), false, '', null, '40%')); $grid->addField(new Am_Grid_Field('validateFunc', ___('Validation'), false, '', null, '20%')) ->setGetFunction(function($r) {return implode(",", (array)$r->validateFunc);}); $grid->setForm(array($this, 'createForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'getTrAttribs')); $grid->actionGet('edit') ->setIsAvailableCallback(function($r) {return isset($r->from_config) && $r->from_config;}); $grid->actionGet('delete') ->setIsAvailableCallback(function($r) {return isset($r->from_config) && $r->from_config;}); $grid->actionAdd(new Am_Grid_Action_Sort_CustomField()) ->setTable($table); $grid->setRecordTitle(___('Field')); return $grid; } public function renderFieldType($record, $fieldName, Am_Grid_ReadOnly $grid) { return $grid->renderTd(!empty($record->sql) ? '[SQL]' : '[DATA]'); } public function createForm() { $form = new Am_Form_Admin_CustomField($this->grid->getRecord()); $form->setTable($this->getTable()); return $form; } public function getTrAttribs(& $ret, $record) { if (!(isset($record->from_config) && $record->from_config)) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } public function valuesToForm(& $ret, $record) { $ret['validate_func'] = @$record->validateFunc; $ret['values'] = array( 'options' => $record->options, 'default' => $record->default ); } }PK\_ZB? ? (default/controllers/UploadController.phpnu[getParam('path')) { if ($path[0]!='.') {$path = '.' . $path;} $upload = $this->getDi()->uploadTable->findFirstByPath($path); } else { $upload = $this->getDi()->uploadTable->load($this->getParam('id')); } if (!$upload) { throw new Am_Exception_InputError( 'Can not fetch file for id: ' . $this->getParam('id') ); } if (!$this->getDi()->uploadAcl->checkPermission($upload, Am_Upload_Acl::ACCESS_READ, $this->getDi()->auth->getUser())) { throw new Am_Exception_AccessDenied(); } $this->_helper->sendFile($upload->getFullPath(), $upload->getType(), array( //'cache'=>array('max-age'=>3600), 'filename' => $upload->getName(), )); exit; } protected function getUploadIds(Am_Upload $upload) { $upload_ids = array(); foreach ($upload->getUploads() as $upload) { $upload_ids[] = $upload->pk(); } return $upload_ids; } public function uploadAction() { if (!$this->getDi()->uploadAcl->checkPermission($this->getParam('prefix'), Am_Upload_Acl::ACCESS_WRITE, $this->getDi()->auth->getUser())) { throw new Am_Exception_AccessDenied(); } $secure = $this->getParam('secure', false); $upload = new Am_Upload($this->getDi()); $upload->setPrefix($this->getParam('prefix')); $upload->loadFromStored(); $ids_before = $this->getUploadIds($upload); $upload->processSubmit('upload', false); //find currently uploaded file $x = array_diff($this->getUploadIds($upload), $ids_before); $upload_id = array_pop($x); try { $upload = $this->getDi()->uploadTable->load($upload_id); $data = array( 'ok' => true, 'name' => $upload->getName(), 'size_readable' => $upload->getSizeReadable(), 'upload_id' => $secure ? Am_Form_Element_Upload::signValue($upload->pk()) : $upload->pk(), 'mime' => $upload->mime ); echo json_encode($data); } catch (Am_Exception $e) { echo json_encode(array( 'ok' => false, 'error' => ___('No files uploaded'), )); } } }PK\<.default/controllers/AdminUpgradeController.phpnu[options = $options; } /** * @return @bool false on failure, true on ok */ abstract function connect(); abstract function cwd(); abstract function put($from, $to); abstract function get($from, $to); abstract function ls($dir); abstract function chdir($dir); abstract function mkdir($dir); /** * @return string last error message */ abstract function getError(); } class Am_FileConnector_Local extends Am_FileConnector { public function connect() { return true; } public function cwd() { return getcwd(); } public function get($from, $to) { return copy($from, $to); } public function getError() { } /** @todo implement normally ! */ public function ls($dir) { $d = opendir($dir); if (!$d) return false; $ret = array(); while ($f = readdir($d)) { $ret[$f] = stat($dir . DIRECTORY_SEPARATOR . $f); } closedir($d); return $ret; } public function mkdir($dir) { return @mkdir($dir) && (chmod($dir, $this->permDir) || true); } public function put($from, $to) { return copy($from,$to) && (chmod($to, $this->permFile) || true); } public function chdir($dir) { return chdir($dir); } } class Am_FileConnector_Ftp extends Am_FileConnector { /** @var ftp */ protected $ftp; public function getHost(){ return @$this->options['hostname']['host']; } public function getPort(){ return ( array_key_exists('port', $this->options['hostname']) && (intval($this->options['hostname']['port'])>0) ) ? intval($this->options['hostname']['port']) : 21; } public function connect() { require_once 'class-ftp.php'; $this->ftp = new ftp(false); $this->ftp->SetServer($this->getHost(), $this->getPort()); if (!$this->ftp->connect()) { $this->ftp->PushError('connect', "Could not connect to host"); return false; } if (!$this->ftp->login($this->options['user'], $this->options['pass'])) { $this->ftp->PushError('auth', "Authentication failed"); return false; } return true; } public function cwd() { $ret = $this->ftp->pwd(); $ret = rtrim($ret, "/\\"); return $ret; } public function put($from, $to) { return $this->ftp->put($from, $to) && ($this->ftp->chmod($to, $this->permFile) || true); } public function get($from, $to) { return $this->ftp->get($from, $to); } public function ls($dir) { return $this->ftp->dirlist($dir); } public function chdir($dir) { return $this->ftp->chdir($dir); } public function mkdir($dir) { return $this->ftp->mkdir($dir) && ($this->ftp->chmod($dir, $this->permDir) || true); } public function getError() { $err = $this->ftp->PopError(); if ($err) return $err['msg']; } } class Am_FileConnector_Sftp extends Am_FileConnector { /** @var Net_SFTP */ protected $ftp; public function getHost(){ return @$this->options['hostname']['host']; } public function getPort(){ return ( array_key_exists('port', $this->options['hostname']) && (intval($this->options['hostname']['port'])>0) ) ? $this->options['hostname']['port'] : 22; } public function connect() { $this->ftp = new Net_SFTP($this->getHost(), $this->getPort()); if (!$this->ftp->login($this->options['user'], $this->options['pass'])) { return false; } return true; } public function cwd() { $ret = $this->ftp->pwd(); $ret = rtrim($ret, "/\\"); return $ret; } public function put($from, $to) { return $this->ftp->put($to, file_get_contents($from)) && $this->ftp->chmod($this->permFile, $to); } public function get($from, $to) { return $this->ftp->get($from, $to); } public function ls($dir) { return array_flip($this->ftp->nlist($dir)); } public function chdir($dir) { return $this->ftp->chdir($dir); } public function mkdir($dir) { return $this->ftp->mkdir($dir) && $this->ftp->chmod($this->permDir, $dir); } public function getError() { $err = $this->ftp->getLastError(); if (!$err) $err = $this->ftp->getLastSFTPError (); if ($err) return $err['msg']; } } class AdminUpgradeController extends Am_Mvc_Controller { const AM_ADMIN_KEY = 'am_admin_key'; protected $allowedDomains = array( 'www.amember.com', 'www.cgi-central.net', ); protected $upgrades = array(); protected $steps = array(); // do not display default layout with content protected $noDisplay = false; public function __construct(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response, array $invokeArgs = array()) { parent::__construct($request, $response, $invokeArgs); $this->steps = array( 0 => array('stepSetCookie', ___('Create Session Key')), 1 => array('stepLoadUpgradesList', ___('Get Available Upgrades List')), 2 => array('stepConfirmUpgrades', ___('Choose Upgrades to Install')), 3 => array('stepGetRemoteAccess', ___('Retreive Access Parameters if necessary')), 4 => array('stepDownload', ___('Download Upgrades')), 5 => array('stepUnpack', ___('Unpack Upgrades')), 6 => array('stepSetMaint', ___('Enter Maintenance Mode')), 7 => array('stepCopy', ___('Copy Upgrades')), 8 => array('stepAutoEnable', ___('Enable plugins if necessary')), 9 => array('stepUpgradeDb', ___('Upgrade Database')), 10 => array('stepUnsetMaint', ___('Quit Maintenance Mode')), ); } public function checkAdminPermissions(Admin $admin) { return $admin->isSuper(); } public function indexAction() { if (@$_GET['reset']) { $this->getSession()->unsetAll(); } $upgradeProcess = new Am_BatchProcessor(array($this, 'doUpgrade')); $status = null; if ($upgradeProcess->run($status)) { $this->view->title = ___('Upgrade Finished'); $this->view->content .= '

' . ___('Upgrade Finished') . '

' . ""; } else { $this->view->title = ___('Upgrade'); $this->view->content .= "
"; } if (!$this->noDisplay) $this->view->display('admin/layout.phtml'); } public function stepConfirmUpgrades() { $form = new Am_Form_Admin; $upgrades = $form->addGroup('upgrades', array('class' => 'no-label')); $options = array(); $static = ''; $upgrades->addStatic()->setContent('

'.___('Available Upgrades').'

'); foreach ($this->getUpgrades() as $k => $upgrade) { if (!empty($upgrade->new)) { $upgrades->addStatic()->setContent('

'.___('New Modules Available').'

'); } $text = sprintf('%s%s, '.___('version').' %s - %s' . '
', ''.$upgrade->title.'', $upgrade->type =='core' ? '' : sprintf(' [%s - %s]', $upgrade->type, $upgrade->id), ''.$upgrade->version.'', ''.amDate($upgrade->date).''); $check = $upgrades->addCheckbox($k, empty($upgrade->checked) ? null : array('checked' => 'checked'))->setContent($text); if (!empty($upgrade->disabled)) { $check->toggleFrozen(true); $check->setValue(0); } $static .= "
".
                $upgrade->text.
                       "
\n"; $upgrades->addStatic()->setContent($static); } $form->addCheckbox('_confirm', array('class' => 'no-label')) ->setContent(___('I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database')) ->addRule('required'); $form->addSubmit('', array('value' => ___('Install Updates'))); if ($form->isSubmitted() && $form->validate()) { $confirmed = array_keys(array_filter($upgrades->getValue())); if (!$confirmed) { $this->view->title = ___('No upgrades to install'); $this->view->content = ''.___('Back').''; return false; } $upgrades = $this->getUpgrades(); foreach ($upgrades as $k => $v) if (!in_array($k, $confirmed)) unset($upgrades[$k]); $this->setUpgrades($upgrades); return true; } else { $this->view->content = (string)$form; $this->view->title = ___('Choose Upgrades to Install'); $this->view->display('admin/layout.phtml'); $this->noDisplay = true; return false; } } public function stepSetCookie() { if (!$this->_request->getCookie(self::AM_ADMIN_KEY)) { unset($this->getSession()->admin_remote_access); $_COOKIE[self::AM_ADMIN_KEY] = $this->getDi()->security->randomString(56); Am_Cookie::set(self::AM_ADMIN_KEY, $_COOKIE[self::AM_ADMIN_KEY], $this->getDi()->time + 3600); } return true; } public function checkAction() { //$this->getDi()->store->delete('upgrades-list'); // read/write to am_store and handle dismission of upgrades and new plugins notifications // check if saved record exists $load = $this->getDi()->store->getBlob('upgrades-list'); if (!empty($load)) { $upgrades = unserialize($load); } else { $upgrades = array('_loaded' => null, '_dismissed' => null); } if ($upgrades['_loaded'] < (time() - 3600*2)) { $upgrades['items'] = $this->loadUpgradesList(false); $upgrades['_loaded'] = time(); $this->getDi()->store->setBlob('upgrades-list', serialize($upgrades)); } $ret = array(); foreach ($upgrades['items'] as $upgrade) { if (!empty($upgrades['_dismissed'] [$upgrade->type] [$upgrade->id] [$upgrade->version] [$this->getDi()->authAdmin->getUserId()] )) continue; $upgrade->notice = ($upgrade->is_new) ? 'New Module Available: ' : 'Upgrade Available'; $upgrade->notice .= sprintf(': %s [%s] ', $upgrade->title, $upgrade->version); $upgrade->dismiss_url = $this->getDi()->url('admin-upgrade/dismiss', array( 'type' => $upgrade->type, 'id' => $upgrade->id, 'version' => $upgrade->version, ), false); $ret[] = $upgrade; } //$this->setCookie('am_upgrade_checked', 1, '+1 hour'); return $this->ajaxResponse($ret); } public function dismissAction() { $load = $this->getDi()->store->getBlob('upgrades-list'); if (!empty($load)) { $upgrades = unserialize($load); $upgrades['_dismissed'] [$this->_request->get('type')] [$this->_request->get('id')] [$this->_request->get('version')] [$this->getDi()->authAdmin->getUserId()] = time(); $this->getDi()->store->setBlob('upgrades-list', serialize($upgrades)); } } public function getTokenAction() { $form = new Am_Form_Admin; $form->addStatic()->setContent('Your [www.amember.com] account information'); $login = $form->addText('login', array('size'=>40))->setLabel(___('Username or e-mail address')); $login->addRule('required'); $form->addPassword('pass', array('size'=>40))->setLabel(___('Password')) ->addRule('required'); $form->addSubmit('', array('value' => ___('Login'))); if ($form->isSubmitted() && $form->validate()) { $req = new Am_HttpRequest('http://www.amember.com/check-upgrades.php', Am_HttpRequest::METHOD_POST); $req->addPostParameter('do', 'get-token'); $vars = $form->getValue(); $req->addPostParameter('login', $vars['login']); $req->addPostParameter('pass', $vars['pass']); $req->addPostParameter('license', $this->getDi()->config->get('license')); try { $response = $req->send(); if ($response->getStatus() == '401') { throw new HTTP_Request2_Exception("Authentication failed: " . $response->getBody()); } if ($response->getStatus() != '200') throw new HTTP_Request2_Exception("Wrong status: " . $response->getStatus()); if ($response->getBody() <= 10000) throw new HTTP_Request2_Exception("Wrong token returned: not a number" . Am_Html::escape($response->getBody())); $ok = true; } catch (HTTP_Request2_Exception $e) { $login->setError('Cannot get token: ' . $e->getMessage()); $ok = false; } if ($ok) { $this->getDi()->store->set('amember-site-auth-token', (int)$response->getBody()); $this->_redirect('admin-upgrade'); } } $this->view->title = ___('Account Verification'); $this->view->content = (string)$form; $this->view->display('admin/layout.phtml'); } public function stepLoadUpgradesList() { if (($ret = $this->loadUpgradesList(true)) === false) return false; $this->setUpgrades($ret); if (!$ret) throw new Am_Exception_InputError( ___("No Updates Available") . ". 1,'beta'=>1))."'>" . ___("Check for beta version") . ''); return true; } public function stepGetRemoteAccess() { if (!$this->needsRemoteAccess()) { $this->storeRemoteAccess(array('method' => 'local', 'root' => $this->getDi()->root_dir, '_tested' => true )); return true; } return ($this->askRemoteAccess()); } public function doUpgrade(& $context, Am_BatchProcessor $batch) { $session = $this->getSession(); if (empty($session->step)) $this->getSession()->step = 0; do { $currentOperation = $this->steps[$session->step][0]; $start = (int)@$session->start; $this->outStepHeader(); $ret = call_user_func_array(array($this, $currentOperation), array($batch, & $start)); $session->start = $start; if (!$ret) { $batch->stop(); return false; } $this->outText(___('Done') . "
\n"); $session->step = $session->step + 1; if ($session->step >= count($this->steps)) { $session->unsetAll(); return true; } } while ($batch->checkLimits()); } protected function outStepHeader() { $step = $this->getSession()->step; $title = $this->steps[$step][1]; $out = sprintf(___('Step %d of %d', $step+1, count($this->steps))); $out .= ' - ' . $title; $this->view->content .= "

".$out."

\n"; } protected function outText($text) { $this->view->content .= $text; } public function getSession() { static $session; if (empty($session)) { $session = new Zend_Session_Namespace('amember_upgrade'); $session->setExpirationSeconds(3600); } return $session; } public function setUpgrades($ret) { $this->getDi()->store->setBlob('do-upgardes-list', serialize($ret)); } public function getUpgrades() { return unserialize($this->getDi()->store->getBlob('do-upgardes-list')); } function stepDownload(Am_BatchProcessor $batch, & $start) { $upgrades = $this->getUpgrades(); foreach ($upgrades as $k => & $upgrade) { if (!empty($upgrade->upload_id)) continue; if (!$batch->checkLimits()) { $start = $k; return false; } $fn = tempnam($this->getDi()->data_dir, '.upgrade.'); $url = $upgrade->url; $parsed = parse_url($url); if ($parsed['scheme'] != 'http') throw new Am_Exception_Security("Strange upgrade URL scheme: ".Am_Html::escape($parsed['scheme'])); if (!in_array($parsed['host'], $this->allowedDomains)) throw new Am_Exception_Security("Strange upgrade URL host: ".Am_Html::escape($parsed['host'])); $req = new Am_HttpRequest($url, Am_HttpRequest::METHOD_GET); $req->setConfig('follow_redirects', false); // openbasedir setting disables curl redirects, // so we will handle redirect manually try { $response = $req->send(); if ($response->isRedirect()) { $req = new Am_HttpRequest($response->getHeader('location'), Am_HttpRequest::METHOD_GET); $response = $req->send(); } } catch (Exception $e) { $this->view->title = ___('Upgrade Download Problem'); $this->view->content = ___('Could not download file [%s]. Error %s. Please %stry again%s later.', Am_Html::escape($url), get_class($e) . ': ' . $e->getMessage(), '', ''); $this->view->display('admin/layout.phtml'); return false; }; ini_set('display_errors', true); if (!file_put_contents($fn, $response->getBody()) || !filesize($fn)) { unlink($fn); $this->view->title = ___('Upgrade Download Problem'); $this->view->content = ___('Could not download file [%s]. Error %s. Please %stry again%s later.', Am_Html::escape($url), 'storing download problem', '', ''); $this->view->display('admin/layout.phtml'); return false; } $upload = $this->getDi()->uploadRecord; $upload->name = basename($fn); $upload->path = basename($fn); $upload->prefix = 'upgrade'; $upload->uploaded = time(); $upload->desc = $upgrade->title .' '.$upgrade->version; $upload->insert(); $upgrade->upload_id = $upload->pk(); $this->setUpgrades($upgrades); $this->outText("Downloaded [$url] - " . $upload->getSizeReadable() . '
'); } return true; // force page load } function _tarError(PEAR_Error $error) { throw new Am_Exception_InputError('Upgrade unpacking problem: ' . $error->getMessage()); } function stepUnpack(Am_BatchProcessor $batch) { $upgrades = $this->getUpgrades(); foreach ($upgrades as $k => & $upgrade) { $upgrade->dir = null; if (!empty($upgrade->dir)) continue; // already unpacked? $record = $this->getDi()->uploadTable->load($upgrade->upload_id); $tar = new Archive_Tar($fn = $record->getFullPath()); $upgrade->dir = $this->getDi()->data_dir . DIRECTORY_SEPARATOR . $record->getFilename() . '-unpack'; if (!mkdir($upgrade->dir)) { throw new Am_Exception_InputError("Could not create folder to unpack downloaded archive: [{$upgrade->dir}]"); unset($upgrade->dir); } $tar->setErrorHandling(PEAR_ERROR_CALLBACK, array($this, '_tarError')); try { if (!$tar->extract($upgrade->dir)) throw new Am_Exception_InputError("Could not unpack downloaded archive: [$fn] to [{$upgrade->dir}]"); } catch (Exception $e) { $this->getDi()->errorLogTable->logException($e); unset($upgrade->dir); @rmdir($upgrade->dir); } // normally we delete uploaded archive $record->delete(); unset($upgrade->upload_id); $this->setUpgrades($upgrades); } return true; } function stepSetMaint() { $this->getSession()->maintenance_stored = $this->getDi()->config->get('maintenance'); Am_Config::saveValue('maintenance', 'Briefly unavailable for scheduled maintenance. Check back in a minute.'); return true; // make the string available for translation ___('Briefly unavailable for scheduled maintenance. Check back in a minute.'); } function stepUnsetMaint() { Am_Config::saveValue('maintenance', @$this->getSession()->maintenance_stored); $this->getDi()->store->delete('upgrades-list'); $this->getDi()->store->delete('do-upgardes-list'); return true; } function stepCopy(Am_BatchProcessor $batch) { @set_time_limit(600); $info = $this->loadRemoteAccess(); $class = 'Am_FileConnector_' . ucfirst(toCamelCase($info['method'])); $connector = new $class($info); if (!$connector->connect()) { $this->outText('Connection error: ' . Am_Html::escape($connector->getMessage())); return false; } if (!$connector->chdir($info['root'])) { $this->outText('Could not chroot to root folder: [' . Am_Html::escape($info['root']) . ']'); return false; } $upgrades = $this->getUpgrades(); foreach ($upgrades as $k => & $upgrade) { if (empty($upgrade->dir)) continue; $upgradePhp = $upgrade->dir . '/amember/_upgrade.php'; if (file_exists($upgradePhp)) require_once $upgradePhp; if (function_exists('_amemberBeforeUpgrade')) _amemberBeforeUpgrade($this, $connector, $upgrade); $dir = $upgrade->dir . DIRECTORY_SEPARATOR . 'amember' . DIRECTORY_SEPARATOR; $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::SELF_FIRST); foreach ($iterator as $file) { if ($file->getFileName() == '.' || $file->getFileName() == '..') continue; if ($file->getFileName() == '_upgrade.php') continue; // do not copy that run-once file if (!strpos($file->getPathName(), $strip = $dir)) { new Am_Exception_InputError(sprintf('Could not strip local root prefix: [%s] from fn [%s]', $strip, $file->getPathName())); } // path relative to amember root $path = substr($file->getPathName(), strlen($strip)); if ($file->isDir()) { if (!$connector->mkdir($path) && !$connector->ls($path)) { $this->outText('Could not create folder [' . Am_Html::escape($path) . ']
' . $connector->getError()); return false; } $this->outText('created folder ' . Am_Html::escape($path) . "
\n"); } else { if (!$connector->put($file->getPathName(), $path)) { $this->outText('Could not copy file [' . Am_Html::escape($file->getPathName()) . '] to remote [' . Am_Html::escape($path) . '] ' . $connector->getError()); return false; } $this->outText('copy file ' . Am_Html::escape($path) . "
\n"); } } // remove localdirectory and files $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $file) { if ($file->getFileName() == '.' || $file->getFileName() == '..') continue; if ($file->isDir()) rmdir($file->getPathName()); else unlink($file->getPathName()); } rmdir($dir); rmdir($upgrade->dir); unset($upgrade->dir); $this->setUpgrades($upgrades); if (function_exists('_amemberAfterUpgrade')) _amemberAfterUpgrade($this, $connector, $upgrade); if (!$batch->checkLimits()) { // $batch->stop(); // return false; } } return true; } /** * @todo ELIMINATE duplication source (Am_Form_Setup_Plugins) */ function stepAutoEnable() { foreach ($this->getUpgrades() as $upgrade) { if (empty($upgrade->auto_enable)) continue; $type = $upgrade->type; if ($type == 'module') $type='modules'; $pm = $this->getDi()->plugins[$type]; if (!$pm) continue; $configKey = $type == 'modules' ? 'modules' : ('plugins.'.$type); $enabled = (array)$this->getDi()->config->get($configKey, array()); if (!in_array($upgrade->id, $enabled)) { if ($pm->load($upgrade->id)) { $class = $pm->getPluginClassName($upgrade->id); try { call_user_func(array($class, 'activate'), $upgrade->id, $type); } catch(Exception $e) { $this->getDi()->errorLogTable->logException($e); trigger_error("Error during plugin [$upgrade->id] activation: " . get_class($e). ": " . $e->getMessage(),E_USER_WARNING); continue; } /// $enabled[] = $upgrade->id; $list = Am_Config::saveValue($configKey, $enabled); if ($type == 'modules') { // to run upgrade db with new module $this->getDi()->config->set('modules', $enabled); } } } } return true; } function stepUpgradeDb() { ob_start(); $this->getDi()->app->dbSync(true); $this->outText(ob_get_clean()); return true; } function loadUpgradesList($requireAuth = false) { $req = new Am_HttpRequest('http://www.amember.com/check-upgrades.php', Am_HttpRequest::METHOD_POST); $req->setConfig('connect_timeout', 5); if ((@$_REQUEST['beta'] > 0) || (defined('AM_BETA') && AM_BETA)) $req->addPostParameter ('beta', 1); $req->setConfig('timeout', 15); $req->addPostParameter('am-version', AM_VERSION); foreach ($this->getDi()->plugins as $type => $pm) foreach ($pm->getEnabled() as $v) $req->addPostParameter('plugins['.$type.']['.$v.']', $pm->loadGet($v)->getVersion()); $req->addPostParameter('extensions', implode(',', get_loaded_extensions())); foreach ($this->getDi()->config->get('lang.enabled', array()) as $l) $req->addPostParameter('lang[]', $l); $req->addPostParameter('php-version', PHP_VERSION); $req->addPostParameter('mysql-version', $this->getDi()->db->selectCell("SELECT VERSION()")); $req->addPostParameter('root-url', ROOT_URL); $req->addPostParameter('root-surl', ROOT_SURL); $req->addPostParameter('license', $this->getConfig('license')); $token = $this->getDi()->store->get('amember-site-auth-token'); if (!$requireAuth) $token = 'TRIAL'; elseif (!$token) $this->_redirect('admin-upgrade/get-token'); $req->addPostParameter('token', $token); // try { $response = $req->send(); if ($response->getStatus() == 401) { $this->_redirect('admin-upgrade/get-token'); } } catch (HTTP_Request2_Exception $e) { $this->view->title = ___('Update Error'); $this->view->content = ___('Could not fetch upgrades list from remote server. %sTry again%', '', ''); $this->view->display('admin/layout.phtml'); return false; } if ($response->getStatus() != '200') { throw new Am_Exception_InternalError(___("Could not fetch upgrades list. Connection error [%s]", $response->getReasonPhrase())); } $xml = new SimpleXMLElement($response->getBody()); $ret = array(); foreach ($xml->item as $u) { $el = new stdclass; foreach ($u->attributes() as $k => $v) $el->$k = (string)$v; $el->text = (string)$u; $el->text = strip_tags($el->text, '


    • '); $ret[] = $el; } return $ret; } function needsRemoteAccess() { if ( !function_exists('getmyuid') && !function_exists('fileowner')) return false; $fn = $this->getDi()->data_dir . '/temp-write-test-' . time(); $f = @fopen($fn, 'w'); if (!$f ) throw new Am_Exception_InternalError("Could not create test file - check if data dir is writeable"); if ( getmyuid() == @fileowner($fn) ) return false; @fclose($f); @unlink($fn); return true; } function askRemoteAccess() { $form = new Am_Form_Admin; $info = $this->loadRemoteAccess(); if ($info && !empty($info['_tested'])) return true; if ($info) $form->addDataSource(new Am_Mvc_Request($info)); $method = $form->addSelect('method', null, array('options' => array('ftp' => 'FTP', 'sftp' => 'SFTP'))) ->setLabel(___('Access Method'));; $gr = $form->addGroup('hostname')->setLabel(___('Hostname')); $gr->addText('host')->addRule('required')->addRule('regex', 'Incorrect hostname value', '/^[\w\._-]+$/'); $gr->addHTML('port-label')->setHTML(' Port'); $gr->addText('port', array('size'=>3)); $gr->addHTML('port-notice')->setHTML(' leave empty if default'); $form->addText('user')->setLabel(___('Username'))->addRule('required'); $form->addPassword('pass')->setLabel(___('Password')); // $form->addTextarea('ssh_public_key')->setLabel(___('SSH Public Key')); // $form->addTextarea('ssh_private_key')->setLabel(___('SSH Private Key')); $form->addSubmit('', array('value' => ___('Continue'))); $form->addScript()->setScript(<<getValue(); if ($form->isSubmitted() && $form->validate() && !($error = $this->tryConnect($vars))) { $vars['_tested'] = true; $this->storeRemoteAccess($vars); return true; } else { //$this->view->title = ___("File Access Credentials Required"); $this->view->title = ___('Upgrade'); $this->view->content = ""; $this->outStepHeader(); if ($error) $method->setError($error); $this->view->content .= (string)$form; $this->view->display('admin/layout.phtml'); $this->noDisplay = true; } } function encrypt($data) { $c = new Am_Crypt_Aes128($_COOKIE[self::AM_ADMIN_KEY]); return $c->encrypt($data); } function decrypt($ciphertext) { $c = new Am_Crypt_Aes128($_COOKIE[self::AM_ADMIN_KEY]); return $c->decrypt($ciphertext); } function storeRemoteAccess(array $info) { $this->getSession()->admin_remote_access = $this->encrypt(serialize($info)); return true; } function loadRemoteAccess() { if (empty($this->getSession()->admin_remote_access)) return array(); return unserialize($this->decrypt($this->getSession()->admin_remote_access)); } function tryConnect(array & $info) { $class = 'Am_FileConnector_' . ucfirst(toCamelCase($info['method'])); $connector = new $class($info); if (!$connector->connect()) { return "Connection failed: " . $connector->getError(); } // create temp file locally $fn = tempnam($this->getDi()->data_dir, 'test-ftp-'); $f = fopen($fn, 'w'); fclose($f); $cwd = $connector->cwd(); $root = $this->guessChrootedAmemberPath($cwd, array_keys($connector->ls('.')), $this->getDi()->root_dir); $root_path = null; foreach(array($root, $this->getDi()->root_dir) as $path){ $ls = $connector->ls($path . '/data'); if(array_key_exists(basename($fn), $ls)){ $root_path = $path; break; } } @unlink($fn); if (is_null($root_path)) { return "Connection succesful, but upgrade script was unable to locate test file on remote server"; } $info['root'] = $root_path; } function guessChrootedAmemberPath($cwd, array $lsCwd, $amRoot) { // split amRoot to dirnames $dirnames_r = array_filter(preg_split('|[\\/]|', $cwd)); $dirnames_l = array_filter(preg_split('|[\\/]|', $amRoot)); // find first occurence of dirnames in lsCwd $start = false; $foundInLs = array(); foreach ($dirnames_l as $lstart => $d) { if ($start = array_search($d, $dirnames_r)) break; if (in_array($d, $lsCwd)) $foundInLs[] = $lstart; } if ($start === false) { if ($foundInLs) { $start = null; $lstart = min($foundInLs) - 1; } } return '/' . implode('/', array_merge( array_slice($dirnames_r, 0, $start), array_slice($dirnames_l, $lstart) )); } } PK\r&W&W5default/controllers/AdminImportIpbNexusController.phpnu[ users * nexus_gateways -> gateways list * nexus_invoices -> invoices * nexus_packages -> products list * nexus_paymethods -> payment gateways settings * nexus_purchases -> payments/accesses * nexus_transactions -> payments */ class_exists('Am_Paysystem_Abstract', true); abstract class InvoiceCreator_Abstract { /** User */ protected $user; // all payments protected $payments = array(); // grouped by invoice protected $groups = array(); // prepared Invoices protected $invoices = array(); // protected $paysys_id; /** @var DbSimple_Mypdo */ protected $db_ipb_nexus; public function getDi() { return Am_Di::getInstance(); } public function __construct($paysys_id, DbSimple_Interface $db) { $this->db_ipb_nexus = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $payments) { $this->user = $user; $this->payments = $payments; return $this->doWork(); } function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$p['product_id']][] = $p; } } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='ipb_nexus:id'"); } return @$cache[$pid]; } } class InvoiceCreator_Ccbill extends InvoiceCreator_Abstract { function doWork() { foreach ($this->payments as $p) { if(!($amPrId = $this->_translateProduct($p['ps_item_id']))) { if($bp = $this->getDi()->billingPlanTable->findFirstByFirstPrice($p['i_total'])) { $amPrId = $bp->product_id; } else { if($p['i_total'] == 3.00) { $amPrId = $this->_translateProduct(3); } else { $this->getDi()->errorLogTable->log("Not found product #{$p['ps_item_id']} for user #[{$p['i_member']}]"); continue; } } } // ivoice + item $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($amPrId)); $item->qty = 1; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'ccbill'; $invoice->tm_added = date('Y-m-d H:i:s', $p['i_date']); $invoice->tm_started = date('Y-m-d H:i:s', $p['i_paid']); $invoice->currency = Am_Currency::getDefault(); $invoice->calculate(); $invoice->status = Invoice::PAID; $invoice->data()->set('ibp_nexus:id', $p['i_id']); $invoice->insert(); // insert payments $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = $p['i_total']; $payment->paysys_id = $invoice->paysys_id; $payment->dattm = $invoice->tm_started; $payment->receipt_id = $payment->transaction_id = 'import-ipb-nexus-' . mt_rand(10000, 99999); $payment->data()->set('ibp_nexus:id', $p['ps_id']); $payment->insert(); //insert access $a = $this->getDi()->accessRecord; $a->invoice_id = $invoice->pk(); $a->invoice_payment_id = $payment->pk(); $a->user_id = $this->user->user_id; $a->product_id = $amPrId; $a->transaction_id = $payment->transaction_id; $a->begin_date = date('Y-m-d', $p['ps_start']); $a->expire_date = $p['ps_expire'] ? date('Y-m-d', $p['ps_expire']) : Am_Period::MAX_SQL_DATE; $a->invoice_item_id = $invoice->getItem(0)->pk(); $a->invoice_public_id = $invoice->public_id; $a->setDisableHooks(); $a->insert(); } $this->user->checkSubscriptions(); } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_ipb_nexus; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_ipb_nexus, array $options = array()) { $this->db_ipb_nexus = $db_ipb_nexus; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init(){} public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='ipb_nexus:id'"); $q = $this->db_ipb_nexus->queryResultOnly("SELECT * FROM ?_nexus_packages"); while ($r = $this->db_ipb_nexus->fetchRow($q)) { if (in_array($r['p_id'], $importedProducts)) continue; $context++; $p = $this->getDi()->productRecord; $p->title = $r['p_name']; $p->description = $r['p_desc']; $p->data()->set('ipb_nexus:id', $r['p_id']); $p->insert(); $bp = $p->createBillingPlan(); $bp->title = 'default'; $data = unserialize($r['p_renew_options']); $bp->first_price = $data[0]['price']; $bp->first_period = $data[0]['term'] . $data[0]['unit']; $bp->rebill_times = 0; $bp->insert(); } return true; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { //$crypt = $this->getDi()->crypt; $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='ipb_nexus:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_ipb_nexus->queryResultOnly(" SELECT member_id, name, email, joined, ip_address, members_pass_hash, members_pass_salt FROM ?_members WHERE member_id > ?d ORDER BY member_id {LIMIT ?d} ",$maxImported, $count ? $count : DBSIMPLE_SKIP); //$q = $this->db_ipb_nexus->queryResultOnly(" // SELECT member_id, name, email, joined, ip_address, members_pass_hash, members_pass_salt // FROM ?_members // WHERE member_id > ?d AND member_id < 5000 // ORDER BY member_id // {LIMIT ?d} //",$maxImported, $count ? $count : DBSIMPLE_SKIP); //$q = $this->db_ipb_nexus->queryResultOnly("SELECT member_id, name, email, joined, ip_address, members_pass_hash, members_pass_salt // FROM ?_members // WHERE member_id IN (?a) //", array(9, 79290, 92408)); while ($r = $this->db_ipb_nexus->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; if ($r['name']) $u->login = $r['name']; else $u->generateLogin(); $u->email = $r['email']; $u->added = date('Y-m-d H:i:s', $r['joined']); $u->last_ip = $r['ip_address']; $u->is_approved = 1; $u->data()->set('ipb_nexus:id', $r['member_id']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time $u->data()->set(Am_Protect_Databased::USER_NEED_SETPASS, 1); try { $u->insert(); $savedPass = $this->getDi()->savedPassRecord; $savedPass->user_id = $u->pk(); $savedPass->format = 'Invision'; $savedPass->pass = $r['members_pass_hash']; $savedPass->salt = $r['members_pass_salt']; $savedPass->save(); if($this->insertPayments($r['member_id'], $u)) { $u->setGroups(array(1)); } $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } function insertPayments($id, User $u) { $payments = $this->db_ipb_nexus->select(" SELECT p.ps_id, i.i_id, p.ps_start, p.ps_expire, p.ps_item_id, i.i_member, i.i_total, i.i_date, i.i_paid FROM ?_nexus_purchases p LEFT JOIN ?_nexus_invoices i ON p.ps_original_invoice = i.i_id WHERE i.i_member = $id AND i.i_status = 'paid' ORDER BY i_id "); if(empty($payments)) return false; InvoiceCreator_Abstract::factory('ccbill', $this->db_ipb_nexus)->process($u, $payments); return true; } } class AdminImportIpbNexusController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_ipb_nexus; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { $enabled = $this->getDi()->plugins_protect->loadEnabled()->getAllEnabled(); foreach ($enabled as $k => $pl) { if($pl->getId() == 'invision') { unset ($enabled[$k]); break; } } $this->getDi()->plugins_protect->setEnabled($enabled); Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->ipb_nexus_db = null; $this->getSession()->ipb_nexus_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->ipb_nexus_import = null; } if (!$this->getSession()->ipb_nexus_db) return $this->askDbSettings(); $this->db_ipb_nexus = Am_Db::connect($this->getSession()->ipb_nexus_db); if (!$this->getSession()->ipb_nexus_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->ipb_nexus_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_ipb_nexus, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from IPB Nexus"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->ipb_nexus_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-ipb-nexus",array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function createCleanUpForm() { $form = new Am_Form_Admin(); $total_products = $this->getDi()->db->selectCell('SELECT count(product_id) FROM ?_product'); $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='ipb_nexus:id'"); $total_users = $this->getDi()->db->selectCell('SELECT count(user_id) FROM ?_user'); $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='ipb_nexus:id'"); $form->addStatic()->setLabel('IMPORTANT INFO')->setContent(<<Clean UP process cannot be reversed, so if you don't understand what are you doing, please navigate away from this page!
      Sometimes this is necessary to remove all data from aMember's database and start import over. This form helps to do this in one go. Please make sure that you don't have any importand data in database, because it can't be restored after clean up. This is good idea to make a backup before "Clean Up" operation.
      DATA WHICH WILL BE REMOVED BY THIS OPERATION:
      User Accounts
      User Invoices/Payments
      User CC info
      Products enabled by setting below
      Affiliate data(if aff module is enabled)
      Newsletter subscriptions data(if newsletter module is enabled)
      Helpdesk tickets(if helpdesk module is enabled)
      EOL ); $form->addAdvCheckbox('remove_products')->setLabel('Remove products'); $form->addPassword('password')->setLabel('Please confirm your Admin password'); $form->addSaveButton('Clean Up'); return $form; } function cleanUpData($value) { $tables = array('access', 'access_cache', 'access_log', 'cc', 'coupon', 'coupon_batch', 'invoice', 'invoice_item', 'invoice_log', 'invoice_payment', 'invoice_refund', 'saved_pass', 'user', 'user_status', 'user_user_group'); if($this->getDi()->modules->isEnabled('aff')) $tables = array_merge($tables, array('aff_click', 'aff_commission', 'aff_lead', 'aff_payout', 'aff_payout_detail')); if(@$value['remove_products']) $tables = array_merge($tables, array('billing_plan', 'product', 'product_product_category')); if($this->getDi()->modules->isEnabled('helpdesk')) $tables = array_merge($tables, array('helpdesk_ticket', 'helpdesk_message')); if($this->getDi()->modules->isEnabled('newsletter')) $tables = array_merge($tables, array('newsletter_list', 'newsletter_user_subscription')); // Doing cleanup foreach($tables as $table){ $this->getDi()->db->query('delete from ?_'.$table); } // Doing data table separately. if(!@$value['remove_products']){ $where = "where `table` <> 'product' and `table`<>'billing_plan'"; }else $where = ''; $this->getDi()->db->query('delete from ?_data '.$where); $this->redirectHtml($this->getDi()->url("admin-import-ipb-nexus",false), 'Records removed'); } function cleanAction() { $this->form = $this->createCleanUpForm(); $this->form->addDataSource($this->_request); if($this->form->isSubmitted() && $this->form->validate()){ $value = $this->form->getValue(); // Validate password; $admin = $this->getDi()->authAdmin->getUser(); if(!$admin->checkPassword($value['password'])){ $this->form->setError('Incorrect Password!'); }else{ $this->cleanUpData($this->form->getValue()); } } $this->view->title = "Clean up Database"; $this->view->content = (string)$this->form; $this->view->display('admin/layout.phtml'); } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->ipb_nexus_import = array( 'import' => $val['import'], 'user' => @$val['user'], ); $this->_redirect('admin-import-ipb-nexus'); return; } } $this->view->title = "Import IPB Nexus Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='ipb_nexus:id'"); $total = $this->db_ipb_nexus->selectCell("SELECT COUNT(*) FROM ?_nexus_packages"); if($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_product")) { $form->addStatic() ->setLabel(___('Clean up v4 Database')) ->setContent( sprintf(___('Use this %slink%s to delete data from aMember v4 database and use clean database for import'), '', '')); } if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); if ($imported_products) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='ipb_nexus:id'"); $total = $this->db_ipb_nexus->selectCell("SELECT COUNT(*) FROM ?_members"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->ipb_nexus_db = $this->form->getValue(); $this->_redirect('admin-import-ipb-nexus'); } else { $this->view->title = "Import IPB NExus Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('IPB MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('IPB MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('IPB MySQL Password'); $form->addText('db')->setLabel('IPB MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('IPB Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => '', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_members LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } }PK\ܚ¤ -default/controllers/AdminFieldsController.phpnu[addElement(new Am_Form_Element_ResourceAccess)->setName('_access') ->setLabel(___("Access Permissions\n" . 'this field will be removed from form if access permission ' . 'does not match and user will not be able to update this field')); } } class AdminFieldsController extends CustomFieldController { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_ADD_USER_FIELD); } public function preDispatch() { parent::preDispatch(); $this->view->headScript()->appendFile($this->view->_scriptJs("resourceaccess.js")); } protected function getTable() { return $this->getDi()->userTable; } public function createGrid() { $grid = parent::createGrid(); $grid->addCallback(Am_Grid_Editable::CB_AFTER_DELETE, array($this, 'afterDelete')); $grid->addCallback(Am_Grid_Editable::CB_AFTER_SAVE, array($this, 'afterSave')); $grid->setPermissionId(Am_Auth_Admin::PERM_ADD_USER_FIELD); return $grid; } public function createForm() { $form = new Am_Form_Admin_CustomField_User($this->grid->getRecord()); $form->setTable($this->getTable()); return $form; } public function valuesToForm(& $ret, $record) { parent::valuesToForm($ret, $record); $ret['_access'] = $record->name ? $this->getDi()->resourceAccessTable->getAccessList(amstrtoint($record->name), Am_CustomField::ACCESS_TYPE) : array( ResourceAccess::FN_FREE_WITHOUT_LOGIN => array( json_encode(array( 'start' => null, 'stop' => null, 'text' => ___('Free Access without log-in') ))) ); } public function afterSave(array & $values, $record) { $record->name = $record->name ? $record->name : $values['name']; $this->getDi()->resourceAccessTable->setAccess(amstrtoint($record->name), Am_CustomField::ACCESS_TYPE, $values['_access']); } public function afterDelete($record) { $this->getDi()->resourceAccessTable->clearAccess(amstrtoint($record->name), Am_CustomField::ACCESS_TYPE); foreach ($this->getDi()->savedFormTable->findBy() as $savedForm) { if ($row = $savedForm->findBrickById('field-' . $record->name)) { $savedForm->removeBrickConfig($row['class'], $row['id']); $savedForm->update(); } } } }PK\(UU,default/controllers/AdminEmailController.phpnu[hasPermission(Am_Auth_Admin::PERM_EMAIL); } function preDispatch() { ignore_user_abort(true); @set_time_limit(0); @ini_set('memory_limit', AM_HEAVY_MEMORY_LIMIT); $this->setActiveMenu('users-email'); if ($this->queue_id = $this->getFiltered('queue_id')) { $this->saved = $this->getDi()->emailSentTable->load($this->queue_id); $this->_request->fromArray($this->saved->unserialize()); } elseif ($id = $this->getInt('resend_id')) { $this->saved = $this->getDi()->emailSentTable->load($id); unset($_GET['resend_id']); $_POST = $this->saved->unserialize(); unset($_POST['_save_']); $this->getRequest()->fromArray($_POST); } $this->_request->set('format', $this->getParam('format', 'html')); $this->searchUi = new Am_Query_Ui; $this->searchUi->addDefaults(); $this->searchUi->setFromRequest($this->_request); } function renderUserUrl(User $user) { $url = $this->getView()->userUrl($user->user_id); return sprintf('%s', $this->escape($url), $this->escape($user->login)); } function browseUsersAction() { $withWrap = (bool) $this->_request->get('_u_wrap'); unset($_GET['_u_wrap']); $ds = $this->searchUi->getActive()->getQuery(); $grid = new Am_Grid_ReadOnly('_u', ___('Selected for E-Mailing'), $ds, $this->_request, $this->view); if ($withWrap) $grid->isAjax(false); $grid->setCountPerPage(10); $grid->addField('login', ___('Username'))->setRenderFunction(array($this, 'renderUserUrl')); $grid->addField('name_f', ___('First Name')); $grid->addField('name_l', ___('Last Name')); $grid->addField('email', ___('E-Mail Address')); $grid->run($this->getResponse()); } /** * For Admin CP->Setup->Email 'test' function */ function testAction() { check_demo(); $config = $this->getDi()->config; foreach ($this->getRequest()->toArray() as $k => $v) $config->set($k, strip_tags($v)); $m = $this->getDi()->mail; $m->addTo($this->getParam('email'), 'Test E-Mail') ->setSubject('Test E-Mail Message from aMember ') ->setBodyText("This is a test message sent from aMember CP\n\nURL: " . $this->getDi()->url('',null,false,true)); $m->setPeriodic(Am_Mail::ADMIN_REQUESTED); $m->setPriority(Am_Mail::PRIORITY_HIGH); try { $m->send(new Am_Mail_Queue($config)); } catch (Exception $e) { echo '' . ___('Error during e-mail sending') . ': ' . get_class($e) . ':' . $e->getMessage() . ''; return; }; $f = current(Am_Mail::getDefaultFrom()); $e = htmlentities($this->getParam('email')); $tm = date('Y-m-d H:i:s'); print ___('

      Message has been sent successfully. Please wait 2 minutes and check the mailbox %s.
      ' . 'There must be a message with subject [Test E-Mail]. Do not forget to check Spam folder.

      ' . '

      If the message does not arrive shortly, contact your webhosting support and ask them to find
      ' . 'in mail.log what happened with a message sent from %s to %s at %s

      ', $e, $f, $e, $tm); } function getAttachments() { if (!$this->_request->getParam('files')) return array(); if (!$this->_attachments) { $this->_attachments = array(); foreach ($this->getDi()->uploadTable->findByIds($this->getParam('files'), 'email') as $f) { /* @var $f Upload */ $at = new Zend_Mime_Part(file_get_contents($f->getFullPath(), 'r')); $at->type = $f->getType(); $at->filename = $f->getName(); $at->disposition = Zend_Mime::DISPOSITION_ATTACHMENT; $at->encoding = Zend_Mime::ENCODING_BASE64; $this->_attachments[] = $at; } } return $this->_attachments; } function createSendSession() { $saved = $this->getDi()->emailSentTable->createRecord(); $saved->admin_id = $this->getDi()->authAdmin->getUserId(); $vars = $this->getRequest()->toArray(); $saved->serialize($this->getRequest()->toArray()); $saved->count_users = $this->searchUi->getFoundRows(); $saved->desc_users = $this->searchUi->getActive()->getDescription(); $saved->sent_users = 0; $saved->is_cancelled = 0; $saved->newsletter_ids = implode(',', array_filter(array_map('intval', $this->searchUi->getTargetListIds()))); $saved->insert(); $this->saved = $saved; } function sendRedirect() { $done = $this->saved->sent_users; $total = $this->saved->count_users; $url = $this->getUrl(null, 'send', null, array('queue_id' => $this->saved->pk())); $text = $total > 0 ? (___('Sending e-mail (sent to %d from %d)', $done, $total) . '. ' . ___('Please wait')) : ___('E-Mail sending started'); $text .= '...'; $this->redirectHtml($url, $text, ___('E-Mail Sending') . '...', false, $done, $total); } function sendComplete() { $this->saved->updateQuick('tm_finished', $this->getDi()->sqlDateTime); $total = $this->saved->count_users; $this->view->assign('title', ___('Email Sent')); ob_start(); $queue_id = $this->getFiltered('queue_id'); print '
      '; __e('E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s', $total, $queue_id); print '. '; $url = $this->getUrl(null, 'index'); print '' . ___('Send New E-Mail') . '
      '; $this->view->assign('content', ob_get_clean()); $this->view->display('admin/layout.phtml'); } protected function getReplyToOptions() { $op = array(); $op['default'] = Am_Html::escape(sprintf('%s <%s>', $this->getConfig('admin_email_name', $this->getConfig('site_title')), $this->getConfig('admin_email_from', $this->getConfig('admin_email')))); foreach (Am_Di::getInstance()->adminTable->findBy() as $admin) { $op['admin-' . $admin->pk()] = Am_Html::escape(sprintf('%s <%s>', $admin->getName(), $admin->email)); } $op['other'] = ___('Other') . ':'; return $op; } function createForm() { $form = new Am_Form_Admin('am-form-email'); $form->setDataSources(array($this->getRequest())); $form->setAction($this->getUrl(null, 'preview')); if ($options = $this->getDi()->emailTemplateLayoutTable->getOptions()) { $form->addSelect('email_template_layout_id') ->setLabel(___('Layout')) ->loadOptions(array(''=>___('No Layout')) + $options); } $gr = $form->addGroup() ->setLabel(___("Reply To\n" . "mailbox for replies to message")) ->setSeparator(' '); $sel = $gr->addSelect('reply_to') ->loadOptions($this->getReplyToOptions()); $id = $sel->getId(); $gr->addText('reply_to_other', array('placeholder' => ___('Email Address'))) ->setId($id.'-other') ->persistentFreeze(true); // ??? why is it necessary? but it is $gr->addScript() ->setScript(<<addText('subject', array('class' => 'el-wide')) ->setLabel(___('Email Subject')); $subj->persistentFreeze(true); // ??? why is it necessary? but it is $subj->addRule('required', ___('Subject is required')); // $arch = $form->addElement('advcheckbox', 'do_archive')->setLabel("Archive Message\n" . 'if you are sending it to newsletter subscribers'); $format = $form->addGroup(null)->setLabel(___('E-Mail Format')); $format->setSeparator(' '); $format->addRadio('format', array('value' => 'html'))->setContent(___('HTML Message')); $format->addRadio('format', array('value' => 'text'))->setContent(___('Plain-Text Message')); $group = $form->addGroup('', array('id' => 'body-group', 'class' => 'no-label')) ->setLabel(___('Message Text')); $group->addStatic()->setContent('
      '); $group->addStatic()->setContent('
      '); $group->addElement('textarea', 'body', array('id' => 'body-0', 'rows' => '15', 'class' => 'el-wide')); $group->addStatic()->setContent('
      '); $group->addStatic()->setContent('
      '); $this->tagsOptions = Am_Mail_TemplateTypes::getInstance()->getTagsOptions('send_signup_mail'); $tagsOptions = array(); foreach ($this->tagsOptions as $k => $v) { $tagsOptions[$k] = "$k - $v"; } $sel = $group->addSelect('', array('id' => 'insert-tags',)); $sel->loadOptions(array_merge(array('' => ''), $tagsOptions)); $group->addStatic()->setContent('
      '); $group->addStatic()->setContent('
      '); $fileChooser = new Am_Form_Element_Upload('files', array('multiple' => '1'), array('prefix' => 'email')); $form->addElement($fileChooser)->setLabel(___('Attachments')); foreach ($this->searchUi->getHidden() as $k => $v) { $form->addHidden($k)->setValue($v); } $id = 'body-0'; $vars = ""; foreach ($this->tagsOptions as $k => $v) $vars .= sprintf("[%s, %s],\n", json_encode($v), json_encode($k)); $vars = trim($vars, "\n\r,"); if($this->queue_id) $form->addHidden('queue_id')->setValue($this->queue_id); $form->addScript('_bodyscript')->setScript(<<getDi()->hook->call(Am_Event::MAIL_SIMPLE_INIT_FORM, array('form' => $form)); $buttons = $form->addGroup('buttons'); $buttons->addSubmit('send', array('value' => ___('Preview'))); return $form; } /** @return Am_Form_Admin */ function getForm() { if (!$this->form) $this->form = $this->createForm(); return $this->form; } function previewAction() { $form = $this->getForm(); if ($this->form->validate()) { $form->toggleFrozen(true); $form->setAction($this->getUrl(null, 'send')); $el = $form->getElementById('send-0')->setAttribute('value', ___('Send E-Mail Message')); $el->getContainer()->setSeparator(' '); $el->getContainer()->addElement('inputbutton', 'back', array( 'value' => 'Back', 'class' => 'form-back', 'data-href' => $this->getUrl(null, 'index'))); // remove text and add hidden instead $group = $form->getElementById('body-group'); $group->removeChild($form->getElementById('body-0')); $group->addHidden('body'); $body = $this->getParam('body'); if($id_ = $this->getParam('email_template_layout_id')) { $layout_ = $this->getDi()->emailTemplateLayoutTable->load($id_); $tpl_ = new Am_SimpleTemplate(); $tpl_->assign('content',$body); $body = $tpl_->render($layout_->layout); } $html = json_encode($body); // now add it for display $form->addScript('_bodyscript')->setScript(<< after newlines if (jQuery("input[name='format']").val() == 'text') { jQuery("#row-body-group .element.group").html('
      * * Where: * ALGORITHM := The signing algorithm used for the credential, ex. DTAv1-SHA-256 * CREDENTIAL := KEYID/DATE. * SIGNED_HEADERS := lower cased header names sorted by byte order joined with semicolons. * SIGNATURE := The signature calculated by the signing algorithm. * KEYID := The public id for the sceret key used to calculate the signature. * DATE := The date the message was signed in YYMMDD format. This is used to generate the daily key. */ class AuthorizationHeader { /** @var string */ private $algorithm; /** @var string */ private $credential; /** @var string */ private $signedHeaders; /** @var string */ private $signature; const AUTHORIZATION_HEADER_PATTERN = '/(\S+) SignedHeaders=(\S+), Credential=(\S+), Signature=([\S]+)$/'; /** * Parses header value string an returns a new object. * * @param string $headerString the string representation of the Authentication header * * @return AuthorizationHeader a new {@link AuthorizationHeader} object if header is valid * * @throws InvalidArgumentException if unable to parse header */ public static function parse($headerString) { if (empty($headerString)) { throw new \InvalidArgumentException('Invalid authorization header.'); } preg_match(self::AUTHORIZATION_HEADER_PATTERN, $headerString, $matches); if (!$matches) { throw new \InvalidArgumentException('Unable to parse authorization header.'); } // split headers by ';' and convert them to lower case $signedHeaders = array_map('strtolower', explode(';', $matches[2])); // the credential should follow this pattern: PUBLIC_KEY_ID/DATE $credential = explode('/', $matches[3]); if (count($credential) < 2) { throw new \InvalidArgumentException('Invalid credential format.'); } $credential = array('key' => $credential[0], 'date' => $credential[1]); // the algorithm used to generate the signature $algorithm = $matches[1]; // the signature of the request $signature = $matches[4]; $header = new AuthorizationHeader( $algorithm, $signedHeaders, $credential, $signature ); return $header; } public function __construct($algorithm, $signedHeaders, $credential, $signature) { if (empty($algorithm)) { throw new \InvalidArgumentException('Empty algorithm information.'); } if (!is_array($signedHeaders)) { throw new \InvalidArgumentException('Invalid signed headers array.'); } if (!is_array($credential) || !array_key_exists('key', $credential) || !array_key_exists('date', $credential)) { throw new \InvalidArgumentException('Invalid credential information.'); } if (empty($signature)) { throw new \InvalidArgumentException('Empty signature information.'); } $this->algorithm = $algorithm; $this->signedHeaders = $signedHeaders; $this->credential = $credential; $this->signature = $signature; } public function getAlgorithm() { return $this->algorithm; } public function getCredential() { return $this->credential; } public function getSignedHeaders() { return $this->signedHeaders; } public function getSignature() { return $this->signature; } public function __tostring() { $str = $this->algorithm . ' '; $str .= 'SignedHeaders=' . implode(';', $this->signedHeaders) . ', '; $str .= 'Credential=' . $this->credential['key'] . '/'. $this->credential['date'] .', '; $str .= 'Signature=' . $this->signature; return $str; } } PK\&  Xdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Signature/Request.phpnu[url = HttpUtils::parseFullURL($server); $this->method = $server['REQUEST_METHOD']; $this->headers = HttpUtils::parseRequestHeaders($server); $this->body = $requestBody; } public function getUrl() { return $this->url; } public function getMethod() { return $this->method; } public function getBody() { return $this->body; } public function &getHeaders() { return $this->headers; } /** * Remove headers that are present in $filter * * @param array $filter array of headers to be removed from this request */ public function filterHeaders(array $filter) { $this->headers = array_diff_key($this->headers, array_flip($filter)); } /** * @return string a human-friendly string representation of the Request */ public function __tostring() { $headersStr = implode( ', ', array_map( function ($v, $k) { return sprintf("%s:'%s'", $k, $v); }, $this->getHeaders(), array_keys($this->getHeaders()) ) ); $bodyStr = trim(preg_replace('/\s+/', ' ', $this->getBody())); return sprintf( 'Method: %s, Url: %s, Headers: %s, Body: %s', $this->getMethod(), $this->getMethod(), $headersStr, $bodyStr ); } } PK\(,`default/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Signature/CredentialStore.phpnu[store)) { return null; } return $this->store[$publicKey]; } /** * Gets the credentials stored in this store. * * @return array an array with all the credentials */ public function getAll() { return $this->store; } /** * Adds the new credential to the store. If the store already contains the public key, the credential is replaced. * * @param Credential credential the credential object to be added */ public function add(Credential $credential) { $this->store[$credential->getPublicKey()] = $credential; } /** * Removes the credential from the store. * * @param string $publicKey the public key of the credential to be removed */ public function remove($publicKey) { unset($this->store[$publicKey]); } /** * Loads keys from a file and populates the store. * * Each line of the file must contain a secret key and a public key separated by an empty space. * * @param string $filePath the path of the file that contains the keys * * @throws InvalidArgumentException if the file does not exist */ public function loadFromFile($filePath) { if (empty($filePath) || !file_exists($filePath)) { $message = 'Invalid keys file path'; throw new \InvalidArgumentException($message); } $contents = file_get_contents($filePath); $this->load($contents); } /** * Loads keys from a string and populates the store. * * Each line of the file must contain a secret key and a public key separated by an empty space. * * @param string $contents the string object that contains the keys * * @throws InvalidArgumentException if the content is empty or malformed */ public function load($contents) { if (empty($contents)) { $message = 'Empty key container'; throw new \InvalidArgumentException($message); } $lines = explode(PHP_EOL, $contents); foreach ($lines as $i => $line) { // Ignore blank lines in between credentials if (!$line) { continue; } // credentials should be separate by an empty space $keys = preg_split('/\s+/', $line); // Invalid format if (count($keys) < 2) { $message = 'Invalid credentials format found on line ' . $i; throw new \InvalidArgumentException($message); } $secretKey = $keys[0]; $publicKey = $keys[1]; $this->store[$publicKey] = new Credential($secretKey, $publicKey); } } } PK\%%Wdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Signature/Signer.phpnu[format(DateUtils::DATE_FORMAT_SHORT); $isoDate = $dateNow->format(DateUtils::DATE_FORMAT_ISO8601); $headers = &$request->getHeaders(); $headers[HttpUtils::X_AMZ_DATE_HEADER] = $isoDate; // Remove the Authorization header from the request, since it could have been set if sign() was previously // called on this request. unset($headers[HttpUtils::AUTHORIZATION_HEADER]); $authorizationHeader = $this->getAuthorizationHeader($request, $credential, $shortDate, $isoDate); Logger::getLogger()->debug(sprintf('Signing request with header: %s', $authorizationHeader)); $headers[HttpUtils::AUTHORIZATION_HEADER] = $authorizationHeader; } /** * Verifies the request signature against a credential store. * * @param Request $request the request to verify. * @param CredentialStore $credentialStore the credential store used to verify the request. * * @return boolean returns true if the request validates. */ public function verify(Request $request, CredentialStore $credentialStore) { if (count($credentialStore->getAll()) == 0) { throw new \InvalidArgumentException('Empty credential store.'); } $dateNow = new \DateTime('@' . time()); $shortDate = $dateNow->format(DateUtils::DATE_FORMAT_SHORT); $headers = $request->getHeaders(); if (!isset($headers[HttpUtils::X_AMZ_DATE_HEADER])) { Logger::getLogger()->warning( sprintf('Header %s not found, aborting request verification.', HttpUtils::X_AMZ_DATE_HEADER) ); return false; } $requestIsoDate = $headers[HttpUtils::X_AMZ_DATE_HEADER]; if (!isset($headers[HttpUtils::AUTHORIZATION_HEADER])) { Logger::getLogger()->warning( sprintf('Header %s not found, aborting request verification.', HttpUtils::AUTHORIZATION_HEADER) ); return false; } $actualAuthorization = $headers[HttpUtils::AUTHORIZATION_HEADER]; $authorizationHeader = null; try { $authorizationHeader = AuthorizationHeader::parse($actualAuthorization); } catch (\InvalidArgumentException $e) { Logger::getLogger()->warning( sprintf('Unable to parse Authorization header, aborting request verification.') ); return false; } $signedHeaders = $authorizationHeader->getSignedHeaders(); // remove unsigned headers $unsignedHeaders = array_diff_key(($request->getHeaders()), array_flip($signedHeaders)); $request->filterHeaders(array_keys($unsignedHeaders)); $dateOfRequest = \DateTime::createFromFormat(DateUtils::DATE_FORMAT_ISO8601, $requestIsoDate); $delta = $dateOfRequest->getTimestamp() - $dateNow->getTimestamp(); if (abs($delta) > self::TIME_TOLERANCE_IN_MS) { Logger::getLogger()->warning(sprintf('Time tolerance exceeded, aborting request verification.')); return false; } $credentialInfo = $authorizationHeader->getCredential(); $credential = $credentialStore->get($credentialInfo['key']); if (!$credential) { Logger::getLogger()->warning( sprintf('Public key not found: %s, aborting request verification.', $credentialInfo['key']) ); return false; } if ($dateOfRequest->format(DateUtils::DATE_FORMAT_SHORT) != $credentialInfo['date']) { Logger::getLogger()->warning( sprintf('Request date and credential date don`t match aborting request verification.') ); return false; } $authorizationHeader = $this->getAuthorizationHeader($request, $credential, $shortDate, $requestIsoDate); Logger::getLogger()->debug( sprintf( 'Verifying request with header: %s, against expected header: %s', $actualAuthorization, $authorizationHeader ) ); if ($authorizationHeader == $actualAuthorization) { return true; } else { Logger::getLogger()->warning(sprintf('Authorization signature doesn`t match, verification failed.')); return false; } } /** * Returns the autorization header based on the parameters * * @param Request $request the request to generate the signature from * @param Credential $credential the credential to use when signing * @param string $shortDate the date to use to sign in short format * @param string $isoDate the date to use to sign in iso format * * @return string a string representation of the authorization header */ public function getAuthorizationHeader(Request $request, Credential $credential, $shortDate, $isoDate) { if (!$shortDate || !$isoDate) { throw new \InvalidArgumentException('Invalid dates.'); } $timedKey = hash_hmac('sha256', $shortDate, $credential->getSecretKey(), true); $canonicalRequest = $this->getCanonicalRequest($request); // We don't use scope in this algorithm $scope = ''; $stringToSign = self::ALGORITHM_ID . "\n" . $isoDate . "\n" . $scope . "\n" . hash('sha256', $canonicalRequest); Logger::getLogger()->debug(sprintf('String to sign: %s', $stringToSign)); $signature = hash_hmac('sha256', $stringToSign, $timedKey); $headers = $request->getHeaders(); ksort($headers); $authorizationHeader = new AuthorizationHeader( self::ALGORITHM_ID, array_keys($headers), array('key' => $credential->getPublicKey(), 'date' => $shortDate), $signature ); return $authorizationHeader->__tostring(); } /** * Returns the canonical representation of the request. The canonical request is of the form: * *
           * METHOD
           * CANONICAL_PATH
           * CANONICAL_QUERY_STRING
           * CANONICAL_HEADER_STRING
           * SIGNED_HEADERS
           * CONTENT_HASH
           * 
      * * Which for a get request to http://amazon.com/ would be: * *
           * GET
           * /
           *
           * x-amz-date:20110909T233600Z
           * 230d8358dc8e8890b4c58deeb62912ee2f20357ae92a5cc861b98e68fe31acb5
           * 
      * * @param Request $request the request to canonicalize. * @return string the canonical request. */ private function getCanonicalRequest(Request $request) { // Method $canonicalRequest = $request->getMethod() . "\n"; // Path $url = parse_url($request->getUrl()); $canonicalRequest .= HttpUtils::normalizePath($url['path']) . "\n"; // Query string // TODO: the Java SDK does not add the query string to the canonical form $canonicalRequest .= "\n"; // Headers $headers = array(); foreach ($request->getHeaders() as $key => $value) { $headers[$key] = preg_replace('/\s+/', ' ', trim($value)); } ksort($headers); foreach ($headers as $key => $value) { $canonicalRequest .= $key . ':' . $value . "\n"; } // TODO: the Java SDK adds a empty line after the headers $canonicalRequest .= "\n"; // Signed headers $headers = $request->getHeaders(); ksort($headers); $canonicalRequest .= implode(';', array_keys($headers)) . "\n"; // Content hash $canonicalRequest .= hash('sha256', $request->getBody()); Logger::getLogger()->debug(sprintf('Canonical request: %s', $canonicalRequest)); return $canonicalRequest; } } PK\Iedefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Controllers/PurchaseController.phpnu[ * {@link PurchaseController::onFulfillPurchase()}
      * {@link PurchaseController::onRevokePurchase()}
      * {@link PurchaseController::onSubscriptionActivate()}
      * {@link PurchaseController::onSubscriptionDeactivate()}
      *
      * The callbacks are called when the {@link Controller::process()} method is invoked. */ class PurchaseController extends Controller { /** @var \Closure */ private $fulfillPurchaseCallback; /** @var \Closure */ private $revokePurchaseCallback; /** @var \Closure */ private $subscriptionActivateCallback; /** @var \Closure */ private $subscriptionDeactivateCallback; /** * Set the callback function for fulfill purchase * * @param \Closure $callback a callable object that receives a {@link FulfillPurchaseRequest} object * and returns a {@link FulfillPurchaseResponse} */ public function onFulfillPurchase(\Closure $callback) { $this->fulfillPurchaseCallback = $callback; } /** * Set the callback function for revoke purchase * * @param \Closure $callback a callable object that receives a {@link RevokePurchaseRequest} object * and returns a {@link RevokePurchaseResponse} */ public function onRevokePurchase(\Closure $callback) { $this->revokePurchaseCallback = $callback; } /** * Set the callback function for subscription activate * * @param \Closure $callback a callable object that receives a {@link SubscriptionActivateRequest} object * and returns a {@link SubscriptionActivateResponse} */ public function onSubscriptionActivate(\Closure $callback) { $this->subscriptionActivateCallback = $callback; } /** * Set the callback function for subscription deactivate * * @param \Closure $callback a callable object that receives a {@link SubscriptionDeactivateRequest} object * and returns a {@link SubscriptionDeactivateResponse} */ public function onSubscriptionDeactivate(\Closure $callback) { $this->subscriptionDeactivateCallback = $callback; } protected function processOperation($operation) { switch ($operation) { case InstantAccessOperationValue::PURCHASE: $callback = $this->fulfillPurchaseCallback; $request = FulfillPurchaseRequest::createFromJson($this->request->getBody()); break; case InstantAccessOperationValue::REVOKE: $callback = $this->revokePurchaseCallback; $request = RevokePurchaseRequest::createFromJson($this->request->getBody()); break; case InstantAccessOperationValue::SUBSCRIPTION_ACTIVATE: $callback = $this->subscriptionActivateCallback; $request = SubscriptionActivateRequest::createFromJson($this->request->getBody()); break; case InstantAccessOperationValue::SUBSCRIPTION_DEACTIVATE: $callback = $this->subscriptionDeactivateCallback; $request = SubscriptionDeactivateRequest::createFromJson($this->request->getBody()); break; default: throw new \InvalidArgumentException( sprintf('Operation %s is not supported by %s', $operation, get_class($this)) ); } if (!$callback) { throw new \UnexpectedValueException(sprintf('Callback not set for %s', $operation)); } $iaResponse = $callback($request); return $iaResponse; } } PK\͋V V kdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Controllers/AccountLinkingController.phpnu[getUserIdCallback = $callback; } protected function processOperation($operation) { switch ($operation) { case InstantAccessOperationValue::GET_USER_ID: $callback = $this->getUserIdCallback; $request = GetUserIdRequest::createFromJson($this->request->getBody()); break; default: throw new \InvalidArgumentException( sprintf('Operation %s is not supported by %s', $operation, get_class($this)) ); } if (!$callback) { throw new \UnexpectedValueException(sprintf('Callback not set for %s', $operation)); } $iaResponse = $callback($request); return $iaResponse; } } PK\j[vv]default/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Controllers/Controller.phpnu[credentialStore = $credentialStore; $this->signer = $signer ?: new Signer(); } /** * Processes the specific operation and return a response. * * @param string $operation the name of the operation being processed * * @return InstantAccessResponse an object that extends {@link InstantAccessResponse} object */ abstract protected function processOperation($operation); /** * Processes a request created from $_SERVER and the body of the request. * * At the end this function sets the response headers and writes the content. After calling this, be sure * to write the string returned to the output stream. * * NOTE: This consumes the body of the request which can cause issues when you try and read it again. * * @uses Controller::processOperation() to call the correct callback * * @param array $server the $_SERVER array * @param string|null $requestBody the path/stream of the body of the request, defaults to php://input * * @return string the response string ready to be sent */ public function process(array $server, $requestBody = 'php://input') { try { Logger::getLogger()->info(sprintf('Started processing request received by %s', get_class($this))); // convert all errors to exception so they can be caught and not just break the script set_error_handler( function ($code, $message, $file, $line, $context) { throw new \Exception($message, $code); } ); // read content of request to a string $body = file_get_contents($requestBody); // create request object $this->request = new Request($server, $body); Logger::getLogger()->debug(sprintf('Request: %s', (string)$this->request)); // verify the request againts the credential store if (!$this->signer->verify($this->request, $this->credentialStore)) { throw new \Exception('Request validation failed.'); } // deserialize the content to a InstantAccessRequest object so we can check which operation is going // to be called $iaRequest = InstantAccessRequest::createFromJson($this->request->getBody()); Logger::getLogger()->info(sprintf('Processing request as %s operation', $iaRequest->getOperation())); // process the request according to the operation $iaResponse = $this->processOperation($iaRequest->getOperation()); // check if the response is valid if (!is_subclass_of($iaResponse, 'Amazon\InstantAccess\Serialization\InstantAccessResponse')) { throw new \UnexpectedValueException( 'Invalid response returned by the controller. ' . 'It needs to be a subclass of InstantAccessResponse' ); } HttpUtils::setResponseHeader('HTTP/1.1 200 OK', true, 200); HttpUtils::setResponseHeader('Content-Type: application/json'); $response = $iaResponse->toJson(); Logger::getLogger()->debug(sprintf('Response: %s', $response)); Logger::getLogger()->info(sprintf('Request processed succesfully')); } catch (\Exception $e) { Logger::getLogger()->error(sprintf('Unable to process request: %s', $e)); HttpUtils::setResponseHeader('HTTP/1.1 500 Internal Server Error', true, 500); HttpUtils::setResponseHeader('Content-Type: text/plain'); $response = ''; } // restore previous error handler restore_error_handler(); return $response; } } PK\ Qdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Log/Logger.phpnu[ $value) { if (substr($key, 0, 5) == 'HTTP_') { $key = substr($key, 5); } elseif ($key != 'CONTENT_TYPE' && $key != 'CONTENT_LENGTH') { continue; } $header = str_replace('_', '-', strtolower($key)); $headers[$header] = $value; } // fix by aMember 2015-12-08 // This seems to be the only way to get the Authorization header on Apache if (function_exists('apache_request_headers')) { $headers = apache_request_headers(); if (isset($headers[$header])) { return $headers[$header]; } $header = strtolower($header); foreach (apache_request_headers() as $key => $value) { $header = str_replace('_', '-', strtolower($key)); $headers[$header] = $value; } } ///// return $headers; } /** * Normalize the URL according to RFC 3986. * * This function replaces multiple slashses with a single one and eliminates '.' (current directory) and * '..' (parent directory). * * @param string a path * * @return string a normalized path */ public static function normalizePath($path) { if (!$path) { return '/'; } $parts = explode('/', $path); $normalizedParts = array(); foreach ($parts as $part) { if ($part == '..') { array_pop($normalizedParts); } elseif ($part != '.' && $part != '') { $normalizedParts[] = $part; } } $newPath = ''; if ($path[0] == '/') { $newPath .= '/'; } $newPath .= implode('/', $normalizedParts); if ($path != '/' && end($parts) == '') { $newPath .= '/'; } return $newPath; } } PK\4D&O&O)default/plugins/payment/gocardlesspro.phpnu[addText('merchant_id', array('size' => 10)) ->setLabel('Your Merchant ID'); $form->addText('access_token', array('size' => 64)) ->setLabel('Your Merchant access token'); $form->addText('webhook_token', array('size' => 64)) ->setLabel('Your Merchant WebHook token'); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox(Testing) Account?"); } public function isConfigured() { return $this->getConfig('merchant_id') && $this->getConfig('access_token'); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $rootURL = $this->getDi()->url('',null,true,2); $url = Am_Html::escape($this->getPluginUrl('ipn')); return <<GoCardless payment plugin configuration 1. Enable "gocardlesspro" payment plugin at aMember CP->Setup->Plugins 2. Configure "GoCardlesspro" payment plugin at aMember CP -> Setup/Configuration -> GoCardlesspro 3. Set up "Webhook URI" in your GoCardless merchant account to $url Set up "Redirect URI" and "Cancel URI" to $rootURL CUT; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $response = $this->_sendRequest('/redirect_flows', array ( 'redirect_flows' => array ( 'description' => $invoice->getLineDescription(), 'session_token' => Zend_Session::getId(), 'success_redirect_url' => $this->getPluginUrl('thanks'), 'links' => array('creditor' => $this->getConfig('merchant_id')) ) )); $response = json_decode($response->getBody(),true); if (!isset($response['redirect_flows']) || !isset($response['redirect_flows']['redirect_url'])) return false; $this->invoice->data()->set('gocardlesspro_id', $response['redirect_flows']['id'])->update(); $result->setAction(new Am_Paysystem_Action_Redirect($response['redirect_flows']['redirect_url'])); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gocardlesspro_Ipn($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gocardlesspro_Thanks($this, $request, $response, $invokeArgs); } private function _sendRequest($url, $params, $method = 'POST') { $request = $this->createHttpRequest(); $request->setHeader(array( 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'User-Agent' => 'gocardlesspro-php/v0.0.1', 'Authorization' => 'Bearer '.$this->getConfig('access_token'), 'GoCardless-version' => '2015-04-29' // Latest version )); $request->setUrl(($this->getConfig('testing') ? Am_Paysystem_Gocardlesspro::SANDBOX_URL : Am_Paysystem_Gocardlesspro::LIVE_URL) . $url); if (!is_null($params)) { $request->setBody(json_encode($params)); } $request->setMethod($method); $this->logOther('Request to '.$url, var_export($params, true)); $response = $request->send(); $this->logOther('Response to '.$url, var_export($response, true)); return $response; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { // Cancelling subscription $subscriptionId = $invoice->data()->get('subscription_id'); $response = $this->_sendRequest('/subscriptions/'.$subscriptionId.'/actions/cancel'); if ($response->getStatus() !== 200) { throw new Am_Exception_InputError("An error occurred while cancellation request"); } // Cancelling mandate $mandateId = $invoice->data()->get('mandate_id'); $response = $this->_sendRequest('/mandates/'.$mandateId.'/actions/cancel'); if ($response->getStatus() !== 200) { throw new Am_Exception_InputError("An error occurred while cancellation request"); } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { // Request to check state of payment ; must be confirmed / paid_out $response = $this->_sendRequest('/payments/'.$payment->transaction_id, null, 'GET'); if ($response->getStatus() !== 200) { $result->setFailed('An error occured, unable to find the payment.'); return $result; } $response = json_decode($response->getBody(),true); if (!in_array($response['payments']['status'], array('confirmed', 'paid_out'))) { $result->setFailed('Payment status must be either "Confirmed" or "Paid out" at GoCardLess. Current state is "'.$response['payments']['status'].'"'); return $result; } $response = $this->_sendRequest('/refunds/', array ( 'refunds' => array ( 'amount' => intval(doubleval($amount) * 100), 'total_amount_confirmation' => intval(doubleval($amount) * 100), 'links' => array ('payment' => $payment->transaction_id) ) )); if ($response->getStatus() !== 201) { throw new Am_Exception_InputError("An error occurred while cancellation request"); } $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id.'-gocardlesspro-refund'); $result->setSuccess($trans); } } class Am_Paysystem_Transaction_Gocardlesspro_Payment extends Am_Paysystem_Transaction_Incoming { public function __construct(Am_Paysystem_Abstract $plugin, array $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, new Am_Mvc_Request($request), $response, $invokeArgs); } public function getUniqId() { return $this->request->get('id'); } public function findInvoiceId() { $i = Am_Di::getInstance()->invoiceTable->findFirstByData('gocardlesspro_id', $this->getUniqId()); if($i) { $this->invoice = $i; return $i->public_id; } return null; } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Gocardlesspro_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->request->get('redirect_flow_id'); } public function findInvoiceId() { $i = Am_Di::getInstance()->invoiceTable->findFirstByData('gocardlesspro_id', $this->getUniqId()); if($i) { $this->invoice = $i; return $i->public_id; } return null; } private function _sendRequest($url, $params, $method = 'POST') { $request = $this->plugin->createHttpRequest(); $request->setHeader(array( 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'User-Agent' => 'gocardlesspro-php/v0.0.1', 'Authorization' => 'Bearer '.$this->plugin->getConfig('access_token'), 'GoCardless-version' => '2015-04-29' // Current API version (version header might be updated soon, see https://gocardless.com/blog/) )); $request->setUrl(($this->plugin->getConfig('testing') ? Am_Paysystem_Gocardlesspro::SANDBOX_URL : Am_Paysystem_Gocardlesspro::LIVE_URL) . $url); if (!is_null($params)) { $request->setBody(json_encode($params)); } $request->setMethod($method); $this->plugin->logOther('Request to '.$url, var_export($params, true)); $response = $request->send(); $this->plugin->logOther('Response to '.$url, var_export($response, true)); return $response; } private function _updateInvoice($type, $id) { switch ($type) { case 'mandate': $this->invoice->data()->set('mandate_id', $id)->update(); break; case 'subscription': $this->invoice->data()->set('subscription_id', $id)->update(); break; } } public function processValidated() { // We do nothing ; // The default behavior is : $this->invoice->addPayment($this); } public function validateSource() { // We "complete" the request by acknowledging that specific user $response = $this->_sendRequest('/redirect_flows/'.$this->getUniqId().'/actions/complete', array ( 'data' => array ( 'session_token' => Zend_Session::getId(), ) )); if ($response->getStatus() !== 200) return false; $response = json_decode($response->getBody(),true); if (!(isset($response['redirect_flows']) && isset($response['redirect_flows']['links']) && isset($response['redirect_flows']['links']['mandate']))) return false; $invoice = $this->loadInvoice($this->findInvoiceId()); $mandateId = $response['redirect_flows']['links']['mandate']; $this->_updateInvoice('mandate', $mandateId); if (!empty($invoice->rebill_times) && intval($invoice->rebill_times) > 0) { // First payment is made outside the subscription, right away (one off payment): $paymentParams = array( 'payments' => array ( 'currency' => $invoice->currency, 'amount' => intval(floatval($invoice->first_total) * 100), 'description' => $invoice->getLineDescription(), 'metadata' => array ( 'user' => $invoice->getEmail(), 'invoice_id' => $invoice->public_id ), 'links' => array('mandate' => $mandateId) ) ); // One time payment of first_total $response = $this->_sendRequest('/payments', $paymentParams); if ($response->getStatus() !== 201) return false; $response = json_decode($response->getBody(),true); $invoice->addPayment(new Am_Paysystem_Transaction_Gocardlesspro_Payment($this->getPlugin(), $response['payments'], $this->response, $this->invokeArgs)); // Start subscription at interval + n $first_period = new Am_Period($invoice->first_period); $date_period = new DateTime($first_period->addTo(date('Y-m-d')), new DateTimeZone('UTC')); // Subscription of second_total $subscriptionParams = array ( 'start_at' => $date_period->format('Y-m-d'), 'links' => array ('mandate' => $mandateId), 'metadata' => array ( 'user' => $invoice->getEmail(), 'invoice_id' => $invoice->public_id ) ); $period = empty($invoice->second_period) ? $invoice->first_period : $invoice->second_period; if($period === Am_Period::MAX_SQL_DATE) { $subscriptionParams['interval_unit'] = 'yearly'; } else { $am_period = new Am_Period($period); switch ($am_period->getUnit()) { case 'm': $interval_unit = 'monthly'; break; case 'y': $interval_unit = 'yearly'; break; } $subscriptionParams['interval_unit'] = $interval_unit; } if (!empty($invoice->second_total)) { $subscriptionParams['amount'] = intval(floatval($invoice->second_total) * 100); } else { $subscriptionParams['amount'] = intval(floatval($invoice->first_total) * 100); } $subscriptionParams['name'] = $invoice->getLineDescription(); $subscriptionParams['currency'] = $invoice->currency; $subscriptionParams['count'] = intval($invoice->rebill_times); if ($subscriptionParams['count'] > 1000) { $subscriptionParams['count'] = 1000; } if ($subscriptionParams['interval_unit'] === 'monthly') { $subscriptionParams['day_of_month'] = 5; } $response = $this->_sendRequest('/subscriptions', array ('subscriptions' => $subscriptionParams)); if ($response->getStatus() !== 201) return false; $response = json_decode($response->getBody(),true); $this->_updateInvoice('subscription', $response['subscriptions']['id']); } else { // One time payment only $paymentParams = array( 'payments' => array ( 'currency' => $invoice->currency, 'amount' => intval(floatval($invoice->first_total) * 100), 'description' => $invoice->getLineDescription(), 'metadata' => array ( 'user' => $invoice->getEmail(), 'invoice_id' => $invoice->public_id ), 'links' => array('mandate' => $mandateId) ) ); // One time payment of first_total $response = $this->_sendRequest('/payments', $paymentParams); if ($response->getStatus() !== 201) return false; $response = json_decode($response->getBody(), true); $invoice->addPayment(new Am_Paysystem_Transaction_Gocardlesspro_Payment($this->getPlugin(), $response['payments'], $this->response, $this->invokeArgs)); } $invoice->updateStatus(); return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Gocardlesspro_Ipn extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { } public function findInvoiceId() { } public function validateSource() { return $this->request->getHeader('Webhook-Signature') === hash_hmac('sha256', $this->request->getRawBody(), $this->getPlugin()->getConfig('webhook_token')); } public function processValidated() { $payload = json_decode($this->request->getRawBody(), true); foreach($payload['events'] as $event) { $request = new Am_Mvc_Request($event, $this->request->getActionName()); $transaction = new Am_Paysystem_Transaction_Gocardlesspro_IpnEvent($this->getPlugin(), $request, $this->response, $this->invokeArgs); $transaction->process(); } } public function validateStatus() { return true; } public function validateTerms() { return true; } public function autoCreate() { return; } } class Am_Paysystem_Transaction_Gocardlesspro_IpnEvent extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('id'); // == EVXXXXXX } private function _sendRequest($url, $params, $method = 'POST') { $request = $this->plugin->createHttpRequest(); $request->setHeader(array( 'Accept' => 'application/json', 'Content-Type' => 'application/json', 'User-Agent' => 'gocardlesspro-php/v0.0.1', 'Authorization' => 'Bearer '.$this->plugin->getConfig('access_token'), 'GoCardless-version' => '2015-04-29' // Current API version (version header might be updated soon, see https://gocardless.com/blog/) )); $request->setUrl(($this->plugin->getConfig('testing') ? Am_Paysystem_Gocardlesspro::SANDBOX_URL : Am_Paysystem_Gocardlesspro::LIVE_URL) . $url); if (!is_null($params)) { $request->setBody(json_encode($params)); } $request->setMethod($method); $this->plugin->logOther('Request to '.$url, var_export($params, true)); $response = $request->send(); $this->plugin->logOther('Response to '.$url, var_export($response, true)); return $response; } public function findInvoiceId() { $links = $this->request->get('links'); switch($this->request->get('resource_type')) { case 'mandates': $i = Am_Di::getInstance()->invoiceTable->findFirstByData('mandate_id', $links['mandate']); if($i) { $this->invoice = $i; return $i->public_id; } break; case 'subscriptions': $i = Am_Di::getInstance()->invoiceTable->findFirstByData('subscription_id', $links['subscription']); if($i) { $this->invoice = $i; return $i->public_id; } break; case 'payments': $transaction = Am_Di::getInstance()->invoicePaymentTable->findFirstBy(array('transaction_id' => $links['payment'])); if ($transaction) { $this->invoice = $transaction->getInvoice(); return $transaction->getInvoice()->public_id; } break; } return null; } public function processValidated() { $links = $this->request->get('links'); switch ($this->request->get('resource_type')) { case 'mandates': if (in_array($this->request->get('action'), array('cancelled', 'failed', 'expired'))) { $this->invoice->setCancelled(true); } break; case 'subscriptions': if ($this->request->get('action') === 'payment_created') { $this->invoice->addPayment(new Am_Paysystem_Transaction_Gocardlesspro_Payment($this->getPlugin(), array('id' => $links['payment']), $this->response, $this->invokeArgs)); } else if ($this->request->get('action') === 'cancelled') { $this->invoice->setCancelled(true); } break; case 'payments': if (in_array($this->request->get('action'), array('cancelled', 'failed', 'late_failure_settled'))) { $this->invoice->setCancelled(true); } else if ($this->request->get('action') === 'charged_back') { $this->invoice->addChargeBack(new Am_Paysystem_Transaction_Gocardlesspro_Payment($this->getPlugin(), array('id' => $links['payment']), $this->response, $this->invokeArgs), $links['payment']); } break; } if (!is_null($this->invoice)) { $this->invoice->updateStatus(); } } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function autoCreate() { try { parent::autoCreate(); } catch (Am_Exception_Paysystem $e) { Am_Di::getInstance()->errorLogTable->logException($e); } } }PK\7^"default/plugins/payment/payeer.phpnu[getConfig('id') && $this->getConfig('key'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('id') ->setLabel("Shop Identifier\n" . 'the identifier of shop registered in Payeer ' . 'system on which will be made payment'); $form->addPassword('key') ->setLabel("Secret Key\n" . 'a confidential key from shop settings'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $params = array( 'm_shop' => $this->getConfig('id'), 'm_orderid' => $invoice->public_id, 'm_amount' => $invoice->first_total, 'm_curr' => $invoice->currency, 'm_desc' => base64_encode($invoice->getLineDescription()) ); $params['m_sign'] = $this->calculateSignature($params); $params['m_process'] = 'send'; foreach ($params as $k => $v) { $a->addParam($k, $v); } $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $actionName = $request->getActionName(); if ($actionName == 'fail') { $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->getParam('m_orderid')); if (!$invoice) throw new Am_Exception_InputError; return $response->redirectLocation($this->getRootUrl() . "/cancel?id=" . $invoice->getSecureId('CANCEL')); } else { return parent::directAction($request, $response, $invokeArgs); } } public function calculateSignature($params) { return strtoupper(hash('sha256', implode(':', $params) . ':' . $this->getConfig('key'))); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payeer_Ipn($this, $request, $response, $invokeArgs); } function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payeer_Thanks($plugin, $request, $response, $invokeArgs); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $fail = $this->getPluginUrl('fail'); $success = $this->getPluginUrl('thanks'); return << My Shop -> crete new one or edit existing 2. Set the following fields Success URL: $success Fail URL: $fail Status URL: $ipn 3. And click 'Change' button aMember configuration: ----------------------- 1. fill in above form and save configuration 2. do test signup CUT; } } class Am_Paysystem_Transaction_Payeer extends Am_Paysystem_Transaction_Incoming { const STATUS_SUCCESS = 'success'; const STATUS_FAIL = 'fail'; public function findInvoiceId() { return $this->request->get('m_orderid'); } public function getUniqId() { return $this->request->get('m_operation_id'); } public function validateSource() { $params = $this->request->getRequestOnlyParams(); $sig = $params['m_sign']; unset($params['m_sign']); if ($sig != $this->getPlugin()->calculateSignature($params)) { return false; } return true; } public function validateStatus() { return $this->request->getParam('m_status') == self::STATUS_SUCCESS; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Payeer_Ipn extends Am_Paysystem_Transaction_Payeer { public function processValidated() { parent::processValidated(); echo $this->request->get('m_orderid') . '|success'; } } class Am_Paysystem_Transaction_Payeer_Thanks extends Am_Paysystem_Transaction_Payeer { }PK\%%default/plugins/payment/senangpay.phpnu[addText('merchant_id') ->setLabel("Merchant ID") ->addRule('required'); $form->addText('secret_key') ->setLabel("Secret Key") ->addRule('required'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $action = new Am_Paysystem_Action_Form(self::URL . $this->getConfig('merchant_id')); $action->detail = str_replace(" ", "_", $invoice->getLineDescription()); $action->amount = $invoice->first_total; $action->order_id = $invoice->public_id; $action->hash = md5($this->getConfig('secret_key') . $action->detail . $action->amount . $action->order_id); $action->name = $invoice->getName(); $action->email = $invoice->getEmail(); $action->phone = $invoice->getPhone(); $result->setAction($action); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_SenangpayIPN($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Senangpay($this, $request, $response, $invokeArgs); } public function thanksAction($request, $response, array $invokeArgs) { try{ parent::thanksAction($request, $response, $invokeArgs); } catch (Am_Exception_Paysystem_TransactionInvalid $ex) { $this->invoice = $transaction->getInvoice(); $this->getDi()->response->redirectLocation($this->getCancelUrl()); } catch (Am_Exception_Paysystem_TransactionUnknown $ex) { $this->getDi()->response->redirectLocation($this->getDi()->url('cancel',null,false)); } } public function getReadme() { $return = $this->getPluginUrl('thanks'); $callback = $this->getPluginUrl('ipn'); return << Profile 3. Refer to Shopping Cart Integration Link section 4. Get your Merchant ID and Secret Key information 5. Set this URL $return as 'Return URL' 6. Set this URL $callback as 'Callback URL' CUT; } } class Am_Paysystem_Transaction_Senangpay extends Am_Paysystem_Transaction_Incoming_Thanks { public function validateSource() { $hash = md5($this->getPlugin()->getConfig('secret_key') . $this->request->get('status_id') . $this->request->get('order_id') . $this->request->get('transaction_id') . $this->request->get('msg')); return $this->request->get('hash') == $hash; } public function findInvoiceId() { return $this->request->get('order_id'); } public function validateStatus() { return $this->request->get('status_id') == 1; } public function getUniqId() { return $this->request->get('transaction_id'); } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_SenangpayIPN extends Am_Paysystem_Transaction_Senangpay { public function process() { parent::process(); echo "OK"; } }PK\q~6default/plugins/payment/nab.phpnu[addText('vendor_name') ->setLabel("Client ID\n" . 'Your Client ID will be supplied when your service is activated. ' . 'It will be in the format “ABC01”, where ABC is your organisation’s ' . 'unique three letter code. It is used for logging into the NAB ' . 'Transact administration, reporting and search tool.'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); parent::_initSetupForm($form); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form($this->getConfig('testing') ? self::TEST_URL : self::LIVE_URL); $a->vendor_name = $this->getConfig('vendor_name'); $a->payment_alert = $this->getDi()->config->get('admin_email'); $a->__set($invoice->getLineDescription(), $invoice->first_total); $a->payment_reference = $invoice->public_id; $a->receipt_address = $invoice->getEmail(); if(floatval($invoice->first_tax) > 0) { $a->gst_rate = $invoice->tax_rate; $a->gst_added = 'true'; } $if = array(); $a->__set($if[] = 'E-Mail', $invoice->getEmail()); $a->__set($if[] = 'Country', $this->getCountry($invoice)); $a->__set($if[] = 'Name', $invoice->getName()); $a->__set($if[] = 'Street/PO Box', $invoice->getStreet()); $a->__set($if[] = 'City', $invoice->getCity()); $a->__set($if[] = 'State', $this->getState($invoice)); $a->__set($if[] = 'Post Code', $invoice->getZip()); $a->__set($if[] = 'Telephone Number', $invoice->getPhone()); $a->information_fields = implode(',', $if); $a->return_link_url = $this->getReturnUrl(); $a->reply_url = $this->getPluginUrl('ipn').'?invoice='.$invoice->public_id; $a->reply_link_url = $this->getPluginUrl('ipn').'?invoice='.$invoice->public_id; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transacton_Nab($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme(){ return <<Test Card Number, Type and Expiry Use the following information when testing your order form: Card Number: 4444333322221111 Card Type: VISA Card CVV: 123 Card Expiry: 08 / 12 (or any date greater then today) Simulating Approved and Declined Transactions For testing purposes only, you can simulate approved and declined transactions by submitting alternative invoice totals. This is the final total that is on the bottom of the secure NAB Transact payment page. If the order total ends in 00, 08, 11 or 16, the transaction will be approved once the credit card details are submitted. All other options will cause a declined transaction. Order totals to simulate approved transactions: $1.00 $1.08 $105.00 $105.08 (or any total ending in 00, 08, 11 or 16) Order totals to simulate declined transactions: $1.51 $1.05 $105.51 $105.05 (or any total not ending in 00, 08, 11 or 16) NOTE: When using the live payments URL for processing live payments, the card issuing bank determines the transaction response independent of the invoice total. EOT; } function getSupportedCurrencies() { return array('AUD'); } protected function getState(Invoice $invoice) { $state = $this->getDi()->stateTable->findFirstBy(array( 'state' => $invoice->getState() )); return $state ? $state->title : $invoice->getState(); } protected function getCountry(Invoice $invoice) { $country = $this->getDi()->countryTable->findFirstBy(array( 'country' => $invoice->getCountry() )); return $country ? $country->title : $invoice->getCountry(); } } class Am_Paysystem_Transacton_Nab extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('invoice'); } public function getUniqId() { return $this->request->get('payment_number'); } public function validateSource() { return true; } public function validateStatus() { return in_array($this->request->get('bank_reference'), array('00','08','11','16')); } public function validateTerms() { return floatval($this->request->get('payment_amount')) == floatval($this->invoice->first_total); } }PK\m00$default/plugins/payment/webmoney.phpnu[addText('purse')->setLabel("Webmoney Purse\nexample: Z123123123123") ->addRule('regex', 'Incorrect value', '/^[ZRED]\d+$/'); $form->addPassword('secret')->setLabel("Webmoney Merchant Secret\nused to validate incoming transactions\nvalidation mode must be set to MD5, not SIGN"); $form->addAdvCheckbox('testing')->setLabel('Webmoney Merchant in Test Mode?'); } public function isConfigured() { return strlen($this->getConfig('purse')); } public function getSupportedCurrencies() { return array('USD', 'RUB', 'EUR', ); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form; $a->setUrl('https://merchant.wmtransfer.com/lmi/payment.asp'); $a->LMI_PAYEE_PURSE = $this->getConfig('purse'); $a->LMI_PAYMENT_AMOUNT = $invoice->first_total; $a->LMI_PAYMENT_NO = $invoice->invoice_id; $a->AMEMBER_ID = $invoice->public_id; $a->LMI_PAYMENT_DESC_BASE64 = base64_encode($invoice->getLineDescription()); //$a->LMI_MODE = $this->getConfig('testing') ? 1 : 0; $a->LMI_SIM_MODE = 2; $a->LMI_RESULT_URL = $this->getPluginUrl('ipn'); $a->LMI_SUCCESS_URL = $this->getPluginUrl('thanks'); $a->LMI_SUCCESS_METHOD = 1; // post to thanks $a->LMI_FAIL_URL = $this->getCancelUrl(); $a->LMI_FAIL_METHOD = 1; // $a->LMI_PAYMER_EMAIL = $invoice->getEmail(); $result->setAction($a); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Webmoney($this, $request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Webmoney($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Webmoney extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getFiltered('LMI_SYS_TRANS_NO'); } public function findInvoiceId() { return $this->request->getFiltered('AMEMBER_ID'); } public function validateSource() { $arr = array( $this->request->get('LMI_PAYEE_PURSE'), $this->request->get('LMI_PAYMENT_AMOUNT'), $this->request->get('LMI_PAYMENT_NO'), $this->request->get('LMI_MODE'), $this->request->get('LMI_SYS_INVS_NO'), $this->request->get('LMI_SYS_TRANS_NO'), $this->request->get('LMI_SYS_TRANS_DATE'), $this->plugin->getConfig('secret'), $this->request->get('LMI_PAYER_PURSE'), $this->request->get('LMI_PAYER_WM'), $this->request->get('AMEMBER_ID') ); $hash = strtoupper(md5(implode('', $arr))); if ($hash != ($h = $this->request->get('LMI_HASH'))) throw new Am_Exception_Paysystem_TransactionSource("Calculated hash [$hash] does not match incoming [$h], check secret word in aMember and WM settings"); return true; } public function validateStatus() { return true; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('LMI_PAYMENT_AMOUNT')); return true; } public function findTime() { return new DateTime($this->request->get('LMI_SYS_TRANS_DATE')); } }PK\3ww!default/plugins/payment/jvzoo.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText('jvzoo_prod_item', "JVZoo product number", "1-5 Characters")); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addTextarea("secret", array('class'=>'one-per-line')) ->setLabel("JVZoo Secret Key\n" . "you can add several keys from different accounts if necessary"); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Jvzoo($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { parent::createThanksTransaction($request, $response, $invokeArgs); } public function canAutoCreate() { return true; } public function getReadme() { $url = Am_Html::escape($this->getPluginUrl('ipn')); $thanks = Am_Html::escape($this->getPluginUrl('thanks')); return <<JVZoo integration JVZIPN URL for your products in JVZoo should be set to: $url Optionally you can set Thank You page url for your product to: $thanks CUT; } } class Am_Paysystem_Transaction_JvzooThanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->request->get('cbreceipt'); } public function findInvoiceId() { return $this->request->get('cbreceipt'); } public function validateSource() { $keys = $this->getPlugin()->getConfig('secret'); $rcpt = $this->request->getParam('cbreceipt'); $time = $this->request->getParam('time'); $item = $this->request->getParam('item'); $cbpop = $this->request->getParam('cbpop'); foreach(explode("\n", $keys) as $key) { $key = trim($key); $xxpop=sha1("$key|$rcpt|$time|$item"); $xxpop=strtoupper(substr($xxpop,0,8)); if($cbpop==$xxpop) return true; } return false; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Jvzoo extends Am_Paysystem_Transaction_Incoming { // payment const SALE = "SALE"; const BILL = "BILL"; // refund const RFND = "RFND"; const CGBK = "CGBK"; const INSF = "INSF"; // cancel const CANCEL_REBILL = "CANCEL-REBILL"; // uncancel const UNCANCEL_REBILL = "UNCANCEL-REBILL"; protected $_autoCreateMap = array( 'name' => 'ccustname', 'email' => 'ccustemail', 'state' => 'ccuststate', 'country' => 'ccustcc', 'user_external_id' => 'ccustemail', ); public function generateInvoiceExternalId() { list($l,) = explode('-',$this->getUniqId()); return $l; } public function autoCreateGetProducts() { $item_name = $this->request->get('cproditem'); if (empty($item_name)) return; foreach ($this->getPlugin()->getDi()->billingPlanTable->findBy() as $bp) { $list = array_map('trim', explode(',', $bp->data()->get('jvzoo_prod_item'))); if (in_array($item_name, $list)) return $bp->getProduct(); } } public function getReceiptId() { switch ($this->request->get('ctransaction')) { //refund case Am_Paysystem_Transaction_Jvzoo::RFND: case Am_Paysystem_Transaction_Jvzoo::CGBK: case Am_Paysystem_Transaction_Jvzoo::INSF: return $this->request->get('ctransreceipt').'-'.$this->request->get('ctransaction'); break; default : return $this->request->get('ctransreceipt'); } } public function getAmount() { return moneyRound($this->request->get('ctransamount')); } public function getUniqId() { return @$this->request->get('ctransreceipt'); } public function validateSource() { $ipnFields = $this->request->getPost(); unset($ipnFields['cverify']); ksort($ipnFields); $pop = implode('|', $ipnFields) . '|' . $this->getPlugin()->getConfig('secret'); if (function_exists('mb_convert_encoding')) $pop = mb_convert_encoding($pop, "UTF-8"); $calcedVerify = strtoupper(substr(sha1($pop), 0, 8)); return $this->request->get('cverify') == $calcedVerify; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->request->get('ctransaction')) { //payment case Am_Paysystem_Transaction_Jvzoo::SALE: case Am_Paysystem_Transaction_Jvzoo::BILL: $this->invoice->addPayment($this); break; //refund case Am_Paysystem_Transaction_Jvzoo::RFND: case Am_Paysystem_Transaction_Jvzoo::CGBK: case Am_Paysystem_Transaction_Jvzoo::INSF: $this->invoice->addRefund($this, Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); //$this->invoice->stopAccess($this); break; //cancel case Am_Paysystem_Transaction_Jvzoo::CANCEL_REBILL: $this->invoice->setCancelled(true); break; //un cancel case Am_Paysystem_Transaction_Jvzoo::UNCANCEL_REBILL: $this->invoice->setCancelled(false); break; } } public function findInvoiceId() { return $this->request->get('ctransreceipt'); } }PK\xaa1default/plugins/payment/blockchain/blockchain.phpnu[addText('address', array('class' => 'el-wide')) ->setLabel('Your Receiving Bitcoin Address'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $req = new Am_HttpRequest(self::LIVE_URL, Am_HttpRequest::METHOD_POST); $req->addPostParameter(array( 'method' => 'create', 'address' => $this->getConfig('address'), 'callback' => $this->getPluginUrl('ipn') . "?secret=" . $invoice->getSecureId('THANKS') . '&invoice_id=' . $invoice->public_id, )); $log = $this->logRequest($req); $log->setInvoice($invoice); $res = $req->send(); $log->add($res); $arr = (array) json_decode($res->getBody(), true); if (empty($arr['input_address'])) { throw new Am_Exception_InternalError($res->getBody()); } $req = new Am_HttpRequest(self::CURRENCY_URL . "?currency={$invoice->currency}&value={$invoice->first_total}", Am_HttpRequest::METHOD_GET); $log->add($req); $res = $req->send(); $log->add($res); $amount = $res->getBody(); if (doubleval($amount) <= 0) { throw new Am_Exception_InternalError($amount); } $invoice->data()->set(self::BLOCKHAIN_AMOUNT, doubleval($amount))->update(); $a = new Am_Paysystem_Action_HtmlTemplate_Blockchain($this->getDir(), 'confirm.phtml'); $a->amount = doubleval($amount); $a->input_address = $arr['input_address']; $a->invoice = $invoice; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try{ parent::directAction($request, $response, $invokeArgs); } catch(Exception $e) { $this->getDi()->errorLogTable->logException($e); } //in other case blockchain will send IPN's once per minute echo 'ok'; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Blockchain_Transaction($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Blockchain_Transaction extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getFiltered('transaction_hash'); } public function validateSource() { return $this->request->getFiltered('secret') == $this->invoice->getSecureId('THANKS'); } public function validateStatus() { return !$this->request->get('test'); } public function validateTerms() { return doubleval($this->invoice->data()->get(Am_Paysystem_Blockchain::BLOCKHAIN_AMOUNT)) == doubleval($this->request->get('value') / 100000000); } public function findInvoiceId() { return $this->request->getFiltered('invoice_id'); } } class Am_Paysystem_Action_HtmlTemplate_Blockchain extends Am_Paysystem_Action_HtmlTemplate { protected $_template; protected $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } }PK\5((8default/plugins/payment/blockchain/scripts/confirm.phtmlnu[setLayout('layout.phtml'); ?>
      _script('_receipt.phtml'); ?>

      Please send amount ?> BTC to input_address; ?>

      PK\|(('default/plugins/payment/paymentwall.phpnu[getConfig('key') && $this->getConfig('secret') && $this->getConfig('widget'); } public function isNotAcceptableForInvoice(Invoice $invoice) { if (!in_array($invoice->rebill_times, array(0, IProduct::RECURRING_REBILLS))) { return 'Can not handle invoice with defined rebill times'; } return parent::isNotAcceptableForInvoice($invoice); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('key') ->setLabel("Application Key\n" . 'can be found in General Settings of the Application ' . 'inside of your Merchant Account'); $form->addPassword("secret") ->setLabel("Secret Key\n" . 'can be found in General Settings of the Application ' . 'inside of your Merchant Account'); $form->addText("widget") ->setLabel('Widget Code'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL_SUBSCRIPTION); $params = array( 'key' => $this->getConfig('key'), 'uid' => $invoice->getUser()->pk(), 'widget' => $this->getConfig('widget'), 'email' => $invoice->getUser()->email, 'amount' => $invoice->first_total, 'currencyCode' => $invoice->currency, 'ag_name' => $invoice->getLineDescription(), 'ag_external_id' => $invoice->public_id, 'ag_type' => $invoice->first_period == Am_Period::MAX_SQL_DATE ? self::TYPE_FIXED : self::TYPE_SUBSCRIPTION, 'ag_recurring' => ($invoice->second_total > 0) ? 1 : 0, 'ag_trial' => ($invoice->second_total > 0 && $invoice->first_total != $invoice->second_total) ? 1 : 0, 'sign_version' => 2, 'success_url' => $this->getReturnUrl(), 'pingback_url' => $this->getPluginUrl('ipn') ); if ($params['ag_type'] == self::TYPE_SUBSCRIPTION) { $period = new Am_Period($invoice->first_period); $params = array_merge($params, array( 'ag_period_length' => $period->getCount(), 'ag_period_type' => $this->trUnit($period->getUnit()), )); } if ($params['ag_trial']) { $period = new Am_Period($invoice->second_period); $params = array_merge($params, array( 'ag_post_trial_period_length' => $period->getCount(), 'ag_post_trial_period_type' => $this->trUnit($period->getUnit()), 'ag_post_trial_external_id' => $invoice->public_id, 'post_trial_amount' => $invoice->second_total, 'post_trial_currencyCode' => $invoice->currency, 'ag_post_trial_name' => $invoice->getLineDescription(), 'hide_post_trial_good' => 1, )); } $params['sign'] = $this->calculateSignature($params, $this->getConfig('secret')); foreach ($params as $k => $v) { $a->addParam($k, $v); } $result->setAction($a); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try{ parent::directAction($request, $response, $invokeArgs); } catch(Am_Exception $e) { $this->getDi()->errorLogTable->logException($e); print "OK"; exit(); } } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $this->invoice = $payment->getInvoice(); $params = array( 'key' => $this->getConfig('key'), 'ref' => $payment->receipt_id, 'uid' => $payment->user_id, 'type' => 1 //REFUND ); $params['sign'] = $this->calculateSignature($params, $this->getConfig('secret')); $requst = new Am_HttpRequest(self::URL_TICKET, Am_HttpRequest::METHOD_POST); $requst->addPostParameter($params); $log = $this->logRequest($requst); $responce = $requst->send(); $log->add($responce); if ($responce->getStatus() != 200) { $result->setFailed('Incorrect HTTP response status: ' . $responce->getStatus()); return; } $res = json_decode($responce->getBody(), true); if ($res['result'] == 1) { $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id); $result->setSuccess($trans); return; } $result->setFailed($res['errors']); } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $this->invoice = $invoice; list($payment) = $invoice->getPaymentRecords(); $params = array( 'key' => $this->getConfig('key'), 'ref' => $payment->receipt_id, 'uid' => $payment->user_id, 'type' => 2 //CANCELL ); $params['sign'] = $this->calculateSignature($params, $this->getConfig('secret')); $requst = new Am_HttpRequest(self::URL_TICKET, Am_HttpRequest::METHOD_POST); $requst->addPostParameter($params); $log = $this->logRequest($requst); $responce = $requst->send(); $log->add($responce); if ($responce->getStatus() != 200) { $result->setFailed('Incorrect HTTP response status: ' . $responce->getStatus()); return; } $res = json_decode($responce->getBody(), true); if ($res['result'] == 1) { $invoice->setCancelled(); $result->setSuccess(); return; } $result->setFailed($res['errors']); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paymentwall($this, $request, $response, $invokeArgs); } public function calculateSignature($params, $secret) { $out = ''; ksort($params); foreach ($params as $k => $v) { $out .= sprintf('%s=%s', $k, $v); } return md5($out . $secret); } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Settings button. 2.1 set Your API to Digital Goods 2.2 set the Pingback type to URL 2.3 set the Pingback URL to: $url 2.4 set Pingback signature version to 2 3. click Save Changes 4. press the Widgets button, Add New Widget aMember configuration: ----------------------- 1. go to aMember CP -> Configuration -> Setup/Configuration -> Plugins and enable paymentwall plugin 2. go to aMember CP -> Configuration -> Setup/Configuration -> Paymentwall and complete plugin configuration. Fill in Application Key, Secret Key and Widget Code 3. do test signup. Submit the application for approval: ------------------------------------ Once all the settings have been properly configured, go back to your Paymentwall Merchant Account, and submit the application for approval by clicking the Submit for Review button at My Applications tab CUT; } protected function trUnit($u) { static $tr = array( 'd' => 'day', 'm' => 'month', 'y' => 'year' ); return $tr[$u]; } } class Am_Paysystem_Transaction_Paymentwall extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('goodsid'); } public function getUniqId() { return $this->request->get('ref'); } public function validateSource() { $this->_checkIp(<<request->getRequestOnlyParams(); $sig = $params['sig']; unset($params['sig']); if ($sig != $this->plugin->calculateSignature($params, $this->plugin->getConfig('secret'))) { return false; } return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { parent::processValidated(); switch ($this->request->getParam($type)) { case '0' : $this->invoice->addPayment($this); break; case '2' : $this->invoice->addRefund($this, $this->request->get('ref')); break; } } }PK\؀Z\%\%%default/plugins/payment/gate2shop.phpnu[addText("merchant_id") ->setLabel("Merchant ID\n" . 'Merchant unique identification number as provided by Gate2Shop'); $form->addText("merchant_site_id") ->setLabel("Merchant Site ID\n" . 'Merchant web site unique identification number as provided by Gate2Shop'); $form->addText("secret_key", array('class' => 'el-wide')) ->setLabel('Secret Key'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('gate2shop_id', "Gate2Shop Subscription name", "")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('gate2shop_template_id', "Gate2Shop Product Descriptor ID (rebillingTemplateId)", "")); } public function getSupportedCurrencies() { return array('AUD', 'CAD', 'CHF', 'DKK', 'EUR', 'GBP', 'NOK', 'SEK', 'USD'); } function calculateOutgoingHash(Am_Paysystem_Action_Redirect $a, Invoice $invoice) { $str = implode('', array( $this->getConfig('secret_key'), $this->getConfig('merchant_id'), $a->currency, $a->total_amount )); for ($i = 1; $i <= count($invoice->getItems()); $i++) { $str .= $a->{"item_name_" . $i}; $str .= $a->{"item_amount_" . $i}; $str .= $a->{"item_quantity_" . $i}; } $str .= $a->time_stamp; return md5($str); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); $a->merchant_id = $this->getConfig('merchant_id'); $a->merchant_site_id = $this->getConfig('merchant_site_id'); $a->currency = $invoice->currency; $a->version = '3.0.0'; $a->merchant_unique_id = $invoice->public_id; $a->first_name = $invoice->getFirstName(); $a->last_name = $invoice->getLastName(); $a->email = $invoice->getEmail(); $a->address1 = $invoice->getStreet(); $a->address2 = $invoice->getStreet1(); $a->city = $invoice->getCity(); $a->country = $invoice->getCountry(); $a->state = $invoice->getState(); $a->zip = $invoice->getZip(); $a->phone1 = $invoice->getPhone(); $a->time_stamp = date("Y-m-d.h:i:s"); if($invoice->rebill_times && ($gate2shop_id = $invoice->getItem(0)->getBillingPlanData('gate2shop_id')) && ($gate2shop_template_id = $invoice->getItem(0)->getBillingPlanData('gate2shop_template_id'))) { $a->productId = $invoice->getItem(0)->item_id; $a->rebillingProductId = $gate2shop_id; $a->rebillingTemplateId = $gate2shop_template_id; if($invoice->rebill_times) $a->isRebilling = 'true'; $a->checksum = md5($this->getConfig('secret_key') . $this->getConfig('merchant_id') . $gate2shop_id. $gate2shop_template_id . $a->time_stamp); } //not recurring else { $a->total_amount = $invoice->first_total; $a->discount = $invoice->first_discount; $a->total_tax = $invoice->first_tax; $a->numberofitems = count($invoice->getItems()); for ($i = 0; $i < $a->numberofitems; $i++) { $item = $invoice->getItem($i); $a->addParam('item_name_' . ($i + 1), $item->item_title); $a->addParam('item_number_' . ($i + 1), $i + 1); $a->addParam('item_amount_' . ($i + 1), $item->first_price); $a->addParam('item_discount_' . ($i + 1), $item->first_discount); $a->addParam('item_quantity_' . ($i + 1), $item->qty); } $a->checksum = $this->calculateOutgoingHash($a, $invoice); } $a->filterEmpty(); $result->setAction($a); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $actionName = $request->getActionName(); if ($actionName == 'cancel') { $invoice = $this->getDi()->invoiceTable->findFirstBy(array('public_id' => $request->getFiltered('merchant_unique_id'))); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); $response->redirectLocation($this->getRootUrl() . "/cancel?id=" . $invoice->getSecureId('CANCEL')); } else parent::directAction($request, $response, $invokeArgs); } function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gate2shop($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gate2shop_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $url = $this->getPluginUrl(); return << 'first_name', 'name_l' => 'last_name', 'state' => 'state', 'email' => 'email', 'city' => 'city', 'country' => 'country', 'street' => 'address1', 'street2' => 'address2', 'user_external_id' => 'email', 'invoice_external_id' => 'membershipId', ); public function autoCreateGetProducts() { $cbId = $this->request->getFiltered('rebillingTemplateId'); if (empty($cbId)) return; $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('gate2shop_template_id', $cbId); if (!$pl) return; $pr = $pl->getProduct(); if (!$pr) return; return array($pr); } public function getUniqId() { return $this->request->get('PPP_TransactionID',$this->request->get('TransactionID')); } public function findInvoiceId() { return $this->request->getFiltered('merchant_unique_id'); } public function validateSource() { return (($this->request->get('responsechecksum') == md5(implode('', array( $this->getPlugin()->getConfig('secret_key'), $this->request->get('TransactionID'), $this->request->get('ErrCode'), $this->request->get('ExErrCode'), $this->request->get('Status') )))) || ($this->request->get('responsechecksum') == md5(implode('', array( $this->getPlugin()->getConfig('secret_key'), $this->request->get('ppp_status'), $this->request->get('PPP_TransactionID') )))) || ($this->request->get('responsechecksum') == md5(implode('', array( $this->getPlugin()->getConfig('secret_key'), $this->request->get('membershipId'), $this->request->get('status') ))))); } public function validateStatus() { return ($this->request->get('ppp_status') == 'OK'); } public function validateTerms() { return ((floatval($this->request->get('totalAmount')) == floatval($this->invoice->isFirstPayment() ? $this->invoice->first_total : $this->invoice->second_total)) || (floatval($this->request->get('rebilling_initial_amount')) == floatval($this->invoice->first_total))); } function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_Gate2shop_Thanks extends Am_Paysystem_Transaction_Gate2shop { public function validateTerms() { return ((floatval($this->request->get('totalAmount')) == floatval($this->invoice->first_total)) || (floatval($this->request->get('rebilling_initial_amount')) == floatval($this->invoice->first_total))); } function processValidated() { $this->invoice->addPayment($this); } }PK\5default/plugins/payment/mollie-ideal/public/style.cssnu[/* Copyright (c) 2008 Bart Kruger */ body, p, td { font-family:Verdana,Arial,Helvetica; font-size:9pt; color:#46596E; background-color:#FFFFFF } p, td { font-family:Verdana,Arial,Helvetica; font-size:9pt; color:#46596E } div#info { font-family:Verdana,Arial,Helvetica; font-size:8pt; color:#46596E } a { color: grey; text-decoration:none } a:hover { color: grey; text-decoration:none } table#outer { border-spacing:50px; background: white url('./betaalscherm-bg-1.jpg') repeat-x right bottom; } table#outer td { padding:20px } table#inner { border-spacing:5px } table#inner td { background-color:#EEEEEE; padding:5px } input.text { width: 230px } textarea { width: 230px } sup.red { color: #dd1414 } PK\,`55default/plugins/payment/mollie-ideal/public/ideal.gifnu[GIF89a93Үhhhu'''牸VGGGܜ="zxxxSSS񔔔wJqqq l===il B777222*钾gf!,93pH,Ȥrl:ШtJZجv x%aj|a8WY/ !2+oVz%5B=5B=PIܽ 1 =xNH-7?D'DM*@"aF8\# ~4H<mrŽ:@ ;@OJC"Ə~taE|0P L%`Y18Pި i)XG5IO?-A^ ~(ctPH4I<}"bA "&pA$a`IGN x!^D,aƏP jYlhᴐ 2J`@>j c:f'WDwD=$c)} q ~&%M,P8a:S_<Aa^!:‰ƊR6b<`HFA8d}P-ic88@%LceX>h DQJqd- m`1@ŸVA j@CJ?H`B"+T'3I¥^@ &$prj6lX@2îꫯ&UEHs$ ``VkR+ŷ+kD;PK\zXw: : ;default/plugins/payment/mollie-ideal/public/mollie_logo.gifnu[GIF89aAprڞ̓gkqۋɁjnsein}otysx}x}v{̩ȼĵܚlquzҬ̗zɾνͽijȷ˺ʺ챣wvfyi}lpux}E4O>\MaSfWl]pb{mt0#4&, /#."2%<-7*-";.8+4(8,7+6*1=1;/@4C5D6B5B5G9F9KOATERFYLVKaVbXg]lcsiz|x9.<1EDҡD9jhuHLysh>p <\'HR'JFɖ$R+7p,}#Bx- le !7|G G3}%,YTiSZ$W~9\ذ#_~ @w,^xt2yq&jI+lg~`nƇmt$B:'CM88(#j2ʍI&bA!8"D^őGFRdfDiBA (7db#9I(db&+xr LNJ)'t0L`TT1"@ Y72ff&+*TjJvChGKZy0VZ8fK r[ 0@ f;PK\kPT)T)Adefault/plugins/payment/mollie-ideal/public/betaalscherm-bg-1.jpgnu[JFIFddDuckyFAdobed    - !1AQa"2qB#3CScD !1QAaq"2BRr3S ?( ]@@( ] @]t t  ]@@ tt P.t P.t ]@]@ (@t ]@]t ]@ t P.t ] @.t ] .t .@.t P.t ]@P.t t ]t P( (@.@.@] (@@.t (@@P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @PK\.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \@.t ]@(@.t ] ]t ]@.t ]@.t P(@.t ]@.t ]@.t .t ]@@.t ]@.t .t ] ]@(@.t ] P.t ]@.t ]t ]@.t ]@.t ]@.t ]@(@.t ]@.@.t ]nt ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t P.t ]@(@.t ]@]@.t ]nt ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ].t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@d( @[n\n\.p \.p \.p%.p \.p \.p \.p \..p \.p%.p \. p.p \.p \-K\. pn\[.p \.p \.p \.p \.p \.p \@P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( A@P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( A]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]AP( @P( @PP( @P( @P( X @P( @P( @P( @P( @P( @P( P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( .p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.4 @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( 4 @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( 7@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.t ]@.27.p \.p \.@.p \.p P.p \\.p \\.p P.p \\(.p \(p \( P.p .p P.@.p \.p \.p \((.p P.p \.p \\3p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \.p \1p%[\.p np \%. p \.p \.p \ pK\.p \K.p npnp-.p-.p \..\ p%. p \.p \%[np-.p \ p .\.\.p \.p-.p \KK\ p.p \ @]@(@@.t (@.t ]@]@.@ P.t  ]@@.t ]@]@.t ]@( .t ]@.t .@.@]@.@.t ]@@( ]@@.t ]t ]t t ] ]@]1Ͽ}xsfr/_͜>~?>qne߇h'YqϷsss@gǻ7|g/N3nrdzs9p嗏.;ssno:_~z|˯rs͛7-͙|Zyw1]vcOg}.nWq_rOutxk9:-\='/xG-w{xq绞Wwsw5<\,{91.㞏?}w=Oɢ?O]w޳Oa<.+;ϛ3xw6OLPp痜sw9g+f)1B& @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( 9\yr|9uv|9[Ǘ/)s}E7˻8yG.>-υ3?>Ai?p~Y9_[}o<~^o#yx߇yg/>|w~}y{=tp9rߛ~^_7 =Wk6=Og1mtG.._Su3vt:sǯos?v~G<~=ܻ;z9r㹝|㜷ݠ\fzN~o;s)gW11qO79}?Z%@P( P( p( \p p p P( p P( \@\@ .p \@.@P(\p ( .@\@P(\p \.@( P.@@ @(P( p @P(P(@P(߷p=gog '>z˗gY>\yyݝۻyzff&g{#>_.\^>~Ngٿpk?ww8˧3g_ͻ>\zoN<{:{q8˟W:_ߴa!GG˿߾rw9ffr]qjav{'Eg.^?G.=3>9v=N&2v?=kEچ4y{;~g/8{g|{8o,[?>?y~y>O\:>&}8}3>7. |7>Os9n}~hc^]# +Gφnq>{w_?Gz[zw~_[ǻÏ&I#9sӿs>^Gy}ۼx]oMծ( <7WО] xn?Zk}tM[!3Lq~/.=o.]3\OO>ُ㟋nToZ4b4[s{w~<?ӛw._yoW?ߝnsسd iQg_Y_7zo;<7<~ޮ}3ṙz:(ffgk}K~b^'Oz|/\Www/Gm߆aTQkz/}_9^dz}ۼpލs G_Fcoox罞_W,÷.];T3O>󫿧vuyӇ=ќx:2|ǎdaRuUvw7;:kչsw7>7b*?[cA|YϞ.{3 ++; @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( @P( |oyq_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_MollieIdeal extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_REVISION = '5.0.6'; protected $defaultTitle = 'Mollie iDEAL'; protected $defaultDescription = 'online betalen via uw eigen bank'; protected $_canResendPostback = true; public function getSupportedCurrencies() { return array('USD', 'GBP', 'EUR', 'CAD', 'JPY'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addInteger('business', array('size'=>20)) ->setLabel("Mollie iDEAL Partner Id\n" . 'your partner id in mollie.nl'); $form->addText('profile_key', array('size'=>20)) ->setLabel("Mollie iDEAL Profile Key\n" . 'Optional. ID of corresponding profile on Mollie.'); $form->addAdvCheckbox('testing') ->setLabel("Test Mode\n" . 'activate Test Mode in your account at mollie.nl as well'); } public function isConfigured() { return $this->getConfig('business') > ''; } public function getBanks() { require_once dirname(__FILE__).'/Mollie/Ideal.php'; $banksArray = array(); $testmode = ($this->getConfig('testing') == "1" ? true : false); $ideal = new Mollie_Ideal($this->getConfig('business')); $banksArray = $ideal->getBanks($testmode); return $banksArray; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $partnerId = $this->getConfig('business'); $checksum = md5($invoice->getLineDescription() . $invoice->first_total. $invoice->public_id . $invoice->user_id . $partnerId); $public = $this->getRootUrl() . "/application/default/plugins/payment/mollie-ideal/public"; $banksSelect = "\r\n"; $a = new Am_Paysystem_Action_HtmlTemplate_MollieIdeal($this->getDir(), 'payment-mollie-ideal-redirect.phtml'); $a->action = $this->getPluginUrl('pay'); $a->profile_key = $this->getConfig('profile_key'); $a->public = $public; $a->description = $invoice->getLineDescription(); $a->price = $invoice->first_total; $a->payment_id = $invoice->public_id; $a->member_id = $invoice->user_id; $a->checksum = $checksum; $a->banksSelect = $banksSelect; $result->setAction($a); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return <<c = new Am_Mvc_Controller($request, $response, $invokeArgs); $PathInfo = $request->getPathInfo(); $this->_case = substr($PathInfo, strrpos($PathInfo, '/') + 1); $this->_params = $this->request->isPost() ? $this->request->getPost() : $this->request->getQuery(); $receipt_id = ''; $invoice = $this->getInvoice(); //Am_Di::getInstance()->invoiceTable->findFirstByPublicId($payment_id); if ($invoice) $receipt_id = Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($invoice->invoice_id); if ($receipt_id) $this->_params['transaction_id'] = $receipt_id; } public function findInvoiceId() { return (isset($this->_params['payment_id'])) ? $this->_params['payment_id'] : ''; } public function getUniqId() { return (isset($this->_params['transaction_id'])) ? $this->_params['transaction_id'] : ''; } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function getAmount() { return (isset($this->_params['price'])) ? $this->_params['price'] : ''; } public function processValidated() { require_once dirname(__FILE__).'/Mollie/Ideal.php'; $partnerId = $this->getPlugin()->getConfig('business'); $ideal = new Mollie_Ideal($partnerId); $testmode = ($this->getPlugin()->getConfig('testing') == "1" ? true : false); $public = $this->getPlugin()->getRootUrl() . "/application/default/plugins/payment/mollie-ideal/public"; $invoice = $this->getInvoice(); $mollieTransactionId = $this->getUniqId(); if ($this->_case == 'pay') { $mollieBankId = $this->_params['mollie_ideal_bank']; $description = $this->_params['description']; $price = $this->_params['price']; $payment_id = $this->_params['payment_id']; $member_id = $this->_params['member_id']; $checksum = md5($description . $price . $payment_id . $member_id . $partnerId); if ($this->_params['checksum'] != $checksum) throw new Am_Exception_Paysystem_TransactionInvalid('Mollie Ideal: Checksum error'); if ($ideal->checkBank($mollieBankId, $testmode)) { // Create the payment, true on succes, false otherwise // $mollieBankId = the id of the bank the user chose // $description = the description that the user will see on his check // $amount = the total amount of money that the user has to pay // $siteReportUrl = the url which will be called from the Mollie server when the payment is complete. // Mollie will add ?transaction_id= to this url! // $siteReturnUrl = the url where Mollie returns the user to when the payment is complete. // Mollie will add ?transaction_id= to this url! $amount = sprintf('%d', $price * 100); $siteReportUrl = $this->getPlugin()->getPluginUrl('ipn') . "?payment_id=" . $payment_id; $siteReturnUrl = $this->getPlugin()->getPluginUrl('status') . "?payment_id=" . $payment_id; // for testing only $siteReportUrl = str_replace('localhost', 'yourdomain.com', $siteReportUrl); $siteReturnUrl = str_replace('localhost', 'yourdomain.com', $siteReturnUrl); if ($ideal->createPayment($mollieBankId, $description, $amount, $siteReportUrl, $siteReturnUrl)) { // Get the url of the chosen bank to redirect the user to, // to complete the payment //$a = new Am_Paysystem_Action_Redirect($ideal->getBankUrl()); //$result->setAction($a); header('Location: ' . $ideal->getBankUrl()); exit; } else { // show message that the payment could not be created // the function $ideal->getStatus() returns the status // message that Mollie returns throw new Am_Exception_Paysystem_TransactionInvalid('Mollie Ideal error: Status = [' . $ideal->getStatus() . ']'); } } else { throw new Am_Exception_Paysystem_TransactionInvalid('Mollie Ideal error: CheckBank Failed'); } } elseif ($this->_case == 'status') { if ($invoice->status > 0){ $status = "Wij hebben uw betaling ontvangen."; } else { $status = "Wij hebben uw betaling nog niet ontvangen.
      Uw iDEAL betaling is wellicht nog onderweg."; $status.= "
      Wacht enkele minuten en ververs dan deze pagina.
      Bij problemen kunt u contact opnemen met " . Am_Di::getInstance()->config->get('admin_email') . "."; $status.= "
      Noteer uw betaalcode."; } $a = new Am_Paysystem_Action_HtmlTemplate_MollieIdeal($this->getPlugin()->getDir(), 'payment-mollie-ideal-thanks.phtml'); $a->action = $this->getPlugin()->getRootUrl() ."/member"; $a->public = $public; $a->status = $status; $a->payment_id = $invoice->public_id; $a->mollieTransactionId = $mollieTransactionId; $a->process($this->c); //$response->setAction($a); } elseif ($this->_case == 'ipn') { // Chech if the given transaction Id is valid if ($ideal->checkPayment($mollieTransactionId) == true) { // process payment $this->invoice->addPayment($this); } else { // Payment failed throw new Am_Exception_Paysystem_TransactionInvalid('Mollie Ideal error: Status = [' . $ideal->getStatus() . ']'); } } else { throw new Am_Exception_Paysystem_TransactionInvalid('Mollie Ideal error: Unknowk case [' . $this->_case . ']'); } } }PK\C.9Ndefault/plugins/payment/mollie-ideal/scripts/payment-mollie-ideal-thanks.phtmlnu[setLayout('layout.phtml'); ?>

      iDEAL betaling

      Betaalstatus

      Betaalstatusstatus; ?>
      Betaalcodepayment_id; ?> / mollieTransactionId; ?>


      PK\4KPdefault/plugins/payment/mollie-ideal/scripts/payment-mollie-ideal-redirect.phtmlnu[setLayout('layout.phtml'); ?>

      iDEAL betaling

      Selecteer uw bank
      Selecteer uw bank en klik op 'Verder' om door te
      gaan naar het iDEAL betaalscherm van uw bank.

      Omschrijvingdescription; ?>
      Bedragprice, 2, ',', ''); ?>
      Uw bankbanksSelect; ?>


      PK\B`>>5default/plugins/payment/mollie-ideal/Mollie/Ideal.phpnu[ * @link http://www.concepto.nl Concepto IT Solution * @version 1.0.1 * * Modified by Bart Kruger: * - modified testmode support in static method getBanks() */ class Mollie_Ideal { const MINIMUM_TRANSACTION_AMOUNT = 60; private $partnerId = 0; private $transactionId = 0; private $bankId = 0; private $amount = 0; private $description = ''; private $reportUrl = ''; private $returnUrl = ''; private $country = 31; // Default: The Netherlands (031) private $currency = 'EUR'; // Default: Euro private $payed = false; private $bankUrl = ''; private $statusMessage = ''; private $testmode = false; private $banks = array(); // Info about the bankaccount that made the payment // (only available after checking the payment) private $consumer = array(); /** * Constructor * * @param integer $partnerId */ function __construct($partnerId) { $this->setPartnerID($partnerId); } /** * Prepare a Payment * * @param integer $bankId * @param string $description * @param integer $amount * @param string $reportUrl * @param string $returnUrl * @return boolean True on succes, false otherwise */ public function createPayment($bankId, $description, $amount, $reportUrl, $returnUrl) { if (!$this->setBankid($bankId) || !$this->setDescription($description) || !$this->setAmount($amount) || !$this->setReportUrl($reportUrl) || !$this->setReturnUrl($returnUrl)) { return false; } $result = $this->sendToHost('www.mollie.nl', '/xml/ideal/', 'a=fetch' . '&partnerid=' . urlencode($this->getPartnerId()) . '&bank_id=' . urlencode($this->getBankId()) . '&amount=' . urlencode($this->getAmount()) . '&reporturl=' . urlencode($this->getReportUrl()) . '&description=' . urlencode($this->getDescription()) . '&returnurl=' . urlencode($this->getReturnUrl())); if (empty($result)) { return false; } list($headers, $xml) = preg_split("/(\r?\n){2}/", $result, 2); try { $data = new SimpleXMLElement($xml); if ($data == false) { return false; } $data = $data->order; $transactionId = $data->transaction_id; $amount = $data->amount; $currency = $data->currency; $bankUrl = html_entity_decode($data->URL); $status = $data->message; /* get an exceptions like -2 This account does not exist or is suspended. */ if (!$status && preg_match('/(.*)<\/message>/i', $result, $matches)) $status = $matches[1]; if (!$this->setStatus($status) || !$this->setTransactionId($transactionId) || !$this->setAmount($amount) || !$this->setCurrency($currency) || !$this->setBankUrl($bankUrl)) { return false; } } catch (Exception $e) { return false; } return true; } /** * Check if the payment was succesfull * * @param integer $transactionId * @return boolean True on succes, false otherwise */ public function checkPayment($transactionId) { // set transaction id if (!$this->setTransactionId($transactionId)) { return false; } // check a payment with mollie $result = $this->sendToHost('www.mollie.nl', '/xml/ideal/', 'a=check' . '&partnerid=' . urlencode($this->getPartnerId()). '&transaction_id=' . urlencode($this->getTransactionId()). ($this->testmode ? '&testmode=true' : '')); if (empty($result)) { return false; } list($headers, $xml) = preg_split("/(\r?\n){2}/", $result, 2); try { $data = new SimpleXMLElement($xml); if ($data == false) { return false; } $data = $data->order; $payed = ($data->payed == 'true'); $consumer = (array)$data->consumer; $amount = $data->amount; $status = $data->message; if (!$status && preg_match('/(.*)<\/message>/i', $result, $matches)) $status = $matches[1]; if (!$this->setStatus($status) || !$this->setPayed($payed) || !$this->setConsumer($consumer) || !$this->setAmount($amount)) { return false; } } catch (Exception $e) { return false; } return true; } /** * Get the URL of the selected bank * * @return null|string Bank URL when exists, else null */ public function getBankUrl() { if (is_null($this->bankUrl)) { return null; } return $this->bankUrl; } /** * Set Bank Url * * @param string $bankUrl * @return boolean */ protected function setBankUrl($bankUrl) { if (!preg_match('|(\w+)://([^/:]+)(:\d+)?/(.*)|', $bankUrl)) { return false; } $this->bankUrl = $bankUrl; return true; } /** * Fetch the currently supported banks * * @static * @param boolean $testmode * @return boolean|array Array of banks, else boolean false */ public function getBanks($testmode) { // Gets/refreshes banks from Mollie $result = self::sendToHost('www.mollie.nl', '/xml/ideal/', 'a=banklist'.($testmode ? '&testmode=true' : '')); if (empty($result)) { return false; } list($headers, $xml) = preg_split("/(\r?\n){2}/", $result, 2); try { $data = new SimpleXMLElement($xml); if ($data == false) { return false; } // build banks-array $banksArray = array(); foreach ($data->bank as $bank) { $banksArray["$bank->bank_id"] = "$bank->bank_name"; } } catch (Exception $e) { return false; } return $banksArray; } /** * Check if the given bankId is valid * * @static * @param integer $bankId * @param boolean $testmode * @return bool True on valid, False otherwise */ public function checkBank($bankId, $testmode) { $banksArray = self::getBanks($testmode); if (!is_array($banksArray)) { return false; } if (array_key_exists($bankId, $banksArray)) { return true; } return false; } /** * Send data to given host * * @param string $host Full webhost Url (like 'www.mollie.nl') * @param string $path Path of script * @param string $data Data to send * @return string */ protected static function sendToHost($host, $path, $data) { // posts data to server $fp = @fsockopen($host, 80); $buf = ''; if ($fp) { @fputs($fp, "POST $path HTTP/1.0\n"); @fputs($fp, "Host: $host\n"); @fputs($fp, "Content-type: application/x-www-form-urlencoded\n"); @fputs($fp, "Content-length: " . strlen($data) . "\n"); @fputs($fp, "Connection: close\n\n"); @fputs($fp, $data); while (!feof($fp)) { $buf .= fgets($fp, 128); } fclose($fp); } return $buf; } /** * Set the Partner Id * * @param integer $partnerId * @return boolean */ protected function setPartnerId($partnerId) { if (!is_numeric($partnerId)) { return false; } $this->partnerId = $partnerId; return true; } /** * Get the Partner Id * * @return integer */ protected function getPartnerId() { return $this->partnerId; } /** * Set transaction amount (price) in cents * * @param integer $amount Minimum amount is the cost of a transaction! * @return boolean */ protected function setAmount($amount) { if (!is_numeric($amount) && $amount < self::MINIMUM_TRANSACTION_AMOUNT ) { return false; } $this->amount = $amount; return true; } /** * Get the Amount (price) in cents * * @return integer */ public function getAmount() { return $this->amount; } /** * Set Currency * * @param string $currency * @return boolean */ protected function setCurrency($currency) { if (empty($currency)) { return false; } $this->currency = $currency; return true; } /** * Get the Currency * * @return string */ protected function getCurrency() { return $this->currency; } /** * Set the Country code * * @param integer $country * @return boolean */ protected function setCountry($country) { if (!is_numeric($country)) { return false; } $this->country = $country; return true; } /** * Get the Country code * * @return integer */ protected function getCountry() { return $this->country; } /** * Set the Url where Mollie reports to if the status of one of our * payments changes * * Mollie adds the 'transaction_id' to this url * * @param string $reportUrl * @return boolean */ protected function setReportUrl($reportUrl) { if (!preg_match('|(\w+)://([^/:]+)(:\d+)?/(.*)|', $reportUrl)) { return false; } $this->reportUrl = $reportUrl; return true; } /** * Get the Report Url * * @return string */ protected function getReportUrl() { return $this->reportUrl; } /** * Set the Url where Mollie returns to when the payment is done * * Mollie add the 'transaction_id' to this url * * @param string $returnUrl * @return boolean */ protected function setReturnUrl($returnUrl) { if (!preg_match('|(\w+)://([^/:]+)(:\d+)?/(.*)|', $returnUrl)) { return false; } $this->returnUrl = $returnUrl; return true; } /** * Get the Return Url * * @return string */ protected function getReturnUrl() { return $this->returnUrl; } /** * Set the Description of the transaction * * If longer than 30 characters, the description will * be trimmed at the 30th character * * @param unknown_type $description * @return unknown */ protected function setDescription($description) { $description = trim($description); if (empty($description)) { return false; } $this->description = substr($description, 0, 29); return true; } /** * Get the transaction Description * * @return string */ protected function getDescription() { return $this->description; } /** * Set Payed status * * @param boolean $payed * @return boolean */ protected function setPayed($payed) { if ($payed === false) { $this->payed = false; return false; } $this->payed = true; return true; } /** * Get the payed status * * @return boolean */ protected function getPayed() { return $this->payed; } /** * Set Status message * * @param string $status * @return boolean */ protected function setStatus($status) { if (empty($status)) { return false; } $this->statusMessage = $status; return true; } /** * Get the Status message * * @return string */ public function getStatus() { return $this->statusMessage; } /** * Set the Bank Id * * The supported Bank Id's can be fetched with the * getBanks($testmode) function * * @see getBanks * @param integer $bankId * @return boolean */ protected function setBankId($bankId) { if (!is_numeric($bankId)) { return false; } $this->bankId = $bankId; return true; } /** * Get the Bank Id * * @return integer */ protected function getBankId() { return $this->bankId; } /** * Set the Transaction Id * * @param integer $transactionId * @return boolean */ protected function setTransactionId($transactionId) { if (empty($transactionId)) { return false; } $this->transactionId = $transactionId; return true; } /** * Get the Transaction Id * * @return integer */ public function getTransactionId() { return $this->transactionId; } /** * Set the Consumer information * * This is information about the bankaccount which payed * the transaction * * The array should have the following elements: *
        *
      • consumerName
      • *
      • consumerAccount
      • *
      • consumerCity
      • *
      * * @param array $consumer * @return boolean */ protected function setConsumer($consumer) { if (!is_array($consumer)) { return false; } $this->consumer = $consumer; return true; } /** * Set testmode * * This is information about the bankaccount which payed * the transaction, and is only available after executing * @see checkPayment() with a 'true' as the result! * * The array should have the following elements: *
        *
      • consumerName
      • *
      • consumerAccount
      • *
      • consumerCity
      • *
      * * @return boolean */ public function setTestMode($testmode) { $this->testmode = $testmode; return true; } /** * Get the Consumer information * * This is information about the bankaccount which payed * the transaction, and is only available after executing * @see checkPayment() with a 'true' as the result! * * The array should have the following elements: *
        *
      • consumerName
      • *
      • consumerAccount
      • *
      • consumerCity
      • *
      * * @return array */ public function getConsumer() { return $this->consumer; } } PK\!1/default/plugins/payment/digital-goods-store.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'dgs_code', "Digital Goods Store Product Code" )); } public function getRecurringType() { return self::REPORTS_REBILL; } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { //nop } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // nop. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_DigitalGoodsStore($this, $request, $response, $invokeArgs); } public function canAutoCreate() { return true; } public function getSiteKey() { return $this->getDi()->security->siteHash($this->getId()); } public function getReadme() { $url = Am_Html::escape($this->getPluginUrl($this->getSiteKey())); return <<$url CUT; } } class Am_Paysystem_Transaction_DigitalGoodsStore extends Am_Paysystem_Transaction_Incoming { protected $notification = null; function init() { $this->notification = json_decode($this->request->getRawBody(), true); } public function generateInvoiceExternalId() { return $this->notification['order']['order_id']; } public function autoCreateGetProducts() { $res = array(); foreach ($this->notification['order']['products'] as $p) { if ($bp = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('dgs_code', $p['code'])) { $res[] = $bp->getProduct(); } } return $res; } function fetchUserInfo() { $order = $this->notification['order']; return array( 'email' => $order['buyers_email'], 'name_f' => $order['buyers_first_name'], 'name_l' => $order['buyers_last_name'], 'country' => $order['buyers_country_code'], 'remote_addr' => $order['buyers_ip_address'] ); } public function getAmount() { return moneyRound($this->notification['order']['amount_total']); } public function getUniqId() { return $this->notification['order']['order_id']; } public function validateSource() { return $this->notification && $this->request->getActionName() == $this->getPlugin()->getSiteKey(); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->notification['type']) { //payment case 'order.placed': case 'subscription.payment': if ((float)$this->invoice->first_total) { $this->invoice->addPayment($this); } else { $this->invoice->addAccessPeriod($this); } break; } } public function findInvoiceId() { return null; } }PK\Hw  $default/plugins/payment/paytrail.phpnu[getConfig('merchant') && $this->getConfig('hash'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant') ->setLabel("Merchant ID\n" . 'merchant identification number given by Paytrail'); $form->addPassword('hash') ->setLabel("Merchant Authentication Hash"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $params = array( 'MERCHANT_ID' => $this->getConfig('merchant'), 'AMOUNT' => $invoice->first_total, 'ORDER_NUMBER' => $invoice->public_id, 'REFERENCE_NUMBER' => '', 'ORDER_DESCRIPTION' => $invoice->getLineDescription(), 'CURRENCY' => $invoice->currency, 'RETURN_ADDRESS' => $this->getReturnUrl(), 'CANCEL_ADDRESS' => $this->getCancelUrl(), 'PENDING_ADDRESS' => '', 'NOTIFY_ADDRESS' => $this->getPluginUrl('ipn'), 'TYPE' => 'S1', 'CULTURE' => '', 'PRESELECTED_METHOD' => '', 'MODE' => '1', 'VISIBLE_METHODS' => '', 'GROUP' => '', ); $params['AUTHCODE'] = strtoupper(md5($this->getConfig('hash') . '|' . implode('|', $params))); foreach ($params as $k => $v) { $a->addParam($k, $v); } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paytrail($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Paytrail extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('ORDER_NUMBER'); } public function getUniqId() { return $this->request->get('PAID'); } public function validateSource() { $params = $this->request->getRequestOnlyParams(); $sig = $params['RETURN_AUTHCODE']; unset($params['RETURN_AUTHCODE']); if ($sig != strtoupper(md5(implode('|', $params) . '|' . $this->plugin->getConfig('hash')))) { return false; } return true; } public function validateStatus() { return $this->request->getParam('PAID'); } public function validateTerms() { return true; } }PK\*{nn"default/plugins/payment/plimus.phpnu[addSelect("testing") ->setLabel("test Mode Enabled"); $s->addOption("Live account", self::MODE_LIVE); $s->addOption("Sandbox account", self::MODE_SANDBOX); // $s->addOption("Account in test mode", self::MODE_TEST); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('plimus_contract_id', "Plimus Contract ID", "You must enter the contract id of Plimus product.
      Plimus contract must have the same settings as amember product.")); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form((($this->getConfig('testing')==self::MODE_SANDBOX) ? self::TESTING_URL : self::URL)); $a->contractId = $invoice->getItem(0)->getBillingPlanData("plimus_contract_id"); $a->custom1 = $invoice->public_id; $a->member_id = $invoice->user_id; $a->currency = strtoupper($invoice->currency); $a->firstName = $invoice->getFirstName(); $a->lastName = $invoice->getLastName(); $a->email = $invoice->getEmail(); $a->overridePrice = sprintf("%.2f",$invoice->first_total); $a->overrideRecurringPrice = sprintf("%.2f",$invoice->second_total); if($this->getConfig('testing') == self::MODE_TEST){ $a->testMode=Y; } $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch($request->get("transactionType")){ case Am_Paysystem_Transaction_Plimus::CHARGE : case Am_Paysystem_Transaction_Plimus::RECURRING : case Am_Paysystem_Transaction_Plimus::AUTH_ONLY : return new Am_Paysystem_Transaction_Plimus_Charge($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Plimus::CANCELLATION : return new Am_Paysystem_Transaction_Plimus_Cancellation($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Plimus::REFUND : return new Am_Paysystem_Transaction_Plimus_Refund($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Plimus::CANCELLATION_REFUND : return new Am_Paysystem_Transaction_Plimus_Cancellation_Refund($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Plimus::CONTRACT_CHANGE : return new Am_Paysystem_Transaction_Plimus_Contract_Change($this, $request, $response,$invokeArgs); default : return null; } } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme(){ return <<Plimus payment plugin configuration This plugin is deprecated. You need to continue use this plugin only in case you have active recurring subscriptions that began with Plimus. Other way use BlueSnap plugin instead. CUT; } public function canAutoCreate() { return true; } } class Am_Paysystem_Transaction_Plimus extends Am_Paysystem_Transaction_Incoming{ protected $_autoCreateMap = array( 'name_f' => 'firstName', 'name_l' => 'lastName', 'email' => 'email', 'street' => 'address1', 'zip' => 'zipCode', 'state' => 'state', 'country' => 'country', 'city' => 'city', 'user_external_id' => 'accountId', 'invoice_external_id' => 'accountId' , ); const REFUND = 'REFUND'; const CHARGE = 'CHARGE'; const RECURRING = 'RECURRING'; const AUTH_ONLY = 'AUTH_ONLY'; const CANCELLATION_REFUND = 'CANCELLATION_REFUND'; const CANCELLATION = 'CANCELLATION'; const CONTRACT_CHANGE = 'CONTRACT_CHANGE'; protected $ip = array( array('62.216.234.196', '62.216.234.222'), array('72.20.107.242', '72.20.107.250'), array('209.128.93.97', '209.128.93.110'), array('209.128.93.225', '209.128.93.255') ); public function autoCreateGetProducts() { $item_number = $this->request->get('contr_id', $this->request->get('contractId')); if (empty($item_number)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('plimus_contract_id', $item_number); if($billing_plan) return array($billing_plan->getProduct()); } public function findInvoiceId(){ return $this->request->get('custom1'); } public function getUniqId() { return $this->request->get("referenceNumber"); } public function validateSource() { $this->_checkIp($this->ip); if(($this->plugin->getConfig('testing') != Am_Paysystem_Plimus::MODE_TEST) && ($this->request->get('testMode') == 'Y')){ throw new Am_Exception_Paysystem_TransactionInvalid("Received test IPN message but test mode is not enabled!"); } return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Plimus_Charge extends Am_Paysystem_Transaction_Plimus{ public function validateTerms() { $amount = ($this->invoice->currency == 'USD') ? $this->request->get('invoiceAmountUSD') : $this->request->get('invoiceChargeAmount'); $message = $this->request->get('transactionType'); return ($amount == (($message == self::CHARGE) || ($message == self::AUTH_ONLY) ? $this->invoice->first_total : $this->invoice->second_total)); } public function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_Plimus_Cancellation extends Am_Paysystem_Transaction_Plimus{ public function processValidated() { $this->invoice->setCancelled(true); } } class Am_Paysystem_Transaction_Plimus_Refund extends Am_Paysystem_Transaction_Plimus{ public function processValidated() { $this->invoice->addRefund($this, $this->getReceiptId(), $this->getAmount()); } } class Am_Paysystem_Transaction_Plimus_Cancellation_Refund extends Am_Paysystem_Transaction_Plimus{ public function processValidated() { $this->invoice->setCancelled(true); $this->invoice->addRefund($this, $this->getReceiptId(), $this->getAmount()); } } class Am_Paysystem_Transaction_Plimus_Contract_Change extends Am_Paysystem_Transaction_Plimus{ public function processValidated() { throw new Am_Exception_Paysystem_NotImplemented("Not implemented"); } }PK\;0D"D"#default/plugins/payment/eway-sp.phpnu[ 'https://payment.ewaygateway.com/Request/', 'AU' => 'https://au.ewaygateway.com/Request/', 'NZ' => 'https://nz.ewaygateway.com/Request/' ); public function supportsCancelPage() { return true; } protected function getUrl() { return $this->requestUrls[$this->getConfig('Country')]; } public function getSupportedCurrencies() { return array('AUD'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('CustomerID', array('size' => 20)) ->setLabel("Customer ID\n" . 'Your eWAY Customer ID') ->addRule('required'); $form->addText('UserName', array('size' => 20)) ->setLabel("User name\n" . 'Your eWAY Customer User Name') ->addRule('required'); $form->addText('PageTitle ', array('class' => 'el-wide')) ->setLabel("Page Title\n" . 'This is value will be displayed as the title of the browser. ' . 'Default: eWAY Hosted Payment Page'); $form->addText('PageDescription', array('class' => 'el-wide')) ->setLabel("Page Description\n" . 'This value will be displayed above the Transaction Details. ' . 'Default: Blank'); $form->addText('PageFooter', array('class' => 'el-wide')) ->setLabel("Page Footer\n" . 'This value will be displayed below the Transaction Details.'); $form->addText('CompanyLogo', array('class' => 'el-wide')) ->setLabel("URL company logo\n" . 'The url of the image can be hosted on the ' . 'merchants website and pass the secure ' . 'https:// path of the image to be displayed ' . 'at the top of the website. This is the top ' . 'image block on the webpage and is ' . 'restricted to 960px X 65px. A default secure ' . 'image is used if none is supplied.'); $form->addText('Pagebanner', array('class' => 'el-wide')) ->setLabel("URL page banner\n" . 'The url of the image can be hosted on the ' . 'merchants website and pass the secure ' . 'https:// path of the image to be displayed ' . 'at the top of the website. This is the second ' . 'image block on the webpage and is ' . 'restricted to 960px X 65px. A default secure ' . 'image is used if none is supplied.'); $form->addAdvCheckbox('ModifiableCustomerDetails') ->setLabel("Modifiable customer cetails\n" . 'This field specifies if the customer can ' . 'change the contact details on the payment ' . 'page This is useful if the merchant is not ' . 'collecting details on their site.'); $form->addSelect("Language", array(), array('options' => array( 'EN' => 'English', 'ES' => 'Spanish', 'FR' => 'French', 'DE' => 'German', 'NL' => 'Dutch' )))->setLabel('Language'); $form->addText('CompanyName', array('class' => 'el-wide')) ->setLabel("Company name\n" . 'This will be displayed as the company the ' . 'customer is purchasing from, including this ' . 'is highly recommended.'); $form->addSelect("Country", array(), array('options' => array( 'UK' => 'United Kingdom', 'AU' => 'Australia', 'NZ' => 'New Zeland' )))->setLabel('Country'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $vars = $this->getConfig(); $vars['Amount'] = $invoice->first_total; $vars['Currency'] = $invoice->currency; $vars['ReturnUrl'] = $this->getPluginUrl('thanks'); $vars['CancelUrl'] = $this->getCancelUrl(); $vars['MerchantInvoice'] = $invoice->public_id; $vars['MerchantReference'] = $invoice->public_id; $vars['CustomerFirstName'] = $invoice->getFirstName(); $vars['CustomerLastName'] = $invoice->getLastName(); $vars['CustomerAddress'] = $invoice->getStreet(); $vars['CustomerCity'] = $invoice->getCity(); $vars['CustomerState'] = $invoice->getState(); $vars['InvoiceDescription'] = $invoice->getLineDescription(); $vars['CustomerCountry'] = $invoice->getCountry(); $vars['CustomerPhone'] = $invoice->getPhone(); $vars['CustomerEmail'] = $invoice->getEmail(); $r = new Am_HttpRequest($this->getUrl() . '?' . http_build_query($vars, '', '&')); $response = $r->send()->getBody(); if (!$response) { $this->getDi()->errorLogTable->log('Plugin eWAY: Got empty response from API server'); $result->setErrorMessages(array(___("An error occurred while handling your payment."))); return; } $xml = simplexml_load_string($response); if (!empty($xml->Error)) { $this->getDi()->errorLogTable->log('Plugin eWAY: Got error from API: ' . (string) $xml->Error); $result->setErrorMessages(array(___("An error occurred while handling your payment."))); return; } $action = new Am_Paysystem_Action_Redirect($xml->URI); $result->setAction($action); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return << 'https://payment.ewaygateway.com/Result/', 'AU' => 'https://au.ewaygateway.com/Result/', 'NZ' => 'https://nz.ewaygateway.com/Result/' ); private $xml_result; protected function getUrl() { return $this->resultUrls[$this->plugin->getConfig('Country')]; } public function process() { $vars = $this->request->getPost(); $vars['CustomerID'] = $this->plugin->getConfig('CustomerID'); $vars['UserName'] = $this->plugin->getConfig('UserName'); $r = new Am_HttpRequest($this->getUrl() . '?' . http_build_query($vars, '', '&')); $response = $r->send()->getBody(); if (!$response) { throw new Am_Exception_Paysystem('Got empty response from API server'); } $xml = simplexml_load_string($response); if (!$xml) { throw new Am_Exception_Paysystem('Got error from API: response is not xml'); } $this->xml_result = $xml; parent::process(); } public function validateSource() { return true; } public function findInvoiceId() { return (string) $this->xml_result->MerchantInvoice; } public function validateStatus() { switch ((string) $this->xml_result->ResponseCode) { case '00': case '08': case 10: case 11: case 16: return true; } } public function getUniqId() { return (string) $this->xml_result->TrxnNumber; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, (string)$this->xml_result->ReturnAmount); return true; } } PK\%default/plugins/payment/dragonpay.phpnu[addText('merchant_id') ->setLabel('Your Dragonpay Merchand ID') ->addRule('required'); $form->addPassword('merchant_password') ->setLabel('Your Dragonpay Password') ->addRule('required'); $form->addAdvCheckbox('test_mode') ->setLabel('Test Mode Enabled'); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getSupportedCurrencies() { return array('PHP', 'USD'); } public function isConfigured() { return (bool)($this->getConfig('merchant_id') && $this->getConfig('merchant_password')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $vars = array( 'merchantid' => $this->getConfig('merchant_id'), 'txnid' => $invoice->public_id, 'amount' => $invoice->first_total, 'ccy' => $invoice->currency, 'description' => strlen($desc = $invoice->getLineDescription()) > 128 ? substr($desc, 0, 125) . "..." : $desc, 'email' => $invoice->getUser()->email, ); if($invoice->rebill_times) { if ($this->invoice->first_total > 0 && $this->invoice->first_total != $this->invoice->second_total) throw new Am_Exception_InternalError('If product has no free trial first price must be the same second price'); if ($this->invoice->first_total > 0 && $this->invoice->first_period != $this->invoice->second_period) throw new Am_Exception_InternalError('If product has no free trial first period must be the same second period'); $p = new Am_Period($invoice->first_period); switch ($p->getUnit()) { case Am_Period::DAY: $vars['period'] = 'daily'; $vars['frequency'] = $invoice->rebill_times; break; case Am_Period::MONTH: $vars['period'] = 'monthly'; $vars['frequency'] = $invoice->rebill_times; break; case Am_Period::YEAR: $vars['period'] = 'monthly'; $vars['frequency'] = 12 * $invoice->rebill_times; break; default: throw new Am_Exception_Paysystem_NotConfigured("Unable to convert period [$invoice->first_period] to Dragonpay-compatible. Must be number of days, months or years"); } $url = $this->getConfig('test_mode') ? self::URL_RECUR_PAY_TEST : self::URL_RECUR_PAY_LIVE; } else { $url = $this->getConfig('test_mode') ? self::URL_PAY_TEST : self::URL_PAY_LIVE; } $vars['digest'] = $this->getDigest(join(':', $vars)); $this->logRequest($vars); $a = new Am_Paysystem_Action_Redirect($url . "?" . http_build_query($vars, '', '&')); $result->setAction($a); } public function getDigest($str) { $str .= ":" . $this->getConfig('merchant_password'); return strtolower(sha1($str)); } public function thanksAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $log = $this->logRequest($request); try { $transaction = $this->createThanksTransaction($request, $response, $invokeArgs); } catch (Am_Exception_Paysystem_NotImplemented $e) { $this->logError("[thanks] page handling is not implemented for this plugin. Define [createThanksTransaction] method in plugin"); throw $e; } $transaction->setInvoiceLog($log); try { $transaction->process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { // ignore this error, as it happens in "thanks" transaction // we may have received IPN about the payment earlier } catch (Am_Exception_Paysystem_TransactionInvalid $e) { if($request->getFiltered('status') == 'P') { $this->invoice = $this->getDi()->invoiceTable->findFirstByPublickId($transaction->findInvoiceId()); $log->setInvoice($this->invoice)->update(); $response->setRedirect($this->getReturnUrl()); return; } } catch (Exception $e) { throw $e; $this->getDi()->errorLogTable->logException($e); throw Am_Exception_InputError(___("Error happened during transaction handling. Please contact website administrator")); } $log->setInvoice($transaction->getInvoice())->update(); $this->invoice = $transaction->getInvoice(); $response->setRedirect($this->getReturnUrl()); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Dragonpay($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Dragonpay($this, $request, $response, $invokeArgs); } public function getReadme() { return <<Dragonpay plugin installation 1. Configure plugin at 'aMember CP -> Setup/Configuration -> Dragonpay' 2. Configure your Dragonpay account: - postback URL: %root_url%/payment/dragonpay/ipn - return URL: %root_url%/payment/dragonpay/thanks NOTE 1: Refund and canceling of subscription are not possible via plugin. NOTE 2: If product is recurring - first price must be the same second price. NOTE 3: If product is recurring - first period must be the same second period. CUT; } } class Am_Paysystem_Transaction_Dragonpay extends Am_Paysystem_Transaction_Incoming{ public function getUniqId() { return $this->request->get("refno"); } public function findInvoiceId() { return $this->request->get("txnid"); } public function validateSource() { $calcDigest = $this->getPlugin()->getDigest($this->request->get("txnid") . ":" . $this->request->get("refno") . ":" . $this->request->get("status") . ":" . $this->request->get("message")); return (bool)($calcDigest == $this->request->get("digest")); } public function validateStatus() { return (bool) ($this->request->getFiltered('status') == 'S'); } public function validateTerms() { return true; } }PK\]:$default/plugins/payment/nanacast.phpnu[paysystemList->getList() as $k=>$p){ if($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'nanacast_product_id', 'Nanacast Product ID used for Advanced API', '%Your Product/Podcast/RSS Feed/Membership ID%
      (you can find this ID by clicking on "Edit Listing" for your particular Product/Podcast/RSS Feed/Membership. At the top there is a field that says "ID used for Advanced API' )); } public function canAutoCreate() { return true; } public function _initSetupForm(Am_Form_Setup $form) { //does not use for some reason to protect IPN /*$form->addText('api_key') ->setLabel("API Key\n". "your Nanacast API key"); */ } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Nanacast($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return << Setup/Configuration -> Plugins and enable "Nanacast" payment plugin. 2. Go to product setting and set up 'Nanacast Product ID' for each product 3. Set the following url as notification url for all products at your account in Nanacast: %root_url%/payment/nanacast/ipn ------------------------------------------------------------------------------ This plugins works only via background in Amember CUT; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { } } class Am_Paysystem_Transaction_Nanacast extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name_f' => 'u_firstname', 'name_l' => 'u_lastname', 'pass' => 'u_password', 'email' => 'u_email', 'city' => 'u_city', 'state' => 'u_state', 'zip' => 'u_zip', 'country' => 'u_country', 'user_external_id' => 'account_id', ); public function getUniqId() { return $_SERVER['REMOTE_ADDR'] . '-' . $this->getPlugin()->getDi()->time; } public function getReceiptId() { return $_SERVER['REMOTE_ADDR'] . '-' . $this->getPlugin()->getDi()->time; } public function findTime() { return new DateTime($this->request->get('u_start_date')); } public function getAmount() { return moneyRound($this->request->get('u_first_price')); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->request->get('mode')) { //payment case 'add': case 'payment': $this->invoice->addPayment($this); break; //delete user case 'delete': $this->getPlugin()->getDi()->userTable->delete($this->invoice->getUser()->login); break; //modify user case 'modify': $user = $this->invoice->getUser(); $user['login'] = $this->request->get('u_username'); $user['pass'] = $this->request->get('u_password'); $user['email'] = $this->request->get('u_email'); $user['name_f'] = $this->request->get('u_firstname'); $user['name_l'] = $this->request->get('u_lastname'); $user['street'] = $this->request->get('u_address') . ' ' . $this->request->get('u_address_2'); $user['city'] = $this->request->get('u_city'); $user['state'] = $this->request->get('u_state'); $user['zip'] = $this->request->get('u_zip'); $user['country'] = $this->request->get('u_country'); $user->update(); break; } } public function fetchUserInfo() { return array_merge(parent::fetchUserInfo(), array( 'street' => $this->request->get('u_address') . ' ' . $this->request->get('u_address_2') )); } public function generateInvoiceExternalId() { return $this->getUniqId(); } public function findInvoiceId() { return $this->generateInvoiceExternalId(); } public function autoCreateGetProducts() { $list_id = $this->request->getFiltered('u_list_id'); if (empty($list_id)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('nanacast_product_id', $list_id); if($billing_plan) return array($billing_plan->getProduct()); } } PK\ #default/plugins/payment/bankart.phpnu[ '978', 'USD' => '840'); var $key = array (1416130419, 1696626536, 1864396914, 1868981619, 1931506799, 543580534, 1869967904, 1718773093, 1685024032, 1634624544, 2036692000, 1684369522, 1701013857, 1952784481, 1734964321, 1953066862, 543257189, 544040302, 544696431, 544694638, 1948283489, 1768824951, 1769236591, 1970544756, 1752526436, 1701978209, 1852055660, 1768384628, 1852403303); public function _initSetupForm(Am_Form_Setup $form) { $form->addText('terminal_id', array('size' => 20)) ->setLabel('Terminal Alias'); } function odpakiraj($stringData) { while (strlen($stringData) % 4 != 0) $stringData .= ' '; for ($i = 0, $j = 0; $i < strlen($stringData); $i = $i + 4, $j++) { $y = unpack("Nx", substr($stringData, $i, 4)); $data[$j] = $y["x"]; } return $data; } function simpleXOR($byteInput) { $k = 0; for ($m = 0; $m < count($byteInput); $m++) { if ($k >= count($this->key)) $k = 0; $result[$m] = $byteInput[$m] ^ $this->key[$k]; $k++; } return $result; } function zapakiraj($data) { $stringData = ''; for ($i = 0; $i < count($data); $i++) { $bin = pack("N", $data[$i]); $stringData = $stringData.$bin; } return $stringData; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $encoded = file_get_contents(dirname(__FILE__).'/resource.cgn'); $decoded = $this->zapakiraj($this->simpleXOR($this->odpakiraj($encoded))); $temp = tempnam($this->getDi()->data_dir,'bnk'); file_put_contents($temp, $decoded); $zipFile = zip_open($temp); while ($zipEntry = zip_read($zipFile)) { if (zip_entry_name($zipEntry) == $this->getConfig('terminal_id').'.xml') { $zip_entry_exist = true; if (zip_entry_open($zipFile, $zipEntry)) { $readStream = zip_entry_read($zipEntry); $data = unpack("N*", $readStream); for ($i=1; $isimpleXOR($data1); $bin = null; for ($i=0; $igetDi()->errorLogTable->log("BANKART API ERROR : terminal xml file is not found in cgn file"); throw new Am_Exception_InputError(___('Error happened during payment process. ')); } //for some reasone xml is broken in bankart cgn file $strData = preg_replace("/\<\/term[a-z]+$/",'',$strData); $terminal = new SimpleXMLElement($strData); $port = (string)$terminal->port[0]; $context = (string)$terminal->context[0]; if($port == "443" ) $url = "https://"; else $url = "http://"; $url.=(string)$terminal->webaddress[0]; if(strlen($port) > 0) $url.= ":" . $port; if(strlen($context) > 0) { if ($context[0] != "/") $url.="/"; $url.=$context; if (!$context[strlen($context)-1] != "/") $url.="/"; } else { $url.="/"; } $url.="servlet/PaymentInitHTTPServlet"; $vars = array( 'id' => (string)$terminal->id[0], 'password' => (string)$terminal->password[0], 'passwordhash' => (string)$terminal->passwordhash[0], 'action' => 4, 'amt' => $invoice->first_total, 'currency' => $this->currency_codes[$invoice->currency], 'responseURL' => $this->getPluginUrl('ipn'), //strange bankart requirements 'errorURL' => $this->getRootUrl() . "/cancel", 'trackId' => $invoice->public_id, 'udf1' => $invoice->public_id, ); $req = new Am_HttpRequest($url, Am_HttpRequest::METHOD_POST); $req->addPostParameter($vars); $res = $req->send(); $body = $res->getBody(); if(strpos($body, 'ERROR')>0) { $this->getDi()->errorLogTable->log("BANKART API ERROR : $body"); throw new Am_Exception_InputError(___('Error happened during payment process. ')); } list($payment_id,$url) = explode(':', $body, 2); $invoice->data()->set('bankart_payment_id', $payment_id)->update(); $a = new Am_Paysystem_Action_Redirect($url. '?PaymentID=' .$payment_id); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->get('Error') || $request->get('result') != 'APPROVED') { $invoice = $this->getDi()->invoiceTable->findFirstByData('bankart_payment_id', $request->get('paymentid')); echo "REDIRECT=".$this->getRootUrl() . "/cancel?id=" . $invoice->getSecureId("CANCEL"); die; } return new Am_Paysystem_Transaction_Bankart($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array_keys($this->currency_codes); } public function getReadme() { $rootURL = $this->getDi()->config->get('root_url'); return <<Bankart payment plugin configuration 1. Enable "bankart" payment plugin at aMember CP->Setup->Plugins 2. Configure "Bankart" payment plugin at aMember CP -> Setup/Configuration -> Bankart 3. Download resource.cgn from your Bankart merchant account and upload it into /amember/application/default/plugins/payment/bankart CUT; } } class Am_Paysystem_Transaction_Bankart extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('udf1'); } public function getUniqId() { return $this->request->get('paymentid'); } public function validateSource() { return true; } public function validateStatus() { return ($this->request->get('result') == 'APPROVED'); } public function validateTerms() { return true; } public function processValidated() { parent::processValidated(); echo "REDIRECT=".$this->plugin->getRootUrl() . "/thanks?id=" . $this->invoice->getSecureId("THANKS"); } }PK\@s)default/plugins/payment/easypaydirect.phpnu[ 'CAD', 'CHF' => 'CHF', 'CNY' => 'CNY', 'EUR' => 'EUR', 'GBR' => 'GBR', 'NTD' => 'TWD' ); const LIVE_URL = 'https://secure.2000charge.com/sys/NATSPaymentProcess.asp'; const CANCEL_URL = ': https://secure.2000charge.com/ClientsOnly/RCS.asp'; protected $payment_options = array( 'COMBO' => 'Allows consumer to choose', 'ACH' => 'ACH USD/ CAD', 'ASTROPAYCARD'=>'ASTROPAYCARD USD', 'BRAZILPAY' => 'BRAZILPAY BRL', 'CREDITCARD' => 'CREDITCARD USD', 'DIRECTPAY' => 'DIRECTPAY USD/EUR', 'EPS' => 'EPS EUR', 'EURODEBIT' => 'EURODEBIT EUR', 'GIROPAY' => 'GIROPAY EUR', 'IDEAL' => 'IDEAL EUR', 'PAYSAFECARD' => 'PAYSAFECARD EUR', 'POLIAU' => 'POLIAU AUD', 'POLINZ' => 'POLINZ NZD', 'PRZELEWY' => 'PRZELEWY PLN', 'QIWI' => 'QIWI EUR', 'SEPA' => 'SEPA EUR', 'TELEINGRESO' => 'TELEINGRESO EUR', 'TELEPAY' => 'TELEPAY MXN', 'YELLOWPAY' => 'YELLOWPAY CHF' ); const PRICEPOINT = 'charge2000_pricepoint'; function init() { parent::init(); $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldText('web_id', '2000Charge.com website ID')); $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldText(self::PRICEPOINT, 'Mapping code given by 2000Charge')); $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldSelect('payment_option', 'Payment Option', 'Display Only Specified Payment Options', null, array('options' =>$this->payment_options))); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('web_id', array('size' => 20, 'maxlength' => 20)) ->setLabel('2000Charge.com website ID') ->addRule('required'); $form->addText('account')->setLabel('Your client account login id'); $form->addText('pwd')->setLabel('Your client account login password'); $form->addSelect('payment_option', '', array('options' => $this->payment_options)) ->setLabel("Payment Option\n" . 'Display Only Specified Payment Options'); } function getPaymentOption(Invoice $invoice) { $products = $invoice->getProducts(); return ($po = $products[0]->data()->get('payment_option')) ? $po : $this->getConfig('payment_option', 'COMBO'); } function getSupportedCurrencies() { return array('AUD', 'BRL', 'CAD', 'CHF', 'CNY', 'EUR', 'GBP', 'NZD', 'PLN', 'USD'); } function getDays(Am_Period $period){ switch($period->getUnit()){ case Am_Period::DAY: return $period->getCount(); case Am_Period::MONTH: return $period->getCount()*30; case Am_Period::YEAR: return $period->getCount()*365; } } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $products = $invoice->getProducts(); $a = new Am_Paysystem_Action_Form(self::LIVE_URL); $web_id = $products[0]->data()->get('web_id'); if(empty($web_id)) $this->getConfig('web_id'); $a->id = $web_id; $a->pricepoint = $products[0]->data()->get(self::PRICEPOINT); $a->paymentoption = $this->getPaymentOption($invoice); $a->firstname = $invoice->getFirstName(); $a->lastname = $invoice->getLastName(); $a->address = $invoice->getStreet(); $a->city = $invoice->getCity(); $a->state = $invoice->getState(); $a->zip = $invoice->getZip(); $a->country = $invoice->getCountry(); $a->phone = $invoice->getPhone(); $a->email = $invoice->getEmail(); $a->username = $invoice->getLogin(); $a->password = 'notused'; $a->purchaseamt = $invoice->first_total; $a->currencyid= $invoice->currency; $a->purchasedesc = $invoice->getLineDescription(); if($invoice->rebill_times) { $a->recurflag = 'Y'; $a->recuramt = $invoice->second_total; $a->recurdatevalue = $this->getDays(new Am_Period($this->invoice->first_period)); } else { $a->recurflag = 'N'; } $a->xfield = $invoice->public_id; $a->postbackurl = $this->getPluginUrl('ipn'); $a->country = $invoice->getCountry(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_charge2000($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<getDi()->db->selectCell("SELECT receipt_id FROM ?_invoice_payment WHERE invoice_id=?d ORDER BY dattm LIMIT 1", $invoice->pk()); } function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $request = new Am_HttpRequest(self::CANCEL_URL, Am_HttpRequest::METHOD_POST); $request->addPostParameter('action', 'Cancel'); $request->addPostParameter('email', $invoice->getEmail()); $request->addPostParameter('mode', 'P'); $request->addPostParameter('transaction', $this->findInitialTransactionNumber($invoice)); $request->addPostParameter('clientaccount', $this->getConfig('account')); $request->addPostParameter('clientpwd', $this->getConfig('pwd')); $this->logRequest($request); $response = $request->send(); $this->logResponse($response); } } class Am_Paysystem_Transaction_charge2000 extends Am_Paysystem_Transaction_Incoming { protected $_ip = array( array('207.71.84.0', '207.71.87.255') ); public function findInvoiceId() { return $_GET['xfield']; // return $this->request->get('xfield'); } public function getUniqId() { return $_GET['transnum']; // return $this->request->get('transnum'); } public function validateSource() { $this->_checkIp($this->_ip); return true; } public function validateStatus() { return $_GET['status'] == 'APPROVED'; //return $this->request->get('status') == 'APPROVED'; } public function validateTerms() { return true; } public function processValidated(){ $this->invoice->addPayment($this); /* switch($this->request->get('transtype')) { case 'SALE-00': case 'SALE-01': case 'SALE-02': $this->invoice->addPayment($this); break; case 'REFUND': case 'VOID': $this->invoice->addRefund($this, $this->request->get('orgtransaction')); break; case 'CHARGEBACK': $this->invoice->addChargeback($this, $this->request->get('orgtransaction')); } * */ } }PK\q+))"default/plugins/payment/segpay.phpnu[addText('package_id') ->setLabel("The Package ID\n" . 'Merchant Setup -> Packages -> Package ID'); $form->addText('userid') ->setLabel("Refunds Username\n" . 'my.segpay.com username'); $form->addText('useraccesskey') ->setLabel("Refunds Password\n" . 'my.segpay.com password'); $form->addAdvCheckbox('dynamic_pricing') ->setLabel("Allow Dynamic Pricing\n" . 'this option does not allow to use recurring'); } public function isConfigured() { return $this->getConfig('package_id') ? true : false; } public function getActionURL(Invoice $invoice) { return sprintf(self::URL . '?x-eticketid=%s:%s', $invoice->getItem(0)->getBillingPlanData('segpay_package_id') ? $invoice->getItem(0)->getBillingPlanData('segpay_package_id') : $this->getConfig('package_id'), $invoice->getItem(0)->getBillingPlanData('segpay_price_point_id') ); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); if($this->getConfig('dynamic_pricing')) { $req = new Am_HttpRequest('http://srs.segpay.com/PricingHash/PricingHash.svc/GetDynamicTrans?value='.$invoice->first_total, Am_HttpRequest::METHOD_GET); $res = $req->send(); $action = new Am_Paysystem_Action_Redirect($this->getActionURL($invoice) . '&dynamictrans=' . strip_tags($res->getBody())); $action->amount = $invoice->first_total; $action->addParam('publicid' , $invoice->public_id); $action->publicid = $invoice->public_id; $action->addParam('x-billname' , $user->getName()); $action->addParam('x-billemail' , $user->email); $action->addParam('x-billaddr' , $user->street); $action->addParam('x-billcity' , $user->city); $action->addParam('x-billzip' , $user->zip); $action->addParam('x-billcntry' , $user->country); $action->addParam('x-billstate' , $user->state); $action->addParam('x-auth-link' , $this->getReturnUrl($request)); $action->addParam('x-decl-link' , $this->getCancelUrl($request)); } else { $action = new Am_Paysystem_Action_Form($this->getActionURL($invoice)); $action->addParam('x-billname' , $user->getName()); $action->addParam('x-billemail' , $user->email); $action->addParam('x-billaddr' , $user->street); $action->addParam('x-billcity' , $user->city); $action->addParam('x-billzip' , $user->zip); $action->addParam('x-billcntry' , $user->country); $action->addParam('x-billstate' , $user->state); $action->addParam('x-auth-link' , $this->getReturnUrl($request)); $action->addParam('x-decl-link' , $this->getCancelUrl($request)); $action->addParam('username' , $invoice->getLogin()); $action->addParam('publicid' , $invoice->public_id); } $result->setAction($action); } public function getSupportedCurrencies() { return array('USD', 'EUR', 'GBP'); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Segpay($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('segpay_price_point_id', "Segpay Price Point ID", "you must create the same product
      in Segpay and apply it to the Package/Website and enter its Price Point ID Here")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('segpay_package_id', "Segpay Package ID", "Merchant Setup -> Packages -> Package ID")); } function getReadme() { $url = preg_replace('#^https?://#', '', $this->getPluginUrl()); return << Postbacks and add postback with below settings. TransPost2 Postback $url/ipn?act=<action>&stage=<stage>&approved=<approved>&trantype=<trantype>&purchaseid=<purchaseid>&tranid=<tranid>&price=<price>¤cycode=<currencycode>&eticketid=<eticketid>&ip=<ipaddress>&initialvalue=<ival>&initialperiod=<iint>&recurringvalue=<rval>&recurringperiod=<rint>&desc=<desc>&username=<extra username>&password=<extrapassword>&name=<billname>&firstname=<billnamefirst>&lastname=<billnamelast>&email=<billemail>&phone=<billphone>&address=<billaddr>&city=<billcity>&state=<billstate>&zipcode=<billzip>&country=<billcntry>&transGUID=<transguid>&standin=<standin>&xsellnum=<xsellnum>&billertranstime=<transtime>&relatedtranid=<relatedtranid>&publicid=<extra publicid> Message OK CUT; } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getActionName() == 'check') { $this->_logDirectAction($request, $response, $invokeArgs); print "OK"; exit; } try { if($_GET['tranid'] && !$request->get('tranid')) { //POST combined with GET $request = new Am_Mvc_Request($_GET); $this->logRequest($request, "POSTBACK GET [ipn]"); } parent::directAction($request, $response, $invokeArgs); print "OK"; exit; } catch (Exception $e) { $this->getDi()->errorLogTable->logException($e); print "ERROR"; exit; } } function processRefund__(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { list(, $trans_id) = explode("-", $payment->receipt_id); try { $r = new Am_HttpRequest( 'http://srs.segpay.com/ADM.asmx/CancelMembership' . '?Userid=' . $this->getConfig('userid') . '&UserAccessKey=' . $this->getCOnfig('useraccesskey') . '&PurchaseID=' . $trans_id . '&CancelReason='); $response = $r->send(); } catch (Exception $e) { $this->getDi()->errorLogTable->logException($e); } if ($response && $response->getBody() == 'Successful') { $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id); $result->setSuccess($trans); } else { $result->setFailed(array('Error Processing Refund! ' . $response->getBody())); } } } class Am_Paysystem_Transaction_Segpay extends Am_Paysystem_Transaction_Incoming { const ACTION_AUTH = 'auth'; const ACTION_VOID = 'void'; const TYPE_SALE = 'sale'; const TYPE_CHARGE = 'charge'; const TYPE_CREDIT = 'credit'; public function findInvoiceId() { return ($this->request->get('publicid') ? $this->request->get('publicid') : $this->request->getFiltered('purchaseid')); } public function getUniqId() { return $this->request->get('tranid'); } public function validateSource() { return true; } public function validateStatus() { return strtolower($this->request->get('approved')) == 'yes'; } public function validateTerms() { $isFirst = $this->invoice->first_total && !$this->invoice->getPaymentsCount(); $expected = $isFirst ? $this->invoice->first_total : $this->invoice->second_total; return $expected <= $this->getAmount(); } function getAmount() { return abs($this->request->get('price')); } public function processValidated() { if(!$this->invoice->data()->get(Am_Paysystem_Segpay::PURCHASE_ID) && $this->request->getFiltered('purchaseid')) $this->invoice->data()->set(Am_Paysystem_Segpay::PURCHASE_ID, $this->request->getFiltered('purchaseid'))->update(); if(strtolower($this->request->get('trantype')) == self::TYPE_SALE) { if(strtolower($this->request->get('act')) == self::ACTION_AUTH) { if(floatval($this->request->get('price'))==0) $this->invoice->addAccessPeriod ($this); else $this->invoice->addPayment($this); } elseif(strtolower($this->request->get('act')) == self::ACTION_VOID) $this->invoice->addRefund ($this); } } public function loadInvoice($invoiceId) { if($invoice = parent::loadInvoice($invoiceId)) return $invoice; else { if($purchaseid = $this->request->getFiltered('purchaseid')) { $invoice = Am_Di::getInstance()->invoiceTable->findFirstByData(Am_Paysystem_Segpay::PURCHASE_ID, $purchaseid); // update invoice_id in the log record if ($invoice && $this->log) { $this->log->updateQuick(array( 'invoice_id' => $invoice->pk(), 'user_id' => $invoice->user_id, )); } return $invoice; } } return false; } }PK\0*default/plugins/payment/smart-debit-dl.phpnu[setTitle('SmartDebit (Direct Link)'); $form->addText('pslid') ->setLabel('PSLID (Service User)')->addRule('required'); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->first_period != $invoice->second_period) { return ___('Can not handle this billing terms'); } if ($invoice->rebill_times != IProduct::RECURRING_REBILLS) { return ___('Can not handle this billing terms'); } $period = new Am_Period($invoice->first_period); if (!in_array($period->getUnit(), array('m', 'w', 'y')) || $period->getCount() != 1) { return ___('Can not handle this billing terms'); } return parent::isNotAcceptableForInvoice($invoice); } public function getSupportedCurrencies() { return array('GBP'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $period = new Am_Period($invoice->first_period); $a = new Am_Paysystem_Action_Redirect(self::GATEWAY); $a->pslid = $this->getConfig('pslid'); $a->reference_number = self::REF_PREFIX . $invoice->public_id; $a->frequency_type = strtoupper($period->getUnit()); if ($invoice->first_total != $invoice->second_total) $a->first_amount = $invoice->first_total * 100; $a->regular_amount = $invoice->second_total * 100; $a->payer_reference = sprintf('U%07d', $user->pk()); $a->first_name = $user->name_f; $a->last_name = $user->name_l; $a->address_1 = $user->street; $a->address_2 = $user->street2; $a->town = $user->city; $a->county = $this->getDi()->countryTable->getTitleByCode($user->country); $a->postcode = $user->zip; $a->email_address = $user->email; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_SmartDebitDl($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOTHING; } public function getHash() { return $this->getDi()->security->siteHash($this->getId() . '-ipn', 10); } public function getReadme() { $ipn_url = $this->getPluginUrl($this->getHash()); return <<SmartDebit plugin configuration Set callback url in your SmartDebit account to: $ipn_url Please note your account collections in SmartDebit should match recurring terms for product in aMember. You need to disable auto-generation for reference_number in your SmartDebit account. CUT; } } class Am_Paysystem_Transaction_SmartDebitDl extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getParam('dd_reference'); } public function findInvoiceId() { $ref = $this->request->get('dd_reference'); return substr($ref, strlen(Am_Paysystem_SmartDebitDl::REF_PREFIX)); } public function validateSource() { return ($this->request->getActionName() == $this->getPlugin()->getHash()); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); $this->invoice->extendAccessPeriod(Am_Period::RECURRING_SQL_DATE); } }PK\e))(default/plugins/payment/moneybookers.phpnu[addText("business") ->setLabel("MoneyBookers account email\n" . 'your email address registered in MoneyBooks'); $form->addText("password") ->setLabel("Secret word\n" . 'Get it from Settings > Developer Settings > Secret Word'); } function getSupportedCurrencies() { return array('USD', 'GBP', 'EUR', 'CAD', 'JPY'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect(self::LIVE_URL); $a->pay_to_email = $this->getConfig('business'); $a->pay_from_email = $u->email; $a->transaction_id = $invoice->public_id; $a->amount = $invoice->first_total; $a->currency = $invoice->currency; $a->language = $u->lang; $a->return_url = $this->getReturnUrl(); $a->cancel_url = $this->getCancelUrl(); $a->status_url = $this->getPluginUrl('ipn'); $a->detail1_text = $invoice->getLineDescription(); $a->firstname = $u->name_f; $a->lastname = $u->name_l; $a->address = $u->street; $a->postal_code = $u->zip; $a->city = $u->city; $a->state = $u->state; $a->country = $u->country; if($invoice->second_total>0){ $a->rec_amount = $invoice->second_total; $periods = array('m' => 'month','y' => 'year', 'd' => 'day'); $second_period = new Am_Period($invoice->second_period); $a->rec_cycle = $periods[$second_period->getUnit()]; $a->rec_period = $second_period->getCount(); $a->rec_start_date = date('Y/m/d',strtotime($invoice->calculateRebillDate(1))); $a->rec_status_url = $this->getPluginUrl('ipn'); } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Moneybookers($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Moneybookers_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } } class Am_Paysystem_Transaction_Moneybookers extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('transaction_id'); } public function getUniqId() { return $this->request->get('mb_transaction_id'); } public function validateSource() { if($this->request->get('pay_to_email') != $this->getPlugin()->getConfig('business')) return false; $str = $this->request->get('merchant_id') . $this->request->get('transaction_id') . strtoupper(md5($this->getPlugin()->getConfig('password'))) . $this->request->get('mb_amount') . $this->request->get('mb_currency') . $this->request->get('status'); if (strtoupper(md5($str)) != $this->request->get('md5sig')) return false; else return true; } public function validateStatus() { return in_array(intval($this->request->get('status')),array(-1,2)); } public function validateTerms() { return $this->request->get('amount')==($this->invoice->isFirstPayment() ? $this->invoice->first_total : $this->invoice->second_total); } public function processValidated() { switch (intval($this->request->get('status'))) { case -1: $this->invoice->setCancelled(true); break; default: $this->invoice->addPayment($this); break; } } }PK\SGNGN'default/plugins/payment/hipay/hipay.phpnu[billingPlanTable->customFields()->add( new Am_CustomFieldText( 'hipay_site_id', "Hipay Site Id", "(optional)" ,array(/*,'required'*/) )); } public function getSupportedCurrencies() { return array( 'AUD', // => 'Australian dollar', 'GBP', // => 'British pound', 'CAD', // => 'Canadian dollar', 'EUR', // => 'Euro', 'BRL', // => 'Réal brésilien', 'SEK', // => 'Swedish krona', 'CHF', // => 'Swiss franc', 'USD' // => 'US dollar' ); } public function _initSetupForm(Am_Form_Setup $form) { $form->addInteger('account_id', array('size'=>20)) ->setLabel("Hipay Account Id\n" . '(number)'); $form->addPassword('merchant_password', array('size'=>20)) ->setLabel("Merchant Password\n" . '(set within your Hipay account)'); $form->addInteger('site_id', array('size'=>20)) ->setLabel("Hipay Site Id" . '(number)'); $sel = $form->addSelect('order_category') ->setLabel("The order/product category attached to the merchant site's category\n" . "if there is no values - please enter Site Id and Save"); $sel->loadOptions($this->getOrderCategories()); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function isConfigured() { return $this->getConfig('account_id') > ''; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { require_once dirname(__FILE__) . '/mapi/mapi_package.php'; $OrderTitle = 'Order on '.$this->getDi()->config->get('site_title'); $OrderInfo = $invoice->getLineDescription(); $OrderCategory = $this->getConfig('order_category'); $params = new HIPAY_MAPI_PaymentParams(); $params->setLogin($this->getConfig('account_id'), $this->getConfig('merchant_password')); $params->setAccounts($this->getConfig('account_id')); $params->setLocale('en_GB'); // The payment interface will be in International French by default $params->setRating('ALL'); // '+16' - The order content is intended for people at least 16 years old. $params->setMedia('WEB'); // The interface will be the Web interface if (!$invoice->rebill_times) $params->setPaymentMethod(HIPAY_MAPI_METHOD_SIMPLE); // This is a single payment else $params->setPaymentMethod(HIPAY_MAPI_METHOD_MULTI); // It is a Recurring payment $params->setCaptureDay(HIPAY_MAPI_CAPTURE_IMMEDIATE); // The capture take place immediately $params->setCurrency($invoice->currency); $params->setIdForMerchant('aMember invoice #' . $invoice->public_id); // The merchant-selected identifier for this order $params->setMerchantDatas('invoice_id', $invoice->public_id); //Data element of type key=value declared and will be returned to the merchant after the payment in the notification data feed [C]. $site_id = $this->invoice->getItem(0)->getBillingPlanData('hipay_site_id'); if (!$site_id) $site_id = $this->getConfig('site_id'); // use default value $params->setMerchantSiteId($site_id); // This order relates to the web site which the merchant declared in the Hipay platform. $params->setURLOk($this->getReturnUrl()); // If the payment is accepted, the user will be redirected to this page $params->setUrlNok($this->getCancelUrl()); // If the payment is refused, the user will be redirected to this page $params->setUrlCancel($this->getCancelUrl()); // If the user cancels the payment, he will be redirected to this page $params->setUrlAck($this->getPluginUrl('ipn')); // The merchant's site will be notified of the result of the payment by a call to the script $t = $params->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating the paymentParams object'); if ($invoice->tax_rate && $invoice->tax_title) { $tax = new HIPAY_MAPI_Tax(); $tax->setTaxName($invoice->tax_title); $percentage = true; //$invoice->tax_type == 1; $tax->setTaxVal($invoice->tax_rate, $percentage); $t = $tax->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating a tax object'); } $item1 = new HIPAY_MAPI_Product(); $item1->setName($invoice->getItem(0)->item_title); $item1->setCategory($OrderCategory); $item1->setquantity(1); $item1->setPrice($invoice->first_total); if (isset($tax)) $item1->setTax(array($tax)); //$item1->setInfo('Simmons, Dan – ISBN 0575076380'); //$item1->setRef('JV005'); $t = $item1->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating a product object'); $order = new HIPAY_MAPI_Order(); $order->setOrderTitle($OrderTitle); // Order title and information $order->setOrderInfo($OrderInfo); $order->setOrderCategory($OrderCategory); // The order category is 3 (Books) if ($invoice->hasShipping()) $order->setShipping($invoice->first_shipping, isset($tax) ? array($tax) : array()); // The shipping costs are 1.50 Euros excluding taxes, and $tax1 is applied //$order->setInsurance(2,array($tax3,$tax1)); // The insurance costs are 2 Euros excluding taxes, and $tax1 and $tax3 are applied //$order->setFixedCost(2.25,array($tax3)); // The fixed costs are 2.25 Euros excluding taxes, and $tax3 is applied to this amount //$order->setAffiliate(array($aff1,$aff2)); // This order has two affiliates, $aff1 and $aff2 $t = $order->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating a product object'); if (!$invoice->rebill_times) { try { $payment = new HIPAY_MAPI_SimplePayment($params, $order, array($item1)); } catch (Exception $e) { throw new Am_Exception_Paysystem_TransactionInvalid($e->getMessage()); } } else { // First payment: The payment will be made in 1 hour, in the amount of 5 Euros, excluding taxes plus tax $tax1. $ins1 = new HIPAY_MAPI_Installment(); if ($invoice->first_total > 0){ $price = $invoice->first_total; $paymentDelay = '0H'; } else { $price = $invoice->second_total; $paymentDelay = $this->getPeriod($invoice->first_period); } $ins1->setPrice($price); if (isset($tax)) $ins1->setTax(array($tax)); $ins1->setFirst(true, $paymentDelay); $t = $ins1->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating an instalment object'); // Subsequent payments: The payments will be made every 30 days in the amount of 12.5 Euros excluding taxes, plus tax of $tax2.0. $ins2 = new HIPAY_MAPI_Installment(); $ins2->setPrice($invoice->second_total); if (isset($tax)) $ins2->setTax(array($tax)); $paymentDelay = $this->getPeriod($invoice->second_period); $ins2->setFirst(false, $paymentDelay); $t = $ins2->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating an instalment object'); // Initial order $orderins1 = new HIPAY_MAPI_Order(); $orderins1->setOrderTitle($OrderTitle); // Title and information on this payment $orderins1->setOrderInfo($OrderInfo); //1 free hour $orderins1->setOrderCategory($OrderCategory); // The order category is 3 (Books) $t = $orderins1->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating an order object'); // Subsequent orders $orderins2 = new HIPAY_MAPI_Order(); $orderins2->setOrderTitle($OrderTitle); // Title and information on this payment $orderins2->setOrderInfo($OrderInfo); //only 12 euros 50 monthly ! $orderins2->setOrderCategory($OrderCategory); // The order category is 3 (Books) $t = $orderins2->check(); if (!$t) throw new Am_Exception_Paysystem_TransactionInvalid('An error occurred while creating an order object'); try { $payment = new HIPAY_MAPI_MultiplePayment($params, $orderins1, $ins1, $orderins2, $ins2); } catch (Exception $e) { throw new Am_Exception_Paysystem_TransactionInvalid($e->getMessage()); } } $xmlTx = $payment->getXML(); $output = HIPAY_MAPI_SEND_XML::sendXML($xmlTx, $this->getConfig('testing') ? self::TEST_URL : self::URL); $r = HIPAY_MAPI_COMM_XML::analyzeResponseXML($output, $url, $err_msg); if ($r === true && !$err_msg) { // The internet user is sent to the URL indicated by the Hipay platform $a = new Am_Paysystem_Action_Redirect($url); $result->setAction($a); } else { throw new Am_Exception_Paysystem_TransactionInvalid($err_msg); } } private function getOrderCategories() { $OrderCategories = array(); $url = $this->getConfig('testing') ? self::TEST_URL : self::URL; $url .= "list-categories/id/" . $this->getConfig('site_id'); $c = new Am_HttpRequest($url); $c->setHeader('Accept', 'application/xml'); $res = $c->send(); preg_match_all('/(.*)<\/category>/sU', $res->getBody(), $matches); foreach ($matches[1] as $k=>$v) $OrderCategories[$v] = $matches[2][$k]; return $OrderCategories; /* The order or product categories are attached to, and depend upon, the merchant site’s category. Depending on the category that is associated with the site, the categories that are available to the order and products will NOT be the same. You can obtain the list of order and product category ID’s for the merchant site at this URL: Live platform : https://payment.hipay.com/order/list-categories/id/[merchant_website_id] Test platform : https://test-payment.hipay.com/order/list-categories/id/[merchant_website_id] Abonnement Autres Télécharegment */ } public function getPeriod($period) { $p = new Am_Period($period); switch ($p->getUnit()) { case Am_Period::DAY: return $p->getCount() . 'D'; case Am_Period::MONTH: return $p->getCount() . 'M'; case Am_Period::YEAR: return $p->getCount() * 12 . 'M'; default: // nop. exception } throw new Am_Exception_Paysystem_NotConfigured( "Unable to convert period [$period] to Hipay-compatible.". "Must be number of days, months or years"); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return << 'Add a new site'. 3. Make test purchase. After your testing is done, disable Hipay plugin Testing mode in aMember Control Panel. HANDLING OF RECURRING TRANSACTIONS IS NOT YET TESTED. CUT; } /* public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); $transaction = $this->createTransaction($request, $response, $invokeArgs); if (!$transaction) { throw new Am_Exception_InputError("Request not handled - createTransaction() returned null"); } $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); } catch (Exception $e) { if ($invoiceLog) $invoiceLog->add($e); throw $e; } if ($invoiceLog) $invoiceLog->setProcessed(); //show thanks page without redirect if ($transaction->isFirst()) $this->displayThanks($request, $response, $invokeArgs, $transaction->getInvoice()); } */ public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Hipay($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Hipay extends Am_Paysystem_Transaction_Incoming { const AUTHORIZATION = 'authorization'; //Request for authorization in order to validate a bank card or to verify if the Hipay account of the payer has sufficient credit, with the intent to subsequently capture the transaction. const CANCELLATION = 'cancellation'; //Request for total or partial cancellation. const REFUND = 'refund'; //Request for total or partial refund. const CAPTURE = 'capture'; //Request for capture. const REJECT = 'reject'; //Rejected transaction after capture const SUBSCRIPTION = 'subscription'; //Cancellation of a subscription (the notification « status » will be cancel). const CANCEL = 'cancel'; const OK = 'ok'; protected $isfirst = false; protected $_xml; protected $_hash; function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); require_once dirname(__FILE__) . '/mapi/mapi_package.php'; // $r = HIPAY_MAPI_COMM_XML::analyzeNotificationXML($this->request->getPost('xml'), $operation, $status, $date, // $time, $transid, $amount, $currency, $idformerchant, $merchantdatas, $emailClient, $subscriptionId, $refProduct); $str = $this->request->getPost('xml'); //$request->getRawBody(); $xml = simplexml_load_string($str); //$this->_xml = $xml->mapi; $this->_xml = $xml; //The value of the MD5 is calculated for the information following the tag and preceding the tag . preg_match("/<\/md5content>(.*)<\/mapi>/im", $str, $matches); $this->_hash = md5($matches[1]); if (!$this->_xml) throw new Am_Exception_Paysystem_TransactionInvalid('Invalid xml received from Hipay: ' . $str); /* 1.0 c0783cc613bf025087b8bf5edecac824 capture ok 2010-02-23 4B83AEA905C49 753EA685B55651DC40F0C2784D5E1170 (if the transaction is attached to a subscription) 10.20 EUR REF6522 email_client@hipay.com <_aKey_id_client>2000 <_aKey_credit>10 REF6522 */ } public function isFirst() { return $this->isfirst; } public function getInvoice() { return $this->invoice; } public function findInvoiceId() { return $this->_xml->result->merchantDatas->_aKey_invoice_id; } public function getUniqId() { return $this->_xml->result->transid; } public function getReceiptId() { return $this->_xml->result->subscriptionId; } public function validateSource() { $this->_checkIp(<<_hash == $this->_xml->md5content; } public function validateStatus() { if (!$this->_xml->result->status == self::OK && !$this->_xml->result->status == self::CANCEL) throw new Am_Exception_Paysystem_TransactionInvalid("Status is not [ok]"); return true; } public function validateTerms() { /* disabled cause of errors like * Transaction First Total [29] does not match expected [1] * if ($this->invoice->status == Invoice::PENDING) $this->assertAmount($this->invoice->first_total, $this->getAmount(), 'First Total'); else $this->assertAmount($this->invoice->second_total, $this->getAmount(), 'Second Total'); */ return true; } public function getAmount() { return $this->_xml->result->origAmount; } public function processValidated() { if ($this->invoice->status == Invoice::PENDING) $this->isfirst = true; switch ($this->_xml->result->operation) { case self::AUTHORIZATION : if($this->invoice->status == Invoice::PENDING && $this->invoice->first_total <= 0) $this->invoice->addAccessPeriod($this); break; case self::CAPTURE : if ($this->getAmount() > 0) $this->invoice->addPayment($this); elseif ($this->invoice->status == Invoice::PENDING) $this->invoice->addAccessPeriod($this); break; case self::CANCELLATION : case self::SUBSCRIPTION : $this->invoice->setCancelled(true); break; case self::REFUND : case self::REJECT : $this->invoice->stopAccess($this); break; } } }PK\86 1default/plugins/payment/hipay/mapi/mapi_utils.phpnu[isPercentage()) { $taxAmount=sprintf("%.02f",($itemValue/100)*$tax->getTaxVal()); } else { $taxAmount+=sprintf("%.02f",$tax->getTaxVal()); } return (float)$taxAmount; } /** * Vérifie la validité d'une URL * * @param string $url * @return boolean */ public static function checkURL( $url ) { return preg_match( '#^(((http|https):\/\/){0,1})(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(.*)#i', $url ); } /** * Vérifie la validité de l'email * * @param string $email * @return boolean */ public static function checkemail( $email ) { return preg_match( '#^[_a-z0-9-]+(\.[_a-z0-9-]*)*@[a-z0-9-]+(\.[a-z0-9-]+)+$#i', $email ); } /** * convertit un délai mapi en tableau * * @param string $delay * @return array */ public static function parseDelay( $delay ) { $array = array_fill_keys( array('H', 'I', 'S', 'M', 'D', 'Y'), 0 ); $n = substr( $delay, 0, -1 ); $r = substr( $delay, -1, 1 ); $array[ strtoupper($r) ] = $n; return $array; } /** * Renvoie le flux xml sous forme de tableau associatif multi dimensionnel * php.net Julio Cesar Oliveira * * @param string $xml * @param boolean $recursive * * @return array */ public static function xml2Array($xml, $recursive = false) { if(!$recursive) { $array = (array) simplexml_load_string($xml); } else { $array = (array) $xml; } $newArray = array(); foreach ($array as $key => $value) { $value = (array)$value; if (isset($value[0])) { $newArray[$key] = trim ($value[0]); } else { $newArray[$key] = self::xml2Array($value, true); } } return $newArray ; } } ?>PK\0default/plugins/payment/hipay/mapi/mapi_utf8.phpnu[= $len) break; if ($chr & 0x80) { $chr <<= 1; while ($chr & 0x80) { $i++; $chr <<= 1; } } } return $count; } } ?>PK\!+bE""4default/plugins/payment/hipay/mapi/mapi_comm_xml.phpnu[result[0]->url)) { $url = $obj->result[0]->url; return true; } if (isset($obj->result[0]->message)) $err_msg = $obj->result[0]->message; return false; } /** * Traitement du flux XML envoyé par HiPay notifiant le résultat d'une action sur une transaction * * @param string $xml * @param string $status * @param string $date * @param string $time * @param string $transid * @param string $origAmount * @param string $origCurrency * @param string $idformerchant * @param array $merchantdatas * @param string $emailClient * @param string $subscriptionId * @param array $refProduct * @return boolean */ public static function analyzeNotificationXML($xml,&$operation,&$status,&$date,&$time,&$transid,&$origAmount,&$origCurrency,&$idformerchant,&$merchantdatas,&$emailClient,&$subscriptionId,&$refProduct) { $operation=''; $status=''; $date=''; $time=''; $transid=''; $origAmount=''; $origCurrency=''; $idformerchant=''; $merchantdatas=array(); $emailClient=''; $subscriptionId=''; $refProduct=array(); try { $obj = new SimpleXMLElement(trim($xml)); } catch (Exception $e) { return false; } if (isset($obj->result[0]->operation)) $operation=$obj->result[0]->operation; else return false; if (isset($obj->result[0]->status)) $status=$obj->result[0]->status; else return false; if (isset($obj->result[0]->date)) $date=$obj->result[0]->date; else return false; if (isset($obj->result[0]->time)) $time=$obj->result[0]->time; else return false; if (isset($obj->result[0]->transid)) $transid=$obj->result[0]->transid; else return false; if (isset($obj->result[0]->origAmount)) $origAmount=$obj->result[0]->origAmount; else return false; if (isset($obj->result[0]->origCurrency)) $origCurrency=$obj->result[0]->origCurrency; else return false; if (isset($obj->result[0]->idForMerchant)) $idformerchant=$obj->result[0]->idForMerchant; else return false; if (isset($obj->result[0]->merchantDatas)) { $d = $obj->result[0]->merchantDatas->children(); foreach($d as $xml2) { if (preg_match('#^_aKey_#i',$xml2->getName())) { $indice = substr($xml2->getName(),6); $xml2 = (array)$xml2; $valeur = (string)$xml2[0]; $merchantdatas[$indice]=$valeur; } } } if (isset($obj->result[0]->emailClient)) $emailClient=$obj->result[0]->emailClient; else return false; if (isset($obj->result[0]->subscriptionId)) $subscriptionId=$obj->result[0]->subscriptionId; foreach($obj->result[0] as $key=>$value) { if(preg_match('#^refProduct[\d]#', $key)) { $refProduct[] = (string)$value; } } return true; } } ?> PK\qq/default/plugins/payment/hipay/mapi/mapi_xml.phpnu[\n"; foreach($this as $name=>$value) { if ($noshow && substr($name,0,1)=='_') continue; if (!is_array($this->$name) && !is_object($this->$name) && !is_bool($this->$name)) { $xml.=str_repeat(chr(9),$t+1)."<$name>$value\n"; } else if (is_bool($this->$name)) { if ($value===true) $xml.=str_repeat(chr(9),$t+1)."<$name>true\n"; else $xml.=str_repeat(chr(9),$t+1)."<$name>false\n"; } else if (is_object($this->$name) && method_exists($this->$name,'getXML')) { $xml.=$this->$name->getXml($t+1); } else if (is_array($this->$name)) { $xml.=str_repeat(chr(9),$t+1)."<$name>\n"; $xml.=self::getXMLArray($this->$name,$t+1,$noshow); $xml.=str_repeat(chr(9),$t+1)."\n"; } // else : no getXML method available } $xml.=str_repeat(chr(9),$t)."\n"; return $xml; } /** * Cré le flux XML d'un tableau * * @param array $array * @param int $t * @return string */ protected function getXMLArray($array,$t=0,$noshow=true) { $xml=''; foreach($array as $name=>$value) { if (substr($name,0,1)=='_') continue; if (!is_array($array[$name]) && !is_object($array[$name]) && !is_bool($array[$name])) { $xml.=str_repeat(chr(9),$t+1)."<_aKey_$name>$value\n"; } else if (is_bool($array[$name])) { if ($value===true) $xml.=str_repeat(chr(9),$t+1)."<$name>true\n"; else $xml.=str_repeat(chr(9),$t+1)."<$name>false\n"; } else if (is_object($array[$name]) && method_exists($array[$name],'getXML')) { $xml.=$array[$name]->getXml($t+1); } else if (is_array($array[$name])){ $xml.=str_repeat(chr(9),$t+1)."<$name>\n"; $xml.=self::getXMLArray($array[$name],$t+1,$noshow); $xml.=str_repeat(chr(9),$t+1)."\n"; } } return $xml; } } ?>PK\֮=OO;default/plugins/payment/hipay/mapi/mapi_multiplepayment.phpnu[getFirst()===$nextInstallment->getFirst() || !$firstInstallment->getFirst()) { throw new Exception('Vous devez définir un objet installment pour le premier et les paiements suivants'); } $firstInstallment->setDelayTS(); $nextInstallment->setDelayTS( $firstInstallment->getDelayTS() ); try { parent::__construct($paymentParams,array($firstOrder,$nextOrder),array($firstInstallment,$nextInstallment)); } catch(Exception $e) { throw new Exception($e->getMessage()); } } /** * Retourne le montant total de la somme devant être * distribuée aux affiliés */ protected function _getTotalAmountForAffiliates($installement_nr) { $affiliates=$this->order[0]->getAffiliate(); if (!HIPAY_MAPI_UTILS::is_an_array_of($affiliates,'HIPAY_MAPI_Affiliate')) return false; $total_aff = 0; foreach($affiliates as $aff) { $total_aff+=$aff->getAmount(); } return $total_aff; } } ?>PK\Pw4default/plugins/payment/hipay/mapi/mapi_lockable.phpnu[_locked=true; } function __construct() { $this->_locked=false; } } ?>PK\Q)--9default/plugins/payment/hipay/mapi/mapi_simplepayment.phpnu[getMessage()); } } } ?>PK\m 3default/plugins/payment/hipay/mapi/mapi_product.phpnu[_locked) return false; $name = HIPAY_MAPI_UTF8::forceUTF8($name); $len=HIPAY_MAPI_UTF8::strlen_utf8($name); if ($len<1 || $len>HIPAY_MAPI_MAX_PRODUCT_NAME_LENGTH) return false; $this->name=$name; return true; } /** * Retourne le nom du produit * * @return string */ public function getName() { return $this->name; } /** * Assigne les informations sur le produit * * @param string $info * @return boolean */ public function setInfo($info) { if ($this->_locked) return false; $info = HIPAY_MAPI_UTF8::forceUTF8($info); $len=HIPAY_MAPI_UTF8::strlen_utf8($info); if ($len>HIPAY_MAPI_MAX_PRODUCT_INFO_LENGTH) return false; $this->info=$info; return true; } /** * Retourne les informations sur le produit * * @return string */ public function getInfo() { return $this->info; } /** * Assigne la quantité de produit * * @param int $quantity * @return boolean */ public function setQuantity($quantity) { if ($this->_locked) return false; $quantity=(int)$quantity; if ($quantity<1) return false; $this->quantity=$quantity; return true; } /** * Retourne la quantité de produit * * @return int */ public function getQuantity() { return $this->quantity; } /** * Assigne la réference du produit * * @param string $ref * @return boolean */ public function setRef($ref) { if ($this->_locked) return false; $ref = HIPAY_MAPI_UTF8::forceUTF8($ref); $len=HIPAY_MAPI_UTF8::strlen_utf8($ref); if ($len>HIPAY_MAPI_MAX_PRODUCT_REF_LENGTH) return false; $this->ref=$ref; return true; } /** * Retourne la réference du produit * * @return string */ public function getRef() { return $this->ref; } /** * Assigne la catégorie du produit * * @param int $category * @return boolean */ public function setCategory($category) { if ($this->_locked) return false; $category = (int)$category; if ($category<1) return false; $this->category=$category; return true; } /** * Retourne la catégorie du produit * * @return int */ public function getCategory() { return $this->category; } /** * Assigne le montant unitaire HT du produit * * @param float $price * @return boolean */ public function setPrice($price) { if ($this->_locked) return false; $price = sprintf('%.02f',(float)$price); // if ($price<0) // return false; $this->price=$price; return true; } /** * Retourne montant unitaire HT du produit * * @return float */ public function getPrice() { return $this->price; } /** * Assigne les taxes s'appliquant à ce produit * * @param array $tax * @return boolean */ public function setTax($tax) { if ($this->_locked) return false; if (!HIPAY_MAPI_UTILS::is_an_array_of($tax,'HIPAY_MAPI_Tax')) return false; foreach ($tax as $obj) $this->tax[]= clone $obj; return true; } /** * Retourne les taxes s'appliquant à ce produit * * @return array */ public function getTax() { return $this->tax; } /** * Vérifie que l'objet est correctement initialisé * * @return boolean */ public function check() { //if ($this->name=='' || $this->quantity<0 || $this->category<0 || $this->price<0 || !HIPAY_MAPI_UTILS::is_an_array_of($this->tax,'HIPAY_MAPI_Tax')) if ($this->name=='' || $this->quantity<0 || $this->category<0 || !HIPAY_MAPI_UTILS::is_an_array_of($this->tax,'HIPAY_MAPI_Tax')) throw new Exception('L\'objet n\'à pas été initialisé. Vous devez préciser un nom de produit, une quantité, un prix, une catégorie et des taxes'); foreach($this->tax as $obj) { if (!$obj->check()) return false; } return true; } protected function init() { $this->name=''; $this->info=''; $this->quantity=-1; $this->ref=''; $this->category=-1; $this->price=-1; $this->tax=array(); } function __construct() { $this->init(); parent::__construct(); } } ?>PK\ 5default/plugins/payment/hipay/mapi/mapi_affiliate.phpnu[0, $val est un pourcentage et $percentageTarget détermine * sur quels montants appliquer le pourcentage * * @var unknown_type */ protected $percentageTarget; /** * Montant à reversé à l'affilié * * @var unknown_type */ protected $_amount; /** * Montant de base sur lequel est calculé le montant * reversé à l'affilié * * @var unknown_type */ protected $_baseAmount; /** * Assigne le numéro de client * * @param int $customerId * @return boolean */ public function setCustomerId($customerId) { if ($this->_locked) return false; $customerId = (int)$customerId; if ($customerId<=0) return false; $this->customerId = $customerId; return true; } /** * Retourne le numéro de client * * @return int */ public function getCustomerId() { return $this->customerId; } /** * Assigne le numéro de compte * * @param int $accountId * @return boolean */ public function setAccountId($accountId) { if ($this->_locked) return false; $accountId = (int)$accountId; if ($accountId<=0) return false; $this->accountId = $accountId; return true; } /** * Retourne le numéro de compte * * @return int */ public function getAccountId() { return $this->accountId; } /** * Assigne le valeur de l'affiliation, qui est un montant fixe ou un pourcentage * S'il s'agit d'un pourcentage, $percentageTarget représente la cible, c'est à dire sur quels * montants est basé le montant de l'affiliation * * @param float $val * @param int $percentageTarget * @return boolean */ public function setValue($val,$percentageTarget=0) { if ($this->_locked) return false; $val = sprintf('%.02f',(float)$val); $percentageTarget = (int)$percentageTarget; if ($val<=0 || $percentageTarget<0) return false; if ($percentageTarget>0 && $val>100) return false; if ($percentageTarget>0 && $percentageTarget>HIPAY_MAPI_TTARGET_ALL) return false; $this->val = $val; $this->percentageTarget = $percentageTarget; $this->setAmount(); return true; } /** * Retourne la valeur de l'affiliation * * @return float */ public function getValue() { return $this->val; } /** * Retourne sur quoi s'applique le pourcentage * * @return int */ public function getPercentageTarget() { return $this->percentageTarget; } /** * Assigne le montant sur lequel sera calculé l'affiliation * * @param float $baseAmount * @return boolean */ public function setBaseAmount($baseAmount) { if ($this->_locked) return false; $baseAmount = sprintf('%.02f',(float)$baseAmount); if ($baseAmount<0) return false; $this->_baseAmount = $baseAmount; $this->setAmount(); return true; } /** * Retourne le montant sur lequel sera calculé l'affiliation * * @return int */ public function getBaseAmount() { return $this->_baseAmount; } /** * Retourne le montant calculé de l'affiliation * * @return float */ public function getAmount() { return $this->_amount; } /** * Assigne le montant calculé de l'affiliation * */ protected function setAmount() { if ($this->percentageTarget>0) { $this->_amount = sprintf('%.02f',($this->_baseAmount/100)*$this->val); } else { $this->_amount = sprintf('%.02f',$this->_baseAmount); } } /** * Vérifie que l'objet est bien initialisé * * @return boolean */ public function check() { if ($this->customerId<=0 || $this->accountId<=0 || $this->val<=0 || $this->percentageTarget<0) throw new Exception('Numéro de client, numéro de compte, valeur ou cible incorrects'); return true; } protected function init() { $this->customerId = 0; $this->accountId = 0; $this->_amount = 0; $this->_baseAmount = 0; $this->val = 0; $this->percentageTarget = 0; } function __construct() { $this->init(); parent::__construct(); } } ?>PK\J J 4default/plugins/payment/hipay/mapi/mapi_send_xml.phpnu[Network problem ? Verify your proxy configuration in mapi_defs.php'; } else $output = ob_get_contents(); ob_end_clean(); curl_close($curl); if (HIPAY_MAPI_CURL_LOG_ON === true) { fclose($errorFileLog); } return $output; } /** * Prépare le flux XML * * @param string $xml * @return string */ public static function prepare($xml) { $cleanXML = ''; $xml = trim($xml); $md5 = hash('md5', $xml); $cleanXML = "\n"; $cleanXML.="\n"; $cleanXML.="" . MAPI_VERSION . "\n"; $cleanXML.='' . $md5 . "\n"; $cleanXML.=$xml; $cleanXML.="\n\n"; return trim($cleanXML); } } PK\ #6 /default/plugins/payment/hipay/mapi/mapi_tax.phpnu[_locked) return false; $taxName = HIPAY_MAPI_UTF8::forceUTF8($taxName); $len=HIPAY_MAPI_UTF8::strlen_utf8($taxName); if ($len<1 || $len>HIPAY_MAPI_MAX_TAX_NAME_LENGTH) return false; $this->taxName=$taxName; return true; } /** * retourne le nom de la taxe * * @return string nom de la taxe */ public function getTaxName() { return $this->taxName; } /** * assigne la valeur de la taxe * * @param float $taxVal valeur de la taxe * @param boolean $percentage true si la valeur de la taxe est un pourcentage * @return boolean true si l'assignation s'est bien déroulée */ public function setTaxVal($taxVal,$percentage=true) { if ($this->_locked) return false; if (!is_bool($percentage)) return false; $taxVal = sprintf('%.02f',(float)$taxVal); if ($percentage && ($taxVal<=0 || $taxVal>100)) return false; $this->taxVal=$taxVal; $this->percentage=$percentage; return true; } /** * retourne la valeur de la taxe * * @return float valeur de la taxe */ public function getTaxVal() { return $this->taxVal; } /** * détermine si la valeur de la taxe est un pourcentage * * @return boolean true si la valeur de la taxe est un pourcentage */ public function isPercentage() { return $this->percentage; } /** * effectue une vérification des propriétés de la taxe * * @return boolean true si les propriétés de la taxe sont correctes */ public function check() { if ($this->taxName=='' || $this->taxVal<0) throw new Exception('Nom ou valeur de la taxe non initialisée'); return true; } /** * initilise les propriétés de la taxe * */ protected function init() { $this->taxVal=-1; $this->taxName=''; $this->percentage=false; $this->_amount=0; $this->_locked=false; } /** * assigne le montant calculé de la taxe * * @param float $amount montant calculé * @return boolean true si l'assignation s'est bien déroulée */ public function setTaxAmount($amount) { if ($this->_locked) return false; $amount=(float)$amount; if ($amount<0) $amount=0; $this->_amount = sprintf("%.02f",$amount); return true; } /** * retourne le montant calculé de la taxe * * @return float montant calculé */ public function getTaxAmount() { return $this->_amount; } /** * constructeur * */ function __construct() { $this->init(); parent::__construct(); } } ?>PK\|0default/plugins/payment/hipay/mapi/mapi_item.phpnu[PK\pp5default/plugins/payment/hipay/mapi/mapi_exception.phpnu[keyword=$keyword; $this->value=$value; parent::__construct($msg,$code); } public function getKeyword() { return $this->keyword; } public function getValue() { return $this->value; } } ?>PK\Xj1default/plugins/payment/hipay/mapi/mapi_order.phpnu[_locked) return false; $shippingAmount = sprintf('%.02f',(float)$shippingAmount); if ($shippingAmount<0) { return false; } if (!HIPAY_MAPI_UTILS::is_an_array_of($shippingTax,'HIPAY_MAPI_Tax')) { return false; } $this->shippingAmount=$shippingAmount; foreach ($shippingTax as $obj) $this->shippingTax[]= clone $obj; return true; } /** * Retourne le montant des frais d'envoi * * @return float */ public function getShippingAmount() { return $this->shippingAmount; } /** * Retourne les taxes s'appliquants aux frais d'envoi * * @return array */ public function &getShippingTax() { return $this->shippingTax; } /** * Défini le montant des assurances * * @param float $insuranceAmount * @param array $insuranceTax * @return boolean */ public function setInsurance($insuranceAmount,$insuranceTax) { if ($this->_locked) return false; $insuranceAmount = sprintf('%.02f',(float)$insuranceAmount); if ($insuranceAmount<0) return false; if (!HIPAY_MAPI_UTILS::is_an_array_of($insuranceTax,'HIPAY_MAPI_Tax')) return false; $this->insuranceAmount=$insuranceAmount; foreach ($insuranceTax as $obj) $this->insuranceTax[]= clone $obj; return true; } /** * Retourne le montant des assurances * * @return float */ public function getInsuranceAmount() { return $this->insuranceAmount; } /** * Retourne les taxes s'appliquants aux assurances * * @return array */ public function &getInsuranceTax() { return $this->insuranceTax; } /** * Défini le montant des coûts fixes et les taxes s'y appliquant * * @param float $fixedCostAmount * @param array $fixedCostTax * @return boolean */ public function setFixedCost($fixedCostAmount,$fixedCostTax) { if ($this->_locked) return false; $fixedCostAmount = sprintf('%.02f',(float)$fixedCostAmount); if ($fixedCostAmount<0) return false; if (!HIPAY_MAPI_UTILS::is_an_array_of($fixedCostTax,'HIPAY_MAPI_Tax')) return false; $this->fixedCostAmount=$fixedCostAmount; foreach ($fixedCostTax as $obj) $this->fixedCostTax[]= clone $obj; return true; } /** * Retourne le montant des coûts fixes * * @return float */ public function getFixedCostAmount() { return $this->fixedCostAmount; } /** * Retourne les taxes s'appliquant aux coûts fixes * * @return array */ public function &getFixedCostTax() { return $this->fixedCostTax; } /** * Défini les affiliés qui recevront une rétribution pour cette commande * * @param array $affiliate * @return boolean */ public function setAffiliate($affiliate) { if ($this->_locked) return false; if (!HIPAY_MAPI_UTILS::is_an_array_of($affiliate,'HIPAY_MAPI_Affiliate')) return false; foreach ($affiliate as $obj) $this->affiliate[]= clone $obj; return true; } /** * Retourne la liste des affiliés de cette commande * * @return array */ public function &getAffiliate() { return $this->affiliate; } /** * Assigne l'intitulé de la commande * * @param string $orderTitle * @return boolean */ public function setOrderTitle($orderTitle) { if ($this->_locked) return false; $orderTitle = HIPAY_MAPI_UTF8::forceUTF8($orderTitle); $len=HIPAY_MAPI_UTF8::strlen_utf8($orderTitle); if ($len<1 || $len>HIPAY_MAPI_MAX_TITLE_LENGTH) return false; $this->orderTitle=$orderTitle; return true; } /** * Retourne l'intitulé de la commande * * @return string */ public function getOrderTitle() { return $this->orderTitle; } /** * Assigne les infos sur la commande * * @param string $orderInfo * @return boolean */ public function setOrderInfo($orderInfo) { if ($this->_locked) return false; $orderInfo = HIPAY_MAPI_UTF8::forceUTF8($orderInfo); $len=HIPAY_MAPI_UTF8::strlen_utf8($orderInfo); if ($len>HIPAY_MAPI_MAX_INFO_LENGTH) return false; $this->orderInfo=$orderInfo; return true; } /** * Retourne les infos sur la commande * * @return string */ public function getOrderInfo() { return $this->orderInfo; } /** * Assigne la catégorie de la commande * * @param int $orderCategory * @return boolean */ public function setOrderCategory($orderCategory) { if ($this->_locked) return false; $orderCategory = (int)$orderCategory; if ($orderCategory<1) return false; $this->orderCategory=$orderCategory; return true; } /** * Retourne la catégorie de la commande * * @return int */ public function getOrderCategory() { return $this->orderCategory; } /** * Vérifie si l'objet est correctement initialisé * * @return boolean */ public function check() { if ($this->orderTitle=='' || $this->orderCategory<0) throw new Exception('L\'intitulé et/ou la catégorie de la commande sont manquants'); foreach($this->affiliate as $obj) { try { $obj->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } foreach($this->shippingTax as $obj) { try { $obj->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } foreach($this->insuranceTax as $obj) { try { $obj->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } foreach($this->fixedCostTax as $obj) { try { $obj->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } return true; } protected function init() { $this->shippingAmount=0; $this->shippingTax=array(); $this->insuranceAmount=0; $this->insuranceTax=array(); $this->fixedCostAmount=0; $this->fixedCostTax=array(); $this->affiliate=array(); $this->orderTitle=''; $this->orderInfo=''; $this->orderCategory=-1; } function __construct() { $this->init(); parent::__construct(); } } ?>PK\ǘ==3default/plugins/payment/hipay/mapi/mapi_package.phpnu[PK\Fcȣ++3default/plugins/payment/hipay/mapi/mapi_payment.phpnu[init($paymentParams,$order,$items); } catch(Exception $e) { throw new Exception($e->getMessage()); } } protected function init($paymentParams,$order,$items) { if (!($paymentParams instanceof HIPAY_MAPI_PaymentParams) || !HIPAY_MAPI_UTILS::is_an_array_of($order,'HIPAY_MAPI_Order') || !HIPAY_MAPI_UTILS::is_an_array_of($items,'HIPAY_MAPI_Item') || count($items)<1) throw new Exception('Wrong parameters'); try { $paymentParams->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } foreach($order as $orderObj) { try { $orderObj->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } } foreach($items as $obj) try { $obj->check(); } catch (Exception $e) { throw new Exception($e->getMessage()); } $this->paymentParams= clone $paymentParams; $this->paymentParams->lock(); foreach($order as $obj) { $this->order[]= clone $obj; end($this->order)->lock(); $this->_taxItemsAmount[]=0; $this->_taxShippingAmount[]=0; $this->_taxInsuranceAmount[]=0; $this->_taxFixedCostAmount[]=0; $this->_itemsTotalAmount[]=0; $this->_taxTotalAmount[]=0; $this->_orderTotalAmount[]=0; $this->_affiliateTotalAmount[]=0; } foreach($items as $obj) { $this->items[]= clone $obj; end($this->items)->lock(); } try { $this->compute(); } catch(Exception $e) { throw new Exception($e->getMessage()); } } /** * Calcul les différents montants (taxes, affiliés, totaux) de la commande * */ protected function compute() { // Mise à jour du montant total des taxes pour chaque item du tableau _taxItemsAmount // Mise à jour du montant total des taxes de livraison pour chaque order du tableau _taxShippingAmount // Mise à jour du montant total des taxes d'assurances pour chaque order du tableau _taxInsuranceAmount // Mise à jour du montant total des taxes de couts fixes pour chaque order du tableau _taxFixedCostAmount $this->computeTaxes(); // Mise a jour du montant total HT des produits pour chaque item du tableau _itemsTotalAmount $this->computeItemsAmount(); // Pour chaque commande foreach($this->order as $key=>$order) { $this->_taxTotalAmount[$key] = $this->_taxItemsAmount[$key] + $this->_taxShippingAmount[$key] + $this->_taxInsuranceAmount[$key] + $this->_taxFixedCostAmount[$key]; $this->_orderTotalAmountHT[$key] = $order->getShippingAmount() + $order->getInsuranceAmount() + $order->getFixedCostAmount() + $this->_itemsTotalAmount[$key]; $this->_orderTotalAmount[$key] = $this->_orderTotalAmountHT[$key] + $this->_taxTotalAmount[$key]; // $this->_orderTotalAmount[$key] = $order->getShippingAmount() + $order->getInsuranceAmount() + $order->getFixedCostAmount() + $this->_itemsTotalAmount[$key] + // $this->_taxItemsAmount[$key] + // $this->_taxShippingAmount[$key] + // $this->_taxInsuranceAmount[$key] + // $this->_taxFixedCostAmount[$key]; } try { $this->computeAffiliates(); } catch(Exception $e) { throw new Exception($e->getMessage()); } } /** * Calcul le montant des taxes * */ protected function computeTaxes() { // Taxes sur les produits au niveau de l'item (ligne de commande) // @FIXME bug et confusion entre indice d'item et indice d'order ? $cur=0; // pour chaque ligne de commande foreach($this->items as $item) { // Liste des taxes de la ligne $itemTaxes= $item->getTax(); $tItemsAmount=0; // pour chaque taxe appliquée sur cette ligne foreach($itemTaxes as $tax) { $amount=HIPAY_MAPI_UTILS::computeTax($item->getPrice(),$tax); $tax->setTaxAmount($amount); $tax->lock(); // mise a jour du montant total des taxes pour cet item (ligne de commande) $tItemsAmount+=$amount; } if (!isset($this->order[$cur])) $cur=0; if (!isset($this->_taxItemsAmount[$cur])) $this->_taxItemsAmount[$cur]=0; // mise a jour du montant total des taxes pour cette ligne de commande // avec prise en compte du nombre de produits dans l'indice numLigneCommande // du tableau _taxItemsAmount de cette commande $this->_taxItemsAmount[$cur]+=($tItemsAmount*$item->getQuantity()); $item->lock(); $cur++; } // Taxes sur frais d'envoi, assurances, coûts fixes // au niveau des commandes $cur=0; foreach($this->order as $order) { // Taxes sur frais d'envoi $taxArr =& $order->getShippingTax(); foreach($taxArr as $key=>$tax) { $amount=HIPAY_MAPI_UTILS::computeTax($order->getShippingAmount(),$tax); $taxArr[$key]->setTaxAmount($amount); $taxArr[$key]->lock(); if (!isset($this->_taxShippingAmount[$cur])) $this->_taxShippingAmount[$cur]=0; $this->_taxShippingAmount[$cur]+=$amount; } // Taxes sur assurances $taxArr =& $order->getInsuranceTax(); foreach($taxArr as $key=>$tax) { $amount=HIPAY_MAPI_UTILS::computeTax($order->getInsuranceAmount(),$tax); $taxArr[$key]->setTaxAmount($amount); $taxArr[$key]->lock(); if (!isset($this->_taxInsuranceAmount[$cur])) $this->_taxInsuranceAmount[$cur]=0; $this->_taxInsuranceAmount[$cur]+=$amount; } // Taxes sur coûts fixes $taxArr =& $order->getFixedCostTax(); foreach($taxArr as $key=>$tax) { $amount=HIPAY_MAPI_UTILS::computeTax($order->getFixedCostAmount(),$tax); $taxArr[$key]->setTaxAmount($amount); $taxArr[$key]->lock(); if (!isset($this->_taxFixedCostAmount[$cur])) $this->_taxFixedCostAmount[$cur]=0; $this->_taxFixedCostAmount[$cur]+=$amount; } $cur++; } } /** * Calcul le montant total HT des produits * */ protected function computeItemsAmount() { $itemsAmount=0; $cur=0; foreach($this->items as $item) { $mt=sprintf("%.02f",$item->getPrice()*$item->getQuantity()); if (!isset($this->order[$cur])) $cur=0; if (!isset($this->_itemsTotalAmount[$cur])) $this->_itemsTotalAmount[$cur]=0; $this->_itemsTotalAmount[$cur]+=$mt; $cur++; } } /** * Retourne le montant total des taxes * * @param array $tItemsAmount * @param array $tShippingAmount * @param array $tInsuranceAmount * @param array $tFixedCostAmount */ public function getTotalTaxes(&$tItemsAmount,&$tShippingAmount,&$tInsuranceAmount,&$tFixedCostAmount) { $tItemsAmount=$this->getItemsTaxes();; $tShippingAmount=$this->getShippingTaxes(); $tInsuranceAmount=$this->getInsuranceTaxes(); $tFixedCostAmount=$this->getFixedCostTaxes(); } /** * Retourne le montant des taxes sur les articles * * @return float */ public function getItemsTaxes() { return $this->_taxItemsAmount; } /** * Retourne le montant des taxes sur les frais de port * * @return float */ public function getShippingTaxes() { return $this->_taxShippingAmount; } /** * Retourne le montant des taxes sur les assurances * * @return float */ public function getInsuranceTaxes() { return $this->_taxInsuranceAmount; } /** * Retourne le montant des taxes sur les couts fixes * * @return float */ public function getFixedCostTaxes() { return $this->_taxFixedCostAmount; } /** * Retourne le montant total des produits * * @return array */ public function getItemsTotalAmount() { return $this->_itemsTotalAmount; } /** * Retourne le montant total des taxes * * @return array */ public function getTaxesTotalAmount() { return $this->_taxTotalAmount; } /** * Retourne le montant total hors taxes de la commande * * @return array */ public function getOrderTotalAmountHT() { return $this->_orderTotalAmountHT; } /** * Retourne le montant total TTC de la commande * * @return array */ public function getOrderTotalAmount() { return $this->_orderTotalAmount; } /** * Retourne le montant total des affiliés * * @return array */ public function getAffiliateTotalAmount() { return $this->_affiliateTotalAmount; } /** * Retourne les objets order * * @return array */ public function getOrder() { return $this->order; } /** * Retourne les objets items * * @return array */ public function getItems() { return $this->items; } /** * Retourne l'objet paramètre * * @return HIPAY_MAPI_PaymentParams */ public function getPaymentParams() { return $this->paymentParams; } /** * Calcul les montants à redistribuer aux affiliés * */ protected function computeAffiliates() { foreach($this->order as $k=>$order) { $totalAmount=0; $tAffiliate = $order->getAffiliate(); foreach($tAffiliate as $key=>$affiliate) { $baseAmount=0; $percentageTarget= $affiliate->getPercentageTarget(); if ($percentageTarget>0) { if ($percentageTarget & HIPAY_MAPI_TTARGET_ITEM) $baseAmount+=$this->_itemsTotalAmount[$k]; if ($percentageTarget & HIPAY_MAPI_TTARGET_TAX) $baseAmount+=$this->_taxItemsAmount[$k]+$this->_taxFixedCostAmount[$k]+$this->_taxInsuranceAmount[$k]+$this->_taxShippingAmount[$k]; if ($percentageTarget& HIPAY_MAPI_TTARGET_INSURANCE) $baseAmount+=$order->getInsuranceAmount(); if ($percentageTarget & HIPAY_MAPI_TTARGET_FCOST) $baseAmount+=$order->getFixedCostAmount(); if ($percentageTarget & HIPAY_MAPI_TTARGET_SHIPPING) $baseAmount+=$order->getShippingAmount(); $tAffiliate[$key]->setBaseAmount($baseAmount); } else { $baseAmount = $affiliate->getValue(); $tAffiliate[$key]->setBaseAmount($baseAmount); } $totalAmount+=$tAffiliate[$key]->getAmount(); $tAffiliate[$key]->lock(); } $this->_affiliateTotalAmount[$k]=$totalAmount; if ($totalAmount > $this->_orderTotalAmount[$k]) { throw new Exception('Le montant à redistribuer est supérieur au montant de la transaction ('.$totalAmount.'/'.$this->_orderTotalAmount.')'); } } } } ?>PK\^  0default/plugins/payment/hipay/mapi/mapi_defs.phpnu[PK\ */ protected $informations; /** * Décrit si la case cgu est cochée par défaut ou non * * @var int */ protected $cguChecked; /** * Assigne le login et le mot de passe * * @param string $login * @param string $password * @return boolean */ public function setLogin($login,$password) { if ($this->_locked) return false; $login = HIPAY_MAPI_UTF8::forceUTF8($login); if (empty($login)) return false; $password = HIPAY_MAPI_UTF8::forceUTF8($password); if (empty($password)) return false; $this->login=$login; $this->password=$password; return true; } /** * Retourne le login * * @return string */ public function getLogin() { return $this->login; } /** * Retourne le mot de passe * * @return string */ public function getPassword() { return $this->password; } /** * Assigne les comptes sur lesquels seront versés les différents montants * * @param int $itemAccount * @param int $taxAccount * @param int $insuranceAccount * @param int $fixedCostAccount * @param int $shippingCostAccount * @return boolean */ public function setAccounts($itemAccount,$taxAccount=0,$insuranceAccount=0,$fixedCostAccount=0,$shippingCostAccount=0) { if ($this->_locked) return false; $itemAccount=(int)$itemAccount; $taxAccount=(int)$taxAccount; $insuranceAccount=(int)$insuranceAccount; $fixedCostAccount=(int)$fixedCostAccount; $shippingCostAccount=(int)$shippingCostAccount; if ($itemAccount<=0) return false; if ($taxAccount<=0) $taxAccount=$itemAccount; if ($insuranceAccount<=0) $insuranceAccount=$itemAccount; if ($fixedCostAccount<=0) $fixedCostAccount=$itemAccount; if ($shippingCostAccount<=0) $shippingCostAccount=$itemAccount; $this->itemAccount = $itemAccount; $this->taxAccount = $taxAccount; $this->insuranceAccount = $insuranceAccount; $this->fixedCostAccount = $fixedCostAccount; $this->shippingCostAccount = $shippingCostAccount; return true; } /** * Retourne le numéro de compte sur lequel sera versé * le montant de produits * * @return int */ public function getItemAccount() { return $this->itemAccount; } /** * Retourne le numéro de compte sur lequel sera versé * le montant des taxes * * @return int */ public function getTaxAccount() { return $this->taxAccount; } /** * Retourne le numéro de compte sur lequel sera versé * le montant des assurances * * @return int */ public function getInsuranceAccount() { return $this->insuranceAccount; } /** * Retourne le numéro de compte sur lequel sera versé * le montant des coûts fixes * * @return int */ public function getFixedCostAccount() { return $this->fixedCostAccount; } /** * Retourne le numéro de compte sur lequel sera versé * le montant des frais d'envoi * * @return int */ public function getShippingCostAccount() { return $this->shippingCostAccount; } /** * Assigne la lange par défaut (AZ_az = pays_langue) * * @param string $defaultLang * @return boolean */ public function setDefaultLang($defaultLang) { if ($this->_locked) return false; if (!preg_match('#^[A-Z]{2}_[a-z]{2}$#',$defaultLang)) return false; $this->defaultLang=$defaultLang; return true; } /** * Retourne la langue par défaut * * @return string */ public function getDefaultLang() { return $this->defaultLang; } /** * Défini le type d'interface de paiement * * @param string $media * @return boolean */ public function setMedia($media) { if ($this->_locked) return false; if (!preg_match('#^[A-Z]+$#',$media)) return false; $this->media=$media; return true; } /** * Retourne le type d'interface de paiement * * @return string */ public function getMedia() { return $this->media; } /** * Défini le public visé * * @param string $rating * @return boolean */ public function setRating($rating) { if ($this->_locked) return false; $rating = trim(substr($rating,0,HIPAY_MAPI_MAX_RATING_LENGTH)); if ($rating=='') return false; $this->rating=$rating; return true; } /** * Retourne le type de public visé * * @return string */ public function getRating() { return $this->rating; } /** * Défini si le paiement est simple ou récurrent * * @param int $paymentMethod * @return boolean */ public function setPaymentMethod($paymentMethod) { if ($this->_locked) { return false; } $paymentMethod = (int)$paymentMethod; if ($paymentMethod!=HIPAY_MAPI_METHOD_SIMPLE && $paymentMethod!=HIPAY_MAPI_METHOD_MULTI) return false; $this->paymentMethod=$paymentMethod; return true; } /** * Retourne le type de paiement (simple ou récurrent) * * @return int */ public function getPaymentMethod() { return $this->paymentMethod; } /** * détermine si la valeur du champ cgu est checkée par défaut * * @return int */ public function getCguChecked() { return $this->cguChecked; } /** * Défini si la case cgu est cochée ou non par défaut * * @param boolean $value * @return int */ public function setCguChecked($value) { if($value === true || $value === '1') $value=1; if($value === false || $value === '0') $value=0; if ($value !== 0 && $value !== 1) return false; $this->cguChecked = $value; return true; } /** * Défini le délai de capture * * @param int $captureDay * @return boolean */ public function setCaptureDay($captureDay) { if ($this->_locked) return false; $captureDay = (int)$captureDay; if (($captureDay!=HIPAY_MAPI_CAPTURE_MANUAL && $captureDay!=HIPAY_MAPI_CAPTURE_IMMEDIATE && $captureDay<=0) || $captureDay>HIPAY_MAPI_CAPTURE_MAX_DAYS) return false; $this->captureDay=$captureDay; return true; } /** * Retourne le délai de capture * * @return int */ public function getCaptureDay() { return $this->captureDay; } /** * Défini la devise * * @param string $currency * @return boolean */ public function setCurrency($currency) { if ($this->_locked) return false; if (!preg_match('#^[A-Z]{3}$#',$currency)) return false; $this->currency = $currency; return true; } /** * Retourne la devise * * @return string */ public function getCurrency() { return $this->currency; } /** * Défini l'identifiant du groupe statistique auquel appartient ce paiement * * @param int $statsGroupId * @return boolean */ public function setStatsGroupId($statsGroupId) { if ($this->_locked) return false; $statsGroupId=(int)$statsGroupId; if ($statsGroupId<0) return false; $this->statsGroupId=$statsGroupId; return true; } /** * Retourne l'identifiant du groupe statistique auquel appartient ce paiement * * @return int */ public function getStatsGroupId() { return $this->statsGroupId; } /** * Défini l'identifiant de cette vente chez le marchand * * @param string $idForMerchant * @return boolean */ public function setIdForMerchant($idForMerchant) { if ($this->_locked) return false; $this->idForMerchant=$idForMerchant; return true; } /** * Retourne l'identifiant de la vente pour le marchand * * @return string */ public function getIdForMerchant() { return $this->idForMerchant; } /** * Défini l'identifiant du site marchand * * @param int $merchantSiteId * @return boolean */ public function setMerchantSiteId($merchantSiteId) { if ($this->_locked) return false; $merchantSiteId=(int)$merchantSiteId; if ($merchantSiteId<0) return false; $this->merchantSiteId=$merchantSiteId; return true; } /** * Retourne l'identifiant du site marchand * * @return int */ public function getMerchantSiteId() { return $this->merchantSiteId; } /** * Assigne des données marchandes * * @param string $merchantDatas * @return boolean */ public function setMerchantDatas($key,$merchantDatas) { if ($this->_locked) return false; if ($key=='') return false; $merchantDatas=substr($merchantDatas,0,HIPAY_MAPI_MAX_MDATAS_LENGTH); $this->merchantDatas[$key]=$merchantDatas; return true; } /** * Retourne les données marchandes * * @return array */ public function getMerchantDatas() { return $this->merchantDatas; } /** * Assigne l'url à appeller si le paiement est ok * * @param string $url_ok * @return unknown */ public function setUrlOk($url_ok) { if ($this->_locked) return false; $url_ok = trim($url_ok); if (!HIPAY_MAPI_UTILS::checkURL($url_ok) && $url_ok!='') return false; $this->url_ok=$url_ok; return true; } /** * Retourne l'url_ok * * @return string */ public function getUrlOk() { return $this->url_ok; } /** * Assigne l'url à appeller si le paiement n'est pas ok * * @param string $url_nok * @return unknown */ public function setUrlNok($url_nok) { if ($this->_locked) return false; $url_nok = trim($url_nok); if (!HIPAY_MAPI_UTILS::checkURL($url_nok) && $url_nok!='') return false; $this->url_nok=$url_nok; return true; } /** * Retourne l'url_nok * * @return string */ public function getUrlNok() { return $this->url_nok; } /** * Assigne l'url à appeller si le paiement est annulé * * @param string $url_cancel * @return boolean */ public function setUrlCancel($url_cancel) { if ($this->_locked) return false; $url_cancel = trim($url_cancel); if (!HIPAY_MAPI_UTILS::checkURL($url_cancel) && $url_cancel!='') return false; $this->url_cancel=$url_cancel; return true; } /** * Retourne l'url_cancel * * @return string */ public function getUrlCancel() { return $this->url_cancel; } /** * Assigne l'url à appeller pour notifier le paiement * * @param string $url_cancel * @return boolean */ public function setUrlAck($url_ack) { if ($this->_locked) return false; $url_ack = trim($url_ack); if (!HIPAY_MAPI_UTILS::checkURL($url_ack) && $url_ack!='') return false; $this->url_ack=$url_ack; return true; } /** * Retourne l'url_ack * * @return string */ public function getUrlAck() { return $this->url_ack; } /** * Assigne le mot clé d'acquittement * * @param string $ack_wd * @return boolean */ public function setAckWd($ack_wd) { if ($this->_locked) return false; $ack_wd=trim($ack_wd); if (strlen($ack_wd)>HIPAY_MAPI_MAX_ACKWD_LENGTH) return false; $this->ack_wd=$ack_wd; return true; } /** * Retourne le mot clé d'acquittement * * @return string */ public function getAckWd() { return $this->ack_wd; } /** * Assigne l'adresse email de notification de paiement * * @param string $email_ack * @return boolean */ public function setEmailAck($email_ack) { if ($this->_locked) return false; $email_ack=trim($email_ack); if (strlen($email_ack)>HIPAY_MAPI_MAX_ACKMAIL_LENGTH || (!HIPAY_MAPI_UTILS::checkemail($email_ack) && $email_ack!='')) return false; $this->email_ack=$email_ack; return true; } /** * Retourne l'email de notification * * @return string */ public function getEmailAck() { return $this->email_ack; } /** * Assigne la couleur de fond de l'interface (#XXXXXX) * * @param string $bg_color * @return boolean */ public function setBackgroundColor($bg_color) { if ($this->_locked) return false; $bg_color = trim($bg_color); if (!preg_match('#^\#([0-9a-f]){6}$#i', $bg_color) && $bg_color != '') return false; $this->bg_color = $bg_color; return true; } /** * Retourne la couleur de fond de l'interface * * @return string */ public function getBackgroundColor() { return $this->bg_color; } /** * Assigne l'url du logo du marchand * * @param string $logo_url * @return boolean */ public function setLogoUrl($logo_url) { if ($this->_locked) return false; $logo_url = trim($logo_url); if (!HIPAY_MAPI_UTILS::checkURL($logo_url) && $logo_url!='') return false; $this->logo_url=$logo_url; return true; } /** * Retourne l'url du logo du marchand * * @return string */ public function getLogoUrl() { return $this->logo_url; } /** * Assigne le login par défaut à utiliser pour le paiement * * @param string $login * @return boolean */ public function setIssuerAccountLogin($login) { if ($this->_locked) return false; $login = trim(strtolower($login)); $this->issuerAccountLogin=$login; return true; } /** * Retourne le login du payeur par défaut * * @return string */ public function getIssuerAccountLogin() { return $this->issuerAccountLogin; } /** * Assigne une description alternative du marchand * * @param string $desc * @return boolean */ public function setMerchantDescription($desc) { if ($this->_locked) return false; $desc = trim($desc); $this->merchantDescription=$desc; return true; } /** * Retourne le login du payeur par défaut * * @return string */ public function getMerchantDescription() { return $this->merchantDescription; } /** * Assigne l'identifiant de boutique * * @param integer $name * @return boolean */ public function setShopId($id) { if ($this->_locked) return false; $this->shopId=$id; return true; } /** * Retourne l'id de boutique * * @return integer */ public function getShopId() { return $this->shopId; } /** * set informations about the order * * @param $informations */ public function setInformations($informations) { $this->informations = $informations; } /** * return informations about the order * * @return String */ public function getInformations() { return $this->informations; } /** * Assigne la locale à utiliser sur les pages de paiement * * @param string $locale * @return boolean */ public function setLocale($locale) { if ($this->_locked) return false; $locale = trim($locale); if (strlen($locale) != 5) return false; if (! preg_match("/^[a-z]{2}_[A-Z]{2}$/", $locale)) return false; $this->locale=$locale; return true; } /** * Retourne la locale * * @return string */ public function getLocale() { return $this->locale; } /** * Vérifie que l'objet est correctement initialisé * * @return boolean */ public function check() { if ($this->login=='') throw new Exception('Nom d\'utilisateur manquant'); if ($this->itemAccount<=0 || $this->taxAccount<=0 || $this->insuranceAccount <=0 || $this->fixedCostAccount<=0 || $this->shippingCostAccount<=0) throw new Exception('Numéros de compte invalides'); if ($this->rating=='') throw new Exception('Type de public visé invalide'); if ($this->paymentMethod<0) throw new Exception('Type de paiement invalide'); if ($this->captureDay==-100) throw new Exception('Délai de capture invalide '); if ($this->currency=='') throw new Exception('Devise non-définie'); if ($this->idForMerchant<0) throw new Exception('ID chez le marchand manquant'); if ($this->idForMerchant>0) if ($this->password=='') throw new Exception('Mot de passe manquant'); if ($this->statsGroupId<0) throw new Exception('ID groupe est négatif'); if ($this->merchantSiteId<0) throw new Exception('ID du site marchand manquant'); return true; } protected function init() { $this->login=''; $this->password=''; $this->itemAccount=0; $this->taxAccount=0; $this->insuranceAccount=0; $this->fixedCostAccount=0; $this->shippingCostAccount=0; $this->defaultLang=HIPAY_MAPI_DEFLANG; $this->media=HIPAY_MAPI_DEFMEDIA; $this->rating=''; $this->paymentMethod=-1; $this->captureDay=-100; $this->currency=''; $this->idForMerchant=-1; $this->statsGroupId=0; $this->merchantSiteId=-1; $this->merchantDatas=array(); $this->url_ok=''; $this->url_nok=''; $this->url_cancel=''; $this->url_ack=''; $this->ack_wd=''; $this->email_ack=''; $this->bg_color=''; $this->logo_url=''; $this->issuerAccountLogin=''; $this->locale=''; $this->cguChecked=0; } function __construct() { $this->init(); parent::__construct(); } } ?>PK\?[7default/plugins/payment/hipay/mapi/mapi_installment.phpnu[_locked) return false; $price = sprintf('%.02f',(float)$price); if ($price<0) return false; $this->price=$price; return true; } /** * Retourne le montant HT * * @return float */ public function getPrice() { return $this->price; } /** * Défini s'il s'agit du premier paiement ou des suivants et le délai de déclenchement * * @param boolean $first * @param string $paymentDelay * @return boolean */ public function setFirst($first,$paymentDelay) { if ($this->_locked) return false; if (!is_bool($first)) return false; $paymentDelay=trim($paymentDelay); if ($first) { if (!preg_match("#[0-9]+[HDM]#",$paymentDelay)) { return false; } } else { if (!preg_match("#[0-9]+[DM]#",$paymentDelay)) { return false; } } $num = (int)substr($paymentDelay,0,strlen($paymentDelay)-1); if (($num<1 && !$first) || ($num<0 && $first) || $num>365) { return false; } $this->first=$first; $this->paymentDelay=$paymentDelay; return true; } /** * Assigne les taxes s'appliquant à ce paiement * * @param array $tax * @return boolean */ public function setTax($tax) { if ($this->_locked) return false; if (!HIPAY_MAPI_UTILS::is_an_array_of($tax,'HIPAY_MAPI_Tax')) return false; foreach ($tax as $obj) $this->tax[]= clone $obj; return true; } /** * assigne le timestamp du premier paiement ou des paiements récurrents * */ public function setDelayTS( $baseTS=0 ) { if( (int)$baseTS <= 0 ) { $baseTS = time(); } switch( substr($this->paymentDelay, -1, 1) ) { case 'd': case 'D': $unit='day'; break; case 'm': case 'M': $unit='month'; break; case 'h': case 'H': default : $unit='hour'; break; } $this->_delayTS = strtotime( '+'.substr($this->paymentDelay, 0, -1).' '.$unit, $baseTS ); } /** * Retourne les taxes s'appliquant à ce paiement * * @return array */ public function getTax() { return $this->tax; } /** * Retourne s'il s'agit du premier paiement * * @return boolean */ public function getFirst() { return $this->first; } /** * Retourne le délai de déclenchement * * @return string */ public function getPaymentDelay() { return $this->paymentDelay; } /** * retourne le timestamp du premier paiement * */ public function getDelayTS() { return $this->_delayTS; } /** * Vérifie si l'objet est correctement initialisé * * @return float */ public function check() { if ($this->price<0) throw new Exception('Montant invalide ou pas initilisé'); if (!HIPAY_MAPI_UTILS::is_an_array_of($this->tax,'HIPAY_MAPI_Tax')) throw new Exception('Taxes invalides ou pas initialisées'); foreach($this->tax as $obj) { if (!$obj->check()) return false; } if (!is_bool($this->first)) throw new Exception('Premier paiement ou suivant n\'est pas initialisé'); return true; } protected function init() { $this->price = -1; $this->tax = array(); $this->first = ''; $this->paymentDelay = ''; $this->_delayTS = ''; } function __construct() { $this->init(); parent::__construct(); } } ?>PK\$default/plugins/payment/bluesnap.phpnu[addSelect("testing") ->setLabel("test Mode Enabled"); $s->addOption("Live account", self::MODE_LIVE); $s->addOption("Sandbox account", self::MODE_SANDBOX); // $s->addOption("Account in test mode", self::MODE_TEST); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('bluesnap_contract_id', "BlueSnap Contract ID", "You must enter the contract id of BlueSnap product.
      BlueSnap contract must have the same settings as amember product.")); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form((($this->getConfig('testing') == self::MODE_SANDBOX) ? self::TESTING_URL : self::URL)); $a->contractId = $invoice->getItem(0)->getBillingPlanData("bluesnap_contract_id"); $a->custom1 = $invoice->public_id; $a->member_id = $invoice->user_id; $a->currency = strtoupper($invoice->currency); $a->firstName = $invoice->getFirstName(); $a->lastName = $invoice->getLastName(); $a->email = $invoice->getEmail(); $a->overridePrice = sprintf("%.2f", $invoice->first_total); $a->overrideRecurringPrice = sprintf("%.2f", $invoice->second_total); if ($this->getConfig('testing') == self::MODE_TEST) { $a->testMode = Y; } $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch ($request->get("transactionType")) { case Am_Paysystem_Transaction_Bluesnap::CHARGE : case Am_Paysystem_Transaction_Bluesnap::RECURRING : case Am_Paysystem_Transaction_Bluesnap::AUTH_ONLY : return new Am_Paysystem_Transaction_Bluesnap_Charge($this, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Bluesnap::CANCELLATION : return new Am_Paysystem_Transaction_Bluesnap_Cancellation($this, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Bluesnap::REFUND : return new Am_Paysystem_Transaction_Bluesnap_Refund($this, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Bluesnap::CANCELLATION_REFUND : return new Am_Paysystem_Transaction_Bluesnap_Cancellation_Refund($this, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Bluesnap::CONTRACT_CHANGE : return new Am_Paysystem_Transaction_Bluesnap_Contract_Change($this, $request, $response, $invokeArgs); default : return null; } } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<BlueSnap payment plugin configuration Up to date instructions can be found at http://www.amember.com/docs/Plimus_Plugin_Configuration CUT; } public function canAutoCreate() { return true; } } class Am_Paysystem_Transaction_Bluesnap extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name_f' => 'firstName', 'name_l' => 'lastName', 'email' => 'email', 'street' => 'address1', 'zip' => 'zipCode', 'state' => 'state', 'country' => 'country', 'city' => 'city', 'user_external_id' => 'accountId', 'invoice_external_id' => 'accountId', ); const REFUND = 'REFUND'; const CHARGE = 'CHARGE'; const RECURRING = 'RECURRING'; const AUTH_ONLY = 'AUTH_ONLY'; const CANCELLATION_REFUND = 'CANCELLATION_REFUND'; const CANCELLATION = 'CANCELLATION'; const CONTRACT_CHANGE = 'CONTRACT_CHANGE'; protected $ip = array( array('62.216.234.196', '62.216.234.222'), array('72.20.107.242', '72.20.107.250'), array('209.128.93.97', '209.128.93.110'), array('209.128.93.225', '209.128.93.255'), '62.216.234.216', '209.128.93.254', '209.128.93.98', '38.99.111.60', '38.99.111.160', '209.128.93.232', '62.216.234.196', '38.99.111.50', '38.99.111.150' ); public function autoCreateGetProducts() { $item_number = $this->request->get('contr_id', $this->request->get('contractId')); if (empty($item_number)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('bluesnap_contract_id', $item_number); if ($billing_plan) return array($billing_plan->getProduct()); } public function findInvoiceId() { return $this->request->get('custom1'); } public function getUniqId() { return $this->request->get("referenceNumber"); } public function validateSource() { $this->_checkIp($this->ip); if (($this->plugin->getConfig('testing') != Am_Paysystem_Bluesnap::MODE_TEST) && ($this->request->get('testMode') == 'Y')) { throw new Am_Exception_Paysystem_TransactionInvalid("Received test IPN message but test mode is not enabled!"); } return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Bluesnap_Charge extends Am_Paysystem_Transaction_Bluesnap { public function validateTerms() { $amount = ($this->invoice->currency == 'USD') ? $this->request->get('invoiceAmountUSD') : $this->request->get('invoiceChargeAmount'); $message = $this->request->get('transactionType'); return ($amount == (($message == self::CHARGE) || ($message == self::AUTH_ONLY) ? $this->invoice->first_total : $this->invoice->second_total)); } public function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_Bluesnap_Cancellation extends Am_Paysystem_Transaction_Bluesnap { public function processValidated() { $this->invoice->setCancelled(true); } } class Am_Paysystem_Transaction_Bluesnap_Refund extends Am_Paysystem_Transaction_Bluesnap { public function processValidated() { $this->invoice->addRefund($this, $this->getReceiptId(), $this->getAmount()); } } class Am_Paysystem_Transaction_Bluesnap_Cancellation_Refund extends Am_Paysystem_Transaction_Bluesnap { public function processValidated() { $this->invoice->setCancelled(true); $this->invoice->addRefund($this, $this->getReceiptId(), $this->getAmount()); } } class Am_Paysystem_Transaction_Bluesnap_Contract_Change extends Am_Paysystem_Transaction_Bluesnap { public function processValidated() { throw new Am_Exception_Paysystem_NotImplemented("Not implemented"); } }PK\XX&default/plugins/payment/dineromail.phpnu[addText("email")->setLabel("Your E-mail\n" . 'received from DineroMail'); $form->addText("merchant")->setLabel("Your merchant identifier\n" . 'received from DineroMail'); $form->addText("PIN")->setLabel("Your Pin\n" . 'recieved from DineroMail'); $form->addText("secret")->setLabel("Your password\n" . 'DM -> My account -> Config Ipn -> Password'); $form->addSelect("country", array(), array('options' => array( '1' => 'Argentina', '2' => 'Brazil', '3' => 'Chile', '4' => 'Mexico' )))->setLabel('Merchant Country'); $form->addSelect("language", array(), array('options' => array( 'en' => 'English', 'es' => 'Spanish', 'pt' => 'Portuguese' )))->setLabel('Site Language'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $vars = array( 'MERCHANT' => $this->getConfig('email'), 'COUNTRY_ID' => $this->getConfig('country'), 'PAYMENT_METHOD_AVAILABLE' => 'all', 'TRANSACTION_ID' => $invoice->public_id, ); $i = '1'; foreach($invoice->getItems() as $item){ //Creating new format without dot for $item->first_price $price = str_replace('.','',$item->first_total); $vars['ITEM_NAME_'.$i] = $item->item_title; $vars['ITEM_CODE_'.$i] = $item->item_id; $vars['ITEM_AMMOUNT_'.$i] = $price; $vars['ITEM_QUANTITY_'.$i] = $item->qty; $vars['ITEM_CURRENCY_'.$i] = $item->currency; $i++; } $vars['CURRENCY'] = strtoupper($invoice->currency); foreach($vars as $k=>$v){ $a->__set($k,$v); } $a->__set('BUYER_FNAME', $invoice->getFirstName()); $a->__set('BUYER_LNAME', $invoice->getLastName()); $a->__set('BUYER_EMAIL', $invoice->getEmail()); $a->__set('BUYER_PHONE', $invoice->getPhone()); $a->__set('BUYER_STREET', $invoice->getStreet()); $a->__set('BUYER_STATE', $invoice->getState()); $a->__set('BUYER_CITY', $invoice->getCity()); $a->__set('BUYER_COUNTRY', $invoice->getCountry()); $a->__set('BUYER_ZIP_CODE', $invoice->getZip()); $a->__set('BUYER_CITY', $invoice->getCity()); $a->__set('BUYER_STATE', $invoice->getState()); $a->__set('LANGUAGE', $this->getConfig('language', 'es')); $result->setAction($a); } function calculateHash($vars){ $hash_src = ''; foreach($vars as $k=>$v){ if(is_array($v)){ foreach($v as $vv){ $hash_src .= strlen(htmlentities($vv)).htmlentities($vv); } }else $hash_src .= strlen(htmlentities($v)).htmlentities($v); } return hash_hmac('md5', $hash_src, $this->getConfig('secret')); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Dineromail($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOTHING; } public function getSupportedCurrencies() { return array('ARS', 'MXN', 'CLP','BRL' ,'USD'); } function getReadme(){ return <<DineroMail plugin configuration Configure IPN url in your account: %root_surl%/amember/payment/dineromail/ipn CUT; } } class Am_Paysystem_Transaction_Dineromail extends Am_Paysystem_Transaction_Incoming { const SUCCESS = '1'; public function findInvoiceId() { $doc = $this->getDoc(); $message = $doc->xpath('//OPERACION/NUMTRANSACCION'); $inv_id = array_shift($message); return $inv_id; } public function getUniqId() { $doc = $this->getDoc(); $message = $doc->xpath('//OPERACION/ID'); $uni_id = array_shift($message); return $uni_id; } public function validateSource() { $ping = Dineromail_Ping::createFromRequest($this->request); $dineromail_request = new Dineromail_Request($this->plugin->getConfing('merchant'), $this->plugin->getConfig('secret'), $ping->getOperationList()); $this->response = $dineromail_request->getPayments(); $doc = $this->getDoc(); $message = $doc->xpath('//OPERACION/NUMTRANSACCION'); if(false === $message){ throw new Am_Exception_Paysystem_TransactionSource('Recieved transaction id is empty'); } $numtransaccion = array_shift($message); if($numtransaccion != $this->getInvoice()->public_id){ throw new Am_Exception_Paysystem_TransactionSource('Recieved transaction id is not equal to sended'); } return true; } public function validateStatus() { $doc = $this->getDoc(); $message = $doc->xpath('//ESTADOREPORTE'); if (false === $message) { throw new Am_Exception_Paysystem_TransactionInvalid('Malformed response.'); } $code = array_shift($message); if (self::SUCCESS != $code) { throw new Am_Exception_Paysystem_TransactionInvalid('Error response with code: ' . $code); } return true; } public function validateTerms() { $doc = $this->getDoc(); $message = $doc->xpath('//OPERACION/MONTO'); $monto = array_shift($message); $this->assertAmount($this->invoice->first_total, $monto); return true; } private function getDoc() { return new SimpleXMLElement($this->response->getBody()); } } class Dineromail_Ping { const REQUEST_PARAM = 'Notification'; private $data; public function __construct($data) { $this->_data = new DOMDocument($data); $this->_data->loadXML($data); } public function getOperationList() { $xpath = new DOMXPath($this->_data); $ops = $xpath->query('//operacion/id/text()'); $result = array(); for($i = 0; $i<$ops->length; $i++){ $result[] = $ops->item($i)->nodeValue; } return $result; } public static function createFromRequest(Am_Mvc_Request $request) { return new self($request->getParam(self::REQUEST_PARAM)); } } class Dineromail_Request { const REQUEST_PARAM = 'DATA'; const SUCCESS = '1'; const URI = 'https://argentina.dineromail.com/Vender/Consulta_IPN.asp'; private $_accountNumber; private $_password; private $_payments; private $_response; public function __construct($accountNumber, $password, array $payments) { $this->_accountNumber = $accountNumber; $this->_password = $password; $this->_payments = $payments; } public function getPayments() { $this->_makeRequest(); return $this->_response; } private function _generatePost() { $res = ''; $res.= ''.$this->_accountNumber.''; $res.= ''; $res.= ''; $res.= ''.$this->_password.''; $res.= '1'; $res.= ''; foreach($this->_payments as $payment) { $res.= ''.$payment.''; } $res.= ''; $res.= ''; $res.= ''; $res.= ''; return $res; } private function _makeRequest() { $request = new Am_HttpRequest($this->URI, Am_HttpRequest::METHOD_POST); $request->addPostParameter(self::REQUEST_PARAM, $this->_generatePost()); $response = $request->send(); $this->_response = $response; } } PK\ۄ8{SS*default/plugins/payment/checkout-enets.phpnu[addText('merchantid') ->setLabel("Merchant ID\n" . 'This value is provided by gateway and this is used to authenticate a merchant.'); $form->addText('merchantpwd') ->setLabel("Merchant Password\n" . 'This value is provided by gateway and this is used to authenticate a merchant.'); $form->addText('gatewayurl')->setLabel('Gateway URL'); } public function getCurrencyCode(Invocie $invoice) { return array_search($invoice->currency, $this->getSupportedCurrencies())+1; } public function getSupportedCurrencies() { return array('SGD', 'HKD'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $xml = new SimpleXMLElement(''); $transactiondetails = $xml->addChild('transactiondetails'); $transactiondetails->addChild('merchantcode', $this->getConfig('merchantid')); $transactiondetails->addChild('merchantpwd', $this->getConfig('merchantpwd')); $transactiondetails->addChild('trackid', $invoice->public_id); $transactiondetails->addChild('customerip', $request->getClientIp()); $transactiondetails->addChild('udf1', $invoice->public_id); $transactiondetails->addChild('customerid', $invoice->getLogin()); $paymentdetails = $xml->addChild('paymentdetails'); $paymentdetails->addChild('paysource', 'enets'); $paymentdetails->addChild('amount', $invoice->first_total); $paymentdetails->addChild('currency', $invoice->currency); $paymentdetails->addChild('actioncode', 1); $notificationurls = $xml->addChild('notificationurls'); $notificationurls->addChild('successurl', $this->getReturnUrl()); $notificationurls->addChild('failurl', $this->getCancelUrl()); $shippingdetails = $xml->addChild('shippingdetails'); foreach(array( 'ship_address' => $invoice->getStreet(), 'ship_email' => $invoice->getEmail(), 'ship_postal' => $invoice->getZip(), 'ship_address2' => $invoice->getStreet1(), 'ship_city' => $invoice->getCity(), 'ship_state' => $invoice->getState(), 'ship_phone' => $invoice->getPhone(), 'ship_country' => $invoice->getCountry() ) as $k=>$v) $shippingdetails->addChild ($k, $v); $req = new Am_HttpRequest($this->getConfig('gatewayurl'), Am_HttpRequest::METHOD_POST); $req->setHeader('Content-type: text/xml; charset=utf-8') ->setHeader('Connection:close') ->setBody($xml->asXML()); $response = $req->send(); $resxml = @simplexml_load_string($response->getBody()); if(!($resxml instanceof SimpleXMLElement)) throw new Am_Exception_InputError('Incorrect Gateway response received!'); if(($paymenturl = (string)$resxml->transactionresponse->paymenturl)){ $a = new Am_Paysystem_Action_Redirect($paymenturl); $result->setAction($a); }else{ throw new Am_Exception_InputError('Incorrect Gateway response received! Got: '.((string) $resxml->responsedesc)); } } function getReadme(){ return <<xml = simplexml_load_string($request->getRawBody()); } public function getUniqId() { return (string)$this->xml->transactionresponse->transid; } public function findInvoiceId() { return (string) $this->xml->transactionresponse->udf1; } public function validateSource() { return true; } public function validateStatus() { return ((string) $this->xml->transactionresponse->result) == 'paid'; } public function validateTerms() { return true; } }PK\d<33,default/plugins/payment/myshortcart-alfa.phpnu[defaultTitle = "ClickBank"; $this->defaultDescription = ___("pay using credit card or PayPal"); parent::__construct($di, $config); $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'clickbank_product_id', 'ClickBank Product#', 'you have to create similar product in ClickBank and enter its number here' ,array(/*,'required'*/) ) /*new Am_CustomFieldSelect( 'clickbank_product_id', 'ClickBank Product#', 'you have to create similar product in ClickBank and enter its number here', 'required', array('options' => array('' => '-- Please select --', '11' => '#11', '22' => '#22')))*/ ); $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'clickbank_skin_id', 'ClickBank Skin ID', 'an ID if your custom skin (cbskin parameter) for an order page' ) ); } public function init() { parent::init(); $this->getDi()->blocks->add(new Am_Block('thanks/success', 'ClickBank Statement', 'clickbank-statement', $this, array($this, 'renederStatement'))); } public function renederStatement(Am_View $v) { if (isset($v->invoice) && $v->invoice->paysys_id == $this->getId()) { $line1 = ___('Your credit card statement will show a charge from ClickBank or CLKBANK*COM'); $line2 = ___("ClickBank is the retailer of products on this site. CLICKBANK® is a registered trademark of Click Sales, Inc., a Delaware corporation located at 917 S. Lusk Street, Suite 200, Boise Idaho, 83706, USA and used by permission. ClickBank's role as retailer does not constitute an endorsement, approval or review of these products or any claim, statement or opinion used in promotion of these products."); return <<

      $line1

      $line2

      CUT; } } public function isConfigured() { return strlen($this->getConfig('account')); } public function canAutoCreate() { return true; } public function isNotAcceptableForInvoice(Invoice $invoice) { foreach ($invoice->getItems() as $item) { /* @var $item InvoiceItem */ if (!$item->getBillingPlanData('clickbank_product_id')) return "item [" . $item->item_title . "] has no related ClickBank product configured"; } } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('account', array('size' => 20, 'maxlength' => 16)) ->setLabel("ClickBank Account Nickname\n". "your ClickBank username") ->addRule('required'); $form->addPassword('secret', array('size' => 20, 'maxlength' => 16)) ->setLabel("Secret Key\n". "defined at clickbank.com -> login -> SETTINGS -> My Site -> Advanced Tools (edit)") ->addRule('required'); $form->addText('clerk_key', array('size' => 50)) ->setLabel("ClickBank Clerk API Key\n". "defined at clickbank.com -> login -> SETTINGS -> My Account -> Clerk API Keys (edit)") ->addRule('required'); $form->addText('dev_key', array('size' => 50)) ->setLabel("Developer API Key\n". "defined at clickbank.com -> login -> SETTINGS -> My Account -> Developer API Keys (edit)") ->addRule('required'); $form->addAdvCheckbox('use_cart')->setLabel("Use Clickbank cart interface\n" . "Allow to select more then one product on signup page"); } public function _process($invoice, $request, $result) { if($this->getConfig('use_cart')) return $this->_processCart ($invoice, $request, $result); return $this->_processRegular($invoice, $request, $result); } public function _processRegular($invoice, $request, $result) { $a = new Am_Paysystem_Action_Redirect($this->url); $a->link = sprintf('%s/%s/%s', $this->getConfig('account'), $this->invoice->getItem(0)->getBillingPlanData('clickbank_product_id'), $this->invoice->getLineDescription() ); $a->seed = $invoice->public_id; $a->cbskin = $this->invoice->getItem(0)->getBillingPlanData('clickbank_skin_id'); $a->name = $invoice->getName(); $a->email = $invoice->getEmail(); $a->country = $invoice->getCountry(); $a->zipcode = $invoice->getZip(); $a->filterEmpty(); $result->setAction($a); } function _processCart($invoice, $request, $result) { $cart = array( 'skipSummary' => true, 'editQuantity' => false ); $items = array(); foreach($invoice->getItems() as $item) { $items[] = array( 'sku' => $item->getBillingPlanData('clickbank_product_id'), 'qty' => $item->qty ); } $cart['items'] = $items; $a = new Am_Paysystem_Action_Redirect(sprintf($this->cartUrl, $this->getConfig('account'))); $a->cbcart = json_encode($cart); $a->seed = $invoice->public_id; $a->name = $invoice->getName(); $a->email = $invoice->getEmail(); $a->country = $invoice->getCountry(); $a->zipcode = $invoice->getZip(); $a->filterEmpty(); $result->setAction($a); } public function directAction($request, $response, $invokeArgs) { try { return parent::directAction($request, $response, $invokeArgs); } catch (Exception $e) { if ($request->getActionName() == 'ipn') { $response->setBody('ERROR')->setHttpResponseCode(200); } else { throw $e; } } } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $request = $this->createHttpRequest(); $ps = new stdclass; $ps->type = 'cncl'; $ps->reason = 'ticket.type.cancel.7'; $ps->comment = 'cancellation request from aMember user ('.$invoice->getLogin().')'; $get_params = http_build_query((array)$ps, '', '&'); $payment = current($invoice->getPaymentRecords()); $request->setUrl($s='https://api.clickbank.com/rest/1.3/tickets/'. Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($invoice->pk())."?$get_params"); $request->setHeader(array( 'Content-Length' => '0', 'Accept' => 'application/xml', 'Authorization' => $this->getConfig('dev_key').':'.$this->getConfig('clerk_key'))); $request->setMethod(Am_HttpRequest::METHOD_POST); $this->logRequest($request); $request->setMethod('POST'); $response = $request->send(); $this->logResponse($response); if( $response->getStatus() != 200 && $response->getBody() != 'Subscription already canceled') throw new Am_Exception_InputError("An error occurred while cancellation request"); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $request = $this->createHttpRequest(); $ps = new stdclass; $ps->type = 'rfnd'; $ps->reason = 'ticket.type.refund.8'; $ps->comment = 'refund request for aMember user ('.$payment->getUser()->login.')'; if(doubleval($amount) == doubleval($payment->amount)) { $ps->refundType = 'FULL'; } else { $ps->refundType = 'PARTIAL_AMOUNT'; $ps->refundAmount = $amount; } $get_params = http_build_query((array)$ps, '', '&'); $request->setUrl($s='https://api.clickbank.com/rest/1.3/tickets/'. $payment->receipt_id."?$get_params"); $request->setHeader(array( 'Content-Length' => '0', 'Accept' => 'application/xml', 'Authorization' => $this->getConfig('dev_key').':'.$this->getConfig('clerk_key'))); $request->setMethod(Am_HttpRequest::METHOD_POST); $this->logRequest($request); $request->setMethod('POST'); $response = $request->send(); $this->logResponse($response); if( $response->getStatus() != 200 && $response->getBody() != 'Refund ticket already open') throw new Am_Exception_InputError("An error occurred during refund request"); $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id.'-clickbank-refund'); $result->setSuccess(); } public function createTransaction($request, $response, array $invokeArgs) { if ($request->getParam('ctransreceipt')) { return new Am_Paysystem_Transaction_Clickbank21($this, $request, $response, $invokeArgs); } else { return new Am_Paysystem_Transaction_Clickbank60($this, $request, $response, $invokeArgs); } } public function createThanksTransaction( $request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Clickbank_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return << Setup/Configuration -> Plugins and enable "ClickBank" payment plugin. 2. Configure plugin: go to aMember CP -> Setup/Configuration -> ClickBank and configure it. 3. For each your product and billing plan, configure ClickBank Product ID at aMember CP -> Manage Products -> Edit 4. Configure ThankYou Page URL in your ClickBank account (for each Product) to this URL: %root_url%/payment/c-b/thanks 5. Configure Instant Notification URL in your ClickBank account (SETTINGS -> My Site -> Advanced Tools (edit)) to this URL: %root_url%/payment/c-b/ipn Set version to 6.0 6. Run a test transaction to ensure everything is working correctly. CUT; } } class Am_Paysystem_Transaction_Clickbank21 extends Am_Paysystem_Transaction_Incoming { // payment const SALE = "SALE"; const TEST = "TEST"; const TEST_SALE = "TEST_SALE"; const BILL = "BILL"; const TEST_BILL = "TEST_BILL"; // refund const RFND = "RFND"; const TEST_RFND = "TEST_RFND"; const CGBK = "CGBK"; const TEST_CGBK = "TEST_CGBK"; const INSF = "INSF"; const TEST_INSF = "TEST_INSF"; // cancel const CANCEL_REBILL = "CANCEL-REBILL"; const CANCEL_TEST_REBILL = "CANCEL-TEST-REBILL"; // cancel const UNCANCEL_REBILL = "UNCANCEL-REBILL"; const UNCANCEL_TEST_REBILL = "UNCANCEL-TEST-REBILL"; protected $_autoCreateMap = array( 'name' => 'ccustname', 'country' => 'ccustcc', 'state' => 'ccuststate', 'email' => 'ccustemail', 'user_external_id' => 'ccustemail', 'invoice_external_id' => 'ccustemail', ); public function findTime() { //clickbank timezone $dtc = new DateTime('now', new DateTimeZone('Canada/Central')); //local timezone $dtl = new DateTime('now', new DateTimeZone(date_default_timezone_get())); $diff = $dtc->getOffset() - $dtl->getOffset(); $dt = new DateTime('@' . ($this->request->getInt('ctranstime') - $diff)); $dt->setTimezone(new DateTimeZone('Canada/Central')); return $dt; } public function getUniqId() { return $this->request->get('ctransreceipt'); } public function getReceiptId() { return $this->request->get('ctransreceipt'); } public function getAmount() { return moneyRound($this->request->get('ctransamount')); } public function findInvoiceId() { $seed = $this->request->getFiltered('seed'); if(!$seed && ($vars = $this->request->get('cvendthru'))){ parse_str(html_entity_decode($vars), $ret); return $ret['seed']; } } public function validateSource() { $ipnFields = $this->request->getPost(); unset($ipnFields['cverify']); ksort($ipnFields); $pop = implode('|', $ipnFields) . '|' . $this->getPlugin()->getConfig('secret'); if (function_exists('mb_convert_encoding')) $pop = mb_convert_encoding($pop, "UTF-8"); $calcedVerify = strtoupper(substr(sha1($pop),0,8)); return ($this->request->get('cverify') == $calcedVerify) && ($this->request->getFiltered('ctransrole') == 'VENDOR'); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->request->get('ctransaction')) { //payment case self::SALE: case self::TEST: case self::TEST_SALE: case self::BILL: case self::TEST_BILL: if(doubleval($this->invoice->first_total) == 0 && $this->invoice->status == Invoice::PENDING) { $this->invoice->addAccessPeriod($this); } else { $this->invoice->addPayment($this); } break; //refund case self::RFND: case self::TEST_RFND: case self::CGBK: case self::TEST_CGBK: case self::INSF: case self::TEST_INSF: $this->invoice->addRefund($this, Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); //$this->invoice->stopAccess($this); break; //cancel case self::CANCEL_REBILL: case self::CANCEL_TEST_REBILL: $this->invoice->setCancelled(true); break; //un cancel case self::UNCANCEL_REBILL: case self::UNCANCEL_TEST_REBILL: $this->invoice->setCancelled(false); break; } } public function generateInvoiceExternalId() { list($l,) = explode('-',$this->getUniqId()); return $l; } public function autoCreateGetProducts() { $cbId = $this->request->getFiltered('cproditem'); if (empty($cbId)) return; $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('clickbank_product_id', $cbId); if (!$pl) return; $pr = $pl->getProduct(); if (!$pr) return; return array($pr); } public function fetchUserInfo() { $email = $this->request->get('ccustemail'); $email = preg_replace('/[^a-zA-Z0-9._+@-]/', '', $email); return array( 'name_f' => ucfirst(strtolower($this->request->getFiltered('ccustfirstname'))), 'name_l' => ucfirst(strtolower($this->request->getFiltered('ccustlastname'))), 'email' => $email, 'country' => $this->request->getFiltered('ccustcounty'), 'zip' => $this->request->getFiltered('ccustzip'), ); } } class Am_Paysystem_Transaction_Clickbank60 extends Am_Paysystem_Transaction_Incoming { // payment const SALE = "SALE"; const TEST = "TEST"; const TEST_SALE = "TEST_SALE"; const BILL = "BILL"; const TEST_BILL = "TEST_BILL"; // refund const RFND = "RFND"; const TEST_RFND = "TEST_RFND"; const CGBK = "CGBK"; const TEST_CGBK = "TEST_CGBK"; const INSF = "INSF"; const TEST_INSF = "TEST_INSF"; // cancel const CANCEL_REBILL = "CANCEL-REBILL"; const CANCEL_TEST_REBILL = "CANCEL-TEST-REBILL"; // cancel const UNCANCEL_REBILL = "UNCANCEL-REBILL"; const UNCANCEL_TEST_REBILL = "UNCANCEL-TEST-REBILL"; protected $notification = null; function init() { $r = json_decode($this->request->getRawBody(), true); if ($r && isset($r['notification']) && isset($r['iv'])) { $msg = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, substr(sha1($this->plugin->getConfig('secret')), 0, 32), base64_decode($r['notification']), MCRYPT_MODE_CBC, base64_decode($r['iv'])), "\0..\32"); $this->notification = json_decode($msg, true); $this->plugin->logOther('DECODED NOTIFICATION', $this->notification); } } public function findTime() { return new DateTime($this->notification['transactionTime']); } public function getUniqId() { return $this->notification['receipt']; } public function findInvoiceId() { $ret = array(); parse_str(parse_url($this->notification['lineItems'][0]['downloadUrl'], PHP_URL_QUERY), $ret); return isset($ret['seed']) ? $ret['seed'] : null; } public function validateSource() { return !is_null($this->notification); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->notification['transactionType']) { //payment case self::SALE: case self::TEST: case self::TEST_SALE: case self::BILL: case self::TEST_BILL: if(doubleval($this->invoice->first_total) == 0 && $this->invoice->status == Invoice::PENDING) { $this->invoice->addAccessPeriod($this); } else { $this->invoice->addPayment($this); } break; //refund case self::RFND: case self::TEST_RFND: case self::CGBK: case self::TEST_CGBK: case self::INSF: case self::TEST_INSF: $this->invoice->addRefund($this, $this->plugin->getDi()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); break; //cancel case self::CANCEL_REBILL: case self::CANCEL_TEST_REBILL: $this->invoice->setCancelled(true); break; //un cancel case self::UNCANCEL_REBILL: case self::UNCANCEL_TEST_REBILL: $this->invoice->setCancelled(false); break; } } public function generateInvoiceExternalId() { list($l,) = explode('-', $this->getUniqId()); return $l; } public function autoCreateGetProducts() { $products = array(); foreach ($this->notification['lineItems'] as $item) { $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('clickbank_product_id', $item['itemNo']); if ($pl) { $products[] = $pl->getProduct(); } } return $products; } public function fetchUserInfo() { $customer = $this->notification['customer']['billing']; return array( 'name_f' => $customer['firstName'], 'name_l' => $customer['lastName'], 'phone' => $customer['phoneNumber'], 'email' => $customer['email'], 'country' => $customer['address']['country'], 'state' => $customer['address']['state'], 'zip' => $customer['postalCode'] ); } } class Am_Paysystem_Transaction_Clickbank_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function autoCreateGetProducts() { $cbId = $this->request->getFiltered('item'); if (empty($cbId)) return; $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('clickbank_product_id', $cbId); if (!$pl) return; $pr = $pl->getProduct(); if (!$pr) return; return array($pr); } public function findTime() { //clickbank timezone $dtc = new DateTime('now', new DateTimeZone('Canada/Central')); //local timezone $dtl = new DateTime('now', new DateTimeZone(date_default_timezone_get())); $diff = $dtc->getOffset() - $dtl->getOffset(); $dt = new DateTime('@' . ($this->request->getInt('time') - $diff)); $dt->setTimezone(new DateTimeZone('Canada/Central')); return $dt; } public function generateInvoiceExternalId() { return $this->getUniqId(); } public function fetchUserInfo() { $names = preg_split('/\s+/', $this->request->get('cname'), 2); $names[0] = preg_replace('/[^a-zA-Z0-9._+-]/', '', $names[0]); $names[1] = preg_replace('/[^a-zA-Z0-9._+-]/', '', $names[1]); $email = $this->request->get('cemail'); $email = preg_replace('/[^a-zA-Z0-9._+@-]/', '', $email); return array( 'name_f' => $names[0], 'name_l' => $names[1], 'email' => $email, 'country' => $this->request->getFiltered('ccountry'), 'zip' => $this->request->getFiltered('czip'), ); } public function findInvoiceId() { $invoice = $this->getPlugin()->getDi()->invoiceTable->findByReceiptIdAndPlugin($this->request->getEscaped('cbreceipt'), $this->plugin->getId()); if ($invoice) return $invoice->public_id; else return $this->request->getFiltered('seed'); } public function getUniqId() { return $this->request->get('cbreceipt'); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function validateSource() { $vars = array( $this->getPlugin()->getConfig('secret'), $this->request->get('cbreceipt'), $this->request->get('time'), $this->request->get('item'), ); $hash = sha1(implode('|', $vars)); return strtolower($this->request->get('cbpop')) == substr($hash, 0, 8); } public function getInvoice() { return $this->invoice; } } PK\qq&default/plugins/payment/interkassa.phpnu[addText('co_id') ->setLabel("Interkassa ID\n" . "The Merchant's unique identification number as provided by Interkassa"); $form->addPassword('secret') ->setLabel("Interkassa Secret Key\n" . "Secret key from your Interkassa account for the checksum calculation"); } public function isConfigured() { return $this->getConfig('co_id') && $this->getConfig('secret'); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times) { return "Interkassa cannot handle products with recurring payment plan"; } return parent::isNotAcceptableForInvoice($invoice); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $data = array( 'ik_co_id' => $this->getConfig('co_id'), 'ik_pm_no' => $invoice->public_id, 'ik_cur' => $invoice->currency, 'ik_am' => $invoice->first_total, 'ik_desc' => $invoice->getLineDescription(), 'ik_cli' => $invoice->getUser()->email, 'ik_ia_u' => $this->getPluginUrl('ipn'), 'ik_suc_u' => $this->getReturnUrl(), 'ik_fal_u' => $this->getCancelUrl(), 'ik_x_invoice' => $invoice->public_id ); $data['ik_sign'] = $this->sign($data); foreach ($data as $k => $v) { $a->addParam($k, $v); } $this->logRequest($a); $result->setAction($a); } public function sign($data) { ksort($data, SORT_STRING); array_push($data, $this->getConfig('secret')); return base64_encode(md5(implode(':', $data), true)); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Interkassa($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Interkassa extends Am_Paysystem_Transaction_Incoming { public function getInvoice() { return $this->invoice; } public function findInvoiceId() { return $this->request->getFiltered('ik_x_invoice'); } public function getUniqId() { return $this->request->getParam('ik_trn_id'); } public function getReceiptId() { return $this->request->getFiltered('ik_inv_id'); } public function validateSource() { $data = array(); foreach ($this->request->getParams() as $k => $v) { if (substr($k, 0, 3) == 'ik_' && $k != 'ik_sign') $data[$k] = $v; } return $this->getPlugin()->sign($data) == $this->request->get('ik_sign'); } public function validateStatus() { if ($this->request->get('ik_inv_st') != 'success') throw new Am_Exception_Paysystem_TransactionInvalid(sprintf("Status is not Success [%s]", $this->request->get('ik_inv_st'))); if ($this->getPlugin()->getConfig('co_id') != $this->request->get('ik_co_id')) throw new Am_Exception_Paysystem_TransactionInvalid(sprintf("Foreign transaction - not our ik_co_id [%s!=%s]", $this->request->get('ik_co_id'), $this->getPlugin()->getConfig('co_id'))); return true; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->getAmount(), 'First Total'); if ($this->request->get('ik_cur') != $this->invoice->currency) return false; return true; } public function getAmount() { return $this->request->get('ik_am'); } public function processValidated() { $this->invoice->addPayment($this); } } PK\͆~~~$default/plugins/payment/safecart.phpnu[addText("username")->setLabel('Your SafeCart username'); $form->addText('auth_token')->setLabel('Auth Token'); return $form; } function init(){ parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('safecart_sku', "SafeCart SKU", "you must create the same product
      in Safecart and enter SKU here")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('safecart_product', "SafeCart Product", "You can get it from cart url: https://safecart.com/1mtest/PRODUCT/")); } function getURL(Invoice $invoice){ /* * Added to fix long username problem. * If username is over 15 characters we truncate it to 15 characters * This helps resolve issue we had with safecart URL versus the IPN validation * return sprintf("https://safecart.com/%s/%s/", $this->getConfig("username"), $invoice->getItem(0)->getBillingPlanData('safecart_product')); */ if (strlen($this->getConfig("username")) > 15) { $username = substr($this->getConfig("username"), 0, 15); } else { $username = $this->getConfig("username"); } return sprintf("https://safecart.com/%s/%s/", $username, $invoice->getItem(0)->getBillingPlanData('safecart_product')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $action = new Am_Paysystem_Action_Redirect($this->getURL($invoice)); $action->name = $invoice->getName(); $action->email = $invoice->getEmail(); $action->country= $invoice->getCountry(); $action->postal_zip = $invoice->getZip(); $action->__set('sku[]', $invoice->getItem(0)->getBillingPlanData('safecart_sku')); $action->payment_id = $invoice->public_id; $action->rbvar = 6; // I don't know what is it. Ported from v3 plugin $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Safecart($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { $ipn = Am_Html::escape($this->getPluginUrl('ipn')); return <<SafeCart Payment Plugin Configuration 1. Notification URL in your Safecart account should be set to $ipn 2. Notification types should be set to XML CUT; } function canAutoCreate(){ return true; } } class Am_Paysystem_Transaction_Safecart extends Am_Paysystem_Transaction_Incoming{ protected $xml; protected $req; protected $ip = array(array('209.139.253.0', '209.139.253.255')); const SALE = 'sale'; const REFUND = 'refund'; function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $this->req = $request->getRawBody(); $this->xml = simplexml_load_string($this->req); } public function getUniqId() { return implode('-', array((string)$this->xml->attributes()->id, (string)$this->xml->attributes()->ref)); } public function validateSource() { // $this->_checkIp($this->ip); $signature = base64_encode(hash_hmac('sha256', $this->req, $this->getPlugin()->getConfig('auth_token'))); if (!($this->request->getHeader('X-Revenuewire-Signature') && $this->request->getHeader('X-Revenuewire-Signature')=== $signature)) { return false; } if($this->xml === false){ throw new Am_Exception_Paysystem_TransactionInvalid("Invalid input type. Make sure that postback notifications type is set to XML"); } if( ((string) $this->xml->attributes()->merchant) != $this->plugin->getConfig('username')) throw new Am_Exception_Paysystem_TransactionSource("Merchant ID is not correct for received transaction!"); return true; } public function findInvoiceId(){ $data = (string) $this->xml->extra->request; parse_str(urldecode($data), $req); return @$req['payment_id']; } public function validateStatus() { return true; } public function validateTerms() { if((string) $this->xml->event->attributes()->type == self::SALE){ $amount = (float) $this->xml->event->sale->attributes()->amount; if($this->xml->event->tax) $amount = $amount - (float) $this->xml->event->tax->attributes()->amount; if(floatval($this->invoice->first_total) != floatval($amount)){ throw new Am_Exception_Paysystem_TransactionInvalid("Incorrect payment amount"); } } return true; } function processValidated() { switch($this->xml->event->attributes()->type){ case self::SALE : $this->invoice->addPayment($this); break; case self::REFUND : $this->invoice->addRefund($this, $this->getReceiptId(), abs($this->xml->sale->amount)); break; } } function setInvoiceLog(InvoiceLog $log) { parent::setInvoiceLog($log); $this->getPlugin()->logOther('SAFECART IPN:', $this->req); } function autoCreateGetProducts(){ $products = array(); foreach($this->xml->products->item as $item){ $sku = (string) $item->attributes()->sku; $bp = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('safecart_sku', $sku); if(!$bp) continue; $products[] = $bp->getProduct(); } return $products; } function generateInvoiceExternalId(){ return (string) $this->xml->attributes()->id; } function generateUserExternalId(array $userInfo){ return md5($userInfo['email']); } function fetchUserInfo(){ $ret = array(); list($ret['name_f'], $ret['name_l']) = explode(" ", (string) $this->xml->customer->name); if(empty($ret['name_l'])) $ret['name_l'] = ''; $ret['email'] = (string) $this->xml->customer->email; return $ret; } } PK\K̝M-default/plugins/payment/ccavenue/ccavutil.jarnu[PK G@com/UT L1ObOux PK G@ com/ccavenue/UT L1ObOux PK `@com/ccavenue/security/UT #bO/bOux PK G@ META-INF/UT 1ObOux PKO`@8ouMETA-INF/MANIFEST.MFUT `O/bOux ȱ 1 нC).ަ:Rb]z4пrZ|RS2LޥF'8sݻت5Z5a].,1-EuXW@,_N 66{/PKa@X+( com/ccavenue/security/AesCryptUtil.javaUT O#bOux XOHN8>k{U &ߩ/Jѧ:1a걑.q#-܀/?ڗ3 5қ910u*"zo˦DUuAs?v {4%99MDU(S[u04""y~" i.}tגh\[5rf=i|-ihD\AL8<;04[&YH&8j Ih';Z-˸1S1m\_<ůmC>z/]/.SKfXNĭ I eS%M9uQ[ acF'_T.?d|MUBgǕ( lw7Fϰ9Z^*yfe(w/F l`2Isr6-VL-C,~`<}[.pmd*MaiawM| [:# i oL:06l ^lY%xg xa -PQ (& fS޵TV+3tsV uɘ6\DB݌bo .<} t~4h.B7Ee]g$|ܼ0V[l*ZH'o%"%.5׌U., (,SSs+6 (]g.V7ւݓo<`0Dn'^VPK _@0t (com/ccavenue/security/AesCryptUtil.classUT O/bOux WSrN)Z% j E HGSNcHsjrt*'9/e*t"`Mn}=9M7}sW04=$.;<$@AZ~> `w bi(x0 = <ķp{PkV}EFK@$+ 8z]%LS-cN`O{Ewn6 ‰=78ōv~-+;mrI}sZxM[~a3(b*6[k*~U_%~6*N"&aqzr\ !蔄%_<إ~sE(NKEeBHkkKKh7vo`1PL2FTgTᬊw3Ka^I#FyK¢ &P؃=}H;Τ₌*~U|ߋTRg|,㒊O Q=3ra:'~#7r__ߑzrfj,{,.km ^?ӲU-~y ' Da%~uPoRIgjtĸ4iI-衼,`h]*CNa);\٧s=o) ?qYU|Hnٯ'Y+[Vn]sÍk#:6K+ -zV@lXڝVKCWm58E3Om-}@՚љZ@< s~*w hL;Zҥ=Yd.ELh3d}[ય-u&Ⲷ[QfI)>O6-&LNɮdȓ0tԖStV˰U 4ё¨c}b, Vt/Qʫ&[#evkz65WIv!BVg{E([t_U =yiv2Ϭ@嫮@۝Aq'\{&v*p")ְOy+t])#&wA6(/b9YAqL2Y>|HNyr-dU sr*6G k8*chc-+8 !(QNOh ZN%lPq!pg1fTm)k)A3!In '8i>XbO9pYŠbG=~4Pl\G޳J'x'xB E'n/W^˵W J8;U9xk8NN8;#CMzMmԎO|PllL|.k6OYփ#x @3hN+&0zɹO`7D7ⶑi1J4 #slhjs^WЫ 1wʿ1F =$-tV`0=L+ܕto%WC[ 7ꇱ` c]MXt2FIK,.Y\ ^L7Iۙ)u$׺>Zweh]?3ȓ#-ƭ벳?% Bpr)-ՏXS(»1z/;EBeo<+~>~£t x)W D}Fqmםژ>c> O=Osbv5@o ^K:>iAqHUrV>wwFs*iʥƓ2^Dq pE { x7&zO "jzW<_XL Wȇ W?Yӄ^Ck }"2!-R ?RL&R97 aoѲ-l ;"-ob.*.[Թj-N[9_ ٍ[kMc'G.춙:!Խ8az=tyjNf3ƢM K{<{VU8E'ޤ' * racz؁g "KCG(a ['xOc|꾂Oyh ~_\&YPK G@Acom/UTL1Oux PK G@ A>com/ccavenue/UTL1Oux PK `@Acom/ccavenue/security/UT#bOux PK G@ AMETA-INF/UT1Oux PKO`@8ouMETA-INF/MANIFEST.MFUT`Oux PKa@X+( com/ccavenue/security/AesCryptUtil.javaUTOux PK _@0t (b com/ccavenue/security/AesCryptUtil.classUTOux PK~8PK\)J-default/plugins/payment/ccavenue/ccavenue.phpnu[> 16) & 0xffff; for ($i = 0; $i < strlen($str); $i++) { $s1 = ($s1 + Ord($str[$i])) % $BASE; $s2 = ($s2 + $s1) % $BASE; } return $this->leftshift($s2, 16) + $s1; } function getChecksum($MerchantId, $OrderId, $Amount, $redirectUrl, $WorkingKey) { $str = "$MerchantId|$OrderId|$Amount|$redirectUrl|$WorkingKey"; $adler = 1; $adler = $this->adler32($adler,$str); return $adler; } function leftshift($str, $num) { $str = DecBin($str); for ($i = 0; $i < (64 - strlen($str)); $i++) $str = "0" . $str; for ($i = 0; $i < $num; $i++) { $str = $str . "0"; $str = substr($str, 1); } return $this->cdec($str); } function cdec($num) { $dec = 0; for ($n = 0; $n < strlen($num); $n++) { $temp = $num[$n]; $dec = $dec + $temp * pow(2, strlen($num) - $n - 1); } return $dec; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('account_id')->setLabel('Merchant Account Id'); $form->addText('secret')->setLabel('Merchant Secret Key'); $form->addText('access_code')->setLabel('Merchant Access Code'); } function decrypt($encryptedText) { $key = $this->getConfig('secret'); $secretKey = $this->hextobin(md5($key)); $initVector = pack("C*", 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f); $encryptedText= $this->hextobin($encryptedText); $openMode = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '','cbc', ''); mcrypt_generic_init($openMode, $secretKey, $initVector); $decryptedText = mdecrypt_generic($openMode, $encryptedText); $decryptedText = rtrim($decryptedText, "\0"); mcrypt_generic_deinit($openMode); return $decryptedText; } function encrypt($plainText) { $key = $this->getConfig('secret'); $secretKey = $this->hextobin(md5($key)); $initVector = pack("C*", 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f); $openMode = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '','cbc', ''); $blockSize = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, 'cbc'); $plainPad = $this->pkcs5_pad($plainText, $blockSize); if (mcrypt_generic_init($openMode, $secretKey, $initVector) != -1) { $encryptedText = mcrypt_generic($openMode, $plainPad); mcrypt_generic_deinit($openMode); } return bin2hex($encryptedText); } function pkcs5_pad ($plainText, $blockSize) { $pad = $blockSize - (strlen($plainText) % $blockSize); return $plainText . str_repeat(chr($pad), $pad); } function hextobin($hexString) { $length = strlen($hexString); $binString=""; $count=0; while($count<$length) { $subString =substr($hexString,$count,2); $packedString = pack("H*",$subString); if ($count==0) { $binString=$packedString; } else { $binString.=$packedString; } $count+=2; } return $binString; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Form(self::LIVE_URL); $vars = array( 'merchant_id' => $this->getConfig('account_id'), 'order_id' => $invoice->public_id, 'amount' => $invoice->first_total, 'redirect_url' => $this->getPluginUrl('thanks'), 'cancel_url' => $this->getCancelUrl(), 'billing_cust_name' => $u->name_f . ' ' . $u->name_l, 'billing_cust_address' => $u->street, 'billing_cust_city' => $u->city, 'billing_cust_state' => substr($u->state, -2), 'billing_zip_code' => $u->zip, 'billing_cust_country' => $u->country, 'billing_cust_tel' => $u->phone, 'billing_cust_email' => $u->email, 'currency' => $invoice->currency, 'txnrype' => 'A', 'actionid' => 'TXN', 'billing_cust_notes' => $invoice->getLineDescription(), ); $query = http_build_query($vars); $a->encRequest = $this->encrypt($query); $a->access_code = $this->getConfig('access_code'); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ccavenue_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_Ccavenue_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function validateSource() { $query = $this->plugin->decrypt($this->request->get('encResp')); parse_str($query, $vars); $this->vars = $vars; return is_array($vars); } function findInvoiceId() { return $this->request->get('orderNo'); } public function getUniqId() { return $this->vars["tracking_id"]; } public function validateStatus() { return $this->vars["order_status"] == "Success"; } public function validateTerms() { return doubleval($this->vars["amount"]) == doubleval($this->invoice->first_total); } }PK\+default/plugins/payment/orbitalpay-form.phpnu[addText('account_id') ->setLabel('Orbitalpay Account ID') ->addRule('required'); $form->addText('site_tag') ->setLabel("Orbitalpay Site Tag\n" . "create it at your orbitalpay account -> Setup -> Site Tools -> Site tags") ->addRule('required'); $form->addText('crypto_hash') ->setLabel("MD5 crypto-hash\n" . "create it at your orbitalpay account -> Fraud Controls -> Fraud Defense -> Step 12") ->addRule('required'); $form->addAdvCheckbox("debugLog") ->setLabel("Debug Log Enabled\n" . "write all requests/responses to log"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $user = $invoice->getUser(); $post = array( 'Ecom_BillTo_Postal_Name_First' => $user->name_f, 'Ecom_BillTo_Postal_Name_Last' => $user->name_l, 'Ecom_BillTo_Postal_Street_Line1' => $user->street, 'Ecom_BillTo_Postal_Street_Line2' => $user->street2, 'Ecom_BillTo_Postal_City' => $user->city, 'Ecom_BillTo_Postal_StateProv' => $user->state, 'Ecom_BillTo_Postal_PostalCode' => $user->zip, 'Ecom_BillTo_Postal_CountryCode' => $user->country, 'Ecom_BillTo_Online_Email' => $user->email, 'Ecom_ShipTo_Postal_Name_First' => $user->name_f, 'Ecom_ShipTo_Postal_Name_Last' => $user->name_l, 'Ecom_ShipTo_Postal_City' => $user->city, 'Ecom_ShipTo_Postal_Street_Line1' => $user->street, 'Ecom_ShipTo_Postal_Street_Line2' => $user->street2, 'Ecom_ShipTo_Postal_StateProv' => $user->state, 'Ecom_ShipTo_Postal_PostalCode' => $user->zip, 'Ecom_ShipTo_Postal_CountryCode' => $user->country, 'Ecom_ShipTo_Online_Email' => $user->email, 'Ecom_Ezic_AccountAndSitetag' => $this->getConfig('account_id') . ":" . $this->getConfig('site_tag'), 'Ecom_Cost_Total' => sprintf("%.2f",$invoice->first_total), 'Ecom_Receipt_Description' => $invoice->getLineDescription(), 'Ecom_Ezic_Security_HashFields' => self::Hash_Fields, 'Ecom_Ezic_Payment_AuthorizationType' => 'SALE', 'Ecom_ConsumerOrderID' => $invoice->public_id, ); $hash = $this->getConfig('crypto_hash'); foreach (explode(' ', self::Hash_Fields) as $field) $hash .= $post[$field]; $post['Ecom_Ezic_Security_HashValue_MD5'] = strtoupper(md5($hash)); if ($this->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('Orbitalpay Form [request-data]:' . json_encode($post)); foreach ($post as $key => $value) $a->$key = $value; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'thanks') { if ($this->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('Orbitalpay Form [response-thanks]:' . json_encode($request->getParams())); if($this->invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->getFiltered('Ecom_ConsumerOrderID'))) $url = ($request->get('Ecom_Ezic_Response_StatusCode') == 0 || $request->get('Ecom_Ezic_Response_StatusCode') == 'F') ? $this->getCancelUrl() : $this->getReturnUrl(); else $url = $this->getRootUrl() . "/thanks"; $response->setRedirect($url); }else parent::directAction($request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_OrbitalpayForm($this, $request, $response, $invokeArgs); } public function getReadme() { $thanks = $this->getPluginUrl('thanks'); $ipn = $this->getPluginUrl('ipn'); return << Configuration -> Setup/Configuration -> Plugins -> Payment Plugins' and enable "orbitalpay-form" plugin. 2. Configure plugin: go to 'aMember CP -> Configuration -> Setup/Configuration -> Orbitalpay Form' and configure it. 3. Configure your Orbitalpay Account: - go to your Orbitalpay Account -> Setup -> Site Tools -> Site tags - find your just created tag and click 'conf' link - enter at 'Return URL': $thanks - enter at 'Postback CGI URL': $ipn CUT; } } class Am_Paysystem_Transaction_OrbitalpayForm extends Am_Paysystem_Transaction_Incoming { public function process() { if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('Orbitalpay Form [response-ipn]:' . json_encode($this->request->getParams())); parent::process(); } public function validateSource() { $hashFields = explode(' ', Am_Paysystem_OrbitalpayForm::Hash_Fields); $hash = $this->plugin->getConfig('crypto_hash') . $this->request->getFiltered('Ecom_Ezic_Response_TransactionID') . $this->request->getFiltered('Ecom_Ezic_Response_StatusCode'); foreach ($hashFields as $v) $hash .= $this->request->get($v); return (strtoupper(md5($hash)) == $this->request->getFiltered('Ecom_Ezic_ProofOfPurchase_MD5')); } public function findInvoiceId() { return $this->request->getFiltered('Ecom_ConsumerOrderID'); } public function validateStatus() { switch ($this->request->getFiltered('Ecom_Ezic_TransactionStatus')) { case 0: case 'F': return false; } return true; } public function getUniqId() { return $this->request->getFiltered('Ecom_Ezic_Response_TransactionID'); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('Ecom_Cost_Total')); return true; } }PK\jO$default/plugins/payment/epayment.phpnu[addText("merchant") ->setLabel("Your merchant identifier\n" . 'received from ePayment'); $form->addText("secret") ->setLabel("Secret Key\n" . 'received from ePayment'); $form->addAdvCheckbox("testing") ->setLabel("Testing\n" . 'enable/disable testmode'); $form->addSelect("language", array(), array('options' => array( 'ro' => 'Romanian', 'en' => 'English', 'fr' => 'French', 'it' => 'Italian', 'de' => 'German', 'es' => 'Spanish' )))->setLabel('Site Language'); } function calculateHash($vars){ $hash_src = ''; foreach($vars as $k=>$v){ if(is_array($v)){ foreach($v as $vv){ $hash_src .= strlen(htmlentities($vv)).htmlentities($vv); } }else $hash_src .= strlen(htmlentities($v)).htmlentities($v); } return hash_hmac('md5', $hash_src, $this->getConfig('secret')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $vars = array( 'MERCHANT' => $this->getConfig('merchant'), 'ORDER_REF' => $invoice->public_id, 'ORDER_DATE' => $invoice->tm_added ); foreach($invoice->getItems() as $item){ $vars['ORDER_PNAME[]'] = $item->item_title; $vars['ORDER_PCODE[]'] = $item->item_id; $vars['ORDER_PRICE[]'] = $item->first_price; $vars['ORDER_QTY[]'] = $item->qty; $vars['ORDER_VAT[]'] = $item->first_tax; } $vars['ORDER_SHIPPING'] = 0; $vars['PRICES_CURRENCY'] = strtoupper($invoice->currency); $vars['DISCOUNT'] = $invoice->first_discount; foreach($vars as $k=>$v){ $a->__set($k,$v); } $a->__set('ORDER_HASH', $this->calculateHash($vars)); $a->__set('BILL_FNAME', $invoice->getFirstName()); $a->__set('BILL_LNAME', $invoice->getLastName()); $a->__set('BILL_EMAIL', $invoice->getEmail()); $a->__set('BILL_PHONE', $invoice->getPhone()); $a->__set('BILL_ADDRESS', $invoice->getStreet()); $a->__set('BILL_ZIPCODE', $invoice->getZip()); $a->__set('BILL_CITY', $invoice->getCity()); $a->__set('BILL_STATE', $invoice->getState()); $a->__set('BILL_COUNTRYCODE', $invoice->getCountry()); $a->__set('LANGUAGE', $this->getConfig('language', 'ro')); if($this->getConfig('testing')) $a->__set('TESTORDER', 'TRUE'); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Epayment($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('RON', 'EUR', 'USD'); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { parent::directAction($request, $response, $invokeArgs); $post = $request->getPost(); $date = date('YmdGis'); $vars = array($post['IPN_PID'][0], $post['IPN_PNAME'][0], $post['IPN_DATE'], $date); printf('%s|%s', $date, $this->calculateHash($vars)); } function getReadme(){ return <<ePayment plugin configuration Configure IPN url ion your account: %root_surl%/payment/epayment/ipn CUT; } } class Am_Paysystem_Transaction_Epayment extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('REFNOEXT'); } public function getUniqId() { return $this->request->get('REFNO'); } public function validateSource() { $post = $this->request->getPost(); $hash = $post['HASH']; unset($post['HASH']); $calc = $this->getPlugin()->calculateHash($post); if($calc != $hash){ throw new Am_Exception_Paysystem_TransactionSource(sprintf('Calculated hash is not equal to received.(%s!=%s)', $calc, $hash)); } return true; } public function validateStatus() { if(!$this->getPlugin()->getConfig('testing') && ($this->request->get('ORDERSTATUS') == 'TEST')) throw new Am_Exception_Paysystem_TransactionInvalid('Test transaction received, but test mode is not enabled'); if($this->request->get('ORDERSTATUS') == '-') throw new Am_Exception_Paysystem_TransactionInvalid('Transaction is not finished yet. ORDERSTATUS='.$this->request->get('ORDERSTATUS')); return true; } public function validateTerms() { return true; } }PK\b_$_$%default/plugins/payment/walletone.phpnu[ 398, // Kazakhstani tenge 'RUB' => 643, // Russian Rubles 'ZAR' => 710, // South African Rand 'USD' => 840, // US Dollar 'UAH' => 980, // Ukrainian Hryvnia ); protected $defaultTitle = 'Wallet One'; protected $defaultDescription = 'quick and easy payments with mobile phone or computer'; public function supportsCancelPage() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addInteger('merchantId', array('maxlength' => 20, 'size' => 15)) ->setLabel('Your WMI Merchant ID#') ->addRule('required'); $form->addSelect('signature') ->setLabel('Signature Method') ->loadOptions(array( '' => 'None', 'md5' => 'MD5', 'sha1' => 'SHA1', )); $form->addText('key', array('size' => 40)) ->setLabel('Secret Key') ->addRule('callback2', 'error', array($this, 'validateSecretKey')); $form->addScript()->setScript(<<getContainer()->getDataSources(); return ( ($sign = $request[0]->getParam('payment.walletone.signature')) && !$key) ? 'Secret Key must not be empty, if Signature Method is ' . strtoupper($sign) : null; } public function isConfigured() { return $this->getConfig('merchantId') > ''; } public function getSupportedCurrencies() { return array_keys(self::$currencies); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $fields = array(); $fields["WMI_MERCHANT_ID"] = $this->getConfig('merchantId'); $fields["WMI_PAYMENT_AMOUNT"] = $invoice->first_total; $fields["WMI_CURRENCY_ID"] = $this->getCurrencyId($invoice->currency); $fields["WMI_PAYMENT_NO"] = $invoice->public_id; $fields["WMI_DESCRIPTION"] = "BASE64:".base64_encode($invoice->getLineDescription()); $fields["WMI_SUCCESS_URL"] = $this->getReturnUrl(); $fields["WMI_FAIL_URL"] = $this->getCancelUrl(); foreach ($fields as $name => $val) { if (is_array($val)) { usort($val, "strcasecmp"); $fields[$name] = $val; } } uksort($fields, "strcasecmp"); $fieldValues = ""; foreach ($fields as $value) { if (is_array($value)) foreach ($value as $v) { // $v = iconv("utf-8", "windows-1251", $v); $fieldValues .= $v; } else { // $value = iconv("utf-8", "windows-1251", $value); $fieldValues .= $value; } } if ($sign = $this->getConfig('signature')) $fields["WMI_SIGNATURE"] = base64_encode(pack("H*", $sign($fieldValues . $this->getConfig('key')))); $a = new Am_Paysystem_Action_Redirect(self::URL_PAY); foreach($fields as $key => $val) $a->$key = $val; $result->setAction($a); } private function getCurrencyId($currency) { return self::$currencies[$currency]; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Walletone($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Walletone($this, $request, $response, $invokeArgs); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'ipn') { $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); $transaction = $this->createTransaction($request, $response, $invokeArgs); $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { $transaction->printAnswer("Ok", "Order #" . $transaction->findInvoiceId() . " is paid!"); } catch (Exception $e) { if ($invoiceLog) $invoiceLog->add($e); $this->getDi()->errorLogTable->logException($e); return; } if ($invoiceLog) $invoiceLog->setProcessed(); return; } else parent::directAction($request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return <<Wallet One payment plugin configuration 1. Log in your account at https://www.walletone.com/client/ 2. At 'Settings -> Profile -> Personal details' copy your 'Account' and paste in field 'Your WMI Merchant ID#' at 'aMember CP -> Setup/Configuration -> Wallet One' (this page) 3. At 'Settings -> E-commerce -> Internet market': -'State' -> 'On' -'Title' on your choice -'Site URL' url your site -'Result URL' -> '{$this->getPluginUrl('ipn')}'. 4. At 'Settings -> E-commerce -> Digital signature' choose 'Signature method'. If it isn't 'None' generate 'Secret key', copy it and click 'Save' button. 5. At 'aMember CP -> Setup/Configuration -> Wallet One' (this page) choose 'Signature Method' the same as on previous step. If it isn't 'None' paste 'Secret key' in field 'Secret Key'. 6. At 'aMember CP -> Setup/Configuration -> Wallet One' (this page) click 'Save' button CUT; } } class Am_Paysystem_Transaction_Walletone extends Am_Paysystem_Transaction_Incoming { public function printAnswer($result, $description) { print "WMI_RESULT=" . strtoupper($result) . "&"; print "WMI_DESCRIPTION=" . urlencode($description); if ($result != 'Ok') { Am_Di::getInstance()->errorLogTable->log('Error when paying by wallet one: ' . $description); } } public function process() { $vars = $this->request->getPost(); if (($sign = $this->plugin->getConfig('signature')) && !isset($vars["WMI_SIGNATURE"])) { $this->printAnswer("Retry", "Parameter WMI_SIGNATURE is absent."); return; } if (!isset($vars["WMI_PAYMENT_NO"])) { $this->printAnswer("Retry", "Parameter WMI_PAYMENT_NO is absent."); return; } if (!isset($vars["WMI_ORDER_STATE"])) { $this->printAnswer("Retry", "Parameter WMI_ORDER_STATE is absent."); return; } $params = array(); foreach ($vars as $key => $value) if ($key !== "WMI_SIGNATURE") $params[$key] = $value; ksort($params, SORT_STRING); $values = ""; foreach ($params as $value) { $values .= $value; } $signature = base64_encode(pack("H*", $sign($values . $this->plugin->getConfig('key')))); if ($signature != $vars["WMI_SIGNATURE"]) { $this->printAnswer("Retry", "Wrong digital signature " . $vars["WMI_SIGNATURE"]); return; } if (strtoupper($this->request->get("WMI_ORDER_STATE")) != "ACCEPTED") { $this->printAnswer("Retry", "Unknown order status " . $vars["WMI_ORDER_STATE"]); return; } parent::process(); $this->printAnswer("Ok", "Order #" . $this->request->get("WMI_PAYMENT_NO") . " is paid!"); } public function validateSource() { return true; } public function findInvoiceId() { return $this->request->get("WMI_PAYMENT_NO"); } public function validateStatus() { return true; } public function getUniqId() { return $this->request->get("WMI_ORDER_ID"); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get("WMI_PAYMENT_AMOUNT")); return true; } } PK\ac]7default/plugins/payment/myshortcart/myshortcartbase.phpnu[addText('store_id') ->setLabel('Your Store ID') ->addRule('required'); $form->addText('shared_key') ->setLabel("Your Shared Key") ->addRule('required'); } protected abstract function getPaymentMethod(); public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('IDR'); } public function isConfigured() { return (bool)($this->getConfig('store_id') && $this->getConfig('shared_key')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $basket = array(); foreach ($invoice->getItems() as $item) { $basket[] = $item->item_title . "," . $item->first_price . "," . $item->qty . "," . $item->first_total; } $vars = array( 'BASKET' => implode(";", $basket), 'TRANSIDMERCHANT' => $invoice->public_id, 'STOREID' => $this->getConfig('store_id'), 'AMOUNT' => $invoice->first_total, 'URL' => ROOT_SURL, 'CNAME' => $user->getName(), 'CEMAIL' => $user->email, 'CWPHONE' => $user->phone ? $user->phone : 0, 'CHPHONE' => $user->phone ? $user->phone : 0, 'CMPHONE' => $user->phone ? $user->phone : 0, 'WORDS' => sha1($invoice->first_total . $this->getConfig('shared_key') . $invoice->public_id), 'PAYMENTMETHODID' => $this->getPaymentMethod() ); $this->logRequest($vars); $action = new Am_Paysystem_Action_Form(self::URL); foreach ($vars as $key => $value) { $action->$key = $value; } $result->setAction($action); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $this->invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->getFiltered('TRANSIDMERCHANT')); $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); switch ($request->getActionName()) { case 'verify': if(!in_array($request->getClientIp(), self::$IPs)) { $invoiceLog->add( new Am_Exception_Paysystem("Uknown IP[{$request->getClientIp()}], allowed[". implode(',', self::$IPs)."]") ); echo "Stop"; return; } if($this->getConfig('store_id') != $request->getFiltered('STOREID')) { $invoiceLog->add( new Am_Exception_Paysystem("Wrong STOREID: got[{$request->get('STOREID')}], expected[{$this->getConfig('store_id')}]") ); echo "Stop"; return; } if(!$this->invoice) { $invoiceLog->add( new Am_Exception_Paysystem("Invoice [{$request->getFiltered('TRANSIDMERCHANT')}] not found") ); echo "Stop"; return; } if($this->invoice->first_total != $request->get('AMOUNT')) { $invoiceLog->add( new Am_Exception_Paysystem("Wrong AMOUNT: got[{$request->get('AMOUNT')}], expected[{$this->invoice->first_total}]") ); echo "Stop"; return; } $hash = sha1($request->get('AMOUNT') . $this->getConfig('shared_key') . $request->getFiltered('TRANSIDMERCHANT')); if($hash != $request->getFiltered('WORDS')) { $invoiceLog->add( new Am_Exception_Paysystem("Wrong WORDS: got[{$request->get('WORDS')}], expected[{$hash}]") ); echo "Stop"; return; } echo "Continue"; return; case 'ipn': try { $transaction = $this->createTransaction($request, $response, $invokeArgs); if (!$transaction) { throw new Am_Exception_InputError("Request not handled - createTransaction() returned null"); } $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); } catch (Exception $e) { if ($invoiceLog) $invoiceLog->add($e); throw $e; } if ($invoiceLog) $invoiceLog->setProcessed(); echo "Continue"; } catch (Exception $e) { echo "Stop"; } return; case 'redirect': if($this->invoice) { $response->redirectLocation($this->getReturnUrl()); } throw new Am_Exception_InputError("Invoice not found"); case 'cancel': if($this->invoice) { $response->redirectLocation($this->getCancelUrl()); } throw new Am_Exception_InputError("Invoice not found"); } } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Myshortcart($this, $request, $response, $invokeArgs); } public function getReadme() { $verify = $this->getPluginUrl('verify'); $notify = $this->getPluginUrl('ipn'); $redirect = $this->getPluginUrl('redirect'); $cancel = $this->getPluginUrl('cancel'); return <<Myshopcart plugin installation - Add at signup form 'Phone' field and set it as required Go to your merchant account -> Website and set these URLs: - Set at your merchant account VERIFY URL - $verify - Set at your merchant account NOTIFY URL - $notify - Set at your merchant account REDIRECT URL - $redirect - Set at your merchant account CANCEL URL - $cancel For testing use: SUCCESS Card Number: 5426400030108754 CVV2: 869 Exp Date 2016 month = April FAIL 4512490020005811=05 CVV2: 166 Exp Date 2016 month = April CUT; } } PK\<0to3default/plugins/payment/myshortcart/transaction.phpnu[request->getFiltered("TRANSIDMERCHANT"); } public function validateSource() { $this->_checkIp(Am_Paysystem_Myshortcart::$IPs); return true; } public function validateStatus() { return $this->request->getFiltered('RESULT') == "Success"; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('AMOUNT')); return true; } } PK\~3default/plugins/payment/myshortcart/myshortcart.phpnu[getId(); $form->addText("storekey")->setLabel('StoreKey'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); $result->setAction($a); $a->StoreKey = $this->getConfig('storekey'); $a->CustomerRefNo = $invoice->public_id; $a->PaymentType = ''; $a->CardAction = '0'; $a->OrderID = $invoice->invoice_id; $a->UserID = $invoice->getLogin(); $a->Email = $invoice->getEmail(); $a->CustomerIP = $user->remote_addr ? $user->remote_addr : $_SERVER['REMOTE_ADDR']; $a->Bname = $invoice->getFirstName().' '.$invoice->getLastName(); $a->Baddress1 = $user->street; $a->Bcity = $user->city; $a->Bpostalcode = $user->zip; $a->Bcountry = $user->country; $a->Sname = $invoice->getFirstName().' '.$invoice->getLastName(); $a->Saddress1 = $user->street; $a->Scity = $user->city; $a->Spostalcode = $user->zip; $a->Scountry = $user->country; $a->SubTotal = $invoice->first_total - $invoice->first_tax; $a->Tax1 = $invoice->first_tax; $a->ThanksURL = $this->getPluginUrl("thanks"); $result->setAction($a); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Psigate($this, $request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_Psigate extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('TransRefNumber'); } public function findInvoiceId() { return $this->request->getFiltered('CustomerRefNo'); } public function validateSource() { return true; } public function validateStatus() { return ($this->request->getFiltered('Approved')=='APPROVED' || $this->request->getFiltered('Approval')=='Successful'); } public function validateTerms() { return true; // terms are signed in the form, no need to validate again } public function getInvoice() { return $this->invoice; } }PK\$Cp$default/plugins/payment/coinbase.phpnu[addText(self::API_KEY, array('class' => 'el-wide')) ->setLabel("API KEY\n" . 'Get it from your coinbase account'); $form->addPassword(self::API_SECRET, array('class' => 'el-wide')) ->setLabel("API SECRET\n" . 'Get it from your coinbase account'); } public function getSupportedCurrencies() { return array('USD', 'BTC'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $vars = array( 'button[name]' => $invoice->getLineDescription(), 'button[price_string]' => $invoice->first_total, 'button[price_currency_iso]' => $invoice->currency, 'button[type]' => 'buy_now', 'button[custom]' => $invoice->public_id, 'button[callback_url]' => $this->getPluginUrl('ipn'), 'button[success_url]' => $this->getReturnUrl(), 'button[cancel_url]' => $this->getCancelUrl(), 'button[variable_price]' => false, 'button[choose_price]' => false ); try{ // Get code from API $r = new Am_Request_Coinbase($this->getConfig(self::API_KEY),$this->getConfig(self::API_SECRET)); $resp = $r->post('buttons', $vars); if(!($code = @$resp->button->code)) throw new Am_Exception_InternalError("Coinbase: Can't create button. Got:". print_r($resp, true)); }catch(Exception $e){ $this->getDi()->errorLogTable->logException($e); throw $e; } $a = new Am_Paysystem_Action_Redirect(self::CHECKOUT_URL . '/'.$code); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Coinbase($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme() { return <<getRawBody(); $ret = @json_decode($str); if(!$ret) throw new Am_Exception_InternalError("Coinbase: Can't decode postback: ".$ret); $this->order = @$ret->order; } public function getUniqId() { return @$this->order->id; } public function validateSource() { return true; } public function validateStatus() { return (@$this->order->status == "completed" ? true : false); } public function validateTerms() { return doubleval(@$this->order->total_native->cents/(@$this->order->total_native->currency_iso == 'USD' ? 100 : 100000000)) == doubleval($this->invoice->first_total); } public function findInvoiceId() { return @$this->order->custom; } } class Am_Request_Coinbase { const API_URL = 'https://coinbase.com/api/v1'; /** * @var Am_HttpRequest */ protected $_request; protected $_key; protected $_secret; function __construct($api_key, $api_secret) { $this->_key = $api_key; $this->_secret = $api_secret; $this->_createRequest(); } protected function _createRequest(){ $this->_request = new Am_HttpRequest(); } protected function _request($function, $method, $params=null) { $this->_request->setUrl(self::API_URL . '/'.$function); $nonce = sprintf('%0.0f',round(microtime(true) * 1000000)); $data = $nonce . self::API_URL . '/' . $function . http_build_query($params); $this->_request->setHeader(array( 'ACCESS_KEY' => $this->_key, 'ACCESS_SIGNATURE' => hash_hmac('sha256', $data, $this->_secret), 'ACCESS_NONCE' => $nonce)); $this->_request->setMethod($method); if(!empty($params)) $this->_request->addPostParameter($params); $resp = $this->_request->send(); if($resp->getStatus() != 200) throw new Am_Exception_InternalError('CoinBase: Status for API request was not 200. Got: '.$resp->getStatus()); $data = json_decode($resp->getBody()); if(is_null($data)) throw new Am_Exception_InternalError('CoinBase: Unable to decode response. Got: '.$resp); if(!@$data->success) throw new Am_Exception_InternalError('CoinBase: Not successfull response.Got: '.print_r($data, true)); return $data; } public function post($function, $params) { return $this->_request($function, Am_HttpRequest::METHOD_POST, $params); } public function get($function) { return $this->_request($function, Am_HttpRequest::METHOD_GET); } }PK\jGdefault/plugins/payment/micropayment/scripts/micropayment-confirm.phtmlnu[setLayout('layout.phtml'); ?>

      methods as $k => $v) { $checked = ''; if($this->url == $k) $checked = ' checked="checked" '; echo "
      "; } ?>
      PK\Iq5default/plugins/payment/micropayment/micropayment.phpnu[addText("key") ->setLabel("Access Key\n" . 'You\'ll find your AccessKey in ControlCenter --> My Configuration'); $form->addText("project")->setLabel('Project Identifier'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); $form->addMagicSelect("methods") ->setLabel("Available methods\n". "if none is selected then all methods will be listed") ->loadOptions(array( 'prepay'=>$this->defaultPrepayDescription, 'lastschrift'=>$this->defaultLastschriftDescription)); $form->addText("prepay.title")->setLabel("Prepay method title\n" . $this->defaultPrepayDescription); $form->setDefault('prepay.title', $this->defaultPrepayDescription); $form->addText("lastschrift.title")->setLabel("Lastschrift method title\n" . $this->defaultLastschriftDescription); $form->setDefault('lastschrift.title', $this->defaultLastschriftDescription); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $m = $this->getConfig('methods'); if(@count($m)==1) $a = new Am_Paysystem_Action_Form(self::URL.$m[0].'/event/'); else { $a = new Am_Paysystem_Action_HtmlTemplate_Micropayment($this->getDir(), 'micropayment-confirm.phtml'); $methods = array(); if(@count($m)) { $a->url = self::URL.$m[0].'/event/'; foreach($m as $title) $methods[self::URL.$title.'/event/'] = $this->getConfig($title.'.title'); } else { foreach($this->getConfig() as $k => $v) { if(is_array($v) && !empty($v['title'])) $methods[self::URL.$k.'/event/'] = $v['title']; } $a->url = array_shift(array_keys($methods)); } $a->methods = $methods; } $a->project = $this->getConfig('project'); $a->amount = $invoice->first_total*100; $a->freepaymentid = $invoice->public_id; $a->seal = md5("project={$a->project}&amount={$a->amount}&freepaymentid={$a->freepaymentid}".$this->getConfig('key')); $result->setAction($a); } public function getReadme() { $ipn = Am_Html::escape($this->getPluginUrl('ipn')); return << My Configuration --> Projects Choose Actions for the product you want to configure Click on Configure Payment Methods For module Prepay and service Event choose Actions Click on Configure Check Activate payment for product and fill in your API-URL $ipn Do the same steps for module debit (Lastschrift) and service Event In your Micropayment Control Center go to My Configuration --> Payment Methods Choose your product and click on Actions for the respective payment method Click on Configure and go to Add GET-Parameters Add freepaymentid on left side and __\$freepaymentid__ on right side Click Save settings CUT; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try { parent::directAction($request, $response, $invokeArgs); } catch (Exception $e) { $this->getDi()->errorLogTable->logException($e); $sep = "\n"; $url = $this->getDi()->url('thanks',null,false,2); echo "status=ok{$sep}url=$url{$sep}target=_top{$sep}forward=1"; } } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Micropayment($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_Micropayment extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('freepaymentid'); } public function getUniqId() { return $this->request->get('auth'); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->request->get('paystatus')) { case 'PAID': $this->invoice->addPayment($this); break; case 'INIT': break; default: break; } $sep = "\n"; $url = $this->getPlugin()->getDi()->url("thanks",array('id'=>$this->invoice->getSecureId("THANKS")),false,2); echo "status=ok{$sep}url=$url{$sep}target=_top{$sep}forward=1"; } } class Am_Paysystem_Action_HtmlTemplate_Micropayment extends Am_Paysystem_Action_HtmlTemplate { protected $_template; protected $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } }PK\߰*R*R#default/plugins/payment/ecsuite.phpnu[getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ecsuite_product_id', "Ecsuite Product ID", "you must create the same product in Ecsuite for CC billing. Enter pricegroup here")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ecsuite_subaccount_id', "Ecsuite Subaccount ID", "keep empty to use default value (from config)")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ecsuite_form_id', "Ecsuite Form ID", "enter Ecsuite Form ID")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldSelect('ecsuite_form_type', "Ecsuite Form Type", "", null, array('options' => array( self::ECSUITE_CC => 'Credit Card', self::ECSUITE_900 => 'Online Check', self::ECSUITE_CHECK => 'Ecsuite 900' )))); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('account')->setLabel("Your Account Id in Ecsuite\n" . 'your account number on Ecsuite, like 112233'); $form->addText('subaccount_id')->setLabel("Subaccount number\n" . 'like 0001 or 0002'); $form->addText('datalink_user')->setLabel("DataLink Username\n" . 'read Ecsuite plugin readme (11) about'); $form->addText('datalink_pass')->setLabel("DataLink Password\n" . 'read Ecsuite plugin readme (11) about'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $subaccount_id = $invoice->getItem(0)->getBillingPlanData("ecsuite_subaccount_id") ? $invoice->getItem(0)->getBillingPlanData("ecsuite_subaccount_id") : $this->getConfig('subaccount_id'); $a = new Am_Paysystem_Action_Redirect(self::URL); $a->clientAccnum = $this->getConfig('account'); $a->clientSubacc = $subaccount_id; $a->subscriptionTypeId = $invoice->getItem(0)->getBillingPlanData("ecsuite_product_id"); $a->allowedTypes = $invoice->getItem(0)->getBillingPlanData("ecsuite_product_id"); $a->username = $user->login; $a->email = $invoice->getEmail(); $a->customer_fname = $invoice->getFirstName(); $a->customer_lname = $invoice->getLastName(); $a->address1 = $invoice->getStreet(); $a->city = $invoice->getCity(); $a->state = $invoice->getState(); $a->zipcode = $invoice->getZip(); $a->country = $invoice->getCountry(); $a->phone_number = $invoice->getPhone(); $a->payment_id = $invoice->public_id; $a->formName = $invoice->getItem(0)->getBillingPlanData("ecsuite_form_id"); $a->customVar1 = $invoice->public_id; $result->setAction($a); } function getCancelUrl(Am_Mvc_Request $request = null) { return "https://www.ecsuite.com"; } public function getSupportedCurrencies() { return array('USD', 'AUD', 'EUR', 'GBP', 'JPY', 'CAD'); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ecsuite($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ecsuite_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<Ecsuite plugin setup NOTE: If you are using this plugin, you don't need Ecsuite script to manage .htpasswd file for protected area. aMember will handle all these things for your site. 1. Login into your Ecsuite account https://webadmin.ecsuite.com/ 2. Click QuickLinks: Account Setup : Account Admin 3. Choose an existing Subaccount, or create new one, then return to this step. 4. Create the same subscription types as you have in aMember control panel, make sure that all settings are the same. 5. Create a form for your subscription types. 6. Goto Modify Subaccount - Advanced. Set Background Post Information: Approval Post URL: %root_url%/payment/ecsuite/ipn Denial Post URL: %root_url%/payment/ecsuite/ipn Click "save" button. Goto Modify Subaccount - Basic Set Approval URL: %root_url%/payment/ecsuite/thanks?customVar1=%%customVar1%% 7. Click on "User Management" link and scroll down to "Username settings". Set: "Username Type" : "USER DEFINED" "Collect Username/Password" : "Display Username, Show Password Text Field" "Min Username Length" : 4 "Max Username Length" : 16 "Min Password Length" : 4 "Max Password Length" : 16 Click "update" button. 8. Click "View Subaccount Info" in left menu to return to subaccount review screen. Remember or write down the following parameters: In top left menu, you will see number, like "911399-0001" Here, 911399 - is your Account ID, and 0001 - is SubAccount ID. Have a look to "Forms" square: you will see form numbers. Write down form numbers with type "CREDIT". "Form name" looks like "22cc" and "Sub. Type ID" looks like "19". 9. Return back to aMember CP admin panel (most possible you're already here). Go to aMember CP -> Setup -> Ecsuite Enter your account and subaccount id. Click Save. Then go to aMember CP -> Edit Products, create or edit your products and don't forget to enter neccessary Ecsuite configuration parameters (form ID, ecsuite Product ID) for each your aMember Product. 10. Try to run test payments. You may setup a testing account here: https://webadmin.ecsuite.com/tools/accountMaintenance/testSignupSettings.cgi And you may find test credit card numbers here: http://ecsuitehelp.ecsuite.com/content/test_numb_card_tls.htm 11. Contact suport@ecsuite.com to obtain username and password for Ecsuite Data Link System. You will need to send them IP address of your site. If you don't know it, ask your hosting support. Ecsuite has two options when you create a datalink user. You can make one for a specific subaccount OR for "ALL" sub accounts. They need to make the datalink user for the specific subaccount, and not use the "ALL" option. 12. Enter datalink username and pasword into Ecsuite plugin settings. 13. To test datalink you can click on the following link
      EOT; } function dateToSQL($date) { if (preg_match('/^\d{14}$/', $date)) { $s = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); return $s; } else { $tm = strtotime($date); return date('Y-m-d', $tm); } } function timeToSQL($date) { $s = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2) . ' ' . substr($date, 8, 2) . ':' . substr($date, 10, 2) . ':' . substr($date, 12, 2) . ''; return $s; } // Datalink request here; function onHourly() { if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $this->getDi()->errorLogTable->log("Ecsuite plugin error: Datalink is not configured!"); return; } define('ECSUITE_TIME_OFFSET', -8 * 3600); $last_run = $this->getDi()->store->get(self::ECSUITE_LAST_RUN); if (!$last_run || ($last_run < 19700101033324 )) $last_run = gmdate('YmdHis', time() - 15 * 3600 * 24 + ECSUITE_TIME_OFFSET); $now_run = gmdate('YmdHis', time() + ECSUITE_TIME_OFFSET); $last_run_tm = strtotime($this->timeToSQL($last_run)); $now_run_tm = strtotime($this->timeToSQL($now_run)); //Ecsuite allows to query data for last 24 hours only; if (($now_run_tm - $last_run_tm) > 3600 * 24) $now_run_tm = $last_run_tm + 3600 * 24; $now_run = date('YmdHis', $now_run_tm); //Ecsuite allow to execute datalink once in a hour only. if (($now_run_tm - $last_run_tm) <= 3600) return; $vars = array( 'startTime' => $last_run, 'endTime' => $now_run, 'transactionTypes' => 'REBILL,REFUND,EXPIRE,CHARGEBACK', 'clientAccnum' => $this->getConfig('account'), 'clientSubacc' => $this->getConfig('subaccount_id'), 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); $r = new Am_HttpRequest($requestString = self::DATALINK_URL . '?' . http_build_query($vars, '', '&')); $response = $r->send(); if (!$response) { $this->getDi()->errorLogTable->log('Ecsuite Datalink error: Unable to contact datalink server'); return; } $resp = $response->getBody(); // Log datalink requests; $this->getDi()->errorLogTable->log(sprintf("Ecsuite Datalink debug (%s, %s):\n%s\n%s", $last_run, $now_run, $requestString, $resp)); if (preg_match('/Error:(.+)/m', $resp, $regs)) { $e = $regs[1]; $this->getDi()->errorLogTable->log('Ecsuite Datalink error: ' . $e); return; } if ($resp == 1) { // Nothing to handle; } else { foreach (preg_split('/[\r\n]+/', $resp) as $line_orig) { $line = trim($line_orig); if (!strlen($line)) continue; $line = preg_split('/,/', $line); foreach ($line as $k => $v) $line[$k] = preg_replace('/^\s*"(.+?)"\s*$/', '\1', $v); $public_id = $line[3]; $invoice = $this->getDi()->invoiceTable->findByReceiptIdAndPlugin($line[3], $this->getId()); if (!$invoice) { $this->getDi()->errorLogTable->log('Ecsuite Datalink error: unable to find invoice for this record: ' . $line_orig); continue; } // "REBILL","434344","0001","0312112601000035671","2012-05-21","0112142105000024275","5.98" // "REBILL","545455","0001","0312112601000035867","2012-05-21","0112142105000024293","6.10" $transaction = null; switch ($line[0]) { case 'EXPIRE': $transaction = new Am_Paysystem_Transaction_Ecsuite_Datalink_Expire($this, $line); break; case 'REFUND': case 'CHARGEBACK': $transaction = new Am_Paysystem_Transaction_Ecsuite_Datalink_Refund($this, $line); break; case 'RENEW': case 'REBILL': case 'REBill': $transaction = new Am_Paysystem_Transaction_Ecsuite_Datalink_Rebill($this, $line); break; default: $this->getDi()->errorLogTable->log('Ecsuite Datalink error: unknown record: ' . $line_orig); } if (is_null($transaction)) continue; $transaction->setInvoice($invoice); try { $transaction->process(); } catch (Am_Exception $e) { $this->getDi()->errorLogTable->log(sprintf('Ecsuite Datalink Error: %s while handling line: %s', $e->getMessage(), $line_orig)); } } } $this->getDi()->store->set(self::ECSUITE_LAST_RUN, $now_run); } function sendTest() { define('ECSUITE_TIME_OFFSET', -8 * 3600); $last_run = $this->getDi()->store->get(self::ECSUITE_LAST_RUN); if (!$last_run || ($last_run < 19700101033324 )) $last_run = gmdate('YmdHis', time() - 15 * 3600 * 24 + ECSUITE_TIME_OFFSET); $now_run = gmdate('YmdHis', time() + ECSUITE_TIME_OFFSET); $last_run_tm = strtotime($this->timeToSQL($last_run)); $now_run_tm = strtotime($this->timeToSQL($now_run)); if (($now_run_tm - $last_run_tm) > 3600 * 24) $now_run_tm = $last_run_tm + 3600 * 24; $now_run = date('YmdHis', $now_run_tm); $vars = array( 'startTime' => $last_run, 'endTime' => $now_run, 'transactionTypes' => 'REBILL,REFUND,EXPIRE,CHARGEBACK', 'clientAccnum' => $this->getConfig('account'), 'clientSubacc' => $this->getConfig('subaccount_id'), 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); $r = new Am_HttpRequest($requestString = self::DATALINK_URL . '?' . http_build_query($vars, '', '&')); $response = $r->send(); //global problems with connection if (!$response) { return 'Ecsuite Datalink error: Unable to contact datalink server'; } $resp = $response->getBody(); $this->getDi()->errorLogTable->log(sprintf("Ecsuite Datalink debug (%s, %s):\n%s\n%s", $last_run, $now_run, $requestString, $resp)); if (preg_match('/Error:(.+)/m', $resp, $regs)) { $e = $regs[1]; //some useful instruction if error like 'authentication error' if(preg_match('/auth/i',$e)) { $r_ip = new Am_HttpRequest('https://www.amember.com/get_ip.php'); $ip = $r_ip->send(); return 'Ecsuite Datalink error: ' . $e.'

      Usually it happens because Ecsuite has wrongly
      configured your server IP address.

      IP of your webserver is:'.$ip->getBody().'

      Please copy it down, contact Ecsuite support
      and provide them with this IP as a correct IP for your website.
      Once Ecsuite reports everything is fixed
      click on the link again and make sure the change was actually applied.'; } else return 'Ecsuite Datalink error: ' . $e. ''; } } public function debugAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { //requires admin to use this tool $admin = $this->getDi()->authAdmin->getUser(); if (!$admin) return; //plugin is not configured if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $response->ajaxResponse(array('ok' => false, 'msg' => 'Ecsuite plugin error: Datalink is not configured!')); return; } $error = $this->sendTest(); if($request->isXmlHttpRequest()) { if(empty($error)) $response->ajaxResponse(array('ok' => true)); else $response->ajaxResponse(array('ok' => false, 'msg' => $error)); } else echo $error; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $actionName = $request->getActionName(); if($actionName=='debug') { $this->debugAction($request, $response, $invokeArgs); } else parent::directAction($request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Ecsuite_datalink extends Am_Paysystem_Transaction_Abstract { protected $vars; function __construct(Am_Paysystem_Abstract $plugin, $vars) { parent::__construct($plugin); $this->vars = $vars; } public function getAmount() { return $this->vars[6]; } public function getUniqId() { return $this->vars[5]; } } class Am_Paysystem_Transaction_Ecsuite_Datalink_Rebill extends Am_Paysystem_Transaction_Ecsuite_datalink { public function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_Ecsuite_Datalink_Refund extends Am_Paysystem_Transaction_Ecsuite_datalink { public function getUniqId() { return $this->vars[3] . '-RFND'; } public function getAmount() { return $this->vars[5]; } public function processValidated() { $this->invoice->addRefund($this, $this->vars[3]); } } class Am_Paysystem_Transaction_Ecsuite_Datalink_Expire extends Am_Paysystem_Transaction_Ecsuite_datalink { function processValidated() { $this->invoice->stopAccess($this); } } class Am_Paysystem_Transaction_Ecsuite extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('payment_id'); } public function getUniqId() { return $this->request->get('subscription_id'); } public function validateSource() { if ($this->request->get('clientAccnum') != $this->getPlugin()->getConfig('account')) throw new Am_Exception_Paysystem_TransactionSource(sprintf('Incorrect ECSUITE account number: [%s] instead of [%s]', $this->request->get('clientAccnum'), $this->getPlugin()->getConfig('account'))); if ($host = gethostbyaddr($addr = $this->request->getClientIp())) { if (!strlen($host) || ($addr == $host)) { // ecsuite_error("Cannot resolve host: ($addr=$host)\n"); // let is go, as some hosts are just unable to resolve names } elseif (!preg_match('/ecsuite\.com$/', $host)) throw new Am_Exception_Paysystem_TransactionSource("POST is not from ecsuite.com, it is from ($addr=$host)\n"); } return true; } public function validateStatus() { if (strlen($this->request->get('reasonForDecline')) > 0) return false; return true; } public function validateTerms() { if (intval($this->invoice->getItem(0)->getBillingPlanData("ecsuite_product_id")) != intval($this->request->get('typeId'))) { throw new Am_Exception_Paysystem_TransactionInvalid(sprintf("Product ID doesn't match: %s and %s", intval($this->invoice->getItem(0)->getBillingPlanData("ecsuite_product_id")), intval($this->request->get('typeId')))); } return true; } } class Am_Paysystem_Transaction_Ecsuite_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function process() { //redirect to thanks page only $this->invoice = $this->loadInvoice($this->request->get('customVar1')); } public function getUniqId() { } public function validateSource() { } public function validateStatus() { } public function validateTerms() { } }PK\ny''#default/plugins/payment/zombaio.phpnu[addInteger('site_id', array('class' => 'el-wide')) ->setLabel('Your Zombaio Site ID'); $form->addInteger('merchant_id', array('class' => 'el-wide')) ->setLabel("Your Zombaio Merchant ID\n" . 'Can be found in ZOA dashboard'); $form->addText('password')->setLabel("Zombaio GW Pass\n" . "Unique key for the verify site/merchant. Can be found under site information in Zombaio Online Administrator"); $form->addSelect("lang", array(), array('options' => array( 'ZOM' => 'Default (Script will detect user language based on IP)', 'US' => 'English', 'FR' => 'French', 'DE' => 'German', 'IT' => 'Italian', 'JP' => 'Japanese', 'ES' => 'Spanish', 'SE' => 'Swedish', 'KR' => 'Korean', 'CH' => 'Traditional Chinese', 'HK' => 'Simplified Chinese' )))->setLabel('Zombaio Site Language'); $form->addAdvCheckbox('validation_mode') ->setLabel("Enable Validation Mode\n" . 'Turn this on in order to validate ZScript in your Zombaio account. ' . 'After script will be validated this setting should be disabled immediately'); $form->addAdvCheckbox('dynamic_pricing') ->setLabel("Enable Dynamic Pricing\n" . 'The amount must be within the range €/$ 10.00 - €/$ 100.00 if you want to use other amounts you must get an approval from support@zombaio.com'); } public function isConfigured() { return $this->getConfig('site_id') > ''; } public function getActionURL(Invoice $invoice) { return sprintf("https://secure.zombaio.com/?%d.%d.%s", $this->getConfig('site_id'), $invoice->getItem(0)->getBillingPlanData('zombaio_pricing_id'), $this->getConfig('lang', 'ZOM') ); } public function getAPIURL($type, $params) { return sprintf("https://secure.zombaio.com/API/%s/?%s", $type, http_build_query($params, '', '&')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $action = new Am_Paysystem_Action_Form($this->getActionURL($invoice)); $action->identifier = $invoice->getLogin(); $action->FirstName = $invoice->getFirstName(); $action->LastName = $invoice->getLastName(); $action->Address = $invoice->getStreet(); $action->Postal = $invoice->getZip(); $action->City = $invoice->getCity(); $action->Email = $invoice->getEmail(); $action->Username = $invoice->getLogin(); $action->extra = $invoice->public_id; $action->return_url_approve = $this->getReturnUrl($request); $action->return_url_decline = $this->getCancelUrl($request); $action->return_url_error = $this->getCancelUrl($request); if($this->getConfig('dynamic_pricing')) { $action->DynAmount_Value = number_format($invoice->first_total,2); $action->DynAmount_Hash = md5($this->getConfig('password').number_format($invoice->first_total,2)); } $result->setAction($action); } public function getSupportedCurrencies() { return array('USD', 'EUR', 'CAD', 'JPY'); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Zombaio($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('zombaio_pricing_id', "Zombaio Pricing ID", "you must create the same product
      in Zombaio and enter its number here")); } function getReadme() { $ipn = Am_Html::escape($this->getPluginUrl('ipn')); return <<Zombaio Payment Plugin Configuration 1. Create equivalents for all aMember products in Your Zombaio account. Make sure it has the same subscription terms (period, price) as aMember Products. 2. Configure aMember CP -> Products -> Manage Products -> Edit -> Zombaio Pricing ID You can get Pricing ID from Signup form URL created by ZOMBAIO. In your Zombaio account go to Tools -> Pricing Structure -> Manage You will see Join Form URL: https://secure.zombaio.com/?287653706.1379928.ZOM In this url 287653706 - your Site ID 1379928 - Pricing ID 3. Set Postback URL (ZScript) for your site at Zombaio merchant account to $ipn You must enable "Validation mode" in plugin configuration in order to validate script url in Zombaio account. Turn "Validation mode" off after validation. aMember will not take any real actions on IPN messages in "Validation mode" CUT; } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs){ if($this->getConfig('validation_mode')) { print "OK"; exit; } try { return parent::directAction($request, $response, $invokeArgs); } catch (Exception $e) { $this->getDi()->errorLogTable->log($e); print "ERROR"; exit; } } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { list(, $trans_id) = explode("-", $payment->receipt_id); try { $r = new Am_HttpRequest($this->getAPIURL(self::API_REFUND, array( 'TRANSACTION_ID' => $trans_id, 'MERCHANT_ID' => $this->getConfig("merchant_id"), 'ZombaioGWPass' => $this->getConfig("password"), 'Refund_Type' => 1 ))); $response = $r->send(); } catch (Exception $e) { $this->getDi()->errorLogTable->logException($e); } if($response && $response->getBody() == 1){ $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id.'-zombaio-refund'); $result->setSuccess($trans); }else{ $result->setFailed(array('Error Processing Refund!')); } } } class Am_Paysystem_Transaction_Zombaio extends Am_Paysystem_Transaction_Incoming { const ACTION_ADD = 'user.add'; const ACTION_REBILL = 'rebill'; const ACTION_DELETE = 'user.delete'; function getSiteID() { return $this->request->get("SiteID") ? $this->request->get("SiteID") : $this->request->get("SITE_ID"); } function getSubscriptionID() { return $this->request->get("SubscriptionID") ? $this->request->get("SubscriptionID") : $this->request->get("SUBSCRIPTION_ID"); } public function findBySubscriptionId() { return $this->getPlugin()->getDi()->db->selectCell(" SELECT i.public_id FROM ?_invoice_payment p LEFT JOIN ?_invoice i USING(invoice_id) WHERE p.paysys_id = 'zombaio' AND (p.transaction_id LIKE ? or p.transaction_id = ?) LIMIT 1 ", $this->getSubscriptionID().'-%', $this->getSubscriptionID()); } public function findInvoiceId() { return ($this->request->get("extra") ? $this->request->get("extra") : $this->findBySubscriptionId()); } public function getUniqId() { return sprintf("%s-%s", $this->getSubscriptionID(), $this->request->get("TRANSACTION_ID")); } public function validateSource() { if($this->request->get("ZombaioGWPass") != $this->plugin->getConfig("password")) throw new Am_Exception_Paysystem_TransactionInvalid("Incorrect GW Password submited!"); if(($this->request->get('Action') == self::ACTION_ADD) && ($this->getSiteID() != $this->plugin->getConfig("site_id"))) throw new Am_Exception_Paysystem_TransactionInvalid("Transaction submited for another site!"); return true; } public function validateStatus() { if($this->request->get('Action') == self::ACTION_REBILL) return (intval($this->request->get('Success')) == 1); return true; } public function validateTerms() { if(($this->request->get('Action') == self::ACTION_ADD) && ($this->request->get("PRICING_ID") != $this->invoice->getItem(0)->getBillingPlanData('zombaio_pricing_id'))) { throw new Am_Exception_Paysystem_TransactionInvalid("Wrong PRICING ID used"); } return true; } public function processValidated(){ switch($this->request->get('Action')){ case self::ACTION_ADD : case self::ACTION_REBILL : $this->invoice->addPayment($this); break; case self::ACTION_DELETE : $this->invoice->stopAccess($this); break; } print "OK"; } }PK\. "default/plugins/payment/ipaymu.phpnu[addText('key', array('class' => 'el-wide'))->setLabel('Your API Key'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $request = new Am_HttpRequest(self::URL, Am_HttpRequest::METHOD_POST); $request->addPostParameter(array( 'key' => $this->getConfig('key'), 'action' => 'payment', 'product' => $invoice->getLineDescription(), 'price' => $invoice->first_total, 'quantity' => 1, 'comments' => $invoice->public_id, 'ureturn' => $this->getReturnUrl(), 'unotify' => $this->getPluginUrl('ipn'), 'ucancel' => $this->getCancelUrl(), 'format' => 'json' )); $log = $this->logRequest($request); $responce = $request->send(); $log->add($responce); if ($responce->getStatus() != 200) { $result->setFailed('Can not connect to iPaymu server'); return; } $r = json_decode($responce->getBody(), true); if (!isset($r['url'])) { $result->setFailed('Request Error ' . $r['Status'] .": ". $r['Keterangan']); return; } $invoice->data() ->set(self::DATA_KEY, $r['sessionID']) ->update(); $a = new Am_Paysystem_Action_Redirect($r['url']); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ipaymu($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Ipaymu extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('trx_id'); } public function validateSource() { return true; //@see findInvoiceId } public function validateStatus() { return true; } public function validateTerms() { return true; } public function findInvoiceId() { $invoice = $this->plugin->getDi()->invoiceTable->findFirstByData(Am_Paysystem_Ipaymu::DATA_KEY, $this->request->get('sid')); return $invoice ? $invoice->public_id : null; } public function processValidated() { if ($this->request->get('status') == 'berhasil') { parent::processValidated(); } } }PK\]P"default/plugins/payment/redsys.phpnu[addText('code')->setLabel('Merchant Code (FUC)'); $form->addText('terminal')->setLabel('Terminal'); $form->addPassword('secret', array('class'=>'el-wide'))->setLabel('Secret Key (CLAVE SECRETA)'); $form->addAdvRadio('version') ->setLabel('Version') ->loadOptions(array( 'sha256' => 'SHA-256', 'sha1' => 'SHA-1 (Depricated)', )); $form->setDefault('version', 'sha256'); $form->addAdvCheckbox('testing') ->setLabel("Is it a Sandbox (Testing) Account?"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form($this->host()); $vars = array( 'Ds_Merchant_Amount' => $invoice->first_total * 100, 'Ds_Merchant_Order' => $invoice->public_id, 'Ds_Merchant_MerchantCode' => $this->getConfig('code'), 'Ds_Merchant_Currency' => Am_Currency::getNumericCode($invoice->currency), 'Ds_Merchant_TransactionType' => 0, 'Ds_Merchant_MerchantURL' => $this->getPluginUrl('ipn') ); $vars['Ds_Merchant_MerchantSignature'] = strtoupper(sha1(implode('', $vars) . $this->getConfig('secret'))); $vars['Ds_Merchant_Terminal'] = $this->getConfig('terminal'); $vars['Ds_Merchant_ProductDescription'] = $invoice->getLineDescription(); $vars['Ds_Merchant_UrlOK'] = $this->getReturnUrl(); $vars['Ds_Merchant_UrlKO'] = $this->getCancelUrl(); $vars['Ds_Merchant_MerchantName'] = $this->getDi()->config->get('site_title'); switch ($this->getConfig('version', 'sha256')) { case 'sha1' : foreach ($vars as $k => $v) { $a->$k = $v; } break; case 'sha256': default: unset($vars['Ds_Merchant_MerchantSignature']); $a->Ds_SignatureVersion='HMAC_SHA256_V1'; $payload = base64_encode(json_encode($vars)); $a->Ds_MerchantParameters = $payload; $a->Ds_Signature = $this->hash($payload, $invoice->public_id); } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch($this->getConfig('version', 'sha256')) { case 'sha1': return new Am_Paysystem_Transaction_RedsysSha1($this, $request, $response, $invokeArgs); case 'sha256': default: return new Am_Paysystem_Transaction_RedsysSha256($this, $request, $response, $invokeArgs); } } function hash($payload, $order_id) { $k = base64_decode($this->getConfig('secret')); $k = $this->encrypt_3DES($order_id, $k); return base64_encode(hash_hmac('sha256', $payload, $k, true)); } function hashNotify($payload, $order_id) { $k = base64_decode($this->getConfig('secret')); $k = $this->encrypt_3DES($order_id, $k); return $this->base64_url_encode(hash_hmac('sha256', $payload, $k, true)); } function encrypt_3DES($message, $key){ $bytes = array(0,0,0,0,0,0,0,0); $iv = implode(array_map("chr", $bytes)); $ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $message, MCRYPT_MODE_CBC, $iv); return $ciphertext; } function base64_url_encode($input) { return strtr(base64_encode($input), '+/', '-_'); } function base64_url_decode($input) { return base64_decode(strtr($input, '-_', '+/')); } function host() { return $this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL; } } class Am_Paysystem_Transaction_RedsysSha256 extends Am_Paysystem_Transaction_Incoming { public function init() { $this->payload = json_decode($this->plugin->base64_url_decode($this->request->get('Ds_MerchantParameters')), true); parent::init(); } public function getUniqId() { return $this->payload['Ds_AuthorisationCode']; } public function findInvoiceId() { return $this->payload['Ds_Order']; } public function validateSource() { $this->_checkIp(<<plugin->hashNotify($this->request->get('Ds_MerchantParameters'), $this->payload['Ds_Order']) == $this->request->getParam('Ds_Signature'); } public function validateStatus() { return substr($this->payload['Ds_Response'], 0, 2) == '00'; } public function validateTerms() { return ($this->payload['Ds_Amount'] / 100) == $this->invoice->first_total && $this->payload['Ds_Currency'] == Am_Currency::getNumericCode($this->invoice->currency); } } class Am_Paysystem_Transaction_RedsysSha1 extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getParam('Ds_AuthorisationCode'); } public function findInvoiceId() { return $this->request->getParam('Ds_Order'); } public function validateSource() { $this->_checkIp(<<request->getParam($key); } $digest = strtoupper(sha1($msg . $this->plugin->getConfig('secret'))); return $digest == $this->request->getParam('Ds_Signature'); } public function validateStatus() { return substr($this->request->getParam('Ds_Response'), 0, 2) == '00'; } public function validateTerms() { return ($this->request->getParam('Ds_Amount') / 100) == $this->invoice->first_total && $this->request->getParam('Ds_Currency') == Am_Currency::getNumericCode($this->invoice->currency); } }PK\tum)default/plugins/payment/authorize-sim.phpnu[addText('login') ->setLabel("Authorize.Net API Login ID\n" . "The API login is different from your Authorize.net username. " . "You can get at the same time as the Transaction Key") ->addRule('required'); $form->addText('tkey') ->setLabel("Transaction Key\n" . "The transaction key is generated by the system " . "and can be obtained from Merchant Interface.\n" . "To obtain the transaction key from the Merchant Interface:\n" . "1. Log into the Merchant Interface\n" . "2. Select Settings from the Main Menu\n" . "3. Click on Obtain Transaction Key in the Security section\n" . "4. Type in the answer to the secret question configured on setup\n" . "5. Click Submit") ->addRule('required'); $form->addPassword('secret') ->setLabel("Secret Word\n" . "From authorize.net MD5 Hash menu " . "You have to create secret word") ->addRule('required'); $form->addAdvCheckbox('testmode') ->setLabel('Is Test Mode?'); $form->addAdvCheckbox('devmode') ->setLabel("Is Developer Account?\n" . 'Select it if you are using developer API Login ID'); } protected function getUrl() { return ($this->getConfig('devmode')) ? self::URL_TEST : self::URL_LIVE; } protected function getTestRequestStatus() { return (!$this->getConfig('devmode') && $this->getConfig('testmode')) ? 'TRUE' : 'FALSE'; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form($this->getUrl()); $a->x_version = '3.1'; $a->x_login = $this->getConfig('login'); $a->x_test_request = $this->getTestRequestStatus(); $a->x_show_form = 'PAYMENT_FORM'; $a->x_amount = $price = sprintf('%.2f', $invoice->first_total); $a->x_receipt_link_url = $this->getPluginUrl('thanks'); $a->x_relay_url = $this->getPluginUrl('thanks'); $a->x_relay_response = 'TRUE'; $a->x_cancel_url = $this->getCancelUrl(); $a->x_invoice_num = $invoice->public_id; $a->x_cust_id = $invoice->getUserId(); $a->x_description = $invoice->getLineDescription(); $a->x_fp_sequence = $invoice->public_id; $a->x_fp_timestamp = $tstamp = time(); $a->x_address = $invoice->getStreet(); $a->x_city = $invoice->getCity(); $a->x_country = $invoice->getCountry(); $a->x_state = $invoice->getState(); $a->x_zip = $invoice->getZip(); $a->x_email = $invoice->getEmail(); $a->x_first_name = $invoice->getFirstName(); $a->x_last_name = $invoice->getLastName(); $a->x_fp_hash = hash_hmac('md5', $this->getConfig('login')."^".$invoice->public_id."^".$tstamp."^".$price."^", $this->getConfig('tkey')); $result->setAction($a); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return <<https://account.authorize.net/ and go to "Home -> ACCOUNT -> Settings" menu. Installation steps: 1. Go to "Transaction Format Settings -> Transaction Submission Settings -> Payment Form" and then to "Form Fields" menu. At least uncheck all boxes near "Customer ID". You can also disable another fields to make signup a bit less painful for your customers. 2. Go to "Security Settings -> General Security Settings -> MD5-Hash" menu. Set secret word to desired values (it is important that it is the same as configured in aMember). 3. Go to "Account -> Settings -> Transaction Format Settings -> Transaction Response Settings -> Relay Response", paste in URL field this url: {$this->getPluginUrl('thanks')} and click submit. 4. If you don't know API Login ID and Transaction Key go to "Security Settings -> General Security Settings -> API Login ID and Transaction Key" menu. Find API Login ID and create new transaction key (it is important that it is the same as configured in aMember). CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_AuthorizeSim($this, $request, $response, $invokeArgs); } public function thanksAction($request, $response, array $invokeArgs) { try{ parent::thanksAction($request, $response, $invokeArgs); } catch (Am_Exception_Paysystem_TransactionInvalid $ex) { $this->invoice = $this->transaction->getInvoice(); $response->setRedirect($this->getCancelUrl()); } } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->transaction = new Am_Paysystem_Transaction_AuthorizeSim($this, $request, $response, $invokeArgs); return $this->transaction; } } class Am_Paysystem_Transaction_AuthorizeSim extends Am_Paysystem_Transaction_Incoming { protected $result; public function process() { $this->result = $this->request->getPost(); parent::process(); } public function validateSource() { return true; } public function findInvoiceId() { return (string) $this->result['x_invoice_num']; } public function validateStatus() { return ( intval($this->result['x_response_code']) == 1 && strtoupper( md5( $this->plugin->getConfig('secret') . $this->plugin->getConfig('login') . $this->result['x_trans_id'] . $this->result['x_amount'] ) ) == $this->result['x_MD5_Hash'] ); } public function getUniqId() { return (string) $this->result['x_trans_id']; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, (string)$this->result['x_amount']); return true; } }PK\EE+default/plugins/payment/fortumo/fortumo.phpnu[getDi()->productTable->customFields()->add(new Am_CustomFieldText('fortumo_service_id', 'Fortumo Service ID', 'Get it from Service Status page')); $this->getDi()->productTable->customFields()->add(new Am_CustomFieldText('fortumo_service_secret', 'Fortumo Service Secret Key', 'Get it from Service Status page')); $this->getDi()->productTable->customFields()->add(new Am_CustomFieldText('fortumo_service_xml', 'Fortumo Service XML URL', 'Get it from Service Setup page')); } public function _initSetupForm(Am_Form_Setup $form) { $form->addSelect('mode', null, array( 'options'=>array( self::MODE_LIVE=>'Live', self::MODE_SANDBOX=>'Sandbox' ) ))->setLabel('Mode'); $form->addText('message', 'size=60')->setLabel('Message with will be sent to client after sucessfull payment'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $products = $invoice->getProducts(); $data = $this->getPaymentData($products[0]->data()->get('fortumo_service_xml')); $a = new Am_Paysystem_Action_HtmlTemplate_Fortumo($this->getDir(), 'fortumo-payment.phtml'); $a->data = $data; $a->invoice = $invoice; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Fortumo($this, $request, $response, $invokeArgs); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try{ parent::directAction($request, $response, $invokeArgs); }catch(Exception $e){ $this->getDi()->errorLogTable->logException($e); $response->setRawHeader('HTTP/1.1 600 user-error'); $response->setBody("Error: ".$e->getMessage()); } } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } /** * * @param type $xmlURL * @return Am_Fortumo_Service_Details $details; * @throws Am_Exception_InternalError */ public function getPaymentData($xmlURL){ if(empty($xmlURL)) throw new Am_Exception_InternalError('Fortumo plugin configuration error: Fortumo Service XML URL is empty in product settings'); return $this->getDi()->cacheFunction->call(array($this, 'loadPaymentData'), array($xmlURL), array(), 24*3600); } /** * * @param type $xmlURL * @return Am_Fortumo_Service_Details $details; * @throws Am_Exception_InternalError */ public function loadPaymentData($xmlURL) { $req = new Am_HttpRequest($xmlURL, Am_HttpRequest::METHOD_GET); $resp = $req->send(); $body = $resp->getBody(); if(empty($body)) throw new Am_Exception_InternalError('Fortumo plugin: Empty response from service XML url'); $xml = simplexml_load_string($body); if($xml === false) throw new Am_Exception_InternalError("Fortumo plugin: Can't parse incoming xml"); if((int)$xml->status->code !== 0) throw new Am_Exception_InternalError("Fortumo plugin: Request status is not OK GOT: ".(int)$xml->status->code); return Am_Fortumo_Service_Details::create($xml); } function getReadme(){ return <<_template = $tmpl; $this->_path = $path; } function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); parent::process($action); } } class Am_Fortumo_Service_Details { protected $id; protected $countries = array(); protected $operators = array(); function __construct(SimpleXMLElement $xml) { foreach($xml->service->countries->country as $c){ if(((string) $c['approved']) != 'true') continue; $this->countries[(string) $c['code']] = (string) $c['name']; foreach($c->prices->price as $p){ $this->operators[(string) $c['code']][(string)$p->message_profile->operator['name']] = array( 'price' => (string) $p['amount'], 'currency' => (string) $p['currency'], 'shortcode' => (string) $p->message_profile['shortcode'], 'keyword' => (string) $p->message_profile['keyword'], 'all_operators' => (string) $p->message_profile['all_operators'], 'text' => (string)$c->promotional_text->local ); } } } function getCountries(){ return $this->countries; } function getOperatorsJson(){ return json_encode($this->operators); } function getOperators(){ return $this->operators; } static function create($xml){ return new self($xml); } } class Am_Paysystem_Transaction_Fortumo extends Am_Paysystem_Transaction_Incoming { protected $ip=array( '9.125.125.1', '79.125.5.95','79.125.5.205','54.72.6.126', '54.72.6.27','54.72.6.17','54.72.6.23','79.125.125.1', '79.125.5.95','79.125.5.205' ); public function getUniqId() { return $this->request->get("message_id"); } public function findInvoiceId() { $message = $this->request->get('message'); $mparts = preg_split('/\s+/', $message); return $mparts[2]; } public function validateSource() { $this->_checkIp($this->ip); return true; } public function validateStatus() { if(($this->request->get('test') == 'true') && ($this->getPlugin()->getConfig('mode') != Am_Paysystem_Fortumo::MODE_SANDBOX)) throw new Am_Exception_InputError('Test transaction received but test mode is not enabled!'); switch($this->request->get('billing_type')){ case 'MO' : return $this->request->get('status') != 'failed'; case 'MT' : return $this->request->get('status') == 'ok'; } return false; } public function validateTerms() { return true; // We have no control here; } function processValidated() { parent::processValidated(); print $this->getPlugin()->getConfig('message', 'Thanks for your payment!'); } } PK\TOO=default/plugins/payment/fortumo/scripts/fortumo-payment.phtmlnu[setLayout('layout.phtml'); ?> _script('_receipt.phtml'); ?>

      Payment information

      Please select your country:
      getOperators() as $country=>$operators) : ?>
      $op) : ?>
      In order to complete payment send SMS with text public_id;?> to number

      Send SMS with text public_id;?> to number
      PK\9hm!default/plugins/payment/okpay.phpnu[addText('wallet_id', array('size'=>40)) ->setLabel('Wallet ID or e-mail'); $form->addAdvCheckbox("dont_verify") ->setLabel( "Disable IPN verification\n" . "Usually you DO NOT NEED to enable this option. However, on some webhostings PHP scripts are not allowed to contact external web sites. It breaks functionality of the OkPay payment integration plugin, and aMember Pro then is unable to contact OkPay to verify that incoming IPN post is genuine. In this case, AS TEMPORARY SOLUTION, you can enable this option to don't contact OkPay server for verification. However, in this case \"hackers\" can signup on your site without actual payment. So if you have enabled this option, contact your webhost and ask them to open outgoing connections to www.okpay.com port 80 ASAP, then disable this option to make your site secure again."); } function isConfigured() { return (bool)$this->getConfig('wallet_id'); } public function getSupportedCurrencies() { return array( 'EUR', 'USD', 'GBP', 'HKD', 'CHF', 'AUD', 'PLN', 'JPY', 'SEK', 'DKK', 'CAD', 'RUB', 'CZK', 'HRK', 'HUF', 'NOK', 'NZD', 'RON', 'TRY', 'ZAR' ); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $result->setAction($a); $a->ok_receiver = $this->getConfig('wallet_id'); $a->ok_invoice = $invoice->public_id; $a->ok_currency = strtoupper($invoice->currency); if (!(float)$invoice->second_total) { $a->ok_kind = 'payment'; $a->ok_item_1_name = $invoice->getLineDescription(); $a->ok_item_1_price = $invoice->first_total; } else { $a->ok_kind = 'subscription'; $a->ok_s_title = $invoice->getLineDescription(); if ($invoice->first_total != $invoice->second_total || $invoice->first_period != $invoice->second_period) { $p = new Am_Period($invoice->first_period); $a->ok_s_trial_price = $invoice->first_total; $a->ok_s_trial_cycle = sprintf('%d %s', $p->getCount(), strtoupper($p->getUnit())); } $p = new Am_Period($invoice->second_period); $a->ok_s_regular_price = $invoice->second_total; $a->ok_s_regular_cycle = sprintf('%d %s', $p->getCount(), strtoupper($p->getUnit())); $a->ok_s_regular_count = ($invoice->rebill_times == IProduct::RECURRING_REBILLS) ? 0 : $invoice->rebill_times; } $a->ok_payer_first_name = $invoice->getFirstName(); $a->ok_payer_last_name = $invoice->getLastName(); $a->ok_payer_street = $invoice->getStreet(); $a->ok_payer_city = $invoice->getCity(); $a->ok_payer_state = $invoice->getState(); $a->ok_payer_zip = $invoice->getZip(); $a->ok_payer_country = $invoice->getCountry(); $a->ok_ipn = $this->getPluginUrl('ipn'); $a->ok_return_success = $this->getReturnUrl(); $a->ok_return_fail = $this->getCancelUrl(); $this->logRequest($a); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return <<Setup->Plugins 2. Configure "OKPAY" payment plugin at aMember CP->Setup->OKPAY Set Wallet ID or E-mail, linked to your wallet. 3. That's all. Now your aMember shop can receive OKPAY payments! CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Okpay_Ipn($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Okpay_Ipn extends Am_Paysystem_Transaction_Incoming { public function validateSource() { if (!$this->plugin->getConfig('dont_verify')) { $req = $this->plugin->createHttpRequest(); $req->setUrl('http://www.okpay.com/ipn-verify.html'); $req->addPostParameter('ok_verify', 'true'); foreach ($this->request->getRequestOnlyParams() as $key => $value) $req->addPostParameter($key, $value); $req->setMethod(Am_HttpRequest::METHOD_POST); $resp = $req->send(); if ($resp->getStatus() != 200 || $resp->getBody()!=="VERIFIED") throw new Am_Exception_Paysystem("Wrong IPN received, okpay [ipn-verify] answers: ".$resp->getBody().'='.$resp->getStatus()); } return true; } public function validateStatus() { return true; } public function findInvoiceId() { return $this->request->getFiltered('ok_invoice'); } public function getUniqId() { return $this->request->get('ok_txn_id'); } public function validateTerms() { $currency = $this->request->get('ok_txn_currency'); $amount = $this->request->get('ok_txn_gross'); if ($currency && (strtoupper($this->invoice->currency) != $currency)) throw new Am_Exception_Paysystem_TransactionInvalid("Wrong currency code [$currency] instead of {$this->invoice->currency}"); $type = $this->request->get('ok_txn_kind'); switch ($type) { case 'payment_link': $expect = $this->invoice->first_total; break; case 'subscription': if ($this->invoice->first_total == $this->invoice->second_total) { $expect = $this->invoice->first_total; } else { $expect = $this->request->get('ok_s_regular_payments_done') > 0 ? $this->invoice->second_total : $this->invoice->first_total; } break; } if($amount && $amount != $expect) throw new Am_Exception_Paysystem_TransactionInvalid("Payment amount is [$amount] instead of {$expect}"); return true; } public function processValidated() { switch ($this->request->get('ok_txn_status')) { case 'completed': if ($this->invoice->first_total <= 0 && $this->invoice->status == Invoice::PENDING) { $this->invoice->addAccessPeriod($this); // add first trial period } else { $this->invoice->addPayment($this); } break; case 'reversed': if($this->request->get('ok_txn_reversal_reason') == 'refund' || $this->request->get('ok_txn_reversal_reason') == 'chargeback') { $this->invoice->addRefund($this, $this->request->get('ok_txn_id'), $this->request->get('ok_txn_gross')); } break; case 'canceled': $this->invoice->setCancelled(); break; } } } PK\L#default/plugins/payment/ipaydna.phpnu[addText('tid') ->setLabel("Merchant terminal ID (TID)\n" . 'registered in gateDNA'); $form->addText('url', array('class' => 'el-wide')) ->setLabel("E-Payment URL\n" . 'to be provided by the respective account manager at gateDNA'); } public function isConfigured() { return (bool) $this->getConfig('tid') && (bool) $this->getConfig('url'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getConfig('url')); $a->customerPaymentPageText = $this->getConfig('tid'); $a->orderDescription = $invoice->public_id; $a->orderdetail = $invoice->getLineDescription(); $a->currencyText = $invoice->currency; $a->purchaseAmount = $invoice->first_total; $a->recurring = 0; $a->Email = $invoice->getUser()->email; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ('reject' == $request->getActionName()) { $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->get("orderDescription")); $url = $this->getRootUrl() . "/cancel?id=" . $invoice->getSecureId('CANCEL'); return $response->redirectLocation($url); } else { return parent::directAction($request, $response, $invokeArgs); } } function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return null; } function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ipaydna($this, $request, $response, $invokeArgs); } public function getReadme() { $signup = $this->getDi()->url('signup',null,true,true); $cancel = Am_Html::escape($this->getPluginUrl('reject')); $thanks = Am_Html::escape($this->getPluginUrl('thanks')); return <<request->get("orderReference"); } public function findInvoiceId() { return $this->request->get("orderDescription"); } public function validateSource() { return $this->request->get('customerPaymentPageText') == $this->getPlugin()->getConfig('tid'); } public function validateTerms() { return $this->request->get('purchaseAmount') == $this->invoice->first_total && $this->request->get('currencyText') == $this->invoice->currency; } public function validateStatus() { return $this->request->get('transactionStatusText') == 'SUCCESSFUL'; } }PK\Fڄ#default/plugins/payment/fasapay.phpnu[addText('fp_account') ->setLabel('Your FasaPay Store Account') ->addRule('required'); $form->addText('fp_store') ->setLabel('FasaPay Store Name') ->addRule('required'); $form->addText('security_word', array('class' => 'el-wide')) ->setLabel('FasaPay Store Security Word') ->addRule('required'); $form->addAdvCheckbox('is_sandbox') ->setLabel("Sandbox Mode Enabled\n" . "use sandbox account data from http://sandbox.fasapay.com/"); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function isConfigured() { return (bool)($this->getConfig('fp_account')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $vars = array( 'fp_acc' => $this->getConfig('fp_account'), 'fp_store' => $this->getConfig('fp_store'), 'fp_item' => $invoice->getLineDescription(), 'fp_amnt' => $invoice->first_total, 'fp_currency' => $invoice->currency, 'fp_merchant_ref' => $invoice->public_id, 'fp_success_url' => $this->getReturnUrl(), 'fp_fail_url' => $this->getCancelUrl(), 'fp_status_url' => $this->getPluginUrl('ipn'), ); $this->logRequest($vars); $action = new Am_Paysystem_Action_Form($this->getConfig('is_sandbox') ? self::URL_TEST : self::URL_LIVE); foreach ($vars as $key => $value) $action->$key = $value; $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Fasapay($this, $request, $response, $invokeArgs); } public function getReadme(){ return <<Fasapay plugin installation NOTE 1: Refund of subscription are not possible via plugin. NOTE 2: This plugin is not support recurring payments. 'Your FasaPay Store Account' - you will get after creating FasaPay account, live account from www.fasapay.com (like 'FP12345') or test account from sandbox.fasapay.com (like 'FPX1234') 'FasaPay Store Name' and 'FasaPay Store Security Word' - these params you fill at matched fields when creating FasaPay Store at 'FasaPay Merchat Account -> SCI -> Store' CUT; } } class Am_Paysystem_Transaction_Fasapay extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getFiltered("fp_batchnumber"); } public function findInvoiceId() { return $this->request->getFiltered("fp_merchant_ref"); } public function validateSource() { $str = $this->request->getFiltered("fp_paidto") . ":" . $this->request->getFiltered("fp_paidby") . ":" . $this->request->get("fp_store") . ":" . $this->request->get("fp_amnt") . ":" . $this->request->getFiltered("fp_batchnumber") . ":" . $this->request->getFiltered("fp_currency") . ":" . $this->getPlugin()->getConfig('security_word'); $hash = hash('sha256', $str); if ($hash == $this->request->getFiltered("fp_hash")) return true; Am_Di::getInstance()->errorLogTable->log( "[Fasapay-incoming]: Transaction HASH [{$this->request->getFiltered("fp_hash")}] does not match expected [$hash]" ); } public function validateStatus() { return true; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get("fp_amnt")); return true; } }PK\u8D D *default/plugins/payment/realexpayments.phpnu[addText("merchant_id") ->setLabel('Your Realex Merchant ID'); $form->addPassword('secret')->setLabel('Secret key'); $form->addAdvcheckbox('testing')->setLabel('Testing mode'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $timestamp = strftime("%Y%m%d%H%M%S"); $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); $a->MERCHANT_ID = $this->getConfig('merchant_id'); $a->ORDER_ID = $invoice->public_id; $a->CURRENCY = $invoice->currency; $a->AMOUNT = $invoice->first_total * 100; $a->TIMESTAMP = $timestamp; $a->SHA1HASH = sha1(sha1($timestamp.'.'.$this->getConfig('merchant_id').'.'.$invoice->public_id.'.'.($invoice->first_total * 100).'.'.$invoice->currency).'.'.$this->getConfig('secret')); $a->AUTO_SETTLE_FLAG = 1; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Realexpayments($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('EUR', 'GBP'); } } class Am_Paysystem_Transaction_Realexpayments extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { return $this->request->getFiltered('ORDER_ID'); } public function getUniqId() { return $this->request->getFiltered('PASREF'); } public function validateSource() { return $this->request->getFiltered('SHA1HASH') == sha1(sha1($this->request->getFiltered('TIMESTAMP').$this->getPlugin()->getConfig('merchant_id').$this->request->getFiltered('ORDER_ID').$this->request->getFiltered('RESULT').$this->request->getFiltered('MESSAGE').$this->request->getFiltered('PASREF').$this->request->getFiltered('AUTHCODE')).$this->getPlugin()->getConfig('secret')); } public function validateStatus() { return $this->request->getFiltered('RESULT') == '00'; } public function validateTerms() { return true; } }PK\dx"default/plugins/payment/dwolla.phpnu[addText('destination_id', 'size=60')->setLabel('Dwolla Account Number', 'Dwolla account ID receiving the funds. Format : XXX-XXX-XXXX.'); $form->addText('app_key', 'size=60')->setLabel('Application Key', 'The key used for the Dwolla API'); $form->addText('app_secret', 'size=60')->setLabel('Application Secret', 'The secret code used for the Dwolla API'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $req = $this->createHttpRequest(); $req->setUrl(self::POST_URL); $req->addPostParameter('Key', $this->getConfig('app_key')); $req->addPostParameter('Secret', $this->getConfig('app_secret')); $req->addPostParameter('DestinationId', $this->getConfig('destination_id')); $req->addPostParameter('OrderId', $invoice->public_id); $req->addPostParameter('Amount', $invoice->first_total); $req->addPostParameter('Test', $this->getConfig('testing') ? 'true' : 'false'); $req->addPostParameter('Redirect', $this->getPluginUrl('thanks').'?id='.$invoice->getSecureId('THANKS')); $req->addPostParameter('Name', $this->getDi()->config->get('site_title')); $req->addPostParameter('Description', $invoice->getLineDescription()); $req->addPostParameter('Callback', $this->getPluginUrl('ipn')); $this->logRequest($req); $req->setMethod(Am_HttpRequest::METHOD_POST); $response = $req->send(); $this->logResponse($response); $resp = $response->getBody(); if (strstr($resp, "Invalid+application+credentials")) { $result->setFailed("Invalid Application Credentials."); return; } elseif (strpos($resp, "heckout/") === false) { $result->setFailed("Invalid Response From Dwolla's server."); return; } $i = strpos($resp, "heckout/"); $checkout_id = substr($resp, $i + 8, 36); $a = new Am_Paysystem_Action_Redirect(self::REDIRECT_URL.$checkout_id); $result->setAction($a); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Dwolla_Thanks(this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times) return "Dwolla gateway does not support recurring payments"; } public function getReadme() { return <<request->get('checkoutId'); } public function validateSource() { return $this->request->get('signature') == hash_hmac('sha1', $this->request->get('checkoutId').'&'.$this->request->get('amount'), $this->plugin->getConfig('app_secret')); } public function validateStatus() { return ($this->request->get('test') != 'true') || $this->plugin->getConfig('testing'); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('amount')); } } class Am_Paysystem_Transaction_Dwolla extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->request->get('checkoutId'); } public function validateSource() { return $this->request->get('signature') == hash_hmac('sha1', $this->request->get('checkoutId').'&'.$this->request->get('amount'), $this->plugin->getConfig('app_secret')); } public function validateStatus() { return ($this->request->get('test') != 'true') || $this->plugin->getConfig('testing'); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('amount')); } }PK\}T$$'default/plugins/payment/mikro-odeme.phpnu[getDi()->billingPlanTable->customFields() ->add( new Am_CustomFieldSelect('mo_product_type', 'Product Type', 'Product type', null, array('options' => array( 1 => 'Physical good', 2 => 'Online Gaming', 3 => 'Content', 4 => 'Service', 5 => 'Social Networking', 6 => 'Automat', 7 => 'Bet', 8 => 'Insurance', 10 => 'Public Services', 11 => 'Mobile Insurance', 12 => 'Box Game', 13 => 'Social Gaming', 14 => 'Mobile Applications', 15 => 'Online Education' ))) ); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('user_code')->setLabel("User Code\n" . 'Refers to the partner company number given by MO'); $form->addText('pin')->setLabel("Pin\n" . 'Refers to the partner company’s API Key/PIN given by MO'); } function getPaymentType(Invoice $invoice) { if (!$invoice->rebill_times) return 1; $period = new Am_Period(); $period->fromString($invoice->second_period); switch ($period->getUnit()) { case Am_Period::MONTH: if ($period->getCount() == 1) return 2; case Am_Period::DAY: if ($period->getCount() == 7) return 3; default: throw new Am_Exception_InputError('Incorrect period unit: ' . $period->getUnit()); } } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { try { $cl = @new SoapClient(self::WSDL); $res = $cl->SaleWithTicket(array( 'token' => array( 'UserCode' => $this->getConfig('user_code'), 'Pin' => $this->getConfig('pin') ), 'input' => array( 'MPAY' => $invoice->public_id, 'Content' => $invoice->getLineDescription(), 'SendOrderResult' => true, 'PaymentTypeId' => $this->getPaymentType($invoice), 'ReceivedSMSObjectId' => '00000000-0000-0000-0000-000000000000', 'ProductList' => array( 'MSaleProduct' => array( 'ProductId' => 0, 'ProductCategory' => $invoice->getItem(0)->getBillingPlanData('mo_product_type') ? $invoice->getItem(0)->getBillingPlanData('mo_product_type') : 1, 'ProductDescription' => $invoice->getLineDescription(), 'Price' => $invoice->first_total, 'Unit' => 1 ) ), 'SendNotificationSMS' => false, 'OnSuccessfulSMS' => '', 'OnErrorSMS' => '', 'RequestGsmOperator' => 0, 'RequestGsmType' => 0, 'Url' => ROOT_URL, 'SuccessfulPageUrl' => $this->getReturnUrl(), 'ErrorPageUrl' => $this->getPluginUrl('cancel') ) )); } catch (Exception $e) { throw new Am_Exception_InputError('Unable to contact payment server:' . $e->getMessage()); } if ($res->SaleWithTicketResult->StatusCode > 0) { throw new Am_Exception_InputError("Error in data format: " . $res->SaleWithTicketResult->ErrorMessage); } // Everything is ok. Redirect User to MO: $a = new Am_Paysystem_Action_Redirect($res->SaleWithTicketResult->RedirectUrl); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_MikroOdeme($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isConfigured() { return strlen($this->getConfig('user_code')) && strlen($this->getConfig('pin')); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times && ($invoice->rebill_times != IProduct::RECURRING_REBILLS)) return 'Incorrect Rebill Times setting!'; if (($invoice->second_total > 0) && ($invoice->second_total != $invoice->first_total)) return 'First & Second price must be the same in invoice!'; if (($invoice->second_period > 0) && ($invoice->second_period != $invoice->first_period)) return 'First & Second period must be the same in invoice!'; if ($invoice->rebill_times) { $p = new Am_Period(); $p->fromString($invoice->first_period); if (($p->getUnit() == Am_Period::MONTH) && $p->getCount() == 1) return; if (($p->getUnit() == Am_Period::DAY) && $p->getCount() == 7) return; return "Incorrect billing terms. Only monthly and weekly payments are supported"; } } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'admin-cancel') return $this->adminCancelAction($request, $response, $invokeArgs); elseif ($request->getActionName() == 'cancel') { $invoice = $this->getDi()->invoiceTable->findBySecureId($request->getFiltered('id'), 'STOP' . $this->getId()); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); $result = new Am_Paysystem_Result; $payment = current($invoice->getPaymentRecords()); $this->cancelInvoice($payment, $result); $invoice->setCancelled(true); $this->_redirect('member/payment-history'); } else return parent::directAction($request, $response, $invokeArgs); } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $payment = current($invoice->getPaymentRecords()); try { $this->cancelInvoice($payment, $result); $invoice->setCancelled(true); } catch (Exception $e) { $result->setFailed($e->getMessage()); } } public function cancelInvoice(InvoicePayment $payment, Am_Paysystem_Result $result) { $log = $this->getDi()->invoiceLogRecord; $log->setInvoice($payment->getInvoice()); try { $cl = @new SoapClient("http://vas.mikro-odeme.com/services/MSubscriberManagementService.asmx?wsdl"); $res = $cl->DeactivateSubscriber(array( 'token' => array( 'UserCode' => $this->getConfig('user_code'), 'Pin' => $this->getConfig('pin') ), 'subscriberId' => $payment->getInvoice()->data()->get('mo_subscriber') )); } catch (Exception $e) { throw new Am_Exception_InputError('Unable to contact payment server:' . $e->getMessage()); } if ($res->DeactivateSubscriberResult->StatusCode > 0) { throw new Am_Exception_InputError("Error in data format: " . $res->DeactivateSubscriberResult->ErrorMessage); } } } class Am_Paysystem_Transaction_MikroOdeme extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { $public_id = $this->request->getFiltered('mpay'); if(!empty($public_id)) return $public_id; else{ $invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByData('mo_subscriber', $this->request->get('subscriber')); return $invoice->public_id; } } public function getUniqId() { return $this->request->get('order'); } public function validateSource() { print "OK"; return true; } public function validateStatus() { return $this->request->get('status') === '0'; } public function validateTerms() { return str_replace(',', '.', $this->request->get('price')) == $this->invoice->first_total; } public function processValidated() { $this->invoice->addPayment($this); $this->invoice->data()->set('mo_subscriber', $this->request->get('subscriber'))->update(); //print "OK"; } }PK\Q,)bb!default/plugins/payment/zaxaa.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'zaxaa_prod_number', "Zaxaa Product Number", "The product number registered in Zaxaa (SKU)")); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("secret", array('size' => 40)) ->setLabel("API Signature\n" . "you can find it on your Zaxaa account " . "Settings -> Account Settings (Show API Signature)"); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Zaxaa($this, $request, $response, $invokeArgs); } public function canAutoCreate() { return true; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Zaxaa integration You need to enabel 'Third Party Script Integration' for products in your account and set Notification Handler URL to $url CUT; } } class Am_Paysystem_Transaction_Zaxaa extends Am_Paysystem_Transaction_Incoming { protected $payment_number = 0; protected $_autoCreateMap = array( 'name_f' => 'cust_firstname', 'name_l' => 'cust_lastname', 'email' => 'cust_email', 'state' => 'cust_state', 'city' => 'cust_city', 'street' => 'cust_address', 'country' => 'cust_country', 'user_external_id' => 'cust_email', 'invoice_external_id' => 'ctransreceipt', ); public function autoCreateGetProducts() { $products = array(); foreach ($this->request->get('products') as $product) { $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('zaxaa_prod_number', $product['prod_number']); if ($billing_plan) { $products[] = $billing_plan->getProduct(); $this->payment_number = $product['payment_number']; } } return $products; } public function getAmount() { return moneyRound($this->request->get('trans_amount')); } public function getUniqId() { return $this->request->get('trans_receipt') . '-' . $this->payment_number; } public function validateSource() { return $this->request->get('hash_key') == $this->hash(); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->request->get('trans_type')) { case 'SALE': case 'FIRST_BILL': case 'REBILL': $this->invoice->addPayment($this); break; case 'REFUND': $this->invoice->addRefund($this, Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); break; case 'CANCELED': $this->invoice->setCancelled(true); break; } } function hash() { return strtoupper(md5( $this->request->get('seller_id') . $this->plugin->getConfig('secret') . $this->request->get('trans_receipt') . $this->request->get('trans_amount'))); } function generateInvoiceExternalId() { foreach ($this->request->get('products') as $product) { if (isset($product['recurring_id'])) return $product['recurring_id']; } return null; } public function findInvoiceId() { return null; } }PK\3b'b'$default/plugins/payment/worldpay.phpnu[addInteger('installation_id', array('size'=>20)) ->setLabel('WorldPay Installation Id (number)'); // $form->addText('callback_pw', array('size'=>20)) // ->setLabel('Callback Password (the same as configured in WorldPay)'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function isConfigured() { return $this->getConfig('installation_id') > ''; } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times && ($invoice->first_period != $invoice->second_period)) { return "WorldPay cannot handle products with different first and second period"; } return parent::isNotAcceptableForInvoice($invoice); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::TEST_URL : self::URL); $a->instId = $this->getConfig('installation_id'); $a->cartId = $invoice->public_id; $a->currency = $invoice->currency; $a->desc = $invoice->getLineDescription(); $a->email = $invoice->getEmail(); $a->name = $invoice->getName(); $a->address = $invoice->getStreet(); $a->city = $invoice->getCity(); $a->state = $invoice->getState(); $a->postcode = $invoice->getZip(); $a->country = $invoice->getCountry(); //$a->MC_callback = preg_replace('|^https?://|', '', $this->getPluginUrl('ipn')); $a->amount = $invoice->first_total; if ($this->getConfig('testing')) { $a->testMode = 100; $a->name = 'CAPTURE'; } if ($invoice->rebill_times) { if ($invoice->rebill_times != IProduct::RECURRING_REBILLS) $a->noOfPayments = $invoice->rebill_times; $a->futurePayType = 'regular'; if($invoice->rebill_times != 1) { list($c, $u) = $this->period2Wp($invoice->second_period); $a->intervalUnit = $u; $a->intervalMult = $c; } $a->normalAmount = $invoice->second_total; $a->option = 0; list($c, $u) = $this->period2Wp($invoice->first_period); $a->startDelayMult = $c; $a->startDelayUnit = $u; } $a->filterEmpty(); $result->setAction($a); } public function period2Wp($period) { $p = new Am_Period($period); switch ($p->getUnit()) { case Am_Period::DAY: return array($p->getCount(), 1); case Am_Period::MONTH: return array($p->getCount(), 3); case Am_Period::YEAR: return array($p->getCount(), 4); default: // nop. exception } throw new Am_Exception_Paysystem_NotConfigured( "Unable to convert period [$period] to Worldpay-compatible.". "Must be number of days, months or years"); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return <<_logDirectAction($request, $response, $invokeArgs); $transaction = $this->createTransaction($request, $response, $invokeArgs); if (!$transaction) { throw new Am_Exception_InputError("Request not handled - createTransaction() returned null"); } $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); } catch (Exception $e) { if ($invoiceLog) $invoiceLog->add($e); throw $e; } if ($invoiceLog) $invoiceLog->setProcessed(); if ($transaction->isFirst()) { // Redirect user to thanks page. $view = new Am_View($this->getDi()); $view->assign('url', $view->url('thanks',array('id'=>$transaction->getInvoice()->getSecureId('THANKS')))); $view->assign('text', ___('Thank you for Signing up')); $view->display('redirect.phtml'); } }catch(Exception $e) { $message = $e->getMessage(); $view = new Am_View($this->getDi()); $view->assign('error', $e->getMessage()); $view->assign('is_html', false); $view ->placeholder("head-start") ->prepend( sprintf( '', (empty($_SERVER['HTTPS']) ? 'http' : 'https'), Am_Html::escape($_SERVER['HTTP_HOST'] ) ) ); $this->invoice = $transaction->getInvoice(); if($this->invoice) $view ->placeholder("head-start") ->prepend( sprintf('', $this->getCancelUrl()) ); $view->display('error.phtml'); } } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Worldpay($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Worldpay extends Am_Paysystem_Transaction_Incoming { protected $isfirst = false; public function isFirst() { return $this->isfirst; } public function getInvoice() { return $this->invoice; } public function findInvoiceId() { return $this->request->getFiltered('cartId'); } public function getUniqId() { return $this->request->getFiltered('transId'); } public function getReceiptId() { return $this->request->getFiltered('transId'); } public function validateSource() { $this->_checkIp(<<request->get('transStatus') == 'C') throw new Am_Exception_Paysystem_TransactionInvalid("Transaction Cancelled!"); if ($this->request->get('transStatus') != 'Y') throw new Am_Exception_Paysystem_TransactionInvalid("Status is not [Y]"); if (!$this->getPlugin()->getConfig('testing') && $this->request->get('testMode')) throw new Am_Exception_Paysystem_TransactionInvalid("Test Mode Postback while plugin is not in test mode"); if ($this->getPlugin()->getConfig('installation_id') != $this->request->get('instId')) throw new Am_Exception_Paysystem_TransactionInvalid("Foreign transaction - not our instId"); return true; } public function validateTerms() { if ($this->invoice->status == Invoice::PENDING) $this->assertAmount($this->invoice->first_total, $this->getAmount(), 'First Total'); else $this->assertAmount($this->invoice->second_total, $this->getAmount(), 'Second Total'); return true; } public function getAmount() { return $this->request->get('amount'); } public function processValidated() { if ($this->invoice->status == Invoice::PENDING) $this->isfirst = true; if ($this->getAmount() > 0) $this->invoice->addPayment($this); elseif ($this->invoice->status == Invoice::PENDING) $this->invoice->addAccessPeriod($this); } } PK\Y"default/plugins/payment/nochex.phpnu[getConfig('merchant_id'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant_id', array('size' => 20)) ->setLabel(___("Nochex Merchant ID\n" . " Your default merchant id is the email address you use with your Nochex account")) ->addRule('required'); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times && ($invoice->first_period != $invoice->second_period)) { return "Nochex cannot handle products with different first and second period"; } if ($invoice->rebill_times && ($invoice->first_total != $invoice->second_total)) { return "Nochex cannot handle products with different first and second amount"; } return parent::isNotAcceptableForInvoice($invoice); } public function _process(\Invoice $invoice, \Am_Mvc_Request $request, \Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->merchant_id = $this->getConfig('merchant_id'); $a->amount = doubleval($invoice->first_total); $a->description = $invoice->getLineDescription(); if ($invoice->rebill_times) { $a->recurring_payment = 1; $p = new Am_Period($invoice->second_period); $a->interval_number = $p->getCount(); $a->interval_unit = strtoupper($p->getUnit()); $a->recurrence_number = ($invoice->rebill_times == 99999 ? 'N' : $invoice->rebill_times); } $a->order_id = $invoice->public_id; $a->success_url = $this->getReturnUrl(); $a->cancel_url = $this->getCancelUrl(); $a->callback_url = $this->getPluginUrl('ipn'); $a->billing_first_name = $invoice->getFirstName(); $a->billing_last_name = $invoice->getLastName(); $a->billing_address_street = $invoice->getStreet(); $a->billing_city = $invoice->getCity(); $a->billing_county = $invoice->getState(); $a->billing_country = $invoice->getCountry(); $a->billing_postcode = $invoice->getZip(); $a->email_address = $invoice->getEmail(); $result->setAction($a); } public function createTransaction(\Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Nochex($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } } class Am_Paysystem_Transaction_Nochex extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('order_id'); } public function getUniqId() { return $this->request->get('transaction_id'); } public function validateSource() { $req = $this->plugin->createHttpRequest(); $req->setConfig('ssl_verify_peer', false); $req->setConfig('ssl_verify_host', false); $req->setUrl('http://www.nochex.com/nochex.dll/apc/apc'); foreach ($this->request->getRequestOnlyParams() as $key => $value) $req->addPostParameter($key, $value); $req->setMethod(Am_HttpRequest::METHOD_POST); $resp = $req->send(); if (($resp->getStatus() != 200) || ($resp->getBody() != "AUTHORISED")) throw new Am_Exception_Paysystem("Wrong callback received, nochex response: " . $resp->getBody() . '=' . $resp->getStatus()); return ($this->request->get('to_email') == $this->plugin->getConfig('merchant_id')); } public function validateStatus() { return true; } public function validateTerms() { return (doubleval($this->request->get('amount')) == doubleval($this->invoice->first_total)); } function processValidated() { $this->invoice->addPayment($this); } } PK\٘--#default/plugins/payment/gumroad.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'gumroad_product_id', "Gumroad product ID", "" , array(/* ,'required' */) )); } function init() { parent::init(); if (!$this->getDi()->store->get(self::KEY)) { $this->getDi()->store->set(self::KEY, $this->getDi()->security->randomString(5)); } // Add route } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("seller_id") ->setLabel("Gumroad seller ID"); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function canAutoCreate() { return true; } public function getReadme() { $url = $this->getDi()->url('payment/gumroad/ipn',array('key'=>$this->getDi()->store->get(self::KEY)),true,2); return <<Gumroad integration Ping URL that you need to specify in your gumroad account is: $url CUT; } function createTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gumroad($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Gumroad extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name' => 'full_name', 'email' => 'email', 'user_external_id' => 'email', ); public function generateInvoiceExternalId() { return $this->request->get('sale_id'); } public function autoCreateGetProducts() { $item_name = $this->request->get('product_id'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('gumroad_product_id', $item_name); if ($billing_plan) return array($billing_plan->getProduct()); } public function getReceiptId() { return $this->request->get('order_number'); } public function getAmount() { return moneyRound($this->request->get('price')); } public function getUniqId() { return @$this->request->get('order_number'); } public function validateSource() { return ( ($this->getPlugin()->getConfig('seller_id') == $this->request->get('seller_id')) && ($_GET['key'] == $this->getPlugin()->getDi()->store->get(Am_Paysystem_Gumroad::KEY)) ); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); } public function findInvoiceId() { return $this->request->get('sale_id'); } } PK\^bL"L"#default/plugins/payment/verotel.phpnu[getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('verotel_id', "VeroTel Site ID", "")); } public function _initSetupForm(Am_Form_Setup $form) { $form->addInteger('merchant_id', array('size'=>20,'maxlength'=>20)) ->setLabel('Your Verotel Merchant ID#'); $form->addInteger('site_id') ->setLabel('Verotel Site Id'); $form->addAdvCheckbox('dynamic_pricing')->setLabel("Allow Dynamic Pricing\n". "this option does not allow to use recurring"); $form->addText('secret') ->setLabel("Private key\n" . "required for dynamic pricing only"); } public function isConfigured() { return strlen($this->getConfig('merchant_id')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if($this->getConfig('dynamic_pricing')) { $a = new Am_Paysystem_Action_Redirect(self::DYNAMIC_URL); $a->version = 1; $a->shopID = $this->getConfig('site_id'); $a->priceAmount = $invoice->first_total; $a->priceCurrency = $invoice->currency; $a->description = $invoice->getLineDescription(); $a->referenceID = $invoice->public_id; $a->signature = sha1($q = $this->getConfig('secret').":description=" . $invoice->getLineDescription() . ":priceAmount=" . $invoice->first_total . ":priceCurrency=" . $invoice->currency . ":referenceID=" . $invoice->public_id . ":shopID=" . $this->getConfig('site_id') . ":version=1"); } else { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->verotel_id = $this->getConfig('merchant_id'); $a->verotel_product = $invoice->getItem(0)->getBillingPlanData("verotel_id") ? $invoice->getItem(0)->getBillingPlanData("verotel_id") : $this->getConfig('site_id'); $a->verotel_website = $invoice->getItem(0)->getBillingPlanData("verotel_id") ? $invoice->getItem(0)->getBillingPlanData("verotel_id") : $this->getConfig('site_id'); $a->verotel_usercode = $invoice->getLogin(); $a->verotel_passcode = 'FromSignupForm';//$invoice->getUser()->getPlaintextPass(); $a->verotel_custom1 = $invoice->public_id; } $a->filterEmpty(); $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try{ parent::directAction($request, $response, $invokeArgs); } catch(Am_Exception_Paysystem $e) { $this->getDi()->errorLogTable->logException($e); print "APPROVED"; exit(); } } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $res = explode(":", $request->get('vercode')); switch($request->get('trn', @$res[3])){ case Am_Paysystem_Transaction_Verotel::ADD : case Am_Paysystem_Transaction_Verotel::REBILL : return new Am_Paysystem_Transaction_Verotel_Charge($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Verotel::DELETE : return new Am_Paysystem_Transaction_Verotel_Delete($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Verotel::CANCEL : return new Am_Paysystem_Transaction_Verotel_Cancellation($this, $request, $response,$invokeArgs); case Am_Paysystem_Transaction_Verotel::MODIFY : return new Am_Paysystem_Transaction_Verotel_Modify($this, $request, $response,$invokeArgs); default : return new Am_Paysystem_Transaction_Verotel_Dynamic($this, $request, $response,$invokeArgs); } } function getReadme() { return <<Verotel payment plugin configuration Configure your Verotel Account - contact verotel support and ask them to set: Remote User Management script URL to %root_url%/payment/verotel/ipn Run a test transaction to ensure everthing is working correctly. CUT; } } class Am_Paysystem_Transaction_Verotel extends Am_Paysystem_Transaction_Incoming { const ADD = 'add'; const REBILL = 'rebill'; const MODIFY = 'modify'; const DELETE = 'delete'; const CANCEL = 'cancel'; protected $vercode; protected $ip = array( '195.20.32.202' ); public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $this->vercode = explode(":", $request->get('vercode')); parent::__construct($plugin, $request, $response, $invokeArgs); } public function findInvoiceId() { return $this->request->get('custom1',@$this->vercode[5]); } public function getUniqId() { return $this->request->get("trn_id",@$this->vercode[6]); } public function validateSource() { $this->_checkIp($this->ip); return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { print "APPROVED"; } } class Am_Paysystem_Transaction_Verotel_Charge extends Am_Paysystem_Transaction_Verotel { //uncomment to allow users to change product on verotel site /*public function validateTerms() { if($this->invoice->isFirstPayment()) { if(doubleval($this->request->get("amount")) == $this->invoice->first_total ) return true; if($bp = Am_Di::getInstance()->billingPlanTable->findFirstBy(array('first_price' => doubleval($this->request->get("amount"))))) { Am_Di::getInstance()->db->query("DELETE from ?_invoice_item where invoice_id=?",$this->invoice->invoice_id); $this->invoice->add(Am_Di::getInstance()->productTable->load($bp->product_id),1); $this->invoice->calculate(); $this->invoice->update(); return true; } return false; } else return true; }*/ public function processValidated() { $this->invoice->addPayment($this); parent::processValidated(); } } class Am_Paysystem_Transaction_Verotel_Delete extends Am_Paysystem_Transaction_Verotel { public function processValidated() { $this->invoice->setCancelled(true); $this->invoice->stopAccess($this); parent::processValidated(); } } class Am_Paysystem_Transaction_Verotel_Cancellation extends Am_Paysystem_Transaction_Verotel { public function processValidated() { $this->invoice->setCancelled(true); parent::processValidated(); } } class Am_Paysystem_Transaction_Verotel_Modify extends Am_Paysystem_Transaction_Verotel { public function processValidated() { parent::processValidated(); } } class Am_Paysystem_Transaction_Verotel_Dynamic extends Am_Paysystem_Transaction_Incoming { protected $ip = array( '195.20.32.202', '217.115.203.18', '89.187.131.244', '93.185.97.248' ); public function findInvoiceId() { return $this->request->get('referenceID'); } public function getUniqId() { return ($this->request->get("transactionID") ?: $this->request->get("saleID")); } public function validateSource() { $this->_checkIp($this->ip); return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); print "OK"; } }PK\/default/plugins/payment/dibs-payment-window.phpnu[ '208', 'EUR' => '978', 'USD' => '840', 'GBP' => '826', 'SEK' => '752', 'AUD' => '036', 'CAD' => '124', 'ISK' => '352', 'JPY' => '392', 'NZD' => '554', 'NOK' => '578', 'CHF' => '756', 'TRY' => '949'); public function supportsCancelPage() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant', array('size' => 20, 'maxlength' => 16)) ->setlabel("Shop identification\n". "(Merchant ID)") ->addRule('required'); $form->addElement('textarea', 'hmackey', array('rows' => 4, 'style' => 'width:30%')) ->setLabel("HMAC key") ->addRule('required'); $form->addSelect('lang', array(), array('options' => array( 'da' => 'Danish', 'sv' => 'Swedish', 'nb' => 'Norwegian', 'en' => 'English' )))->setLabel("The payment window language"); $form->addAdvCheckbox('test')->setLabel("Test Mode Enabled"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::WINDOW_URL); $currency = $this->getCurrencyCode($invoice); /* Mandatory input parameters: */ $formKeyValues = array(); $formKeyValues['merchant'] = $this->getConfig('merchant'); $formKeyValues['amount'] = intval($invoice->first_total * 100); $formKeyValues['currency'] = $currency; $formKeyValues['orderid'] = $invoice->public_id; $formKeyValues['acceptReturnUrl'] = $this->getReturnUrl($request); /* Optional input parameters: */ $formKeyValues['cancelreturnurl'] = $this->getCancelUrl($request); $formKeyValues['callbackurl'] = $this->getPluginUrl('ipn'); $formKeyValues['language'] = $this->getConfig('lang'); $formKeyValues['addFee'] = 1; $formKeyValues['capturenow'] = 1; /* Invoice's parameters: */ $formKeyValues['oiTypes'] = 'QUANTITY;DESCRIPTION;AMOUNT;ITEMID'; $formKeyValues['oiNames'] = 'Items;Description;Amount;ItemId'; $i = 0; foreach($invoice->getItems() as $item) { $row_name = "oiRow".++$i; $formKeyValues[$row_name] = $item->qty.";".$item->item_title.";".intval($item->first_total * 100).";".$item->item_id; } if($this->getConfig('test')) $formKeyValues['test'] = 1; foreach($formKeyValues as $k=>$v) { $a->addParam($k, $v); } $a->addParam('MAC', $this->calculateMac($formKeyValues, $this->getConfig('hmackey'))); $result->setAction($a); } function createMessage($formKeyValues) { $string = ""; if(is_array($formKeyValues)) { ksort($formKeyValues); foreach($formKeyValues as $key => $value) { if($key != "MAC") { if(strlen($string) > 0) $string.="&"; $string.= "$key=$value"; } } return $string; } else return null; } function hextostr($hex) { $string = ""; foreach(explode("\n", trim(chunk_split($hex, 2))) as $h) { $string.=chr(hexdec($h)); } return $string; } function calculateMac($formKeyValues, $HmacKey) { if(is_array($formKeyValues)) { $messageToBeSigned = $this->createMessage($formKeyValues); $MAC = hash_hmac("sha256", $messageToBeSigned, $this->hextostr($HmacKey)); return $MAC; } else return null; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_DibsPaymentWindow($this, $request, $response, $invokeArgs); } public function getSupportedCurrencies() { return array( 'DKK', 'USD', 'GBP', 'SEK', 'AUD', 'CAD', 'ISK', 'JPY', 'NZD', 'NOK', 'CHF', 'TRY'); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getCurrencyCode($invoice) { return $this->currency_codes[strtoupper($invoice->currency)]; } function getReadme() { return <<DIBS Payment Plugin Configuration 1. Login to DIBS Administration and then go to "integration" -> Return Values. 2. Please check "orderid" parameter. CUT; } } class Am_Paysystem_Transaction_DibsPaymentWindow extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('orderid'); } public function getUniqId() { return $this->request->get("transaction"); } public function validateSource() { $request = $this->request; $p = $request->getParams(); foreach($p as $k=>$v) { if(preg_match('/(^plugin_id$)|(^action$)|(^module$)|(^controller$)|(^type$)/', $k)) { continue; } $params[$k] = $v; } $MAC = $this->getPlugin()->calculateMac($params, $this->getPlugin()->getConfig('hmackey')); if ($MAC != $this->request->get('MAC')) { throw new Am_Exception_Paysystem_TransactionInvalid("IPN validation failed: Mac is incorrect!"); } return true; } public function validateStatus() { $statuses = array('ACCEPTED', 'PENDING'); if(in_array($this->request->get("status"), $statuses)) return true; else return false; } public function validateTerms() { $invoice = $this->invoice; if($this->request->get("amount") != intval($invoice->first_total * 100)) return false; else return true; } } PK\p&"default/plugins/payment/ccbill.phpnu[ 840, 'AUD' => 036, 'EUR' => 978, 'GBP' => 826, 'JPY' => 392, 'CAD' => 124 ); public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ccbill_product_id', "ccBill Product ID", "you must create the same product in ccbill for CC billing. Enter pricegroup here")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ccbill_subaccount_id', "ccBill Subaccount ID", "keep empty to use default value (from config)")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ccbill_form_id', "ccBill Form ID", "enter ccBill Form ID")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('ccbill_flexform_id', "ccBill FlexForm ID", 'like "32be552a-7f5b-417c-b458-611e955927fd"')); } public function canAutoCreate() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('account')->setLabel("Your Account Id in ccbill\n" . 'your account number on ccBill, like 112233'); $form->addText('subaccount_id')->setLabel("Subaccount number\n" . 'like 0001 or 0002'); $form->addText('datalink_user')->setLabel("DataLink Username\n" . 'read ccBill plugin readme (11) about'); $form->addText('datalink_pass')->setLabel("DataLink Password\n" . 'read ccBill plugin readme (11) about'); $form->addAdvCheckbox('dynamic_pricing')->setLabel('Allow Dynamic Pricing'); $form->addText('salt')->setLabel("Salt\n" . 'Contact ccBill client support and receive the salt value, OR Create your own salt value (up to 32 alphanumeric characters) and provide it to ccBill client support.'); } function getDays($period) { $period = new Am_Period($period); switch($period->getUnit()){ case Am_Period::DAY: return $period->getCount(); case Am_Period::MONTH: return $period->getCount()*30; case Am_Period::YEAR: return $period->getCount()*365; case Am_Period::FIXED: return 3; //it does not matter, just return minimum allowed value } } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $subaccount_id = $invoice->getItem(0)->getBillingPlanData("ccbill_subaccount_id") ? $invoice->getItem(0)->getBillingPlanData("ccbill_subaccount_id") : $this->getConfig('subaccount_id'); $cascade_id = $invoice->getItem(0)->getBillingPlanData("ccbill_cascade_id"); $a = new Am_Paysystem_Action_Redirect($cascade_id ? self::CASCADE_URL : self::URL); if($cascade_id) $a->cascadeId = $cascade_id; $a->clientAccnum = $this->getConfig('account'); $a->clientSubacc = $subaccount_id; $a->formName = $invoice->getItem(0)->getBillingPlanData("ccbill_form_id"); $a->username = $user->login; $a->email = $invoice->getEmail(); $a->customer_fname = $invoice->getFirstName(); $a->customer_lname = $invoice->getLastName(); $a->address1 = $invoice->getStreet(); $a->city = $invoice->getCity(); $a->state = $invoice->getState(); $a->zipcode = $invoice->getZip(); $a->phone_number = $invoice->getPhone(); $a->payment_id = $invoice->public_id; $a->customVar1 = $invoice->public_id; $a->invoice = $invoice->getSecureId("THANKS"); $a->referer = $invoice->getUser()->aff_id; if($flexform_id = $invoice->getItem(0)->getBillingPlanData("ccbill_flexform_id")) { $a->setUrl('https://api.ccbill.com/wap-frontflex/flexforms/'.$flexform_id); $a->initialPrice = $invoice->first_total; $a->initialPeriod = $this->getDays($invoice->first_period); $a->currencyCode = $this->currency_codes[$invoice->currency]; if($invoice->rebill_times) { if($invoice->rebill_times == IProduct::RECURRING_REBILLS) $invoice->rebill_times = 99; $a->recurringPrice = $invoice->second_total; $a->recurringPeriod = $this->getDays($invoice->second_period); $a->numRebills = $invoice->rebill_times; $a->formDigest = md5($s = $invoice->first_total.$this->getDays($invoice->first_period).$invoice->second_total.$this->getDays($invoice->second_period).$invoice->rebill_times.$a->currencyCode.$this->getConfig('salt')); } else { $a->formDigest = md5($s = $invoice->first_total.$this->getDays($invoice->first_period).$a->currencyCode.$this->getConfig('salt')); } } elseif($this->getConfig('dynamic_pricing')) { $a->country = $invoice->getCountry(); $a->formPrice = $invoice->first_total; $a->formPeriod = $this->getDays($invoice->first_period); $a->currencyCode = $this->currency_codes[$invoice->currency]; if($invoice->rebill_times) { if($invoice->rebill_times == IProduct::RECURRING_REBILLS) $invoice->rebill_times = 99; $a->formRecurringPrice = $invoice->second_total; $a->formRecurringPeriod = $this->getDays($invoice->second_period); $a->formRebills = $invoice->rebill_times; $a->formDigest = md5($s = $invoice->first_total.$this->getDays($invoice->first_period).$invoice->second_total.$this->getDays($invoice->second_period).$invoice->rebill_times.$a->currencyCode.$this->getConfig('salt')); } else { $a->formDigest = md5($s = $invoice->first_total.$this->getDays($invoice->first_period).$a->currencyCode.$this->getConfig('salt')); } } else { $a->country = $invoice->getCountry(); $a->subscriptionTypeId = $invoice->getItem(0)->getBillingPlanData("ccbill_product_id"); $a->allowedTypes = $invoice->getItem(0)->getBillingPlanData("ccbill_product_id"); $a->allowedCurrencies = $this->currency_codes[$invoice->currency]; } $result->setAction($a); } function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $this->getDi()->errorLogTable->log("ccBill plugin error: Datalink is not configured!"); return; } //https://datalink.ccbill.com/utils/subscriptionManagement.cgi?clientSubacc=&usingSubacc=0005&subscriptionId=1071776966&username=ccbill12&password=test123&returnXML=1&action=cancelSubscription&clientAccnum=923590 $payments = $invoice->getPaymentRecords(); $subscriptionId = $payments[0]->transaction_id; $vars = array( 'clientAccnum' => $this->getConfig('account'), 'clientSubacc' => $this->getConfig('subaccount_id'), 'usingSubacc' => $this->getConfig('subaccount_id'), 'returnXML' => 1, 'action' => 'cancelSubscription', 'subscriptionId' => $subscriptionId, 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); $r = new Am_HttpRequest($requestString = self::DATALINK_SUBSCR_MANAGEMENT . '?' . http_build_query($vars, '', '&')); $response = $r->send(); if (!$response) { $this->getDi()->errorLogTable->log('ccBill Subscription Management error: Unable to contact datalink server'); throw new Am_Exception_InternalError('ccBill Subscription Management error: Unable to contact datalink server'); } $resp = $response->getBody(); // Log datalink requests; $this->getDi()->errorLogTable->log(sprintf("ccBill SMS debug:\n%s\n%s", $requestString, $resp)); $xml = simplexml_load_string($resp); if((string)$xml != "1") throw new Am_Exception_InternalError('ccBill Subscription Management error: Incorrect response received while attempting to cancel subscription!'); $result->setSuccess(); } function doUpgrade(Invoice $invoice, InvoiceItem $item, Invoice $newInvoice, ProductUpgrade $upgrade) { if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $this->getDi()->errorLogTable->log("ccBill plugin error: Datalink is not configured!"); return; } $payments = $invoice->getPaymentRecords(); $subscriptionId = $payments[0]->transaction_id; $vars = array( 'clientAccnum' => $this->getConfig('account'), // 'clientSubacc' =>$this->getConfig('subaccount_id'), 'usingSubacc' => $this->getConfig('subaccount_id'), 'subscriptionId' => $subscriptionId, 'newClientAccnum' => $this->getConfig('account'), 'newClientSubacc' => $this->getConfig('subaccount_id'), 'sharedAuthentication' => 1, 'action' => 'chargeByPreviousTransactionId', 'currencyCode' => $this->currency_codes[$invoice->currency], 'initialPrice' => $newInvoice->first_total, 'initialPeriod' => $this->getDays($newInvoice->first_period), // 'specialOffer' => 0, // 'prorate' => 1, 'returnXML' => 1, 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); if($newInvoice->rebill_times) { $vars['recurringPrice'] = $newInvoice->second_total; $vars['recurringPeriod'] = $this->getDays($newInvoice->second_period); $vars['rebills'] = $newInvoice->rebill_times == IProduct::RECURRING_REBILLS ? 99 : $newInvoice->rebill_times; }else{ $vars['recurringPrice'] = 0; $vars['recurringPeriod'] = 0; $vars['rebills'] = 0; } $r = new Am_HttpRequest($requestString = "https://bill.ccbill.com/jpost/billingApi.cgi?" . http_build_query($vars, '', '&')); $response = $r->send(); if (!$response) { $this->getDi()->errorLogTable->log('ccBill Billing API error: Unable to contact datalink server'); throw new Am_Exception_InternalError('ccBill Billing API error: Unable to contact datalink server'); } $resp = $response->getBody(); // Log datalink requests; $this->getDi()->errorLogTable->log(sprintf("ccBill billing API debug:\n%s\n%s", $requestString, $resp)); $xml = simplexml_load_string($resp); if((string)$xml->approved != "1") throw new Am_Exception_InternalError('ccBill Subscription Management error: Incorrect response received while attempting to upgrade subscription!'); $tr = new Am_Paysystem_Transaction_Ccbill_Upgrade($this, $xml); // Add payment to new invocie; $newInvoice->addPayment($tr); // Cancel old one $invoice->setCancelled(true); } /** function doUpgrade(\Invoice $invoice, \InvoiceItem $item, \Invoice $newInvoice, \ProductUpgrade $upgrade) { // Attempt to upgrade invoice; if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $this->getDi()->errorLogTable->log("ccBill plugin error: Datalink is not configured!"); return; } // https://bill.ccbill.com/jpost/billingApi.cgi?clientAccnum=900100&username=testUser&password=testPass&action=upgradeSubscription&subscriptionId=0108114301000018799&upgradeTypeId=14&upgradeClientAccnum=900100&upgradeClientSubacc=0000&specialOffer=1&sharedAuthentication=1&returnXML=1 $payments = $invoice->getPaymentRecords(); $subscriptionId = $payments[0]->transaction_id; $vars = array( 'upgradeClientAccnum' => $this->getConfig('account'), 'upgradeClientSubacc' => $this->getConfig('subaccount_id'), 'returnXML' => 1, 'action' => 'upgradeSubscription', 'subscriptionId' => $subscriptionId, 'upgradeTypeId' => $newInvoice->getItem(0)->getBillingPlanData("ccbill_product_id"), 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); $r = new Am_HttpRequest($requestString = "https://bill.ccbill.com/jpost/billingApi.cgi?" . http_build_query($vars, '', '&')); $response = $r->send(); if (!$response) { $this->getDi()->errorLogTable->log('ccBill Billing API error: Unable to contact datalink server'); throw new Am_Exception_InternalError('ccBill Billing API error: Unable to contact datalink server'); } $resp = $response->getBody(); // Log datalink requests; $this->getDi()->errorLogTable->log(sprintf("ccBill billing API debug:\n%s\n%s", $requestString, $resp)); $xml = simplexml_load_string($resp); if((string)$xml->approved != "1") throw new Am_Exception_InternalError('ccBill Subscription Management error: Incorrect response received while attempting to upgrade subscription!'); $tr = new Am_Paysystem_Transaction_Ccbill_Upgrade($this, $xml); // Add payment to new invocie; $newInvoice->addPayment($tr); // Cancel old one $invoice->setCancelled(true); } * */ public function getSupportedCurrencies() { return array_keys($this->currency_codes); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ccbill($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ccbill_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<ccBill plugin setup NOTE: If you are using this plugin, you don't need ccBill script to manage .htpasswd file for protected area. aMember will handle all these things for your site. 1. Login into your ccBill account https://webadmin.ccbill.com/ 2. Click QuickLinks: Account Setup : Account Admin 3. Choose an existing Subaccount, or create new one, then return to this step. 4. Create the same subscription types as you have in aMember control panel, make sure that all settings are the same. 5. Create a form for your subscription types. 6. Goto Modify Subaccount - Advanced. Set Background Post Information: Approval Post URL: %root_url%/payment/ccbill/ipn Denial Post URL: %root_url%/payment/ccbill/ipn Click "save" button. Goto Modify Subaccount - Basic Set Approval URL: %root_url%/payment/ccbill/thanks?customVar1=%%customVar1%%&id=%%invoice%% 7. Click on "User Management" link and scroll down to "Username settings". Set: "Username Type" : "USER DEFINED" "Collect Username/Password" : "Display Username, Show Password Text Field" "Min Username Length" : 4 "Max Username Length" : 16 "Min Password Length" : 4 "Max Password Length" : 16 Click "update" button. 8. Click "View Subaccount Info" in left menu to return to subaccount review screen. Remember or write down the following parameters: In top left menu, you will see number, like "911399-0001" Here, 911399 - is your Account ID, and 0001 - is SubAccount ID. Have a look to "Forms" square: you will see form numbers. Write down form numbers with type "CREDIT". "Form name" looks like "22cc" and "Sub. Type ID" looks like "19". 9. Return back to aMember CP admin panel (most possible you're already here). Go to aMember CP -> Setup -> ccBill Enter your account and subaccount id. Click Save. Then go to aMember CP -> Edit Products, create or edit your products and don't forget to enter neccessary ccBill configuration parameters (form ID, ccbill Product ID) for each your aMember Product. 10. Try to run test payments. You may setup a testing account here: https://webadmin.ccbill.com/tools/accountMaintenance/testSignupSettings.cgi And you may find test credit card numbers here: http://ccbillhelp.ccbill.com/content/test_numb_card_tls.htm 11. Contact suport@ccbill.com to obtain username and password for CCBill Data Link System. You will need to send them IP address of your site. If you don't know it, ask your hosting support. CCBill has two options when you create a datalink user. You can make one for a specific subaccount OR for "ALL" sub accounts. They need to make the datalink user for the specific subaccount, and not use the "ALL" option. 12. Enter datalink username and pasword into ccBill plugin settings. 13. To test datalink you can click on the following link
      EOT; } function dateToSQL($date) { if (preg_match('/^\d{14}$/', $date)) { $s = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2); return $s; } else { $tm = strtotime($date); return date('Y-m-d', $tm); } } function timeToSQL($date) { $s = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6, 2) . ' ' . substr($date, 8, 2) . ':' . substr($date, 10, 2) . ':' . substr($date, 12, 2) . ''; return $s; } // Datalink request here; function onHourly() { if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $this->getDi()->errorLogTable->log("ccBill plugin error: Datalink is not configured!"); return; } define('CCBILL_TIME_OFFSET', -8 * 3600); $last_run = $this->getDi()->store->get(self::CCBILL_LAST_RUN); if (!$last_run || ($last_run < 19700101033324 )) $last_run = gmdate('YmdHis', time() - 15 * 3600 * 24 + CCBILL_TIME_OFFSET); $now_run = gmdate('YmdHis', time() + CCBILL_TIME_OFFSET); $last_run_tm = strtotime($this->timeToSQL($last_run)); $now_run_tm = strtotime($this->timeToSQL($now_run)); //ccBill allows to query data for last 24 hours only; if (($now_run_tm - $last_run_tm) > 3600 * 24) $now_run_tm = $last_run_tm + 3600 * 24; $now_run = date('YmdHis', $now_run_tm); //ccBill allow to execute datalink once in a hour only. if (($now_run_tm - $last_run_tm) <= 3600) return; $vars = array( 'startTime' => $last_run, 'endTime' => $now_run, 'transactionTypes' => 'REBILL,REFUND,EXPIRE,CHARGEBACK', 'clientAccnum' => $this->getConfig('account'), 'clientSubacc' => $this->getConfig('subaccount_id'), 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); $r = new Am_HttpRequest($requestString = self::DATALINK_URL . '?' . http_build_query($vars, '', '&')); $log = $this->logRequest($r, 'Datalink'); $response = $r->send(); $log->add($response); $log->toggleMask(); $log->add(array( $last_run, $now_run )); if (!$response) { $this->getDi()->errorLogTable->log('ccBill Datalink error: Unable to contact datalink server'); return; } $resp = $response->getBody(); if (preg_match('/Error:(.+)/m', $resp, $regs)) { $e = $regs[1]; $this->getDi()->errorLogTable->log('ccBill Datalink error: ' . $e); return; } if ($resp == 1) { // Nothing to handle; } else { foreach (preg_split('/[\r\n]+/', $resp) as $line_orig) { $line = trim($line_orig); if (!strlen($line)) continue; $line = preg_split('/,/', $line); foreach ($line as $k => $v) $line[$k] = preg_replace('/^\s*"(.+?)"\s*$/', '\1', $v); $public_id = $line[3]; $invoice = $this->getDi()->invoiceTable->findByReceiptIdAndPlugin($line[3], $this->getId()); if (!$invoice) { // In case of free trial there is no payment. So try to find invoice by external_id $invoice = $this->getDi()->invoiceTable->findFirstByData('external_id', $line[3]); if(!$invoice || ($invoice->paysys_id != $this->getId())) { $this->getDi()->errorLogTable->log('ccBill Datalink error: unable to find invoice for this record: ' . $line_orig); continue; } } // "REBILL","434344","0001","0312112601000035671","2012-05-21","0112142105000024275","5.98" // "REBILL","545455","0001","0312112601000035867","2012-05-21","0112142105000024293","6.10" $transaction = null; switch ($line[0]) { case 'EXPIRE': $transaction = new Am_Paysystem_Transaction_Ccbill_Datalink_Expire($this, $line); break; case 'REFUND': case 'CHARGEBACK': $transaction = new Am_Paysystem_Transaction_Ccbill_Datalink_Refund($this, $line); break; case 'RENEW': case 'REBILL': case 'REBill': $transaction = new Am_Paysystem_Transaction_Ccbill_Datalink_Rebill($this, $line); break; default: $this->getDi()->errorLogTable->log('ccBill Datalink error: unknown record: ' . $line_orig); } if (is_null($transaction)) continue; $transaction->setInvoice($invoice); try { $transaction->process(); } catch (Am_Exception $e) { $this->getDi()->errorLogTable->log(sprintf('ccBill Datalink Error: %s while handling line: %s', $e->getMessage(), $line_orig)); } } } $this->getDi()->store->set(self::CCBILL_LAST_RUN, $now_run); } function sendTest() { define('CCBILL_TIME_OFFSET', -8 * 3600); $last_run = $this->getDi()->store->get(self::CCBILL_LAST_RUN); if (!$last_run || ($last_run < 19700101033324 )) $last_run = gmdate('YmdHis', time() - 15 * 3600 * 24 + CCBILL_TIME_OFFSET); $now_run = gmdate('YmdHis', time() + CCBILL_TIME_OFFSET); $last_run_tm = strtotime($this->timeToSQL($last_run)); $now_run_tm = strtotime($this->timeToSQL($now_run)); if (($now_run_tm - $last_run_tm) > 3600 * 24) $now_run_tm = $last_run_tm + 3600 * 24; $now_run = date('YmdHis', $now_run_tm); $vars = array( 'startTime' => $last_run, 'endTime' => $now_run, 'transactionTypes' => 'REBILL,REFUND,EXPIRE,CHARGEBACK', 'clientAccnum' => $this->getConfig('account'), 'clientSubacc' => $this->getConfig('subaccount_id'), 'username' => $this->getConfig('datalink_user'), 'password' => $this->getConfig('datalink_pass') ); $r = new Am_HttpRequest($requestString = self::DATALINK_URL . '?' . http_build_query($vars, '', '&')); $response = $r->send(); //global problems with connection if (!$response) { return 'ccBill Datalink error: Unable to contact datalink server'; } $resp = $response->getBody(); $this->getDi()->errorLogTable->log(sprintf("ccBill Datalink debug (%s, %s):\n%s\n%s", $last_run, $now_run, $requestString, $resp)); if (preg_match('/Error:(.+)/m', $resp, $regs)) { $e = $regs[1]; //some useful instruction if error like 'authentication error' if(preg_match('/auth/i',$e)) { $r_ip = new Am_HttpRequest('https://www.amember.com/get_ip.php'); $ip = $r_ip->send(); return 'ccBill Datalink error: ' . $e.'

      Usually it happens because ccBill has wrongly
      configured your server IP address.

      IP of your webserver is:'.$ip->getBody().'

      Please copy it down, contact ccBill support
      and provide them with this IP as a correct IP for your website.
      Once ccBill reports everything is fixed
      click on the link again and make sure the change was actually applied.'; } else return 'ccBill Datalink error: ' . $e. ''; } } public function debugAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { //requires admin to use this tool $admin = $this->getDi()->authAdmin->getUser(); if (!$admin) return; //plugin is not configured if (!$this->getConfig('datalink_user') || !$this->getConfig('datalink_pass')) { $response->ajaxResponse(array('ok' => false, 'msg' => 'ccBill plugin error: Datalink is not configured!')); return; } $error = $this->sendTest(); if($request->isXmlHttpRequest()) { if(empty($error)) $response->ajaxResponse(array('ok' => true)); else $response->ajaxResponse(array('ok' => false, 'msg' => $error)); } else echo $error; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $actionName = $request->getActionName(); if($actionName=='debug') { $this->debugAction($request, $response, $invokeArgs); } else parent::directAction($request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Ccbill_Upgrade extends Am_Paysystem_Transaction_Abstract { protected $xml; function __construct(Am_Paysystem_Abstract $plugin, $xml) { parent::__construct($plugin); $this->xml = $xml; } public function getUniqId() { return (string)$this->xml->subscriptionId; } } class Am_Paysystem_Transaction_Ccbill_datalink extends Am_Paysystem_Transaction_Abstract { protected $vars; function __construct(Am_Paysystem_Abstract $plugin, $vars) { parent::__construct($plugin); $this->vars = $vars; } public function getAmount() { return $this->vars[6]; } public function getUniqId() { return $this->vars[5]; } } class Am_Paysystem_Transaction_Ccbill_Datalink_Rebill extends Am_Paysystem_Transaction_Ccbill_datalink { public function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_Ccbill_Datalink_Refund extends Am_Paysystem_Transaction_Ccbill_datalink { public function getUniqId() { return $this->vars[3] . '-RFND'; } public function getAmount() { return $this->vars[5]; } public function processValidated() { $this->invoice->addRefund($this, $this->vars[3]); } } class Am_Paysystem_Transaction_Ccbill_Datalink_Expire extends Am_Paysystem_Transaction_Ccbill_datalink { function processValidated() { $this->invoice->stopAccess($this); } } class Am_Paysystem_Transaction_Ccbill extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'login' => 'username', 'pass' => 'password', 'name_f' => 'customer_fname', 'name_l' => 'customer_lname', 'country' => 'country', 'state' => 'state', 'email' => 'email', 'city' => 'city', 'street' => 'address1', 'user_external_id' => 'email', 'invoice_external_id' => array('originalSubscriptionId', 'subscription_id'), ); public function autoCreateGetProducts() { $cbId = $this->request->getFiltered('productId') ? $this->request->getFiltered('productId') : intval($this->request->getFiltered('typeId')); if (empty($cbId)) return; $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('ccbill_product_id', $cbId); if (!$pl) return; $pr = $pl->getProduct(); if (!$pr) return; return array($pr); } public function findInvoiceId() { return $this->request->get('payment_id'); } public function getUniqId() { return $this->request->get('subscription_id'); } public function validateSource() { if ($this->request->get('clientAccnum') != $this->getPlugin()->getConfig('account')) throw new Am_Exception_Paysystem_TransactionSource(sprintf('Incorrect CCBILL account number: [%s] instead of [%s]', $this->request->get('clientAccnum'), $this->getPlugin()->getConfig('account'))); if ($host = gethostbyaddr($addr = $this->request->getClientIp())) { if (!strlen($host) || ($addr == $host)) { // ccbill_error("Cannot resolve host: ($addr=$host)\n"); // let is go, as some hosts are just unable to resolve names } elseif (!preg_match('/ccbill\.com$/', $host)) throw new Am_Exception_Paysystem_TransactionSource("POST is not from ccbill.com, it is from ($addr=$host)\n"); } return true; } public function validateStatus() { if (strlen($this->request->get('reasonForDecline')) > 0) return false; return true; } public function validateTerms() { if($this->getPlugin()->getConfig('dynamic_pricing')) return true; if($this->invoice->getItem(0)->getBillingPlanData("ccbill_flexform_id")) return true; if (intval($this->invoice->getItem(0)->getBillingPlanData("ccbill_product_id")) != intval($this->request->get('typeId'))) { throw new Am_Exception_Paysystem_TransactionInvalid(sprintf("Product ID doesn't match: %s and %s", intval($this->invoice->getItem(0)->getBillingPlanData("ccbill_product_id")), intval($this->request->get('typeId')))); } return true; } public function processValidated() { if(!count($this->invoice->getAccessRecords()) && (floatval($this->invoice->first_total) == 0)) { if(!$this->invoice->data()->get('external_id') && $this->request->get('subscription_id')) { $this->invoice->data()->set('external_id', $this->request->get('subscription_id'))->update(); } $this->invoice->addAccessPeriod($this); } else { $this->invoice->addPayment($this); } } } class Am_Paysystem_Transaction_Ccbill_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function process() { //redirect to thanks page only $this->invoice = $this->loadInvoice($this->request->get('customVar1')); } public function getUniqId() { } public function validateSource() { } public function validateStatus() { } public function validateTerms() { } }PK\H>_ default/plugins/payment/free.phpnu[isZero()) return array(___('Cannot use FREE payment plugin with a product which cost more than 0.0')); } function _process(/* Invoice */$invoice, /*Am_Mvc_Request */$request, /*Am_Paysystem_Result */$result) { $result->setSuccess(new Am_Paysystem_Transaction_Free($this)); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function createTransaction(/* Am_Mvc_Request */$request, /*Am_Mvc_Response */$response, array $invokeArgs) { return null; } public function onSetupForms(Am_Event_SetupForms $e) { return; } }PK\ 66%default/plugins/payment/payanyway.phpnu[addText('url') ->setLabel(___("Payment System Domain\n" . 'Leave default value if you are not sure')) ->setValue(self::DOMAIN); $form->addText('mnt_id') ->setLabel(___("Shop Id\n" . 'Unique Shop ID in the system')); $form->addAdvCheckbox('test_mode')->setLabel(___('Test Mode')); $form->addSelect('locale', array(), array('options'=>array('ru'=>'ru', 'eng'=>'eng')))->setLabel(___('Language')); $form->addText('secret_code') ->setLabel(___('Data Integrity Code')); } public function getSupportedCurrencies() { return array( 'RUB', 'USD'); } function getOutgoingSignature(Am_Paysystem_Action_Redirect $a){ $sig = md5($ss = sprintf('%s%s%s%s%s%s', $a->MNT_ID, $a->MNT_TRANSACTION_ID, $a->MNT_AMOUNT, $a->MNT_CURRENCY_CODE, $a->MNT_TEST_MODE, $this->getConfig('secret_code') )); return $sig; } function getIncomingSignature(Am_Mvc_Request $r){ $sig = md5(sprintf('%s%s%s%s%s%s%s', $r->get('MNT_ID'), $r->get('MNT_TRANSACTION_ID'),$r->get('MNT_OPERATION_ID'), $r->get('MNT_AMOUNT'), $r->get('MNT_CURRENCY_CODE'), $r->get('MNT_TEST_MODE'), $this->getConfig('secret_code') )); return $sig; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect('https://'.$this->getConfig('url', self::DOMAIN).'/assistant.htm'); $a->MNT_ID = $this->getConfig('mnt_id'); $a->MNT_TRANSACTION_ID = $invoice->public_id; $a->MNT_CURRENCY_CODE = $invoice->currency; $a->MNT_AMOUNT = $invoice->first_total; $a->MNT_TEST_MODE = $this->getConfig('test_mode')? 1:0; $a->MNT_DESCRIPTION = $invoice->getLineDescription(); $a->MNT_SUCCESS_URL = $this->getReturnUrl(); $a->MNT_FAIL_URL = $this->getCancelUrl(); $a->MNT_SIGNATURE = $this->getOutgoingSignature($a); $a->__set('moneta.locale', $this->getConfig('locale', 'ru')); $result->setAction($a); } function getReadme() { return << «Управление» -> «Редактировать счет» Впишите следующий адрес в поле «Pay URL»: %root_url%/payment/payanyway/ipn CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payanyway($this, $request,$response,$invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function isNotAcceptableForInvoice(Invoice $invoice) { if($invoice->rebill_times){ return array(___('Payanyway plugin does not support recurring billing!')); } } } class Am_Paysystem_Transaction_Payanyway extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('MNT_OPERATION_ID'); } public function findInvoiceId() { return $this->request->get('MNT_TRANSACTION_ID'); } public function validateSource() { if($this->getPlugin()->getIncomingSignature($this->request) != $this->request->get('MNT_SIGNATURE')){ throw new Am_Exception_Paysystem_TransactionSource( sprintf('Signature verification failed got=%s calculated=%s', $this->request->get('MNT_SIGNATURE'), $this->getPlugin()->getIncomingSignature($this->request))); } return true; } public function validateStatus() { return true; } public function validateTerms() { if($this->request->get('MNT_AMOUNT') != $this->invoice->first_total) throw new Am_Exception_Paysystem_TransactionInvalid('Invalid amount for transaction. Got '.$this->request->get('MNT_AMOUNT')); return true; } function processValidated() { $this->invoice->addPayment($this); echo "SUCCESS"; } } PK\m,o&default/plugins/payment/algocharge.phpnu[addText('merchant_id') ->setLabel('Your Algocharge Merchand ID') ->addRule('required'); $form->addText('merchant_desc', array('maxlength' => 9)) ->setLabel("Description\n" . "typically value is the name of the company\nmax length - 9 symbols"); $form->addAdvCheckbox('is_adult') ->setLabel('For Adult Products'); $form->addAdvCheckbox('test_mode') ->setLabel('Test Mode Enabled'); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function isConfigured() { return (bool)($this->getConfig('merchant_id')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $vars = array( 'INAME' => 'purchase', 'Mer' => $this->getConfig('merchant_desc'), 'MerchantID' => $this->getConfig('merchant_id'), 'TransactionID' => $invoice->public_id, 'UserDesc' => strlen($desc = $invoice->getLineDescription()) > 256 ? substr($desc, 0, 253) . "..." : $desc, 'Amount' => $invoice->first_total, 'Currency' => $invoice->currency, 'itemType' => $this->getConfig('is_adult', false) ? 1 : 3, 'SuccessUserPage' => $this->getPluginUrl('thanks'), 'FailureUserPage' => $this->getCancelUrl(), 'MerchantData' => $invoice->getSecureId(self::SECURE_STRING . $invoice->first_total), 'ResultPageMethod' => 'POST', 'settleImmediate' => 1, //? 'FirstName' => $user->name_f, 'LastName' => $user->name_l, 'email' => $user->email, 'Address' => $user->street, 'City' => $user->city, 'postCode' => $user->zip, 'Country' => $user->country, 'State' => $user->state, 'Telephone' => $user->phone, ); $this->logRequest($vars); $action = new Am_Paysystem_Action_Form($this->getConfig('test_mode') ? self::URL_PAY_TEST : self::URL_PAY_LIVE); foreach ($vars as $key => $value) $action->$key = $value; $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Algocharge($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Algocharge($this, $request, $response, $invokeArgs); } public function getReadme(){ return <<Algocharge plugin installation NOTE 1: Refund of subscription are not possible via plugin. NOTE 2: This plugin is not support recurring payments. For testing use: Merchant ID: 212643 Check 'Test Mode Enabled' option Test Credit Cards: 5100981398990605 5100984857420395 5100987211166349 5100988144651688 5100988917934055 5100989508431394 All expiration dates: 12/2014 CUT; } } class Am_Paysystem_Transaction_Algocharge extends Am_Paysystem_Transaction_Incoming{ public function getUniqId() { return microtime(true) . rand(10000, 99990); } public function findInvoiceId() { return $this->request->get("TransactionID"); } public function validateSource() { return (bool)(Am_Di::getInstance()->invoiceTable->findBySecureId($this->request->get("MerchantData"), Am_Paysystem_Algocharge::SECURE_STRING . $this->request->get("Amount"))); } public function validateStatus() { return (bool) ($this->request->getFiltered('RetCode') == 0); } public function validateTerms() { return true; } }PK\- "default/plugins/payment/dotpay.phpnu[addText("seller_id") ->setLabel('Your DotPay Seller ID'); $form->addSelect('lang', array(), array('options' => array( 'en' => 'English', 'de' => 'German', 'fr' => 'French', 'cz' => 'Czech', 'es' => 'Spanish', 'it' => 'Italian', 'ru' => 'Russian', 'pl' => 'Polish' )))->setLabel('The payment window language'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect(self::LIVE_URL); $a->id = $this->getConfig('seller_id'); $a->amount = $invoice->first_total; $a->currency = $invoice->currency; $a->description = $invoice->getLineDescription(); $a->control = $invoice->public_id; $a->URL = $this->getReturnUrl(); $a->type = '0'; $a->lang = $this->getConfig('lang'); $a->URLC = $this->getPluginUrl('ipn'); $a->firstname = $u->name_f; $a->lastname = $u->name_l; $a->email = $u->email; $a->street = $u->street; $a->state = $u->state; $a->city = $u->city; $a->postcode = $u->zip; $a->country = $u->country; $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Dotpay($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('PLN', 'EUR', 'GBP', 'JPY', 'USD'); } } class Am_Paysystem_Transaction_Dotpay extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getFiltered('t_id'); } public function validateSource() { $this->_checkIp(<<request->getFiltered('id') == $this->getPlugin()->getConfig('seller_id'); } public function validateStatus() { return $this->request->getFiltered('status') == 'OK'; } public function validateTerms() { return true; } public function processValidated() { parent::processValidated(); echo "OK"; } }PK\%default/plugins/payment/payumoney.phpnu[addText('key') ->setLabel('PayUMoney Key') ->addRule('required'); $form->addText('salt') ->setLabel('PayUMoney Salt') ->addRule('required'); $form->addAdvCheckbox('testing') ->setLabel("Test Mode"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { /* @var $user User*/ $user = $invoice->getUser(); $a = new Am_Paysystem_Action_Form($this->getConfig('testing') ? self::URL_TEST : self::URL_LIVE); $post = array( 'key' => $this->getConfig('key'), 'txnid' => $invoice->public_id, 'amount' => $invoice->first_total, 'productinfo' => $invoice->getLineDescription(), 'firstname' => $user->name_f, 'lastname' => $user->name_l, 'email' => $user->email, 'phone' => $user->phone, 'surl' => $this->getPluginUrl('thanks'), 'furl' => $this->getCancelUrl(), 'curl' => $this->getCancelUrl(), 'service_provider' => 'payu_paisa' ); $post['hash'] = hash("sha512", "{$post['key']}|{$post['txnid']}|{$post['amount']}|{$post['productinfo']}|{$post['firstname']}|{$post['email']}" . "|||||||||||" . $this->getConfig('salt')); foreach ($post as $k => $v) if($k) $a->$k = $v; $this->logRequest($post, 'POST'); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payumoney($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return <<PayU Money plugin readme Ask PayU Money support your Key & Salt and configure plugin. Test Info: Test Card Name: any name Test Card Number: 5123456789012346 Test CVV: 123 Test Expiry: May 2017 CUT; } } class Am_Paysystem_Transaction_Payumoney extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('payuMoneyId'); } public function validateSource() { $calcHash = hash("sha512", $this->plugin->getConfig('salt') . "|" . $this->request->get('status') . "|||||||||||" . $this->request->get('email') . "|" . $this->request->get('firstname') . "|" . $this->request->get('productinfo') . "|" . $this->request->get('amount') . "|" . $this->request->get('txnid') . "|" . $this->request->get('key')); return $calcHash == $this->request->get('hash'); } public function validateStatus() { return ($this->request->get('status') == "success"); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('amount')); return true; } public function findInvoiceId() { return $this->request->get('txnid'); } } PK\F"͸&default/plugins/payment/przelewy24.phpnu[addText('merchant_id')->setLabel('Merchant ID'); $form->addText('pos_id')->setLabel('Shop ID (default: Merchant ID)'); $form->addPassword('crc')->setLabel('CRC Key'); $form->addAdvCheckbox('testing') ->setLabel("Is it a Sandbox(Testing) Account?"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $req = new Am_HttpRequest($this->host() . 'trnRegister', Am_HttpRequest::METHOD_POST); $vars = array( 'p24_merchant_id' => $this->getConfig('merchant_id'), 'p24_pos_id' => $this->getConfig('pos_id'), 'p24_session_id' => $invoice->public_id, 'p24_amount' => $invoice->first_total * 100, 'p24_currency' => $invoice->currency, 'p24_description' => $invoice->getLineDescription(), 'p24_email' => $user->email, 'p24_country' => $user->country, 'p24_url_return' => $this->getReturnUrl(), 'p24_url_status' => $this->getPluginUrl('ipn'), 'p24_time_limit' => 5, 'p24_encoding' => 'UTF-8', 'p24_api_version' => '3.2' ); $vars['p24_sign'] = $this->sign(array( $vars['p24_session_id'], $vars['p24_pos_id'], $vars['p24_amount'], $vars['p24_currency'] )); $req->addPostParameter($vars); $this->logRequest($req); $resp = $req->send(); $this->logResponse($resp); if ($resp->getStatus() != 200) { $result->setFailed('Incorrect HTTP response status: ' . $resp->getStatus()); return; } parse_str($resp->getBody(), $params); if ($params['error']) { $result->setFailed(explode('&', $params['errorMessage'])); return; } $a = new Am_Paysystem_Action_Redirect($this->host() . 'trnRequest/' . $params['token']); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Przelewy24($this, $request, $response, $invokeArgs); } function sign($params) { $params[] = $this->getConfig('crc'); return md5(implode('|', $params)); } function host() { return $this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Address Brick to your signup form with country field enabled. Information about user country is requered for this payment plugin. You can modify signup form at aMember CP -> Configuration -> Forms Editor CUT; } } class Am_Paysystem_Transaction_Przelewy24 extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getParam("p24_order_id"); } public function findInvoiceId() { return $this->request->getParam("p24_session_id"); } public function validateSource() { $this->_checkIp(<<plugin->sign(array( $this->request->getParam('p24_session_id'), $this->request->getParam('p24_order_id'), $this->request->getParam('p24_amount'), $this->request->getParam('p24_currency') )) != $this->request->getParam('p24_sign')) { return false; } //this request is very important. Transaction will not //be completed on payment sytem side until we verify it $req = new Am_HttpRequest($this->plugin->host() . 'trnVerify', Am_HttpRequest::METHOD_POST); $req->addPostParameter(array( 'p24_merchant_id' => $this->request->getParam('p24_merchant_id'), 'p24_pos_id' => $this->request->getParam('p24_pos_id'), 'p24_session_id' => $this->request->getParam('p24_session_id'), 'p24_amount' => $this->request->getParam('p24_amount'), 'p24_currency' => $this->request->getParam('p24_currency'), 'p24_order_id' => $this->request->getParam('p24_order_id'), 'p24_sign' => $this->plugin->sign(array( $this->request->getParam('p24_session_id'), $this->request->getParam('p24_order_id'), $this->request->getParam('p24_amount'), $this->request->getParam('p24_currency') )) )); $this->log->add($req); $resp = $req->send(); $this->log->add($resp); if ($resp->getStatus() != 200) return false; parse_str($resp->getBody(), $params); if ($params['error']) return false; return true; } public function validateStatus() { return true; } public function validateTerms() { return $this->invoice->currency == $this->request->getParam("p24_currency") && 100 * $this->invoice->first_total == $this->request->getParam("p24_amount"); } }PK\oVV default/plugins/payment/epdq.phpnu[addText('pspid') ->setLabel('Your affiliation name in ePDQ'); $form->addPassword('shain', array('class' => 'el-wide')) ->setLabel("SHA IN Pass Phrase\n" . "can be found on page Configuration -> Technical Information -> Data and origin verification in your ePDQ account"); $form->addPassword('shaout', array('class' => 'el-wide')) ->setLabel("SHA OUT Pass Phrase\n" . "can be found on page Configuration -> Technical Information -> Transaction Feedback in your ePDQ account"); $form->addAdvCheckbox('testing') ->setLabel("Is it a Sandbox(Testing) Account?"); } public function getUrl() { return $this->getConfig('testing') ? self::ACTION_URL_TEST : self::ACTION_URL_PROD; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getUrl()); $params = array( 'PSPID' => $this->getConfig('pspid'), 'ORDERID' => $invoice->public_id, 'AMOUNT' => $invoice->first_total * 100, 'CURRENCY' => $invoice->currency, 'LANGUAGE' => 'en_US', 'CN' => $invoice->getUser()->getName(), 'EMAIL' => $invoice->getUser()->email, 'COM' => $invoice->getLineDescription(), 'ACCEPTURL' => $this->getReturnUrl(), 'DECLINEURL' => $this->getCancelUrl(), 'CANCELURL' => $this->getCancelUrl(), 'EXCEPTIONURL' => $this->getCancelUrl() ); ksort($params, SORT_STRING); $s = ''; foreach ($params as $k => $v) { $s .= $k . '=' . $v . $this->getConfig('shain'); } $params['SHASIGN'] = strtoupper(sha1($s)); foreach ($params as $k => $v) { $a->{$k} = $v; } $this->logRequest($a); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Epdq($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Epdq_Thanks($this, $request, $response, $invokeArgs); } public function getReadme() { $ipn = Am_Html::escape($this->getPluginUrl('ipn')); return << Technical Information -> Transaction Feedback' in your ePDQ account and set it to $ipn CUT; } } class Am_Paysystem_Transaction_Epdq extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get("PAYID"); } public function findInvoiceId() { return $this->request->get("orderID"); } public function validateSource() { $params = array(); foreach ($this->request->getRequestOnlyParams() as $k => $v) { $params[strtoupper($k)] = $v; } ksort($params, SORT_STRING); $sign = $params['SHASIGN']; unset($params['SHASIGN']); $s = ''; foreach ($params as $k => $v) { $s .= $k . '=' . $v . $this->getPlugin()->getConfig('shaout'); } return ($sign && $sign == strtoupper(sha1($s))); } public function validateStatus() { return in_array($this->request->get('STATUS'), array(5,9)); } public function validateTerms() { return (float)$this->invoice->first_total == (float)$this->request->get('amount') && $this->invoice->currency == $this->request->get('currency'); } } class Am_Paysystem_Transaction_Epdq_Thanks extends Am_Paysystem_Transaction_Epdq { function process() { try { parent::process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { // do nothing if transaction is already handled } if (Am_Di::getInstance()->config->get('auto_login_after_signup')) Am_Di::getInstance()->auth->setUser($this->invoice->getUser(), $this->request->getClientIp()); } }PK\G5default/plugins/payment/monelib/public/buyCode_fr.pngnu[PNG  IHDRIBd֐.tEXtCreation Timemar. 18 nov. 2008 17:49:11 +0100c@tIME %3< pHYs  ~gAMA asIDATx] xT~k2C¢CX"₂R뵖GZRr*^lmUD-."[ D d_fsd2 C$`d?sHq-HƕW^FD1c mݘnD ĊYh k dMࢁt>}:T*|IO#==op 7`̘1"Ǚ3gں %~vO?ǨQҽ^8عs'Ν ++@QHVڵkѭ[7\{mcW^i̒t͚5l&'~5 4C3+-59m)lglJ֢̯}F*ߍMu>Y h0m4!%%Nʕ+믋&LСC1rHraƌ?~Cylk<͆ ۷'OiֱE'O/~fǎgСN'ݻy涞"dz/}y 툄Dw֗bشrS>lƠK̘ Q=HKKƍ 9i$\uUxꩧ+Vk/_^z {ixwq5hԩMڵd #3xCq;̙s@HD=)= Z+ZǴOF}!.\%kڦ`BWߊ,Gv*`‡#}B+D}ڶ.,$ HA \4H5 &p A.ĴziI#$l; |n$ 4 ,-G*d' C DB}o,G9MLz YϭB&{2}a~;˸yw[ŋ2%13/J63n t(Sj Y:O(GdďT OҴY$qW?Ɣ[򊽲 ӡӁB?3!1z&ޒ8rSW[ E2>ڸԂtp6?D~ MA.0 }|V|Nq?"Ac5|ٜK?[X Rgh!jk43X='|VlSQ[k=TףT #>?m kS[p~ʐ1mQQg4&ew'v ;5Qs<0K3ct_{ )yN7+SL*GV‹㵥~LMz2vy'ZoRjOEE]Iiia%fLT7eE14^m ѣ-((h=IDtی* ~ѩ.Y0!{|9$V+cr>$d%ʔڀG@\ N*YH/~A@d4mD&#晻I4_VI~MwZ/O-@cw#@JM*Ϥ RDjG `ϱ .7-)G3?IF`%չP+\?-qx%1|͝ j=$a@IHSb51RjSMci6I*|u ##ep7W6F ^O[KsB2?c繑ݗ;&q]kɱlZB,Y*Z}rCf}oe>HZ  ͒t^GX(F>>(0QM_rh]W[#'JWId s64)MeU;y>O)>g̑ ƠK%:*uHߴ-; +B4ɬj#M4}ZWrGrJUʎ.zyvHM+5+j EV^qSEFeĒ*x'({sӿ*yjgg)e x X6;|(4fW}?D!}'!-%{ϟ5E%vex/x"B졲Ã, n܄t~嵁R'Re+w(<.Msh|%9xfn^d($ż(P;1f,(GXm/ :u;6ܝ$Ig ~rG䳈5{fv,]2IF'`fddOʼnؾ}x!JK HY3# $ ~_ܵkWyy}FF*6jZUz$ym]qy(-;۷"77ww}w=D6Yr<BkI!CT9s`#jK!K>zjq- Nʥuc ѯo?,_\y5xz&u0xrPfcE APKT{Q鬀GAڊLK1/X\ɘx1~:ٳ'v~4iO!%*bM{rq]Bn^9X^D6L :Y:a@@Ty0tܖy'n6ARI&&A Č/~f"7ztl]6 pq~ (>9擅!/Î3ا0 gυnUD 3QHܵ@LuUب9ʊg>QHLT>NO?g2 H{Nl/ٌ]%ۉb9SHC(Y*9_#Mȡuw2^Xhyl,4o߾ٳp}vI0X^QZnGY.>"hU]*kcW$mU> ŕDZtJ ߃55 ׏v5 g73`ى3+oq_igO۰ڈwrJQ,Si>_Cmk~V1V]gś喰8'[^JJ3pբ/Y*}e(qc$FeG$a֙!,#T R//6c0tUXn8獬u~ZE^5 , ZSS{-iSQoT"jqp]Eo[&Q4o;ksM^8ȉbUr802'_Ed"2t9uc]3o*9Q|]wâl+$aY[c+Z"RIQ61Sփ[g[ كra"3C\lZ60,.?Amj8~GR]'}Co~Nj+6B$hrXnbOn ݟko}Pph!cǎa>@Y!ZEff6c2:#X .`Ϟ]up7``!ik67, ? lٱUF#.ʃ5YvRtVi:X| ffߊ"8zG 4I~ȭ&ЋGRk`9>v:&C>bwIMT.O8 &@yV1Hnqo*ZK\o[Omgu[^|eRV[8{kÿG^qwtm 'ncrmߔC_E nOyO-=K`%HנfV%1!Rܕ~'^=v.~ms"V.IXB1 /gUJ3*mi29bNo {/0YPBPNxd I 9l"웳3>NsrZ..wVmE\'<"k4|Sɶ[q[pæ۰ ̰R,F |5/,|N~ Ȑ`KKk C*Get~բD1nuIԕ0>gf=v%LsvAdŚ TE+'2'iPygweZD<,9=GFiieTE'iu&M&z-s LRZȪ!OdjDu1tX Yپ qbMΫPsnI6-G[V 40L'\bLj̛p_vX26t:k.,]݇_ƭt7KwMhth5 *LbHPZ:tj] l٪*;QoeG`9jsxbgo^4ưA) }x{k9ode' yxo;_PRp,b?f%,gΜO2]b? HZU.r|t~Y5ZTҼ]i< R+.\@P_L`퇾9bv۶m"UXX#Fa7A㛓{pv;v`A+ؒ='z"?m !IXb._ʨDe$Eq`yXvݺu٣'^>]1 F*]WY1-;v)9DŞ8Y8'0i9"vV^-EIMMd<~5,~1_˱[Ѥi0dM!$'X&')HxR@-Pyg%IYh5(a oM$b2 \4kםwn[7$y%cIENDB`PK\?U<<<5default/plugins/payment/monelib/public/buyCode_en.pngnu[PNG  IHDRIBd֐.tEXtCreation Timemar. 18 nov. 2008 17:51:27 +0100\F7tIME $4W pHYs  ~gAMA aIDATx] |TչLEe"]P֪_ŵ>byuŅ"ll%(Q 2ٗ;7LI2s{~};RNNxZ.B 1D1. &yCKo~GUgW"ZYc8k#k g 4]NܹsRp8^G0m4'DqqqgW;n׿ 2&MTm{b6l:1? ظq#z.j=sٓnذ]ڈg?< <2E&|v 2 nXϫkx.6uV!\xxߵk׊}֬Ygy |3x뭷0~x=g`0஻qM7`j߾}HOOovbl{׮]B4ߏ;S`#FeZ cN4ncoI_ީ&@kB~Us[7$q̇&ʋ~N;=f7(w߅nۘK,?Gii>lٲO=0rԯL`'L/b߿#E q/8⯪B߾}.5s(OMM;Ybt8Yӝ5jTmǍ^zxX>}:fϞ]?]^t ?|u-ZHbSщe?7NQSDxEϸ;DN3-c…'1DzHs5o=M}73:w&FsnV~OczIxh E~LKykd*wvu"Fd3:۾c?^]l@fuxVT_u2^B?x Ա^^UJ2WaB1gl;cV\iaH7S]_&`L97D;O,Ei۝ `B8WoxKY\ӆKx5JD>7T iego^c؋auXG jh_ LTq}6< dԒ}`JUL\6#[W#24tsբܦ\Ѧ|o~I9Uwrq0qBTnާJțjAT.U~JxOeyR'|.6,ޔ N?->H}a;'?ƄߔEd7c/zZV* $ *"Ҳ~en`w;Qw|Q &I*Pǁ]B 2ڠh)=i{@/OJv*KdUgJݓfeW5S(>=wFWQSg{[ƺ<)CTp*2 q_54t E+Y_@utT`?NC,:9Z{7H&g`]#t9.}$!C ȝۑ/e_H>> ODq!}(;VMbӡ&$IBJJ 222н{w_v~Q3:yX;r=0`a.v:7xgCY 80[<^={#+ lq6:H'n/<wؽ{x{ϙH)u޶g&R!oRO[{}!;{2S3!ksa[v9N_J8oxjp r6CRK1MF)2 M)SzQGWw0[eC'5aQ^9TW&ΠAЯ_L-8F)]׃*()e$+ y[OBAI>aQ۰&K.9ۦ鬳VN2;tjyNcYodIK-XXan  2KxҪslgwIfuD\W~Qf};!!Xg_G:Sڇt[ NF׎˳$7 >)MYggT(sdYOl˜bMb v Y ܎$īd Z,~gN1 +y*9TئG;C$2R2`%zdAA.S/Hpz\*83)T 9OThFWK *OO [ 7̱ۧ>X,WgO+7.?*㎂$Wa"WhcS+lWn>mZO<ګg/Rʃ<C)jB/Gaiҭ>e}i GtFdZɫqgPbzI%_zQAǞDjWtL[8ny_gj9[Yb<\.LINV *5x w'Tcܱ4\D7Qyi6|.˻nš[W;IAeЍ* nEnQ%ZWp#]@ČN.$KDs̴Z 4WG֩Ğ1$s8/ ]lV'{ֳN6QpV_-m "b-!os|&0IEZk4{f0{=_#dʚjC#1ޡɜ@^?UGDj)\dnE$<|PWiP.9R5QW|b ٮEjJ2RI2C]8ZihŐ8V )i`a{p0,MHIHDG)רy`YU>d8"N%FcMʯ"2y|-`0~hKWhp?BPp{.|`FXm60PiT"h4`1AwA9舔f85Z{丷"W*4: j|5֋. <ϳiuPY$E#m1+n%u`4MӺ;X2Yy4l#eŕUUH$A]CI]DYyWF/Ws)ܬDUf}v_b6ܵnqSuZhx,}l q w;ngH2%Hυmf(0pԵ$$z<.砰$y\xqLeG |7+XdG6!plن_¸c޸ePᓂ^e.խP^v^*eR!^bŧ yrU"jSW1DxFiǎfYcS>m^s,M"(|p[6'dAWPԖ0]{F/K7_v"F"XUR\\]} >o#o_ܪ#RgU(Og}TjPAJ45x= ^^7,_5ݵk K.S^kG\`}؃#5G`/oC~c臑I1"~$Z nsFmYchx g a7mڄ~}a{`}bHWj88AQž{Dz~NQq0jF1 Lcǎ٦׋GQa2h=1S7}9w iK41nIc2r> dD&@<)S|֙setLayout('layout.phtml'); ?>
      src)): ?>
      PK\wn55+default/plugins/payment/monelib/monelib.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Monelib extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_REVISION = '5.0.6'; protected $defaultTitle = 'Monelib'; protected $defaultDescription = 'credit card payments'; const MONELIB_POS_FIELD = 'monelib_point_of_sale'; const MONELIB_ZOS_FIELD = 'monelib_zone_of_sale'; const MONELIB_PIN_FIELD = 'monelib_pin'; const URL_PURCHASE = 'https://www.%smonelib.com/accessScript/ezPurchase.php'; const URL_CHECK = 'http://www.monelib.com/accessScript/check.php'; const URL_CANCEL = 'https://www.%smonelib.com/accessScript/ezManager.php'; public function _initSetupForm(Am_Form_Setup $form) { $form->addSelect('lang') ->setLabel('Language') ->loadOptions(array( 'en' => 'English', 'fr' => 'France', )); $form->addAdvCheckbox('use_image') ->setLabel("Use Monelib Image\n" . 'instead standard aMember button'); } public function init() { parent::init(); if ($this->isConfigured()) { $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldText(self::MONELIB_ZOS_FIELD, 'Monelib Zone of Sale ID')); $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldText(self::MONELIB_POS_FIELD, 'Monelib Point of Sale ID')); } } protected function getUrl($url) { return sprintf($url, $this->getConfig('lang') == 'en' ? 'en.' : ''); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if(!($product = $invoice->getItem(0)->tryLoadProduct())) throw new Am_Exception_InternalError("Product is not loaded from item"); if(!($zos = $product->data()->get(self::MONELIB_ZOS_FIELD))) throw new Am_Exception_InternalError("This product is not assigned to Monelib Zone of Sale ID"); if(!($pos = $product->data()->get(self::MONELIB_POS_FIELD))) throw new Am_Exception_InternalError("This product is not assigned to Monelib Point of Sale ID"); $a = new Am_Paysystem_Action_HtmlTemplate_Monelib($this->getDir(), 'monelib.phtml'); $a->ext_frm_pos = $pos; $a->ext_frm_tpldiz = 'std_' . $this->getConfig('lang'); $a->ext_frm_data0 = $invoice->public_id; $a->ext_frm_data1 = $zos; $a->action = $this->getUrl(self::URL_PURCHASE); $a->url_thanks = $this->getReturnUrl(); if($this->getConfig('use_image')) { $a->src = $this->getRootUrl() . "/application/default/plugins/payment/monelib/public/buyCode_" . $this->getConfig('lang') . ".png"; } $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if( $request->getActionName() == 'ipn' && ($request->getParam('monelib_meaning') == 'USEMULTISHOT' || $request->getParam('monelib_meaning') == 'USEEZSHOT') ) { return; } parent::directAction($request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { if($actionName == 'cancel-admin') { $invoice->setCancelled(true); } else { parent::cancelAction($invoice, $actionName, $result); } } function getUserCancelUrl(Invoice $invoice) { return $this->getUrl(self::URL_CANCEL); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $url = $this->getUrl(self::URL_CANCEL); return <<Monelib Installation Readme 1. Go to 'Monelib Account -> Set up -> Zones and points of sales': a. create new sales zone (it is 'Monelib Zone of Sale ID') b. create new point of sales (it is 'Monelib Point of Sale ID'): - configure Subscription plans so that this plan is matched with your current subscription - at 'Advanced configuration': at 'Return of the parameters on the return pages' check 'If the code is accepted' option at 'Notification url' set this URL $ipn Repeat this step for each your product. 2. Go to 'aMember CP -> Products -> Manage Products', click edit and fill: - 'Monelib Zone of Sale ID' option (from step 1a) - 'Monelib Point of Sale ID' option (from step 1b) Repeat this step for each your product. Note: When user stops his subscription (by link like as $url?ext_frm_key=05888686af39) - monelib does not send any notification about that, but admin can set at invoice status 'Recurring Cancelled' by clicking to 'Stop Recurring' link CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Incoming_Monelib($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Incoming_Monelib extends Am_Paysystem_Transaction_Incoming { public function validateSource() { return true; } public function findInvoiceId() { if ($this->request->getParam('monelib_meaning') == 'NEWMULTISHOT') return $this->request->getParam('monelib_data0'); elseif ($this->request->getParam('monelib_meaning') == 'RENEWMULTISHOT') return Am_Di::getInstance()->invoiceTable-> findFirstByData(Am_Paysystem_Monelib::MONELIB_PIN_FIELD, $this->request->getParam('monelib_pincode0'))->public_id; } public function validateStatus() { if ($this->request->getParam('monelib_meaning') == 'RENEWMULTISHOT') return true; $pin = $this->request->getParam('monelib_pincode0'); $zos = $this->request->getParam('monelib_data1'); $pos = $this->request->getParam('monelib_pos'); $post = array( 'ext_frm_code0' => $pin, 'ext_frm_online' => 1, 'ext_frm_pos' => $pos, 'ext_frm_zos' => $zos, ); $req = new Am_HttpRequest(Am_Paysystem_Monelib::URL_CHECK . "?" . http_build_query($post)); $res = $req->send()->getBody(); if(strpos($res, "OK") === 0) { $this->invoice->data()->set(Am_Paysystem_Monelib::MONELIB_PIN_FIELD, $pin); $this->invoice->comment = "Pin: " . $pin; $this->invoice->update(); return true; } } public function getUniqId() { $trId = $this->request->getParam('monelib_trans'); if($trId == 'test') $trId .= '-' . $this->request->getParam('monelib_expires'); return $trId; } public function validateTerms() { return true; } }PK\>5;5;!default/plugins/payment/wepay.phpnu[addInteger('client_id', array('size' => 20)) ->setLabel('Your Client ID#'); $form->addText('secret', array('size' => 20)) ->setLabel('Your Client Secret'); $form->addText('token', array('size' => 40)) ->setLabel('Your Access Token'); $form->addInteger('account_id', array('size' => 20)) ->setLabel('Your Account ID#'); $form->addSelect('fee_payer')->setLabel(___('Who is paying the fee')) ->loadOptions(array( 'payee' => 'the person receiving the money', 'payer' => 'the person paying', /*'payee_from_app' => 'if payee is paying for app fee and app is paying for WePay fees' 'payer_from_app' => 'if payer is paying for app fee and the app is paying WePay fees',*/ )); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function getUrl() { return ($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); } function getPeriod(Invoice $invoice) { $tz = date_default_timezone_get(); date_default_timezone_set('EST5EDT'); $first_period = new Am_Period($invoice->first_period); $second_period = new Am_Period($invoice->second_period); $periods = array( '1d' => 'daily', '7d' => 'weekly', '14d' => 'biweekly', '1m' => 'monthly', '2m' => 'bimonthly', '3m' => 'quarterly', '1y' => 'yearly', Am_Period::MAX_SQL_DATE => 'once' ); $period = $periods[$invoice->second_period]; if(empty($period)) { Am_Di::getInstance()->errorLogTable->log("WEPAY. {$invoice->second_period} is not supported"); date_default_timezone_set($tz); throw new Am_Exception_InternalError(); } if($invoice->rebill_times == IProduct::RECURRING_REBILLS) { date_default_timezone_set($tz); return array($period,''); } $end = $first_period->addTo(date('Y-m-d')); for($i=0;$i<$invoice->rebill_times;$i++) $end = $second_period->addTo($end); date_default_timezone_set($tz); return array($period,$end); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { //recurring if(!is_null($invoice->second_period)) { if($invoice->first_total != $invoice->second_total) throw new Am_Exception_InputError(___('Wepay does not support trial periods!')); list($period,$end_time) = $this->getPeriod($invoice); $mode = 'preapproval'; $params = array( 'account_id' => $this->getConfig('account_id'), 'amount' => $invoice->second_total, 'short_description' => $invoice->getLineDescription(), 'redirect_uri' => $this->getReturnUrl(), 'callback_uri' => $this->getPluginUrl('ipn'), 'reference_id' => $invoice->public_id, 'frequency' => 1, 'end_time' => $end_time, 'auto_recur' => 'true', 'period' => $period, 'fee_payer' => $this->getConfig('fee_payer'), 'currency' => $invoice->currency ); } //not recurring else { $mode = 'checkout'; $params = array( 'account_id' => $this->getConfig('account_id'), 'amount' => $invoice->first_total, 'short_description' => $invoice->getLineDescription(), 'type' => 'goods', 'hosted_checkout' => array( 'redirect_uri' => $this->getPluginUrl('thanks'), 'mode' => 'regular' ), 'fee' => array( 'fee_payer' => $this->getConfig('fee_payer'), ), 'reference_id' => $invoice->public_id, 'currency' => $invoice->currency ); } $params = array_filter($params); $req = new Am_HttpRequest($this->getUrl() . "/$mode/create", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); if($res->getStatus()!=200) { $this->getDi()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); throw new Am_Exception_InputError(___('Error happened during payment process. ')); } if(!empty($arr['error_description'])) throw new Am_Exception_InputError($arr['error_description']); $a = new Am_Paysystem_Action_Redirect(!empty($arr['hosted_checkout']['checkout_uri']) ? $arr['hosted_checkout']['checkout_uri'] : $arr['preapproval_uri']); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->get('checkout_id')) return new Am_Paysystem_Transaction_Wepay_Checkout($this, $request, $response,$invokeArgs); else return new Am_Paysystem_Transaction_Wepay_Preapproval($this, $request, $response,$invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Wepay_Thanks($this, $request, $response,$invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getSupportedCurrencies() { return array('USD'); } public function getReadme() { return <<getPaymentRecords(); $params = array( 'checkout_id' => $payments[0]->receipt_id ); $req = new Am_HttpRequest(($this->getUrl()) . "/checkout/", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); if($res->getStatus()!=200) { Am_Di::getInstance()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); return false; } if(!empty($arr['error_description'])) return false; //cancel preapproval $params = array( 'preapproval_id' => $arr['preapproval_id'], ); $req = new Am_HttpRequest($this->getUrl() . "/preapproval/cancel", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); if($res->getStatus()!=200) { $this->getDi()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); throw new Am_Exception_InputError(___("An error occurred while cancellation request")); } if($arr['state'] != 'cancelled') throw new Am_Exception_InputError(___("An error occurred while cancellation request")); } } class Am_Paysystem_Transaction_Wepay_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { protected $checkout; public function findInvoiceId() { return $this->checkout['reference_id']; } public function getUniqId() { return $this->checkout['checkout_id']; } public function validateSource() { $params = array( 'checkout_id' => $this->request->get('checkout_id') ); $req = new Am_HttpRequest(($this->plugin->getUrl()) . "/checkout/", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->plugin->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); $this->log->add(var_export($arr,true)); if($res->getStatus()!=200) { Am_Di::getInstance()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); return false; } if(!empty($arr['error_description'])) return false; $this->checkout = $arr; return true; } public function validateStatus() { return in_array($this->checkout['state'], array('captured','approved','authorized')); } public function validateTerms() { return doubleval($this->invoice->first_total) == doubleval($this->checkout['amount']); } } class Am_Paysystem_Transaction_Wepay_Checkout extends Am_Paysystem_Transaction_Incoming { protected $checkout; protected $preapproval; public function findInvoiceId() { return $this->preapproval['reference_id']; } public function getUniqId() { return $this->request->get('checkout_id'); } public function validateSource() { $params = array( 'checkout_id' => $this->request->get('checkout_id') ); $req = new Am_HttpRequest(($this->plugin->getUrl()) . "/checkout/", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->plugin->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); $this->log->add(var_export($arr,true)); if($res->getStatus()!=200) { Am_Di::getInstance()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); return false; } if(!empty($arr['error_description'])) return false; $this->checkout = $arr; $params = array( 'preapproval_id' => isset($arr['preapproval_id']) ? $arr['preapproval_id'] : $arr['payment_method']['preapproval']['id'] ); $req = new Am_HttpRequest(($this->plugin->getUrl()) . "/preapproval/", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->plugin->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); $this->log->add(var_export($arr,true)); if($res->getStatus()!=200) { Am_Di::getInstance()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); return false; } if(!empty($arr['error_description'])) return false; $this->preapproval = $arr; return true; } public function validateStatus() { return in_array($this->checkout['state'], array('authorized','captured','refunded')); } public function validateTerms() { return doubleval($this->invoice->second_total) == doubleval($this->checkout['amount']); } public function processValidated() { switch ($this->checkout['state']) { case 'authorized': case 'captured': $this->invoice->addPayment($this); break; case 'refunded': $this->invoice->addRefund($this, $this->request->get('checkout_id')); break; default : ; } } } class Am_Paysystem_Transaction_Wepay_Preapproval extends Am_Paysystem_Transaction_Incoming { protected $preapproval; public function findInvoiceId() { return $this->preapproval['reference_id']; } public function getUniqId() { return $this->request->get('preapproval_id'); } public function validateSource() { $params = array( 'preapproval_id' => $this->request->get('preapproval_id') ); $req = new Am_HttpRequest(($this->plugin->getUrl()) . "/preapproval/", Am_HttpRequest::METHOD_POST); $req->setBody(json_encode($params)); $req->setHeader("Content-Type", "application/json"); $req->setHeader("Authorization", "Bearer ". $this->plugin->getConfig('token')); $res = $req->send(); $arr = json_decode($res->getBody(),true); $this->log->add(var_export($arr,true)); if($res->getStatus()!=200) { Am_Di::getInstance()->errorLogTable->log("WEPAY API ERROR : $arr[error_code] - $arr[error_description]"); return false; } if(!empty($arr['error_description'])) return false; $this->preapproval = $arr; return true; } public function validateStatus() { return in_array($this->preapproval['state'], array('new', 'approved', 'expired', 'revoked', 'cancelled', 'stopped', 'completed', 'retrying')); } public function validateTerms() { return doubleval($this->invoice->second_total) == doubleval($this->preapproval['amount']); } public function processValidated() { switch ($this->preapproval['state']) { case 'cancelled': case 'revoked': case 'stopped': $this->invoice->setCancelled(true); break; default : ; } } }PK\Cgi;;%default/plugins/payment/pagseguro.phpnu[addText('merchant')->setLabel('Merchant Email'); $form->addText('token')->setLabel('Security Token'); } function getSupportedCurrencies() { return array('BRL', 'USD'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect('https://pagseguro.uol.com.br/security/webpagamentos/webpagto.aspx'); $a->email_cobranca = $this->getConfig('merchant'); $a->tipo = 'CP'; $a->moeda = strtoupper($invoice->currency); $a->image = 'btnComprarBR.jpg'; $a->item_id_1 = $invoice->public_id; $a->item_descr_1 = $invoice->getLineDescription(); $a->item_quant_1 = 1; $a->item_valor_1 = str_replace('.', '', sprintf('%.2f', $invoice->first_total)); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Pagseguro($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme() { return <<PagSecuro payment plugin configuration http://pagseguro.uol.com.br Activate "return URL" at your PagSeguro merchant account. To activate Automatic Data Return, select the option Ativar and inform the URL to which PagSeguro will redirect your customers after completion of payment. After that, click Salvar. You have to set up %root_url%/payment/pagseguro/ipn as "return URL". CUT; } function getReturnUrl($invoice) { $this->invoice = $invoice; return parent::getReturnUrl(); } } class Am_Paysystem_Transaction_Pagseguro extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('ProdID_1'); } public function getUniqId() { return $this->request->get('TransacaoID'); } public function validateSource() { $vars = $this->request->getPost(); $vars['tipo'] = 'CP'; $vars['Comando'] = 'validar'; $vars['Token'] = $this->getPlugin()->getConfig('token'); $vars['email_cobranca']= $this->getPlugin()->getConfig('merchant'); try{ $r = new Am_HttpRequest("https://pagseguro.uol.com.br/Security/NPI/Default.aspx?".http_build_query($vars, '', '&')); $response = $r->send(); }catch(Exception $e){ $this->getPlugin()->getDi()->errorLogTable->logException($e); } if($response && ($response->getBody() == 'VERIFICADO')){ return true; } throw new Am_Exception_Paysystem_TransactionSource('Incorrect transaction received. Please contact webmaster for details'); } public function validateStatus() { if(in_array(strtoupper($this->request->get('StatusTransacao')),array('APROVADO','COMPLETO'))) return true; throw new Am_Exception_Paysystem_TransactionInvalid('Transaction is not approved'); } public function validateTerms() { if(str_replace(',', '.', $this->request->get('ProdValor_1')) != $this->invoice->first_total) throw new Am_Exception_Paysystem_TransactionInvalid('Incorrect amount received'); return true; } public function processValidated() { $this->invoice->addPayment($this); Am_Mvc_Response::redirectLocation($this->getPlugin()->getReturnUrl($invoice)); } } PK\)SR#R#%default/plugins/payment/paygarden.phpnu[getDi()->productTable->customFields() ->add(new Am_CustomFieldText(self::PAYGARDEN_PRODUCT_ID, 'Paygarden Product ID')); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('parther_id') ->setLabel("Your Parner ID\n" . 'unique string that identifies your corporate entity') ->addRule('required'); $form->addText('api_key', array('class' => 'el-wide')) ->setLabel("Your API Key\n" . 'unique string supplied to you during initial setup') ->addRule('required'); } public function getSupportedCurrencies() { return array_keys(Am_Currency::getFullList()); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $prs = $invoice->getProducts(); /* @var $product Product */ $product = $prs[0]; if(!($prId = $product->data()->get(self::PAYGARDEN_PRODUCT_ID))) throw new Am_Exception_InternalError("Product #{$product->pk} {$product->title} has no Paygarden Product ID"); /* @var $user User */ $user = $invoice->getUser(); $data = array( 'txn-type' => 'initial', 'account-id' => $user->pk(), 'email' => $user->email, 'passthrough' => $invoice->public_id, 'postback-url' => $this->getPluginUrl('ipn'), 'continue-url' => $this->getReturnUrl(), ); $url = sprintf(self::URL, $this->getConfig('parther_id'), $prId); $a = new Am_Paysystem_Action_Redirect($url . "?" . http_build_query($data, null, '&')); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paygarden($this, $request, $response, $invokeArgs); } function onThanksPage(Am_Event $event) { if($event->getInvoice()->paysys_id != $this->getId()) return; $content = ""; $this->getDi()->blocks->add(new Am_Block('thanks/success', ___('Thanks Success'), 'thanks-page-content', $this, function(Am_View $view) use ($content) { return $content; })); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return << true)); exit; } } public function getUniqId() { return ($this->request->get('txn-type') == 'initial') ? $this->request->get("confirmation-code") : $this->request->get("txn-id"); } public function findInvoiceId() { if(($this->request->get('txn-type') == 'initial')) return $this->request->get("passthrough"); if(($this->request->get('txn-type') == 'cancel')) { if($invoice = $this->plugin->getDi()->invoiceTable->findFirstByData(Am_Paysystem_Paygarden::PAYGARDEN_TXN_ID, $this->request->get("txn-id"))) return $invoice->public_id; } // old invoice header('Content-Type: application/json'); echo json_encode(array('success' => true)); exit; } protected function autoCreate() { try { $invoiceId = $this->findInvoiceId(); if ($invoiceId === null) throw new Am_Exception_Paysystem_TransactionEmpty("Looks like an invalid IPN post - no Invoice# passed"); $invoiceId = filterId($invoiceId); if (!strlen($invoiceId)) throw new Am_Exception_Paysystem_TransactionInvalid("Could not load Invoice related to this transaction, passed id is not a valid Invoice#[$invoiceId]"); if (!$this->invoice = $this->loadInvoice($invoiceId)) { // throw new Am_Exception_Paysystem_TransactionUnknown("Unknown transaction: related invoice not found #[$invoiceId]"); $this->getPlugin()->getDi()->errorLogTable->log("Unknown transaction: related invoice not found #[$invoiceId]"); // say to paysys - don't resend IPN header('Content-Type: application/json'); echo json_encode(array('success' => true)); exit; } } catch (Am_Exception_Paysystem $e) { if (!$this->plugin->getConfig('auto_create')) throw $e; // try auto-create invoice $invoice = $this->autoCreateInvoice(); if ($invoice) $this->invoice = $invoice; else throw $e; } $this->time = $this->findTime(); } public function validateSource() { return ($this->request->get('api-key') == $this->plugin->getConfig('api_key') && in_array($this->request->get('txn-type'), array('initial', 'cancel'))); } public function validateStatus() { return true; } public function validateTerms() { if(($this->request->get('txn-type') == 'cancel')) return true; $prs = $this->invoice->getProducts(); /* @var $product Product */ $product = $prs[0]; return ($this->request->get('product-id') == $product->data()->get(Am_Paysystem_Paygarden::PAYGARDEN_PRODUCT_ID)); } public function processValidated() { switch ($this->request->get('txn-type')) { case 'initial': $data = $this->processPayment(); break; case 'cancel': $data = $this->processCancel(); break; default: throw new Am_Exception_InputError("Unknown IPN-request type [{$this->request->get('txn-type')}]"); } header('Content-Type: application/json'); echo json_encode($data); exit; } protected function processPayment() { $days = $this->request->get('units-sold'); $paid = moneyRound($this->request->get('payout')/100); //Pasar a EUR $rate_default = '1.12'; $XMLContent=file("http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"); foreach($XMLContent as $line){ if(preg_match("/currency='([[:alpha:]]+)'/",$line,$currencyCode) && $currencyCode[1] == 'USD'){ if(preg_match("/rate='([[:graph:]]+)'/",$line,$rate)){ $rate_default = $rate[1]; } } } $paid /= $rate_default; $item = $this->invoice->getItem(0); $item->first_period = $days . 'd'; $item->first_price = $paid; $item->rebill_times = 0; $item->second_price = 0; $item->_calculateTotal(); $item->update(); $item->data()->set('orig_first_price', null)->update(); $this->invoice->calculate(); $this->invoice->first_period = $days . 'd'; $this->invoice->data()->set(Am_Paysystem_Paygarden::PAYGARDEN_TXN_ID, $this->request->get("txn-id")); $this->invoice->update(); parent::processValidated(); /* @var $user User */ $user = $this->invoice->getUser(); return array( 'success' => true, 'username' => $user->login, 'account-id' => $user->pk(), ); } protected function processCancel() { /* @var $access Access */ if(!($access = $this->plugin->getDi()->accessTable->findFirstByInvoiceId($this->invoice->pk()))) throw new Am_Exception_InternalError("Access not found for invoice {$this->invoice->public_id}"); $access->updateQuick('expire_date', sqlDate(strtotime('-1 day'))); $this->invoice->getUser()->checkSubscriptions(true); $this->invoice->updateQuick('comment', 'Canceled by PayGarden at ' . amDate('now')); return array( 'success' => true, ); } }PK\] &default/plugins/payment/metacharge.phpnu[addText("installation_id", array('size' => 15)) ->setLabel("Your Metacharge installation ID\n" . "refer to Merchant Extranet: Account Management > Installations") ->addRule('required'); $form->addText("auth_username", array('size' => 15)) ->setLabel("Response HTTP Auth Username\n" . "Metacharge PRN response authorisation username") ->addRule('required'); $form->addPassword("auth_password", array('size' => 15)) ->setLabel("Response HTTP Auth Password\n" . "Metacharge PRN response authorisation password") ->addRule('required'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } function metacharge_get_period($period) { // For scheduled payments based upon this transaction, the interval between payments, // given as XY where X is a number (1-999) and Y is “D” for days, “W” for weeks or “M” for months. $days = strtolower(trim($days)); if (preg_match('/^(\d+)(d|w|m|y)$/', $period, $regs)) { $count = $regs[1]; $period = $regs[2]; if ($period == 'd'){ return sprintf("%03d", $count) . "D"; } elseif ($period == 'w'){ return sprintf("%03d", $count) . "W"; } elseif ($period == 'm'){ return sprintf("%03d", $count) . "M"; } elseif ($period == 'y'){ return sprintf("%03d", $count * 12) . "M"; } else { Am_Di::getInstance()->errorLogTable->log("METACHARGE. $period is not supported"); throw new Am_Exception_InternalError(); } } elseif (preg_match('/^\d+$/', $days)) return sprintf("%03d", $days) . "D"; else { Am_Di::getInstance()->errorLogTable->log("METACHARGE. $period is not supported"); throw new Am_Exception_InternalError(); } } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::LIVE_URL); $u = $invoice->getUser(); $a->intInstID = $this->config['installation_id']; $a->strCartID = $invoice->public_id; $a->strCurrency = $invoice->currency; $a->strDesc = $invoice->getLineDescription(); $a->strEmail = $u->email; $a->strCardHolder = $u->getName(); $a->strAddress = $u->street; $a->strCity = $u->city; $a->strState = $u->state; $a->strCountry = $u->country; $a->strPostcode = $u->zip; $a->intTestMode = $this->getConfig('testing') ? '1' : ''; $a->fltAmount = sprintf('%.3f', $invoice->first_total); //recurring if(!is_null($invoice->second_period)) { $a->intRecurs = '1'; $a->intCancelAfter = substr($invoice->rebill_times,3); $a->fltSchAmount1 = sprintf('%.3f', $invoice->second_total); $a->strSchPeriod1 = $this->metacharge_get_period($invoice->first_period); $a->fltSchAmount = sprintf('%.3f', $invoice->first_total); $a->strSchPeriod = $this->metacharge_get_period($invoice->second_period); } $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Metacharge($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Metacharge_Thanks($this, $request, $response, $invokeArgs); } public function getReadme() { $ipn = Am_Html::escape($this->getPluginUrl('ipn')); $thanks = Am_Html::escape($this->getPluginUrl('thanks')); return <<Metacharge payment plugin configuration 1. Enable and configure Metacharge Plugin in aMember control panel. 2. PRN is enabled and configured on a per-installation basis via the Merchant Extranet. Click on Account Management and then Installations, then select the relevant installation from the pop-up menu. Please complete the following fields to enable PRNs: - Response URL: The URL where you want the PRN to be sent: $ipn - Scheduled Payment Response URL: Configured as above if subscriptions have been enabled on your installation. 3. Go to Merchant Extranet. Click Account Management then Installations and select the installation you wish to configure from the pop-up menu. Please complete the following fields to redirect customer to your website after completed transaction. - return URL: $thanks 4. We recommend that you perform HTTP Basic Authorisation on your server to ensure that the response is coming from a trusted source. If you have enabled HTTP Basic Authorisation on your server, you will need to specify: - Response HTTP Auth Username - Response HTTP Auth Password CUT; } public function getRecurringType() { return self::REPORTS_REBILL; } public function getSupportedCurrencies() { return array('USD', 'GBP', 'EUR', 'JPY', 'AUD'); } } class Am_Paysystem_Transaction_Metacharge extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get("strCartID"); } public function getUniqId() { return $this->request->get("intTransID"); } public function validateSource() { // do HTTP Basic Authorisation if (!isset($_SERVER['PHP_AUTH_USER'])) { // HTTP Authentication header('WWW-Authenticate: Basic realm="aMember Metacharge PRN response"'); header('HTTP/1.0 401 Unauthorized'); print "Error - HTTP Auth Username is not entered"; exit(); } // checking name and password if( ($_SERVER['PHP_AUTH_USER'] != $this->plugin->getConfig('auth_username')) || ($_SERVER['PHP_AUTH_PW'] != $this->plugin->getConfig('auth_password'))){ header('WWW-Authenticate: Basic realm="aMember Metacharge PRN response"'); header('HTTP/1.0 401 Unauthorized'); print "Error - Incorrect HTTP Auth username or password entered"; exit(); } return ($this->request->get("intInstID") == $this->plugin->getConfig('installation_id')); } public function validateStatus() { return ($this->request->get("intStatus") == 1); } public function validateTerms() { return doubleval($this->request->get("fltAmount")) == doubleval($this->invoice->isFirstPayment() ? $this->invoice->first_total : $this->invoice->second_total); } } class Am_Paysystem_Transaction_Metacharge_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { return $this->request->get("strCartID"); } public function getUniqId() { return $this->request->get("intTransID"); } public function validateSource() { return true; } public function validateStatus() { if($this->request->get("intStatus") != 1) Am_Mvc_Response::redirectLocation ($this->plugin->getRootUrl() . "/cancel?id=" . $this->invoice->getSecureId('CANCEL')); return true; } public function validateTerms() { return true; } }PK\2˖$default/plugins/payment/paymento.phpnu[addText('shop_reference') ->setLabel('Shop ID') ->addRule('required'); $form->addText('shop_name') ->setLabel('Shop Name') ->addRule('required'); $form->addSelect('type') ->setLabel('Payment Type') ->loadOptions(array( '' => '-- Please Select --', 'ecard' => 'Card', 'etransfer' => 'Bank Transfer', 'payment' => 'User Choice', )) ->addRule('required'); $form->addSelect('lang') ->setLabel('Language') ->loadOptions(array( '' => '-- Please Select --', 'pl' => 'Polish', 'en' => 'English', 'cz' => 'Czech', 'de' => 'Deutsch', 'dk' => 'Denmark', 'fi' => 'Deutsch', 'fr' => 'France', 'hu' => 'Hungary', 'it' => 'Italiano', 'ro' => 'Romanian', 'se' => 'Swedish', 'sk' => 'Slovakia', 'sl' => 'Slovenia', 'sp' => 'Spain', )) ->addRule('required'); } public function isConfigured() { return $this->getConfig('shop_reference') && $this->getConfig('shop_name') && $this->getConfig('type') && $this->getConfig('lang'); } protected function getPaymentUrl() { return sprintf(self::URL, $this->getConfig('lang'), $this->getConfig('type')); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { list($action, $status, $id) = explode("-", $request->getActionName()); if ($action != 'status') { if( ($action != 'ipn' && $action != 'thanks') || $request->get('transaction_status') == 'SETTLED' ){ parent::directAction($request, $response, $invokeArgs); } return; } if(!in_array($status, array('return', 'ok', 'fail'))) { throw new Am_Exception_InternalError("Bad status-request $status"); } if(!$id) { throw new Am_Exception_InternalError("Invoice ID is absent"); } if(!($this->invoice = $this->getDi()->invoiceTable->findFirstByPublicId($id))) { throw new Am_Exception_InternalError("Invoice not found by id [$id]"); } switch ($status) { case 'return': $url = ($request->get('transactionStatus') == 'REJECTED') ? $this->getCancelUrl() : $this->getReturnUrl(); break; case 'ok': $url = $this->getReturnUrl(); break; case 'fail': $url = $this->getCancelUrl(); break; } $response->setRedirect($url); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $vars = array( 'amount' => $invoice->first_total, 'currency' => $invoice->currency, 'shop_reference_card' => $this->getConfig('shop_reference'), 'shop_reference_transfer' => $this->getConfig('shop_reference'), 'shop_name' => $this->getConfig('shop_name'), 'transaction_description' => $invoice->getLineDescription(), 'order_id' => $invoice->public_id, 'return_address' => $this->getPluginUrl('status-return-' . $invoice->public_id), 'success_url' => $this->getPluginUrl('status-ok-' . $invoice->public_id), 'failure_url' => $this->getPluginUrl('status-fail-' . $invoice->public_id), 'customer_first_name' => $invoice->getUser()->name_f, 'customer_second_name' => $invoice->getUser()->name_l, 'customer_email' => $invoice->getUser()->email, ); $this->getDi()->errorLogTable->log('paymento-request: ['.print_r($vars, true). ']'); $action = new Am_Paysystem_Action_Form($this->getPaymentUrl()); foreach ($vars as $key => $value) { $action->$key = $value; } $result->setAction($action); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { $u = $this->getPluginUrl('ipn'); return <<$u NOTE: plugin does not support recurring payments. CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paymento($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paymento($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Paymento extends Am_Paysystem_Transaction_Incoming { protected $result; public function process() { $this->result = $this->request->getPost(); parent::process(); } public function validateSource() { return $this->plugin->getConfig('shop_reference') == $this->result['shop_reference']; } public function findInvoiceId() { return $this->result['order_id']; } public function validateStatus() { return $this->result['transaction_status'] == 'SETTLED'; } public function getUniqId() { return (string) $this->result['transaction_reference']; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->result['amount']); return true; } } PK\H} } 0default/plugins/payment/chinapaymentservices.phpnu[addText('merchant_id', array('size' => 40))->setLabel('Your ChinaPaymentServices Merchant ID'); $form->addText('site_id', array('size' => 40))->setLabel('Your ChinaPaymentServices Site ID'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $a = new Am_Paysystem_Action_Form(self::LIVE_URL); $a->Merchant = $this->getConfig('merchant_id'); $a->Site = $this->getConfig('site_id'); $a->DirectTransfer = 'true'; $a->Amount = $invoice->first_total; $a->Currency = $invoice->currency; $a->TransRef = $invoice->public_id; $a->Product = $invoice->getLineDescription(); $a->PaymentType = 'cup'; $a->AttemptMode = '1'; $a->TestTrans = $this->getConfig('testing') ? '1' : '0'; $a->__set("customer[email]", $user->email); $a->__set("customer[first_name]", $user->name_f); $a->__set("customer[last_name]", $user->name_l); $a->__set("customer[address1]", $user->street); $a->__set("customer[address2]", $user->street2); $a->__set("customer[city]", $user->city); $a->__set("customer[state]", $user->state); $a->__set("customer[postcode]", $user->postcode); $a->__set("customer[country]", $user->country); $a->__set("customer[phone]", $user->phone); $a->ReturnUrlFailure = $this->getCancelUrl(); $a->ReturnUrlSuccess = $this->getPluginUrl('thanks'); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Chinapaymentservices_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('USD'); } } class Am_Paysystem_Transaction_Chinapaymentservices_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { } public function validateSource() { } public function validateStatus() { } public function validateTerms() { } }PK\[$#default/plugins/payment/centili.phpnu[billingPlanTable->customFields()->add( new Am_CustomFieldText( 'centili_apikey', 'Centili Api Key', 'you have to create similar service in Centili and enter its Api Key here') ); Am_Di::getInstance()->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'centili_package', 'Centili Package Index', 'zero based index of package for service in Centili') ); Am_Di::getInstance()->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'centili_signkey', 'Centili Signature Key', 'you have to create similar service in Centili and enter its Signature Key here') ); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { foreach ($invoice->getItems() as $item) { /* @var $item InvoiceItem */ if (!$item->getBillingPlanData('centili_apikey')) return "item [" . $item->item_title . "] has no related Centili Api Key configured"; } } public function _initSetupForm(Am_Form_Setup $form) { //nop } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_HtmlTemplate('layout.phtml'); $apikey = $this->invoice->getItem(0)->getBillingPlanData('centili_apikey'); $package = (int)$this->invoice->getItem(0)->getBillingPlanData('centili_package'); $a->title = sprintf('Pay with %s', $this->getTitle()); $a->layoutNoMenu = true; $query = http_build_query(array( 'api' => $apikey, 'clientId' => $invoice->public_id, 'package' => $package, 'packagelock' => 'true', )); $a->content = << CUT; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Centili($this, $request, $response, $invokeArgs); } function sign($vars, $key) { ksort($vars, SORT_STRING); return hash_hmac('sha1', implode('', $vars), $key); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $thanks = $this->getDi()->url('thanks'); return <<$thanks Payment result notification URL: $ipn You can do it with 'Advanced Integration Setup' on tab 'Setup' of service configuration. CUT; } } class Am_Paysystem_Transaction_Centili extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getParam('transactionid'); } public function validateSource() { $this->_checkIp(<<request->getRequestOnlyParams(); $sign = $p['sign']; $bp = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('centili_apikey', $p['service']); if (!$bp) return false; unset($p['sign']); $expect = $this->getPlugin()->sign($p, $bp->data()->get('centili_signkey')); return $expect == $sign; } public function validateTerms() { return true; } public function validateStatus() { return $this->request->getParam('status') == 'success'; } public function findInvoiceId() { return $this->request->getParam('clientid'); } public function processValidated() { switch ($this->request->getParam('event_type')) { case 'one_off' : case 'opt_in' : case 'recurring_billing' : $this->invoice->addPayment($this); break; case 'opt_out' : $this->invoice->setCancelled(); break; } } }PK\i}-4(4((default/plugins/payment/warrior-plus.phpnu[paysystemList->getList() as $k=>$p){ if($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'wsopro_item_name', "WSO Pro Item Name", "You should specify exactly the same name as your WSO Pro Listing Item Name" ,array(/*,'required'*/) )); } function getConfig($key = null, $default = null) { switch($key){ case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } public function getSupportedCurrencies() { return array( 'AUD', 'BRL', 'CAD', 'CZK', 'DKK', 'EUR', 'HKD', 'HUF', 'ILS', 'JPY', 'MYR', 'MXN', 'NOK', 'NZD', 'PHP', 'PLN', 'GBP', 'SGD', 'SEK', 'CHF', 'TWD', 'THB', 'USD', 'TRY'); } public function _initSetupForm(Am_Form_Setup $form) { $plugin = $this->getId(); $form->addText("business", array('size'=>40)) ->setLabel("Your PayPal Email Address"); $form->addTextarea("alt_business", array('cols'=>40, 'rows'=>3,)) ->setLabel("Other Paypal Email addresses that you have registered in WSO PRO"); $form->addAdvCheckbox("dont_verify") ->setLabel( "Disable IPN verification\n" . "Usually you DO NOT NEED to enable this option. However, on some webhostings PHP scripts are not allowed to contact external web sites. It breaks functionality of the PayPal payment integration plugin, and aMember Pro then is unable to contact PayPal to verify that incoming IPN post is genuine. In this case, AS TEMPORARY SOLUTION, you can enable this option to don't contact PayPal server for verification. However, in this case \"hackers\" can signup on your site without actual payment. So if you have enabled this option, contact your webhost and ask them to open outgoing connections to www.paypal.com port 80 ASAP, then disable this option to make your site secure again."); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->get('ACK')) return new Am_Paysystem_WsoPro_Transaction_PRO($this, $request, $response, $invokeArgs); else return new Am_Paysystem_WsoPro_Transaction($this, $request, $response, $invokeArgs); } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Warrior+ WSO PRO integration Each WSO PRO listing which you want to integrate with aMember should have separate product created in aMember CP -> Manage Products -> Edit Product Both WSO PRO listing and aMember Product should have exactly the same price/period settings. aMember CP -> Manage Products -> Edit Product -> WSO PRO Item Name should be exactly the same as you have in WSO PRO -> my listings -> Item Name IPN Forwarding URL for WSO listing should be set to: $url CUT; } public function canAutoCreate() { return true; } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } } class Am_Paysystem_WsoPro_Transaction extends Am_Paysystem_Transaction_Paypal { protected $_autoCreateMap = array( 'name_f' => 'first_name', 'name_l' => 'last_name', 'email' => 'payer_email', 'street' => 'addres_street', 'zip' => 'address_zip', 'state' => 'address_state', 'country' => 'address_country_code', 'city' => 'address_city', 'user_external_id' => 'payer_id', 'invoice_external_id' => array('subscr_id', 'txn_id') , ); public function processValidated() { switch ($this->txn_type) { case self::TXN_SUBSCR_SIGNUP: if ($this->invoice->first_total <= 0) // no payment will be reported if ($this->invoice->status == Invoice::PENDING) // handle only once $this->invoice->addAccessPeriod($this); // add first trial period break; case self::TXN_SUBSCR_EOT: $this->invoice->stopAccess($this); break; case self::TXN_SUBSCR_CANCEL: $this->invoice->setCancelled(true); break; case self::TXN_WEB_ACCEPT: case self::TXN_SUBSCR_PAYMENT: switch ($this->request->payment_status) { case 'Completed': $this->invoice->addPayment($this); break; default: } break; } switch($this->request->payment_status){ case 'Refunded': case 'Chargeback': $this->invoice->addRefund($this, $this->request->parent_txn_id, $this->getAmount()); break; } } public function validateStatus() { $status = $this->request->getFiltered('status'); return $status === null || $status === 'Completed'; } public function validateTerms() { $currency = $this->request->getFiltered('mc_currency'); if ($currency && (strtoupper($this->invoice->currency) != $currency)) throw new Am_Exception_Paysystem_TransactionInvalid("Wrong currency code [$currency] instead of {$this->invoice->currency}"); if ($this->txn_type == self::TXN_SUBSCR_PAYMENT) { $isFirst = $this->invoice->first_total && !$this->invoice->getPaymentsCount(); $expected = $isFirst ? $this->invoice->first_total : $this->invoice->second_total; if ($expected > ($amount = $this->getAmount())) throw new Am_Exception_Paysystem_TransactionInvalid("Payment amount is [$amount], expected not less than [$expected]"); } elseif ($this->txn_type == self::TXN_SUBSCR_SIGNUP) { if ($this->invoice->first_total != $this->request->get('mc_amount1')) return false; if ("" != $this->request->get('mc_amount2')) return false; if ($this->invoice->second_total != $this->request->get('mc_amount3')) return false; if ($this->invoice->currency != $this->request->get('mc_currency')) return false; $p1 = new Am_Period($this->invoice->first_period); $p3 = new Am_Period($this->invoice->second_period); try { $p1 = $p1->getCount() . ' ' . $this->plugin->getPeriodUnit($p1->getUnit()); $p3 = $p3->getCount() . ' ' . $this->plugin->getPeriodUnit($p3->getUnit()); } catch (Exception $e) { } if ($p1 != $this->request->get('period1')) return false; if ("" != $this->request->get('period2')) return false; if ($p3 != $this->request->get('period3')) return false; } return true; } public function autoCreateGetProducts() { $item_name = $this->request->get('item_name'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('wsopro_item_name', $item_name); if($billing_plan) return array($billing_plan->getProduct()); } function validateBusiness() { return true; } } class Am_Paysystem_WsoPro_Transaction_PRO extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name_f' => 'FIRSTNAME', 'name_l' => 'LASTNAME', 'email' => 'EMAIL', 'user_external_id' => 'PAYERID', 'invoice_external_id' => array('PROFILEID', 'TRANSACTIONID') , ); public function getUniqId() { return @$this->request->get('TRANSACTIONID'); } public function getAmount() { return @$this->request->get('AMT'); } public function processValidated() { $this->invoice->addPayment($this); } public function validateStatus() { if (!in_array($this->request->get('ACK'), array('Success', 'SuccessWithWarning'))) throw new Am_Exception_Paysystem_TransactionInvalid($this->request->get('L_SHORTMESSAGE0')); return true; } public function validateTerms() { return true; } public function autoCreateGetProducts() { $item_name = $this->request->get('WP_ITEM_NAME'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('wsopro_item_name', $item_name); if($billing_plan) return array($billing_plan->getProduct()); } function validateBusiness() { return true; } public function validateSource() { return true; } public function findInvoiceId(){ return $this->request->get('PROFILEID', $this->request->get('TRANSACTIONID')); } } PK\=&&!default/plugins/payment/epoch.phpnu[getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('epoch_product_id', "Epoch Product ID", "you must create the same product in Epoch and enter its number here")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('epoch_site_subcat', "Epoch Site Subcat", "leave empty if you are not sure")); } public function canAutoCreate() { return true; } public function canUpgrade(Invoice $invoice, InvoiceItem $item, ProductUpgrade $upgrade) { return false; } public function getRecurringType() { return self::REPORTS_REBILL; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("co_code") ->setLabel("Company code\n" . 'Three (3) alphanumeric ID assigned by Epoch (Company code does not change)'); $form->addAdvCheckbox("testing") ->setLabel("Testing\n" . 'enable/disable payments with test credit cars ask Epoch support for test credit card numbers'); $form->addAdvCheckbox("ach_form") ->setLabel("Enable ACH Flag\n" . 'If this field is passed in it will enable online check (ACH) processing. Online check processing is only valid for US'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $a->co_code = $this->getConfig('co_code'); $a->pi_code = $invoice->getItem(0)->getBillingPlanData('epoch_product_id'); if($site_subcat = $invoice->getItem(0)->getBillingPlanData('epoch_site_subcat')) $a->site_subcat = $site_subcat; $a->reseller = 'a'; $a->zip = $invoice->getZip(); $a->email = $invoice->getEmail(); $a->country = $invoice->getCountry(); $a->no_userpass = 1; $a->name = $invoice->getName(); $a->street = $invoice->getStreet(); $a->phone = $invoice->getPhone(); $a->city = $invoice->getCity(); $a->state = $invoice->getState(); $a->pi_returnurl = $this->getPluginUrl("thanks"); $a->response_post = 1; $a->x_payment_id = $invoice->public_id; if($this->getConfig('ach_form')) { $a->ach_form = 1; } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Epoch_IPN($this, $request, $response, $invokeArgs); } public function createThanksTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Epoch_Thanks($this, $request, $response, $invokeArgs); } function getReadme(){ $url = $this->getDi()->url('payment/epoch/ipn',null,true,true); return <<Epoch payment plugin ---------------------------------------------------------------------- - Set up products with the same settings as you have defined in aMember. Then enter Epoch Product IDs into corresponding field in aMember Product settings (aMember Cp -> Manage Products->Edit product -> Billing terms) - Set up the data postback URL to {$url} CUT; } } class Am_Paysystem_Transaction_Epoch_IPN extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'email' => 'email', 'name' => 'name', 'country' => 'country', 'state' => 'state', 'zip' => 'zip', 'state' => 'state', 'user_external_id' => 'email', 'invoice_external_id' => 'order_id', ); public function getUniqId() { if($this->request->get('transaction_id')) { return $this->request->get('transaction_id'); } else { return $this->request->get('ets_transaction_id'); } } function findInvoiceId() { if($this->request->get("x_payment_id")) { return $this->request->get("x_payment_id"); } elseif($this->request->get("ets_transaction_id")) { if($invoice = $this->getPlugin()->getDi()->invoiceTable->findByReceiptIdAndPlugin($this->request->get("ets_transaction_id"), $this->getPlugin()->getId())) return $invoice->public_id; if($member_id = $this->request->get('ets_member_idx')) { if($invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByData(Am_Paysystem_Epoch::EPOCH_MEMBER_ID, $member_id)) return $invoice->public_id; } } elseif($member_id = $this->request->get('mcs_or_idx')) { if($invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByData(Am_Paysystem_Epoch::EPOCH_MEMBER_ID, $member_id)) return $invoice->public_id; } } public function getIps() { $req = new Am_HttpRequest('https://epoch.com/ip_list.php'); $res = $req->send(); $body = explode('|', $res->getBody()); $ips = array(); foreach($body as $ip) { if(filter_var($ip, FILTER_VALIDATE_IP)) { $ips[] = $ip; } else { $ips[] = array($ip.'0',$ip.'255'); } } // # ULA-46577-159 This IP is used to send manual postbacks when Epoch conducts tests and submits duplicate postbacks during the troubleshooting process. $ips[] = '208.236.105.27'; return $ips; } public function validateSource() { $ips = $this->plugin->getDi()->cacheFunction->call(array($this, 'getIps'), array(), array(), 24*3600); $this->_checkIp($ips); return true; } public function validateStatus() { if($this->request->get("ets_transaction_id") || $this->request->get('mcs_or_idx')) return true; if(substr($this->request->get('ans'),0,1) != 'Y') throw new Am_Exception_Paysystem_TransactionInvalid('Transaction declined!'); if((strstr($this->request->get('ans'), 'YGOODTEST') !== false) && !$this->getPlugin()->getConfig('testing')) throw new Am_Exception_Paysystem_TransactionInvalid("Received test result but test mode is not enabled!"); return true; } public function validateTerms() { return true; } function processValidated() { if($member_id = $this->request->get('member_id')) { $this->invoice->data()->set(Am_Paysystem_Epoch::EPOCH_MEMBER_ID, $member_id)->update(); } /* C = Credit to Customers Account D = Chargeback Transaction F = Initial Free Trial Transaction I = Standard Initial Recurring Transaction J = Denied Trial Conversion K = Cancelled Trial N = Non-Initial Recurring Transaction O = Non-Recurring Transaction T = Initial Paid Trial Order Transaction U = Initial Trial Conversion X = Returned Check Transaction */ if ($ets_transaction_type = $this->request->get("ets_transaction_type")) { if (in_array($this->request->get("ets_transaction_type"), array('U', 'N'))) $this->invoice->addPayment($this); if (in_array($this->request->get("ets_transaction_type"), array('K'))) $this->invoice->setCancelled(); if (in_array($this->request->get("ets_transaction_type"), array('D', 'C', 'X', 'A'))) $this->invoice->addRefund($this, $this->request->get("ets_ref_trans_ids"), abs($this->request->get("ets_amountlocal"))); } elseif ($mcs_mcs_memberstype = $this->request->get("mcs_memberstype")) { $this->invoice->setCancelled(); } elseif ($ets_payment_type = $this->request->get("ets_payment_type")) { if (in_array($ets_payment_type, array('X', 'D'))) { $this->invoice->addRefund($this, $this->request->get("ets_ref_trans_ids"), abs($this->request->get("ets_amountlocal"))); $this->invoice->setCancelled(); } if (in_array($ets_payment_type, array('A', 'C'))) $this->invoice->addRefund($this, $this->request->get("ets_ref_trans_ids"), abs($this->request->get("ets_amountlocal"))); } else { $this->invoice->addPayment($this); } print "OK"; } public function autoCreateGetProducts() { $Id = $this->request->getFiltered('pi_code'); if (empty($Id)) return; $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('epoch_product_id', $Id); if (!$pl) return; $pr = $pl->getProduct(); if (!$pr) return; return array($pr); } } class Am_Paysystem_Transaction_Epoch_Thanks extends Am_Paysystem_Transaction_Epoch_IPN { public function validateSource() { return true; } public function processValidated() { return; } }PK\b$default/plugins/payment/jambopay.phpnu[getConfig('business') && $this->getConfig('key'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('business') ->setLabel("JamboPay Account ID (Email address)"); $form->addPassword('key') ->setLabel("Shared Key"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $params = array( 'jp_item_type' => 'cart', 'jp_item_name' => $invoice->getLineDescription(), 'order_id' => $invoice->public_id, 'jp_business' => $this->getConfig('business'), 'jp_payee' => $invoice->getEmail(), 'jp_shipping' => '', 'jp_amount_1' => $invoice->currency == 'KES' ? $invoice->first_total : $this->exchange($invoice->first_total), 'jp_amount_2' => 0, 'jp_amount_5' => $invoice->currency == 'USD' ? $invoice->first_total : 0, 'jp_rurl' => $this->getPluginUrl('thanks'), 'jp_furl' => $this->getCancelUrl(), 'jp_curl' => $this->getCancelUrl() ); $invoice->data()->set('jambopay-terms-KES', $params['jp_amount_1']); $invoice->data()->set('jambopay-terms-USD', $params['jp_amount_5']); $invoice->save(); foreach ($params as $k => $v) { $a->addParam($k, $v); } $result->setAction($a); } function exchange($val) { $date = sqlDate('now'); $kes = $this->getDi()->currencyExchangeTable->getRate('KES', $date); $usd = $this->getDi()->currencyExchangeTable->getRate('USD', $date); return moneyRound($val * $kes / $usd); } function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return null; } function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Jambopay_Thanks($this, $request, $response, $invokeArgs); } function calculateSignature($params) { return md5(utf8_encode(implode('', array( $params['JP_MERCHANT_ORDERID'], $params['JP_AMOUNT'], $params['JP_CURRENCY'], $this->getConfig('key'), $params['JP_TIMESTAMP'] )))); } function getReadme() { $link = $this->getDi()->url('admin-currency-exchange'); return <<here. CUT; } } class Am_Paysystem_Transaction_Jambopay_Thanks extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('JP_MERCHANT_ORDERID'); } public function getUniqId() { return $this->request->get('JP_TRANID'); } public function validateSource() { $params = $this->request->getRequestOnlyParams(); $sig = $params['JP_PASSWORD']; return $sig == $this->getPlugin()->calculateSignature($params); } public function validateStatus() { return true; } public function validateTerms() { return (float)$this->invoice->data()->get('jambopay-terms-' . $this->request->get('JP_CURRENCY')) == (float)$this->request->get('JP_AMOUNT'); } }PK\2mx^^$default/plugins/payment/i-payout.phpnu[addText('merchant')->setLabel('Merchant Name'); $form->addText('MerchantGUID')->setLabel('API Merchant ID'); $form->addPassword('MerchantPassword')->setLabel('API Merchant Password'); $form->addAdvCheckbox('testing') ->setLabel("Is it a Sandbox(Testing) Account?"); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('USD', 'EUR', 'GBP', 'AUD', 'JPY', 'CAD', 'CNY', 'HKD', 'CHF', 'NZD', 'THB', 'SGD'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); if (!$user->data()->get(self::DATA_KEY)) { //create user $req = new Am_HttpRequest($this->url(), Am_HttpRequest::METHOD_POST); $req->addPostParameter(array( 'fn' => 'eWallet_RegisterUser', 'MerchantGUID' => $this->getConfig('MerchantGUID'), 'MerchantPassword' => $this->getConfig('MerchantPassword'), 'UserName' => $user->login, 'FirstName' => $user->name_f, 'LastName' => $user->name_l, 'EmailAddress' => $user->email, 'DateOfBirth' => '1/1/1900' //unknown )); $this->logRequest($req); $resp = $req->send(); $this->logResponse($resp); if ($resp->getStatus() != 200) { $result->setFailed('Incorrect HTTP response status: ' . $resp->getStatus()); return; } parse_str($resp->getBody(), $tmp); parse_str($tmp['response'], $params); if ($params['m_Code'] != 'NO_ERROR') { $result->setFailed($params['m_Text']); return; } $user->data()->set(self::DATA_KEY, $params['TransactionRefID'])->update(); } //create invoice $req = new Am_HttpRequest($this->url(), Am_HttpRequest::METHOD_POST); $arrItems = array( 'Amount' => $invoice->first_total, 'CurrencyCode' => $invoice->currency, 'ItemDescription' => $invoice->getLineDescription(), 'MerchantReferenceID' => $invoice->public_id, 'UserReturnURL' => $this->getReturnUrl(), 'MustComplete' => 'false', 'IsSubscription' => 'false' ); $req->addPostParameter(array( 'fn' => 'eWallet_AddCheckoutItems', 'MerchantGUID' => $this->getConfig('MerchantGUID'), 'MerchantPassword' => $this->getConfig('MerchantPassword'), 'UserName' => $user->login, 'arrItems' => sprintf('[%s]', http_build_query($arrItems)), 'AutoChargeAccount' => 'false' )); $this->logRequest($req); $resp = $req->send(); $this->logResponse($resp); if ($resp->getStatus() != 200) { $result->setFailed('Incorrect HTTP response status: ' . $resp->getStatus()); return; } parse_str($resp->getBody(), $tmp); parse_str($tmp['response'], $params); if ($params['m_Code'] != 'NO_ERROR') { $result->setFailed($params['m_Text']); return; } //login and redirect $req = new Am_HttpRequest($this->url(), Am_HttpRequest::METHOD_POST); $req->addPostParameter(array( 'fn' => 'eWallet_RequestUserAutoLogin', 'MerchantGUID' => $this->getConfig('MerchantGUID'), 'MerchantPassword' => $this->getConfig('MerchantPassword'), 'UserName' => $user->login )); $this->logRequest($req); $resp = $req->send(); $this->logResponse($resp); if ($resp->getStatus() != 200) { $result->setFailed('Incorrect HTTP response status: ' . $resp->getStatus()); return; } parse_str($resp->getBody(), $tmp); parse_str($tmp['responset'], $params); if ($params['m_Code'] != 'NO_ERROR') { $result->setFailed($params['m_Text']); return; } $a = new Am_Paysystem_Action_Redirect($this->urlLogin()); $a->secKey = $params['m_ProcessorTransactionRefNumber']; $result->setAction($a); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'ipn') { echo 'OK'; } return parent::directAction($request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_IPayout($this, $request, $response, $invokeArgs); } function url() { return $this->getConfig('testing') ? 'https://www.testewallet.com/eWalletWS/ws_Adapter.aspx' : 'https://www.i-payout.net/eWalletWS/ws_Adapter.aspx'; } function urlLogin() { return sprintf($this->getConfig('testing') ? 'https://%s.testewallet.com/MemberLogin.aspx' : 'https://%s.globalewallet.com/MemberLogin.aspx', $this->getConfig('merchant')); } function hash($trnx_id, $log_id) { return strtoupper(sha1($trnx_id . $log_id . $this->getConfig('MerchantGUID') . $this->getConfig('MerchantPassword'))); } function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Merchant Notify URL to: $url To do it you need to login into eWallet Management Console and set it up on System Overview page in the eWallet Setup section. CUT; } } class Am_Paysystem_Transaction_IPayout extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('log_id'); } public function findInvoiceId() { return $this->request->get('trnx_id'); } public function validateSource() { return $this->plugin->hash($this->request->get('trnx_id'), $this->request->get('log_id')) == $this->request->get('hash'); } public function validateStatus() { return $this->request->get('status_id') == 'settled'; } public function validateTerms() { return true; } } PK\ii'default/plugins/payment/thrive-cart.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText('thrive_cart_product_id', "Thrive Cart product ID", "for example product-1, upsell-3 or downsell-7")); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("secret", array('class'=>'el-wide')) ->setLabel("Thrive Cart Secret Word\n" . "it can be found at Settings -> ThriveCart API"); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_ThriveCart($this, $request, $response, $invokeArgs); } public function canAutoCreate() { return true; } public function getReadme() { $url = Am_Html::escape($this->getPluginUrl('ipn')); return <<Thrive Cart integration Set up notification url for your Thrive Cart to: $url CUT; } } class Am_Paysystem_Transaction_ThriveCart extends Am_Paysystem_Transaction_Incoming { function generateUserExternalId(array $userInfo) { $customer = $this->request->get('customer'); return $customer['email']; } public function generateInvoiceExternalId() { $this->request->get('order_id'); } public function fetchUserInfo() { $customer = $this->request->get('customer'); return array( 'name_f' => $customer['first_name'], 'name_l' => $customer['last_name'], 'email' => $customer['email'], 'country' => $customer['email']['address']['country'], ); } public function recur($pref, $k, $v) { if(is_array($v)) foreach($v as $k_ => $v_) $this->recur(($pref ? $pref.'_' : '').$k_, $k_, $v_); else { $this->request->set($pref, $v); } } public function autoCreateGetProducts() { $item_name = $this->request->get('purchase_map_flat'); if (empty($item_name)) return; $products = array(); foreach (explode(',', $item_name) as $pid) { if(!($pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('thrive_cart_product_id', $pid))) continue; if($p = $pl->getProduct()) $products[] = $p; } return $products; } public function getReceiptId() { return $this->request->get('order_id'); } public function getAmount() { return moneyRound($this->request->get('order_total')); } public function getUniqId() { return $this->request->get('order_id'); } public function validateSource() { return $this->request->get('thrivecart_secret') == $this->getPlugin()->getConfig('secret'); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); } public function findInvoiceId() { //nothing } }PK\i*/default/plugins/payment/cashenvoy/cashenvoy.phpnu[addInteger('merchant_id', array('size' => 20)) ->setLabel('Your Merchant ID#'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_HtmlTemplate_Cashenvoy($this->getDir(), 'confirm.phtml'); $a->url = $this->getConfig('testing') ? self::SANDBOX_PAY_URL : self::LIVE_PAY_URL; $a->ce_merchantid = $this->config['merchant_id']; $a->ce_transref = 'CSHNV' . $invoice->public_id; $a->ce_amount = $invoice->first_total; $a->ce_customerid = $invoice->getUser()->email; $a->ce_memo = $invoice->getLineDescription(); $a->ce_notifyurl = $this->getPluginUrl('thanks'); $a->ce_window = 'parent'; $a->invoice = $invoice; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { //do nothing } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Cashenvoy_Thanks($this, $request, $response, $invokeArgs); } public function getSupportedCurrencies() { return array('NGN','USD'); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_Cashenvoy_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { protected $vars; public function getUniqId() { return $this->request->getFiltered("ce_transref").$this->request->getFiltered("ce_response"); } public function validateSource() { $request = new Am_HttpRequest($this->getPlugin()->getConfig('testing') ? Am_Paysystem_Cashenvoy::SANDBOX_STATUS_URL : Am_Paysystem_Cashenvoy::LIVE_STATUS_URL, Am_HttpRequest::METHOD_POST); $request->addPostParameter(array( 'mertid' => $this->getPlugin()->getConfig('merchant_id'), 'transref' => $this->request->getFiltered("ce_transref"), 'respformat' => 'json' )); $response = $request->send(); $this->vars = json_decode($response->getBody(), true); $this->log->add($this->vars); return true; } public function validateStatus() { if($this->vars['TransactionStatus'] == 'C00') return true; $errors = array( 'C01' => 'User cancellation.', 'C02' => 'User cancellation by inactivity.', 'C03' => 'No transaction record.', 'C04' => 'Insufficient funds.', 'C05' => 'Transaction failed. Contact support@cashenvoy.com for more information.'); throw new Am_Exception_QuietError($errors[$this->vars['TransactionStatus']].'/'.$this->request->getFiltered("ce_transref")); } public function validateTerms() { return doubleval($this->request->get("ce_amount")) == doubleval($this->invoice->first_total); } public function findInvoiceId() { return substr($this->request->getFiltered("ce_transref"),5); } } class Am_Paysystem_Action_HtmlTemplate_Cashenvoy extends Am_Paysystem_Action_HtmlTemplate { protected $_template; protected $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } PK\7w7default/plugins/payment/cashenvoy/scripts/confirm.phtmlnu[setLayout('layout.phtml'); ?>
      _script('_receipt.phtml'); ?>

      PK\`z'default/plugins/payment/clickbetter.phpnu[billingPlanTable->customFields()->add( new Am_CustomFieldText( 'clickbetter_prod_item', "ClickBetter product number", "" , array(/* ,'required' */) )); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { } public function getRecurringType() { return self::REPORTS_REBILL; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect('https://clickbetter.com/pay/'.$invoice->getItem(0)->getBillingPlanData('clickbetter_prod_item')); $result->setAction($a); $a->api = 'yes'; $a->custom1 = $invoice->public_id; $a->first_name = $invoice->getFirstName(); $a->last_name = $invoice->getLastName(); $a->email = $invoice->getEmail(); $a->city = $invoice->getCity(); $a->address = $invoice->getStreet(); $a->phone_no = $invoice->getPhone(); if($country = $invoice->getCountry()) { if(!($country3 = $this->getDi()->db->selectCell("SELECT alpha3 FROM ?_country WHERE country=?", $country))) $country3 = $country; } else $country3 = ''; $a->country = $country3; $a->state = $invoice->getState(); $a->zipcode = $invoice->getZip(); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Clickbetter($this, $request, $response, $invokeArgs); } public function canAutoCreate() { return true; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<ClickBetter integration 1. Login to your ClickBetter account. 2. Click on “MyProducts” OR “Sell” tab and then clickon API tab. 3. Set IPN URL field to $url 4. Click on UPDATE IPN URL button! 5. Set IPN URL for refund field to $url 6. Click on UPDATE IPN URL FOR REFUND button! 7. Edit your products in Amember and set up "ClickBetter product number" CUT; } } class Am_Paysystem_Transaction_Clickbetter extends Am_Paysystem_Transaction_Incoming { // payment const SALE = "sale"; const REBILL = "rebill"; // refund const REFUND = "refund"; protected $_autoCreateMap = array( 'name_f' => 'firstName', 'name_l' => 'lastName', 'email' => 'customeremail', 'phone' => 'phone', 'city' => 'city', 'zip' => 'zipcode', 'street' => 'address', 'user_external_id' => 'customeremail', 'invoice_external_id' => 'orderid', ); public function fetchUserInfo() { $countryRecord = Am_Di::getInstance()->countryTable->findFirstBy(array('country' => $this->request->get('country'))); if(!$countryRecord) $countryRecord = Am_Di::getInstance()->countryTable->findFirstBy(array('alpha3' => $this->request->get('country'))); if ($countryRecord && $countryRecord->isLoaded()) { $country = $countryRecord->country; $stateRecord = Am_Di::getInstance()->stateTable->findFirstBy( array( 'country' => $countryRecord->country, 'state' => $this->request->get('state') )); if(!$stateRecord) $stateRecord = Am_Di::getInstance()->stateTable->findFirstBy( array( 'country' => $countryRecord->country, 'state' => $countryRecord->country .'-'. $this->request->get('state'), )); if ($stateRecord && $stateRecord->isLoaded()) $state = $stateRecord->state; else $state = $this->request->get('state'); } else { $country = $this->request->get('country'); $state = $this->request->get('state'); } return array_merge(parent::fetchUserInfo(), array( 'country' => $country, 'state' => $state, )); } public function autoCreateGetProducts() { $item_name = $this->request->get('productid'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('clickbetter_prod_item', $item_name); if ($billing_plan) return array($billing_plan->getProduct()); } public function getReceiptId() { return $this->getOrderid(); } public function getAmount() { return moneyRound($this->request->get('amount')); } public function getUniqId() { return @$this->getOrderid(); } public function getOrderid() { return $this->request->get('orderid', preg_replace("/[^0-9]/", '', $this->request->get('testmode'))); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $vars = $this->request->isPost() ? $this->request->getPost() : $this->request->getQuery(); switch ($vars['type']) { //payment case Am_Paysystem_Transaction_Clickbetter::SALE: $this->invoice->addPayment($this); break; //refund case Am_Paysystem_Transaction_Clickbetter::REFUND: $this->invoice->addRefund($this, Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); break; //cancel case Am_Paysystem_Transaction_Clickbetter::REBILL: if($this->request->get('paystatus') == 'cancelled') $this->invoice->setCancelled(true); else $this->invoice->addPayment($this); break; } } public function findInvoiceId() { return $this->request->getFiltered('custom1'); } }PK\M#(55-default/plugins/payment/checkout/checkout.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Checkout extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_REVISION = '5.2.2'; protected $defaultTitle = 'Checkout'; protected $defaultDescription = 'electronic payments'; const URL = 'https://payment.checkout.fi'; const LOG_PREFIX_ERROR = '[Checkout Payment ERROR]. '; protected static $coMapOut = array( 'VERSION', 'STAMP', 'AMOUNT', 'REFERENCE', 'MESSAGE', 'LANGUAGE', 'MERCHANT', 'RETURN', 'CANCEL', 'REJECT', 'DELAYED', 'COUNTRY', 'CURRENCY', 'DEVICE', 'CONTENT', 'TYPE', 'ALGORITHM', 'DELIVERY_DATE', 'FIRSTNAME', 'FAMILYNAME', 'ADDRESS', 'POSTCODE', 'POSTOFFICE' ); public static $coMapIn = array( 'VERSION', 'STAMP', 'REFERENCE', 'PAYMENT', 'STATUS', 'ALGORITHM' ); public function supportsCancelPage() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant_id') ->setLabel('Checkout Merchant') ->addRule('required'); $form->addText('security_key') ->setLabel('Checkout Security Key') ->addRule('required'); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('EUR'); } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $data = array( 'VERSION' => "0001", 'STAMP' => $invoice->public_id . '-' . $this->getDi()->time, 'AMOUNT' => $invoice->first_total * 100, 'REFERENCE' => $invoice->public_id, 'MESSAGE' => $invoice->getLineDescription(), 'LANGUAGE' => "FI", 'MERCHANT' => $this->getConfig('merchant_id'), 'RETURN' => $this->getPluginUrl('thanks'), 'CANCEL' => $this->getCancelUrl(), 'REJECT' => "", 'DELAYED' => "", 'COUNTRY' => "FIN", 'CURRENCY' => "EUR", 'DEVICE' => "10", 'CONTENT' => "1", 'TYPE' => "0", 'ALGORITHM' => "1", 'DELIVERY_DATE' => date("Ymd"), 'FIRSTNAME' => $user->name_f, 'FAMILYNAME' => $user->name_l, 'ADDRESS' => $user->street . ($user->street2 ? '; ' . $user->street2 : ''), 'POSTCODE' => $user->zip, 'POSTOFFICE' => "", ); $data['MAC'] = $this->getMac(self::$coMapOut, $data); $req = new Am_HttpRequest(self::URL, Am_HttpRequest::METHOD_POST); $req->addPostParameter($data); $this->logRequest($data); $res = $req->send(); if ($res->getStatus() != '200') throw new Am_Exception_InternalError(self::LOG_PREFIX_ERROR . "[_process()] - bad status of server response [{$res->getStatus()}]"); if (!($body=$res->getBody())) throw new Am_Exception_InternalError(self::LOG_PREFIX_ERROR . "[_process()] - server return null"); $this->logResponse($body); if(!($xml = simplexml_load_string($body))) throw new Am_Exception_InternalError(self::LOG_PREFIX_ERROR . "[_process()] - server return bad xml"); $a = new Am_Paysystem_Action_HtmlTemplate_Checkout($this->getDir(), 'payment-checkout-redirect.phtml'); $a->xml = $xml; $result->setAction($a); } public function getMac($map, $data) { $mac = ''; foreach ($map as $key) { $mac .= $data[$key] . '+'; } $mac .= $this->getConfig('security_key'); return strtoupper(md5($mac)); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Checkout($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Checkout($this, $request, $response, $invokeArgs); } function getReadme() { return <<Checkout Payment Plugin This plugin allows you to use Checkout payment sevice for payment. You have to register for an account at http://checkout.fi/ to use this plugin. This plugin does not support recurring payment. For test you can use next data: Seller's identity (Merchant): 375917 Security key: SAIPPUAKAUPPIAS CUT; } } class Am_Paysystem_Transaction_Checkout extends Am_Paysystem_Transaction_Incoming { public function validateSource() { $mac = $this->getPlugin()->getMac(Am_Paysystem_Checkout::$coMapIn, $this->request->getParams()); return $mac == $this->request->getFiltered('MAC'); } public function findInvoiceId() { return $this->request->getFiltered('REFERENCE'); } public function validateTerms() { return true; } public function validateStatus() { $status = $this->request->getFiltered('STATUS'); if(in_array($status, array(2, 4, 5, 6, 7, 8, 9, 10))) return true; } public function getUniqId() { return $this->request->getFiltered('PAYMENT'); } }PK\naWWHdefault/plugins/payment/checkout/scripts/payment-checkout-redirect.phtmlnu[setLayout('layout.phtml'); ?> payments->payment->banks as $bankX):?>
      ' method='post'> $value):?> '>
      PK\F&&#default/plugins/payment/moneris.phpnu[addText("ps_store_id")->setLabel("Merchant ps_store_id\n" . 'Provided by Moneris Solutions – Hosted Paypage Configuration Tool. ' . 'Identifies the configuration for the Hosted Paypage.'); $form->addText("hpp_key")->setLabel("Merchant hpp_key\n" . 'Provided by Moneris Solutions – Hosted Paypage Configuration Tool. ' . 'This is a security key that corresponds to the ps_store_id.'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } function getSupportedCurrencies() { return array('CAD', 'USD'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); $a->ps_store_id = $this->getConfig('ps_store_id'); $a->hpp_key = $this->getConfig('hpp_key'); $a->charge_total = sprintf('%.2f', $invoice->first_total); $a->cust_id = $invoice->public_id; $a->email = $u->email; $a->shipping_cost = sprintf('%.2f', $invoice->first_shipping); $i = 1; foreach ($invoice->getItems() as $item) { $a->{'id' . $i} = $item->item_id; $a->{'description' . $i} = $item->item_title; $a->{'quantity' . $i} = $item->qty; $a->{'price' . $i} = $item->first_price; $a->{'subtotal' . $i} = $item->first_total; $i++; } $a->bill_first_name = $u->name_f; $a->bill_last_name = $u->name_l; $a->bill_address_one = $u->street; $a->bill_city = $u->city; $a->bill_state_or_province = $u->state; $a->bill_postal_code = $u->zip; $a->bill_country = $u->country; if ($invoice->second_total > 0) { $periods = array('m' => 'month', 'y' => 'year', 'd' => 'day', 'w' => 'week'); $second_period = new Am_Period($invoice->second_period); $a->recurUnit = $periods[$second_period->getUnit()]; $a->recurPeriod = $second_period->getCount(); $a->recurStartNow = ($invoice->first_total > 0) ? 'true' : 'false'; $a->doRecur = 1; $a->recurStartDate = date('Y/m/d', strtotime($invoice->calculateRebillDate(1))); $a->recurAmount = sprintf('%.2f', $invoice->second_total); $a->recurNum = $invoice->rebill_times; } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Moneris($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Moneris_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<Moneris payment plugin configuration CONFIGURATION OF ACCOUNT 1. Login into your Moneris account. 2. Once you have successfully logged in, click on the “ADMIN” menu item on the left and then in the submenu that appears click on “HOSTED CONFIG”. 3. Set Response method to Sent to your server as a POST Approved URL to %root_surl%/payment/moneris/thanks Declined URL to %root_surl%/cancel 4. Click on "Configure Response Fields". 5. Enable "Return other customer fields. (cust_id, client_email, note . . .)". Enable "Perform asynchronous data post.". Set "Async Response URL" to %root_surl%/payment/moneris/ipn CUT; } } class Am_Paysystem_Transaction_Moneris_Thanks extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('cust_id'); } public function getUniqId() { return $this->request->get('bank_transaction_id'); } public function validateSource() { return true; } public function validateStatus() { return intval($this->request->get('response_code')) < 50; } public function validateTerms() { return $this->request->get('charge_total') == $this->invoice->first_total; } public function getInvoice() { return $this->invoice; } public function processValidated() { parent::processValidated(); if ($this->invoice->status == Invoice::RECURRING_ACTIVE) $this->invoice->extendAccessPeriod(Am_Period::RECURRING_SQL_DATE); } } class Am_Paysystem_Transaction_Moneris extends Am_Paysystem_Transaction_Incoming { protected $xml; public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $this->xml = simplexml_load_string($request->get('xml_response')); parent::__construct($plugin, $request, $response, $invokeArgs); } public function findInvoiceId() { return $this->xml->od_other->cust_id; } public function getUniqId() { return $this->xml->bank_transaction_id; } public function validateSource() { if (!$this->xml) return false; return true; } public function validateStatus() { return (intval($this->xml->response_code) < 50 && strtolower($this->xml->response_code) != 'null'); } public function validateTerms() { return $this->xml->charge_total == ($this->invoice->isFirstPayment() ? $this->invoice->first_total : $this->invoice->second_total); } public function processValidated() { parent::processValidated(); if ($this->invoice->status == Invoice::RECURRING_ACTIVE) $this->invoice->extendAccessPeriod(Am_Period::RECURRING_SQL_DATE); } }PK\#default/plugins/payment/hotmart.phpnu[addText('token', array('size' => 40)) ->setLabel('Your Access Token') ->addRule('required'); } public function __construct(Am_Di $di, array $config) { parent::__construct($di, $config); foreach ($di->paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'hotmart_id', "Hotmart Product#", "" , array(/* ,'required' */) )); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function isConfigured() { return strlen($this->getConfig('token', '')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Hotmart($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } public function canAutoCreate() { return true; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<$url CUT; } } class Am_Paysystem_Transaction_Hotmart extends Am_Paysystem_Transaction_Incoming { // payment const APPROVED = "approved"; // refund const REFUNDED = "refunded"; protected $_autoCreateMap = array( 'name_f' => 'first_name', 'name_l' => 'last_name', 'email' => 'email', 'city' => 'address_city', 'zip' => 'address_zip_code', 'state' => 'address_state', 'country' => 'address_country', 'user_external_id' => 'email', 'invoice_external_id' => 'transaction', ); public function autoCreateGetProducts() { $item_name = $this->request->get('prod'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('hotmart_id', $item_name); if ($billing_plan) return array($billing_plan->getProduct()); } public function getReceiptId() { return $this->request->get('transaction'); } public function getAmount() { return moneyRound($this->request->get('price')); } public function getUniqId() { return @$this->request->get('transaction'); } public function validateSource() { return $this->request->get('hottok') == $this->getPlugin()->getConfig('token'); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->request->get('status')) { //payment case Am_Paysystem_Transaction_Hotmart::APPROVED: $this->invoice->addPayment($this); break; //refund case Am_Paysystem_Transaction_Hotmart::REFUNDED: $this->invoice->addRefund($this, Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); break; } } public function findInvoiceId() { return $this->request->get('transaction'); } } PK\kXyUFUF-default/plugins/payment/allopass/allopass.phpnu[addText('site_id') ->setLabel("Site ID\n" . 'Identifier of the merchant site'); $form->addText('api_key') ->setLabel("API Key\n" . 'This keyset is available under My Profile in the Allopass merchant account.'); $form->addText('api_secret_key') ->setLabel("API Secret Key\n" . 'This keyset is available under My Profile in the Allopass merchant account.'); $form->addAdvCheckbox('testing') ->setLabel('Test Mode'); } public function getSupportedCurrencies() { return array('EUR', 'GBP', 'USD'); } function getHash($queryParameters = array()) { ksort($queryParameters); $stringToHash = ''; foreach ($queryParameters as $parameter => $value) { $stringToHash .= $parameter . (is_array($value) ? implode('', $value) : $value); } $stringToHash .= $this->getConfig('api_secret_key'); $signature = hash(self::API_HASH_FUNCTION, $stringToHash); return $signature; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { date_default_timezone_set('UTC'); $params = array( 'api_hash' => self::API_HASH_FUNCTION, 'api_ts' => time(), 'api_key' => $this->getConfig('api_key'), 'format' => self::RESPONSE_FORMAT, 'site_id' => $this->getConfig('site_id'), // Identifier of the merchant site. 'product_name' => $invoice->getLineDescription(), // Product name. 'forward_url' => $this->getReturnUrl(), // URL of the page where customers are forwarded when an access code //has been successfully redeemed or when a payment without code was successful. 'forward_target' => 'parent', // Specifies where to open the forward and error URL. Allowed values are: // parent – uses the parent window (default) // current – uses the current window (recommended if the payment dialog is loaded into an iframe) 'price_mode' => 'price', // Defines what "amount" refers to. Currently, only end-user price is supported ("price") 'error_url' => $this->getCancelUrl(), // URL of the page where customers are forwarded if a transaction is denied. 'notification_url' => $this->getPluginUrl('ipn'), // Payment notification URL 'amount' => $invoice->first_total, // Amount of the transaction. The currency is determined by the price point identifier. 'price_policy' => 'nearest', // Affects sorting and prioritization of retrieved price points. Given an amount: // high-preferred – First retrieves and presents those higher than amount, then those below // high-only – Only returns price points above the defined amount // low-preferred – First retrieves and presents those lower than amount, then those higher // low-only – Only returns price points below the defined amount // nearest – Pricepoints are sorted and listed by the absolute value difference to amount 'reference_currency' => $invoice->currency, // Base currency (EUR is default) 'merchant_transaction_id' => $invoice->public_id, // Identifier of the transaction 'data' => $invoice->public_id // Custom data ); /* require_once(dirname(__FILE__).'/apikit/api/AllopassAPI.php'); $conf_xml = ' ' . $this->getConfig('api_key') . ' ' . $this->getConfig('api_secret_key') . ' ' . self::API_HASH_FUNCTION . ' ' . self::RESPONSE_FORMAT . ' 30 http 80 api.allopass.com '; $Allopas = new AllopassAPI($conf_xml); // use $configurationEmailAccount variable $Button = $Allopas->createButton($params); $BuyUrl = $Button->getBuyUrl(); */ /**/ ksort($params); $hash = $this->getHash($params); $params['api_sig'] = $hash; $request = new Am_Paysystem_Allopass_Request(self::RESPONSE_FORMAT, self::API_HASH_FUNCTION, $this->getConfig('api_secret_key')); $request->makeRequest(self::API_BASE_URL . '/onetime/button', http_build_query($params, '', '&')); $BuyUrl = $request->getResponse()->buy_url; /**/ if ($request->isResponseValidated() && $request->httpStatusCode == '200') { $a = new Am_Paysystem_Action_Redirect($BuyUrl); $result->setAction($a); } else { throw new Am_Exception_Paysystem_TransactionSource('Validation failed. Status code: [' . $request->httpStatusCode . '] Error code: [' . $request->code . '] Message: [' . $request->message . ']'); } } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Allopass($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme(){ return <<Allopass plugin installation - Configure plugin at aMember CP -> Setup/Configuration -> Allopass - Run a test transaction to ensure everything is working correctly. CUT; } } class Am_Paysystem_Transaction_Allopass extends Am_Paysystem_Transaction_Incoming{ function verifySignature($parameters = array()) { $api_hash = $parameters['api_hash'] ? $parameters['api_hash'] : Am_Paysystem_Allopass::API_HASH_FUNCTION; $signature = $parameters['api_sig']; unset($parameters['api_sig']); ksort($parameters); $string2compute = ''; foreach ($parameters as $name => $value) $string2compute .= $name . $value; return (hash($api_hash, $string2compute . $this->getPlugin()->getConfig('api_secret_key')) == $signature); } public function getUniqId() { return $this->request->get("transaction_id"); } public function findInvoiceId() { return $this->request->get("merchant_transaction_id"); } public function validateSource() { $vars = $this->request->getQuery(); $verified = $this->verifySignature($vars); if(!$verified) throw new Am_Exception_Paysystem_TransactionSource('Received security hash is not correct'); return true; } public function validateStatus() { if($this->request->get('test') == 'true' && !$this->getPlugin()->getConfig('testing')){ throw new Am_Exception_Paysystem_TransactionInvalid('Test IPN received by test mode is not enabled'); } return ($this->request->get('status') == '0'); //0 - Success - Payment accepted } public function validateTerms() { /** * @todo Add real validation here; Need to check variables that will be sent from Allopass. */ return true; } public function getAmount() { return $this->request->get('amount'); } public function processValidated() { $this->invoice->addPayment($this); // Merchants may return an XML response to Allopass so as to explicitly acknowledge that the notification was successfully processed. // The Notification Response is optional but recommended. In the absence of a response from the merchant, Allopass will interpret an HTTP 200 return code as a success. // A response status of 0 is a failure, 1 is a success. After a failure, Allopass will attempt 4 more times. header('Content-Type: text/xml; charset=UTF-8'); echo ' 123 OK '; exit; } } class Am_Paysystem_Transaction_Allopass_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { return $this->request->get("merchant_transaction_id"); } public function getUniqId() { return $this->request->get("transaction_id"); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function validateSource() { //After a successful payment the Forward URL passes GET parameters that you can collect and use to query the /transaction for verification. date_default_timezone_set('UTC'); $params = array( 'id' => $this->getUniqId(), // Transaction Identifier 'api_hash' => Am_Paysystem_Allopass::API_HASH_FUNCTION, 'api_ts' => time(), 'api_key' => $this->getPlugin()->getConfig('api_key'), 'format' => Am_Paysystem_Allopass::RESPONSE_FORMAT ); /* require_once(dirname(__FILE__).'/apikit/api/AllopassAPI.php'); $conf_xml = ' ' . $this->getPlugin()->getConfig('api_key') . ' ' . $this->getPlugin()->getConfig('api_secret_key') . ' ' . Am_Paysystem_Allopass::API_HASH_FUNCTION . ' ' . Am_Paysystem_Allopass::RESPONSE_FORMAT . ' 30 http 80 api.allopass.com '; $Allopas = new AllopassAPI($conf_xml); // use $configurationEmailAccount variable $Transaction = $Allopas->getTransaction($this->getUniqId()); $status = $Transaction->getStatus(); */ /**/ ksort($params); $hash = $this->getHash($params); $params['api_sig'] = $hash; $request = new Am_Paysystem_Allopass_Request(Am_Paysystem_Allopass::RESPONSE_FORMAT, Am_Paysystem_Allopass::API_HASH_FUNCTION, $this->getPlugin()->getConfig('api_secret_key')); $request->makeRequest(self::API_BASE_URL . '/transaction', http_build_query($params, '', '&')); $status = $request->getResponse()->status; /**/ return ($status == '0'); } public function getInvoice() { return $this->invoice; } } class Am_Paysystem_Allopass_Request { protected $api_secret_key; protected $responseFormat = 'xml'; protected $hashFunction = 'sha1'; public $httpStatusCode; public $code; public $message; protected $responseHeaders = array(); protected $responseBody; function __construct($responseFormat, $hashFunction, $api_secret_key) { if ($responseFormat) $this->responseFormat = $responseFormat; if ($hashFunction) $this->hashFunction = $hashFunction; $this->api_secret_key = $api_secret_key; } public function makeRequest($url, $post='') { $sock = curl_init(); $headers = array(); if ($this->responseFormat == 'json') $headers[] = 'Content-type: application/json'; elseif ($this->responseFormat == 'xml') $headers[] = 'Content-type: text/xml'; /* curl_setopt_array($sock, array( CURLOPT_HEADER => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_FOLLOWLOCATION => false, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_LOW_SPEED_TIME => 10, CURLOPT_TIMEOUT => 10, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $post )); */ curl_setopt($sock, CURLOPT_TIMEOUT, 30); curl_setopt($sock, CURLOPT_PORT, 80); curl_setopt($sock, CURLOPT_HEADER, true); curl_setopt($sock, CURLOPT_USERAGENT, 'Allopass-ApiKit-PHP5'); curl_setopt($sock, CURLOPT_RETURNTRANSFER, true); curl_setopt($sock, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($sock, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($sock, CURLOPT_POST, true); curl_setopt($sock, CURLOPT_POSTFIELDS, $post); // if (count($headers) > 0) // curl_setopt($sock, CURLOPT_HTTPHEADER, $headers); curl_setopt($sock, CURLOPT_URL, $url); $response = curl_exec($sock); if (0 < ($curlErrno = curl_errno($sock))) { //trigger_error("CURL Error ($curlErrno): " . curl_error($sock), E_USER_NOTICE); throw new Am_Exception_Paysystem("CURL Error ($curlErrno): " . curl_error($sock)); } $this->httpStatusCode = curl_getinfo($sock, CURLINFO_HTTP_CODE); $httpHeaderSize = curl_getinfo($sock, CURLINFO_HEADER_SIZE); curl_close($sock); $rawHeaders = substr($response, 0, $httpHeaderSize - 4); $this->responseBody = substr($response, $httpHeaderSize); if (preg_match('/code="(\d+)" message="(.*)"/', $response, $matches)){ $this->code = $matches[1]; $this->message = $matches[2]; } foreach (explode("\r\n", $rawHeaders) as $header) { if (strpos($header, ":") > 0) { list($name, $value) = explode(':', $header); $name = trim($name); if ($name) $this->responseHeaders[$name] = trim($value); } } } public function isResponseValidated() { if (isset($this->responseHeaders['X-Allopass-Response-Signature'])) { $returnedResponseSignature = $this->responseHeaders['X-Allopass-Response-Signature']; $computedResponseSignature = hash($this->hashFunction, $this->responseBody . $this->api_secret_key); $responseValidated = (trim($returnedResponseSignature) == trim($computedResponseSignature)); } else { $responseValidated = false; } return $responseValidated; } public function getResponse() { //if ($this->responseFormat == 'json') if (strpos($this->responseBody, '"response": {') > 0) $response = json_decode($this->responseBody); //if ($this->responseFormat == 'xml') > 0) { if (strpos($this->responseBody, 'response xmlns') > 0) $response = simplexml_load_string($this->responseBody); if (!$response) $response = $this->responseBody; return $response; } } /* 123456 {"response": { "@attributes": { "code": "0", "message": "OK" }, "id": "123456", "name": "PRODUCT NAME", "purchase_url": "http:\/\/localhost\/purchase", "forward_url": " http:\/\/localhost\/product" } */ /* Response: creation_date Date of server reply (GMT) 2009-08-30T12:04:21+00:00 button_id Temporary button ID issued by Allopass 12345678-1234-1234-1234-123456789012 reference_currency Base currency (euro is default) USD website Customer website information – site name, forwarding URL, Allopass ID, category, audience restrictions 123456 buy_url Secure button link provided by allopass payment.allopass.com URL with associated btnid checkout_button Code to create a modal window for merchant use payment allopass.com URL with associated btnid and carousel avascript code carousel presentation */ PK\V##Jdefault/plugins/payment/allopass/apikit/exception/AllopassApiException.phpnu[ * * @date 2009 (c) Hi-media */ abstract class AllopassApiException extends Exception { /** * Constructor * * @param message (string) Exception description * @param code (integer) Exception code */ public function __construct($message, $code) { parent::__construct($message, $code); } }PK\- +-  `default/plugins/payment/allopass/apikit/exception/AllopassApiConfFileMissingSectionException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiConfFileMissingSectionException extends AllopassApiException { /** * Exception code */ const CODE = 12; /** * Exception definition */ const MESSAGE = 'A required section cannot be found in the configuration file'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\X>\default/plugins/payment/allopass/apikit/exception/AllopassApiMissingHashFeatureException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiMissingHashFeatureException extends AllopassApiException { /** * Exception code */ const CODE = 8; /** * Exception definition */ const MESSAGE = 'Your local PHP system doesn\'t support the configurated hash cipher (SHA1)'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\tyf^default/plugins/payment/allopass/apikit/exception/AllopassApiUnavailableRessourceException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiUnavailableRessourceException extends AllopassApiException { /** * Exception code */ const CODE = 1; /** * Exception definition */ const MESSAGE = 'The API you are requesting is currently unavailable'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\ie[default/plugins/payment/allopass/apikit/exception/AllopassApiConfFileCorruptedException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiConfFileCorruptedException extends AllopassApiException { /** * Exception code */ const CODE = 6; /** * Exception definition */ const MESSAGE = 'Configuration file is corrupted or bad formatted'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\? ]default/plugins/payment/allopass/apikit/exception/AllopassApiWrongFormatResponseException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiWrongFormatResponseException extends AllopassApiException { /** * Exception code */ const CODE = 3; /** * Exception definition */ const MESSAGE = 'The response contains invalid data'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\=x_default/plugins/payment/allopass/apikit/exception/AllopassApiMissingNetworkFeatureException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiMissingNetworkFeatureException extends AllopassApiException { /** * Exception code */ const CODE = 9; /** * Exception definition */ const MESSAGE = 'Your local PHP system supports neither cURL nor fsockopen'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\Ydefault/plugins/payment/allopass/apikit/exception/AllopassApiConfFileMissingException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiConfFileMissingException extends AllopassApiException { /** * Exception code */ const CODE = 5; /** * Exception definition */ const MESSAGE = 'Configuration file is missing'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\[default/plugins/payment/allopass/apikit/exception/AllopassApiMissingXMLFeatureException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiMissingXMLFeatureException extends AllopassApiException { /** * Exception code */ const CODE = 7; /** * Exception definition */ const MESSAGE = 'Your local PHP system doesn\'t support needed SimpleXML library'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\kUdefault/plugins/payment/allopass/apikit/exception/AllopassApiRemoteErrorException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiRemoteErrorException extends AllopassApiException { /** * Exception code */ const CODE = 4; /** * Exception definition */ const MESSAGE = 'The response indicates that an error occured when processing the request'; /** * Remote exception code */ protected $_remoteCode; /** * Remote exception definition */ protected $_remoteMessage; /** * Constructor */ public function __construct($code, $message) { parent::__construct(self::MESSAGE, self::CODE); $this->_remoteCode = $code; $this->_remoteMessage = $message; } /** * Method retrieving the remote exception code * * @return (integer) The remote exception code */ public function getRemoteCode() { return $this->_remoteCode; } /** * Method retrieving the remote exception message * * @return (string) The remote exception message */ public function getRemoteMessage() { return $this->_remoteMessage; } /** * Overload of parent __toString magic method * * @return (string) Exception string representation containing local and remote exceptions definitions */ public function __toString() { return "Remote exception with code '{$this->_remoteCode}' and message '{$this->_remoteMessage}'\n\n" . parent::__toString(); } }PK\vcdefault/plugins/payment/allopass/apikit/exception/AllopassApiMissingCompressionFeatureException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiMissingCompressionFeatureException extends AllopassApiException { /** * Exception code */ const CODE = 10; /** * Exception definition */ const MESSAGE = 'Your local PHP system doesn\'t support required compression library'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\* )`default/plugins/payment/allopass/apikit/exception/AllopassApiFalseResponseSignatureException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiFalseResponseSignatureException extends AllopassApiException { /** * Exception code */ const CODE = 2; /** * Exception definition */ const MESSAGE = 'The signature of the response is false, possible hack attempt'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\]default/plugins/payment/allopass/apikit/exception/AllopassApiConfAccountNotFoundException.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiConfAccountNotFoundException extends AllopassApiException { /** * Exception code */ const CODE = 11; /** * Exception definition */ const MESSAGE = 'You provided an account (its email) which doesn\'t exist in configuration file'; /** * Constructor */ public function __construct() { parent::__construct(self::MESSAGE, self::CODE); } }PK\;Ģ5default/plugins/payment/allopass/apikit/conf/conf.xmlnu[ sha1 xml 30 http 80 api.allopass.com PK\ѱE E Bdefault/plugins/payment/allopass/apikit/tools/AllopassApiTools.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiTools { /** * Checks if a string begins with another one * * @param haystack (string) The containing string * @param needle (string) The expected contained string * * @return (boolean) If the containing string begins with the contained string */ public static function beginsWith($haystack, $needle) { $haystack = strtolower($haystack); $needle = strtolower($needle); return (substr($haystack, 0, strlen($needle)) == $needle); } /** * Checks if a string ends with another one * * @param haystack (string) The containing string * @param needle (string) The expected contained string * * @return (boolean) If the containing string ends with the contained string */ public static function endsWith($haystack, $needle) { $haystack = strtolower($haystack); $needle = strtolower($needle); return (substr($haystack, -strlen($needle)) == $needle); } /** * Checks if SimpleXML library is available * * @throws AllopassApiMissingXMLFeatureException If SimpleXML API isn't loaded/supported */ private static function _checkXmlParser() { if (!function_exists('simplexml_load_string') || !class_exists('SimpleXMLElement')) { throw new AllopassApiMissingXMLFeatureException(); } } /** * Load an XML string into a mapping object * * @param string (string) The XML string to be parsed * * @return (SimpleXMLElement) The mapping object */ public static function xmlParseString($string) { self::_checkXmlParser(); return @simplexml_load_string($string); } /** * Load an XML file into a mapping object * * @param path (string) The XML file path * * @return (SimpleXMLElement) The mapping object */ public static function xmlParseFile($path) { self::_checkXmlParser(); return @simplexml_load_file($path); } }PK\{Adefault/plugins/payment/allopass/apikit/model/AllopassKeyword.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassKeyword { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the keyword name * * @return (string) The keyword name */ public function getName() { return (string) $this->_xml->attributes()->name; } /** * Method retrieving the keyword shortcode * * @return (string) The keyword shortcode */ public function getShortcode() { return (string) $this->_xml->attributes()->shortcode; } /** * Method retrieving the keyword operators * * @return (string) The keyword operators */ public function getOperators() { return (string) $this->_xml->attributes()->operators; } /** * Method retrieving the keyword number billed messages * * @return (integer) The keyword number billed messages */ public function getNumberBilledMessages() { return (integer) $this->_xml->attributes()->number_billed_messages; } /** * Method retrieving the phone number description * * @return (string) The phone number description */ public function getDescription() { return (string) $this->_xml->description; } }PK\eDdefault/plugins/payment/allopass/apikit/model/AllopassPricepoint.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassPricepoint { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the pricepoint id * * @return (integer) The pricepoint id */ public function getId() { return (integer) $this->_xml->attributes()->id; } /** * Method retrieving the pricepoint type * * @return (string) The pricepoint type */ public function getType() { return (string) $this->_xml->attributes()->type; } /** * Method retrieving the pricepoint category * * @return (string) The pricepoint category */ public function getCategory() { return (string) $this->_xml->attributes()->category; } /** * Method retrieving the pricepoint country code * * @return (string) The pricepoint country code */ public function getCountryCode() { return (string) $this->_xml->attributes()->country_code; } /** * Method retrieving the pricepoint's price * * @return (AllopassPrice) The pricepoint's price */ public function getPrice() { $object = $this->_xml->price; return (empty($object)) ? null : new AllopassPrice($object); } /** * Method retrieving the pricepoint's payout * * @return (AllopassPrice) The pricepoint's payout */ public function getPayout() { $object = $this->_xml->payout; return (empty($object)) ? null : new AllopassPayout($object); } /** * Method retrieving the pricepoint buy url * * @return (string) The pricepoint buy url */ public function getBuyUrl() { return (string) $this->_xml->buy_url; } /** * Method retrieving the pricepoint's phone numbers * * @return (AllopassPhoneNumber[]) The pricepoint's phone numbers */ public function getPhoneNumbers() { $phoneNumbers = array(); $object = $this->_xml->phone_numbers; if (empty($object)) { return $phoneNumbers; } foreach ($object->children() as $child) { $phoneNumbers[] = new AllopassPhoneNumber($child); } return $phoneNumbers; } /** * Method retrieving the pricepoint's keywords * * @return (AllopassKeyword[]) The pricepoint's keywords */ public function getKeywords() { $keywords = array(); $object = $this->_xml->keywords; if (empty($object)) { return $keywords; } foreach ($object->children() as $child) { $keywords[] = new AllopassKeyword($child); } return $keywords; } /** * Method retrieving the pricepoint description * * @return (string) The pricepoint description */ public function getDescription() { return (string) $this->_xml->description; } }PK\)SJdefault/plugins/payment/allopass/apikit/model/AllopassApiPlainResponse.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiPlainResponse extends AllopassApiResponse { /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } }PK\LfQQAdefault/plugins/payment/allopass/apikit/model/AllopassApiConf.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassApiConf { /** * Relative path of the configuration file */ const FILE_PATH = '../conf/conf.xml'; /** * (ApiConf) Static instance of the class */ private static $_instance = null; /** * (SimpleXMLElement) SimpleXML object representation of the configuration file */ private $_xml; /** * Constructor */ private function __construct() { // commented by aMember //$this->_loadFile(); //$this->_checkFile(); } /** * Internal method processing configuration file loading * * @throws AllopassApiConfFileMissingException If local API configuration file doesn't exist * * @throws AllopassApiConfFileCorruptedException If local API configuration file doensn't contain valid XML */ private function _loadFile() { $path = dirname(__FILE__) . '/' . self::FILE_PATH; if (!file_exists($path)) { throw new AllopassApiConfFileMissingException(); } $this->_xml = AllopassApiTools::xmlParseFile($path); if (!is_object($this->_xml)) { throw new AllopassApiConfFileCorruptedException(); } } /** * Internal method processing configuration file checking * * @throws AllopassApiConfFileMissingSectionException If local API configuration file doesn't contain every required sections */ private function _checkFile() { static $sections = array('accounts', 'default_hash', 'default_format', 'network_timeout', 'network_protocol', 'network_port', 'host'); $fileSections = array(); foreach ($this->_xml as $section) { $fileSections[] = $section->getName(); } foreach ($sections as &$section) { if (!in_array($section, $fileSections)) { throw new AllopassApiConfFileMissingSectionException(); } } } /** * Method retrieving the API key * * @param email (string) The mail account from which retrieve the API key * If email isn't provided or null, the first account is considered * * @return (string) The public API key */ public function getApiKey($email = null) { return (string) $this->_retrieveAccount($email)->keys->api_key; } /** * Method retrieving the private key * * @param email (string) The mail account from which retrieve the private key * If email isn't provided or null, the first account is considered * * @return (string) The private API key */ public function getPrivateKey($email = null) { return (string) $this->_retrieveAccount($email)->keys->private_key; } /** * Internal method retrieving an account from its email * * @param email (string) The mail account from which retrieve the account * If email is null, the first account is considered * * @return (SimpleXMLElement) The SimpleXML representation of the account * * @throws AllopassApiConfAccountNotFoundException If an email is provided but can't be found */ private function _retrieveAccount($email) { // aMember code // use $email variable to pass XML $this->_xml = AllopassApiTools::xmlParseString($email); if (!is_object($this->_xml)) { throw new AllopassApiConfFileCorruptedException(); } $this->_checkFile(); $email = null; // clear variable to make following code work correct ///// $accounts = $this->_xml->accounts->children(); if ($email === null) { return $accounts[0]; } else { foreach ($accounts as $account) { if ($account->attributes()->email == $email) { return $account; } } throw new AllopassApiConfAccountNotFoundException(); } } /** * Method retrieving the default response format * * @return (string) The response format */ public function getDefaultFormat() { return (string) $this->_xml->default_format; } /** * Method retrieving the API hostname * * @return (string) The API hostname */ public function getHost() { return (string) $this->_xml->host; } /** * Method retrieving the default hash function name * * @return (string) The default hash function name */ public function getDefaultHash() { return (string) $this->_xml->default_hash; } /** * Method retrieving the network timeout delay * * @return (integer) The network timeout delay */ public function getNetworkTimeout() { return (integer) $this->_xml->network_timeout; } /** * Method retrieving the network protocol * * @return (string) The network protocol */ public function getNetworkProtocol() { return (string) $this->_xml->network_protocol; } /** * Method retrieving the network port * * @return (integer) The network port */ public function getNetworkPort() { return (integer) $this->_xml->network_port; } /** * Static method providing a single access-point to the class * * @return (AllopassApiConf) The class instance */ public static function getInstance() { if (self::$_instance === null) { self::$_instance = new self(); } return self::$_instance; } }PK\K(ͼAdefault/plugins/payment/allopass/apikit/model/AllopassWebsite.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassWebsite { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the website id * * @return (integer) The website id */ public function getId() { return (integer) $this->_xml->attributes()->id; } /** * Method retrieving the website name * * @return (string) The website name */ public function getName() { return (string) $this->_xml->attributes()->name; } /** * Method retrieving the website url * * @return (string) The website url */ public function getUrl() { return (string) $this->_xml->attributes()->url; } /** * Method retrieving if the website's audience is restricted * * @return (boolean) If the website's audience is restricted */ public function isAudienceRestricted() { return ($this->_xml->attributes()->audience_restricted == 'true'); } /** * Method retrieving the website category * * @return (string) The website category */ public function getCategory() { return (string) $this->_xml->attributes()->category; } }PK\B(@default/plugins/payment/allopass/apikit/model/AllopassMarket.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassMarket { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the market country code * * @return (string) The market country code */ public function getCountryCode() { return (string) $this->_xml->attributes()->country_code; } /** * Method retrieving the market country * * @return (string) The market country */ public function getCountry() { return (string) $this->_xml->attributes()->country; } /** * Method retrieving the market pricepoints * * @return (AllopassPricepoint[]) The market pricepoints */ public function getPricepoints() { $pricepoints = array(); foreach ($this->_xml->children() as $child) { $pricepoints[] = new AllopassPricepoint($child); } return $pricepoints; } }PK\;u8?default/plugins/payment/allopass/apikit/model/AllopassPrice.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassPrice { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the price currency * * @return (string) The price currency */ public function getCurrency() { return (string) $this->_xml->attributes()->currency; } /** * Method retrieving the price amount * * @return (float) The price amount */ public function getAmount() { return (float) $this->_xml->attributes()->amount; } /** * Method retrieving the price exchange rate * * @return (double) The price exchange rate */ public function getExchange() { return (double) $this->_xml->attributes()->exchange; } /** * Method retrieving the price reference currency * * @return (string) The price reference currency */ public function getReferenceCurrency() { return (string) $this->_xml->attributes()->reference_currency; } /** * Method retrieving the price reference amount * * @return (float) The price reference amount */ public function getReferenceAmount() { return (float) $this->_xml->attributes()->reference_amount; } }PK\_mTdefault/plugins/payment/allopass/apikit/model/AllopassSubscriptionDetailResponse.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassSubscriptionDetailResponse extends AllopassApiMappingResponse { /** * The subscription is active */ const SUBSCRIPTION_ACTIVE = 0; /** * The subscription is not active */ const SUBSCRIPTION_NOT_ACTIVE = 1; /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the subscription status * * @return (integer) The subscription status */ public function getStatus() { return (integer) $this->_xml->status; } /** * Method retrieving the subscription status description * * @return (string) The subscription status description */ public function getStatusDescription() { return (string) $this->_xml->status_description; } /** * Method retrieving the subscription access-type * * @return (string) The subscription access-type */ public function getAccessType() { return (string) $this->_xml->access_type; } /** * Method retrieving the subscriber reference * * @return (string) The subscriber reference */ public function getSubscriberReference() { return (string) $this->_xml->subscriber_reference; } /** * Method retrieving the merchant subscriber reference * * @return (string) merchant The subscriber reference */ public function getMerchantSubscriberReference() { return (string) $this->_xml->merchant_subscriber_reference; } /** * Method retrieving the merchant transaction id * * @return (string) The merchant transaction id */ public function getMerchantTransactionId() { return (string) $this->_xml->merchant_transaction_id; } /** * Method retrieving the transaction's website * * @return (AllopassWebsite) The transaction's website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the subscription's product * * @return (AllopassProduct) The subscription's product */ public function getProduct() { return new AllopassProduct($this->_xml->product); } /** * Method retrieving the subscription's offer * * @return (AllopassOffer) The subscription's offer */ public function getOffer() { return new AllopassOffer($this->_xml->offer); } /** * Method retrieving the subscription customer country * * @return (string) The subscription customer country */ public function getCustomerCountry() { return (string) $this->_xml->customer_country; } /** * Method retrieving the subscription customer locale * * @return (string) The subscription customer locale */ public function getCustomerLocale() { return (string) $this->_xml->customer_locale; } /** * Method retrieving the subscription creation date * * @return (AllopassDate) The subscription creation date */ public function getSubscriptionDate() { return new AllopassDate($this->_xml->subscription_date); } /** * Method retrieving the subscription renewal date * * @return (AllopassDate) The subscription renewal date */ public function getRenewalDate() { return new AllopassDate($this->_xml->renewal_date); } /** * Method retrieving the subscription cancellation date * * @return (AllopassDate) The subscription cancellation date */ public function getCancellationDate() { return new AllopassDate($this->_xml->cancellation_date); } /** * Method retrieving the subscription periodicity * * @return (AllopassPeriodicity) The subscription periodicity */ public function getPeriodicity() { return new AllopassPeriodicity($this->_xml->frequency); } /** * Method retrieving the subscription pricepoint * * @return (AllopassPricepoint) The subscription pricepoint */ public function getPricepoint() { return new AllopassPricepoint($this->_xml->pricepoint); } /** * Method retrieving the subscription's price * * @return (AllopassPrice) The subscription's price */ public function getPrice() { return new AllopassPrice($this->_xml->price); } /** * Method retrieving the subscription's payout price * * @return (AllopassPrice) The subscription's payout price */ public function getPayout() { return new AllopassPrice($this->_xml->payout); } } PK\P4Sdefault/plugins/payment/allopass/apikit/model/AllopassTransactionDetailResponse.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassTransactionDetailResponse extends AllopassApiMappingResponse { /** * The transaction is at first step : initialization */ const TRANSACTION_INIT = -1; /** * The transaction is successful */ const TRANSACTION_SUCCESS = 0; /** * The transaction failed due to insufficient funds */ const TRANSACTION_INSUFFICIENT_FUNDS = 1; /** * The transaction timeouted */ const TRANSACTION_TIMEOUT = 2; /** * The transaction has been cancelled by user */ const TRANSACTION_CANCELLED = 3; /** * The transaction has been blocked due to fraud suspicions */ const TRANSACTION_ANTI_FRAUD = 4; /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the transaction status * * @return (integer) The transaction status */ public function getStatus() { return (integer) $this->_xml->status; } /** * Method retrieving the transaction status description * * @return (string) The transaction status description */ public function getStatusDescription() { return (string) $this->_xml->status_description; } /** * Method retrieving the transaction access-type * * @return (string) The transaction access-type */ public function getAccessType() { return (string) $this->_xml->access_type; } /** * Method retrieving the transaction id * * @return (string) The transaction id */ public function getTransactionId() { return (string) $this->_xml->transaction_id; } /** * Method retrieving the transaction's price * * @return (AllopassPrice) The transaction's price */ public function getPrice() { return new AllopassPrice($this->_xml->price); } /** * Method retrieving the transaction's paid price * * @return (AllopassPrice) The transaction's paid price */ public function getPaid() { return new AllopassPrice($this->_xml->paid); } /** * Method retrieving the transaction creation date * * @return (AllopassDate) The transaction creation date */ public function getCreationDate() { return new AllopassDate($this->_xml->creation_date); } /** * Method retrieving the transaction end date * * @return (AllopassDate) The transaction end date */ public function getEndDate() { return new AllopassDate($this->_xml->end_date); } /** * Method retrieving the transaction product name * * @return (string) The transaction product name */ public function getProductName() { return (string) $this->_xml->product_name; } /** * Method retrieving the transaction's website * * @return (AllopassWebsite) The transaction's website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the transaction customer ip * * @return (string) The transaction customer ip */ public function getCustomerIp() { return (string) $this->_xml->customer_ip; } /** * Method retrieving the transaction customer country * * @return (string) The transaction customer country */ public function getCustomerCountry() { return (string) $this->_xml->customer_country; } /** * Method retrieving the transaction expected number of codes * * @return (integer) The transaction expected number of codes */ public function getExpectedNumberOfCodes() { return (integer) $this->_xml->expected_number_of_codes; } /** * Method retrieving if the transaction is in direct access * * @return (boolean) If the transaction is in direct access */ public function isDirectAccess() { return ($this->_xml->direct_access == 'true'); } /** * Method retrieving the transaction codes * * @return (string[]) The transaction codes */ public function getCodes() { $codes = array(); foreach ($this->_xml->codes->children() as $child) { $codes[] = (string) $child; } return $codes; } /** * Method retrieving the transaction merchant transaction id * * @return (string) The transaction merchant transaction id */ public function getMerchantTransactionId() { return (string) $this->_xml->merchant_transaction_id; } /** * Method retrieving the transaction client data * * @return (string) The transaction client data */ public function getData() { return (string) $this->_xml->data; } /** * Method retrieving the transaction affiliate code * * @return (string) The transaction affiliate code */ public function getAffiliate() { return (string) $this->_xml->affiliate; } /** * Method retrieving the transaction partners * * @return (AllopassPartner[]) The transaction partners */ public function getPartners() { $partners = array(); foreach ($this->_xml->partners->children() as $child) { $partners[] = new AllopassPartner($child); } return $partners; } }PK\q\Udefault/plugins/payment/allopass/apikit/model/AllopassOnetimeValidateCodesRequest.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassOnetimeValidateCodesRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'onetime/validate-codes'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Overload of internal method which determinates that request has to be done using POST * * @return (boolean) The request has to be done using POST */ protected function _isHttpPost() { return true; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassOnetimeValidateCodesResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassOnetimeValidateCodesResponse($signature, $headers, $body); } }PK\۫\Ndefault/plugins/payment/allopass/apikit/model/AllopassOnetimeButtonRequest.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassOnetimeButtonRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'onetime/button'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Overload of internal method which determinates that request has to be done using POST * * @return (boolean) The request has to be done using POST */ protected function _isHttpPost() { return true; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassOnetimeButtonResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassOnetimeButtonResponse($signature, $headers, $body); } }PK\9Tdefault/plugins/payment/allopass/apikit/model/AllopassTransactionMerchantRequest.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassTransactionMerchantRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'transaction/merchant'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassTransactionDetailResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassTransactionDetailResponse($signature, $headers, $body); } }PK\eRdefault/plugins/payment/allopass/apikit/model/AllopassTransactionDetailRequest.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassTransactionDetailRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'transaction'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassTransactionDetailResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassTransactionDetailResponse($signature, $headers, $body); } }PK\.~I@default/plugins/payment/allopass/apikit/model/AllopassPayout.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassPayout { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the payout currency * * @return (string) The payout currency */ public function getCurrency() { return (string) $this->_xml->attributes()->currency; } /** * Method retrieving the payout amount * * @return (float) The payout amount */ public function getAmount() { return (float) $this->_xml->attributes()->amount; } /** * Method retrieving the payout exchange rate * * @return (double) The payout exchange rate */ public function getExchange() { return (double) $this->_xml->attributes()->exchange; } /** * Method retrieving the payout reference currency * * @return (string) The payout reference currency */ public function getReferenceCurrency() { return (string) $this->_xml->attributes()->reference_currency; } /** * Method retrieving the payout reference amount * * @return (float) The payout reference amount */ public function getReferenceAmount() { return (float) $this->_xml->attributes()->reference_amount; } }PK\Ndefault/plugins/payment/allopass/apikit/model/AllopassProductDetailRequest.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassProductDetailRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'product'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassProductDetailResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassProductDetailResponse($signature, $headers, $body); } }PK\.Adefault/plugins/payment/allopass/apikit/model/AllopassProduct.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassProduct { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the product id * * @return (integer) The product id */ public function getId() { return (integer) $this->_xml->attributes()->id; } /** * Method retrieving the product name * * @return (string) The product name */ public function getName() { return (string) $this->_xml->attributes()->name; } }PK\1Sdefault/plugins/payment/allopass/apikit/model/AllopassSubscriptionDetailRequest.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassSubscriptionDetailRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'subscription'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassSubscriptionDetailResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassSubscriptionDetailResponse($signature, $headers, $body); } }PK\uVdefault/plugins/payment/allopass/apikit/model/AllopassOnetimeDiscreteButtonRequest.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassOnetimeDiscreteButtonRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'onetime/discrete-button'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Overload of internal method which determinates that request has to be done using POST * * @return (boolean) The request has to be done using POST */ protected function _isHttpPost() { return true; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassOnetimeButtonResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassOnetimeButtonResponse($signature, $headers, $body); } }PK\mD?default/plugins/payment/allopass/apikit/model/AllopassOffer.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassOffer { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the offer id * * @return (integer) The offer id */ public function getId() { return (integer) $this->_xml->attributes()->id; } /** * Method retrieving the offer name * * @return (string) The offer name */ public function getName() { return (string) $this->_xml->attributes()->name; } }PK\ʣRdefault/plugins/payment/allopass/apikit/model/AllopassSubscriptionLoginRequest.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassSubscriptionLoginRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'subscription/login'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassSubscriptionLoginResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassSubscriptionLoginResponse($signature, $headers, $body); } }PK\U+Edefault/plugins/payment/allopass/apikit/model/AllopassPeriodicity.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassPeriodicity { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the periodicity value * * @return (integer) The periodicity value */ public function getValue() { return (integer) $this->_xml->attributes()->value; } /** * Method retrieving the periodicity unit * * @return (string) The periodicity unit */ public function getUnit() { return (string) $this->_xml->attributes()->unit; } }PK\I$kkSdefault/plugins/payment/allopass/apikit/model/AllopassSubscriptionLoginResponse.phpnu[ * * @date 2011 (c) Hi-media */ class AllopassSubscriptionLoginResponse extends AllopassApiMappingResponse { /** * The login is successful */ const LOGIN_SUCCESS = 0; /** * The login failed */ const LOGIN_FAILED = 1; /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the validation status * * @return (integer) The validation status */ public function getStatus() { return (integer) $this->_xml->status; } /** * Method retrieving the validation status description * * @return (string) The validation status description */ public function getStatusDescription() { return (string) $this->_xml->status_description; } }PK\z#Adefault/plugins/payment/allopass/apikit/model/AllopassCountry.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassCountry { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the country code * * @return (string) The country code */ public function getCode() { return (string) $this->_xml->attributes()->code; } /** * Method retrieving the country name * * @return (string) The country name */ public function getName() { return (string) $this->_xml->attributes()->name; } }PK\KssLdefault/plugins/payment/allopass/apikit/model/AllopassApiMappingResponse.phpnu[ * * @date 2009 (c) Hi-media */ abstract class AllopassApiMappingResponse extends AllopassApiResponse { /** * (SimpleXMLElement) The SimpleXML object representation of the response */ protected $_xml; /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); $this->_xml = AllopassApiTools::xmlParseString($this->_body); $this->_verify(); } /** * Overload of parent internal method providing signature verification * * @throws AllopassApiWrongFormatResponseException If response doesn't contain valid XML * * @throws AllopassApiRemoteErrorException if response describe a remote API exception */ protected function _verify() { if (!is_object($this->_xml)) { throw new AllopassApiWrongFormatResponseException(); } $attributes = $this->_xml->attributes(); if ((int) $attributes->code != 0) { throw new AllopassApiRemoteErrorException($attributes->code, $attributes->message); } parent::_verify(); } }PK\Adefault/plugins/payment/allopass/apikit/model/AllopassPartner.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassPartner { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the partner id * * @return (integer) The partner id */ public function getId() { return (integer) $this->_xml->attributes()->id; } /** * Method retrieving the partner share amount * * @return (float) The partner share amount */ public function getShare() { return (float) $this->_xml->attributes()->share; } /** * Method retrieving the partner map id * * @return (integer) The partner map id */ public function getMap() { return (integer) $this->_xml->attributes()->map; } }PK\3737Ddefault/plugins/payment/allopass/apikit/model/AllopassApiRequest.phpnu[ * * @date 2009 (c) Hi-media */ abstract class AllopassApiRequest { /** * The response format needed to provide response object mapping */ const MAPPING_FORMAT = 'xml'; /** * The API remote path */ const API_PATH = '/rest/'; /** * The HTTP connector */ const HTTP_CONNECTOR = '://'; /** * The HTTP query string connector */ const HTTP_QUERY_CONNECTOR = '?'; /** * The HTTP carriage return line feed */ const HTTP_CRLF = "\r\n"; /** * The HTTP version */ const HTTP_VERSION = '1.1'; /** * The HTTP chunk size */ const HTTP_CHUNK_SIZE = 4096; /** * The HTTP size of separator between headers and data */ const HTTP_HEADER_SEPARATOR_SIZE = 4; /** * The HTTP specific user agent header */ const HTTP_USER_AGENT = 'Allopass-ApiKit-PHP5'; /** * (array) Query string parameters of the API call */ protected $_parameters; /** * (boolean) If the request call has to return an object mapped response */ protected $_mapping; /** * (string) Email of the configurated account */ protected $_emailAccount; /** * Provide a way to get the route of each child request * * @return (string) The route of the request */ abstract protected function _getPath(); /** * Provide a way to get the wired response of each child request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassApiResponse) A new response regarding the type of the request */ abstract protected function _newResponse($signature, $headers, $body); /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { $this->_mapping = $mapping; parse_str(http_build_query($parameters, '', '&'), $this->_parameters); $this->_emailAccount = $emailAccount; } /** * Method to call the request and get its response * * @return (AllopassApiResponse) The request response */ public function call() { list($headers, $body) = $this->_buildParameters()->_sign()->_call(); $signature = $this->_hash($body . AllopassApiConf::getInstance()->getPrivateKey($this->_emailAccount)); return ($this->_mapping) ? $this->_newResponse($signature, $headers, $body) : new AllopassApiPlainResponse($signature, $headers, $body); } /** * Internal method to build special required API parameters * * @return (AllopassApiRequest) The class instance */ protected function _buildParameters() { static $formats = array('json', 'xml'); $this->_parameters['api_ts'] = time(); $this->_parameters['api_key'] = AllopassApiConf::getInstance()->getApiKey($this->_emailAccount); $this->_parameters['api_hash'] = AllopassApiConf::getInstance()->getDefaultHash(); if (isset($this->_parameters['format'])) { if ($this->_mapping) { $this->_parameters['format'] = self::MAPPING_FORMAT; } elseif (!in_array($this->_parameters['format'], $formats)) { $this->_parameters['format'] = AllopassApiConf::getInstance()->getDefaultFormat(); } } else { $this->_parameters['format'] = AllopassApiConf::getInstance()->getDefaultFormat(); } return $this; } /** * Internal method to sign the request call * * @return (AllopassApiRequest) The class instance */ protected function _sign() { $sign = ''; ksort($this->_parameters); foreach ($this->_parameters as $key => &$value) { $sign .= $key; $sign .= (is_array($value)) ? implode($value) : $value; } $this->_parameters['api_sig'] = $this->_hash($sign . AllopassApiConf::getInstance()->getPrivateKey($this->_emailAccount)); return $this; } /** * Internal method to hash data with the defined cipher * * @param data (string) Data to be hashed * * @return (string) The hashed data * * @throws AllopassApiMissingHashFeatureException If configured cipher (SHA1) API isn't loaded/supported */ protected function _hash($data) { $cipher = AllopassApiConf::getInstance()->getDefaultHash(); if (!function_exists($cipher)) { throw new AllopassApiMissingHashFeatureException(); } return call_user_func($cipher, $data); } /** * Internal method which determinates if the request has to be done using POST * * @return (boolean) If the request has to be done using POST */ protected function _isHttpPost() { return false; } /** * Internal method which tries to call remote API * * @return (string[]) A 0-indexed array which contains response headers and body * * @throws AllopassApiMissingNetworkFeatureException If there is neither cURL nor fsockopen enabled/available */ protected function _call() { if (function_exists('curl_init')) { return $this->_curlCall(); } elseif (function_exists('fsockopen')) { return $this->_rawCall(); } else { throw new AllopassApiMissingNetworkFeatureException(); } } /** * Internal method performing a raw request using socket * * @return (string[]) A 0-indexed array which contains response headers and body * * @throws AllopassApiUnavailableRessourceException If raw call to remote API fails */ protected function _rawCall() { $host = AllopassApiConf::getInstance()->getHost(); if (($socket = @fsockopen($host, AllopassApiConf::getInstance()->getNetworkPort(), $socket_errno, $socket_errstr, AllopassApiConf::getInstance()->getNetworkTimeout())) === false) { throw new AllopassApiUnavailableRessourceException(); } $path = AllopassApiConf::getInstance()->getHost() . self::API_PATH . $this->_getPath(); if ($this->_isHttpPost()) { $method = 'POST'; $data = http_build_query($this->_parameters, '', '&'); $length = strlen($data); } else { $method = 'GET'; $data = ''; $length = 0; $path .= self::HTTP_QUERY_CONNECTOR . http_build_query($this->_parameters, '', '&'); } $headers = array(); $headers[] = 'Host: ' . $host; $headers[] = 'Content-Type: application/x-www-form-urlencoded'; $headers[] = 'User-Agent: ' . self::HTTP_USER_AGENT; $headers[] = 'Content-Length: ' . $length; $headers[] = 'Connection: close'; $request = $method . ' ' . AllopassApiConf::getInstance()->getNetworkProtocol() . self::HTTP_CONNECTOR; $request .= $path . ' HTTP/' . self::HTTP_VERSION . self::HTTP_CRLF; $request .= implode(self::HTTP_CRLF, $headers) . self::HTTP_CRLF; $request .= self::HTTP_CRLF . $data; if (fwrite($socket, $request, strlen($request)) === false) { throw new AllopassApiUnavailableRessourceException(); } $content = ''; while (!feof($socket)) { if (($line = fread($socket, self::HTTP_CHUNK_SIZE)) === false) { throw new AllopassApiUnavailableRessourceException(); } $content .= $line; } fclose($socket); $pos = strpos($content, self::HTTP_CRLF . self::HTTP_CRLF); if ($pos === false) { throw new AllopassApiUnavailableRessourceException(); } $headers = substr($content, 0, $pos); $body = substr($content, $pos + self::HTTP_HEADER_SEPARATOR_SIZE); $aHeaders = explode(self::HTTP_CRLF, $headers); foreach ($aHeaders as &$header) { if (AllopassApiTools::beginsWith($header, 'Transfer-Encoding') && AllopassApiTools::endsWith($header, 'chunked')) { $body = $this->_decodeChunkedBody($body); continue; } if (AllopassApiTools::beginsWith($header, 'Content-Encoding')) { if (AllopassApiTools::endsWith($header, 'gzip')) { $body = $this->_ungzipBody($body); } elseif (AllopassApiTools::endsWith($header, 'deflate')) { $body = $this->_inflateBody($body); } } } return array($headers, $body); } /** * Decode a gzipped content-encoded body * * @param body (string) The gzipped HTTP body * * @return (string) The ungzipped response body * * @throws AllopassApiMissingCompressionFeatureException If gzip inflate function isn't loaded */ protected function _ungzipBody($body) { if (!function_exists('gzinflate')) { throw new AllopassApiMissingCompressionFeatureException(); } return gzinflate(substr($body, 10)); } /** * Decode a deflated content-encoded body * * @param body (string) The deflated HTTP body * * @return (string) The inflated response body * * @throws AllopassApiMissingCompressionFeatureException If gzip uncompress function isn't loaded */ protected function _inflateBody($body) { if (!function_exists('gzuncompress')) { throw new AllopassApiMissingCompressionFeatureException(); } return gzuncompress($body); } /** * Decode a "chunked" transfer-encoded body * * @param body (string) The chunked HTTP body * * @return (string) The response body "chunk decoded" * * @throws AllopassApiWrongFormatResponseException If response body is not chunked whereas headers say so */ protected function _decodeChunkedBody($body) { $decBody = ''; $tokens = array(); while (trim($body)) { if (!preg_match('/^([\da-fA-F]+)[^\r\n]*\r\n/sm', $body, $tokens)) { throw new AllopassApiWrongFormatResponseException(); } $length = hexdec(trim($tokens[1])); $cut = strlen($tokens[0]); $decBody .= substr($body, $cut, $length); $body = substr($body, $cut + $length + 2); } return $decBody; } /** * Internal method performing a cURL request * * @return (string[]) A 0-indexed array which contains response headers and body * * @throws AllopassApiUnavailableRessourceException If cURL call to remote API fails */ protected function _curlCall() { $url = AllopassApiConf::getInstance()->getNetworkProtocol() . self::HTTP_CONNECTOR; $url .= AllopassApiConf::getInstance()->getHost() . self::API_PATH . $this->_getPath(); $curl = curl_init(); curl_setopt($curl, CURLOPT_TIMEOUT, AllopassApiConf::getInstance()->getNetworkTimeout()); curl_setopt($curl, CURLOPT_PORT, AllopassApiConf::getInstance()->getNetworkPort()); curl_setopt($curl, CURLOPT_HEADER, true); curl_setopt($curl, CURLOPT_USERAGENT, self::HTTP_USER_AGENT); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); if ($this->_isHttpPost()) { curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($this->_parameters, '', '&')); } else { $url .= self::HTTP_QUERY_CONNECTOR . http_build_query($this->_parameters, '', '&'); } curl_setopt($curl, CURLOPT_URL, $url); $content = @curl_exec($curl); if (curl_errno($curl) > 0 || $content === false || $content == '') { throw new AllopassApiUnavailableRessourceException(); } $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); curl_close($curl); $headers = substr($content, 0, $headerSize - self::HTTP_HEADER_SEPARATOR_SIZE); $body = substr($content, $headerSize); return array($headers, $body); } }PK\ȴ/Wdefault/plugins/payment/allopass/apikit/model/AllopassOnetimeDiscretePricingRequest.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassOnetimeDiscretePricingRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'onetime/discrete-pricing'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassOnetimePricingResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassOnetimePricingResponse($signature, $headers, $body); } }PK\fGb b Tdefault/plugins/payment/allopass/apikit/model/AllopassTransactionPrepareResponse.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassTransactionPrepareResponse extends AllopassApiMappingResponse { /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the transaction access-type * * @return (string) The transaction access-type */ public function getAccessType() { return (string) $this->_xml->access_type; } /** * Method retrieving the transaction id * * @return (string) The transaction id */ public function getTransactionId() { return (string) $this->_xml->transaction_id; } /** * Method retrieving the transaction creation date * * @return (AllopassDate) The transaction creation date */ public function getCreationDate() { return new AllopassDate($this->_xml->creation_date); } /** * Method retrieving the transaction's price * * @return (AllopassPrice) The transaction's price */ public function getPrice() { return new AllopassPrice($this->_xml->price); } /** * Method retrieving the transaction's pricepoint * * @return (AllopassPricepoint) The transaction's pricepoint */ public function getPricepoint() { return new AllopassPricepoint($this->_xml->pricepoint); } /** * Method retrieving the transaction's website * * @return (AllopassWebsite) The transaction's website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the transaction buy url * * @return (string) The transaction buy url */ public function getBuyUrl() { return (string) $this->_xml->buy_url; } /** * Method retrieving the transaction checkout button HTML string * * @return (string) The transaction checkout button HTML string */ public function getCheckoutButton() { return (string) $this->_xml->checkout_button; } }PK\l)>default/plugins/payment/allopass/apikit/model/AllopassCode.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassCode { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the code value (the code string) * * @return (string) The code value */ public function getValue() { return (string) $this->_xml->value; } /** * Method retrieving the code pricepoint * * @return (AllopassPricepoint) The code pricepoint */ public function getPricepoint() { return new AllopassPricepoint($this->_xml->pricepoint); } /** * Method retrieving the code price * * @return (AllopassPrice) The code price */ public function getPrice() { return new AllopassPrice($this->_xml->price); } /** * Method retrieving the code paid price * * @return (AllopassPrice) The code paid price */ public function getPaid() { return new AllopassPrice($this->_xml->paid); } /** * Method retrieving the code payout * * @return (AllopassPrice) The code payout */ public function getPayout() { return new AllopassPrice($this->_xml->payout); } }PK\, , Pdefault/plugins/payment/allopass/apikit/model/AllopassOnetimePricingResponse.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassOnetimePricingResponse extends AllopassApiMappingResponse { public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the creation date * * @return (AllopassDate) The creation date */ public function getCreationDate() { return new AllopassDate($this->_xml->creation_date); } /** * Method retrieving the customer ip * * @return (string) The customer ip */ public function getCustomerIp() { return (string) $this->_xml->customer_ip; } /** * Method retrieving the customer country * * @return (string) The customer country */ public function getCustomerCountry() { return (string) $this->_xml->customer_country; } /** * Method retrieving the website * * @return (AllopassWebsite) The website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the countries * * @return (AllopassCountry[]) The countries */ public function getCountries() { $countries = array(); foreach ($this->_xml->countries->children() as $child) { foreach ($child->children() as $cChild) { $countries[] = new AllopassCountry($cChild); } } return $countries; } /** * Method retrieving the regions * * @return (AllopassRegion[]) The regions */ public function getRegions() { $regions = array(); foreach ($this->_xml->countries->children() as $child) { $regions[] = new AllopassRegion($child); } return $regions; } /** * Method retrieving the markets * * @return (AllopassMarket[]) The markets */ public function getMarkets() { $markets = array(); foreach ($this->_xml->markets->children() as $child) { $markets[] = new AllopassMarket($child); } return $markets; } }PK\C@default/plugins/payment/allopass/apikit/model/AllopassRegion.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassRegion { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the region name * * @return (string) The region name */ public function getName() { return (string) $this->_xml->attributes()->name; } /** * Method retrieving the region's countries * * @return (AllopassCountry[]) The region's countries */ public function getCountries() { $countries = array(); foreach ($this->_xml->children() as $child) { $countries[] = new AllopassCountry($child); } return $countries; } }PK\pӂfEdefault/plugins/payment/allopass/apikit/model/AllopassApiResponse.phpnu[ * * @date 2009 (c) Hi-media */ abstract class AllopassApiResponse { /** * (string) Expected response signature */ protected $_signature; /** * (string) HTTP headers of the response */ protected $_headers; /** * (string) Raw data of the response */ protected $_body; /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { $this->_signature = $signature; $this->_headers = $headers; $this->_body = $body; } /** * Internal method providing signature verification * * @throws AllopassApiFalseResponseSignatureException If the expected signature is not found among response headers */ protected function _verify() { if (!strpos($this->_headers, "X-Allopass-Response-Signature: {$this->_signature}")) { throw new AllopassApiFalseResponseSignatureException(); } } /** * Overload of parent __toString magic method * * @return (string) String representation of an API response (its body) */ public function __toString() { return $this->_body; } }PK\5Vdefault/plugins/payment/allopass/apikit/model/AllopassOnetimeValidateCodesResponse.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassOnetimeValidateCodesResponse extends AllopassApiMappingResponse { /** * The validation is successful */ const VALIDATECODES_SUCCESS = 0; /** * The validation failed */ const VALIDATECODES_FAILED = 1; /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the validation status * * @return (integer) The validation status */ public function getStatus() { return (integer) $this->_xml->status; } /** * Method retrieving the validation status description * * @return (string) The validation status description */ public function getStatusDescription() { return (string) $this->_xml->status_description; } /** * Method retrieving the access-type * * @return (string) The access-type */ public function getAccessType() { return (string) $this->_xml->access_type; } /** * Method retrieving the transaction id * * @return (string) The transaction id */ public function getTransactionId() { return (string) $this->_xml->transaction_id; } /** * Method retrieving the validation's price * * @return (AllopassPrice) The validation's price */ public function getPrice() { return new AllopassPrice($this->_xml->price); } /** * Method retrieving the validation's paid price * * @return (AllopassPrice) The validation's paid price */ public function getPaid() { return new AllopassPrice($this->_xml->paid); } /** * Method retrieving the validation date * * @return (AllopassDate) The validation date */ public function getValidationDate() { return new AllopassDate($this->_xml->validation_date); } /** * Method retrieving the product name * * @return (string) The product name */ public function getProductName() { return (string) $this->_xml->product_name; } /** * Method retrieving the website * * @return (AllopassWebsite) The website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the customer ip * * @return (string) The customer ip */ public function getCustomerIp() { return (string) $this->_xml->customer_ip; } /** * Method retrieving the customer country * * @return (string) The customer country */ public function getCustomerCountry() { return (string) $this->_xml->customer_country; } /** * Method retrieving the expected number of codes * * @return (integer) The expected number of codes */ public function getExpectedNumberOfCodes() { return (integer) $this->_xml->expected_number_of_codes; } /** * Method retrieving the validation codes * * @return (AllopassCode[]) The validation codes */ public function getCodes() { $codes = array(); foreach ($this->_xml->codes->children() as $child) { $codes[] = new AllopassCode($child); } return $codes; } /** * Method retrieving the merchant transaction id * * @return (string) The merchant transaction id */ public function getMerchantTransactionId() { return (string) $this->_xml->merchant_transaction_id; } /** * Method retrieving the client data * * @return (string) The client data */ public function getData() { return (string) $this->_xml->data; } /** * Method retrieving the affiliate code * * @return (string) The affiliate code */ public function getAffiliate() { return (string) $this->_xml->affiliate; } /** * Method retrieving the partners * * @return (AllopassPartner[]) The partners */ public function getPartners() { $partners = array(); foreach ($this->_xml->partners->children() as $child) { $partners[] = new AllopassPartner($child); } return $partners; } }PK\iSa++Edefault/plugins/payment/allopass/apikit/model/AllopassPhoneNumber.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassPhoneNumber { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the phone number number * * @return (string) The phone number number */ public function getValue() { return (string) $this->_xml->attributes()->value; } /** * Method retrieving the phone number description * * @return (string) The phone number description */ public function getDescription() { return (string) $this->_xml->description; } }PK\||>default/plugins/payment/allopass/apikit/model/AllopassDate.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassDate { /** * (SimpleXMLElement) SimpleXML object representation of the item */ private $_xml; /** * Constructor * * @param xml (SimpleXMLElement) The SimpleXML object representation of the item */ public function __construct(SimpleXMLElement $xml) { $this->_xml = $xml; } /** * Method retrieving the date timestamp * * @return (integer) The partner timestamp */ public function getTimestamp() { return (integer) $this->_xml->attributes()->timestamp; } /** * Method retrieving the date ISO-8601 representation * * @return (string) The date ISO-8601 representation */ public function getDate() { return (string) $this->_xml->attributes()->date; } }PK\GLSdefault/plugins/payment/allopass/apikit/model/AllopassTransactionPrepareRequest.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassTransactionPrepareRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'transaction/prepare'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Overload of internal method which determinates that request has to be done using POST * * @return (boolean) The request has to be done using POST */ protected function _isHttpPost() { return true; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassTransactionPrepareResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassTransactionPrepareResponse($signature, $headers, $body); } }PK\>Odefault/plugins/payment/allopass/apikit/model/AllopassOnetimePricingRequest.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassOnetimePricingRequest extends AllopassApiRequest { /** * Route path of the API */ const PATH = 'onetime/pricing'; /** * Constructor * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * @param emailAccount (string) Email of the configurated account */ public function __construct(array $parameters, $mapping = true, $emailAccount = null) { parent::__construct($parameters, $mapping, $emailAccount); } /** * Provide a way to get the route of the request * * @return (string) The route of the request */ protected function _getPath() { return self::PATH; } /** * Provide a way to get the wired response of the request * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response * * @return (AllopassOnetimePricingResponse) A new response */ protected function _newResponse($signature, $headers, $body) { return new AllopassOnetimePricingResponse($signature, $headers, $body); } }PK\dOdefault/plugins/payment/allopass/apikit/model/AllopassOnetimeButtonResponse.phpnu[ * * @date 2010 (c) Hi-media */ class AllopassOnetimeButtonResponse extends AllopassApiMappingResponse { /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the button access-type * * @return (string) The button access-type */ public function getAccessType() { return (string) $this->_xml->access_type; } /** * Method retrieving the button id * * @return (string) The button id */ public function getButtonId() { return (string) $this->_xml->button_id; } /** * Method retrieving the button creation date * * @return (AllopassDate) The button creation date */ public function getCreationDate() { return new AllopassDate($this->_xml->creation_date); } /** * Method retrieving the button's website * * @return (AllopassWebsite) The button's website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the button buy url * * @return (string) The button buy url */ public function getBuyUrl() { return (string) $this->_xml->buy_url; } /** * Method retrieving the button checkout HTML string * * @return (string) The button checkout HTML string */ public function getCheckoutButton() { return (string) $this->_xml->checkout_button; } }PK\L Odefault/plugins/payment/allopass/apikit/model/AllopassProductDetailResponse.phpnu[ * * @date 2009 (c) Hi-media */ class AllopassProductDetailResponse extends AllopassApiMappingResponse { /** * Constructor * * @param signature (string) Expected response signature * @param headers (string) HTTP headers of the response * @param body (string) Raw data of the response */ public function __construct($signature, $headers, $body) { parent::__construct($signature, $headers, $body); } /** * Method retrieving the product id * * @return (integer) The product id */ public function getId() { return (integer) $this->_xml->id; } /** * Method retrieving the product key * * @return (string) The product key */ public function getKey() { return (string) $this->_xml->key; } /** * Method retrieving the product access-type * * @return (string) The product access-type */ public function getAccessType() { return (string) $this->_xml->access_type; } /** * Method retrieving the product creation date * * @return (AllopassDate) The product creation date */ public function getCreationDate() { return new AllopassDate($this->_xml->creation_date); } /** * Method retrieving the product name * * @return (string) The product name */ public function getName() { return (string) $this->_xml->name; } /** * Method retrieving the product's website * * @return (AllopassWebsite) The product's website */ public function getWebsite() { return new AllopassWebsite($this->_xml->website); } /** * Method retrieving the product expected number of codes * * @return (integer) The product expected number of codes */ public function getExpectedNumberOfCodes() { return (integer) $this->_xml->expected_number_of_codes; } /** * Method retrieving the product purchase url * * @return (string) The product purchase url */ public function getPurchaseUrl() { return (string) $this->_xml->purchase_url; } /** * Method retrieving the product forward url * * @return (string) The product forward url */ public function getForwardUrl() { return (string) $this->_xml->forward_url; } /** * Method retrieving the product error url * * @return (string) The product error url */ public function getErrorUrl() { return (string) $this->_xml->error_url; } /** * Method retrieving the product notification url * * @return (string) The product notification url */ public function getNotificationUrl() { return (string) $this->_xml->notification_url; } }PK\5Bƨe7e7;default/plugins/payment/allopass/apikit/api/AllopassAPI.phpnu[ * @author Jérémy Langlais * * @date 2011 (c) Hi-media */ class AllopassAPI { /** * Email of the configurated account */ private $_configurationEmailAccount; /** * Constructor * * @param configurationEmailAccount (string) Email of the configurated account * If email is null, the first account is considered */ public function __construct($configurationEmailAccount = null) { $this->_configurationEmailAccount = $configurationEmailAccount; } /** * Method for changing the configuration account email * * @param configurationEmailAccount (string) Email of the configurated account * If email is null, the first account is considered * * @return (AllopassAPI) The class instance */ public function setConfigurationEmailAccount($configurationEmailAccount) { $this->_configurationEmailAccount = $configurationEmailAccount; return $this; } /** * Method performing a onetime pricing request * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassOnetimePricingResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->getOnetimePricing(array('site_id' => 127042, 'country' => 'FR')); * echo $response->getWebsite()->getName(), "\n-----\n"; * foreach ($response->getCountries() as $country) { * echo $country->getCode(), "\n-----\n"; * echo $country->getName(), "\n-----\n"; * } * @endcode */ public function getOnetimePricing(array $parameters, $mapping = true) { $request = new AllopassOnetimePricingRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a onetime discrete pricing request * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassOnetimePricingResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->getOnetimeDiscretePricing(array('site_id' => 127042, 'country' => 'FR', 'amount' => 12)); * echo $response->getWebsite()->getName(), "\n-----\n"; * foreach ($response->getCountries() as $country) { * echo $country->getCode(), "\n-----\n"; * echo $country->getName(), "\n-----\n"; * } * @endcode */ public function getOnetimeDiscretePricing(array $parameters, $mapping = true) { $request = new AllopassOnetimeDiscretePricingRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a onetime validate codes request * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassOnetimeValidateCodesResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->validateCodes(array('site_id' => 127042, 'product_id' => 354926, 'code' => array('9M7QU457'))); * echo $response->getStatus(), "\n-----\n"; * echo $response->getStatusDescription(), "\n-----\n"; * @endcode */ public function validateCodes(array $parameters, $mapping = true) { $request = new AllopassOnetimeValidateCodesRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a onetime button request * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassOnetimeButtonResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->createButton(array('site_id' => 127042, 'product_name' => 'premium sms access', 'forward_url'=> 'http://product-page.com', 'amount' => 3, 'reference_currency' => 'EUR', 'price_mode' => 'price', 'price_policy' => 'high-only')); * echo $response->getButtonId(), "\n-----\n"; * echo $response->getBuyUrl(), "\n-----\n"; * @endcode */ public function createButton(array $parameters, $mapping = true) { $request = new AllopassOnetimeButtonRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a onetime discrete button request * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassOnetimeButtonResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->createDiscreteButton(array('site_id' => 127042, 'product_name' => 'discrete premium sms access', 'forward_url'=> 'http://product-page.com', 'amount' => 3, 'reference_currency' => 'EUR', 'price_mode' => 'price', 'price_policy' => 'high-only')); * echo $response->getButtonId(), "\n-----\n"; * echo $response->getBuyUrl(), "\n-----\n"; * @endcode */ public function createDiscreteButton(array $parameters, $mapping = true) { $request = new AllopassOnetimeDiscreteButtonRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a product detail request * * @param id (integer) The product id * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassProductDetailResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->getProduct(354926); * echo $response->getName(), "\n-----\n"; * @endcode */ public function getProduct($id, array $parameters = array(), $mapping = true) { $request = new AllopassProductDetailRequest(array('id' => $id) + $parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a transaction prepare request * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassTransactionPrepareResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->prepareTransaction(array('site_id' => 127042, 'pricepoint_id' => 2, 'product_name' => 'premium calling product', 'forward_url' => 'http://product-page.com')); * echo $response->getBuyUrl(), "\n-----\n"; * echo $response->getCheckoutButton(), "\n-----\n"; * @endcode */ public function prepareTransaction(array $parameters, $mapping = true) { $request = new AllopassTransactionPrepareRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a transaction detail request based on the transaction id * * @param id (string) The transaction id * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassTransactionDetailResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->getTransaction('3f5506ac-5345-45e4-babb-96570aafdf6a'); * echo $response->getPaid()->getCurrency(), "\n-----\n"; * echo $response->getPaid()->getAmount(), "\n-----\n"; * @endcode */ public function getTransaction($id, array $parameters = array(), $mapping = true) { $request = new AllopassTransactionDetailRequest(array('id' => $id) + $parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a transaction detail request based on the merchant transaction id * * @param id (string) The merchant transaction id * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassTransactionDetailResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->getTransactionMerchant('TRX20091112134569B8'); * echo $response->getPaid()->getCurrency(), "\n-----\n"; * echo $response->getPaid()->getAmount(), "\n-----\n"; * @endcode */ public function getTransactionMerchant($id, array $parameters = array(), $mapping = true) { $request = new AllopassTransactionMerchantRequest(array('id' => $id) + $parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a subscription login request based on the sid * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassSubscriptionLoginResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->loginSubscription(array('site_id' => 127042, 'sid' => 'd5425009734ea2801c0389c7bc2f8be4')); * echo $response->getStatus(), "\n-----\n"; * echo $response->getStatusDescription(), "\n-----\n"; * @endcode */ public function loginSubscription(array $parameters = array(), $mapping = true) { $request = new AllopassSubscriptionLoginRequest($parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } /** * Method performing a subscription detail request based on the subscriber_reference * * @param parameters (array) Query string parameters of the API call * @param mapping (boolean) Should the response be an object mapping or a plain response * * @return (AllopassApiResponse) The API call response * Will be a AllopassSubscriptionDetailResponse instance if mapping is true, an AllopassApiPlainResponse if not * * @code * require_once 'apikit/php5/api/AllopassAPI.php'; * $api = new AllopassAPI(); * $response = $api->getSubscription('Z556W642'); * echo $response->getStatus(), "\n-----\n"; * echo $response->getStatusDescription(), "\n-----\n"; * echo $response->getAccessType(), "\n-----\n"; * echo $response->getSubscriberReference(), "\n-----\n"; * @endcode */ public function getSubscription($subscriberReference, array $parameters = array(), $mapping = true) { $request = new AllopassSubscriptionDetailRequest(array('subscriber_reference' => $subscriberReference) + $parameters, $mapping, $this->_configurationEmailAccount); return $request->call(); } }PK\)jj'default/plugins/payment/twocheckout.phpnu[addInteger('seller_id', array('size'=>20)) ->setLabel('2CO Account#'); $form->setDefault('secret', $this->getDi()->security->randomString(10)); $form->addPassword('secret', array('class'=>'el-wide')) ->setLabel("2CO Secret Word\n" . 'set it to the same value as configured in 2CO'); $form->addText('api_username') ->setLabel("2CO API Username\n" . "see point 5 below for details"); $form->addPassword('api_password') ->setLabel("2CO API Password\n" . "see point 5 below for details"); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox (Developer) Account?"); $form->addSelect('lang', array(), array('options' => array( 'en' => 'English', 'zh' => 'Chinese', 'da' => 'Danish', 'nl' => 'Dutch', 'fr' => 'French', 'gr' => 'German', 'el' => 'Greek', 'it' => 'Italian', 'jp' => 'Japanese', 'no' => 'Norwegian', 'pt' => 'Portuguese', 'sl' => 'Slovenian', 'es_ib' => 'Spanish (es_ib)', 'es_la' => 'Spanish (es_la)', 'sv' => 'Swedish' )))->setLabel('2CO Interface language'); $form->addAdvCheckbox('inline') ->setLabel("Use Inline Checkout\n" . "Inline Checkout is iframe checkout option which " . "displays a secure payment form as an overlay on " . "your checkout page. " . 'Your form must also pass in the buyer’s name, email, and full billing address.'); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($ret = parent::isNotAcceptableForInvoice($invoice)) return $ret; foreach ($invoice->getItems() as $item) { if (!(float)$item->first_total && (float)$item->second_total) return array("2Checkout does not support products with free trial"); if ($item->rebill_times && $item->second_period != $item->first_period) return array(___("2Checkout is unable to handle billing for product [{$item->item_title}] - second_period must be equal to first_period")); } } public function getEndpoint() { return $this->getConfig('testing') ? self::SANDBOX_URL : self::URL; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if ($this->getConfig('inline')) { $a = new Am_Paysystem_Action_Form($this->getEndpoint()); $a->setAutoSubmit(false) ->setDisplayReceipt($invoice) ->setProlog(''); } else { $a = new Am_Paysystem_Action_Redirect($this->getEndpoint()); } $a->sid = $this->getConfig('seller_id'); $a->mode = '2CO'; // Check invoice first. If there are more than one recurring product or // recurring product with quantity more then one, then just send one item to 2CO. // 2CO allow to reduce quantity of existing recurring subscription (to cancel eact item if quantity more then 1) // Also IPN notification is sent for each item in subscirption so if quantity = 10, then 10 notifications will be sent. // That can't be handled properly by amember, so disable this functionality. $rec_count = 0; $mul_qty= false; foreach($invoice->getItems() as $item) { if($item->rebill_times) { $rec_count++; if($item->qty>1) $mul_qty = true; } } if(($rec_count>1) || $mul_qty) { $a->{"li_0_type"} = 'product'; $a->{"li_0_name"} = $invoice->getLineDescription(); $a->{"li_0_quantity"} = 1; $a->{"li_0_price"} = moneyRound($invoice->rebill_times ? $invoice->second_total : $invoice->first_total); $a->{"li_0_tangible"} = $invoice->hasShipping() ? 'Y' : 'N'; $a->{"li_0_product_id"} = $invoice->public_id; if ($invoice->rebill_times) { $a->{"li_0_recurrence"} = $this->period2Co($invoice->first_period); if ($invoice->rebill_times != IProduct::RECURRING_REBILLS) $a->{"li_0_duration"} = $this->period2Co($invoice->first_period, $invoice->rebill_times + 1); else $a->{"li_0_duration"} = 'Forever'; $a->{"li_0_startup_fee"} = $invoice->first_total - $invoice->second_total; } } else { $i = 0; foreach ($invoice->getItems() as $item) { $a->{"li_{$i}_type"} = 'product'; $a->{"li_{$i}_name"} = $item->item_title; $a->{"li_{$i}_quantity"} = $item->qty; $a->{"li_{$i}_price"} = moneyRound(($item->rebill_times ? $item->second_total : $item->first_total) / $item->qty); $a->{"li_{$i}_tangible"} = $item->is_tangible ? 'Y' : 'N'; $a->{"li_{$i}_product_id"} = $item->item_id; if ($item->rebill_times) { $a->{"li_{$i}_recurrence"} = $this->period2Co($item->first_period); if ($item->rebill_times != IProduct::RECURRING_REBILLS) $a->{"li_{$i}_duration"} = $this->period2Co($item->first_period, $item->rebill_times + 1); else $a->{"li_{$i}_duration"} = 'Forever'; $a->{"li_{$i}_startup_fee"} = $item->first_total - $item->second_total; } $i++; } } $a->currency_code = $invoice->currency; $a->skip_landing = 1; $a->x_Receipt_Link_URL = $this->getReturnUrl(); $a->lang = $this->getConfig('lang', 'en'); $a->merchant_order_id = $invoice->public_id; $a->first_name = $invoice->getFirstName(); $a->last_name = $invoice->getLastName(); $a->city = $invoice->getCity(); $a->street_address = $invoice->getStreet(); $a->state = $invoice->getState(); $a->zip = $invoice->getZip(); $a->country = $invoice->getCountry(); $a->email = $invoice->getEmail(); $a->phone = $invoice->getPhone(); $result->setAction($a); } public function period2Co($period, $rebill_times = 1) { $p = new Am_Period($period); $c = $p->getCount() * $rebill_times; switch ($p->getUnit()) { case Am_Period::DAY: if (!($c % 7)) return sprintf('%d Week', $c/7); else throw new Am_Exception_Paysystem_NotConfigured("2Checkout does not supported per-day billing, period must be in weeks (=7 days), months, or years"); case Am_Period::MONTH: return sprintf('%d Month', $c); case Am_Period::YEAR: return sprintf('%d Year', $c); } throw new Am_Exception_Paysystem_NotConfigured( "Unable to convert period [$period] to 2Checkout-compatible.". "Must be number of weeks, months or years"); } /** @return Am_Paysystem_Twocheckout_Api|null */ public function getApi() { $user = $this->getConfig('api_username'); $pass = $this->getConfig('api_password'); if (empty($user) || empty($pass)) return null; return new Am_Paysystem_Twocheckout_Api($user, $pass, $this->getDi()); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return Am_Paysystem_Transaction_Twocheckout::create($this, $request, $response, $invokeArgs); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch ($request->getActionName()) { case 'thanks' : return $this->thanksAction($request, $response, $invokeArgs); case 'admin-cancel' : return $this->adminCancelAction($request, $response, $invokeArgs); case 'cancel' : $invoice = $this->getDi()->invoiceTable->findBySecureId($request->getFiltered('id'), 'STOP'.$this->getId()); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); $result = new Am_Paysystem_Result; $payment = current($invoice->getPaymentRecords()); $this->cancelInvoice($payment, $result); $invoice->setCancelled(true); return $response->redirectLocation($this->getDi()->url('member/payment-history',null,false)); default : return parent::directAction($request, $response, $invokeArgs); } } public function thanksAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $log = $this->logRequest($request); $transaction = new Am_Paysystem_Transaction_Twocheckout_Thanks($this, $request, $response, $invokeArgs); $transaction->setInvoiceLog($log); try { $transaction->process(); } catch(Am_Exception_Paysystem_TransactionAlreadyHandled $e){ // Ignore. Just show receipt. } catch (Exception $e) { throw $e; $this->getDi()->errorLogTable->logException($e); throw Am_Exception_InputError(___("Error happened during transaction handling. Please contact website administrator")); } $log->setInvoice($transaction->getInvoice())->update(); $this->invoice = $transaction->getInvoice(); $response->setRedirect($this->getReturnUrl()); } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $payment = current($invoice->getPaymentRecords()); try { $this->cancelInvoice($payment, $result); if ($result->isSuccess()) { $invoice->setCancelled(true); } } catch (Exception $e) { $result->setFailed($e->getMessage()); } } public function cancelInvoice(InvoicePayment $payment, Am_Paysystem_Result $result) { try { $ret = $this->getApi()->detailSale($payment->receipt_id); } catch (Am_Exception_Paysystem $e) { //try to check if it is payment imported from v3 $am3id = $this->getDi()->getDbService()->selectCell("SELECT value from ?_data where `key`='am3:id' AND `table`='invoice_payment' and id=?",$payment->invoice_payment_id); if(!$am3id) throw $e; //try to load by invoice id to find sale id $ret = $this->getApi()->detailInvoice($payment->receipt_id); if(!$ret['sale']['sale_id']) throw $e; //now we have sale id $ret = $this->getApi()->detailSale($ret['sale']['sale_id']); } $lineitems = array(); foreach ($ret['sale']['invoices'] as $inv) { foreach ($inv['lineitems'] as $litem) { if ($litem['billing']['recurring_status'] == 'active') { $lineitems[] = $litem['lineitem_id']; } } } $lineitems = array_unique($lineitems); if (!$lineitems) { $result->setFailed("Order not found, try to refund it manually"); return; } $log = $this->getDi()->invoiceLogRecord; $log->setInvoice($payment->getInvoice()); // foreach ($lineitems as $id) // { $id = max($lineitems); try { $return = $this->getApi()->stopLineitemRecurring($id); } catch (Am_Exception_Paysystem $e) { //if we get //NOTHING_TO_DO //or //Lineitem is not scheduled to recur //mark invoice as cancelled if(preg_match('/NOTHING_TO_DO/', $e->getMessage()) && preg_match('/Lineitem is not scheduled to recur/', $e->getMessage())) return; else throw $e; } if ($return['response_code'] != 'OK') { $result->setFailed("Could not stop recurring for lieitem [$id]. Fix it manually in 2CO account"); return; } // } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { if (!$this->getApi()) throw new Am_Exception_Paysystem_NotConfigured("No 2Checkout API username/password configured - could not do refund"); $log = $this->getDi()->invoiceLogRecord; $log->setInvoice($payment->getInvoice()); $invoice_id = $payment->data()->get(self::DATA_INVOICE_KEY); $return = $this->getApi()->refundInvoice($payment->receipt_id, 5, "Customer Request", $invoice_id); $log->add($return); if ($return['response_code'] == 'OK') { $result->setSuccess(); } else { $result->setFailed($return['response_message']); } } public function getReadme() { return <<Site Management". Set: Direct Return: (*) Header Redirect (your URL) Secret Word: set to any value you like (aMember will offer you generated value, look at the form). IMPORTANT! The same value must be entered to aMember 2Checkout plugin settings on this page Approved URL: %root_url%/payment/twocheckout/thanks 3. Go to "Notifications->Settings", set INS URL: %root_url%/payment/twocheckout/ipn for all messages, click Save You can find Notification menu item (circle) on right side of menu near Help button. 4. Check your aMember product settings: for recurring products first period must be equal to to second period, and period must be in weeks (specify days multilplied to 7), months or years. 5. You can optionally configure API access. It is neccessary for Cancel and Refunds. Your 2Checkout API username and password is different from your 2Checkout login username and password. To get API username and password - Login to your 2Checkout account - Go to Account - User Management. Click on Create Username - Enter necessary details - Make sure to select API Access and API Updating within Access selection. - Save and use these credentials for API username and password CUT; } } class Am_Paysystem_Transaction_Twocheckout extends Am_Paysystem_Transaction_Incoming { // the following messages are sent once for each invoice const ORDER_CREATED = "ORDER_CREATED"; const FRAUD_STATUS_CHANGED = "FRAUD_STATUS_CHANGED"; const SHIP_STATUS_CHANGED = "SHIP_STATUS_CHANGED"; const INVOICE_STATUS_CHANGED = "INVOICE_STATUS_CHANGED"; // the following messages are sent for EACH item in the invoice const REFUND_ISSUED = "REFUND_ISSUED"; const RECURRING_INSTALLMENT_SUCCESS = "RECURRING_INSTALLMENT_SUCCESS"; const RECURRING_INSTALLMENT_FAILED = "RECURRING_INSTALLMENT_FAILED"; const RECURRING_STOPPED = "RECURRING_STOPPED"; const RECURRING_COMPLETE = "RECURRING_COMPLETE"; const RECURRING_RESTARTED = "RECURRING_RESTARTED"; public function findInvoiceId() { return $this->request->getFiltered('vendor_order_id'); } public function getUniqId() { return $this->request->getFiltered('sale_id', $this->request->getFiltered('message_id')); } public function getReceiptId() { return $this->request->getFiltered('sale_id'); // @todo . add rebill date or message_id ? } public function validateSource() { $hash = $this->request->get('sale_id') . intval($this->plugin->getConfig('seller_id')) . $this->request->get('invoice_id') . $this->plugin->getConfig('secret'); return strtoupper(md5($hash)) === $this->request->get('md5_hash'); } public function validateStatus() { return true; } public function validateTerms() { return true; } static function create(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch ($request->get('message_type')) { case Am_Paysystem_Transaction_Twocheckout::ORDER_CREATED: return new Am_Paysystem_Transaction_Twocheckout_Order($plugin, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Twocheckout::RECURRING_INSTALLMENT_SUCCESS: return new Am_Paysystem_Transaction_Twocheckout_RecurringOrder($plugin, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Twocheckout::RECURRING_COMPLETE: return new Am_Paysystem_Transaction_Twocheckout_Null($plugin, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Twocheckout::FRAUD_STATUS_CHANGED: return new Am_Paysystem_Transaction_Twocheckout_Fraud($plugin, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Twocheckout::REFUND_ISSUED: return new Am_Paysystem_Transaction_Twocheckout_Refund($plugin, $request, $response, $invokeArgs); case Am_Paysystem_Transaction_Twocheckout::RECURRING_STOPPED: return new Am_Paysystem_Transaction_Twocheckout_Cancel($plugin, $request, $response, $invokeArgs); } } } class Am_Paysystem_Transaction_Twocheckout_Order extends Am_Paysystem_Transaction_Twocheckout { public function processValidated() { if ($this->invoice->getPaymentsCount() == 1) foreach ($this->invoice->getPaymentRecords() as $p) if ($p->transaction_id == $this->getUniqId()) return; // already handled by thanksAction, skip silently $p = $this->invoice->addPayment($this); $p->data()->set(Am_Paysystem_Twocheckout::DATA_INVOICE_KEY, $this->request->getParam('invoice_id')); $p->save(); } public function validateTerms() { // @todo for recurring return $this->request->get('invoice_list_amount') == $this->invoice->first_total; } } class Am_Paysystem_Transaction_Twocheckout_RecurringOrder extends Am_Paysystem_Transaction_Twocheckout { public function getUniqId() { return $this->request->getFiltered('sale_id').'-'.$this->request->getFiltered('message_id'); } public function processValidated() { $p = $this->invoice->addPayment($this); $p->data()->set(Am_Paysystem_Twocheckout::DATA_INVOICE_KEY, $this->request->getParam('invoice_id')); $p->save(); } public function validateTerms() { $sum = 0; if($count = $this->request->get('item_count')){ for($i = 1; $i<= $count; $i++){ $sum += $this->request->get('item_list_amount_'.$i); } } return $sum == $this->invoice->second_total; } } class Am_Paysystem_Transaction_Twocheckout_Null extends Am_Paysystem_Transaction_Twocheckout { public function processValidated() { //we just record this info to log } } class Am_Paysystem_Transaction_Twocheckout_Fraud extends Am_Paysystem_Transaction_Twocheckout { public function processValidated() { //we just record this info to log, 2checkout will send separate notification about refund } } class Am_Paysystem_Transaction_Twocheckout_Cancel extends Am_Paysystem_Transaction_Twocheckout { public function processValidated() { $this->invoice->setCancelled(); } } class Am_Paysystem_Transaction_Twocheckout_Refund extends Am_Paysystem_Transaction_Twocheckout { public function getUniqId() { return $this->request->getFiltered('message_id'); } public function getReceiptId() { return $this->request->getFiltered('message_id'); } public function getAmount() { //https://www.2checkout.com/static/va/documentation/INS/message_refund_issued.html $amount = 0; foreach($this->request->getParams() as $k => $v) if(preg_match("/item_type_([0-9]+)/", $k, $m) && $v == 'refund') $amount+=$this->request->get("item_list_amount_$m[1]", 0); return $amount; } public function processValidated() { if (!$this->getAmount()) return; //refund notification for free record $this->invoice->addRefund($this, $this->plugin->getDi()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); } } class Am_Paysystem_Twocheckout_Api { const URL = 'https://www.2checkout.com/api/'; protected $req, $di; public function __construct($user, $pass, Am_Di $di) { $this->di = $di; $this->req = new Am_HttpRequest(); $this->req->setAuth($user, $pass); $this->req->setHeader('Accept', 'application/json'); } protected function send($title = '') { $log = $this->di->invoiceLogRecord; $log->title = $title; $log->add($this->req); $res = $this->req->send(); $log->add($res); if ($res->getStatus() != 200) throw new Am_Exception_Paysystem("Bad response from 2CO api: HTTP Status " . $res->getStatus() . ', body: ' . $res->getBody()); $ret = json_decode(utf8_encode($res->getBody()), true); if ($ret['response_code'] != 'OK') throw new Am_Exception_Paysystem("Bad response from 2CO api: " . $ret['response_code'] . '-' . $ret['response_message']); return $ret; } function detailSale($saleId) { $this->req->setUrl(self::URL . 'sales/detail_sale?sale_id='.$saleId); return $this->send('detailSale'); } function detailInvoice($invoiceId) { $this->req->setUrl(self::URL . 'sales/detail_sale?invoice_id='.$invoiceId); return $this->send('detailInvoice'); } function refundInvoice($saleId, $reasonCategory, $reasonComment, $invoice_id=null) { $this->req->addPostParameter('sale_id', $saleId); if ($invoice_id) { $this->req->addPostParameter('invoice_id', $invoice_id); } $this->req->addPostParameter('category', $reasonCategory); $this->req->addPostParameter('comment', $reasonComment); $this->req->setMethod('POST'); $this->req->setUrl(self::URL . 'sales/refund_invoice'); return $this->send('refundInvoice'); } function stopLineItemRecurring($lineItemId) { $this->req->addPostParameter('lineitem_id', $lineItemId); $this->req->setMethod('POST'); $this->req->setUrl(self::URL . 'sales/stop_lineitem_recurring'); return $this->send('stopLineItemRecurring'); } } class Am_Paysystem_Transaction_Twocheckout_Thanks extends Am_Paysystem_Transaction_Incoming { public function fetchUserInfo() { $email = preg_replace('/[^a-zA-Z0-9._+@-]/', '', $this->request->get('cemail')); return array( 'name_f' => $this->request->getFiltered('first_name'), 'name_l' => $this->request->getFiltered('last_name'), 'email' => $email, 'country' => $this->request->getFiltered('country'), 'zip' => $this->request->getFiltered('zip'), ); } public function generateInvoiceExternalId() { return $this->getUniqId(); } // // public function autoCreateGetProducts() // { // $cbId = $this->request->getFiltered('item'); // if (empty($cbId)) return; // $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('clickbank_product_id', $cbId); // if (!$pl) return; // $pr = $pl->getProduct(); // if (!$pr) return; // return array($pr); // } public function getUniqId() { return $this->request->getFiltered('order_number'); } public function findInvoiceId() { return $this->request->getFiltered('merchant_order_id'); } public function getAmount() { return moneyRound($this->request->get('total')); } public function validateSource() { $vars = array( $this->getPlugin()->getConfig('secret'), $this->getPlugin()->getConfig('seller_id'), $this->request->get('order_number'), sprintf('%.2f', $this->request->get('total')), ); $hash = strtoupper(md5(implode('', $vars))); if ($this->request->get('key') != $hash) { throw new Am_Exception_Paysystem_TransactionSource("2Checkout validation failed - most possible [secret] is configured incorrectly - mismatch between values in aMember and 2Checkout"); } return true; } public function validateStatus() { return true; } public function validateTerms() { if ($this->invoice->status == Invoice::PENDING) { $this->assertAmount($this->invoice->first_total, $this->getAmount(), 'First Total'); } else { $this->assertAmount($this->invoice->second_total, $this->getAmount(), 'Second Total'); } return true; } public function getInvoice() { return $this->invoice; } }PK\ FyE P P"default/plugins/payment/paypal.phpnu[billingPlanTable->customFields()->add( new Am_CustomFieldText( 'paypal_id', "PayPal Button Item Number", "if you want to use PayPal buttons, create button with \n". "the same billing settings, and enter its item number here" ,array(/*,'required'*/) )); } public function getSupportedCurrencies() { return array( 'AUD', 'BRL', 'CAD', 'CZK', 'DKK', 'EUR', 'HKD', 'HUF', 'ILS', 'JPY', 'MYR', 'MXN', 'NOK', 'NZD', 'PHP', 'PLN', 'GBP', 'SGD', 'SEK', 'CHF', 'TWD', 'THB', 'USD', 'TRY', 'RUB'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("business", array('class' => 'el-wide')) ->setLabel("Primary Paypal E-Mail Address"); $form->addText("merchant_id", array('class' => 'el-wide')) ->setLabel("Your Merchant ID\n" . "You can get it from Your Account -> Profile"); $form->addText("api_username", array('class' => 'el-wide'))->setLabeL("API Username"); $form->addPassword("api_password")->setLabel("API Password"); $form->addText("api_signature", array('class' => 'el-wide'))->setLabel("API Signature"); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox(Testing) Account?"); $form->addTextarea("alt_business", array('rows'=>3, 'class' => 'one-per-line')) ->setLabel("Alternate PayPal account emails (one per line)"); $form->addAdvCheckbox("dont_verify") ->setLabel( "Disable IPN verification\n" . "Usually you DO NOT NEED to enable this option. However, on some webhostings PHP scripts are not allowed to contact external web sites. It breaks functionality of the PayPal payment integration plugin, and aMember Pro then is unable to contact PayPal to verify that incoming IPN post is genuine. In this case, AS TEMPORARY SOLUTION, you can enable this option to don't contact PayPal server for verification. However, in this case \"hackers\" can signup on your site without actual payment. So if you have enabled this option, contact your webhost and ask them to open outgoing connections to www.paypal.com port 80 ASAP, then disable this option to make your site secure again."); $form->addText("lc", array('size'=>4)) ->setLabel("PayPal Language Code\n" . "This field allows you to configure PayPal page language that will be displayed when customer is redirected from your website to PayPal for payment. By default, this value is empty, then PayPal will automatically choose which language to use. Or, alternatively, you can specify for example: US (for english language), or FR (for french Language) and so on. In this case, PayPal will not choose language automatically.
      Default value for this field is empty string"); $form->addText("page_style") ->setLabel("PayPal Page Style" . "\n" . "use the custom payment page style from your account profile that has the specified name. Default value for this field is empty string"); $form->addAdvCheckbox("accept_pending_echeck") ->setLabel("Recognize pending echeck payments as completed"); $form->addSelect("sra") ->setLabel("Reattempt on failure\n". "PayPal attempts to collect the payment two more times before canceling the subscription") ->loadOptions(array('2' => 'Reattempt failed recurring payments before canceling', '1' => 'Do not reattempt failed recurring payments')); } function init() { $this->domain = $this->getConfig('testing') ? 'www.sandbox.paypal.com' : 'www.paypal.com'; } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($err = parent::isNotAcceptableForInvoice($invoice)) return $err; if ($invoice->rebill_times >= 1 && $err = $this->checkPeriod(new Am_Period($invoice->first_period))) return array($err); if ($invoice->rebill_times == 1 && $invoice->second_period == Am_Period::MAX_SQL_DATE) return; if ($invoice->rebill_times >= 1 && $err = $this->checkPeriod(new Am_Period($invoice->second_period))) return array($err); if ($invoice->rebill_times != IProduct::RECURRING_REBILLS && $invoice->rebill_times > 52) return array('PayPal can not handle subscription terms with number of rebills more than 52'); } /** * Return error message if period could not be handled by PayPal * @param Am_Period $p */ public function checkPeriod(Am_Period $p){ $period = $p->getCount(); switch ($unit = strtoupper($p->getUnit())){ case 'Y': if (($period < 1) or ($period > 5)) return ___('Period must be in interval 1-5 years'); break; case 'M': if (($period < 1) or ($period > 24)) return ___('Period must be in interval 1-24 months'); break; case 'D': if (($period < 1) or ($period > 90)) return ___('Period must be in interval 1-90 days'); break; default: return sprintf(___('Unknown period unit: %s'), $unit); } } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if (!$this->getConfig('business')) throw new Am_Exception_Configuration("There is a configuration error in [paypal] plugin - no [business] e-mail configured"); $a = new Am_Paysystem_Action_Redirect('https://' . $this->domain . '/cgi-bin/webscr'); $result->setAction($a); $a->business = $this->getConfig('business'); $a->return = $this->getReturnUrl(); $a->notify_url = $this->getPluginUrl('ipn'); $a->cancel_return = $this->getCancelUrl(); $a->item_name = $invoice->getLineDescription(); $a->no_shipping = $invoice->hasShipping() ? 0 : 1; $a->shipping = $invoice->first_shipping; $a->currency_code = strtoupper($invoice->currency); $a->no_note = 1; $a->invoice = $invoice->getRandomizedId(); $a->bn = 'CgiCentral.aMemberPro'; $a->first_name = $invoice->getFirstName(); $a->last_name = $invoice->getLastName(); $a->address1 = $invoice->getStreet(); $a->city = $invoice->getCity(); $a->state = $invoice->getState(); $a->zip = $invoice->getZip(); $a->country = $invoice->getCountry(); $a->charset = 'utf-8'; if ($lc = $this->getConfig('lc')) $a->lc = $lc; if ($page_style = $this->getConfig('page_style')) $a->page_style = $page_style; $a->rm = 2; if ($invoice->rebill_times) { $a->cmd = '_xclick-subscriptions'; $a->sra = $this->getConfig('sra', self::DEFAULT_SRA) - 1; /** @todo check with rebill times = 1 */ $p1 = new Am_Period($invoice->first_period); $p3 = new Am_Period($invoice->second_period == Am_Period::MAX_SQL_DATE ? '5y' : $invoice->second_period); $a->a3 = $invoice->second_total; $a->p3 = $p3->getCount(); $a->t3 = $this->getPeriodUnit($p3->getUnit()); $a->tax3 = $invoice->second_tax; if($invoice->first_total == $invoice->second_total && $invoice->first_period == $invoice->second_period && $invoice->first_tax == $invoice->second_tax) { $a->src = 1; //Ticket #HPU-80211-470: paypal_r plugin not passing the price properly (or at all)? if ($invoice->rebill_times != IProduct::RECURRING_REBILLS ) $a->srt = $invoice->rebill_times + 1; } else { if ($invoice->rebill_times == 1) { $a->src = 0; } else { $a->src = 1; //Ticket #HPU-80211-470: paypal_r plugin not passing the price properly (or at all)? if ($invoice->rebill_times != IProduct::RECURRING_REBILLS ) $a->srt = $invoice->rebill_times; } $a->a1 = $invoice->first_total; $a->p1 = $p1->getCount(); $a->t1 = $this->getPeriodUnit($p1->getUnit()); $a->tax1 = $invoice->first_tax; } } else { $a->cmd = '_xclick'; $a->amount = $invoice->first_total - $invoice->first_tax - $invoice->first_shipping; $a->tax = $invoice->first_tax; } } function getPeriodUnit($unit){ $units = array('D', 'M', 'Y'); $unit = strtoupper($unit); if (!in_array($unit, $units)) throw new Am_Exception_Paysystem("Unfortunately PayPal could not handle period unit [$unit], please choose another payment method"); return $unit; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Paypal_Transaction($this, $request, $response, $invokeArgs); } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<PayPal payment plugin installation Up to date instructions how to enable and configure PayPal plugin you may find at http://www.amember.com/docs/Payment/Paypal IPN URL to enter into PayPal settings: $url It is only necessary to enable IPN in PayPal. If IPN is already enabled, it does not matter what exactly URL is specified. aMember will automatically let PayPal know to use aMember URL. CUT; } function getUserCancelUrl(Invoice $invoice) { if( $invoice->data()->get(self::PAYPAL_PROFILE_ID) && $this->getConfig('api_username') && $this->getConfig('api_password') && $this->getConfig('api_signature') && (strpos($invoice->data()->get(self::PAYPAL_PROFILE_ID), 'S-') !== 0 ) ) return parent::getUserCancelUrl ($invoice); return 'https://' . $this->domain . '?' . http_build_query(array( 'cmd' => '_subscr-find', 'alias' => $this->getConfig('merchant_id'), ), '', '&'); } public function getAdminCancelUrl(Invoice $invoice) { if( $invoice->data()->get(self::PAYPAL_PROFILE_ID) && $this->getConfig('api_username') && $this->getConfig('api_password') && $this->getConfig('api_signature') && (strpos($invoice->data()->get(self::PAYPAL_PROFILE_ID), 'S-') !== 0 ) ) return parent::getAdminCancelUrl ($invoice); return 'https://' . $this->domain . '?' . http_build_query(array( 'cmd' => '_subscr-find', 'alias' => $this->getConfig('merchant_id'), ), '', '&'); } public function canAutoCreate() { return true; } function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = "cancelRecurringPaymentProfile"; $log->paysys_id = $this->getId(); $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->cancelRecurringPaymentProfile($invoice, $invoice->data()->get(self::PAYPAL_PROFILE_ID)); $vars = $apireq->sendRequest($log); $log->setInvoice($invoice); $log->update(); if($vars['ACK'] != 'Success') throw new Am_Exception_InputError('Transaction was not cancelled. Got error from paypal: '.$vars['L_SHORTMESSAGE0']); $invoice->setCancelled(true); $result->setSuccess(); } } class Am_Paysystem_Paypal_Transaction extends Am_Paysystem_Transaction_Paypal { protected $_autoCreateMap = array( 'name_f' => 'first_name', 'name_l' => 'last_name', 'email' => 'payer_email', 'street' => 'addres_street', 'zip' => 'address_zip', 'state' => 'address_state', 'country' => 'address_country_code', 'city' => 'address_city', 'user_external_id' => 'payer_id', 'invoice_external_id' => array('parent_txn_id', 'subscr_id', 'txn_id') , ); public function processValidated() { switch ($this->txn_type) { case self::TXN_SUBSCR_SIGNUP: if ((float)$this->invoice->first_total <= 0) // no payment will be reported if ($this->invoice->status == Invoice::PENDING) // handle only once $this->invoice->addAccessPeriod($this); // add first trial period $this->invoice->data()->set(Am_Paysystem_Paypal::PAYPAL_PROFILE_ID, $this->request->subscr_id)->update(); break; case self::TXN_SUBSCR_EOT: // Stop access only if we have lifetime access within invoice. // This is done to handle records imported from v3 if(Am_Di::getInstance()->getDbService()->selectCell(' SELECT count(*) FROM ?_access WHERE invoice_id = ? and expire_date = ?', $this->invoice->pk(), Am_Period::MAX_SQL_DATE)) $this->invoice->stopAccess($this); break; case 'recurring_payment_suspended_due_to_max_failed_payment' : $this->invoice->setStatus(Invoice::RECURRING_FAILED); $this->invoice->updateQuick('rebill_date', null); break; case self::TXN_SUBSCR_CANCEL: $this->invoice->setCancelled(true); break; case self::TXN_WEB_ACCEPT: case self::TXN_SUBSCR_PAYMENT: case self::TXN_CART: switch ($this->request->payment_status) { case 'Completed': $this->invoice->addPayment($this); break; case 'Pending': if($this->plugin->getConfig('accept_pending_echeck') && $this->request->payment_type == 'echeck') $this->invoice->addPayment($this); break; default: } if($this->request->subscr_id) $this->invoice->data()->set(Am_Paysystem_Paypal::PAYPAL_PROFILE_ID, $this->request->subscr_id)->update(); break; } switch($this->request->payment_status){ case 'Reversed': if ($originalInvoicePayment = Am_Di::getInstance()->invoicePaymentTable->findFirstBy(array( 'receipt_id' => $this->request->parent_txn_id, 'invoice_id' => $this->invoice->pk() ))) { Am_Di::getInstance()->accessTable->deleteBy(array( 'invoice_payment_id' =>$originalInvoicePayment->pk(), )); } break; case 'Canceled_Reversal': if ($originalInvoicePayment = Am_Di::getInstance()->invoicePaymentTable->findFirstBy(array( 'receipt_id' => $this->request->parent_txn_id, 'invoice_id' => $this->invoice->pk() ))) { $this->invoice->addAccessPeriod($this, $originalInvoicePayment->pk()); } break; case 'Refunded': $this->invoice->addRefund($this, $this->request->parent_txn_id, $this->getAmount()); break; case 'Chargeback': $this->invoice->addChargeback($this, $this->request->parent_txn_id); break; } } public function validateStatus() { $status = $this->request->getFiltered('status'); if($this->plugin->getConfig('accept_pending_echeck') && $this->request->getFiltered('payment_type') == 'echeck') { if($this->request->getFiltered('payment_status') == 'Pending' || $status == 'Pending') return true; } return $status === null || $status === 'Completed'; } public function validateTerms() { $currency = $this->request->getFiltered('mc_currency'); if ($currency && (strtoupper($this->invoice->currency) != $currency)) throw new Am_Exception_Paysystem_TransactionInvalid("Wrong currency code [$currency] instead of {$this->invoice->currency}"); if (in_array($this->txn_type, array(self::TXN_CART, self::TXN_SUBSCR_PAYMENT, self::TXN_WEB_ACCEPT))) { $isFirst = $this->invoice->first_total && !$this->invoice->getPaymentsCount(); if($this->invoice->first_total == $this->invoice->second_total && $this->invoice->first_period == $this->invoice->second_period) { $isFirst = false; } $expected = $isFirst ? $this->invoice->first_total : $this->invoice->second_total; if ($expected > ($amount = $this->getAmount())) throw new Am_Exception_Paysystem_TransactionInvalid("Payment amount is [$amount], expected not less than [$expected]"); } elseif ($this->txn_type == self::TXN_SUBSCR_SIGNUP) { if ($this->invoice->first_total != $this->invoice->second_total || $this->invoice->first_period != $this->invoice->second_period) { if ($this->invoice->first_total != $this->request->get('mc_amount1')) return false; } if ("" != $this->request->get('mc_amount2')) return false; if ($this->invoice->second_total != $this->request->get('mc_amount3')) return false; if ($this->invoice->currency != $this->request->get('mc_currency')) return false; $p1 = new Am_Period($this->invoice->first_period); $p3 = new Am_Period($this->invoice->second_period); try { $p1 = $p1->getCount() . ' ' . $this->plugin->getPeriodUnit($p1->getUnit()); $p3 = $p3->getCount() . ' ' . $this->plugin->getPeriodUnit($p3->getUnit()); } catch (Exception $e) { } if ($this->invoice->first_total != $this->invoice->second_total || $this->invoice->first_period != $this->invoice->second_period) { if ($p1 != $this->request->get('period1')) return false; } if ("" != $this->request->get('period2')) return false; if ($p3 != $this->request->get('period3')) return false; } return true; } public function autoCreateGetProducts() { $item_number = $this->request->get('item_number', $this->request->get('item_number1')); if (empty($item_number)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('paypal_id', $item_number); if($billing_plan) return array($billing_plan->getProduct()); } }PK\eyy'default/plugins/payment/postfinance.phpnu[addText('pspid', array('size' => 20)) ->setLabel('Your Affiliation Name in Postfinance'); $form->addText('sha_in', array('size' => 20)) ->setLabel('SHA IN pass phrase'); $form->addText('sha_out', array('size' => 20)) ->setLabel('SHA OUT pass phrase'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); $result->setAction($a); $u = $invoice->getUser(); $vars = array(); $vars['PSPID'] = $this->config['pspid']; $vars['ORDERID'] = $invoice->public_id; $vars['AMOUNT'] = $invoice->first_total*100; $vars['CURRENCY'] = $invoice->currency; $vars['LANGUAGE'] = 'en_US'; $vars['CN'] = $u->getName(); $vars['EMAIL'] = $u->email; $vars['OWNERZIP'] = $u->zip; $vars['OWNERADDRESS'] = $u->street; $vars['OWNERCTY'] = $u->city; $vars['COM'] = $invoice->getLineDescription(); $vars['HOMEURL'] = $this->getReturnUrl(); $vars['ACCEPTURL'] = $this->getPluginUrl('thanks'); $vars['DECLINEURL'] = $this->getCancelUrl(); $vars['CANCELURL'] = $this->getCancelUrl(); $vars = array_filter($vars); ksort($vars); foreach($vars as $k => $v) { $sha.="$k=$v".$this->config['sha_in']; $a->addParam($k, $v); } $a->SHASIGN = sha1($sha); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Postfinance_Thanks($this, $request, $response,$invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array ('EUR', 'USD', 'GBP', 'CHF'); } public function getReadme() { return <<request->get('orderID'); } public function getUniqId() { return $this->request->get('PAYID'); } public function validateSource() { $vars = $this->request->getParams(); $hash = $vars['SHASIGN']; unset($vars['plugin_id'],$vars['action'],$vars['module'],$vars['controller'],$vars['type'], $vars['SHASIGN']); $vars = array_filter($vars,'strlen'); uksort($vars, 'strcasecmp'); $sha = ''; $secret = $this->plugin->getConfig('sha_out'); foreach($vars as $k => $v) $sha.=strtoupper($k)."=$v$secret"; return (strtoupper(sha1($sha)) == strtoupper($hash)); } public function validateStatus() { return in_array($this->request->get('STATUS'),array(5,9)); } public function validateTerms() { return (doubleval($this->invoice->first_total) == doubleval($this->request->get('amount'))); } }PK\h%default/plugins/payment/robokassa.phpnu[addText('merchant_login')->setLabel('Merchant Login'); $form->addText('merchant_pass1')->setLabel("Password #1\n" . 'From shop technical preferences'); $form->addText('merchant_pass2')->setLabel("Password #2\n" . 'From shop technical preferences'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); $form->addSelect('language', '', array('options' => array('en'=>'English', 'ru'=>'Russian')))->setLabel('Interface Language'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::TEST_URL : self::LIVE_URL); $vars = array( 'MrchLogin' =>$this->getConfig('merchant_login'), 'OutSum'=> $invoice->first_total, 'InvId'=> $invoice->invoice_id, 'Desc' => $invoice->getLineDescription(), 'Culture' => $this->getConfig('language', 'en') ); $vars['SignatureValue'] = $this->getSignature($vars, $this->getConfig('merchant_pass1')); foreach($vars as $k=>$v){ $a->addParam($k,$v); } $result->setAction($a); } function getSignature($vars, $pass) { $md5 = md5($s = sprintf("%s:%s:%s:%s", $vars['MrchLogin'], $vars['OutSum'], $vars['InvId'], $pass)); return $md5; } function getIncomingSignature($vars, $pass) { $md5 = md5($s = sprintf("%s:%s:%s", $vars['OutSum'], $vars['InvId'], $pass)); return $md5; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Robokassa($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Robokassa_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme() { return <<invoice->public_id; } public function validateSource() { if(strtoupper($this->getPlugin()->getIncomingSignature($this->request->getParams(), $this->getPlugin()->getConfig('merchant_pass2'))) != $this->request->getParam('SignatureValue')) return false; return true; } public function validateStatus() { return true; } public function validateTerms() { return $this->request->getParam('OutSum') == $this->invoice->first_total; } function findInvoiceId() { $invoice = $this->getPlugin()->getDi()->invoiceTable->load($this->request->getFiltered('InvId')); return $invoice->public_id; } function processValidated() { parent::processValidated(); print "OK".$this->invoice->invoice_id; } } class Am_Paysystem_Transaction_Robokassa_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->invoice->public_id; } public function validateSource() { if($this->getPlugin()->getIncomingSignature($this->request->getParams(), $this->getPlugin()->getConfig('merchant_pass1')) != $this->request->getParam('SignatureValue')) return false; return true; } public function validateStatus() { return true; } public function validateTerms() { return $this->request->getParam('OutSum') == $this->invoice->first_total; } function findInvoiceId() { $invoice = $this->getPlugin()->getDi()->invoiceTable->load($this->request->getFiltered('InvId')); return $invoice->public_id; } }PK\~,.,.!default/plugins/payment/xfers.phpnu[addAdvRadio("api_ver") ->setLabel('Xfers API Version') ->loadOptions(array( '' => 'V2', '3' => 'V3', )); $form->setDefault("api_ver", ''); $form->addText("api_key", array('class' => 'el-wide api_v2')) ->setLabel('Merchant API Key'); $form->addPassword("api_secret", array('class' => 'el-wide api_v2')) ->setLabel('Merchant API Secret'); $form->addText("api_key_v3", array('class' => 'el-wide api_v3')) ->setLabel('X-XFERS-USER-API-KEY'); $form->addTextarea('meta_fields', array('class' => 'el-wide api_v3', 'rows' => 8)) ->setLabel("Additional Fields\n" . "xfers_field|amember_field\n" . "one pair per row, eg:\n" . "firstname|name_f\n" . "lastname|name_l\n" ); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox (Testing) Account?"); $form->addAdvCheckbox("dont_verify") ->setLabel( "Disable IPN verification\n" . "Usually you DO NOT NEED to enable this option. However, on some webhostings PHP scripts are not allowed to contact external web sites. It breaks functionality of the Xrefs payment integration plugin, and aMember Pro then is unable to contact Xrefs to verify that incoming IPN post is genuine. In this case, AS TEMPORARY SOLUTION, you can enable this option to don't contact Xrefs server for verification. However, in this case \"hackers\" can signup on your site without actual payment. So if you have enabled this option, contact your webhost and ask them to open outgoing connections to www.xfers.io port 80 ASAP, then disable this option to make your site secure again."); $form->addScript() ->setScript(<<getConfig('api_ver') == 3) { return $this->_process3($invoice, $request, $result); } $u = $invoice->getUser(); $domain = $this->getConfig('testing') ? Am_Paysystem_Xfers::SANDBOX_DOMAIN : Am_Paysystem_Xfers::LIVE_DOMAIN; $a = new Am_Paysystem_Action_Form('https://' . $domain . '/api/v2/payments'); $a->api_key = $this->getConfig('api_key'); $a->order_id = $invoice->public_id; $a->cancel_url = $this->getCancelUrl(); $a->return_url = $this->getReturnUrl(); $a->notify_url = $this->getPluginUrl('ipn'); if ($invoice->first_tax) { $a->tax = $invoice->first_tax; } /* @var $item InvoiceItem */ $i = 1; foreach ($invoice->getItems() as $item) { $a->{'item_name_' . $i} = $item->item_title; $a->{'item_description_' . $i} = $item->item_description; $a->{'item_quantity_' . $i} = $item->qty; $a->{'item_price_' . $i} = moneyRound($item->first_total/$item->qty); $i++; } $a->total_amount = $invoice->first_total; $a->currency = $invoice->currency; $a->user_email = $invoice->getUser()->email; $a->signature = sha1($a->api_key . $this->getConfig('api_secret') . $a->order_id . $a->total_amount . $a->currency); $result->setAction($a); } public function _process3(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $req = $this->createHttpRequest(); $req->setUrl('https://' . ($this->getConfig('testing') ? self::SANDBOX_DOMAIN : self::LIVE_DOMAIN) . '/api/v3/charges'); $req->setMethod(Am_HttpRequest::METHOD_POST); $req->setConfig('ssl_verify_peer', false); $req->setConfig('ssl_verify_host', false); $req->setHeader(array( 'X-XFERS-USER-API-KEY' => $this->getConfig('api_key_v3'), 'Content-Type' => 'application/json' )); $data = array( 'amount' => $invoice->first_total, 'currency' => $invoice->currency, 'order_id' => $invoice->public_id, 'description' => $invoice->getLineDescription(), 'notify_url' => $this->getPluginUrl('ipn3'), 'return_url' => $this->getReturnUrl(), 'cancel_url' => $this->getCancelUrl(), 'redirect' => 'false', 'items' => array(), 'meta_data' => $this->getMetaData($invoice->getUser()), 'receipt_email' => $invoice->getEmail(), ); /* @var $item InvoiceItem */ foreach ($invoice->getItems() as $item) { $data['items'][] = array( 'name' => $item->item_title, 'description' => $item->item_description, 'price' => moneyRound($item->first_total/$item->qty), 'quantity' => $item->qty, ); } if ($invoice->first_shipping) { $data['shipping'] = $invoice->first_shipping; } if ($invoice->first_tax) { $data['tax'] = $invoice->first_tax; } $req->setBody(json_encode($data)); $resp = $req->send(); if($resp->getStatus() != 200 || !($body = $resp->getBody()) || !($ret = json_decode($body, true)) || empty($ret['checkout_url'])) { throw new Am_Exception_Paysystem("Bad response, Xrefs answers: " . $resp->getBody() . '=' . $resp->getStatus()); } $a = new Am_Paysystem_Action_Redirect($ret['checkout_url']); $result->setAction($a); } protected function getMetaData(User $user) { $meta = array(); $cfg = $this->getConfig('meta_fields'); if (!empty($cfg)) { foreach (explode("\n", str_replace("\r", "", $cfg)) as $str) { if (!$str) continue; list($k, $v) = explode("|", $str); if (!$v) continue; if (($value = $user->get($v)) || ($value = $user->data()->get($v))) { $meta[$k] = $value; } } } return $meta; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getActionName() == 'ipn3' || $this->getConfig('api_ver')) { return new Am_Paysystem_Transaction_Xfers3($this, $request, $response, $invokeArgs); } return new Am_Paysystem_Transaction_Xfers($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('SGD'); } } class Am_Paysystem_Transaction_Xfers extends Am_Paysystem_Transaction_Incoming { const STATUS_CANCELED = 'cancelled'; const STATUS_PAID = 'paid'; const STATUS_EXPIRED = 'expired'; public function findInvoiceId() { return $this->request->getFiltered('order_id'); } public function getUniqId() { return $this->request->getFiltered('txn_id'); } public function validateSource() { // validate if that is genuine POST coming from Xfers if (!$this->plugin->getConfig('dont_verify')) { $req = $this->plugin->createHttpRequest(); $domain = $this->plugin->getConfig('testing') ? Am_Paysystem_Xfers::SANDBOX_DOMAIN : Am_Paysystem_Xfers::LIVE_DOMAIN; $req->setConfig('ssl_verify_peer', false); $req->setConfig('ssl_verify_host', false); $req->setUrl('https://' . $domain . '/api/v2/payments/validate'); foreach ($this->request->getRequestOnlyParams() as $key => $value) $req->addPostParameter($key, $value); $req->setMethod(Am_HttpRequest::METHOD_POST); $resp = $req->send(); if ($resp->getStatus() != 200 || $resp->getBody() !== "VERIFIED") throw new Am_Exception_Paysystem("Wrong IPN received, Xrefs answers: " . $resp->getBody() . '=' . $resp->getStatus()); } return $this->request->getFiltered('api_key') == $this->getPlugin()->getConfig('api_key'); } public function validateStatus() { return $this->request->getFiltered('status') == self::STATUS_PAID; } public function validateTerms() { return $this->request->get('total_amount') == $this->invoice->first_total && $this->request->get('currency') == $this->invoice->currency; } } class Am_Paysystem_Transaction_Xfers3 extends Am_Paysystem_Transaction_Incoming { const STATUS_CANCELED = 'cancelled'; const STATUS_PAID = 'paid'; const STATUS_EXPIRED = 'expired'; public function findInvoiceId() { return $this->request->getFiltered('order_id'); } public function getUniqId() { return $this->request->getFiltered('txn_id'); } public function validateSource() { // validate if that is genuine POST coming from Xfers if (!$this->plugin->getConfig('dont_verify')) { $domain = $this->plugin->getConfig('testing') ? Am_Paysystem_Xfers::SANDBOX_DOMAIN : Am_Paysystem_Xfers::LIVE_DOMAIN; $req = $this->plugin->createHttpRequest(); $req->setUrl('https://' . $domain . '/api/v3/charges/' . $this->getUniqId() . '/validate'); $req->setMethod(Am_HttpRequest::METHOD_POST); $req->setConfig('ssl_verify_peer', false); $req->setConfig('ssl_verify_host', false); $req->setHeader(array( 'X-XFERS-USER-API-KEY' => $this->plugin->getConfig('api_key_v3'), 'Content-Type' => 'application/json' )); $data = array(); foreach ($this->request->getRequestOnlyParams() as $key => $value) { if(in_array($key, array('order_id', 'total_amount', 'currency', 'status'))) { $data[$key] = $value; } } $req->setBody(json_encode($data)); $resp = $req->send(); if($resp->getStatus() != 200 || !($body = $resp->getBody()) || !($ret = json_decode($body, true)) || $ret['msg'] !== 'VERIFIED') { throw new Am_Exception_Paysystem("Wrong IPN received, Xrefs answers: " . $resp->getBody() . '=' . $resp->getStatus()); } } return true; } public function validateStatus() { return $this->request->getFiltered('status') == self::STATUS_PAID; } public function validateTerms() { return $this->request->get('total_amount') == $this->invoice->first_total && $this->request->get('currency') == $this->invoice->currency; } } PK\b֨##"default/plugins/payment/mollie.phpnu[addText('api_key', 'class="el-wide"') ->setLabel('Mollie API Key'); } /** * @return Am_Rest_Client_Mollie */ function restClient() { $client = new Am_Rest_Client_Mollie(); $client->setKey($this->getConfig('api_key')); return $client; } /** * @param Invoice $invoice * @param Am_Mvc_Request $request * @param Am_Paysystem_Result $result */ function _process($invoice, $request, $result) { $user = $invoice->getUser(); if (!($customer_id = $user->data()->get(self::DATA_MOLLIE_CUSTOMER_ID))) { $customer = $this->restClient() ->customers() ->create(array( 'name' => $invoice->getName(), 'email' => $invoice->getEmail() )); $user->data() ->set(self::DATA_MOLLIE_CUSTOMER_ID, $customer_id = $customer['id']) ->update(); } $paymentReq = array( 'amount' => $invoice->first_total, 'description' => $invoice->getLineDescription(), 'redirectUrl' => $this->getReturnUrl(), 'webhookUrl' => $this->getPluginUrl('ipn'), 'metadata' => array('invoice' => $invoice->public_id), 'customerId' => $user->data()->get(self::DATA_MOLLIE_CUSTOMER_ID) ); if ($invoice->rebill_times) { $paymentReq['recurringType'] = 'first'; } $payment = $this->restClient() ->payments() ->create($paymentReq); if ($url = @$payment['links']['paymentUrl']) { $a = new Am_Paysystem_Action_Redirect($url); $result->setAction($a); } else { throw new Am_Exception_InternalError('No url was returned. Payment object: ' . print_r($payment, true)); } } function createTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Mollie($this, $request, $response, $invokeArgs); } public function getUserCancelUrl(Invoice $invoice) { if ($invoice->data()->get(self::DATA_MOLLIE_SUBSCRIPTION_ID)) { return parent::getUserCancelUrl($invoice); } } public function getAdminCancelUrl(Invoice $invoice) { if ($invoice->data()->get(self::DATA_MOLLIE_SUBSCRIPTION_ID)) { return parent::getAdminCancelUrl($invoice); } } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $cid = $invoice->data()->get(self::DATA_MOLLIE_CUSTOMER_ID); $sid = $invoice->data()->get(self::DATA_MOLLIE_SUBSCRIPTION_ID); $req = new Am_HttpRequest(Am_Rest_Client_Mollie::URL . "customers/{$cid}/subscriptions/{$sid}", Am_HttpRequest::METHOD_DELETE); $req->setHeader("Authorization: Bearer {$this->getConfig('api_key')}"); $l = $this->logOther('CANCEL', $req); $l->setInvoice($invoice); $resp = $req->send(); $l->add($resp); if ($resp->getStatus() == 200) { $result->setSuccess(); $invoice->setCancelled(true); } else { $result->setErrorMessages(); } } } class Am_Paysystem_Transaction_Mollie extends Am_Paysystem_Transaction_Incoming { protected $payment; function validate() { if ($id = $this->request->getFiltered('id')) { $this->payment = $this->getPlugin()->restClient()->payments()->get($id); $this->log->add($this->payment); } return parent::validate(); } function findInvoiceId() { if ($this->payment['recurringType'] == 'recurring' && $invoice = $this->getPlugin()->getDi()->invoiceTable ->findFirstByData(Am_Paysystem_Mollie::DATA_MOLLIE_SUBSCRIPTION_ID, $this->payment['subscriptionId'])) { return $invoice->public_id; } else { return @$this->payment['metadata']['invoice']; } } function getUniqId() { return @$this->payment['id']; } function validateSource() { return !empty($this->payment); } function validateStatus() { return true; } function validateTerms() { return true; } function processValidated() { switch (@$this->payment['status']) { case 'refunded': $this->invoice->addRefund($this, @$this->payment['id']); break; case 'charged_back' : $this->invoice->addChargeback($this, @$this->payment['id']); break; case 'paid': $this->invoice->addPayment($this); if ($this->payment['recurringType'] == 'first' && $this->invoice->rebill_times) { $p = new Am_Period($this->invoice->first_period); $startDate = $p->addTo('now'); $subscirption = array( 'description' => $this->invoice->getLineDescription(), 'amount' => $this->invoice->second_total, 'interval' => $this->getInterval($this->invoice->second_period), 'startDate' => $startDate, 'webhookUrl' => $this->getPlugin()->getPluginUrl('ipn') ); if ($this->invoice->rebill_times != Product::RECURRING_REBILLS) { $subscirption['times'] = $this->invoice->rebill_times; } $r = $this->getPlugin() ->restClient() ->setEndpoint('customers/' . $this->invoice->getUser()->data()->get(Am_Paysystem_Mollie::DATA_MOLLIE_CUSTOMER_ID) . '/subscriptions') ->create($subscirption); $this->log->add($r); $this->invoice->data()->set(Am_Paysystem_Mollie::DATA_MOLLIE_SUBSCRIPTION_ID, $r['id']); $this->invoice->data()->set(Am_Paysystem_Mollie::DATA_MOLLIE_CUSTOMER_ID, $r['customerId']); $this->invoice->save(); } break; } } function getInterval($int) { $p = new Am_Period($int); switch ($p->getUnit()) { case Am_Period::DAY : return sprintf('%s days', $p->getCount()); case Am_Period::MONTH : return sprintf('%s months', $p->getCount()); case Am_Period::YEAR : return sprintf('%s months', $p->getCount() * 12); } } } class Am_Rest_Client_Mollie extends Am_HttpRequest { const URL = 'https://api.mollie.nl/v1/'; protected $key, $endpoint; function setKey($key) { $this->key = $key; } function getKey() { return $this->key; } function setEndpoint($endpoint) { $this->endpoint = $endpoint; return $this; } function getEndpoint() { return $this->endpoint; } function __call($method, $object) { $this->setEndpoint($method); return $this; } function create($obj) { $this->setMethod(self::METHOD_POST); $this->setUrl(self::URL . $this->getEndpoint()); $this->setAuthHeader(); foreach ($obj as $k => $v) { $this->addPostParameter($k, $v); } $resp = $this->send(); if ($resp->getStatus() != 201) throw new Am_Rest_Client_Mollie_Exception("Object wasn't created. Status: " . $resp->getStatus() . " Response: " . $resp->getBody() . " Request: " . $this->getBody()); return json_decode($resp->getBody(), true); } function get($id) { $this->setMethod(self::METHOD_GET); $this->setUrl(self::URL . $this->getEndpoint() . '/' . $id); $this->setAuthHeader(); $resp = $this->send(); if ($resp->getStatus() != 200) throw new Am_Rest_Client_Mollie_Exception("Unable to fetch payment. Status: " . $resp->getStatus() . " Response: " . $resp->getBody()); return json_decode($resp->getBody(), true); } function setAuthHeader() { $this->setHeader('Authorization: Bearer ' . $this->getKey()); } } class Am_Rest_Client_Mollie_Exception extends Am_Exception { }PK\|&&+default/plugins/payment/pesapal/pesapal.phpnu[addText('consumer_key', array('size' => 40)) ->setLabel(___('Merchant Key')); $form->addText('consumer_secret', array('size' => 40)) ->setLabel(___('Merchant Secret')); } function getConsumer() { require_once dirname(__FILE__) . '/OAuth.php'; if(self::$consumer) return self::$consumer; self::$consumer = new OAuthConsumer($this->getConfig('consumer_key'), $this->getConfig('consumer_secret')); return self::$consumer; } function getMethod() { if(self::$method) return self::$method; self::$method = new OAuthSignatureMethod_HMAC_SHA1(); return self::$method; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $result->setAction( new Am_Paysystem_Action_Redirect( $this->getDi()->url( "payment/".$this->getId()."/confirm", array('id'=>$invoice->getSecureId($this->getId())), false) )); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Pesapal_Thanks($this, $request, $response, $invokeArgs); } public function onHourly() { foreach($this->getDi()->db->select("select d.id,d.value,i.public_id from ?_data d left join ?_invoice i on (d.id=i.invoice_id) where d.`table`='invoice' and d.`key` = 'pesapal_transaction_tracking_id'") as $row){ if(!empty($row['value'])){ $transaction = new Am_Paysystem_Transaction_Pesapal_Pending($this, $row); $transaction->setInvoice($this->getDi()->invoiceTable->load($row['id'])); $transaction->process(); } } } public function thanksAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $log = $this->logRequest($request); try { $transaction = $this->createThanksTransaction($request, $response, $invokeArgs); } catch (Am_Exception_Paysystem_NotImplemented $e) { $this->logError("[thanks] page handling is not implemented for this plugin. Define [createThanksTransaction] method in plugin"); throw $e; } $transaction->setInvoiceLog($log); if($request->get("pesapal_transaction_status") == Am_Paysystem_Transaction_Pesapal_Thanks::PENDING) { $invoice = $this->getDi()->invoiceTable->findFirstBy(array('public_id' => $transaction->findInvoiceId())); $invoice->data()->set('pesapal_transaction_tracking_id',$transaction->getUniqId())->update(); $view = new Am_View; $view->addScriptPath(dirname(__FILE__)); $response->setBody($view->render("payment-pesapal-pending.phtml")); return; } try { $transaction->process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { // ignore this error, as it happens in "thanks" transaction // we may have received IPN about the payment earlier } catch (Exception $e) { throw $e; $this->getDi()->errorLogTable->logException($e); throw Am_Exception_InputError(___("Error happened during transaction handling. Please contact website administrator")); } $log->setInvoice($transaction->getInvoice())->update(); $this->invoice = $transaction->getInvoice(); $response->setRedirect($this->getReturnUrl()); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { //if ($request->getActionName() == 'cron') return $this->onHourly(); if ($request->getActionName() == 'thanks') { return $this->thanksAction($request, $response, $invokeArgs); } $invoice = $this->getDi()->invoiceTable->findBySecureId($request->getFiltered('id'), $this->getId()); if (!$invoice) throw new Am_Exception_InputError(___("Sorry, seems you have used wrong link")); $u = $invoice->getUser(); $xml = new DOMDocument('1.0', 'utf-8'); $e = new DOMElement('PesapalDirectOrderInfo'); $el = $xml->appendChild($e); $el->setAttribute('xmlns:xsi','http://www.w3.org/2001/XMLSchemainstance'); $el->setAttribute('xmlns:xsd','http://www.w3.org/2001/XMLSchema'); $el->setAttribute('Amount',number_format($invoice->first_total, 2)); $el->setAttribute('Description',$invoice->getLineDescription()); $el->setAttribute('Code',''); $el->setAttribute('Type','MERCHANT'); $el->setAttribute('PaymentMethod',''); $el->setAttribute('Reference',$invoice->public_id); $el->setAttribute('FirstName',$u->name_f); $el->setAttribute('LastName',$u->name_l); $el->setAttribute('Email',$u->email); $el->setAttribute('PhoneNumber',$u->phone); $el->setAttribute('UserName',$u->email); $el->setAttribute('Currency',$invoice->currency); $el->setAttribute('xmlns','http://www.pesapal.com'); //post transaction to pesapal $consumer = $this->getConsumer(); $token = $params = NULL; $method = $this->getMethod(); $iframe_src = OAuthRequest::from_consumer_and_token($consumer, $token, "GET", self::URL, $params); $iframe_src->set_parameter("oauth_callback", $this->getPluginUrl('thanks')); $iframe_src->set_parameter("pesapal_request_data", $s=htmlentities($xml->saveXML())); $iframe_src->sign_request($method, $consumer, $token); $view = new Am_View; $view->addScriptPath(dirname(__FILE__)); $view->invoice = $invoice; $view->iframe_src = $iframe_src; $response->setBody($view->render("payment-pesapal-confirm.phtml")); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Pesapal($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return <<request->get('pesapal_transaction_tracking_id'); } function validateTerms() { return true; } function getInvoice() { return $this->invoice; } public function findInvoiceId() { return $this->request->get("pesapal_merchant_reference"); } public function validateStatus() { return $this->request->get("pesapal_transaction_status")==self::COMPLETED; } } class Am_Paysystem_Transaction_Pesapal_Pending extends Am_Paysystem_Transaction_Abstract { protected $vars; const CHECK_URL = "https://www.pesapal.com/api/QueryPaymentStatus"; public function __construct(Am_Paysystem_Abstract $plugin, array $vars) { $this->vars = $vars; parent::__construct($plugin); } public function getUniqId() { return $this->vars['value']; } public function validate() { $consumer = $this->plugin->getConsumer(); $token = $params = NULL; $method = $this->plugin->getMethod(); $st = OAuthRequest::from_consumer_and_token($consumer, $token, "GET", self::CHECK_URL, $params); $st->set_parameter("pesapal_merchant_reference", $vars['public_id']); $st->set_parameter("pesapal_transaction_tracking_id", $vars['value']); $st->sign_request($method, $consumer, $token); $req = $this->plugin->createHttpRequest(); $resp = $req->setUrl($st->to_url())->send()->getBody(); parse_str($resp,$vars); if($vars['pesapal_response_data']==Am_Paysystem_Transaction_Pesapal_Thanks::COMPLETED) return true; } public function processValidated() { $this->invoice->addPayment($this); $this->plugin->getDi()->getDbService()->query("DELETE from ?_data where `table`='invoice' AND `key`='pesapal_transaction_tracking_id' and id=?",$this->vars['id']); } }PK\g`Y`Y)default/plugins/payment/pesapal/OAuth.phpnu[key = $key; $this->secret = $secret; $this->callback_url = $callback_url; } function __toString() { return "OAuthConsumer[key=$this->key,secret=$this->secret]"; } } class OAuthToken { // access tokens and request tokens public $key; public $secret; /** * key = the token * secret = the token secret */ function __construct($key, $secret) { $this->key = $key; $this->secret = $secret; } /** * generates the basic string serialization of a token that a server * would respond to request_token and access_token calls with */ function to_string() { return "oauth_token=" . OAuthUtil::urlencode_rfc3986($this->key) . "&oauth_token_secret=" . OAuthUtil::urlencode_rfc3986($this->secret); } function __toString() { return $this->to_string(); } } class OAuthSignatureMethod { public function check_signature(&$request, $consumer, $token, $signature) { $built = $this->build_signature($request, $consumer, $token); return $built == $signature; } } class OAuthSignatureMethod_HMAC_SHA1 extends OAuthSignatureMethod { function get_name() { return "HMAC-SHA1"; } public function build_signature($request, $consumer, $token) { $base_string = $request->get_signature_base_string(); $request->base_string = $base_string; $key_parts = array( $consumer->secret, ($token) ? $token->secret : "" ); $key_parts = OAuthUtil::urlencode_rfc3986($key_parts); $key = implode('&', $key_parts); return base64_encode(hash_hmac('sha1', $base_string, $key, true)); } } class OAuthSignatureMethod_PLAINTEXT extends OAuthSignatureMethod { public function get_name() { return "PLAINTEXT"; } public function build_signature($request, $consumer, $token) { $sig = array( OAuthUtil::urlencode_rfc3986($consumer->secret) ); if ($token) { array_push($sig, OAuthUtil::urlencode_rfc3986($token->secret)); } else { array_push($sig, ''); } $raw = implode("&", $sig); // for debug purposes $request->base_string = $raw; return OAuthUtil::urlencode_rfc3986($raw); } } class OAuthSignatureMethod_RSA_SHA1 extends OAuthSignatureMethod { public function get_name() { return "RSA-SHA1"; } protected function fetch_public_cert(&$request) { // not implemented yet, ideas are: // (1) do a lookup in a table of trusted certs keyed off of consumer // (2) fetch via http using a url provided by the requester // (3) some sort of specific discovery code based on request // // either way should return a string representation of the certificate throw Exception("fetch_public_cert not implemented"); } protected function fetch_private_cert(&$request) { // not implemented yet, ideas are: // (1) do a lookup in a table of trusted certs keyed off of consumer // // either way should return a string representation of the certificate throw Exception("fetch_private_cert not implemented"); } public function build_signature(&$request, $consumer, $token) { $base_string = $request->get_signature_base_string(); $request->base_string = $base_string; // Fetch the private key cert based on the request $cert = $this->fetch_private_cert($request); // Pull the private key ID from the certificate $privatekeyid = openssl_get_privatekey($cert); // Sign using the key $ok = openssl_sign($base_string, $signature, $privatekeyid); // Release the key resource openssl_free_key($privatekeyid); return base64_encode($signature); } public function check_signature(&$request, $consumer, $token, $signature) { $decoded_sig = base64_decode($signature); $base_string = $request->get_signature_base_string(); // Fetch the public key cert based on the request $cert = $this->fetch_public_cert($request); // Pull the public key ID from the certificate $publickeyid = openssl_get_publickey($cert); // Check the computed signature against the one passed in the query $ok = openssl_verify($base_string, $decoded_sig, $publickeyid); // Release the key resource openssl_free_key($publickeyid); return $ok == 1; } } class OAuthRequest { private $parameters; private $http_method; private $http_url; // for debug purposes public $base_string; public static $version = '1.0'; public static $POST_INPUT = 'php://input'; function __construct($http_method, $http_url, $parameters=NULL) { @$parameters or $parameters = array(); $this->parameters = $parameters; $this->http_method = $http_method; $this->http_url = $http_url; } /** * attempt to build up a request from what was passed to the server */ public static function from_request($http_method=NULL, $http_url=NULL, $parameters=NULL) { $scheme = (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") ? 'http' : 'https'; @$http_url or $http_url = $scheme . '://' . $_SERVER['HTTP_HOST'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['REQUEST_URI']; @$http_method or $http_method = $_SERVER['REQUEST_METHOD']; // We weren't handed any parameters, so let's find the ones relevant to // this request. // If you run XML-RPC or similar you should use this to provide your own // parsed parameter-list if (!$parameters) { // Find request headers $request_headers = OAuthUtil::get_headers(); // Parse the query-string to find GET parameters $parameters = OAuthUtil::parse_parameters($_SERVER['QUERY_STRING']); // It's a POST request of the proper content-type, so parse POST // parameters and add those overriding any duplicates from GET if ($http_method == "POST" && @strstr($request_headers["Content-Type"], "application/x-www-form-urlencoded") ) { $post_data = OAuthUtil::parse_parameters( file_get_contents(self::$POST_INPUT) ); $parameters = array_merge($parameters, $post_data); } // We have a Authorization-header with OAuth data. Parse the header // and add those overriding any duplicates from GET or POST if (@substr($request_headers['Authorization'], 0, 6) == "OAuth ") { $header_parameters = OAuthUtil::split_header( $request_headers['Authorization'] ); $parameters = array_merge($parameters, $header_parameters); } } return new OAuthRequest($http_method, $http_url, $parameters); } /** * pretty much a helper function to set up the request */ public static function from_consumer_and_token($consumer, $token, $http_method, $http_url, $parameters=NULL) { @$parameters or $parameters = array(); $defaults = array("oauth_version" => OAuthRequest::$version, "oauth_nonce" => OAuthRequest::generate_nonce(), "oauth_timestamp" => OAuthRequest::generate_timestamp(), "oauth_consumer_key" => $consumer->key); if ($token) $defaults['oauth_token'] = $token->key; $parameters = array_merge($defaults, $parameters); return new OAuthRequest($http_method, $http_url, $parameters); } public function set_parameter($name, $value, $allow_duplicates = true) { if ($allow_duplicates && isset($this->parameters[$name])) { // We have already added parameter(s) with this name, so add to the list if (is_scalar($this->parameters[$name])) { // This is the first duplicate, so transform scalar (string) // into an array so we can add the duplicates $this->parameters[$name] = array($this->parameters[$name]); } $this->parameters[$name][] = $value; } else { $this->parameters[$name] = $value; } } public function get_parameter($name) { return isset($this->parameters[$name]) ? $this->parameters[$name] : null; } public function get_parameters() { return $this->parameters; } public function unset_parameter($name) { unset($this->parameters[$name]); } /** * The request parameters, sorted and concatenated into a normalized string. * @return string */ public function get_signable_parameters() { // Grab all parameters $params = $this->parameters; // Remove oauth_signature if present // Ref: Spec: 9.1.1 ("The oauth_signature parameter MUST be excluded.") if (isset($params['oauth_signature'])) { unset($params['oauth_signature']); } return OAuthUtil::build_http_query($params); } /** * Returns the base string of this request * * The base string defined as the method, the url * and the parameters (normalized), each urlencoded * and the concated with &. */ public function get_signature_base_string() { $parts = array( $this->get_normalized_http_method(), $this->get_normalized_http_url(), $this->get_signable_parameters() ); $parts = OAuthUtil::urlencode_rfc3986($parts); return implode('&', $parts); } /** * just uppercases the http method */ public function get_normalized_http_method() { return strtoupper($this->http_method); } /** * parses the url and rebuilds it to be * scheme://host/path */ public function get_normalized_http_url() { $parts = parse_url($this->http_url); $port = @$parts['port']; $scheme = $parts['scheme']; $host = $parts['host']; $path = @$parts['path']; $port or $port = ($scheme == 'https') ? '443' : '80'; if (($scheme == 'https' && $port != '443') || ($scheme == 'http' && $port != '80')) { $host = "$host:$port"; } return "$scheme://$host$path"; } /** * builds a url usable for a GET request */ public function to_url() { $post_data = $this->to_postdata(); $out = $this->get_normalized_http_url(); if ($post_data) { $out .= '?'.$post_data; } return $out; } /** * builds the data one would send in a POST request */ public function to_postdata() { return OAuthUtil::build_http_query($this->parameters); } /** * builds the Authorization: header */ public function to_header() { $out ='Authorization: OAuth realm=""'; $total = array(); foreach ($this->parameters as $k => $v) { if (substr($k, 0, 5) != "oauth") continue; if (is_array($v)) { throw new OAuthException('Arrays not supported in headers'); } $out .= ',' . OAuthUtil::urlencode_rfc3986($k) . '="' . OAuthUtil::urlencode_rfc3986($v) . '"'; } return $out; } public function __toString() { return $this->to_url(); } public function sign_request($signature_method, $consumer, $token) { $this->set_parameter( "oauth_signature_method", $signature_method->get_name(), false ); $signature = $this->build_signature($signature_method, $consumer, $token); $this->set_parameter("oauth_signature", $signature, false); } public function build_signature($signature_method, $consumer, $token) { $signature = $signature_method->build_signature($this, $consumer, $token); return $signature; } /** * util function: current timestamp */ private static function generate_timestamp() { return time(); } /** * util function: current nonce */ private static function generate_nonce() { mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up. $charid = strtoupper(md5(uniqid(rand(), true))); $hyphen = chr(45);// "-" $uuid = chr(123)// "{" .substr($charid, 0, 8).$hyphen .substr($charid, 8, 4).$hyphen .substr($charid,12, 4).$hyphen .substr($charid,16, 4).$hyphen .substr($charid,20,12) .chr(125);// "}" return $uuid; } } class OAuthServer { protected $timestamp_threshold = 300; // in seconds, five minutes protected $version = 1.0; // hi blaine protected $signature_methods = array(); protected $data_store; function __construct($data_store) { $this->data_store = $data_store; } public function add_signature_method($signature_method) { $this->signature_methods[$signature_method->get_name()] = $signature_method; } // high level functions /** * process a request_token request * returns the request token on success */ public function fetch_request_token(&$request) { $this->get_version($request); $consumer = $this->get_consumer($request); // no token required for the initial token request $token = NULL; $this->check_signature($request, $consumer, $token); $new_token = $this->data_store->new_request_token($consumer); return $new_token; } /** * process an access_token request * returns the access token on success */ public function fetch_access_token(&$request) { $this->get_version($request); $consumer = $this->get_consumer($request); // requires authorized request token $token = $this->get_token($request, $consumer, "request"); $this->check_signature($request, $consumer, $token); $new_token = $this->data_store->new_access_token($token, $consumer); return $new_token; } /** * verify an api call, checks all the parameters */ public function verify_request(&$request) { $this->get_version($request); $consumer = $this->get_consumer($request); $token = $this->get_token($request, $consumer, "access"); $this->check_signature($request, $consumer, $token); return array($consumer, $token); } // Internals from here /** * version 1 */ private function get_version(&$request) { $version = $request->get_parameter("oauth_version"); if (!$version) { $version = 1.0; } if ($version && $version != $this->version) { throw new OAuthException("OAuth version '$version' not supported"); } return $version; } /** * figure out the signature with some defaults */ private function get_signature_method(&$request) { $signature_method = @$request->get_parameter("oauth_signature_method"); if (!$signature_method) { $signature_method = "PLAINTEXT"; } if (!in_array($signature_method, array_keys($this->signature_methods))) { throw new OAuthException( "Signature method '$signature_method' not supported " . "try one of the following: " . implode(", ", array_keys($this->signature_methods)) ); } return $this->signature_methods[$signature_method]; } /** * try to find the consumer for the provided request's consumer key */ private function get_consumer(&$request) { $consumer_key = @$request->get_parameter("oauth_consumer_key"); if (!$consumer_key) { throw new OAuthException("Invalid consumer key"); } $consumer = $this->data_store->lookup_consumer($consumer_key); if (!$consumer) { throw new OAuthException("Invalid consumer"); } return $consumer; } /** * try to find the token for the provided request's token key */ private function get_token(&$request, $consumer, $token_type="access") { $token_field = @$request->get_parameter('oauth_token'); $token = $this->data_store->lookup_token( $consumer, $token_type, $token_field ); if (!$token) { throw new OAuthException("Invalid $token_type token: $token_field"); } return $token; } /** * all-in-one function to check the signature on a request * should guess the signature method appropriately */ private function check_signature(&$request, $consumer, $token) { // this should probably be in a different method $timestamp = @$request->get_parameter('oauth_timestamp'); $nonce = @$request->get_parameter('oauth_nonce'); $this->check_timestamp($timestamp); $this->check_nonce($consumer, $token, $nonce, $timestamp); $signature_method = $this->get_signature_method($request); $signature = $request->get_parameter('oauth_signature'); $valid_sig = $signature_method->check_signature( $request, $consumer, $token, $signature ); if (!$valid_sig) { throw new OAuthException("Invalid signature"); } } /** * check that the timestamp is new enough */ private function check_timestamp($timestamp) { // verify that timestamp is recentish $now = time(); if ($now - $timestamp > $this->timestamp_threshold) { throw new OAuthException( "Expired timestamp, yours $timestamp, ours $now" ); } } /** * check that the nonce is not repeated */ private function check_nonce($consumer, $token, $nonce, $timestamp) { // verify that the nonce is uniqueish $found = $this->data_store->lookup_nonce( $consumer, $token, $nonce, $timestamp ); if ($found) { throw new OAuthException("Nonce already used: $nonce"); } } } class OAuthDataStore { function lookup_consumer($consumer_key) { // implement me } function lookup_token($consumer, $token_type, $token) { // implement me } function lookup_nonce($consumer, $token, $nonce, $timestamp) { // implement me } function new_request_token($consumer) { // return a new token attached to this consumer } function new_access_token($token, $consumer) { // return a new access token attached to this consumer // for the user associated with this token if the request token // is authorized // should also invalidate the request token } } class OAuthUtil { public static function urlencode_rfc3986($input) { if (is_array($input)) { return array_map(array('OAuthUtil', 'urlencode_rfc3986'), $input); } else if (is_scalar($input)) { return str_replace( '+', ' ', str_replace('%7E', '~', rawurlencode($input)) ); } else { return ''; } } // This decode function isn't taking into consideration the above // modifications to the encoding process. However, this method doesn't // seem to be used anywhere so leaving it as is. public static function urldecode_rfc3986($string) { return urldecode($string); } // Utility function for turning the Authorization: header into // parameters, has to do some unescaping // Can filter out any non-oauth parameters if needed (default behaviour) public static function split_header($header, $only_allow_oauth_parameters = true) { $pattern = '/(([-_a-z]*)=("([^"]*)"|([^,]*)),?)/'; $offset = 0; $params = array(); while (preg_match($pattern, $header, $matches, PREG_OFFSET_CAPTURE, $offset) > 0) { $match = $matches[0]; $header_name = $matches[2][0]; $header_content = (isset($matches[5])) ? $matches[5][0] : $matches[4][0]; if (preg_match('/^oauth_/', $header_name) || !$only_allow_oauth_parameters) { $params[$header_name] = OAuthUtil::urldecode_rfc3986($header_content); } $offset = $match[1] + strlen($match[0]); } if (isset($params['realm'])) { unset($params['realm']); } return $params; } // helper to try to sort out headers for people who aren't running apache public static function get_headers() { if (function_exists('apache_request_headers')) { // we need this to get the actual Authorization: header // because apache tends to tell us it doesn't exist return apache_request_headers(); } // otherwise we don't have apache and are just going to have to hope // that $_SERVER actually contains what we need $out = array(); foreach ($_SERVER as $key => $value) { if (substr($key, 0, 5) == "HTTP_") { // this is chaos, basically it is just there to capitalize the first // letter of every word that is not an initial HTTP and strip HTTP // code from przemek $key = str_replace( " ", "-", ucwords(strtolower(str_replace("_", " ", substr($key, 5)))) ); $out[$key] = $value; } } return $out; } // This function takes a input like a=b&a=c&d=e and returns the parsed // parameters like this // array('a' => array('b','c'), 'd' => 'e') public static function parse_parameters( $input ) { if (!isset($input) || !$input) return array(); $pairs = explode('&', $input); $parsed_parameters = array(); foreach ($pairs as $pair) { $split = explode('=', $pair, 2); $parameter = OAuthUtil::urldecode_rfc3986($split[0]); $value = isset($split[1]) ? OAuthUtil::urldecode_rfc3986($split[1]) : ''; if (isset($parsed_parameters[$parameter])) { // We have already recieved parameter(s) with this name, so add to the list // of parameters with this name if (is_scalar($parsed_parameters[$parameter])) { // This is the first duplicate, so transform scalar (string) into an array // so we can add the duplicates $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]); } $parsed_parameters[$parameter][] = $value; } else { $parsed_parameters[$parameter] = $value; } } return $parsed_parameters; } public static function build_http_query($params) { if (!$params) return ''; // Urlencode both keys and values $keys = OAuthUtil::urlencode_rfc3986(array_keys($params)); $values = OAuthUtil::urlencode_rfc3986(array_values($params)); $params = array_combine($keys, $values); // Parameters are sorted by name, using lexicographical byte value ordering. // Ref: Spec: 9.1.1 (1) uksort($params, 'strcmp'); $pairs = array(); foreach ($params as $parameter => $value) { if (is_array($value)) { // If two or more parameters share the same name, they are sorted by their value // Ref: Spec: 9.1.1 (1) natsort($value); foreach ($value as $duplicate_value) { $pairs[] = $parameter . '=' . $duplicate_value; } } else { $pairs[] = $parameter . '=' . $value; } } // For each parameter, the name is separated from the corresponding value by an '=' character (ASCII code 61) // Each name-value pair is separated by an '&' character (ASCII code 38) return implode('&', $pairs); } } PK\kk=default/plugins/payment/pesapal/payment-pesapal-pending.phtmlnu[setLayout('layout.phtml'); ?>
      PK\o>=default/plugins/payment/pesapal/payment-pesapal-confirm.phtmlnu[setLayout('layout.phtml'); if (empty($btnText)) $btnText = ___("Make Payment"); include $this->_script('_receipt.phtml'); ?>
      PK\L~##"default/plugins/payment/paypro.phpnu[billingPlanTable->customFields()->add( new Am_CustomFieldText( 'paypro_product_id', "Paypro product ID", "" , array(/* ,'required' */) )); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function canAutoCreate() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addAdvCheckbox('new') ->setId('protocol-version') ->setLabel('Use New Protocol'); $form->addInteger('product_id', array('size' => 20)) ->setLabel('PayPro Product Id'); $form->setDefault('new', 1); $form->addText('key', array('size' => 20, 'rel' => 'protocol-old')) ->setLabel('PayPro Product Variable Price Hash'); $form->addText('enc_key', array('class' => 'el-wide', 'rel' => 'protocol-new')) ->setLabel("Encryption key\n" . "Key must be length 32 symbols"); $form->addText('enc_vector', array('class' => 'el-wide', 'rel' => 'protocol-new')) ->setLabel("Encryption init. vector\n" . "Initialization vector must be length 16 symbols"); $g = $form->addGroup() ->setLabel('Use Test Mode') ->setSeparator(' '); $g->addAdvcheckbox('testing', array('id' => 'testing')) ->setLabel('Use Test Mode'); $g->addText('secret_key', array( 'id' => 'secret_key', 'placeholder' => 'Secret Key')); $form->addScript() ->setScript(<<getConfig('key'); $data = ""; $td = mcrypt_module_open('des', '', 'ecb', ''); $ckey = $key; $iv = $key; mcrypt_generic_init($td, $ckey, $iv); $data = mcrypt_generic($td, $str); mcrypt_generic_deinit($td); mcrypt_module_close($td); return $data; } function encrypt($data) { //default padding is not compliant with paypro implementation $l = strlen($data); $pad = 16 - $l % 16; $data = str_pad($data, $l + $pad, chr($pad)); return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $this->getConfig('enc_key'), $data, MCRYPT_MODE_CBC, $this->getConfig('enc_vector')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $id = $this->invoice->getSecureId("THANKS"); $desc = array(); foreach ($invoice->getItems() as $it) if ($it->first_total > 0) $desc[] = $it->item_title; $desc = implode(',', $desc); $desc .= ". (invoice: $id)"; $name = $invoice->getLineDescription(); if ($this->getConfig('new')) { $data = array( 'Name' => $name, 'Description' => $desc, ); $data['Price'][$invoice->currency]['Amount'] = $invoice->first_total; $data = http_build_query($data); $a = new Am_Paysystem_Action_Redirect(self::URL_NEW); $params = array( 'products[1][id]' => current(array_filter(array($invoice->getItem(0)->getBillingPlanData('paypro_product_id'), $this->getConfig('product_id')))), 'products[1][data]' => base64_encode($this->encrypt($data)), 'currency' => $invoice->currency, 'billing-first-name' => $invoice->getFirstName(), 'billing-last-name' => $invoice->getLastName(), 'billing-email' => $invoice->getEmail(), 'billing-contact-phone' => $invoice->getPhone(), 'billing-country' => $invoice->getCountry() == 'GB' ? 'united kingdom' : $invoice->getCountry(), 'billing-state' => $invoice->getState(), 'billing-city' => $invoice->getCity(), 'billing-zip' => $invoice->getZip(), 'billing-address' => $invoice->getStreet(), 'x-invoice' => $invoice->public_id ); if ($this->getConfig('testing')) { $params['use-test-mode'] = 'true'; $params['secret-key'] = $this->getConfig('secret_key'); } foreach ($params as $k => $v) { $a->addParam($k, $v); } $a->filterEmpty(); } else { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->products = current(array_filter(array($invoice->getItem(0)->getBillingPlanData('paypro_product_id'), $this->getConfig('product_id')))); $a->hash = base64_encode($this->getHash("price={$invoice->first_total}-{$invoice->currency}^^^name=$name^^^desc=$desc")); ; $a->CustomField1 = $invoice->public_id; $a->firstname = $invoice->getFirstName(); $a->Lastname = $invoice->getLastName(); $a->Email = $invoice->getEmail(); $a->Address = $invoice->getStreet(); $a->City = $invoice->getCity(); $a->Country = $invoice->getCountry() == 'GB' ? 'united kingdom' : $invoice->getCountry(); $a->State = $invoice->getState(); $a->Zipcode = $invoice->getZip(); $a->Phone = $invoice->getPhone(); } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paypro($this, $request, $response, $invokeArgs); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $refund = $this->getPluginUrl('refund'); return << 'CUSTOMER_FIRST_NAME', 'name_l' => 'CUSTOMER_LAST_NAME', 'email' => 'CUSTOMER_EMAIL', 'user_external_id' => 'CUSTOMER_ID', 'invoice_external_id' => 'CUSTOMER_EMAIL', ); public function autoCreateGetProducts() { $item_name = $this->request->get('PRODUCT_ID'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('paypro_product_id', $item_name); if ($billing_plan) return array($billing_plan->getProduct()); } public function validateSource() { return true; } public function validateStatus() { return !$this->request->get('IS_DELAYED_PAYMENT'); } public function validateTerms() { return true; // terms are signed! } public function getUniqId() { return $this->request->get('ORDER_ID'); } public function findInvoiceId() { $id = $this->request->getParam('CUSTOM_FIELD1'); if (!$id) { $cf = $this->request->getParam('ORDER_CUSTOM_FIELDS'); if (preg_match('/x-invoice=(.*)(,|$)/', $cf, $m)) { $id = $m[1]; } elseif (preg_match('/x-CustomField1=(.*)(,|$)/', $cf, $m)) { $id = $m[1]; } } return $id; } public function processValidated() { if ($this->request->get('REFUND') > 0 || in_array($this->request->get('IPN_TYPE_ID'), array( 2, //OrderRefunded 3, //OrderChargedBack 5 //OrderPartiallyRefunded ))) { if ($this->request->get('IPN_TYPE_ID') == 3) {//OrderChargedBack $this->invoice->addChargeback($this, $this->request->get('ORDER_ID')); } else { $this->invoice->addRefund($this, $this->request->get('ORDER_ID')); } } elseif ($this->request->get('ORDER_STATUS_ID') == 5) { $this->invoice->addPayment($this); } } } PK\5!default/plugins/payment/ccnow.phpnu[addText('login') ->setLabel('CCNow Client ID') ->addRule('required'); $form->addText('key') ->setLabel('Activation Key') ->addRule('required'); $form->addAdvCheckbox('testmode') ->setLabel('Is Test Mode?'); } public function isNotAcceptableForInvoice(\Invoice $invoice) { if($invoice->rebill_times && ($invoice->first_period != $invoice->second_period)) return array(___ ("This payment system doesn't support Trial Periods")); return parent::isNotAcceptableForInvoice($invoice); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL_LIVE); $result->setAction($a); $sequence = rand(1, 1000); $vars = array( 'x_version' => '1.0', 'x_login' => $this->getConfig('login'), 'x_invoice_num' => $invoice->public_id, 'x_method' => $this->getConfig('testmode') ? 'TEST' : 'NONE', 'x_name' => $invoice->getName(), 'x_address' => $invoice->getStreet(), 'x_address2' => $invoice->getStreet2(), 'x_city' => $invoice->getCity(), 'x_country' => $invoice->getCountry(), 'x_state' => $invoice->getState(), 'x_zip' => $invoice->getZip(), 'x_email' => $invoice->getEmail(), 'x_currency_code' => $invoice->currency, 'x_amount' => $price = sprintf('%.2f', $invoice->first_total), 'x_tax_amount' => $tprice = sprintf('%.2f', $invoice->first_tax), 'x_fp_sequence' => $sequence, 'x_fp_arg_list' => 'x_login^x_fp_arg_list^x_fp_sequence^x_amount^x_currency_code', 'x_fp_hash' => '', 'x_fp_hash' => md5($q = $this->getConfig('login')."^x_login^x_fp_arg_list^x_fp_sequence^x_amount^x_currency_code^".$sequence."^".$price."^".$invoice->currency."^".$this->getConfig('key')) ); foreach ($invoice->getItems() as $kk => $item) { $k = $kk+1; $vars['x_product_sku_'.$k] = $item->item_id; $vars['x_product_title_'.$k] = $item->item_title; $vars['x_product_quantity_'.$k] = $item->qty; $vars['x_product_unitprice_'.$k] = $item->first_total; $vars['x_product_url_'.$k] = ROOT_URL; } if($invoice->rebill_times){ $vars['x_subscription_type'] = 'A'; $vars['x_subscription_freq'] = strtoupper($invoice->second_period); if($invoice->rebill_times < 99999) $vars['x_subscription_max'] = $invoice->rebill_times; } foreach($vars as $k => $v) $a->addParam($k, $v); $result->setAction($a); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return <<request->get('x_status') == 'received'; } public function findInvoiceId() { return $this->request->get('x_invoice_num'); } public function validateStatus() { return true; } public function getUniqId() { return $this->request->get('x_orderid'); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('x_amount')); return true; } }PK\#.&&&default/plugins/payment/fastspring.phpnu[addText('company') ->setLabel("Company Name\n" . 'your Company name as registered at FastSpring'); $form->addText('key') ->setLabel("Private Security Key\n" . 'FastSpring -> Account -> Notification Configuration -> Order Notification -> Security'); $form->addText('api_user') ->setLabel("API Username\n" . 'used to handle cancellations'); $form->addText('api_pass') ->setLabel("API Password\n" . 'used to handle cancellations'); $form->addAdvCheckbox("instant") ->setLabel("Instant order process\n" . 'leave it disabled for default product pages'); $form->addAdvCheckbox("testing") ->setLabel('Test Mode'); $form->addAdvcheckbox('doc_mode') ->setLabel("Digital Only Condensed mode\n" . 'leave it unchecked if you are not sure'); } public function getSupportedCurrencies() { return array('AUD', 'CAD', 'CHF', 'DKK', 'EUR', 'GBP', 'HKD', 'JPY', 'NZD', 'SGD', 'USD'); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('fastspring_product_id', "FastSpring Product ID", "You can get an ID from your FastSpring account -> Products and Settings -> Product Pages -> Option 1: View Product Detail Page
      For example ID is 'testmembership' for an URL http://sites.fastspring.com/your_company/product/testmembership")); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('fastspring_product_name', "FastSpring Product Name", "You can get Name from your FastSpring account -> Products and Settings -> Product Catalog")); } function getActionUrl(Invoice $invoice) { $url = "https://sites.fastspring.com/%s/product/%s"; if ($this->getConfig('instant') == 1) $url = "https://sites.fastspring.com/%s/instant/%s"; return sprintf($url, $this->getConfig('company'), $invoice->getItem(0)->getBillingPlanData('fastspring_product_id')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if ($this->getConfig('instant') == 1) { $a = new Am_Paysystem_Action_Redirect($this->getActionUrl($invoice)); } elseif ($this->getConfig('doc_mode')) { $a = new Am_Paysystem_Action_Form("https://sites.fastspring.com/".$this->getConfig('company')."/product/".$invoice->getItem(0)->getBillingPlanData('fastspring_product_id')); } else { $a = new Am_Paysystem_Action_Form("https://sites.fastspring.com/".$this->getConfig('company')."/api/order"); $a->operation = 'create'; $a->destination = 'checkout'; $i=1; foreach($invoice->getItems() as $item) { $path = "product_{$i}_path"; $quantity = "product_{$i}_quantity"; $a->{$path} = '/'.$item->getBillingPlanData('fastspring_product_id'); $a->{$quantity} = $item->qty; $i++; } } $a->contact_fname = $invoice->getFirstName(); $a->contact_lname = $invoice->getLastName(); //$a->contact_company = ''; $a->contact_email = $invoice->getEmail(); $a->contact_phone = $invoice->getPhone(); $a->referrer = $invoice->public_id; if($this->getConfig('testing')){ $a->mode = 'test'; $a->member = 'new'; // $a->sessionOption = 'new'; } $coupon = $invoice->getCoupon()->code; if ($coupon) $a->coupon = $coupon; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Fastspring($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme(){ return <<FastSpring plugin installation 1. Configure plugin at aMember CP -> Setup/Configuration -> FastSpring 2. Configure FastSpring Product ID/Name at aMember CP -> Manage Products -> ->Billing Plans Please note that in order for integration to work, Product Name should not have spaces included. 4. Configure Remote Server URL in your FastSpring account (NOTIFY -> Add Notification Rule) Format: HTTP Remote Server Call Type: Order Notification Remote Server URL: %root_surl%/payment/fastspring/ipn Optionally, after clicking 'Next' button you can add following 'HTTP Parameters'. Name: SubscriptionURL Value: #{order.allItems[0].subscription.url.detail} Name: OrderReference2 Value: #{order.allItems[0].subscription.reference} Name: OrderReferrer2 Value: #{order.allItems[0].subscription.referrer} 5. Run a test transaction to ensure everything is working correctly. Note: You can setup in FastSpring the same coupon code as in aMember. CUT; } function canAutoCreate() { return true; } function getUserCancelUrl(Invoice $invoice) { $customerUrl = ''; $SubscriptionURL = $invoice->data()->get('SubscriptionURL'); $OrderReference = $invoice->data()->get('OrderReference2'); if ($SubscriptionURL != ''){ $customerUrl = $SubscriptionURL; } elseif ($OrderReference != ''){ $url = sprintf("https://api.fastspring.com/company/%s/subscription/%s?user=%s&pass=%s", $this->getConfig('company'), $OrderReference, $this->getConfig('api_user'), $this->getConfig('api_pass')); $request = new Am_HttpRequest($url); $response = $request->send(); $body = $response->getBody(); if (strpos($body, "customerUrl; } else { $this->logResponse($body); } } return $customerUrl; } } class Am_Paysystem_Transaction_Fastspring extends Am_Paysystem_Transaction_Incoming{ protected $_autoCreateMap = array( 'name_f' => 'CustomerFirstName', 'name_l' => 'CustomerLastName', 'phone' => 'phone', 'country' => 'AddressCountry', 'street' => 'AddressStreet1', 'state' => 'AddressRegion', 'email' => 'CustomerEmail', 'zip' => 'AddressPostalCode', 'user_external_id' => 'CustomerEmail', 'invoice_external_id' => array( 'OrderReference', 'OrderReference2' ) ); public function getUniqId() { return $this->request->get("OrderReference") ? $this->request->get("OrderReference") : $this->request->get("OrderID"); } public function findInvoiceId() { return $this->request->get("OrderReferrer"); } public function validateSource() { if(md5($this->request->get('security_data').$this->getPlugin()->getConfig('key')) != $this->request->get('security_hash')) throw new Am_Exception_Paysystem_TransactionSource('Received security hash is not correct'); return true; } public function validateStatus() { if($this->request->get('OrderIsTest') == 'true' && !$this->getPlugin()->getConfig('testing')){ throw new Am_Exception_Paysystem_TransactionInvalid('Test IPN received but test mode is not enabled'); } return true; } public function validateTerms() { /** * @todo Add real validation here; Need to check variables that will be sent from fastspring. */ return true; } public function processValidated() { $SubscriptionURL = $this->request->get('SubscriptionURL'); $OrderReference2 = $this->request->get('OrderReference2'); if ($SubscriptionURL != '') $this->invoice->data()->set('SubscriptionURL', $SubscriptionURL)->update(); if ($OrderReference2 != '') $this->invoice->data()->set('OrderReference2', $OrderReference2)->update(); if(doubleval($this->invoice->first_total) == 0 && $this->invoice->status == Invoice::PENDING) { $this->invoice->addAccessPeriod($this); } else { $this->invoice->addPayment($this); } } public function autoCreateGetProducts() { $prId = $this->request->get('OrderProductNames'); if (empty($prId)) return; $products = array(); foreach(array_merge(array($prId), explode(' ', $prId)) as $prId){ $pl = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('fastspring_product_name', $prId); if (!$pl) continue; $pr = $pl->getProduct(); if(!$pr) continue; $products[] = $pr; } return $products; } function autoCreateGetProductQuantity(Product $pr){ return ($this->request->get('Quantity') ?: 1); } }PK\ o%%/default/plugins/payment/inet-cash/inet-cash.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_InetCash extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_REVISION = '5.0.5'; protected $defaultTitle = 'INET-CASH'; protected $defaultDescription = 'accepts credit card (VISA & Master Card) & debit payment (only Germany and Austria)'; const URL = 'https://www.inet-cash.com/mc/shop/start/'; const URL_CANCEL = 'https://www.inet-cash.com/callbacks/shop_cancel/'; protected $ips = array( '88.208.190.24', '62.159.133.4', '88.208.190.19', '88.208.190.20', '88.208.190.21', '88.208.190.24', '195.185.208.210', '91.66.104.163', '82.116.47.86', '82.114.228.174', '130.180.21.66' ); public function getSupportedCurrencies() { return array('EUR', 'USD'); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Inet_Cash($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function _initSetupForm(Am_Form_Setup $form) { $form->addText('siteid', array('size' => 20, 'maxlength' => 20)) ->setLabel("Site-ID: will be assigned by INET-CASH after you create your shop"); $form->addSelect('lang', array(), array('options' => array( 'en' => 'English', 'de' => 'Deutsch', 'es' => 'Español', 'pl' => 'język polski', 'fr' => 'français' )))->setLabel("Language"); $form->addSelect('zahlart', array(), array('options' => array( 'all' => 'All available types', 'cc' => 'Credit Card', 'dd' => 'Direct Debit, only Germany/Austria', 'db' => 'Sofortuberweisung', 'dp' => 'Payment in advance' )))->setLabel("Payment method"); $form->addText('owntxt', array('size' => '18', 'maxlength' => 18)) ->setLabel("Your own text will be shown on the top of the payment form."); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $params = array(); $params['shopid'] = $invoice->public_id; $params['lang'] = $this->getConfig('lang'); $params['owntxt'] = $this->getConfig('owntxt'); if ($this->getConfig('zahlart') !== 'all') $params['zahlart'] = $this->getConfig('zahlart'); $url = self::URL; $url.= $this->getConfig('siteid') . "?" . http_build_query($params); $request = new Am_HttpRequest($url, Am_HttpRequest::METHOD_GET); $response = $request->send(); if (!$response->getHeader('location')) { $result->setFailed($response->getBody()); return; } $a = new Am_Paysystem_Action_HtmlTemplate_InetCash($this->getDir(), 'inet-cash.phtml'); $a->url = $url; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $actionName = $request->getActionName(); if ($actionName == 'ipn') { if (!in_array($request->getClientIp(), $this->ips)) throw new Am_Exception_InputError("Request not handled - ip is not allowed"); if ($request->get('art') == 'request') { $shopid = $request->get('shopid'); if (!$shopid) throw new Am_Exception_InputError("Parameter shopid wasn't received"); $invoice = Am_Di::getInstance()->invoiceTable->findFirstByPublicId($shopid); if (!$invoice) throw new Am_Exception_InputError("No invoice found"); $params = array(); $params['nachname'] = $invoice->getLastName(); $params['vorname'] = $invoice->getFirstName(); $params['strasse'] = $invoice->getStreet(); $params['plz'] = $invoice->getZip(); $params['ort'] = $invoice->getCity(); $params['land'] = $invoice->getUser()->country; $params['email'] = $invoice->getEmail(); $params['betrag'] = $invoice->first_total * 100; $params['compain_id'] = ''; $params['ipadresse'] = $invoice->getUser()->remote_addr; if ($invoice->second_period) { $aboanlage = 1; $abopreis = $invoice->second_total * 100; preg_match("/[\d]+/", $invoice->second_period, $days); if (($days[0] <= 365) && ($days[0] >= 30)) $abozeit = $days[0]; preg_match("/[\d]+/", $invoice->first_period, $days); if (($days[0] <= 365) && ($days[0] >= 3)) $abonext = $days[0]; $params['aboanlage'] = $aboanlage; $params['abopreis'] = $abopreis; $params['abozeit'] = $abozeit; $params['abonext'] = $abonext; } $params['cur'] = strtolower($invoice->currency); $message = ''; foreach ($params as $p) $message .= $p . ";"; echo utf8_decode($message); return; } //Getting invoice for providing a redirect-URL with the result confirmation $shopid = $request->get('shopid'); $this->invoice = Am_Di::getInstance()->invoiceTable->findFirstByPublicId($shopid); $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); $transaction = $this->createTransaction($request, $response, $invokeArgs); if (!$this->invoice) { throw new Am_Exception_InputError("Request not handled - Request's parameter shopid is incorrect"); } if (!$transaction) { throw new Am_Exception_InputError("Request not handled - createTransaction() returned null"); } $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); } catch (Exception $e) { echo "OK;" . $this->getCancelUrl() . "?shopid=" . $this->invoice->public_id; if ($invoiceLog) $invoiceLog->add($e); throw $e; } echo "OK;" . $this->getReturnUrl() . "?shopid=" . $this->invoice->public_id; if ($invoiceLog) $invoiceLog->setProcessed(); } else { return parent::directAction($request, $response, $invokeArgs); } } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $params = array(); $params['shopid'] = $invoice->public_id; $params['reason'] = $actionName; $url = self::URL_CANCEL; $url.= $this->getConfig('siteid') . "?" . http_build_query($params); $request = new Am_HttpRequest($url, Am_HttpRequest::METHOD_GET); $response = $request->send(); if ($response->getBody() == 'ok') { $result->setSuccess(); } else $result->setFailed($response->getBody()); } function getReadme() { return <<Inet-Cash Configuration 1. Please for products that must be with recurring payments use values in days, for successful working of plugin. For first period, boundry must be following: from 3 to 365 (days), and number of days for second period must be from 30 to 365 (days). 2. In your admin INET-CASH->Shops->My Shops->_your_shop_->Edit please put into field Shop Script URL: http://yoursite.com/_your_amember_/payment/inet-cash/ipn CUT; } } class Am_Paysystem_Transaction_Inet_Cash extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('shopid'); } public function getUniqId() { return $this->request->get('traceno') . "-" . $this->request->get('belegnr'); } public function validateSource() { $shopid = $this->request->get('shopid'); $invoice = Am_Di::getInstance()->invoiceTable->findByPublicId($shopid); if (is_null($invoice)) return false; return true; } public function validateStatus() { if ($this->request->get('art') == 'cancel') throw new Am_Exception_Paysystem_TransactionInvalid("Cancellation request - ignored"); $errcod = $this->request->get('errcod'); if ($errcod == 0) { return true; } else { throw new Am_Exception_Paysystem_TransactionInvalid("Unknown type of errorcod returned from Inet-Cash"); } return false; } public function validateTerms() { return true; } }PK\99default/plugins/payment/inet-cash/scripts/inet-cash.phtmlnu[setLayout('layout.phtml'); ?> PK\'''default/plugins/payment/ideal/ideal.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Ideal extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_DATE = '$Date$'; const PLUGIN_REVISION = '5.0.6'; const ING_TEST = 'https://idealtest.secure-ing.com/ideal/iDEALv3'; const ING_LIVE = 'https://ideal.secure-ing.com/ideal/iDEALv3'; const RABOBANK_TEST = 'https://idealtest.rabobank.nl/ideal/iDEALv3'; const RABOBANK_LIVE = 'https://ideal.rabobank.nl/ideal/iDEALv3'; protected $defaultTitle = "iDEAL"; protected $defaultDescription = "accepts all major credit cards"; public function _initSetupForm(Am_Form_Setup $form) { $form->addSelect("ideal_bank")->setLabel("Merchant bank")-> loadOptions(array('ing' => 'secure-ing.com','rabobank' => 'rabobank.nl')); $form->addInteger("merchantId", array('maxlength' => 15, 'size' => 15)) ->setLabel("Merchant ID") ->addRule('required'); $form->addInteger("subId", array('value' => 0)) ->setLabel("Sub ID\n" . "usually it is not need to change it"); $form->addText("privateKey", array('size' => 40)) ->setLabel("Private Key\n" . "filename of private key") ->addRule('required'); $form->addText("privateKeyPass") ->setLabel("Private Key Password\n" . "password for private key") ->addRule('required'); $form->addText("privateCert", array('size' => 40)) ->setLabel("Merchant Certificate\n" . "filename of the certificate created by the merchant") ->addRule('required'); $form->addText("acquirerCert", array('size' => 40)) ->setLabel("Acquirer Certificate\n" . "filename of the certificate created by the acquirer") ->addRule('required'); $form->addSelect("lang") ->setLabel("Language") ->loadOptions(array('nl' => 'NL', 'en' => 'EN')); $form->addAdvCheckbox("testMode") ->setLabel("Test Mode Enabled"); $form->addAdvCheckbox("debugLog") ->setLabel("Debug Log Enabled\n" . "write all requests/responses to log"); } public function isConfigured() { return strlen($this->getConfig('merchantId')); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('EUR'); } private function getApiUrl() { $url = strtoupper($this->getConfig('ideal_bank', 'ing')).'_'.($this->getConfig('testMode') ? 'TEST' : 'LIVE'); return constant("self::$url"); } private function getCertsPath() { return $this->getDir() . '/certs/'; } public function getConfigArray() { return array( 'MERCHANTID' => $this->getConfig('merchantId'), 'SUBID' => $this->getConfig('subId', 0), 'MERCHANTRETURNURL' => $this->getPluginUrl('thanks'), 'ACQUIRERURL' => $this->getApiUrl(), 'CERTIFICATE0' => $this->getCertsPath() . $this->getConfig('acquirerCert'), 'PRIVATECERT' => $this->getCertsPath() . $this->getConfig('privateCert'), 'PRIVATEKEY' => $this->getCertsPath() . $this->getConfig('privateKey'), 'PRIVATEKEYPASS' => $this->getConfig('privateKeyPass'), 'DEBUGLOG' => $this->getConfig('debugLog') ? 1 : 0 ); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if(!count($issuers = $this->getConfig('issuers', array()))) { require_once ("lib/iDEALConnector.php"); $iDEALConnector = iDEALConnector::getDefaultInstance($this->getConfigArray()); $response = $iDEALConnector->getIssuers(); $issuers = array(); foreach ($response->getCountries() as $country) foreach ($country->getIssuers() as $issuer) $issuers[$country->getCountryNames()][$issuer->getId()] = $issuer->getName(); $this->getDi()->config->saveValue('payment.ideal.issuers', $issuers); } $banksSelect = "\r\n"; $a = new Am_Paysystem_Action_HtmlTemplate_Ideal($this->getDir(), 'payment-ideal-redirect.phtml'); $a->action = $this->getPluginUrl('pay'); $a->public = $this->getRootUrl() . "/application/default/plugins/payment/ideal/public"; $a->description = substr($invoice->getLineDescription(),0,32); $a->price = $invoice->first_total; $a->payment_id = $invoice->public_id; $a->banksSelect = $banksSelect; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ideal($this, $request, $response, $invokeArgs); } public function getReadme() { return <<getCertsPath()} folder. * Create 'Private Key' *.pem and 'Merchant Certificate' *.cer files using instruction here: '{$this->getCertsPath()}iDEAL_How-To-Generate-Certificates.pdf'. Get 'Acquirer Certificate' at your acquirer bank. CUT; } } class Am_Paysystem_Transaction_Ideal extends Am_Paysystem_Transaction_Incoming { protected $_params = array(); function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $this->_params = $this->request->isPost() ? $this->request->getPost() : $this->request->getQuery(); } public function findInvoiceId() { return (isset($this->_params['ec'])) ? $this->_params['ec'] : ''; } public function getUniqId() { return (isset($this->_params['trxid'])) ? $this->_params['trxid'] : ''; } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { require_once ("lib/iDEALConnector.php"); $iDEALConnector = iDEALConnector::getDefaultInstance($this->plugin->getConfigArray()); if ($this->request->getActionName() == 'pay') { $response = $iDEALConnector->startTransaction( $this->_params['IssuerIDs'], new Transaction( //(float)$this->invoice->first_total, (float)number_format($this->invoice->first_total, 2, '.', ''), substr($this->invoice->getLineDescription(),0,32), $this->invoice->public_id, //Entrance Code $iDEALConnector->getConfiguration()->getExpirationPeriod(), $this->invoice->public_id, // purchase Id, $this->invoice->currency, //'EUR', $this->plugin->getConfig('lang', 'nl') ), $this->plugin->getPluginUrl('ipn') // $this->plugin->getPluginUrl('status') ??? ); header('Location: ' . $response->getIssuerAuthenticationURL()); exit; } elseif ($this->request->getActionName() == 'ipn') { $response = $iDEALConnector->getTransactionStatus($this->getUniqId()); if ($response->getStatus() == 'Cancelled') { header('Location: ' . $this->plugin->getRootUrl() . "/cancel?id=" . $this->invoice->getSecureId('CANCEL')); exit; } if ($response->getAmount() != $this->invoice->first_total || $response->getCurrency() != $this->invoice->currency) //if ($response->getAmount() != $this->invoice->first_total) throw new Am_Exception_Paysystem_TransactionInvalid("Subscriptions terms in the IPN does not match subscription terms in our Invoice"); if ($response->getStatus() != 'Success') throw new Am_Exception_Paysystem_TransactionInvalid("Payment status is invalid, this IPN is not regarding a completed payment"); $this->invoice->addPayment($this); header('Location: ' . $this->plugin->getRootUrl() . "/thanks?id=" . $this->invoice->getSecureId("THANKS")); exit; } else throw new Am_Exception_Paysystem_TransactionInvalid('Ideal error: Unknowk case [' . $this->_case . ']'); } }PK\{^q.default/plugins/payment/ideal/public/style.cssnu[/* Copyright (c) 2008 Bart Kruger */ body, p, td { font-family:Verdana,Arial,Helvetica; font-size:9pt; color:#46596E; background-color:#FFFFFF } p, td { font-family:Verdana,Arial,Helvetica; font-size:9pt; color:#46596E } div#info { font-family:Verdana,Arial,Helvetica; font-size:8pt; color:#46596E } a { color: grey; text-decoration:none } a:hover { color: grey; text-decoration:none } table#outer { border-spacing:50px; } table#outer td { padding:20px } table#inner { border-spacing:5px } table#inner td { background-color:#EEEEEE; padding:5px } input.text { width: 230px } textarea { width: 230px } sup.red { color: #dd1414 } PK\,`5.default/plugins/payment/ideal/public/ideal.gifnu[GIF89a93Үhhhu'''牸VGGGܜ="zxxxSSS񔔔wJqqq l===il B777222*钾gf!,93pH,Ȥrl:ШtJZجv x%aj|a8WY/ !2+oVz%5B=5B=PIܽ 1 =xNH-7?D'DM*@"aF8\# ~4H<mrŽ:@ ;@OJC"Ə~taE|0P L%`Y18Pި i)XG5IO?-A^ ~(ctPH4I<}"bA "&pA$a`IGN x!^D,aƏP jYlhᴐ 2J`@>j c:f'WDwD=$c)} q ~&%M,P8a:S_<Aa^!:‰ƊR6b<`HFA8d}P-ic88@%LceX>h DQJqd- m`1@ŸVA j@CJ?H`B"+T'3I¥^@ &$prj6lX@2îꫯ&UEHs$ ``VkR+ŷ+kD;PK\. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * * Neither the name of Robert Richards nor the names of his * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * @author Robert Richards * @copyright 2007-2011 Robert Richards * @license http://www.opensource.org/licenses/bsd-license.php BSD License * @version 1.3.0 */ /* Functions to generate simple cases of Exclusive Canonical XML - Callable function is C14NGeneral() i.e.: $canonical = C14NGeneral($domelement, TRUE); */ /* helper function */ function sortAndAddAttrs($element, $arAtts) { $newAtts = array(); foreach ($arAtts AS $attnode) { $newAtts[$attnode->nodeName] = $attnode; } ksort($newAtts); foreach ($newAtts as $attnode) { $element->setAttribute($attnode->nodeName, $attnode->nodeValue); } } /* helper function */ function canonical($tree, $element, $withcomments) { if ($tree->nodeType != XML_DOCUMENT_NODE) { $dom = $tree->ownerDocument; } else { $dom = $tree; } if ($element->nodeType != XML_ELEMENT_NODE) { if ($element->nodeType == XML_DOCUMENT_NODE) { foreach ($element->childNodes AS $node) { canonical($dom, $node, $withcomments); } return; } if ($element->nodeType == XML_COMMENT_NODE && !$withcomments) { return; } $tree->appendChild($dom->importNode($element, TRUE)); return; } $arNS = array(); if ($element->namespaceURI != "") { if ($element->prefix == "") { $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName); } else { $prefix = $tree->lookupPrefix($element->namespaceURI); if ($prefix == $element->prefix) { $elCopy = $dom->createElementNS($element->namespaceURI, $element->nodeName); } else { $elCopy = $dom->createElement($element->nodeName); $arNS[$element->namespaceURI] = $element->prefix; } } } else { $elCopy = $dom->createElement($element->nodeName); } $tree->appendChild($elCopy); /* Create DOMXPath based on original document */ $xPath = new DOMXPath($element->ownerDocument); /* Get namespaced attributes */ $arAtts = $xPath->query('attribute::*[namespace-uri(.) != ""]', $element); /* Create an array with namespace URIs as keys, and sort them */ foreach ($arAtts AS $attnode) { if (array_key_exists($attnode->namespaceURI, $arNS) && ($arNS[$attnode->namespaceURI] == $attnode->prefix)) { continue; } $prefix = $tree->lookupPrefix($attnode->namespaceURI); if ($prefix != $attnode->prefix) { $arNS[$attnode->namespaceURI] = $attnode->prefix; } else { $arNS[$attnode->namespaceURI] = NULL; } } if (count($arNS) > 0) { asort($arNS); } /* Add namespace nodes */ foreach ($arNS AS $namespaceURI => $prefix) { if ($prefix != NULL) { $elCopy->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:" . $prefix, $namespaceURI); } } if (count($arNS) > 0) { ksort($arNS); } /* Get attributes not in a namespace, and then sort and add them */ $arAtts = $xPath->query('attribute::*[namespace-uri(.) = ""]', $element); sortAndAddAttrs($elCopy, $arAtts); /* Loop through the URIs, and then sort and add attributes within that namespace */ foreach ($arNS as $nsURI => $prefix) { $arAtts = $xPath->query('attribute::*[namespace-uri(.) = "' . $nsURI . '"]', $element); sortAndAddAttrs($elCopy, $arAtts); } foreach ($element->childNodes AS $node) { canonical($elCopy, $node, $withcomments); } } /* $element - DOMElement for which to produce the canonical version of $exclusive - boolean to indicate exclusive canonicalization (must pass TRUE) $withcomments - boolean indicating wether or not to include comments in canonicalized form */ function C14NGeneral($element, $exclusive=FALSE, $withcomments=FALSE) { /* IF PHP 5.2+ then use built in canonical functionality */ $php_version = explode('.', PHP_VERSION); if (($php_version[0] > 5) || ($php_version[0] == 5 && $php_version[1] >= 2)) { return $element->C14N($exclusive, $withcomments); } /* Must be element or document */ if (!$element instanceof DOMElement && !$element instanceof DOMDocument) { return NULL; } /* Currently only exclusive XML is supported */ if ($exclusive == FALSE) { throw new Exception("Only exclusive canonicalization is supported in this version of PHP"); } $copyDoc = new DOMDocument(); canonical($copyDoc, $element, $withcomments); return $copyDoc->saveXML($copyDoc->documentElement, LIBXML_NOEMPTYTAG); } class XMLSecurityKey { const TRIPLEDES_CBC = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'; const AES128_CBC = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'; const AES192_CBC = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'; const AES256_CBC = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'; const RSA_1_5 = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'; const RSA_OAEP_MGF1P = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p'; const DSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'; const RSA_SHA1 = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'; const RSA_SHA256 = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'; private $cryptParams = array(); public $type = 0; public $key = NULL; public $passphrase = ""; public $iv = NULL; public $name = NULL; public $keyChain = NULL; public $isEncrypted = FALSE; public $encryptedCtx = NULL; public $guid = NULL; /** * This variable contains the certificate as a string if this key represents an X509-certificate. * If this key doesn't represent a certificate, this will be NULL. */ private $x509Certificate = NULL; /* This variable contains the certificate thunbprint if we have loaded an X509-certificate. */ private $X509Thumbprint = NULL; public function __construct($type, $params=NULL) { srand(); switch ($type) { case (XMLSecurityKey::TRIPLEDES_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_TRIPLEDES; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'; $this->cryptParams['keysize'] = 24; break; case (XMLSecurityKey::AES128_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes128-cbc'; $this->cryptParams['keysize'] = 16; break; case (XMLSecurityKey::AES192_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes192-cbc'; $this->cryptParams['keysize'] = 24; break; case (XMLSecurityKey::AES256_CBC): $this->cryptParams['library'] = 'mcrypt'; $this->cryptParams['cipher'] = MCRYPT_RIJNDAEL_128; $this->cryptParams['mode'] = MCRYPT_MODE_CBC; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'; $this->cryptParams['keysize'] = 32; break; case (XMLSecurityKey::RSA_1_5): $this->cryptParams['library'] = 'openssl'; $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-1_5'; if (is_array($params) && !empty($params['type'])) { if ($params['type'] == 'public' || $params['type'] == 'private') { $this->cryptParams['type'] = $params['type']; break; } } throw new Exception('Certificate "type" (private/public) must be passed via parameters'); return; case (XMLSecurityKey::RSA_OAEP_MGF1P): $this->cryptParams['library'] = 'openssl'; $this->cryptParams['padding'] = OPENSSL_PKCS1_OAEP_PADDING; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p'; $this->cryptParams['hash'] = NULL; if (is_array($params) && !empty($params['type'])) { if ($params['type'] == 'public' || $params['type'] == 'private') { $this->cryptParams['type'] = $params['type']; break; } } throw new Exception('Certificate "type" (private/public) must be passed via parameters'); return; case (XMLSecurityKey::RSA_SHA1): $this->cryptParams['library'] = 'openssl'; $this->cryptParams['method'] = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'; $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING; if (is_array($params) && !empty($params['type'])) { if ($params['type'] == 'public' || $params['type'] == 'private') { $this->cryptParams['type'] = $params['type']; break; } } throw new Exception('Certificate "type" (private/public) must be passed via parameters'); break; case (XMLSecurityKey::RSA_SHA256): $this->cryptParams['library'] = 'openssl'; $this->cryptParams['method'] = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'; $this->cryptParams['padding'] = OPENSSL_PKCS1_PADDING; $this->cryptParams['digest'] = 'SHA256'; if (is_array($params) && !empty($params['type'])) { if ($params['type'] == 'public' || $params['type'] == 'private') { $this->cryptParams['type'] = $params['type']; break; } } throw new Exception('Certificate "type" (private/public) must be passed via parameters'); break; default: throw new Exception('Invalid Key Type'); return; } $this->type = $type; } /** * Retrieve the key size for the symmetric encryption algorithm.. * * If the key size is unknown, or this isn't a symmetric encryption algorithm, * NULL is returned. * * @return int|NULL The number of bytes in the key. */ public function getSymmetricKeySize() { if (!isset($this->cryptParams['keysize'])) { return NULL; } return $this->cryptParams['keysize']; } public function generateSessionKey() { if (!isset($this->cryptParams['keysize'])) { throw new Exception('Unknown key size for type "' . $this->type . '".'); } $keysize = $this->cryptParams['keysize']; if (function_exists('openssl_random_pseudo_bytes')) { /* We have PHP >= 5.3 - use openssl to generate session key. */ $key = openssl_random_pseudo_bytes($keysize); } else { /* Generating random key using iv generation routines */ $key = mcrypt_create_iv($keysize, MCRYPT_RAND); } if ($this->type === XMLSecurityKey::TRIPLEDES_CBC) { /* Make sure that the generated key has the proper parity bits set. * Mcrypt doesn't care about the parity bits, but others may care. */ for ($i = 0; $i < strlen($key); $i++) { $byte = ord($key[$i]) & 0xfe; $parity = 1; for ($j = 1; $j < 8; $j++) { $parity ^= ($byte >> $j) & 1; } $byte |= $parity; $key[$i] = chr($byte); } } $this->key = $key; return $key; } public static function getRawThumbprint($cert) { $arCert = explode("\n", $cert); $data = ''; $inData = FALSE; foreach ($arCert AS $curData) { if (!$inData) { if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) { $inData = TRUE; } } else { if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) { $inData = FALSE; break; } $data .= trim($curData); } } if (!empty($data)) { return strtolower(sha1(base64_decode($data))); } return NULL; } public function loadKey($key, $isFile=FALSE, $isCert = FALSE) { if ($isFile) { $this->key = file_get_contents($key); } else { $this->key = $key; } if ($isCert) { $this->key = openssl_x509_read($this->key); openssl_x509_export($this->key, $str_cert); $this->x509Certificate = $str_cert; $this->key = $str_cert; } else { $this->x509Certificate = NULL; } if ($this->cryptParams['library'] == 'openssl') { if ($this->cryptParams['type'] == 'public') { if ($isCert) { /* Load the thumbprint if this is an X509 certificate. */ $this->X509Thumbprint = self::getRawThumbprint($this->key); } $this->key = openssl_get_publickey($this->key); } else { $this->key = openssl_get_privatekey($this->key, $this->passphrase); } } else if ($this->cryptParams['cipher'] == MCRYPT_RIJNDAEL_128) { /* Check key length */ switch ($this->type) { case (XMLSecurityKey::AES256_CBC): if (strlen($this->key) < 25) { throw new Exception('Key must contain at least 25 characters for this cipher'); } break; case (XMLSecurityKey::AES192_CBC): if (strlen($this->key) < 17) { throw new Exception('Key must contain at least 17 characters for this cipher'); } break; } } } private function encryptMcrypt($data) { $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], ''); $this->iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND); mcrypt_generic_init($td, $this->key, $this->iv); if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) { $bs = mcrypt_enc_get_block_size($td); for ($datalen0 = $datalen = strlen($data); (($datalen % $bs) != ($bs - 1)); $datalen++) $data.=chr(rand(1, 127)); $data.=chr($datalen - $datalen0 + 1); } $encrypted_data = $this->iv . mcrypt_generic($td, $data); mcrypt_generic_deinit($td); mcrypt_module_close($td); return $encrypted_data; } private function decryptMcrypt($data) { $td = mcrypt_module_open($this->cryptParams['cipher'], '', $this->cryptParams['mode'], ''); $iv_length = mcrypt_enc_get_iv_size($td); $this->iv = substr($data, 0, $iv_length); $data = substr($data, $iv_length); mcrypt_generic_init($td, $this->key, $this->iv); $decrypted_data = mdecrypt_generic($td, $data); mcrypt_generic_deinit($td); mcrypt_module_close($td); if ($this->cryptParams['mode'] == MCRYPT_MODE_CBC) { $dataLen = strlen($decrypted_data); $paddingLength = substr($decrypted_data, $dataLen - 1, 1); $decrypted_data = substr($decrypted_data, 0, $dataLen - ord($paddingLength)); } return $decrypted_data; } private function encryptOpenSSL($data) { if ($this->cryptParams['type'] == 'public') { if (!openssl_public_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) { throw new Exception('Failure encrypting Data'); return; } } else { if (!openssl_private_encrypt($data, $encrypted_data, $this->key, $this->cryptParams['padding'])) { throw new Exception('Failure encrypting Data'); return; } } return $encrypted_data; } private function decryptOpenSSL($data) { if ($this->cryptParams['type'] == 'public') { if (!openssl_public_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) { throw new Exception('Failure decrypting Data'); return; } } else { if (!openssl_private_decrypt($data, $decrypted, $this->key, $this->cryptParams['padding'])) { throw new Exception('Failure decrypting Data'); return; } } return $decrypted; } private function signOpenSSL($data) { $algo = OPENSSL_ALGO_SHA1; if (!empty($this->cryptParams['digest'])) { $algo = $this->cryptParams['digest']; } if (!openssl_sign($data, $signature, $this->key, $algo)) { throw new Exception('Failure Signing Data: ' . openssl_error_string() . ' - ' . $algo); return; } return $signature; } private function verifyOpenSSL($data, $signature) { $algo = OPENSSL_ALGO_SHA1; if (!empty($this->cryptParams['digest'])) { $algo = $this->cryptParams['digest']; } return openssl_verify($data, $signature, $this->key, $algo); } public function encryptData($data) { switch ($this->cryptParams['library']) { case 'mcrypt': return $this->encryptMcrypt($data); break; case 'openssl': return $this->encryptOpenSSL($data); break; } } public function decryptData($data) { switch ($this->cryptParams['library']) { case 'mcrypt': return $this->decryptMcrypt($data); break; case 'openssl': return $this->decryptOpenSSL($data); break; } } public function signData($data) { switch ($this->cryptParams['library']) { case 'openssl': return $this->signOpenSSL($data); break; } } public function verifySignature($data, $signature) { switch ($this->cryptParams['library']) { case 'openssl': return $this->verifyOpenSSL($data, $signature); break; } } public function getAlgorith() { return $this->cryptParams['method']; } static function makeAsnSegment($type, $string) { switch ($type) { case 0x02: if (ord($string) > 0x7f) $string = chr(0) . $string; break; case 0x03: $string = chr(0) . $string; break; } $length = strlen($string); if ($length < 128) { $output = sprintf("%c%c%s", $type, $length, $string); } else if ($length < 0x0100) { $output = sprintf("%c%c%c%s", $type, 0x81, $length, $string); } else if ($length < 0x010000) { $output = sprintf("%c%c%c%c%s", $type, 0x82, $length / 0x0100, $length % 0x0100, $string); } else { $output = NULL; } return($output); } /* Modulus and Exponent must already be base64 decoded */ static function convertRSA($modulus, $exponent) { /* make an ASN publicKeyInfo */ $exponentEncoding = XMLSecurityKey::makeAsnSegment(0x02, $exponent); $modulusEncoding = XMLSecurityKey::makeAsnSegment(0x02, $modulus); $sequenceEncoding = XMLSecurityKey:: makeAsnSegment(0x30, $modulusEncoding . $exponentEncoding); $bitstringEncoding = XMLSecurityKey::makeAsnSegment(0x03, $sequenceEncoding); $rsaAlgorithmIdentifier = pack("H*", "300D06092A864886F70D0101010500"); $publicKeyInfo = XMLSecurityKey::makeAsnSegment(0x30, $rsaAlgorithmIdentifier . $bitstringEncoding); /* encode the publicKeyInfo in base64 and add PEM brackets */ $publicKeyInfoBase64 = base64_encode($publicKeyInfo); $encoding = "-----BEGIN PUBLIC KEY-----\n"; $offset = 0; while ($segment = substr($publicKeyInfoBase64, $offset, 64)) { $encoding = $encoding . $segment . "\n"; $offset += 64; } return $encoding . "-----END PUBLIC KEY-----\n"; } public function serializeKey($parent) { } /** * Retrieve the X509 certificate this key represents. * * Will return the X509 certificate in PEM-format if this key represents * an X509 certificate. * * @return The X509 certificate or NULL if this key doesn't represent an X509-certificate. */ public function getX509Certificate() { return $this->x509Certificate; } /* Get the thumbprint of this X509 certificate. * * Returns: * The thumbprint as a lowercase 40-character hexadecimal number, or NULL * if this isn't a X509 certificate. */ public function getX509Thumbprint() { return $this->X509Thumbprint; } /** * Create key from an EncryptedKey-element. * * @param DOMElement $element The EncryptedKey-element. * @return XMLSecurityKey The new key. */ public static function fromEncryptedKeyElement(DOMElement $element) { $objenc = new XMLSecEnc(); $objenc->setNode($element); if (!$objKey = $objenc->locateKey()) { throw new Exception("Unable to locate algorithm for this Encrypted Key"); } $objKey->isEncrypted = TRUE; $objKey->encryptedCtx = $objenc; XMLSecEnc::staticLocateKeyInfo($objKey, $element); return $objKey; } } class XMLSecurityDSig { const XMLDSIGNS = 'http://www.w3.org/2000/09/xmldsig#'; const SHA1 = 'http://www.w3.org/2000/09/xmldsig#sha1'; const SHA256 = 'http://www.w3.org/2001/04/xmlenc#sha256'; const SHA512 = 'http://www.w3.org/2001/04/xmlenc#sha512'; const RIPEMD160 = 'http://www.w3.org/2001/04/xmlenc#ripemd160'; const C14N = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'; const C14N_COMMENTS = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments'; const EXC_C14N = 'http://www.w3.org/2001/10/xml-exc-c14n#'; const EXC_C14N_COMMENTS = 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments'; const template = ' '; public $sigNode = NULL; public $idKeys = array(); public $idNS = array(); private $signedInfo = NULL; private $xPathCtx = NULL; private $canonicalMethod = NULL; private $prefix = NULL; private $searchpfx = 'secdsig'; /* This variable contains an associative array of validated nodes. */ private $validatedNodes = NULL; public function __construct() { $sigdoc = new DOMDocument(); $sigdoc->loadXML(XMLSecurityDSig::template); $this->sigNode = $sigdoc->documentElement; } private function resetXPathObj() { $this->xPathCtx = NULL; } private function getXPathObj() { if (empty($this->xPathCtx) && !empty($this->sigNode)) { $xpath = new DOMXPath($this->sigNode->ownerDocument); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); $this->xPathCtx = $xpath; } return $this->xPathCtx; } static function generate_GUID($prefix='pfx') { $uuid = md5(uniqid(rand(), true)); $guid = $prefix . substr($uuid, 0, 8) . "-" . substr($uuid, 8, 4) . "-" . substr($uuid, 12, 4) . "-" . substr($uuid, 16, 4) . "-" . substr($uuid, 20, 12); return $guid; } public function locateSignature($objDoc) { if ($objDoc instanceof DOMDocument) { $doc = $objDoc; } else { $doc = $objDoc->ownerDocument; } if ($doc) { $xpath = new DOMXPath($doc); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); $query = ".//secdsig:Signature"; $nodeset = $xpath->query($query, $objDoc); $this->sigNode = $nodeset->item(0); return $this->sigNode; } return NULL; } public function createNewSignNode($name, $value=NULL) { $doc = $this->sigNode->ownerDocument; if ($this->prefix != null) { $name = $this->prefix . ':' . $name; } if (!is_null($value)) { $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name, $value); } else { $node = $doc->createElementNS(XMLSecurityDSig::XMLDSIGNS, $name); } return $node; } public function setCanonicalMethod($method) { switch ($method) { case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315': case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments': case 'http://www.w3.org/2001/10/xml-exc-c14n#': case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments': $this->canonicalMethod = $method; break; default: throw new Exception('Invalid Canonical Method'); } if ($xpath = $this->getXPathObj()) { $query = './' . $this->searchpfx . ':SignedInfo'; $nodeset = $xpath->query($query, $this->sigNode); if ($sinfo = $nodeset->item(0)) { $query = './' . $this->searchpfx . 'CanonicalizationMethod'; $nodeset = $xpath->query($query, $sinfo); if (!($canonNode = $nodeset->item(0))) { $canonNode = $this->createNewSignNode('CanonicalizationMethod'); $sinfo->insertBefore($canonNode, $sinfo->firstChild); } $canonNode->setAttribute('Algorithm', $this->canonicalMethod); } } } private function canonicalizeData($node, $canonicalmethod, $arXPath=NULL, $prefixList=NULL) { $exclusive = FALSE; $withComments = FALSE; switch ($canonicalmethod) { case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315': $exclusive = FALSE; $withComments = FALSE; break; case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments': $withComments = TRUE; break; case 'http://www.w3.org/2001/10/xml-exc-c14n#': $exclusive = TRUE; break; case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments': $exclusive = TRUE; $withComments = TRUE; break; } /* Support PHP versions < 5.2 not containing C14N methods in DOM extension */ $php_version = explode('.', PHP_VERSION); if (($php_version[0] < 5) || ($php_version[0] == 5 && $php_version[1] < 2)) { if (!is_null($arXPath)) { throw new Exception("PHP 5.2.0 or higher is required to perform XPath Transformations"); } return C14NGeneral($node, $exclusive, $withComments); } return $node->C14N($exclusive, $withComments, $arXPath, $prefixList); } public function canonicalizeSignedInfo() { $doc = $this->sigNode->ownerDocument; $canonicalmethod = NULL; if ($doc) { $xpath = $this->getXPathObj(); $query = "./secdsig:SignedInfo"; $nodeset = $xpath->query($query, $this->sigNode); if ($signInfoNode = $nodeset->item(0)) { $query = "./secdsig:CanonicalizationMethod"; $nodeset = $xpath->query($query, $signInfoNode); if ($canonNode = $nodeset->item(0)) { $canonicalmethod = $canonNode->getAttribute('Algorithm'); } $this->signedInfo = $this->canonicalizeData($signInfoNode, $canonicalmethod); return $this->signedInfo; } } return NULL; } public function calculateDigest($digestAlgorithm, $data) { switch ($digestAlgorithm) { case XMLSecurityDSig::SHA1: $alg = 'sha1'; break; case XMLSecurityDSig::SHA256: $alg = 'sha256'; break; case XMLSecurityDSig::SHA512: $alg = 'sha512'; break; case XMLSecurityDSig::RIPEMD160: $alg = 'ripemd160'; break; default: throw new Exception("Cannot validate digest: Unsupported Algorith <$digestAlgorithm>"); } if (function_exists('hash')) { return base64_encode(hash($alg, $data, TRUE)); } elseif (function_exists('mhash')) { $alg = "MHASH_" . strtoupper($alg); return base64_encode(mhash(constant($alg), $data)); } elseif ($alg === 'sha1') { return base64_encode(sha1($data, TRUE)); } else { throw new Exception('xmlseclibs is unable to calculate a digest. Maybe you need the mhash library?'); } } public function validateDigest($refNode, $data) { $xpath = new DOMXPath($refNode->ownerDocument); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); $query = 'string(./secdsig:DigestMethod/@Algorithm)'; $digestAlgorithm = $xpath->evaluate($query, $refNode); $digValue = $this->calculateDigest($digestAlgorithm, $data); $query = 'string(./secdsig:DigestValue)'; $digestValue = $xpath->evaluate($query, $refNode); return ($digValue == $digestValue); } public function processTransforms($refNode, $objData, $includeCommentNodes = TRUE) { $data = $objData; $xpath = new DOMXPath($refNode->ownerDocument); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); $query = './secdsig:Transforms/secdsig:Transform'; $nodelist = $xpath->query($query, $refNode); $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'; $arXPath = NULL; $prefixList = NULL; foreach ($nodelist AS $transform) { $algorithm = $transform->getAttribute("Algorithm"); switch ($algorithm) { case 'http://www.w3.org/2001/10/xml-exc-c14n#': case 'http://www.w3.org/2001/10/xml-exc-c14n#WithComments': if (!$includeCommentNodes) { /* We remove comment nodes by forcing it to use a canonicalization * without comments. */ $canonicalMethod = 'http://www.w3.org/2001/10/xml-exc-c14n#'; } else { $canonicalMethod = $algorithm; } $node = $transform->firstChild; while ($node) { if ($node->localName == 'InclusiveNamespaces') { if ($pfx = $node->getAttribute('PrefixList')) { $arpfx = array(); $pfxlist = explode(" ", $pfx); foreach ($pfxlist AS $pfx) { $val = trim($pfx); if (!empty($val)) { $arpfx[] = $val; } } if (count($arpfx) > 0) { $prefixList = $arpfx; } } break; } $node = $node->nextSibling; } break; case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315': case 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments': if (!$includeCommentNodes) { /* We remove comment nodes by forcing it to use a canonicalization * without comments. */ $canonicalMethod = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'; } else { $canonicalMethod = $algorithm; } break; case 'http://www.w3.org/TR/1999/REC-xpath-19991116': $node = $transform->firstChild; while ($node) { if ($node->localName == 'XPath') { $arXPath = array(); $arXPath['query'] = '(.//. | .//@* | .//namespace::*)[' . $node->nodeValue . ']'; $arXpath['namespaces'] = array(); $nslist = $xpath->query('./namespace::*', $node); foreach ($nslist AS $nsnode) { if ($nsnode->localName != "xml") { $arXPath['namespaces'][$nsnode->localName] = $nsnode->nodeValue; } } break; } $node = $node->nextSibling; } break; } } if ($data instanceof DOMNode) { $data = $this->canonicalizeData($objData, $canonicalMethod, $arXPath, $prefixList); } return $data; } public function processRefNode($refNode) { $dataObject = NULL; /* * Depending on the URI, we may not want to include comments in the result * See: http://www.w3.org/TR/xmldsig-core/#sec-ReferenceProcessingModel */ $includeCommentNodes = TRUE; if ($uri = $refNode->getAttribute("URI")) { $arUrl = parse_url($uri); if (empty($arUrl['path'])) { if ($identifier = $arUrl['fragment']) { /* This reference identifies a node with the given id by using * a URI on the form "#identifier". This should not include comments. */ $includeCommentNodes = FALSE; $xPath = new DOMXPath($refNode->ownerDocument); if ($this->idNS && is_array($this->idNS)) { foreach ($this->idNS AS $nspf => $ns) { $xPath->registerNamespace($nspf, $ns); } } $iDlist = '@Id="' . $identifier . '"'; if (is_array($this->idKeys)) { foreach ($this->idKeys AS $idKey) { $iDlist .= " or @$idKey='$identifier'"; } } $query = '//*[' . $iDlist . ']'; $dataObject = $xPath->query($query)->item(0); } else { $dataObject = $refNode->ownerDocument; } } else { $dataObject = file_get_contents($arUrl); } } else { /* This reference identifies the root node with an empty URI. This should * not include comments. */ $includeCommentNodes = FALSE; $dataObject = $refNode->ownerDocument; } $data = $this->processTransforms($refNode, $dataObject, $includeCommentNodes); if (!$this->validateDigest($refNode, $data)) { return FALSE; } if ($dataObject instanceof DOMNode) { /* Add this node to the list of validated nodes. */ if (!empty($identifier)) { $this->validatedNodes[$identifier] = $dataObject; } else { $this->validatedNodes[] = $dataObject; } } return TRUE; } public function getRefNodeID($refNode) { if ($uri = $refNode->getAttribute("URI")) { $arUrl = parse_url($uri); if (empty($arUrl['path'])) { if ($identifier = $arUrl['fragment']) { return $identifier; } } } return null; } public function getRefIDs() { $refids = array(); $doc = $this->sigNode->ownerDocument; $xpath = $this->getXPathObj(); $query = "./secdsig:SignedInfo/secdsig:Reference"; $nodeset = $xpath->query($query, $this->sigNode); if ($nodeset->length == 0) { throw new Exception("Reference nodes not found"); } foreach ($nodeset AS $refNode) { $refids[] = $this->getRefNodeID($refNode); } return $refids; } public function validateReference() { $doc = $this->sigNode->ownerDocument; if (!$doc->isSameNode($this->sigNode)) { $this->sigNode->parentNode->removeChild($this->sigNode); } $xpath = $this->getXPathObj(); $query = "./secdsig:SignedInfo/secdsig:Reference"; $nodeset = $xpath->query($query, $this->sigNode); if ($nodeset->length == 0) { throw new Exception("Reference nodes not found"); } /* Initialize/reset the list of validated nodes. */ $this->validatedNodes = array(); foreach ($nodeset AS $refNode) { if (!$this->processRefNode($refNode)) { /* Clear the list of validated nodes. */ $this->validatedNodes = NULL; throw new Exception("Reference validation failed"); } } return TRUE; } private function addRefInternal($sinfoNode, $node, $algorithm, $arTransforms=NULL, $options=NULL) { $prefix = NULL; $prefix_ns = NULL; $id_name = 'Id'; $overwrite_id = TRUE; $force_uri = FALSE; if (is_array($options)) { $prefix = empty($options['prefix']) ? NULL : $options['prefix']; $prefix_ns = empty($options['prefix_ns']) ? NULL : $options['prefix_ns']; $id_name = empty($options['id_name']) ? 'Id' : $options['id_name']; $overwrite_id = !isset($options['overwrite']) ? TRUE : (bool) $options['overwrite']; $force_uri = !isset($options['force_uri']) ? FALSE : (bool) $options['force_uri']; } $attname = $id_name; if (!empty($prefix)) { $attname = $prefix . ':' . $attname; } $refNode = $this->createNewSignNode('Reference'); $sinfoNode->appendChild($refNode); if (!$node instanceof DOMDocument) { $uri = NULL; if (!$overwrite_id) { $uri = $node->getAttributeNS($prefix_ns, $attname); } if (empty($uri)) { $uri = XMLSecurityDSig::generate_GUID(); $node->setAttributeNS($prefix_ns, $attname, $uri); } $refNode->setAttribute("URI", '#' . $uri); } elseif ($force_uri) { $refNode->setAttribute("URI", ''); } $transNodes = $this->createNewSignNode('Transforms'); $refNode->appendChild($transNodes); if (is_array($arTransforms)) { foreach ($arTransforms AS $transform) { $transNode = $this->createNewSignNode('Transform'); $transNodes->appendChild($transNode); if (is_array($transform) && (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116'])) && (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']))) { $transNode->setAttribute('Algorithm', 'http://www.w3.org/TR/1999/REC-xpath-19991116'); $XPathNode = $this->createNewSignNode('XPath', $transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['query']); $transNode->appendChild($XPathNode); if (!empty($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'])) { foreach ($transform['http://www.w3.org/TR/1999/REC-xpath-19991116']['namespaces'] AS $prefix => $namespace) { $XPathNode->setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:$prefix", $namespace); } } } else { $transNode->setAttribute('Algorithm', $transform); } } } elseif (!empty($this->canonicalMethod)) { $transNode = $this->createNewSignNode('Transform'); $transNodes->appendChild($transNode); $transNode->setAttribute('Algorithm', $this->canonicalMethod); } $canonicalData = $this->processTransforms($refNode, $node); $digValue = $this->calculateDigest($algorithm, $canonicalData); $digestMethod = $this->createNewSignNode('DigestMethod'); $refNode->appendChild($digestMethod); $digestMethod->setAttribute('Algorithm', $algorithm); $digestValue = $this->createNewSignNode('DigestValue', $digValue); $refNode->appendChild($digestValue); } public function addReference($node, $algorithm, $arTransforms=NULL, $options=NULL) { if ($xpath = $this->getXPathObj()) { $query = "./secdsig:SignedInfo"; $nodeset = $xpath->query($query, $this->sigNode); if ($sInfo = $nodeset->item(0)) { $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options); } } } public function addReferenceList($arNodes, $algorithm, $arTransforms=NULL, $options=NULL) { if ($xpath = $this->getXPathObj()) { $query = "./secdsig:SignedInfo"; $nodeset = $xpath->query($query, $this->sigNode); if ($sInfo = $nodeset->item(0)) { foreach ($arNodes AS $node) { $this->addRefInternal($sInfo, $node, $algorithm, $arTransforms, $options); } } } } public function addObject($data, $mimetype=NULL, $encoding=NULL) { $objNode = $this->createNewSignNode('Object'); $this->sigNode->appendChild($objNode); if (!empty($mimetype)) { $objNode->setAtribute('MimeType', $mimetype); } if (!empty($encoding)) { $objNode->setAttribute('Encoding', $encoding); } if ($data instanceof DOMElement) { $newData = $this->sigNode->ownerDocument->importNode($data, TRUE); } else { $newData = $this->sigNode->ownerDocument->createTextNode($data); } $objNode->appendChild($newData); return $objNode; } public function locateKey($node=NULL) { if (empty($node)) { $node = $this->sigNode; } if (!$node instanceof DOMNode) { return NULL; } if ($doc = $node->ownerDocument) { $xpath = new DOMXPath($doc); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); $query = "string(./secdsig:SignedInfo/secdsig:SignatureMethod/@Algorithm)"; $algorithm = $xpath->evaluate($query, $node); if ($algorithm) { try { $objKey = new XMLSecurityKey($algorithm, array('type' => 'public')); } catch (Exception $e) { return NULL; } return $objKey; } } return NULL; } public function verify($objKey) { $doc = $this->sigNode->ownerDocument; $xpath = new DOMXPath($doc); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); $query = "string(./secdsig:SignatureValue)"; $sigValue = $xpath->evaluate($query, $this->sigNode); if (empty($sigValue)) { throw new Exception("Unable to locate SignatureValue"); } return $objKey->verifySignature($this->signedInfo, base64_decode($sigValue)); } public function signData($objKey, $data) { return $objKey->signData($data); } public function sign($objKey, $appendToNode = NULL) { // If we have a parent node append it now so C14N properly works if ($appendToNode != NULL) { $this->resetXPathObj(); $this->appendSignature($appendToNode); $this->sigNode = $appendToNode->lastChild; } if ($xpath = $this->getXPathObj()) { $query = "./secdsig:SignedInfo"; $nodeset = $xpath->query($query, $this->sigNode); if ($sInfo = $nodeset->item(0)) { $query = "./secdsig:SignatureMethod"; $nodeset = $xpath->query($query, $sInfo); $sMethod = $nodeset->item(0); $sMethod->setAttribute('Algorithm', $objKey->type); $data = $this->canonicalizeData($sInfo, $this->canonicalMethod); $sigValue = base64_encode($this->signData($objKey, $data)); $sigValueNode = $this->createNewSignNode('SignatureValue', $sigValue); if ($infoSibling = $sInfo->nextSibling) { $infoSibling->parentNode->insertBefore($sigValueNode, $infoSibling); } else { $this->sigNode->appendChild($sigValueNode); } } } } public function appendCert() { } public function appendKey($objKey, $parent=NULL) { $objKey->serializeKey($parent); } /** * This function inserts the signature element. * * The signature element will be appended to the element, unless $beforeNode is specified. If $beforeNode * is specified, the signature element will be inserted as the last element before $beforeNode. * * @param $node The node the signature element should be inserted into. * @param $beforeNode The node the signature element should be located before. * * @return DOMNode The signature element node */ public function insertSignature($node, $beforeNode = NULL) { $document = $node->ownerDocument; $signatureElement = $document->importNode($this->sigNode, TRUE); if ($beforeNode == NULL) { return $node->insertBefore($signatureElement); } else { return $node->insertBefore($signatureElement, $beforeNode); } } public function appendSignature($parentNode, $insertBefore = FALSE) { $beforeNode = $insertBefore ? $parentNode->firstChild : NULL; return $this->insertSignature($parentNode, $beforeNode); } static function get509XCert($cert, $isPEMFormat=TRUE) { $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat); if (!empty($certs)) { return $certs[0]; } return ''; } static function staticGet509XCerts($certs, $isPEMFormat=TRUE) { if ($isPEMFormat) { $data = ''; $certlist = array(); $arCert = explode("\n", $certs); $inData = FALSE; foreach ($arCert AS $curData) { if (!$inData) { if (strncmp($curData, '-----BEGIN CERTIFICATE', 22) == 0) { $inData = TRUE; } } else { if (strncmp($curData, '-----END CERTIFICATE', 20) == 0) { $inData = FALSE; $certlist[] = $data; $data = ''; continue; } $data .= trim($curData); } } return $certlist; } else { return array($certs); } } static function staticAdd509Cert($parentRef, $cert, $isPEMFormat=TRUE, $isURL=False, $xpath=NULL) { if ($isURL) { $cert = file_get_contents($cert); } if (!$parentRef instanceof DOMElement) { throw new Exception('Invalid parent Node parameter'); } $baseDoc = $parentRef->ownerDocument; if (empty($xpath)) { $xpath = new DOMXPath($parentRef->ownerDocument); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); } $query = "./secdsig:KeyInfo"; $nodeset = $xpath->query($query, $parentRef); $keyInfo = $nodeset->item(0); if (!$keyInfo) { $inserted = FALSE; $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:KeyInfo'); $query = "./secdsig:Object"; $nodeset = $xpath->query($query, $parentRef); if ($sObject = $nodeset->item(0)) { $sObject->parentNode->insertBefore($keyInfo, $sObject); $inserted = TRUE; } if (!$inserted) { $parentRef->appendChild($keyInfo); } } // Add all certs if there are more than one $certs = XMLSecurityDSig::staticGet509XCerts($cert, $isPEMFormat); // Atach X509 data node $x509DataNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Data'); $keyInfo->appendChild($x509DataNode); // Atach all certificate nodes foreach ($certs as $X509Cert) { $x509CertNode = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'ds:X509Certificate', $X509Cert); $x509DataNode->appendChild($x509CertNode); } } public function add509Cert($cert, $isPEMFormat=TRUE, $isURL=False) { if ($xpath = $this->getXPathObj()) { self::staticAdd509Cert($this->sigNode, $cert, $isPEMFormat, $isURL, $xpath); } } function addKeyInfoAndName($keyName, $xpath=NULL) { $baseDoc = $this->sigNode->ownerDocument; if (empty($xpath)) { $xpath = new DOMXPath($baseDoc); $xpath->registerNamespace('secdsig', XMLSecurityDSig::XMLDSIGNS); } $query = "./secdsig:KeyInfo"; $nodeset = $xpath->query($query, $this->sigNode); $keyInfo = $nodeset->item(0); if (!$keyInfo) { $inserted = FALSE; $keyInfo = $baseDoc->createElementNS(XMLSecurityDSig::XMLDSIGNS, 'KeyInfo'); $query = "./secdsig:Object"; $nodeset = $xpath->query($query, $this->sigNode); if ($sObject = $nodeset->item(0)) { $sObject->parentNode->insertBefore($keyInfo, $sObject); $inserted = TRUE; } if (!$inserted) { $this->sigNode->appendChild($keyInfo); } } $keyInfo->appendChild($baseDoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'KeyName', $keyName)); } /* This function retrieves an associative array of the validated nodes. * * The array will contain the id of the referenced node as the key and the node itself * as the value. * * Returns: * An associative array of validated nodes or NULL if no nodes have been validated. */ public function getValidatedNodes() { return $this->validatedNodes; } } class XMLSecEnc { const template = " "; const Element = 'http://www.w3.org/2001/04/xmlenc#Element'; const Content = 'http://www.w3.org/2001/04/xmlenc#Content'; const URI = 3; const XMLENCNS = 'http://www.w3.org/2001/04/xmlenc#'; private $encdoc = NULL; private $rawNode = NULL; public $type = NULL; public $encKey = NULL; private $references = array(); public function __construct() { $this->_resetTemplate(); } private function _resetTemplate() { $this->encdoc = new DOMDocument(); $this->encdoc->loadXML(XMLSecEnc::template); } public function addReference($name, $node, $type) { if (!$node instanceOf DOMNode) { throw new Exception('$node is not of type DOMNode'); } $curencdoc = $this->encdoc; $this->_resetTemplate(); $encdoc = $this->encdoc; $this->encdoc = $curencdoc; $refuri = XMLSecurityDSig::generate_GUID(); $element = $encdoc->documentElement; $element->setAttribute("Id", $refuri); $this->references[$name] = array("node" => $node, "type" => $type, "encnode" => $encdoc, "refuri" => $refuri); } public function setNode($node) { $this->rawNode = $node; } public function encryptNode($objKey, $replace=TRUE) { $data = ''; if (empty($this->rawNode)) { throw new Exception('Node to encrypt has not been set'); } if (!$objKey instanceof XMLSecurityKey) { throw new Exception('Invalid Key'); } $doc = $this->rawNode->ownerDocument; $xPath = new DOMXPath($this->encdoc); $objList = $xPath->query('/xenc:EncryptedData/xenc:CipherData/xenc:CipherValue'); $cipherValue = $objList->item(0); if ($cipherValue == NULL) { throw new Exception('Error locating CipherValue element within template'); } switch ($this->type) { case (XMLSecEnc::Element): $data = $doc->saveXML($this->rawNode); $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Element); break; case (XMLSecEnc::Content): $children = $this->rawNode->childNodes; foreach ($children AS $child) { $data .= $doc->saveXML($child); } $this->encdoc->documentElement->setAttribute('Type', XMLSecEnc::Content); break; default: throw new Exception('Type is currently not supported'); return; } $encMethod = $this->encdoc->documentElement->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod')); $encMethod->setAttribute('Algorithm', $objKey->getAlgorith()); $cipherValue->parentNode->parentNode->insertBefore($encMethod, $cipherValue->parentNode->parentNode->firstChild); $strEncrypt = base64_encode($objKey->encryptData($data)); $value = $this->encdoc->createTextNode($strEncrypt); $cipherValue->appendChild($value); if ($replace) { switch ($this->type) { case (XMLSecEnc::Element): if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) { return $this->encdoc; } $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE); $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode); return $importEnc; break; case (XMLSecEnc::Content): $importEnc = $this->rawNode->ownerDocument->importNode($this->encdoc->documentElement, TRUE); while ($this->rawNode->firstChild) { $this->rawNode->removeChild($this->rawNode->firstChild); } $this->rawNode->appendChild($importEnc); return $importEnc; break; } } } public function encryptReferences($objKey) { $curRawNode = $this->rawNode; $curType = $this->type; foreach ($this->references AS $name => $reference) { $this->encdoc = $reference["encnode"]; $this->rawNode = $reference["node"]; $this->type = $reference["type"]; try { $encNode = $this->encryptNode($objKey); $this->references[$name]["encnode"] = $encNode; } catch (Exception $e) { $this->rawNode = $curRawNode; $this->type = $curType; throw $e; } } $this->rawNode = $curRawNode; $this->type = $curType; } /** * Retrieve the CipherValue text from this encrypted node. * * @return string|NULL The Ciphervalue text, or NULL if no CipherValue is found. */ public function getCipherValue() { if (empty($this->rawNode)) { throw new Exception('Node to decrypt has not been set'); } $doc = $this->rawNode->ownerDocument; $xPath = new DOMXPath($doc); $xPath->registerNamespace('xmlencr', XMLSecEnc::XMLENCNS); /* Only handles embedded content right now and not a reference */ $query = "./xmlencr:CipherData/xmlencr:CipherValue"; $nodeset = $xPath->query($query, $this->rawNode); $node = $nodeset->item(0); if (!$node) { return NULL; } return base64_decode($node->nodeValue); } /** * Decrypt this encrypted node. * * The behaviour of this function depends on the value of $replace. * If $replace is FALSE, we will return the decrypted data as a string. * If $replace is TRUE, we will insert the decrypted element(s) into the * document, and return the decrypted element(s). * * @params XMLSecurityKey $objKey The decryption key that should be used when decrypting the node. * @params boolean $replace Whether we should replace the encrypted node in the XML document with the decrypted data. The default is TRUE. * @return string|DOMElement The decrypted data. */ public function decryptNode($objKey, $replace=TRUE) { if (!$objKey instanceof XMLSecurityKey) { throw new Exception('Invalid Key'); } $encryptedData = $this->getCipherValue(); if ($encryptedData) { $decrypted = $objKey->decryptData($encryptedData); if ($replace) { switch ($this->type) { case (XMLSecEnc::Element): $newdoc = new DOMDocument(); $newdoc->loadXML($decrypted); if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) { return $newdoc; } $importEnc = $this->rawNode->ownerDocument->importNode($newdoc->documentElement, TRUE); $this->rawNode->parentNode->replaceChild($importEnc, $this->rawNode); return $importEnc; break; case (XMLSecEnc::Content): if ($this->rawNode->nodeType == XML_DOCUMENT_NODE) { $doc = $this->rawNode; } else { $doc = $this->rawNode->ownerDocument; } $newFrag = $doc->createDocumentFragment(); $newFrag->appendXML($decrypted); $parent = $this->rawNode->parentNode; $parent->replaceChild($newFrag, $this->rawNode); return $parent; break; default: return $decrypted; } } else { return $decrypted; } } else { throw new Exception("Cannot locate encrypted data"); } } public function encryptKey($srcKey, $rawKey, $append=TRUE) { if ((!$srcKey instanceof XMLSecurityKey) || (!$rawKey instanceof XMLSecurityKey)) { throw new Exception('Invalid Key'); } $strEncKey = base64_encode($srcKey->encryptData($rawKey->key)); $root = $this->encdoc->documentElement; $encKey = $this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptedKey'); if ($append) { $keyInfo = $root->insertBefore($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo'), $root->firstChild); $keyInfo->appendChild($encKey); } else { $this->encKey = $encKey; } $encMethod = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:EncryptionMethod')); $encMethod->setAttribute('Algorithm', $srcKey->getAlgorith()); if (!empty($srcKey->name)) { $keyInfo = $encKey->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyInfo')); $keyInfo->appendChild($this->encdoc->createElementNS('http://www.w3.org/2000/09/xmldsig#', 'dsig:KeyName', $srcKey->name)); } $cipherData = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherData')); $cipherData->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:CipherValue', $strEncKey)); if (is_array($this->references) && count($this->references) > 0) { $refList = $encKey->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:ReferenceList')); foreach ($this->references AS $name => $reference) { $refuri = $reference["refuri"]; $dataRef = $refList->appendChild($this->encdoc->createElementNS(XMLSecEnc::XMLENCNS, 'xenc:DataReference')); $dataRef->setAttribute("URI", '#' . $refuri); } } return; } public function decryptKey($encKey) { if (!$encKey->isEncrypted) { throw new Exception("Key is not Encrypted"); } if (empty($encKey->key)) { throw new Exception("Key is missing data to perform the decryption"); } return $this->decryptNode($encKey, FALSE); } public function locateEncryptedData($element) { if ($element instanceof DOMDocument) { $doc = $element; } else { $doc = $element->ownerDocument; } if ($doc) { $xpath = new DOMXPath($doc); $query = "//*[local-name()='EncryptedData' and namespace-uri()='" . XMLSecEnc::XMLENCNS . "']"; $nodeset = $xpath->query($query); return $nodeset->item(0); } return NULL; } public function locateKey($node=NULL) { if (empty($node)) { $node = $this->rawNode; } if (!$node instanceof DOMNode) { return NULL; } if ($doc = $node->ownerDocument) { $xpath = new DOMXPath($doc); $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS); $query = ".//xmlsecenc:EncryptionMethod"; $nodeset = $xpath->query($query, $node); if ($encmeth = $nodeset->item(0)) { $attrAlgorithm = $encmeth->getAttribute("Algorithm"); try { $objKey = new XMLSecurityKey($attrAlgorithm, array('type' => 'private')); } catch (Exception $e) { return NULL; } return $objKey; } } return NULL; } static function staticLocateKeyInfo($objBaseKey=NULL, $node=NULL) { if (empty($node) || (!$node instanceof DOMNode)) { return NULL; } $doc = $node->ownerDocument; if (!$doc) { return NULL; } $xpath = new DOMXPath($doc); $xpath->registerNamespace('xmlsecenc', XMLSecEnc::XMLENCNS); $xpath->registerNamespace('xmlsecdsig', XMLSecurityDSig::XMLDSIGNS); $query = "./xmlsecdsig:KeyInfo"; $nodeset = $xpath->query($query, $node); $encmeth = $nodeset->item(0); if (!$encmeth) { /* No KeyInfo in EncryptedData / EncryptedKey. */ return $objBaseKey; } foreach ($encmeth->childNodes AS $child) { switch ($child->localName) { case 'KeyName': if (!empty($objBaseKey)) { $objBaseKey->name = $child->nodeValue; } break; case 'KeyValue': foreach ($child->childNodes AS $keyval) { switch ($keyval->localName) { case 'DSAKeyValue': throw new Exception("DSAKeyValue currently not supported"); break; case 'RSAKeyValue': $modulus = NULL; $exponent = NULL; if ($modulusNode = $keyval->getElementsByTagName('Modulus')->item(0)) { $modulus = base64_decode($modulusNode->nodeValue); } if ($exponentNode = $keyval->getElementsByTagName('Exponent')->item(0)) { $exponent = base64_decode($exponentNode->nodeValue); } if (empty($modulus) || empty($exponent)) { throw new Exception("Missing Modulus or Exponent"); } $publicKey = XMLSecurityKey::convertRSA($modulus, $exponent); $objBaseKey->loadKey($publicKey); break; } } break; case 'RetrievalMethod': $type = $child->getAttribute('Type'); if ($type !== 'http://www.w3.org/2001/04/xmlenc#EncryptedKey') { /* Unsupported key type. */ break; } $uri = $child->getAttribute('URI'); if ($uri[0] !== '#') { /* URI not a reference - unsupported. */ break; } $id = substr($uri, 1); $query = "//xmlsecenc:EncryptedKey[@Id='$id']"; $keyElement = $xpath->query($query)->item(0); if (!$keyElement) { throw new Exception("Unable to locate EncryptedKey with @Id='$id'."); } return XMLSecurityKey::fromEncryptedKeyElement($keyElement); case 'EncryptedKey': return XMLSecurityKey::fromEncryptedKeyElement($child); case 'X509Data': if ($x509certNodes = $child->getElementsByTagName('X509Certificate')) { if ($x509certNodes->length > 0) { $x509cert = $x509certNodes->item(0)->textContent; $x509cert = str_replace(array("\r", "\n"), "", $x509cert); $x509cert = "-----BEGIN CERTIFICATE-----\n" . chunk_split($x509cert, 64, "\n") . "-----END CERTIFICATE-----\n"; $objBaseKey->loadKey($x509cert, FALSE, TRUE); } } break; } } return $objBaseKey; } public function locateKeyInfo($objBaseKey=NULL, $node=NULL) { if (empty($node)) { $node = $this->rawNode; } return XMLSecEnc::staticLocateKeyInfo($objBaseKey, $node); } } PK\xZ5default/plugins/payment/ideal/lib/Xml/XmlSecurity.phpnu[setCanonicalMethod(XMLSecurityDSig::EXC_C14N); $signature->addReference($doc, XMLSecurityDSig::SHA256, array('http://www.w3.org/2000/09/xmldsig#enveloped-signature'), array('force_uri' => true)); $key = new XMLSecurityKey(XMLSecurityKey::RSA_SHA256, array('type' => 'private')); $key->passphrase = $passphrase; $key->loadKey($privateKeyPath, TRUE); $signature->sign($key); $fingerprint = $this->getFingerprint($privateCertificatePath); $signature->addKeyInfoAndName($fingerprint); $signature->appendSignature($doc->documentElement); return $doc->saveXML(); } public function verify(DOMDocument $doc, $certificatePath) { $signature = new XMLSecurityDSig(); $sig = $signature->locateSignature($doc); if (!$sig) throw new SecurityException("Cannot locate Signature Node"); //$signature->setCanonicalMethod(XMLSecurityDSig::EXC_C14N); //whitespaces are significant $signature->canonicalizeSignedInfo(); try { $signature->validateReference(); } catch(Exception $ex) { throw new SecurityException("Reference Validation Failed"); } $key = $signature->locateKey(); if (!$key) throw new SecurityException("Cannot locate the key."); $key->loadKey($certificatePath,true); return $signature->verify($key) == 1; } private function getFingerprint($path) { $contents = file_get_contents($path); if (is_null($contents)) throw new SecurityException("Empty certificate."); $contents = str_replace('-----END CERTIFICATE-----', '', str_replace('-----BEGIN CERTIFICATE-----', '', $contents)); $contents = base64_decode($contents); return sha1($contents); } } PK\m+8+87default/plugins/payment/ideal/lib/Xml/XmlSerializer.phpnu[createElement("DirectoryReq"); $this->serializeAbstractRequest($element, $input); /* @var $input DirectoryRequest */ $this->serializeDirectoryRequest($element, $input); $doc->appendChild($element); } else if ($className === "iDEALConnector\Entities\AcquirerTransactionRequest") { $element = $doc->createElement("AcquirerTrxReq"); $this->serializeAbstractRequest($element, $input); /* @var $input AcquirerTransactionRequest */ $this->serializeAcquirerTransactionRequest($element, $input); $doc->appendChild($element); } else if ($className === "iDEALConnector\Entities\AcquirerStatusRequest") { $element = $doc->createElement("AcquirerStatusReq"); $this->serializeAbstractRequest($element, $input); /* @var $input AcquirerStatusRequest */ $this->serializeAcquirerStatusRequest($element, $input); $doc->appendChild($element); } else throw new SerializationException('Given object type could not be serialized.'); return $doc; } private function serializeAbstractRequest(DOMElement $element, AbstractRequest $request) { $element->appendChild(new DOMElement("createDateTimestamp", $request->getCreateDateTimestamp()->format("Y-m-d\TH:i:s\Z"))); $element->setAttribute("version", $request->getVersion()); $element->setAttribute("xmlns", "http://www.idealdesk.com/ideal/messages/mer-acq/3.3.1"); } private function serializeDirectoryRequest(DOMElement $element, DirectoryRequest $request) { $merchant = $element->ownerDocument->createElement("Merchant"); $this->serializeMerchant($merchant, $request->getMerchant()); $element->appendChild($merchant); } private function serializeAcquirerTransactionRequest(DOMElement $element, AcquirerTransactionRequest $request) { $item = $element->ownerDocument->createElement("Issuer"); $item->appendChild(new DOMElement("issuerID", $request->getIssuerID())); $element->appendChild($item); $item = $element->ownerDocument->createElement("Merchant"); $this->serializeMerchant($item, $request->getMerchant(), true); $element->appendChild($item); $item = $element->ownerDocument->createElement("Transaction"); $this->serializeTransaction($item, $request->getTransaction()); $element->appendChild($item); } private function serializeAcquirerStatusRequest(DOMElement $element, AcquirerStatusRequest $request) { $item = $element->ownerDocument->createElement("Merchant"); $this->serializeMerchant($item, $request->getMerchant()); $element->appendChild($item); $item = $element->ownerDocument->createElement("Transaction"); $item->appendChild(new DOMElement("transactionID", $request->getTransactionID())); $element->appendChild($item); } private function serializeMerchant(DOMElement $element, Merchant $merchant, $withUrl = false) { $element->appendChild(new DOMElement("merchantID", $merchant->getMerchantID())); $element->appendChild(new DOMElement("subID", $merchant->getSubID())); if ($withUrl) $element->appendChild(new DOMElement("merchantReturnURL", $merchant->getMerchantReturnURL())); } private function serializeTransaction(DOMElement $element, Transaction $transaction) { $element->appendChild(new DOMElement("purchaseID", $transaction->getPurchaseId())); $element->appendChild(new DOMElement("amount", number_format($transaction->getAmount(), 2, '.', ''))); $element->appendChild(new DOMElement("currency", $transaction->getCurrency())); if ($transaction->getExpirationPeriod() === 60) $element->appendChild(new DOMElement("expirationPeriod", "PT1H")); else $element->appendChild(new DOMElement("expirationPeriod", "PT".$transaction->getExpirationPeriod()."M")); $element->appendChild(new DOMElement("language", $transaction->getLanguage())); $element->appendChild(new DOMElement("description", $transaction->getDescription())); $element->appendChild(new DOMElement("entranceCode", $transaction->getEntranceCode())); } ///Deserialize/// /** * @param \DOMDocument $xml * @return \iDEALConnector\Entities\AbstractResponse */ public function deserialize(DOMDocument $xml) { $this->checkForErrorMessage($xml); return $this->deserializeResponse($xml->documentElement); } private function checkForErrorMessage(DOMDocument $doc) { if ($doc->documentElement->tagName === "AcquirerErrorRes") { $code = null; $message = null; $details = ''; $action = '' ; $consumerMessage = '' ; if($doc->documentElement->hasChildNodes()) { $elements = $doc->documentElement->getElementsByTagName("Error"); if ($elements->length === 1) { try { /* @var $element \DOMElement */ $element = $elements->item(0); $code = $element->getElementsByTagName("errorCode")->item(0)->nodeValue; $message = $element->getElementsByTagName("errorMessage")->item(0)->nodeValue; $nodes = $element->getElementsByTagName("errorDetail"); if ($nodes->length === 1) $details = $nodes->item(0)->nodeValue; $nodes = $element->getElementsByTagName("suggestedAction"); if ($nodes->length === 1) $action = $nodes->item(0)->nodeValue; $nodes = $element->getElementsByTagName("consumerMessage"); if ($nodes->length === 1) $consumerMessage = $nodes->item(0)->nodeValue; } catch(\Exception $e) { //Pass-through to exception throwing if minimum requirements are not met. } } if(is_null($code) || is_null($message)) throw new SerializationException("Invalid format of error response."); throw new iDEALException($code, $message, $details, $action, $consumerMessage); } throw new SerializationException("Error response missing content."); } } private function deserializeResponse(DOMElement $xml) { $timestamp = $xml->getElementsByTagName("createDateTimestamp"); if ($timestamp->length != 1) throw new SerializationException('Element "createDateTimestamp" should be present once.'); $timestamp = new DateTime($timestamp->item(0)->nodeValue); if ($xml->tagName === "DirectoryRes") { return $this->deserializeDirectoryResponse($xml, $timestamp); } else if ($xml->tagName === "AcquirerTrxRes") { return $this->deserializeAcquirerTransactionResponse($xml, $timestamp); } else if ($xml->tagName === "AcquirerStatusRes") { return $this->deserializeAcquirerStatusResponse($xml, $timestamp); } throw new SerializationException('Could not deserialize response.'); } private function deserializeDirectoryResponse(DOMElement $xml, DateTime $createdTimestamp) { /* @var $nodes DOMNodeList */ /* @var $node DOMElement */ $nodes = $this->getChildren($xml, "Acquirer"); $node = $nodes->item(0); $acquirerID = $this->getFirstValue($node, "acquirerID","Acquirer.acquirerID"); $nodes = $this->getChildren($xml, "Directory"); $node = $nodes->item(0); $timestamp = new DateTime( $this->getFirstValue($node, "directoryDateTimestamp","Directory.directoryDateTimestamp")); $countryElements = $this->getChildren($node, "Country", "Directory.Country", -1); $countries = array(); /* @var $country DOMElement */ foreach($countryElements as $country) { require_once (__DIR__ . "/../Entities/Issuer.php"); require_once (__DIR__ . "/../Entities/Country.php"); $names = $this->getFirstValue($country, "countryNames","Directory.Country.countryNames"); $subNodes = $this->getChildren($country, "Issuer", "Directory.Country.Issuer", -1); $issuers = array(); /* @var $issuer DOMElement */ foreach($subNodes as $issuer) { $id = $this->getFirstValue($issuer, "issuerID","Directory.Country.Issuer.issuerID"); $name = $this->getFirstValue($issuer, "issuerName","Directory.Country.Issuer.issuerName"); array_push($issuers, new \iDEALConnector\Entities\Issuer($id, $name)); } array_push($countries, new \iDEALConnector\Entities\Country($names, $issuers)); } return new DirectoryResponse($createdTimestamp, $timestamp, $acquirerID, $countries); } private function deserializeAcquirerTransactionResponse(DOMElement $xml, DateTime $createdTimestamp) { /* @var $nodes DOMNodeList */ /* @var $node DOMElement */ $nodes = $this->getChildren($xml, "Acquirer"); $node = $nodes->item(0); $acquirerID = $this->getFirstValue($node, "acquirerID","Acquirer.acquirerID"); $nodes = $this->getChildren($xml, "Issuer"); $node = $nodes->item(0); $issuerAuthenticationUrl = $this->getFirstValue($node, "issuerAuthenticationURL","Issuer.issuerAuthenticationURL"); $nodes = $this->getChildren($xml, "Transaction"); $node = $nodes->item(0); $transactionId = $this->getFirstValue($node, "transactionID","Transaction.transactionID"); $transactionCreateDateTimestamp = new DateTime($this->getFirstValue( $node, "transactionCreateDateTimestamp", "Transaction.transactionCreateDateTimestamp")); $purchaseID = $this->getFirstValue($node, "purchaseID","Transaction.purchaseID"); return new AcquirerTransactionResponse( $acquirerID, $issuerAuthenticationUrl, $purchaseID, $transactionId, $transactionCreateDateTimestamp, $createdTimestamp); } private function deserializeAcquirerStatusResponse(DOMElement $xml, DateTime $createdTimestamp) { /* @var $nodes DOMNodeList */ /* @var $node DOMElement */ $nodes = $this->getChildren($xml, "Acquirer"); $node = $nodes->item(0); $acquirerID = $this->getFirstValue($node, "acquirerID","Acquirer.acquirerID"); $nodes = $this->getChildren($xml, "Transaction"); $node = $nodes->item(0); $transactionId = $this->getFirstValue($node, "transactionID","Transaction.transactionID"); $status = $this->getFirstValue($node, "status","Transaction.status"); $timestamp = new DateTime($this->getFirstValue($node, "statusDateTimestamp","Transaction.statusDateTimestamp")); $consumerName = $this->getFirstValue($node, "consumerName","Transaction.consumerName", 0); $consumerIBAN = $this->getFirstValue($node, "consumerIBAN","Transaction.consumerIBAN", 0); $consumerBIC = $this->getFirstValue($node, "consumerBIC","Transaction.consumerBIC", 0); $amount = floatval($this->getFirstValue($node, "amount","Transaction.amount", 0)); $currency = $this->getFirstValue($node, "currency","Transaction.currency", 0); return new AcquirerStatusResponse( $acquirerID, $amount, $consumerBIC, $consumerIBAN, $consumerName, $createdTimestamp, $currency, $status, $timestamp, $transactionId); } private function getChildren(DOMElement $element, $tag, $key = null, $occurs = 1) { if(is_null($key)) $key = $tag; $nodes = $element->getElementsByTagName($tag); if ($occurs === 0 && $nodes->length != 1) throw new SerializationException("Element '$key' should be present once."); if ($occurs === 1 && $nodes->length < 1) throw new SerializationException("Element '$key' should be present at least once."); return $nodes; } private function getFirstValue(DOMElement $node, $tag, $key, $occurs = 1) { /* @var $nodes DOMNodeList */ $nodes = $node->getElementsByTagName($tag); if ($nodes->length === 0) return null; if ($occurs === 1 && $nodes->length != 1) throw new SerializationException("Element '$key' should be present once."); if ($occurs === -1 && $nodes->length < 1) throw new SerializationException("Element '$key' should be present at least once."); return $nodes->item(0)->nodeValue; } } PK\}kY  Jdefault/plugins/payment/ideal/lib/Entities/AcquirerTransactionResponse.phpnu[acquirerID = $acquirerID; $this->issuerAuthenticationURL = $issuerAuthenticationURL; $this->purchaseID = $purchaseID; $this->transactionID = $transactionID; $this->transactionTimestamp = $transactionTimestamp; } /** * @return string */ public function getPurchaseID() { return $this->purchaseID; } /** * @return string */ public function getTransactionID() { return $this->transactionID; } /** * @return DateTime */ public function getTransactionTimestamp() { return $this->transactionTimestamp; } /** * @return string */ public function getAcquirerID() { return $this->acquirerID; } /** * @return string */ public function getIssuerAuthenticationURL() { return $this->issuerAuthenticationURL; } } PK\PP5default/plugins/payment/ideal/lib/Entities/Issuer.phpnu[id = $id; $this->name = $name; } /** * @return string */ public function getId() { return $this->id; } /** * @return string */ public function getName() { return $this->name; } } PK\JVXl?default/plugins/payment/ideal/lib/Entities/AbstractResponse.phpnu[createDateTimestamp = $createDateTimestamp; } /** * @return DateTime */ public function getCreateDateTimestamp() { return $this->createDateTimestamp; } } PK\+y00?default/plugins/payment/ideal/lib/Entities/DirectoryRequest.phpnu[merchant = $merchant; } /** * @return Merchant */ public function getMerchant() { return $this->merchant; } } PK\;a33Edefault/plugins/payment/ideal/lib/Entities/AcquirerStatusResponse.phpnu[acquirerID = $acquirerID; $this->amount = $amount; $this->consumerBIC = $consumerBIC; $this->consumerIBAN = $consumerIBAN; $this->consumerName = $consumerName; $this->currency = $currency; $this->status = $status; $this->statusTimestamp = $statusTimestamp; $this->transactionID = $transactionID; } /** * @return string */ public function getAcquirerID() { return $this->acquirerID; } /** * @return float */ public function getAmount() { return $this->amount; } /** * @return string */ public function getConsumerBIC() { return $this->consumerBIC; } /** * @return string */ public function getConsumerIBAN() { return $this->consumerIBAN; } /** * @return string */ public function getConsumerName() { return $this->consumerName; } /** * @return string */ public function getCurrency() { return $this->currency; } /** * @return string */ public function getStatus() { return $this->status; } /** * @return DateTime */ public function getStatusTimestamp() { return $this->statusTimestamp; } /** * @return string */ public function getTransactionID() { return $this->transactionID; } } PK\O!!>default/plugins/payment/ideal/lib/Entities/AbstractRequest.phpnu[createDateTimestamp = new DateTime(); } /** * @return DateTime */ public function getCreateDateTimestamp() { return $this->createDateTimestamp; } /** * @return string */ public function getVersion() { return "3.3.1"; } } PK\ =7default/plugins/payment/ideal/lib/Entities/Merchant.phpnu[merchantID = $merchantID; $this->merchantReturnURL = $merchantReturnURL; $this->subID = $subID; } /** * @return string */ public function getMerchantID() { return $this->merchantID; } /** * @return int */ public function getSubID() { return $this->subID; } /** * @return string */ public function getMerchantReturnURL() { return $this->merchantReturnURL; } } PK\K\6default/plugins/payment/ideal/lib/Entities/Country.phpnu[countryNames = $countryNames; $this->issuers = $issuers; } /** * @return string */ public function getCountryNames() { return $this->countryNames; } /** * @return Issuer[] */ public function getIssuers() { return $this->issuers; } } PK\Idefault/plugins/payment/ideal/lib/Entities/AcquirerTransactionRequest.phpnu[issuerID = $issuerID; $this->merchant = $merchant; $this->transaction = $transaction; } /** * @return string */ public function getIssuerID() { return $this->issuerID; } /** * @return Merchant */ public function getMerchant() { return $this->merchant; } /** * @return Transaction */ public function getTransaction() { return $this->transaction; } } PK\SccDdefault/plugins/payment/ideal/lib/Entities/AcquirerStatusRequest.phpnu[merchant = $merchant; $this->transactionID = $transactionID; } /** * @return Merchant */ public function getMerchant() { return $this->merchant; } /** * @return string */ public function getTransactionID() { return $this->transactionID; } } PK\W9@default/plugins/payment/ideal/lib/Entities/DirectoryResponse.phpnu[directoryDate = $directoryDate; $this->acquirerID = $acquirerID; $this->countries = $countries; } /** * @return string */ public function getAcquirerID() { return $this->acquirerID; } /** * @return Country[] */ public function getCountries() { return $this->countries; } /** * @return DateTime */ public function getDirectoryDate() { return $this->directoryDate; } } PK\: : :default/plugins/payment/ideal/lib/Entities/Transaction.phpnu[amount = $amount; $this->currency = $currency; $this->description = $description; $this->entranceCode = $entranceCode; $this->expirationPeriod = $expirationPeriod; $this->language = $language; $this->purchaseId = $purchaseID; } /** * Amount * @return float */ public function getAmount() { return $this->amount; } /** * Currency * @return string */ public function getCurrency() { return $this->currency; } /** * @return string */ public function getDescription() { return $this->description; } /** * Entrance code * @return string */ public function getEntranceCode() { return $this->entranceCode; } /** * Expiration period * @return int */ public function getExpirationPeriod() { return $this->expirationPeriod; } /** * Language * @return string */ public function getLanguage() { return $this->language; } /** * Purchase number * @return string */ public function getPurchaseId() { return $this->purchaseId; } } PK\@Kdefault/plugins/payment/ideal/lib/Configuration/IConnectorConfiguration.phpnu[loadFromFile($pathOrArray); else $this->loadFromArray($pathOrArray); } private function loadFromFile($path) { $file = fopen($path,'r'); $config_data = array(); if ($file) { while (!feof($file)) { $buffer = fgets($file); /* @var $buffer array() */ $buffer = trim($buffer); if (!empty($buffer)) { if ($buffer[0] != '#') { $pos = strpos($buffer, '='); if ($pos > 0 && $pos != (strlen($buffer) - 1)) { $dumb = trim(substr($buffer, 0, $pos)); if (!empty($dumb)) { // Populate the configuration array $config_data[strtoupper(substr($buffer, 0, $pos))] = substr($buffer, $pos + 1); } } } } } } fclose($file); if(isset($config_data['MERCHANTID'])) $this->merchantID = $config_data['MERCHANTID']; if(isset($config_data['SUBID'])) $this->subID = intval($config_data['SUBID']); if(isset($config_data['MERCHANTRETURNURL'])) $this->returnURL = $config_data['MERCHANTRETURNURL']; if(isset($config_data['ACQUIRERURL'])) { $this->acquirerDirectoryURL = $config_data['ACQUIRERURL']; $this->acquirerStatusURL = $config_data['ACQUIRERURL']; $this->acquirerTransactionURL = $config_data['ACQUIRERURL']; } if(isset($config_data['ACQUIRERTIMEOUT'])) $this->timeout = intval($config_data['ACQUIRERTIMEOUT']); if(isset($config_data['EXPIRATIONPERIOD'])) { if ($config_data['EXPIRATIONPERIOD'] === "PT1H") $this->expirationPeriod = 60; else { $value = substr($config_data['EXPIRATIONPERIOD'], 2, strlen($config_data['EXPIRATIONPERIOD']) - 3); if (is_numeric($value)) $this->expirationPeriod = intval($value); } } if(isset($config_data['CERTIFICATE0'])) $this->acquirerCertificate = $config_data['CERTIFICATE0']; if(isset($config_data['PRIVATECERT'])) $this->certificate = $config_data['PRIVATECERT']; if(isset($config_data['PRIVATEKEY'])) $this->privateKey = $config_data['PRIVATEKEY']; if(isset($config_data['PRIVATEKEYPASS'])) $this->passphrase = $config_data['PRIVATEKEYPASS']; if(isset($config_data['PROXY'])) $this->proxy = $config_data['PROXY']; if(isset($config_data['PROXYACQURL'])) $this->proxyUrl = $config_data['PROXYACQURL']; if(isset($config_data['LOGFILE'])) $this->logFile = $config_data['LOGFILE']; if(isset($config_data['TRACELEVEL'])) { $level = $config_data['TRACELEVEL']; if ($level === "DEBUG") $this->logLevel = LogLevel::Debug; else if ($level === "ERROR") $this->logLevel = LogLevel::Error; } } private function loadFromArray($config_data) { if(isset($config_data['MERCHANTID'])) $this->merchantID = $config_data['MERCHANTID']; if(isset($config_data['SUBID'])) $this->subID = intval($config_data['SUBID']); if(isset($config_data['MERCHANTRETURNURL'])) $this->returnURL = $config_data['MERCHANTRETURNURL']; if(isset($config_data['ACQUIRERURL'])) { $this->acquirerDirectoryURL = $config_data['ACQUIRERURL']; $this->acquirerStatusURL = $config_data['ACQUIRERURL']; $this->acquirerTransactionURL = $config_data['ACQUIRERURL']; } if(isset($config_data['ACQUIRERTIMEOUT'])) $this->timeout = intval($config_data['ACQUIRERTIMEOUT']); if(isset($config_data['EXPIRATIONPERIOD'])) { if ($config_data['EXPIRATIONPERIOD'] === "PT1H") $this->expirationPeriod = 60; else { $value = substr($config_data['EXPIRATIONPERIOD'], 2, strlen($config_data['EXPIRATIONPERIOD']) - 3); if (is_numeric($value)) $this->expirationPeriod = intval($value); } } if(isset($config_data['CERTIFICATE0'])) $this->acquirerCertificate = $config_data['CERTIFICATE0']; if(isset($config_data['PRIVATECERT'])) $this->certificate = $config_data['PRIVATECERT']; if(isset($config_data['PRIVATEKEY'])) $this->privateKey = $config_data['PRIVATEKEY']; if(isset($config_data['PRIVATEKEYPASS'])) $this->passphrase = $config_data['PRIVATEKEYPASS']; if(isset($config_data['PROXY'])) $this->proxy = $config_data['PROXY']; if(isset($config_data['PROXYACQURL'])) $this->proxyUrl = $config_data['PROXYACQURL']; if(isset($config_data['LOGFILE'])) $this->logFile = $config_data['LOGFILE']; if(isset($config_data['TRACELEVEL'])) { $level = $config_data['TRACELEVEL']; if ($level === "DEBUG") $this->logLevel = LogLevel::Debug; else if ($level === "ERROR") $this->logLevel = LogLevel::Error; } if(isset($config_data['DEBUGLOG'])) $this->debugLog = $config_data['DEBUGLOG'] > 0; } public function getAcquirerCertificatePath() { return $this->acquirerCertificate; } public function getCertificatePath() { return $this->certificate; } public function getExpirationPeriod() { return $this->expirationPeriod; } public function getMerchantID() { return $this->merchantID; } public function getPassphrase() { return $this->passphrase; } public function getPrivateKeyPath() { return $this->privateKey; } public function getMerchantReturnURL() { return $this->returnURL; } public function getSubID() { return $this->subID; } public function getAcquirerTimeout() { return $this->timeout; } public function getAcquirerDirectoryURL() { return $this->acquirerDirectoryURL; } public function getAcquirerStatusURL() { return $this->acquirerStatusURL; } public function getAcquirerTransactionURL() { return $this->acquirerTransactionURL; } /** * @return string */ public function getProxy() { return $this->proxy; } /** * @return string */ public function getProxyUrl() { return $this->proxyUrl; } /** * @return string */ public function getLogFile() { return $this->logFile; } /** * @return int */ public function getLogLevel() { return $this->logLevel; } public function getDebugLog() { return $this->debugLog; } } PK\D?default/plugins/payment/ideal/lib/Exceptions/iDEALException.phpnu[errorCode = $code; $this->errorDetail = $errorDetail; $this->suggestedAction = $suggestedAction; $this->consumerMessage = $consumerMessage; } public function getConsumerMessage() { return $this->consumerMessage; } public function getErrorCode() { return $this->errorCode; } public function getErrorDetail() { return $this->errorDetail; } public function getSuggestedAction() { return $this->suggestedAction; } } PK\#``Gdefault/plugins/payment/ideal/lib/Exceptions/SerializationException.phpnu[xml; } } PK\HllCdefault/plugins/payment/ideal/lib/Exceptions/ConnectorException.phpnu[xml; } } PK\ss4default/plugins/payment/ideal/lib/Log/DefaultLog.phpnu[logLevel = $logLevel; // $this->logPath = $logPath; // } function __construct($debugLog) { $this->debugLog = $debugLog; } public function logAPICall($method, AbstractRequest $request) { // if ($this->logLevel === 0) if ($this->debugLog) $this->log("Entering[".$method."]", $request); } public function logAPIReturn($method, AbstractResponse $response) { // if ($this->logLevel === 0) if ($this->debugLog) $this->log("Exiting[".$method."]", $response); } public function logRequest($xml) { // if ($this->logLevel === 0) if ($this->debugLog) $this->log("Request", $xml); } public function logResponse($xml) { // if ($this->logLevel === 0) if ($this->debugLog) $this->log("Response", $xml); } public function logErrorResponse(iDEALException $exception) { $this->log("ErrorResponse", $exception); } public function logException(ConnectorException $exception) { $this->log("Exception", $exception); } private function log($message, $value) { // $now = new DateTime(); // file_put_contents($this->logPath, $now->format('Y-m-d H:i:s').' '.$message."\n".serialize($value)."\n\n", FILE_APPEND); \Am_Di::getInstance()->errorLogTable->log("iDEAL debug-log: " . $message."[".serialize($value)."]"); } } PK\3bb2default/plugins/payment/ideal/lib/Log/LogLevel.phpnu[validateMerchant($request->getMerchant()); } else if ($className === "iDEALConnector\Entities\AcquirerTransactionRequest") { /* @var $request AcquirerTransactionRequest */ $this->validateAcquirerTransactionRequest($request); } else if ($className === "iDEALConnector\Entities\AcquirerStatusRequest") { /* @var $request AcquirerStatusRequest */ $this->validateAcquirerStatusRequest($request); } else if ($className === "iDEALConnector\Entities\DirectoryResponse") { /* @var $request DirectoryResponse */ $this->validateDirectoryResponse($request); } else if ($className === "iDEALConnector\Entities\AcquirerTransactionResponse") { /* @var $request AcquirerTransactionResponse */ $this->validateAcquirerTransactionResponse($request); } else if ($className === "iDEALConnector\Entities\AcquirerStatusResponse") { /* @var $request AcquirerStatusResponse */ $this->validateAcquirerStatusResponse($request); } else throw new ValidationException('Given object type could not be validated.'); } private function validateAcquirerStatusRequest(AcquirerStatusRequest $input) { if(strlen($input->getTransactionID()) !== 16) throw new ValidationException("Transaction.transactionID length not 16."); $length = preg_match('/[0-9]+/', $input->getTransactionID(), $matches); if ($length !== 1 || $matches[0] !== $input->getTransactionID()) throw new ValidationException("Transaction.transactionID does not match format."); $this->validateMerchant($input->getMerchant()); } private function validateAcquirerTransactionRequest(AcquirerTransactionRequest $input) { $length = preg_match('/[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}/', $input->getIssuerID(), $matches); if ($length !== 1 || $matches[0] !== $input->getIssuerID()) throw new ValidationException("Issuer.issuerID does not match format."); $this->validateMerchant($input->getMerchant()); $this->validateTransaction($input->getTransaction()); } private function validateMerchant(Merchant $merchant) { if (strlen($merchant->getMerchantID()) !== 9) throw new ValidationException("Merchant.merchantID length is not 9"); $length = preg_match('/[0-9]+/',$merchant->getMerchantID(), $matches); if ($length !== 1 || $matches[0] !== $merchant->getMerchantID()) throw new ValidationException("Merchant.merchantID does not match format."); if ($merchant->getSubID() > 999999 || $merchant->getSubID() < 0) throw new ValidationException("Merchant.subID value must be between 0 and 999999."); if (strlen($merchant->getMerchantReturnURL()) > 512) throw new ValidationException("Merchant.merchantReturnURL length is to large."); } private function validateTransaction(Transaction $transaction){ if ($transaction->getAmount() < 0 || $transaction->getAmount() >= 1000000000000) throw new ValidationException("Transaction.amount outside value range."); if($transaction->getCurrency() !== "EUR") throw new ValidationException("Transaction.currency does not match format."); if($transaction->getExpirationPeriod() < 1 || $transaction->getExpirationPeriod() > 60) throw new ValidationException("Transaction.expirationPeriod length outside range('PT1M', 'PT1H')."); if(strlen($transaction->getLanguage()) !== 2) throw new ValidationException("Transaction.language length not 2."); if (strlen($transaction->getDescription()) < 1 || strlen($transaction->getDescription()) > 35) throw new ValidationException("Transaction.description length outside range(1, 35)."); if(strlen($transaction->getEntranceCode()) < 1 || strlen($transaction->getEntranceCode()) > 40) throw new ValidationException("Transaction.entranceCode length outside range(1, 35)."); $length = preg_match('/[a-z]+/', $transaction->getLanguage(), $matches); if ($length !== 1 || $matches[0] !== $transaction->getLanguage()) throw new ValidationException("Transaction.language does not match format."); $length = preg_match('/[a-zA-Z0-9]+/',$transaction->getEntranceCode(), $matches); if ($length !== 1 || $matches[0] !== $transaction->getEntranceCode()) throw new ValidationException("Transaction.entranceCode does not match format."); $length = preg_match('/[a-zA-Z0-9]+/',$transaction->getPurchaseId(), $matches); if ($length !== 1 || $matches[0] !== $transaction->getPurchaseId()) throw new ValidationException("Transaction.purchaseId does not match format."); } private function validateDirectoryResponse(DirectoryResponse $response) { $i = 0; foreach ($response->getCountries() as $country) { $length = strlen($country->getCountryNames()); if ($length < 1 || $length > 128) throw new ValidationException("Country.issuerID does not match format."); $j = 0; foreach ($country->getIssuers() as $issuer) { $length = preg_match('/[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}/', $issuer->getId(), $matches); if ($length !== 1 || $matches[0] !== $issuer->getId()) throw new ValidationException("Country[$i].Issuer[$j].issuerID does not match format."); $length = strlen($issuer->getName()); if ($length < 1 || $length > 35) throw new ValidationException("Country[$i].Issuer[$j].issuerName does not match format."); $j++; } $i++; } } private function validateAcquirerTransactionResponse(AcquirerTransactionResponse $response) { $length = strlen ($response->getAcquirerID()); if ($length !== 4) throw new ValidationException("Acquirer.acquirerID does not match length."); $length = preg_match('/[0-9]+/', $response->getAcquirerID(), $matches); if ($length !== 1 || $matches[0] !== $response->getAcquirerID()) throw new ValidationException("Acquirer.acquirerID does not match format."); $length = strlen ($response->getIssuerAuthenticationURL()); if ($length > 512) throw new ValidationException("Issuer.issuerAuthenticationURL exceeds length."); $length = strlen ($response->getTransactionID()); if ($length !== 16) throw new ValidationException("Transaction.transactionID exceeds length."); $length = preg_match('/[0-9]+/', $response->getTransactionID(), $matches); if ($length !== 1 || $matches[0] !== $response->getTransactionID()) throw new ValidationException("Transaction.transactionID does not match format."); $length = strlen ($response->getPurchaseID()); if ($length < 1 || $length > 35) throw new ValidationException("Transaction.purchaseID length not in range(1,35)."); $length = preg_match('/[a-zA-Z0-9]+/', $response->getPurchaseID(), $matches); if ($length !== 1 || $matches[0] !== $response->getPurchaseID()) throw new ValidationException("Transaction.purchaseID does not match format."); } private function validateAcquirerStatusResponse(AcquirerStatusResponse $response) { $length = strlen ($response->getAcquirerID()); if ($length !== 4) throw new ValidationException("Acquirer.acquirerID does not match length."); $length = preg_match('/[0-9]+/', $response->getAcquirerID(), $matches); if ($length !== 1 || $matches[0] !== $response->getAcquirerID()) throw new ValidationException("Acquirer.acquirerID does not match format."); $length = strlen ($response->getTransactionID()); if ($length !== 16) throw new ValidationException("Transaction.transactionID exceeds length."); $length = preg_match('/[0-9]+/', $response->getTransactionID(), $matches); if ($length !== 1 || $matches[0] !== $response->getTransactionID()) throw new ValidationException("Transaction.transactionID does not match format."); $length = preg_match('/Open|Success|Failure|Expired|Cancelled/', $response->getStatus(), $matches); if ($length !== 1 || $matches[0] !== $response->getStatus()) throw new ValidationException("Transaction.status does not match format."); } } PK\(##4default/plugins/payment/ideal/lib/iDEALConnector.phpnu[log = $log; $this->configuration = $configuration; date_default_timezone_set('UTC'); $this->serializer = new XmlSerializer(); $this->signer = new XmlSecurity(); $this->validator = new EntityValidator(); $this->merchant = new Merchant($this->configuration->getMerchantID(), $this->configuration->getSubID(), $this->configuration->getMerchantReturnURL()); } /** * This is a conveninence method to create an instance of iDEALConnector using the default implementations of IConnectorConfiguration and IConnector Log * @param string $configurationPath The path of your config.conf file * @return iDEALConnector */ public static function getDefaultInstance($configurationPath) { $config = new DefaultConfiguration($configurationPath); // $config = new AmemberConfiguration($configurationArray); return new iDEALConnector($config, new DefaultLog($config->getDebugLog())); // return new iDEALConnector($config, new DefaultLog($config->getLogLevel(),$config->getLogFile())); } /** * Get directory listing. * * @return Entities\DirectoryResponse * @throws Exceptions\SerializationException * @throws Exceptions\iDEALException * @throws Exceptions\ValidationException * @throws Exceptions\SecurityException */ public function getIssuers() { try{ $request = new DirectoryRequest($this->merchant); $this->log->logAPICall("getIssuers()", $request); $this->validator->validate($request); $response = $this->sendRequest($request, $this->configuration->getAcquirerDirectoryURL()); $this->validator->validate($response); $this->log->logAPIReturn("getIssuers()", $response); return $response; } catch(iDEALException $ex) { $this->log->logErrorResponse($ex); throw $ex; } catch(ValidationException $ex) { $this->log->logException($ex); throw $ex; } catch(SerializationException $ex) { $this->log->logException($ex); throw $ex; } catch(SecurityException $ex) { $this->log->logException($ex); throw $ex; } } /** * Start a transaction. * * @param $issuerID * @param Entities\Transaction $transaction * @param null $merchantReturnUrl * @throws Exceptions\SerializationException * @throws Exceptions\iDEALException * @throws Exceptions\ValidationException * @throws Exceptions\SecurityException * @return Entities\AcquirerTransactionResponse */ public function startTransaction($issuerID, Transaction $transaction, $merchantReturnUrl = null) { try{ $merchant = $this->merchant; if (!is_null($merchantReturnUrl)) $merchant = new Merchant($this->configuration->getMerchantID(), $this->configuration->getSubID(), $merchantReturnUrl); $request = new AcquirerTransactionRequest($issuerID, $merchant, $transaction); $this->log->logAPICall("startTransaction()", $request); $this->validator->validate($request); $response = $this->sendRequest($request, $this->configuration->getAcquirerTransactionURL()); $this->validator->validate($response); $this->log->logAPIReturn("startTransaction()", $response); return $response; } catch(iDEALException $iex) { $this->log->logErrorResponse($iex); throw $iex; } catch(ValidationException $ex) { $this->log->logException($ex); throw $ex; } catch(SerializationException $ex) { $this->log->logException($ex); throw $ex; } catch(SecurityException $ex) { $this->log->logException($ex); throw $ex; } } /** * Get a transaction status. * * @param $transactionID * @throws Exceptions\SerializationException * @throws Exceptions\iDEALException * @throws Exceptions\ValidationException * @throws Exceptions\SecurityException * @return Entities\AcquirerStatusResponse */ public function getTransactionStatus($transactionID) { try{ $request = new AcquirerStatusRequest($this->merchant, $transactionID); $this->log->logAPICall("startTransaction()", $request); $this->validator->validate($request); $response = $this->sendRequest($request, $this->configuration->getAcquirerStatusURL()); $this->validator->validate($response); $this->log->logAPIReturn("startTransaction()", $response); return $response; } catch(iDEALException $iex) { $this->log->logErrorResponse($iex); throw $iex; } catch(ValidationException $ex) { $this->log->logException($ex); throw $ex; } catch(SerializationException $ex) { $this->log->logException($ex); throw $ex; } catch(SecurityException $ex) { $this->log->logException($ex); throw $ex; } } /* * Returns the assigned configuration. */ public function getConfiguration() { return $this->configuration; } private function sendRequest($request, $url) { $xml = $this->serializer->serialize($request); $this->signer->sign( $xml, $this->configuration->getCertificatePath(), $this->configuration->getPrivateKeyPath(), $this->configuration->getPassphrase() ); $request = $xml->saveXML(); $this->log->logRequest($request); if(!is_null($this->configuration->getProxy())) $response = WebRequest::post($url, $request, $this->configuration->getProxy()); else $response = WebRequest::post($url, $request); $this->log->logResponse($response); $doc = new DOMDocument('1.0', 'utf-8'); $doc->loadXML($response); $verified = $this->signer->verify($doc, $this->configuration->getAcquirerCertificatePath()); if (!$verified) throw new SecurityException('Response message signature check fails.'); return $this->serializer->deserialize($doc); } } PK\P5default/plugins/payment/ideal/lib/Http/WebRequest.phpnu[setLayout('layout.phtml'); ?>

      iDEAL betaling

      Selecteer uw bank
      Selecteer uw bank en klik op 'Verder' om door te
      gaan naar het iDEAL betaalscherm van uw bank.

      Omschrijvingdescription; ?>
      Bedragprice, 2, ',', ''); ?>
      Uw bankbanksSelect; ?>


      PK\1[ ! !Jdefault/plugins/payment/ideal/certs/iDEAL_How-To-Generate-Certificates.pdfnu[%PDF-1.5 % 1 0 obj <>>> endobj 2 0 obj <> endobj 3 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 4 0 R/Group<>/Tabs/S/StructParents 0>> endobj 4 0 obj <> stream xXnF}G2V;w _j8M-l̒M"sΞ=3K6};t~}cz`r5:߽cgl17lq?SjAt"C\M'7b% gkP;u있N'VpI!L91K67lEO7zI*V|I7"Ub C#b[>H<^ }|NNFr 52VxW3n2褪<9_Z9NtJNA$NN9$GnSK]rt}rt-ѡ /t<K7\뺖Y.@%rDin[eU| ro²3ǁỦ 2NqcޕP[b[ah:;S%?5UTJ_JYmj@ok0Ơ{GMU9 @E݈ןX>PJ<3̊}}v.ZэYy՟2`ˉR@ !_`8ׇv(ʇu#BY-W{4u=U; B UkX֛e6'=?&${ S8iKAc^vzC9μk,;8ϥ.B-C }7J'A>[ h;cVmxB9(^Xj:v]Ge{=q QbWAp"վ>T RTA*Ñ4" .45iۛlGs48zHɣy)qv`%c${Lh:ֱ$ (Fuɣ):Dxx锼\04ymve1X: ~MhHG> R7. c4 8fTG_ZN2e^SFo@rf怑٪QB]8(o脊ͯgkVO'< endstream endobj 5 0 obj <> endobj 6 0 obj <> endobj 7 0 obj <> endobj 8 0 obj <> endobj 9 0 obj <> stream JFIFDuckydC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222do" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?(o[Ӽ9Ojgo.}(A'@WyCI\?v<$?z~Wn]?a+7@Ey.߇0|DgQӼq]],|C#t\s'?oEPEP^InQzy$:Dt|+W/VլeY%Wut+8v|@.OO;"<O?4‰?ƽ"v%U_)*gc˰?]r_k^k?|@.O'Ys~=l׌R20eb:pkOa{_=͚LHׯ-߲FۏֹIϊmd"弶7CGې֓OnM^F-Wx_*Zxw./ {}GS*R[8F<q+l.Qtg͔vG&"lό"CBE6hN8#9xl%bLp{b<3(+6!J#@?$](3 jW{mBeK,THğz?REt٩µ;\(9X]~W h<*1>LIqhmysG7)A\kzo{)l)BeER>:޸/ٺ_^*7#1HݼƑ ֠[H{6͞Zog5;C%R5g*rQj-8ڧ5k2 ժnK.0@#yɫ^&SMHBŷOu|GHhc"1&:o?+|p?}/Rke6} }zؘhWs)xk5즴>쥈0ci #1vҴG$*9'^R;K),ޣz ώR"ܣǁ?%RͧRuRjIsG֥qcZH $ r84g*1]>_ $4C܆ڹT}gik? ݮ6ti=G㔶QVU<,ڜUH_n)^ѴQEfyA^InQzy$:DtCͽk m V*[8S jv5{MsCk ǟ`b8 ɺץ_0Pٿu\hX!Ѭ"8f2Xyr~:h&4tjǒqԞՋ4?;JlRVrb\jE5k ź;F٣J윓sWzοiVf(YH\zs\ʯse)GOcR1j=ɭ{O_Js)X\ry:1E>T?QVWK=7D=K^dK!q9X[!Y'zi7$c܏?~ڗۘէs_xU/J ߖ`ȉu#]Vt>T縐QO{ר?? h x3?$|aolNL0n ǟVfJqbxڊr3oP3)dX"A1L+oki7Ej}$FoZÏKח7xXu#9k{xm-b$ h0@zW;m+Vj$)r<7yjZGuulyت 觵uP6>$[lRHBgw;O(?guS_ī9Ρr WTPi߳cM_Ļ9d?6?-zOxC’$zw/nu>}j(((((((((( endstream endobj 10 0 obj <>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 18 0 R 21 0 R 23 0 R 24 0 R 25 0 R 27 0 R 28 0 R 29 0 R 30 0 R 32 0 R 34 0 R 43 0 R 44 0 R 49 0 R 53 0 R 58 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 11 0 R/Group<>/Tabs/S/StructParents 8>> endobj 11 0 obj <> stream x\moFnw 'M{ }0ApdǸDJerI/ofI\q%%"qEj<}b{[g._vϫO}[]_?嫫3 ^fPBaJvu~ϟY}÷>?dew^ߝA&_Bї+_DvO9?ɳg')oW[cnkk6rKSCQ&zqQ/:5?}Z\ /BOx9&y)+ ==%|oqT-o ۬O3]nN3h)\ R!*Tp!IfΑЀZc,1Ř: Y>:[eui%`EJm UatT-m`1*e&8Z|2: ޛIPq4=,q-vw-.Vy+I ^D9Z~,5p=B*;s/ȸr_ "(>[|-__aj}Ӄ=%^}w}o^.LZ-.xC|qamwc~Ɵ]'[% ֢H`h%c (o J0H}C1y@|\ǂɚ(zbʅyHBof*(,+zJ\>]8Tof1ΘŔƘ2:e3/M~L7Kä:jnSc_uLZjC@gpd9F#gڤ|adM6PoK[ vCvX`P`D=j[{ ZCR;ΎE1,KQ&D(e ghi yqՅn&IZI5DQCiv 37sP$9M>F11Ɖ *d&6o[>,\Oȣ?*f##SdFrĔy;*GLn^?/h(=I*3KMۯAi6R3%;JjL'?I xh1Ci!kۏJ~J%ʎ\Fm:xHds_acdQ ϥ:c#OXj0'Ga8) ؕLL_eƵL FĤ, =29>MգV=ZU J>lH$v?U6pgJo<[ٍf aIg)&UkJ;BmSim@dR/A:i/#K8 ćBBg"cY1ė(0n^!O)R&1tWȃm+ g]7^=c()ų-q~{juSq^atyq^4'_¤ `ht҅r.L o\NJ@'O)A jjG4]~}}xe/[ےRJR#1xՄs,%CL\ 9J,K?c.dspָI]0khj[#Dzw)A| am2.F0`jBU hZO; V)+߷toRݾU+V,wjr%PS[YbKUX\bȱˀ'4*(O% f E,K+w#(G+QRŤ[@%ޚh}=RVZ /U :1 Z:Hr`bOˑ[ Gulѥ72GtEU@/ %6y% ]9"٦ZWؘ9M׎nLd%7519ee{\@YLvj*:\L?9K)pfRЌ?~բ9+!Whv1mW-~kdPʊJ/L'GɊ4#+Pf@>++O'+yImYkEǮ QΥ}DlwKDS4s]a`f Nt^\偒y)2=FFXz(N77ZB6뼝tJӶ28W1}_Uuuڇ.OYX6 (IGlnlwWאLvBY:䌞9=^/l*٭ͲSqw,㊵fv,]cqÆλiLmY9O߾HyoUlط5!/};xS]M/ l%#>vd cD@)vӐ Q[U҅jEX v(ۖԿ!C|w&r6cXj7x endstream endobj 12 0 obj <> endobj 13 0 obj [ 14 0 R] endobj 14 0 obj <> endobj 15 0 obj <> endobj 16 0 obj <> endobj 17 0 obj <> stream JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!222222222222222222222222222222222222222222222222223" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+_h8o]R=K(D1J?}[|O]iSQ.Inzxw+S蚽].aTlĜ'G1u+1sexdsG{uծmQ^Y ߤд=wON&p{;NTy ROcF+7;_ M t]cEp)w; m-Ɗ9*3&mr(3n](AAmB8a~i裟\J|kF/5}AO$5TiNJ #(2դErkF;wT_Һ]z?G6LIܛo%uҜw@QEEmB=:[C22X~5V *Zڪ) $ 6z6:d*ɣ.tAqfҁlߐflARb? q5TӓãЧJR*Wow> jw34ʩ| <JtB=N.Y %^68 . G[Mg[.&QpU s\߅Cwk<7F6rv5φFά^ x}ox_bQ]gWŚ,~ ԑU[@k:_T3]-c[6dU*Vӿi\SAfo|E⫝:̷ӯd3$cBcJOxPN'l \ړÏQñZ\|G7${J*+:SM`NT0ӧſe?#ť̏qе?zL:8Q;X_"Y~ 3_::uo> e)ԶQñ|~iGU9VYt.4SR'KEFؠnYɑL+ASo;Rz #ޥQ$DoK^%kvc(=2SWi~xN_^)Եe"K39Ov_J[%c jT{^k"! (罐Wf6!VW)zUdz7V0*}G> g%{VnRPc"s˩-G9 d.^ƱMe89INWc'&cpt|"sեӬcӥWH.~qGLqϭr却xZa,2ptCӎTс%ǜV{df]FAȨd ڳ,hU}*Gk%T+wo?V"O IqV}l,n F d1>K&[ ww$Lf`Ɵq+IF37Sֽ_zcgǑN2+-7=z9hH]eYNAVO\sMMO\ ʝ=Eg&K{˭r?P3PxXh^'V5BKAIh&FX,C?6;h!mȡ+2h[ٮ }?֊>RUeO::_T3_Zx' Rʕ2$J_#j-uwӿi\SAf/xD /ξe+)Um{Gm}Z@g.k[STծy)>;d\e X|v~TmmuWi#b,c=_@Z]}i մH&@zwL_~%I$Ͳ ?4:Vib[чk(e*#־| 6Nr69yG=}:ta ^Ȝ-=KOjώZ49|Belq@VSױ(ᎉ\F5jxzt94Ẉ0#SmvS4<&<_xW^~=V%nԼNÁu=?OeNY2}b')sT YYOĈOZu 0w QdP@FWx׆_ j6nno!0HJ?[G+0hayMHKV@8PX+-ġR'S?`;J{(B`{L!]CX' V!`>ƾ_]*v[Z{+QdyPZ<RnOzw*m4F=0U\wŽP Hʤ{or8!:5wL9@Fci99:沝B/߱:'%ȭ܆x]D Uu HgyOd8x8V/##hd}O(Kda,ͻU3s9ReȪɤNs;}zwS$^(nՔBa^^GOu)Dk4BV+{Ռq۽u]Uڑ-9q }zYn!ӣ*tܛM=[<WJJ)k5|n|M \Q] Q1$QT@TvRTO>{WUNv(0=(h J( ` P*(REBC/֗e;-1EP@Iiako\aTBEQ@(P1EbQEQEQE endstream endobj 18 0 obj <>/F 4/Dest[ 10 0 R/XYZ 68 760 0] /StructParent 11>> endobj 19 0 obj <> endobj 20 0 obj <> endobj 21 0 obj <>/F 4/Dest[ 22 0 R/XYZ 68 760 0] /StructParent 12>> endobj 22 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 61 0 R/Group<>/Tabs/S/StructParents 40>> endobj 23 0 obj <>/F 4/Dest[ 22 0 R/XYZ 68 609 0] /StructParent 13>> endobj 24 0 obj <>/F 4/Dest[ 22 0 R/XYZ 68 308 0] /StructParent 14>> endobj 25 0 obj <>/F 4/Dest[ 26 0 R/XYZ 68 760 0] /StructParent 15>> endobj 26 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 65 0 R 66 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 63 0 R/Group<>/Tabs/S/StructParents 1>> endobj 27 0 obj <>/F 4/Dest[ 26 0 R/XYZ 68 716 0] /StructParent 16>> endobj 28 0 obj <>/F 4/Dest[ 26 0 R/XYZ 68 580 0] /StructParent 17>> endobj 29 0 obj <>/F 4/Dest[ 26 0 R/XYZ 68 235 0] /StructParent 18>> endobj 30 0 obj <>/F 4/Dest[ 31 0 R/XYZ 68 760 0] /StructParent 19>> endobj 31 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 69 0 R] /MediaBox[ 0 0 595.32 841.92] /Contents 68 0 R/Group<>/Tabs/S/StructParents 43>> endobj 32 0 obj <>/F 4/Dest[ 33 0 R/XYZ 68 760 0] /StructParent 20>> endobj 33 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 70 0 R/Group<>/Tabs/S/StructParents 2>> endobj 34 0 obj <>/F 4/Dest[ 42 0 R/XYZ 68 760 0] /StructParent 21>> endobj 35 0 obj <>/XObject<>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 73 0 R/Group<>/Tabs/S/StructParents 3>> endobj 36 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 77 0 R/Group<>/Tabs/S/StructParents 4>> endobj 37 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 80 0 R/Group<>/Tabs/S/StructParents 5>> endobj 38 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 83 0 R/Group<>/Tabs/S/StructParents 6>> endobj 39 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 88 0 R/Group<>/Tabs/S/StructParents 7>> endobj 40 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 90 0 R/Group<>/Tabs/S/StructParents 9>> endobj 41 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 92 0 R/Group<>/Tabs/S/StructParents 10>> endobj 42 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 95 0 R/Group<>/Tabs/S/StructParents 27>> endobj 43 0 obj <>/F 4/Dest[ 42 0 R/XYZ 68 569 0] /StructParent 22>> endobj 44 0 obj <>/F 4/Dest[ 48 0 R/XYZ 68 760 0] /StructParent 23>> endobj 45 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 97 0 R/Group<>/Tabs/S/StructParents 28>> endobj 46 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 100 0 R/Group<>/Tabs/S/StructParents 29>> endobj 47 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 103 0 R/Group<>/Tabs/S/StructParents 30>> endobj 48 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 106 0 R/Group<>/Tabs/S/StructParents 31>> endobj 49 0 obj <>/F 4/Dest[ 52 0 R/XYZ 68 465 0] /StructParent 24>> endobj 50 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 108 0 R/Group<>/Tabs/S/StructParents 32>> endobj 51 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 110 0 R/Group<>/Tabs/S/StructParents 33>> endobj 52 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 113 0 R/Group<>/Tabs/S/StructParents 34>> endobj 53 0 obj <>/F 4/Dest[ 57 0 R/XYZ 68 760 0] /StructParent 25>> endobj 54 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 116 0 R/Group<>/Tabs/S/StructParents 35>> endobj 55 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 119 0 R/Group<>/Tabs/S/StructParents 36>> endobj 56 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 122 0 R/Group<>/Tabs/S/StructParents 37>> endobj 57 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 124 0 R/Group<>/Tabs/S/StructParents 38>> endobj 58 0 obj <>/F 4/Dest[ 60 0 R/XYZ 68 760 0] /StructParent 26>> endobj 59 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 126 0 R/Group<>/Tabs/S/StructParents 39>> endobj 60 0 obj <>/ExtGState<>/XObject<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/MediaBox[ 0 0 595.32 841.92] /Contents 128 0 R/Group<>/Tabs/S/StructParents 45>> endobj 61 0 obj <> stream x\n}7hi&(v7bb(u6x#VٻWk[]I1^-6MFr22&AqO r,Vs }~Wyme7<I4BHB m u۶ϷH+IYH?V]k_D=]h6":n5-aWpW>5ɾþ7O$ ,NU+ -.p{^n7HcY ? ®0-bġ7O&w(E?hGB4z 7T(BiHm`fϯp7 qx2{Diop}PHkbh*ΰH=Y&3F0pxzR5v?]6n"n Ksj.xhwíh'Z$\ */vaS`Ogk.z C'ïk)_K\e:0P+Nm@@"_C 4_1/{SN7ړ-񡲉=ET>NUa?p_Ⴔ !\R'SHYz $ 46;]cw~Ȝ3CGךU6T3Qv:~ZEEJWCBN Q;>wtɚ.\X4SQס}7J2|ŖPo(u7dPc2IϞ,HKg(@hqK>cҝ4&OɛaUBI d#d-w2Iaѥr6 :-6d"wήJ˸L;E ,\.c45E3W}x~,1>U}:佣Tz<,CyKZjJ2u'\-0Sby(vL@tCM&b$5B?Ӓa VvPƺkVBwM&tyIm_1hZ'w](HY_YP6ܕ1=. yw#KAKy98IǾ> 7{,C0 Ӥ7mU:6ǩ Qa' \g~l-Y>iS0[ Nf?/pWW _FMWH/WUhKhV2:l%:)R wWh ÌLҙ0,`_*"bA:Li%ե# `]Ă/zx{Hz{By\V@`q͖5,~1!IU:Wt0"SyAΊWJlEux&5t{w]貂ea\vYT{{{MНT4\PoHhCbkg)J|`QU{'̃)anJ '9I[spdɩcN*aÃ`SId+v<<׹δץA R*w&!6(x̦vywD8]Hwk`횪%(MJ\gƻqO$Q$SHۘumS-C8qM#`̥- sr204r&ͮC/Vֵ"ǡlǸ[҆Wlng󫧂(wmpMN⯝t:0Sb˿se[L;X v7΁K':_"ĚwUݘe ,UQ:[o*ΜKڱfk΍iGJ1S[/s%Jjk)ep{idZTQ}Y&2L}9I퍉6|CKZv 7%H=۝b'IPn^pE%]iхN ˲w <α!yZN Ɣ7dyQl4cUWMt8,0gD9ס0]Q e ;0='Og΀]B'}l0Xv|"~oD%-v#[,g`s}MBanO*YW;`֩gpx۝^ZvԦg=u>Pl VC-hˀW{Jt@Q7Yr4%*x{I`Y͡N> PȻņK$94jGkRjQ'Q>OolSk|bj>Nq}pz3¥St,_b?|!Yӱ\&s㻎>5P%?D$T 74)<P`ٽgyJ꿲-Y*Yʊk EFH t{e#4w"@8;=#$/ 脄D76 cSX mJ綊thU2ף[UZ˙،xnfI/Nq (PE5TPS|-'qvk\Pә;9 r(I&=fkiYIʏ#)5$Jʇm]h/OݗI'µ,9g Q*4aCs+TوPR6P(w贋XfUA+0)LF0\ѫ [$iQދ2M; &-eY E:d7j N NSy&҇XȁNU2> G=f$0?s`b)F -2b0πVC0c1%\m,+"Fa [dS_[=%69s@س@6pilȖ[zrd*G@"@֫2iUNB@ G=d"?+tdtB0&Ydž{ c6YecЯL|GoocA#l5,\& [_CϞ`kqtGO;;%Sc' Ls3(8Lr_u{}QXBިbV.`ˌX:2x3 c QkjJ4#yN>X=!伊ϩÿ=ɢ¿' {9Gl)>\{|\ȥ|BM;#2I5HMӻU]+IP蝧*H0H]8iC!El;7q]O72C=5ؗ1刄m9 l/c7rDm }.4?PoK|f0qDòd'c endstream endobj 62 0 obj <> endobj 63 0 obj <> stream xZ[o۸~GiQM @ӦEz&"5Vl8țG_$Kh;Mpp87|CzjYNo _ev3GzxU,^ȇ_tb~z޼f?VfSD"I2?>6?>"hV`++F"6wf{:`90F.ze~(m -g0Z{'8B፥OZi@;mT-9wuQ&7&ziJ8lʹV|$KWHPL&Fހ7rLAWʭ]6h)ط W^_ac6 ޝp4j^`Թ-9ot<<&[cLkd| D0)f,lignq+ԙKLWܒŒ9AVr b $)gɝI9*vnɂk4ނBLZb*öם2Av'WSeA dBOkF.a'!x0RDX[&>'֪xEf ELF^ej2gu#Dmvf]5RpgϮ8SinE]dQ6$$F3&y¸R ;rvE "xv/uLwK-^`C Rӷ쑵bwn4R(kk gYj%LH-d0)hGJKӶYI捣~4vk750x6*hTہOan} g_rW;}65mk1VXˮ(oOmX+ѾC-KX#%"Io+5^BoDcܢj!uM1^3H\֌Vݙ *7t@#bD%evO endstream endobj 64 0 obj <> endobj 65 0 obj <>/F 4/A<>/StructParent 41>> endobj 66 0 obj <>/F 4/A<>/StructParent 42>> endobj 67 0 obj <> stream x TU3Fqmoۯzhoo|m5IێFMA$&1j6}Q >PDy)5Fc+ ۃs\s}y`LM5{pϹZ{Y֬(W1(֙&uI֤YcPԬXklzU&|:6ODgiWdic1ju\:.KEF\T*z3QYhphÀԸtelrTeLJlx2 ^(V'ŮJYmD֘ѫ`"cVĮ$j(hG&F"C1 Qpp0h4162!&² ݼ2<>*6GFKӊ Q0ˊHJtӊeڈ0]rph@!b><õaap0庈'Q nX_ 8kBX#L,T"\ mmR>zi4F-+CClXnXG|8jBC˖k-Ne`ҥߥZ =4T U,U.28T\,.$ņ,Q,ſKbcC&_80&dIt⨠ ֆcp%/"4N Z '*, [(86] :(1ыV-X*pq^(fbxE D/ Y(drђ3`QыXj"00b#.X<`ኅ/ [h F_/#.OcX@ eйo_v`ؼA D. w :AAo{{!x!s0>tЛsߚ pP@f9,Jfy(~`)2O \ ?rC(0$ A natT#1+_p3LBq@u c/)N)LS(PŤ8t{*Y T3өIr=pˈ \zp@:- , CE xPP!&X$UD H,28F nz/H=!:usORۘhdF1)qq:Ơ̵טq&bD+)_g@Bm ^,MGhGtS^Tc"$:DT$ptp{MS| T٘ht%#:QL3 !l!aTu{H+R6B1Ł0.3\DR&2}4Gt„S^􀀅b=ĐbnlL2=pbl`18?kPR)ZF$P);pF1OrY昜~Qd*JttŪcѱ9z3V.H  EUZZR!ff5 #G7ncœ) DcE *$=24B3I*,Nֳ"hwlu'Y#WuFMۘ04iE1^1^ heC8 6&cl:(&eY%̭0t^Ҟ?rnHTVZ NɗQnܸ}s0TУ,Q_jՃ(j JxY8q)Il`[r+T4z@&_giWc)ZG7ncxyHrXЮH1(I2Vp$ 7h>fJ[B3kiCu&<4kjSk0Z!ZWܸsB /4Luh)Q^I["EV ^[TN pMEwhncZJzHO}Ӯ5hf[ ܸ s̰xyР+FY؂'YyMY$5q!Au/Bd{)Y-MH魻8`Չ/+ Ԝxs wᖄirvԩd< h rR:@&:SN&c#C^pߏʝҴK/{{_{ܹs[ndթ*ReIBA)q[b1 N$*%n@OԀ=Й@bpod3֫8as1Ztw N=4`{Fg}6ܹ?zjP_L_?&6Z zVhN8'[V"+>>I;$Kۋ3)tz1V"F>6Q ^i+**NOOOKK+.p-1qk{o;wB"G,?=P~"=ȉtIx% \'(AgkEz9!.Í cךc!w`PWWPPpƆ#G.%ovoΝC :L𞁅TΡA )BM8!TƖ9?z~u'_WWooa4ݯƝ;twt<)BCYbTP ID,2Tk z8zePI{.rtܾ3?|dJӦC~|\^ydͯ?(}ĉ0 1JݽFם}6W͓Wis~wF[g}y|(O;̔䬆*$˒jl%MC7!TQFh z8cpjM:imoViwu{SƺㆮG~1gN%!1ƻ{ۍ]}6 *+{,ݑweclng*!H@' < P T?&Lݲ!aQ}M لd Ct;w?oޜR=Wŧ7t{O̝@~6dk9 zW_wx돆_~gtL?aoE2L1  :Lr:@u(42ؒ`m/:S,z(0\4Y .c6to<))T~zUǟO;龳8~#>!ƻՎC^̫>楫g튀&Xt:ڬa ful@Un1#m_e-NW!?_LzW5S8f.P\F:q:#U׫Ӧ+KSAR"@F+8EH}0zh8A(`J*\'"*:<9OMKp·ǟОz"ß=???ƫxwz]{gMKWf#iL6Nױ cHve{ ǘb} ?Mo4agfQu;}.~G URQъncQ1ˡg :qs8nnH²8 >-R%6_^лq xO}+yr'O|NtáýSҮG"]ׯ1_:8OF<wE  U6Ad2 P :Ud@qЁb  ^!lݜ#Bwttڳo|:><`ߕ]?xuS۷wi_5p~&s?s锵=v.\7{ @puEpo$Ca3ǹo+\.:ÏQrtL?~oeqrÄTM)fp& m̗*R,1s:rLsJ։@ 4rtنn \v]$-^8xu{1$Vŧ"Ű1v$F@ ɁiMBfl!,cl 8eIDTt@₎A Wn&Z@x}nݏUMWD8q5)HR[Wz;w.ݸNJ\&iMJ 8V%j9=8MоYBTpR4B.ʚSCN-ǁ-* /St[Gw_c.LTΪL $RJYX9X%M a_S@UhXƌ+=(wࢡr0w3hoq!ee Mz4$9pnkƌ`ІreXBklisuiQS)Jtw sW LfhZn}kcµn햍;w.6g+Rp XH~lN3nJ5T$#ORRb)@g#VTA7A :!F/!Gw#pKv8o=i_MTGUQdf<@%YQb hrS I"̗[U8@Is)4F td{G]{W]ܹ?- 7 LTLSU8i&)jT*V&DwgYTŵr"36 Zȷ5>vwܹvjym'~gږ #F)T؄fUhfUG`QN8R1J54]c h F|p-+!ä7nc˄/nNӃ#T#ҲhesAu2Ҡ V6 :q,'_I1a0IL0nI7TedM[2ՙ-i&T#yI{ȫӉ`Ii1V\gJOg I8:qX0 ܀*S_eN7oJ.5,xP"dl(ۘ0S%f7f1a81d=ÖLJ£LzZS(Xٔf"Gd]x[4%I#TH6Xp1=v>c?X2:&y& QV)iF* ۔c1jٜaHӲ}7e/䬴 .I[`݁E W_mբc4 5 >ޓfLۖmٞcFnTgȫ 4BtM7-Rރ1ݑjdD cEJ=YZ,Jim G#lr^='qckЁaK:"@M@TJpa> L*3M4"WCP Ih=jtK =_CZZ}f al:tO1up) q+ܾSB."F8pJ`#R!0J.L0HT!ǧOLu/M#@X3:,G.w?~4#eTc :ns$s {ApYy-uI'-8Kzpsܸ1g:DGhPBQhJ RR)^ sBl*8X$n*i-%nƄI:Y~{֥nˉߵ& hꠤ;%˷V:@WlJ7Ve+?8z%S ڲd5sܸ ͰxhMn1(AaPU#@Ġ-D*KGOcS:5eVUy@8:q@HE;B̒kuRmjH HDG>ݱ&P a@iA lL=4JRq7n_9gOձ# @ؾ:Jqz$Gf_vLdPudz|\ov4ݔRLC\s$P境7n_95i_H 9V`Ŏ,+cgv-'psⅭsL:!P-X3fakm=ĤUr4uK/y1dC\Z]kcubguWN2)3-5bj39l#pcsFMQaS!$=D!wU#stp6&́IϞؙ@N AnNɦZ0vxd X@xH eJ)a =pAj˓Te:ci;rk⅔)Y@iȎߖa3,#=h5jIhEtH=nRTlU̪ݔjmL{DpIu.5]30G9c>!*T6xn` DOk8:q&4i]w%#dG6Dm=Й01ШJӂW[SuThʶ3uXnL6yT6Cm'FeOѿe]]^sQ>0~x'7aj$qX81p/DA-g).(g %R)e8t\oQ?eep@/B2Jurtp6b&Wî=kEhڃpA>Fn V2pAШJ7D'm#FKy > cJfY8OE俑Qޚ ;.mdL~k ) O=+<\x^lH/c#:&ggԈ}g/ݨqb ;O^{G|y</3,OtBӅζ)ou^k ./'ܩ*߸ /!;:0%i~G&^>h=X㿨??ҨhYH8:=B@_{km9wzG岫77 KnL 'ob|͂C_o'?_O>7_磧 ]k۰oj_7=(:<ܸ=T}o.cvf(9`Il4 `~LlݺmS΃76]b"@/ya<̏~]֟oҾ^δƔGRZC*{2;{(nOwʞ(vss"6FM:^{qڵ% wCM<$?xC۶(...*)[g'nُv?hnXY}t3";zBWxXT|pCX/+˞1y<QYFI;] lIޯO|:A - (Ku'ξm9ٙ8~й~{cM{ qW{/ܩ(QO~qQu^LշȟٴĮL㪝WxjύGAρ6\,bTVėR~cugmk׮KOO[nwCdqm~bi?s~򆽾~:Jqq^{fΜxcWS^OG^zb]KӖK;5GW}{yYAQao[yퟅXv-{Nռ凳U}oqw_7GU(>nϬ])#\nc$tL+$-DE1ZYY{s:n9hnظgkc?mo7ܲa?uɛ?:jٻ;|pP^cCCKBO |bZES# {;?_WW|󕸘 ^MʍȘ<)ȌfWohjmhg322>`o_q%G3@.+٢wnYV}{>tO=՛V|}&@vן~~5[Ͻhe. md9`At4:"Ac@z7WUرO?Eh\ʸ=+8a;F䮾}v83xZvvo-?{鏁_̜orןo?{bL/_ɗq6b&csρ7!rLZZf[{q~r~^I= tl^^۳bg]}+vgn{tܺ;}j=\{O;;6N_S|=7n#lۉ49+T|GR4aQ^Iz n8u{ծ97o l[wxmʝQЧ|r`^$1aL't|!krtEBpMeGJJJFqW }n卅U7Z+wvtن>5;gi޽;aq{{9:q&aqJM4QJcSkCc+:F⒃[C%'#vtͩ ҵt[w$+h9 A1 $yԖrx1a0@4 "05(Ҥl峍7y8b߹`ڇkj\:O"wEz?n[^3w֝[;tmw{}IImz%1$jc& $**N2PPL3U,`Uc" T80&*o})(z^6޵s}oI7CӰ`V+#p8݃07nC7o{#=EP57T;vd|]xA{uwjf;2t01 `,ݥ:nE[O񼖟kjij&> ntÛэكںQg7ɕ8܊SQⅇq -'?~j]v LLB#bQ+:OLJfeuTk.tuQGz?҈R4(%4.pspqR8woΝ LLCFcl@ `ښz-ɤ``I8'Zz23ξ]ffWʉ q+щF> Į=gODNN'%ﶋݵ;鞉iXH&]8kV Z4jS\h(=j HO@vk]wHMiOJn nhͣ#ߓpǘY?e}Eˑ w>Et011=- 1~lKct Ày\BS{P׭58u),-*ߓv!}`0ݠGxW#V01 9찴v&SKx'44yyw\a7B!wQE}GGھ9Uq,^Vs'E֣Zt%kviXHX8{nnQ}NQ:9G\&̸P';Ry7'vf3g: ˺5ں t4k'[Pb35$^u_촟4,db D7#˝o9S7;SSkc/W_.kHmcrmB1Q~ΙA"hHcdqشS LLB^Ǥ u$ MUF&OL8z[r;ֻEe7Nh4FE o #HE'.OpE^o ?#Wсא_B&gik&wΟi hܨ"xtPb+`y\Rl F'|]ғ[Y[Uz#E[+t`$r+r9B:(IʹP'Mz3u-'b o{gCcdL:W8111} : QmBYBr=v-|%;H{ ^y]f]C_C>wdJ-1IZZ: :n99G1VFX=[eg7'iģc䉋ѶvT\T{uZ.-tZn"wHj[ =K/W nYwi83xLg倱^߿_?%'2ѯ}]T\dⵒ}{p>?EGb&'0u,m BGM:ƮջN[UbzMߢ?P0==}"g//hA̢ݝwj>z FiM.juݣNz }9^sgD`с2"нQx4_\5!+$_G ecAFv/nTj(4(71w0+54o х([{XEoWЖ?-/V|p2t 56{]cz?mޘvly.əXz? =:09Det4,hYK-5`U"k Zhi|<W4 p_G篣3{樂8}5}|} <&cwV[azbБ,#{?Sq`[?z_n }^K79lt>׭!eEshɚ@L_ɽuVz,ʹi "zfFHBt̟i:3CXY]Ccbݘh 8ׅtϫnRb&Zкh> X$eC%Wӛn ?9n._wzͽZn7c%'o0Qya+zDBt,=Cک>B]]o0'1U*74,Z<) <- J u'&NpO#?C7_u|qz졋h/BmؕJr2n1M~4dtk^J_\7uyүarBpq?:M {$?g`z1{fYj/]SoU7V: ܤE0o"cbŜAAUv<&78ߎJC _@K -Y;<&~KfMc'sK_ٗF1;њrKyaToc.ߛx`C8k^kRڷf^qV&fABnC^G [2+O$_Hc.V>^wԶ-v?%ᫌ"Kwn;uٵڱꮄ]XLL? 6g'@hlLP7jɄУF9tej])q,H`͇߆Pt礪+>Q^x<u_˚7E_BqmcJu[8 #x3g[:~<:0:7)=((.UEu 'Nؾ%8NYQpan'iCYWQVls%bO`uuuWkצ^Zi6R(=y!;ixH&OSG!rQ s kq)o޽G˵љ+et2:VY??q}]r.[lBB%޲iShZ#atɜu8ujKkN<4ȜJt$|\rߡc۷nپmHt?\{,~v҆jmqLV['kZggѵk:~E&A7aL -V6H9zDJU ^(jٺ4qG__ciy~ʻ {[m`vzz7iGGG@@Ͷp4:&&2ctLDV+>YH9*_N;⠢J9([lܼIPVѱctu?7R9oނe>u;lmw~s$:}C 1~Hhh擠X+=MFZzL[ӄ*_}h(h<:0a,ޱt_KA~w/QC^s77Gc=$D" $u\Ѩؑ/SzWid\4,dHS&, |=7 ztT`â_ll9lW>7$K7:(_{fk]7Nxs_LOo'CӰP6N Bsff/OJ}S\@iWG1b˿2k CӰ`svAGѢ/^ZC?+ZУ?H1@~]**Y*~{Z_ ui LLB6%Vuyi _Ғ/F~%GSGZZHr]9vT "t9a5oi6~uɴkk:Ӳ]<>|oI|Z^o4maҦ&ۆM]kL^/x2*I!䫌w"?G&&Y9_gb"=LdtLj}Upa'pexXR75̋cpԳ@ꩊ(DyFKN޻D[7Dq!'\ eCݳBDg]fx:ٜwLM]nj X,B 0t0Vg ШJ<(HL(yQR(H=*Z(z:Qyb޹0W{4@Hn+ÍC&M~˯vT{W]ReժU#̝6~ټU8ED Gyo 9`BE1^HpH G[>.4~.Hp9 I?\wF^5K"^oe&mResW= u@z1hB `pC-VE.P!P%5; :`NK([r€!.0aw21 ZV$x=$~h.&SzG9!oPK%*B$H7@ aBꊳWpyA!҂{HV+}0=LA"9j(I@ p̋₋xStHJ1L,~+Cp{,ytNiY@CRYCz]0,tBC8 ut䅉AZla`bЂ*ɗ0(,t@(7,EGP]Z1i}Pni8b.(7&ܶKkNV\a4<$apQ\70bz & 9p9qGf)EV3|AAYa.gB`d`b2+޵T8JʅA㇡Go"C @`p&")[-6i4,ԫM yDQGK@a,3 bʽ!G7(=`{.M zw< LLB6g+HfBL?h=Rz-Rp#])E"Td*7 .?`b.>3 (U屒L ' xEohb}BӂK#!W8煹(IA =da`b2"dIǏX [RGwX$--4H EH0*B˒'/~qDxٌi(e@;Y@ШS:x~{ xA7=!2wʍb[Y7p-.{dL# cI C2\Dm^{_p: oEB;+WE7Lő|4}_ &{j#vJ1=c=*p..`7b<xI7իl[Ť`T( (M:ڷyO>Ҥ=_t?tЃ wCi vXA;W[tСN}$dDO0$+gH-1U|!uϏD="]r#!~<nJf83;}Dǐ-b92HpOJ>`1'Ƈ9L%u,7·& Zʓx11FޞFuģT&)zEIJb$EQP€qHrOkN +yNx=\1zhG$7EBv*}F`W#v&I~(8̽̽Nhgbz2JC IÇL]R`t1 >J0/)r(ڭ8\ksIn(;:k HlA:Y苳t2pXÍ.Aǂ[i0$_}`t tB;ӔnRHDIuo(Xh1,΃vJqB$c@ XQ/HУHpE Aau`f6e}| {M,CC~^i_P<:}ggԜ@hfJ*^t,zF|<쁷Qb8H/01p͂p^GpQG C }ۨBTW0t0=1mCrW'z $F ]oRxRz sX"L#`qwiICo@z$:}4][s>ek5]m211=,PwxRt{JϳxW~.r1 mI#n{Ю)dj a>X_yu|cnfuEoXꅎ0=J}C 'E 4u/0:0[o`6b~fih$,XhMJ&Ap%8-| S2~T\o(ȡ6)qAY1' ӧ?^yWk ܨ>YEQ;8c=9ɒe$$eo-ˢwlK(DdF1#0 3faVUDBN{4z!oխ[ 'd:as:$N:1!\0Wh /Ҏ$ѡM5KX70/ Ej D(fX=CAW:j7+=^V n\AaUΞ\Jmaᒰ:Dc4,@шSdW,rGpa պ8IfTzT 8F6m0_9_n)nHhK{iEl4zi  #萀Cbъ Ц.fM~ulKT(P Iz@)|ْ18N 1@[R!Jq#T!f_/ЦV)@&b/!sX8; VyUzSPWj8_Q1KofHy.5:iYҤ~5edn"5yMC!RJ*=,:&1@ XkIx 3vpڴ,XSƭBR><1˜2A :/k\=(`rW8y \)(8;kf ,u\s cP`bCuIwD(J IDoZ7AK!2CQnnlѵiYVX~1Ӝn@&C>Ѡ_HdJ.^g1C6E. <,-z&֨qwclmZ:oR,4cҌȟh b'G^8"lA 8Eu*-$$=IrW XWGti5)?t֘}>dΘ];BO?Ѷt͂տ{\kX1Ӓ\̞ϗTDOQP$ E\TTE.p u@j<¢RpQ˫#OtvZ~= Qߏk R|-EXh:!{Hu Z䐉!9FpǺ"E(z0@ܽei͍옆I:Ǣ_4PtzkUǦ5lMZn0tPAV:t&uFrHЀP$*K ܁h%.:iGt-d΍ /;y^m̊?lth C87%G@T`dRQ.::INژ`Y-]#޸zE)y9o8Fe$%hj2L7<Mk?غЀ(0<~ᆈ HCA,Fٹj<\ &"B@FyGhpD7?{ _?Bܻ;ёh tsN^}̪:>|g, U$zH#*Y | R3Łai &_|:GƸ=Ha!:^4'Z:IzkYJVYjACҤ1R:$lQK5 k 2Ch"*="n$c:/s"dHxNvш?:?ROIyzkkҤ4DY6X AfrDKFj}2X:p#;Wx:@L!U4}?wf XVۋypFBKpBt,~j|P@ @#2PYӄ;4:; oKYB,-P R$AjD+HDuJT!gj=p@ !KݞܙEu`zmEM8^N7fBYcE$Ef,xe=VS0X`hk5V)q $|·#6mKɬCq9at_|&iRI~x&@/&&@Hz'>A!M4z'C>bHKV?ڴbU$Hg[ϛj2IAz1ݐ+Q"8TD&J mldٕض^sEs-s-"<D.@p!܀OICD1$0 C5#A'B ! Цf&]w6"NZq|)?@ 5OP.Sa9 PZFȏ\F6m0+:~uAYu̵:HipCtTG'ͤ!BBIHltG9SCC65tȂQa f`BC(1YU1Hu fАaDC6[XdcP)pqވ\ZX1E[9t ^N{ā#AJ,ڴKʏoM z%LK)S)'`#z+ 3)"0– v @ H#]6[B;[VuIiY.hʿ\0E\E+<4C_eu|2 guGtmږ)tlߴ S* ^ȃ`!a Fv /B:7/:T٘ʠ 7wD]>Ϧ,\of^{1gJ$_ "uPIC-pA': h7Aʅ*ިu #uzK:9PKS.ƒeY"бQ @-PPFLo.24&p&5Έs:P#,bGxlkڞs)`A#qɧX1@<#htsSUJK%!u;C8-#:~[[Ftn ;x}{gtg8WK'Jp]hc +>ںn)wۊ:8xaj0ďӄfu:. yhcÅ9C~0rCo#z‡minmZ΍ک/xTdmL=y!XP pDqѡͰp@ǝ|B,x)@nI Ćz)IڷR^5z7%@}:'RQ|-f7k!ߧ<AJC\ ^!N\2"68Bq.0<􋲣A{ii⺎IGx vH)=j^F1n ;69رi;RoEf0.bBz&Ta D.!JF/ *Ֆ8B+,q[/"9 &֘EAK=R-ƚK*4bFCxeQ8R4~! .G2[\+y֞Ѣ#Y 8E4yѡͲ’[m u:.Ts=༪b$=pǺh+a$ <"?T,Wuؤ#e=_fQ+?ں^[nP 4Dr:TzCV! 5Fq)CCjMu2<@l]CeaձqS{;t8-0wYWX|&SBXHD>Vdb`Bx#aێڞ/Oo:nyYm,$lPV2tX\ kps|:tGtmږWXRV}m#n{*Ú萉uE??|ښ5m;wF55<=ln>oX6 ttUa7Dlݶ9sUuP%Z3!㴥\|&GwD+⩢Z$y谤Il{K |JrvYnj7JRBep"T\ys=(MI9 /BcF7on#䘆Iw[,:p]^H#Yq[6ҶF$T+5Fqf5!q-D;Gw)тKJ};?H~5on'1I-ź2W|UD褰{TFqYeA d "@B "ɍ:r Qb@fF θx;G}Hk$D_"?d'n\=w{9=#͒YUpDH*Lᗑs%kpC\PKE– )Aǔ%!;ғyRI=P"oqrtijy/xoO=~_Nm %yBK!mi1G::fCn(!Ce< 4㵹"#R0:RHuHB1By -w-jܐPx)CqZ1O$Tj98e<{"Eڊw/Opct|;kӶ̊Ovl\qPS(kQi8'ZͲ pU|<ը{g]O6cՎҌK_|@kw/ o.p$>iCCѦ:YCVUd7V5\%-K߬/M(/wLկL9yԮ#{:>Wč/Z!f!z4}4>k t$uhthӶL7V}}#G )J VgWd;;w.ƙSNv"_uq#_yl_=F/JX@]pЦfEǟoEX* ܀T TeD,rǍs=gzTqt@Ż!B _ lԇF6mpa[L3^pT*)Bʆb:=g"N. qv{ZK>}V+$Gsmlaդ֍TW W,qÈVx nIxMQ~^{/:Յtً Tmv! o.ՔѡM=, U;nV̀P@̒!+˄SϦ]?wܸrjpx+\"ßOhxM-,},YIt7+ʳ ArpRJ7H{wУaCR GSysҧwڴ:Iy7nVfUBcYMv2/ʔQeWvqjɏS@ÖUS)9}@Gi\C{Hbf<@#sE_=wR$YĎ(I\sImb-rkȐ.)S8$? ,"ܸQń3:xtc 8&F!=tH,bGqktMf S^õoG1Rx=ZdhdZm@yZyŗ=M4C~|} cV\"OxAjӶMcƗ>9fX-,< HE:|gJ:h =H~jW>{:$xѣYKܠ4nےȎP( fM]Lצm B[ۿɅ:FNPA 1ޡj%kJI^ "K'\9M;Ye02iN&U"O %̚P ==-n/8b~э mBǖ?ڱepc*p27l$"?)Jrc[4 3rR9q@"toM%`wBGkp!FHu:$: =Υ(Me 1KRUzu OSm#>-w%Ikѡm)d9zȏLg; nHT fGTzX9P)Ũ F4K*QɹZHi:Ll]:6_h`@DoXt((0kƌ[5c #KvQ)7 r!Kض#6mϗ)trMyI@AOnĠGN׻tCxY NޡoGUT V =8‹jp̊2nێڴ=_XhN7zyȣq8虨sRz*#Q0P|Шf`zP8SeFh[nEu*hC?8RLwDצmXXu1Az\lCD\L5x<*=:v:H5#A JFcTf2ѭ~is+m4ҸF=.;kf Sx՟eA8Ž|Z!IqfMT.z2$̨ا7rI#;毷jYs{c5p-bk+4dӚoŤ eZf$dQfLqwDжL+~~gm,{Dqc!D4$ V K |8b,cYwDfW ,~bz:@"$KhcdM%ơHOI F|&.|\,1Ne= 7QWѵ-5Sx뵟u.y Ag1CҽO Mp"vtG|8yP)"9=CbOiMXb

      R!ŒG 4 5t !Q$Q aW %Q R%"'aG>`|14^D$BǷ˳#zԑ؀(iMi nxy[!B2'\.&7Ht΁XxU(ε"0R#.xT)#z̑vQ'GTج_׎y?4rD0B:$)+}#q bA mo(ؑLDd,]6[Bo6ӯʑ148!\B?p$4>D6*IܐQXA\Kt;kf SxoӪ?mn4@.b$_:dBMzbUu# #6m0:6 UŒ|@.&21Jc]f %.B2~7pJpV/\wDצf&] ;@KvMy}"0ʮX}ډ_,= R h*֦[-q:/ܞRҨqw/n~@-mOm|IK3ϛ[m~82:n4%9X`@m  O3_#psY\Zو{k#vnq{=5;7oZ Pҥ\⎞mv͆snzlSI25#tpC0C;N{艓M鐃Gu,XvG~Sohiv:uǐx^[#cu%9A0 8G<̀g(8Ḣ2sҽ'N?iGܟ'CmƓ)H<)t^3Q;%ϖl'aԷBBdeYo`˃'$e=*`K~I>a#E!|-QL,YT+h0\1R9Z9V5V3Q뚮) = tL68&9ʠۿ8U 48(}osAWšj(hDzy0灌3ff#=s"dHxNvш?:?˱N"TۯIa'PJGj0 ,*@clDPB˒a5;k o{o&Og!_x8m:#R ЃG:Ex tI"g dW|) :z#lї=XmK:Z~Qw1ok-= ?1VZP&Ӹ `i7!'Ne HZҪR΁>!@FwD_^ѱlM_7|ULC эt7z/Rf߽?{@F6m0:^;M!b9ZP9R *P%(00oʑP' :]#6m07佔u9UD`uPM͊쁲 иYb=x\z߹ԛeiG Q$h'Ugb/M(̀?7RM-L㗫 tLy pC\D+7+s+29l *8FdE$.G8@yV3OI7zO8u}=_; LڴªcO~iE'!3fɺY=\:od{+2+1(K^rj˲F95 R"y"6Xy\:4LٴҌϦ!ZĎlW0-k#[2Z'&?X“iSزʕzOe 7Ksǫ}ͪʬJ`M.I 2Hy80JY&$&Ar09}7JӮNv:LS1v"5xfѣO$%nD{#w-lzd=Y6˪iө='^9BWJ Upg@c [U}i S{OAd =0(7A(-,4 9.>g;tIzY؂aq>9 zBOYo9pIث?\;@G^:±WN|j/؇9np>"@Gש׎[Lq8&YM2Τθy*Ky׎_>vN81p.3-=x6;;}8}Íuh&k+fqx]άD'k6+:۴ʱ=Oq:@qK'9EKǾxtw/_tn/م3<≽G>plϥc{.Y_u=w{.8~sKXM +#5k"n;-&m~R yo/u$8sf?m\QRuQ҇*MӇm<"5I:cAU"Jˌ=3ޡF6x T5f0fI(Hhdfν..lu?} h\Kѹ~ZǸn|Y 1y:Q:7qy1͈F|?" Ϟ?@ ꪪ #ZQVgQ PR* C")i=FF& R_]VCa@へ#y}el4lN|HZa/k| g'ZPV]4~CT5H^tO𚚛pI0'Hv$^܏x`(pc$>@:Wg vD4>h?k鸇/h>~Ž]>:9'0׈fW-vsv.P`#Z)v^4/[4(%I+ oYcRD@c$A#Fm`?"a03F%&D$,GGt ]ǏЮZh#IBi$nLy΄A[-ÊT-,[Z8t 9P`Q*,dEDvqT*fxO½5: lɝlȪNNȎ_OAd+y%!ڃ+͗**⪃r{l!:<5=fg۵ t2Ѓ㻇>{2IMiay 2Zljf:xԽ.D3O9Hf0"t$4م~6Lg !ؘvZb` CIEՉ O8:F я^6Y`{"Ř"Y2' Mԣ˓Ѓ`x}>^wh٤S5/`U[0Yn8:Nu<.am=M#ai!gBf_D[c[`v3B)W+ŵa8;Yt7#!3B[68:NuLD endstream endobj 68 0 obj <> stream xXnF}G2V{."_j$M\LKBmQeR2)rZΜh٤bϟ_VU6l|Z,O]6/j^,^`GpkK$b2$-+3j2&;8ƿHpP^  H&c5o@v*6?ϓ,`vz88?0(cJWMy;~ *l f SɓAukXG( ^Q>4;AFpz< FZ{.ā|:I5QSXM'p9.IpLPe805;:Z%Tyk'cDFD zja.al$1'gA.XvF}_ߢ A(.L(q.w7׆ S_Xp zKHhC6EUWecNS#íatdE$ź A60,8,+J (+oSJYPuo'( 8Dt8 ǠQv 4 +1vn>pi2d$.~ogeWZir(:<%" 7]!!EL%&tGm܊ z/Z u.D}ne#2^pISp!*UK;rtKGq=iqd\(~hMfO1O0A/bO ?!Z4^Ъx/u>iuG yrԑVMH줡yUtEWH9,mP^%/!7HԞ)t5ݚ+Zx^]eQ#&ĘG\`{J:?i@0I k 2-pd"pb#|nJXdxBa!:f&5}q,.I,< ЀeH9ëoM%:TS߀Aʉ]%{c-3w[ZTpt,p1$'dʈ0/Bifņ .f굩C -,.6ɳctqG&cyY5sk%Wvl?匭 ek>`4mWR j`v0=?H~;T7B{3ܓ;JR%qlZ'j݆6\8l$ǒF g;N Uzb3OcD+][gMIЛÞV2nҪCfy];n쫖9ԯZo-urd*RL>b$̻Έ-b:Sm>)\T\1J8)s?͗ni_ ӱ_a9֒|ywLj :zwocndTS5>>PM]%]D$uTJuW]VU.BuAaN7ν{׮wӵL,Oit2)ꖙm7s˭ꝰ$u endstream endobj 69 0 obj <>/F 4/A<>/StructParent 44>> endobj 70 0 obj <> stream xXn7}nx'0HNIeJ|R3$wŕv}Ķp搜s8h^`^O/g|yup~68or1YI-:KKAT;xfE͘zl| 9q,ϯ=N[A%N#w`v2*~<.2%#p5eAs*0fP mɩsa:;< r'ջoyQf&e^l "tr4Jށ1>^nH܍}Q]v-/l6s=U^pjr|tpLl5f(ͨ]:X2nE6]|޾qlMGANJz  aT9q܏l ktQn`KA9LőGВ2Pr^=-PYD*M&\J2V\E k`X}MNe#m^~< Q;kz7;I4>M#ɖs٘.u/sh0]R7mUv!tKG~˝P&ECL!+58mIU@Ȍdkֹ.ĚќjvtfV R4w"^g{:'E@N=Z,et՞!ZxB+^5}to=|C9<.؛1j*1I\  K^I@"֪u)M3(4S, C溜9fdJ So_VQ%[ e,4Ɵ tl3H\k3 e9/ɠ:BA 6ҿ Kys %>'gs.QBư q ]jq &GWUwF(T%4j¶C݇rW#/P:j|qâWŘ6Bg ̼Ic`g὆LS8i<8] Г!wDW~!TD7!jaJƩ g8X N;F#]-0Hdž{Ap7p"DŅ=XU3ScjQJ̶./INS6WXX`!/BJ7 Buk؟.;Y}_5K71 |z#_lt4>9-W ,o:?r-|\6>_ /Hۯ?\/ѧ@GvqۂM<;UB͑Ij,TLgxɚ!s\1oCVL@ILCf!iP"!SbIY)K&PړA:qzI[%ɨ+UycXUR<3W 5/9m1:^D^ ð"XaZ0@H*ŊFL|á>O`iȶǓY=E*AўQ?ӣtjqG#eC( OϢSuM0OmephU[ѾFu8TFժ#O6~ʱgdRT xwȎݕTj0s_ƫXb~lU1*IPU1Jd)27+A4OGN0>@u“gUP[8m(f q.))sΕ%"h`> stream xwםjwf93;g_8rl'2/ƖEY,Jd2[{sH$A${'HDg$k;N^<ؙTs{/|vKe{+|? lVc o0HNؠ BX8c#Fbk3Jmoev♝m$d$z_ K`7=OHs`vƑ4K ^'C6Dx Xt'A֑P?VlorC.[i->g3{kDz궬&d͈Z;Wt0jQj^eөv°hҬ]4k5B0R̭.呯( Krִ8"[!m)2?mPrnVRIǗ%JTDbK>:;,ot=u>u<?LSDөp-Ŵw w @᜻\KCdhfiLK3¶·GݏU2zfvsu CcP 7P1#y) c- cEs:)m_E{)N@y)~ , ,Q/S5 WO)@:2h٨23Iq 9`J?7eȣ2 , aZy> FH;/1,J Q9McPN̨f3,0-M*`δ<YQ+V4UnaMh1(eʱqYtk3&s5Z  % xφ9t1\ k~X9^? ܱ C9Оh@4T<{ă@Y<'أ' eQ՟xsgx?H> %O%=@<iW/ xBn(/mx4&U);1DZEpflgo%v.LR] ͤ2`)8-–&Mf`Oj@.I)f(*c%Ɉ-9c8H?_!0F@>wCm 'RNaA?3,鵁%Wnm6 5 -Xsqb`z@e/uMĠC*iߦ(AHXje'8qZfJ<$ZOt)F[fd}uҞjI oOwGTt+ 4G#G+i-"6Csh"4W2RF߅.Lw?u?>f5`baC}Edt&di!(8ڼ8RIZ m_E{dC' t-*!Q@jӔvzP+ʣFQ (A,㆙1,02aʩ )7*@b{Ѓ`=#Ak\ ӀII}3cRΘPBB=CV55@;oʹXU;4nk3Fs%\ n3H-x) >+imQ? R?b5$t}N3Gcr;5ޕʎuƻƻƻw='~w|xT.g]{ݻݙ =c4_MPXx<O줁(ف;d<Klf%Q*'&Z&Nd@b BX\X˂eEP#(~@t tlTO0QcD r`zШHhT$ #*DQB(6*Ab2oC̆ExP* JDVTYlUsjџ~͸d7-;W.c?#>Kg,\Y#D\kH P}νoXꪋw%twmff栧YO5iOz]zvew~SiOڧ=5nOm6SKvo# [ & uF'ÔIUUUQrX&Ge@YNђl&%r8|I/cXt+ P7@cH A4#W&ǐBTz JJCm lA6`X"[\aPocSy!@͠hTa^ 5 ddI8YTzkݏ%mȡTg64Sڀ([& kmwMwA3=fߓ~z: Ng[aEʱg)r X2޾4Q20I9ր*K-.ED4^ c@)Z  AdzH #!at!4Ό%p( s'r FRE0bET!`[5"1  ´$P2*D2 YfYWrԟџUsY1kD?}?uHH" L!,r};/j-Ob-O6[Ǜo>i}n}m{0s?ynɳ=mO.鶇;mm}lppwR%x &/RWWU`v6@HBAZͥAd&Hh / o7ףH4lD1 Q8lJ81GyC^$~pӍ;Qg7iݕ")R' $0kX jviU=oRusIԟ`@9=?.l鯕a&7 7 O(O#KQ;`oEwSXL&9+O+mw$w;IKȨ{ ȀL/Ve7X8zLy)# 1*Dz4rH iB&A$A رB 嫣z:DeR22Ȫа(5THGQ̀+ˬUU ?nQ+-Izҟ)^E<Y)i\ !'˞@_k|3<^wofCVCe2Xi6U76~ms3 >?xϚ6=lstgr H5w6EJ}O|=⋃lSWxNjx<^B\19x2_ A3R|)>W]3Ÿ8Nn.}h5j:ՊjѸ4gX+$Z@5=,VN-7 멞z$i jǸuWG8΀Ok*tGG ȜL܇! + >>N-rǡ}3X?_Zl#7ڢ"Ɗ 'QU"`@u,2ӈPVԏŃ:meUH!O.*d bk1t$Γ!QΐS3/3QA~^A'̈BNK A3B ,K cy q/>_>}_|UuUͥWu^5]ݗ_r#T~/o6^|/;}wJ+/>_r㭗mog_zU{Kg=\v,RDNݗL$O@|| 91 lF_C=IQWU. SnU&xG9yIrhVySCDyIXխk  =D.C^OBo&X~`0 ©d >v"؎oǷͭ&:H4DÄP8 C ! p0(CT>@$6 {=~#\Es^tpm.ٱj[m;{AbT/ZŴV.R&q'DɞvPu=tPU 3q߱;b ?+$eLx7Jw w!.{RFG7`ͩT2s`wdN~ܬ7z2#WmX1 scj@a*$X"L+&櫣t|NFT JP73J: gɢA9 /$#y 8:P?G@ S]2ϴ ˈ3o >D*Sz;-`#Xߌochl=YFp`8Dt!6`O`.~i%^y|^-><|x\n>.7vsn&xow8Vۚٲb6ͶoUJRIsb[)z:Zf=}mȜۂ|:6kO_S%YA q(_~d??py8SjF_K*S\JM^`@A Z PK'ɐZ0!CGVLHԑP7;&us:BN:%(˅:=(Bb%IP.$AND .fq -~jҟ?gN>-{4H{$p&d}7N{'pԀM;M|L8%9A%lD}Dd y_U?y)/ݜc +NMgBl)b$}=Oy>[ 2B@bFA$ȔCid 8%QbaրA͠hC,[-kgYlAY"AaN"ĀϏ#%F+\lݴ s1>v#?jY?vr >'BݗΎ#s]^o^]j3\9g*?Z~Z~Q~]~[~.Pq.Tq.rص^GYv6Zq6\q6xY+gWZϮ5si9 ᵿ>// oU"܁̒$<+Sl"Mh|:T:d+@I?Н+j&ʇTfzP}k iɸ}TLw ^f"!U/Gj䂂( np>n&WΦ~ywit'<2'5N2GMcAKܖ1XYos1zwyCxэ!>y Hy@(p,x`0`8pwWNs GZ4ԭie^-^FukH"l2wCV:O`#a_*\+;xeJRjY|y}=ROQ+Wdy/\AFg.O_-=}\ /h3Y XJJ7,9}YQ 'HDžz0v?1`?J J1 82^6%-菶cjgǵ3lڙI-g3 #fQZ9+9j@&A 4.Qr>(̬pNiΕP>]TǺ 5ߢ#ݚ.޻hx齲w/X޻`yu= ϯd?&ǯG;o~w/-3[{ ^ྐu'OHs]zw ݩ2(>> @_p+HS>4)M} 5i.Qorw}܇="yh\UQeXfb-ɡ,]t_תzElv/@:W\Rg<.\H'ufp52eem!z("ǩ+ӕ%ݑ? Gр^8{xov.v"j[N|PuߵsȮE;:R62 cnm(|e:za7ۭS@11SpݷLܷknr_qX&$xZ_?|Ncw+_%溏Cݍ&F27QVdg@8CA) ߿YX =fPW \<(-2 T ]Lh}j\A1A A-ITij"ALރcB %52 ̤F6MiЃSD|   c@?::A̴OEҟ1 z;3X!ྲ?bQӯ5V{_|k_^s /+*W^& o7囿#}5rzq󋫎_\ ϯ~vk_ ^ɗ}۱u⾭$uߤsG/H1 \5AFBLs x$%\̚-*Tc`RklD=gq`#s]8ׅݗg B}bxs<ʺd=t_*Ґu)fmy#/K҅8?'er4*]x\{AV3j}Xm&P<*~mX>z~b{X?]jMpNa:FB1qWֵ`wXDdVjYB{kb7[lJwChCױDGt:츀Z3`Z^n3[}5:ܷUaS-+}}Ү*qCQ=}d#Ws-Nj0Kwn>>gyG+> cW"ߑ'gI+~'WmGGs1 2E*eK5ٍo@"BÂ?@ (&$P M!6id(AF552f $(`  `^qM427KȪ%>QL񳠿0{*cG@Y~E2?? IOd}xa%QG;>y|xH;ƁD~QGʏ<~ r|A7qV}N5 |ʝNPUEKfT4)U)P\!`N@sG7vw}j .Ab.K[pJ! p@r5zS8 R2U󋼙sq--Vk:dr8(Lmi-tqȗ_V L;tf{H->}0 AI0{].ut*KcSx=.ֵ݄DrbϷlv]fas|gw,bf+XYA|wMi6{,6tu 凅N,ڰ$JgUM.t[f fC7lv>^:O]Z,(439)O%$cJdbC>,뭛z"n{ j'hd}`I+~"՗O)鏻z +id'_7^bMW*>Bo)𤙟>R %+p>X-t.;!D|y I Uԃ(A28Ob@Ȁd@M H_1P:& уQtD=xP T(P#5 eFA s )J7O)~YQO*_X p)s]z}'lۖMڞxo{kkGG?hdxM'~j~=I;7v1pᚏUx?>K'5|yIei;YߗL%Xu7d F55.8\{pIw*0~&i\'4I&MeʞF#}:c̿㸮cfbı33Q'9gS3#Kر)[DI/ @;zo z}þ."eJ"jtE;u^WWUW7}UcO==h<}]xW{";03 ?݇dIdI' I79161ax{MhpBՁl:eܗb,@mH-@Gc}7Q0"1 6^#d_z.q_dze=4}ӝCwv`1>Yox97s@E^H8}Nt߿w\Î_M~֪S[4}ܬYM7 k:{G^&OrUvŷCUwx^'}No=݇_@4Swt_ݛ-П'ʞ繏cUm*megN3֫}J9Bq6]j.Xu!:€?-d@qIJ2A26ɬڃĀfvIdzmAE+&EI0 $LĀf4` Z}@F$cggѐ>gEApDl'gћ}~&鉱G3eiyX kvֿIض__rU%[ D>ZVXԗ,EfiHd3MGM峱o,FƘ;,St: uə@7`ƳOrLO!S%Nϒ1d[Ď#C 9U(UރadbL".3Fc76ajevv WMf߆0>9 82:Vq|B1_(P|!grL629ėLX<i]8 !Pz 8uaR zw\Nӡ=nt*LL<>/ďy x='"= ~ %rvrZ+(-2s/yS<@>p\Y$X*0C|澒pΉәg ?5+!m(7]59N⾁7*a}7ܧ}D-,;ꏸOW}z{U$7Yyƃtδ. N}ed:Bgc(hzSɀA<(mdfK9PB$bm&Y,А:LYvd:B@)%?$:0 [!`ˌ|d>BP6N|2 0siOVTlyaş}?~O~o3?OgOw/R`^i9HxG9<go{o?~?[&cQ'SDW: 3$~3T&I7Yz ZSh_iJcKiNjѱIb-"9"L!ΧRd2cT4̎xר~_GF|0XVBx2? ٿuжNbB8 ,!BNi8Ko9~kr:iWk{靾gr; oIB;ɩb{OO\}Un`z=slG{!cW{꫺\״Ҵmt*A0kCW5kEmϖWMetİ] ڌ:/0p4ۂbրb@1 * LT^%i#ZKԀ e-&YQNH+%ndF0 @2A (b "~VןꏻCU,%/s/_d!{6*˔-+lo]&[&[̦B^G]d|4\֐z\3Ȱ:$O:&&X&~`(D1d1%ydtk2":9t޽|m~gYQ43)4$b禞S?0MʼnB%?ӊNX)Ept1)R02h:NC`-IM_+OQz^x1ŅNNLGPV#Pgm1D'Yĩr2ʔ?\HG9I5Ek #}uG.ź(P-q wFi#M,`O1RN)|>- ̣DgE*Y=ϓS9TMBupGHoIH!cFX(a$/OhRB(k2RQ /A}П"0:L2??zP 怤L?Q|70 {NyMǼcփÌϽ2<L)T`s/7uX X!)N ! 2؁\VA#ʼn]a3ubB*QL'Dzi 9`$O"$©)Lv3ZՋ&["tay40icyx|)# &t)p2Lf(3(0E\{{X/7X IFJdßD<Q$F#h8BEɠgy" 53:CA% Y6uad,6{F!k0&ըL AltX{h 5d, /kt!m6L:Ak׫a_κ}(wd!{Cr5WE'~#: pqǀ_+W ," x C2ǕF'9 ҃ >s7bROvw?5o(k(kŞϷ.?/v]c844QNhN0z|hUk;]Ι2(^Rv_$}H'P>}oD¸215;ay:n?>"AIQ]ƀ&֓4% \ƗtCAheQl6eQ4H)v #d:Be nAԟeZ @4 'G&=糙Ƞ?اg$}2t=ʎ/@4+^}AW?_>П2< ^cEX\#~';V Bn[s#\Y#v]OA~m7%g~MtwN9ߔq8ocr PNӏFPG9(" w?*E|w⳯ߐQԾjxW.kbio񤦉G)V=Qkg QFbs,m];G7U^ZJԖ6u ]ubz# BLiŐvxb5yќ. FѤ* #⓵`)kc k7H;:g" CKԢ!Z0N9 f2yIwHB.,b} 3YAN=,r=?w"Xp@dC4c=64HmEJ+A4`Kؗ/e/`@<Ke,KRl.S;) ̖HVbe!dDyKĄ,:"^c'l8.23Y[$ [<bڲp(B@ &|^H 8"n{i 9!HF8̰n Z:@5Zp' @+GȚAY3 qC*(? ,{JIcu:QI^z鬲ᔢsoϾ):4z3S| ɩ7$Y88Si> o}3syDz-مo+Q\|X_q USjдgV9mv|J.Tѱ nr׋↪(=G@0&EdalFI5Pp-m%#;Y+q)k;YAiuR.mT{EF>OlRI%j`Pz}z0B4E{F^oaHkq3k K$BDȃYH0]l'v:ϲ.P7f.Pi'g4 P1!*LGCx6$;I&2 $yS8% $D ̻X藝J<$m܀þGݨh7YPz nAJE^ޡ .%]v@7͠eRDWl{>OjR2S/T5AҬE,A lYFȠf: W ybQ> "TaB >ڈ3K_BX^` z#AO$~|%>'%xā~;%FnH3vo )Ia}(Z] I$%ԆSRGO##[F`w0f< sST*KәBvt&_nɒJ(Dx@$_-NZWDS(@ê="Bt y6gȐ{x5dq&h3݈NkѪ*׋(:\iRL5Eç_ң@[%Հ[+{w."H RԢUOQ(o\ɚ.Hj$5sk$Hy(<@ 3 {!y44i9i9\#oQ\P)z/u\TA64w75=ڞ2DEE_* a$FYidVB[bPI }R4p^U2C̠*aWT,J#kT+M^פ3iU&mi@5ԀEh , Z`80dBM:`d4 6f1نf {V)H\a>SD$(hʆ")B(aevODBh(H0@$ A\/x7Xq <.3A%BP8-'D,%|Ј3$Q$8A"N%6][pp$bT62\,q\>WƩl&ɑI'4Ob) ǏR E H0 #PC> ɠqSxp0؝p.jw؜##аl#&dF֠T>F٫Q(5 Sd2W* b X'"]V=,.^qOoOwoOSա ȻmUЂ!ߍ6VE9е[{R=v)? Bst"] v)z{D*@c2_!PHuQt z)r=ox\D ^#wUcԪxyt u%z<6 ٕdݱm:A/q96⒠#`[FD: g uflЛl2ZF2h<8d6[C`#ÀmdplpNx>oy8Tfa$|~m3G`"D4% ,0E*E,@Aouuiiqs}}s}cscsscksskkk{k>[ܪv퍪lؗ&tW/_]ٓRB67)mlln㯵lpr3k ǥK%V?%wq8#1@#3dj0 <>;5 [>eÇ$ej_.Cg;UݾZicT:Ǩ24̤{e,Swga8a ?/~+KX56]Sq=>bGr%^*\e m,3˕e@ *eY[YWY3l+3^l_渺\y֐ ȖWu_JBa6-f ъ~_帴 yg{/8/|ş|C?"8C9 xrN8%"aco0??X^I˿JS< /?w%XٳNHQ}υB!k^p,v=3B!B_֕P,7֟{}FB!BxㅟjH<z6ן{/B!Ƌ!B!-FgfgO쏽7r{`e'BևBBg ;v4߽{ͧ~ebf||9}pMFv[Okrjx$RS|h#WdvdOcj_ !_󘜚Juuub߯ {oj Q$<ϒ<(cT Z;"6o3n*U|l_镚e ;zWQO!FEP4'Ot:{gsl.͛O=*a|#k;M5+sН?T?>!ׯ_/uu?.ޝ;w"ѨfJO 9Gvs|de}=US1Ǫzp{/(O!&Y\z߿?N'S馦'py2*hȢx]UCTgcܷס !X][-6a_St4gӬv{֥[t;l> \]*{4o#W| o(P!:dWW[[[[ W/b1sҥ?1B^ø&R!B'w܉Z~> 7tSIj[XX\_ߘ |c:Cn^0u\{B!ǽ{0yܥ :~Φ-GgķgEw_7&&g-hq!77'B!ėKK\24xnݺEWޜ |4-y{ŋg.g.^ gK]wW%뮖K++˗V&&@#gF>!B!!>c33;7r۷o-o/*sYźnx6#}{5π0 w7-W^[ZJgjm_Ȍ !Bg @( x.~rI|a]|555Ν/ G~}b5EnA'I(tOwF";  !B_'ͩ>Lo8Ⱥu1ТVg4=z'Ƨ>+?w裏7\nBs6 !B_qΝ0vh,Lv/ЧyO3'>?{'w=_(9sfvvvO}t_@pB!~)dm>;|{f荻3MvݿԂʛ=X{oCzoص7 #Gw}p_`kCpB!6ݛNȂ\Jwi.:],]wfj?_r{՟}Aƍ)Je"z}B!x.}w rE\ڵkT..Rѱͭ噤Z ~}Qӕז/ol&T ~2q_,<[J/|V5 |5/T!q폓L$+++cDpe*|e)ze9vRb}!99 Z]{hgM~?70x{uuO}I#7%x|ծíOŮ_&_˷S!ݻw3浵b2^m,k Rfk%sۣ৫lEgÑw>lT 8}D,k%|>.tB _S!:͛7gfgram>2\O.dVKեRquylkm<[}qw𥕵e͑H"4&?k׮B!H!ܹ HݗM}>))Cë́59f!^j#W[:1Uk4f }/ۭsҕZoUvQ\:+^ާJ(*wv>՞gr滝h/pӿ_p?2Y;rTQ!`X,Ưcť쥅bae4<~iybyyjiyzum9]\\ .፾ѱ Y()?uĝazŒ] UN>.KƔqX?ܩlМ{Z6RNEPٯʈ m=VFl&[1W>\pwSW>}ȧ '?nKO1G\;tZU׵ [75h8~se=5'?qO{g?Gќiݹs眿_{sKKKΌQ@G[|վʔݎ}] \c+Lr cuZMƁ;Fuw,.;XQU6vqvΝ:>??_\rwjjl3_9_5snb6V9X{ڱcGgg 徾#G۶mۿ@p#Mͻwvt[;^L:Z:z7OGf#}ݍ{ƛN̍7ύ W~zazf??<[IGj&[G:j{+v_]n}ϿmjjҼ_.,, {[n]v^tIo}ΔCLWS#>wPYkKsκ_<;GgWVVVZZzsv <{]O['G?=xҵgw^~htt=u_Qs87h_ @h7 oӝw֭~tx06>0vm?:g}ڙҾFGʜy@@4·e˖'N8:ݑ>*Zi>0v'~1Yg;LMMk}sK,SC]U>牃?3;ѡ?/)kj*{>K_5WOgOM~Se?+++!Zjs>([__<9?/=73Xi~}C~뭷]tof~|qh O?—bnsϿ[PWw;N:!ZҾ~G&}r[?)9\rEW>}cx>Dk{W]^99> ^xᡇr-++ |K=Z\\s9LNN_JZ:k (-// uvv;gdիWc&C0R9P}}nڷ_S\)'}m]5g}n27XSQuq"ڄ9;-+}μ\ʼn>kw>1MyY9μ>k;,j_v&}Վh503о=iR5X_Zr?nHw}y"q}KC k}nڷ=X]p#hrgpSMO}:?o}n ~kmѾih5}󋗺.5BBk} '}# M>7)iolpoaqo`ev`оٙY`͓ҾNhu@" 9h5ťYhOZz;g}O>٨)틍w./d}q_|#+]CѾ@O@B6,.'oq~ D}K+ } >&2poѾqKt KK>y&tydt Twҥ˗/;H.L Š}}9o~}}})׾o{})AD})׿}|gmۖpot؅K>yG>Gn-[ٳß}YYYٱcǜԾcSF/-_3O&yߥ]?pi3Mju_Ҿ GWW}L796r  D}++W&&1 h?/6'? D}K}?9>2<[OQxX4ũo.7$ɷs7?H(R\J'h]:1*\6Vߵ^LBT;MG͊i0Z=1!8s( )ס_ㅏ\)\q]OQnO>Z"d CX.8W__Ƴ{Կ.jjj EF.8U==m?%RJwR#ԇՠpFBj>l_vvQy~p\j_OJ!\=^+zWJR&0Gw`$ T?CR|5lz ջe CƁ^Ҡ[+|iqiiaaqtt< uno|BѾΞ|o_4g9#VvU>A"g s!W<~tu }Ե.92 oJ2}t:줉WF,F{ ʲճ7 B"џw(LeYAh!w\庥us{+jmNYs@?c')S2-S}Ɗ}xi,-<9O}J^x3WG~ș;;2+dz.>tʏٷ[,^;&E*ٌ<=\¨q0nJ:3Qoǫj 8h cjPMOa>!I'6i;ɡDzty>{ro־8ݤ1$HeP;M~Dm1>jhi_f~Ըp*(hRGXym7saoB>of}Ɍf'lw}UrM>Ϧp&rTj~#.$6O3 t#$2s^ə?^DsBY:*Ѵ6R`L/_.ܖo} ]sEP}9秧ȗЉ\^Eۼ]9o|[ A*s",g'b}ahuL0w7-$2} d yg7.}t7eIUꗤ)#pdTRM~);OcRT+|d_r϶&3AڷݽϿґS}4!7Ѕ OkvPoNrپ.׎O(oe}]]P0Q>䋖WOg BUO -bCK0Dz9Aڷ BSHS]X#91*ie o*Whl i*[ STUlw S,훟-VmO9Ҿ.KK˓Scc##c#]WpGL~tV'R9RqTTH-vWn' ʭ}jIu+-6;=ʕwz`˖g /|C9Ѿ^]#m}%%G2>}`-՚g~߳>՚gZ}MTkg}" 5τZ|c@4ڷG;5W} 9DZ˜fDBW%ťґ B@D}]=7_)vb4Ϸ.cxڧIJ 6cyK:B}1֨b8R>aN{ned ]^D5'H ^$.~J8YU.,GėeLI6Zu%-ӇL-gTi_&Ӕ@e QxQKg _o̗>^hOx M)}7X"'/'F}bw/ ߌUYyX :jߥKᛞxq|홲po#=eZ>1.! Z(WPQBxӝRTY!DKJI_J''';oh8wkM9OkL,y+.EÔCmpyjn,m+(MִʏVhqcccKKKٙYg7887U[[BOV>O> y Jx7g<泌j{V/pLvjR^hqڑ?gN8wow#4QttW5!CEOP~_e Y{Rkf& SЪ-NNN-08ř.//}{ :$kG je}DxVH*Fd~ :uG}ROk_IGtq䬙9#j~Q _e [tKT;B.DK4חҾ]IC>y%R{ D}o|)D@~돠}JD7}KTWOg"ѾGJ>hﵧ^j>y'*۷v@D@tw Ѿ?j߫OBD@T8b;4wӾ_ݞоCH D}6hTv7A(m>y'B{Ѿ6h|'/=<@FFǞkkh D}[?QjߣϵCHo`ȳ @>N>}gZZ}Ltw8}߇+j·nk3h;o{ߟj7jhs?? wӾϞ{Ѿ0/voXwSQKiѺ؟%a%7VrZ/|ҧo]1./͌D\ü"Ŕ/eÒY0N3PpuV ei>7 ±'U9tZƐ+^P(\l:s<R9mlH?}ۛkr}o.bdhfES_B8ȢTfPQta &Xٴ@\i6{BYҾ`iF}"Du͐lҒQ}s2;pfSM':"ԾgSsU*v8M`nz$hnF"ST{+}",]R~(L͈dst鳜81L\BHg$-޸^}Ȑdvg^u3A<@gO&}t}ea$ wAL0ḼB2xIzSP:^w"o'9(mv)IT "վ?{m9վL+()Uhb~$.2d!/sIFe"$Y;>"f|$wsI\ .˸yy*[d?M% *b:/֭H 'c*eDֆ Y @`hhԗ={}CI0Q(?Ykv)U{wWAdо@חԾgxș9&*#ɿ{o4:oɋ˜O~. }͓hڻ-mDYʤ*w)5v$(^sʹ>Oݓ\۳K mP*e.__kd}2R%=kS` DX ֥S_4cJ稏qU3yTZ 2Ah_kSw[~e\!Z 54R|{9>fD}=\b1N(~tD 7t"މ̵J6 jU%Z%֝)y(zg}4H>t ,XR{0PΑPk_')-R$i}/y-7V7RbNh iqMj)q@NlTY>;SnK R1m\򪽑ȨGH`6d}y|N2 F}D Tr/i_h]TNUB8GD}.L3!E]R Bо?k)5sһ8r-9%fY< K~>&&q,.h8)q""7҃+;r.AlAR^I4'~dTػ8ԦljH{~UP_ϺtW*g,:E9Mz_s}Vjz^yXUD}[X4x7k'fPh8ԈyrȂ}|E~ P.fŽB\#+Z'?"ymP*h8qU )^tiR67$U ҽ[,:LTi_Ϻtl*"ap9—)_)3ֺڭ 2Ah_X١?(0 |T-{\gOWPD}rֆ*Gn> Th}ƣ+.JLyWSeITAhhR{ D}'ADAHCU=@R>*~s+sԻBKy)Oc]d)zWMųsCsO+PF2ɜ㡔<1[}qѽ2%X(` >bgdvx.òN3.D,ra^ 6IUVe/GV'j_DSִU))EJySm:2ExEtՕ̔)inQWiϗkfnd[U1UOF1gcۣ#U/d-a .!j6ٶHO1_q*XNeo][H^Cƺ-x*)~ `miںpæ$,\|_a˸_4E ]dORjcOoky)#~S~) Ⱥ,Ed_4HS,f2%BhOMc1$S4ʸ?B-[Ve H^Q~)Ȁh ĶM9]F/i l,3MP'-h:`{X7rLC.}-LjҽhjdW櫍zXYXU\dU(v K ҍ6PH^ڰ>ږ)17Tj1=EKa![,MDSmύ6VE%0ڧI 9B_"VOEgj`oE0J(*xuA*1\du(!|4{$R-Sec=`ڪ& [)289Z 5 4˅1?DMF{wcH0qJ׽S(rOYQdޗ>xWs@>o9_u"YǼTdDjA)|-zߞMciD^}VE,'[kzXpǞh5 ȵ U6 ]Ʌ>Bgm\K&on(_i +ߩI,lf7gm6Kc$]I_zȺP8Tzb}vHn9~_6Alzh>t}Y~eR B{rsڧ ޑ~ؔsF3؁yf,@ڧ ]$\K0n"c-^^d$د̗C0scvu1# >vd㊶NzчB%Bݍ%*؞׹ym XNVV AM( =۸BR& $ ( >6@ V*,{ ч)P'p j_:vmε:ȖUd?v%J{h|='hTYF$-x{GJnk串nfZ_ECK&Qk_p[x|hzKimj7(( d3+3k*ߗ/퓶C~_`х/I+RѼiK/{ f ֣1̝+-,E/1DK)[WV!Q3M-)#*73[T5hUZLm,LSg$er,ua;>јyld9x%CԻp '"N̐( 6ܠbH*Ӈ2T9ZW]OC3oVqlfZ5h]H=ZPl:MNDn(I /}a!5(1M}SZ%[NVyH25:Yrsik 琛Zj!c_Yd)/9P*f;>TxLeY|Vl6ye[i$Љ{ԅE)j]⻃g8u qLT2><0* iїSvhYYrA͘-OJ73[Fh_H=Z01aH(`RR[DIQ62\ ڧ_*}Vb=4Q%SeXxP"@S3$Fhk=T8lU6P W]z# tJ]XD'BZs=hnׇ/f8 _"40m߃&5G[oxWv 0DUq~jӫ Oc<]URַdF߲Uynfz5h_M`!Ⱥ:I`/lH&SQK=Zl`ڐKh|ڐk0O+g|i.5E2T|b|dyXqdÓ&P%fsml&;m˺:lI/hG? .,о i٢}0# Js@WEkd4LnKi?=U"5@ЉD}OD}nhӾ>UA䛨ݴ5Bȴݓg] ag|5HtB|c4o-7MҞeS̺M;1@ pIyI/^yo]P*MU'r%Iو~RH;AmʓD$JxҾc lZ>߬N>7?a&Ŏ1U0LPJNkN;R%ċ]Vy2:B{"}? Sj^q^d{|hwS'7<Ө*2* )Ƭ9B;w0w ebʊclA(r a?Iwlk< j3#vLTvXKS`I֮y/~O/"<ê)U7ɖl=h@-.=ttD_qQ%NAL捹LYkˢ˚T)?kd[|*]"^[7Ҟ~#6E*eg<{3jPY)s#f12mFk%FANܑ8 Ui\4Q;̡Nl' }B̛g") INtӱDMz5ã2k'T dY|C=mA}ukeS3l4 }Yצ"gj3d%uxF[av ܽb#fU7&RȜOVsQC?(=t{e#VyTriҾH7EQFxH!Â`Y{WX_Wu.,BMeF$VD ;)Pmƨ畞QZҤo4wDh_y_6_Ei,#LC2RR"<c5jye6qY-GLcX$΢ Lw %˦kާTɲmg-bAզpːkI~F.imЦ}*gf_f0!1 EHU\wwzOk/ n=O'aA>m(_Y[ze-XȶsO'Z{3}s>7"<䖐1ឲ86[ɵ}<;Å("JuRx#O#)?9 _kMg ![Y2mI+ CyMQmDE~6\:ػ{%g}r%I$Bf$z]=}lqO9bv*ul.vml_6"$ZB_'uWmcU R%5kVMD}o@=hyh|Ojێ=Ѿ| D}Bc癅5l($v/{d(SmnQ$#qSq)kI֡RlGǿe|)=ؗ~=Xvmo.b~ZY4;zT9=(ybB!$a^Ffaj/Mֵ7Jis)7W"ɿӾj] BVbjDNϡ<dwK #TJy;r(Oo..U72{[%:QfW\nB)bO1ک1Lˈ,,6EGSԺhoPWM6ieTK.:)\mUȴ˵Y]aA+Az"x&߻'Q$krOT>ۍ9f ' N:M?F`zSIi 2w4U-ZJZ&G}sL[\j5}|O e!Ub#JwKP!џ*Ծ bQi욙^&Hn9!t<,/m s]J2J#,M}r6*GMׅʽjYPXcU}G>0UWX0{|wU89,Hղ@ N$ ugPFM/Bj)5Lĉ @:k]I奄w[&G'}r$uTf;xE%<{gqyLc#މYEhF Y@D](Q@gFF7d$H˦%-(gAR(Aě 57YwVUfvuQY_ee忲PB/4'CڇqPcվ!}WA>4'xpZ\duj9,01 v~[70Fv2}hs5(W9l\J#j_=װe8s̘ROy۔'B0F<pTb9mO[?R,ǘ5?Fj8Qlcƛt4z\1J]j)ܙ,˷lx81~Rg)X-Ɗ>iLm3}Zx i؋B&쒠:|m]ӊtQʵl{na>c/JsѢ,UZm1sa6Ef>=lmͰsfOwVʬm.pJhzg 1*@-<Rùj`rƈ]E̔j :"fǜ~DkƏ>}C=7faL_CRC/Y|`zʙY@uŶ[ak=<ӵ4J}Geֶ]ooİgZ= "P auĎiSʧs]1J>\JwdjЬt#>QnJzN۞+*Rr.|?^%feY,0mÖDi`kCv&O\-F $7A|h0F?}b w>=خ>KħYYXqf\3I Z@;XAm1J.@(=O'CÛ>9~l\x/~itXGAfmAf&xޱX۶PYqNܮ6ϴ/>kldy簂:O̱NȖj{:"NQH?7'#CKmG^]',9%[uڗ֟Y@ڜvxz#} o/:>ņϺ@xgwC9>O 8#U2|&%f ]oPov3g:[ۜwULW1v2'<JmK2/v^* s//LKq0l^о<'жSڗ}j͊bpV>{fUt(q~s2ڒ=Dͮ,66q0°e2/v"lۛxvk{N0֌ãmB!m[XلwЦZJlū0Kq}d?b9]ᦉe?&Vj^ueZiN.O?ed2/v"nۛ0;fhضWlag&^iߡj_>tugUᦉe?谧ṱ,!:\-a#t/_lQYd. ^#~zi\t0ypv!st@?s¬4N΍9Qihm1|p{"2wL3 ׾9sqirp+֌ãmیm{ѬG{홇Zњk+f >]ɩ5wO0,h<6~eS$Q0,hbcp/9 >i}mhF(["^%ͳ2Wg8ϴ>\^3kyQҐUƣc̖| x}ùվ,(&PN{{$kDA2 5Z-ÓBmX3ļF1I 7s:{c۬.L,aJx/x˕L2 | >MffL$|05io@JzUS1/~nCAۼޘ3mZ3qR[DoG|h)f@.J} UZ>T[N|s1?sꊏUX›>Mώ¸pʊy3/i_r`t{>Vd##tKy:mfNYIQ &EQs>>G)uό"k߷ eXo}}s}<Ծh/Rd[*^i}>}>n}<#;hx}цΑx}>^Plx}}_L.ZH.ɥI:E<23$$ݑ@}GTfrJCEiҥtӴH`rsQ!0'0G}je+3L}q&vgX13 ~C/TG4c943ni(^VtY" KtPکoHZbOVj_#J';ۺBdy|zݕ^|'0Vpڗ>#1u6T/¬H\LusZM"=fp|'4/ ؃8z-`Ll,ҹbѾ3Xc|dh p/ >q.j_{$1F\C vBEb1;;+[k_H־G}Ģ}D뮿w{?dy[G}܆9[zSO=UUUeG/ }UTT꫉DBkG4w(w…+WBĎHޑ#GtˏmpE.^HF|)n޼7ߐO} >9־$(G} ɑ}h_*92+w4Ҿ_>hQ.s7oT>-RڶC}vq(u&PR> \h_Wkq Jrn;Phf<$k2hchè(ڷ7cr9m ]:FJBU^( k+]s$XҾh P QO-;AEjc-9hPoo#5>E}5־|ӫO #rw޾Cwuw#_OPN CIrd2HYW{^J/}o=:55uC|!?B55Kzaj0SqUq sKbBӅ8ax}dpG4>|Nػ| YH _tvns Goz?aѾni_o_}Ŷn?ٲp=/^D" zcc8h ~XANtzK k9 7m"nӫpV(]j=#j:%sy+ -Rf9wܗ>EXKnQiJci)UiŖuW+陞~]~vl;+澰tK#վo߻zԷwhG^j>Ƹ:g>A(Ei_}<j-֕ETkhr6Qq>B׾N7gϞ㉁>GҾS~= P]>šu5h"h @h>ł}'gvo5@Iy:|B~fgRhL3f.p@ҾP7)q>ztjj B~8cuvc=L@F /T8܅hOwmUU]|w`wG? ?| 7~y]\C*Wv\@pI&?I:!W__|wxl 9~?'.^D" ĢD?˫֛&6~sb닍r柖lԞN,Z(X{kҕӞ?m9xzFl=֧k 11 _Y1ܕJc..T煾}[%KxgzzZF&c&OOO23>qjbrEXahC=::;uᖼ-?JnZzi} oٲ+Y:$7/j4WQv:OsVu/2֐"wb8ϫR@X-kߎ_nj_Ww7zg~z_}Յ __$uQOu,@9Idt/Fs~͓3MVnϟ:g`KͨY'uasK mWϽkSg|9QWcjz|/ GmYӺd'#}k\CsEºȑ!ڡm;tIV ={v$5>y"|7o޼u֕+W.\@" 0Jx͓5X`\RjFg΂.g-#7a.zIb"8s2I}ԕ9sʤƞ%ր[@!7N}]nk_oow޹tprs}ׯ_x"H ɺx)}5UXưF1 2Oe<af/5OV* R\3d_hr^S=emKn<_Nc Mk>k׮sf__ruvvW)BiVYqhv2ě)3==M~m@ j(ڷ i{XXOOì}.k>>@PlSP/~8\ӝp9O}$tkpku@1@i_9u/T#ڷhwH>b^\;"m=J}>}/h_W`}AGxllBҾ|M.о?Ogh Ƹ}zei -\Jf ]>#T}f@%F} J#?"˟<47bt]uί뾕u+ o85}OߠhWW;K?WKM}o߾쌡’~S9A]d 3]: }2s^~x%C Ꟗ)]}1زpa c6S<.zU%իy-c>'twvTҵ6Z0t´%{ ,lt*iE' 4W/ ~LKG<`]SII(P?k_{} ;sbƻmwž%"KT=^bב7ߜu{Ss~$)-+%_̇ A>%;/L'؁GKTO-y{R>?9V킒uee)]}SxwޭG_HgВ-c1>'t D}7(ڗ:{ޒ{o?|{ ?G^,7jgS}wIڽϽk%~G|QK\d~B>)n;@toS~Y^nCMa"ǜgHJh߭[N;k^"K^Z{͚z zj;eg}7&G}Hw3^)]}'>'I1lo ;TCXz}Ѷ9yiYKJ'>0} ñX-9/77BYqF-B0$c-ٵ}@Y]Ni_⇠}|O|5visdwdC+/v}~kRx/^l<\`eÏ| ܴuCXG@~YQVLLhzekRDX2\0PlуeKZK]Vtyje5+[ VSld+xO+VZL-7lule6#+jVRUVa1goyѶ|fZUlYiV*Qˍ汮lT[n6٥uMMb^Vb*יInk|jeIBkW͞e+i[*i)*˕P)UQ]1i˳7Sʧ9q,coiX\+(tdV.ydCjƍgo?8><;K N Ma2q0S%OʖlQi唧6Jc62rz$I)G0rztT2ۘdc63';5lTFF6idI&L6<1lظ%6ԆƆ 6Hl ElXj/Ow ZmYWʁ`DBn0zmcɄ}ߝfvhjJk!ɤ"''CA&$Wll6XҰ!%hDliFHLGuy/Qb Z6?ζ> MM#er")9FKi>Nu8c|un Tld6)ِd+ sgfgNmj94-&g(?2x<9p,>}aCqcSӦPsE{3Tvu%ְC;"M;:wD[vƈwCZwu˶5l2%?1[e^! Iގ"{ڛI;LخV5 7")ۚwtD{:tw-'>Mֱ;N,Bld;l?;v o׭X+HPnbZu %kbkT3DnAEZtNfj#M mU*uM5/V?Z1TlrCh3gBe UM؆bϵVo Qkbm՝hhpKGHӋM /χ[7=``d-U3fݪTmYcbҸj *HV}zCsͳ[mbiOݶzb#&kZ٢ukâ&NCe6 >Q-R5R^Vn UF[njo|!@69bg[64>\#Yj*Y5e5)iH5ڬVhuKRl6P-XoDYd!5)1kds 4,Pt]O3Ͷ endstream endobj 72 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}귋o|3w}0{A`H^ng{ϧi`Qi?&-)-i V ^LZ+DXԩ!|e]suti7t%Frc.ddB`iܸ$^f@?# kZ: VE}FB(bY~MGDfCQ/okp>ZPx84&h6FYCs V,4 aK鮄`GMCnrGq_&J[Ά\Ӻ'u玝+Gmw4W@я*t&tk^^Wk5ҵ갪$忔*zMia An-Zc+8@ :89 3ӌsWDl3`'N>q5k(twyblYͩyxE3߽h7-#.N Ԗ(R'B0( 3s\nh&ӿ?E IѴ+"?z$hr]<ɌA!J퇈m?g1%Tܖc9뎙'\#/tɤi# e9!;# nKZEf(bBqڭGS%m/.c(!XٱXIG9ǠsNHš4='wG\\q[[NOd Y;cGr6#4nQ5]&Esך_+6mN9K%@MӱM^,mQgkoqƜvj֖Pcnq5GOY}3N#?].1Ak8^Zm}%i:vq>b|8ۜMuD1Ttp:SpVjm3O/&4-'NŠ6;vb,8 R+Hd!48 Ϝ_MGk,>CqMD.;`rF5-iGa-iF[/-;N(I\ZgV5Eltei?&fwcMM5rHI+}'K`3i UNH­E68fa?(ӿ?Ntno0}-%5`w9i(Zv3>q5i2 'Gӳ^ "-a18*z;u)2NHµ@U[ǥE4m?ӿ?F };# EY7t,ryѴ*i USE[:(ӿ?.4+y2Ea_H ̸},4m/JLcGӿ?𭈑HQS]BIZH SŖ$Z3N[Hi`+30};# Akw+a4߰K,Ų`wGOXNHµV1JmzRHXi;i,?$I ;# ԉjЁHz]3JOi TJӿ?[5z]6"4$RAΑ$ZNAڝ%Yzk]06I?&i:GrSWAr(Α,VVӿ?X՘mȇOi M@B4m;c GS 1J9y%Gӿ?͎?$]jg`?4*X%AwGJmš,*?Q,PhBt|82(=+X U{_Zt-*aNX£ԥJX/8|OFfD?wt!ec 0?#_oz縸%ԑ`*FMNWjqt^[?>v3:YN@9;{ez0ޞ,"<'q -۵Qլ\]GN)>B=.hc B.-Q|;j}G3@d աBtm;c Hm]yF3? *a/ SŠR䕶+gy #CV8\=:Sߜ%/WCG/ gh ZvQˠYBa$FWp=qAhӿ? IkqnD$P#W9G5swQ*CFO 渽_7>dLMnxN2pܜb.u ?鄿uĶFIIs֓^P U,T{OB~KtH9,;I#,2p"|vvZ;'HkDh_6UOXê=(@?+ABf? }iDڇ?$ 6gM FYo﬙~h쁐I8U mG[M:kķ󘁟M#/ש_&=VBԪ|?_\j7#(]`B<3|V[%mh%1 R7~nMly㴞m?-4N n̄P iVS4sך$mksyyqXmO[ůjgr!w %}s(x=Դ+gZݢEP630pگ }i;1ݙm)t0>'<=3ڤ–o׷~|SaEPNh}v^h^m T.u[m&iQ 1$h6+F.lm\(}0<{S{@k;I_pzZûʃzmdû(F[җ?FڰkNaAv0+>O_p.J_v>v-uS3y]ej #Mo }i|_pR咳F—cQ^^^ƙWlj65u?u?yƣcQ^^`ljO-/y@k;Gy@k;GЭNU|_p<_p*1VDsM.jy@k;He5 2r\&K0k;H^vdd4{@{;MM=0mEa&", |?}}AjE{=,4u?u?AfN\Kͼ5/{@{;EY5&b@nrv7]V9Ro(M=?npWAfN{?6rz.ݽT {;R0[;Em?6]B./ }Qq}E]676F?Џӿo?h5,?ӿ;~m㴿i5,ͷ7Gw3tϴp.̖(f3M(MFjNO^;,Rגo^gqm##Hi Tlfzy/m?ctPs0qkZܖ , '[ʨ?y{޹<O[2ūmvb'U%vH[‹M lO24n3=2}:qM 7 .S=pY22{=5"QHU[d+a:) VH#8w+|'09w^1{v2jޛ F+PJH/]+n-`rqVYcjM(O> +6X䷸sܑ$F?opIq7ȥJ!vzGA,fmߕ3.yU]t{mrE5q$YGj,3VUV9&CF>$ݽȌU-<6wZDI=-l縑["Cl'꣕\Wпs{plF\c:ϰ\78R X*{xb q2Y|ai[YҧW=;QʀoYQɾFR&fT w5|k_"9K3fg=AUF4m]"/' 1CFX䍁"xmǩ, T +.^=ilեf4p&L/=c֬ZZP+"g,OMWO7v h7I!/$C uv./-]IC+RR&f3^F'T~v1cg#urnQbIZhdv 8N w\ݲ>0%R-< *l25JabiC,Whæ=8&5lQ PU\؅f9ɫo5G{{Kڙb G2DF.ȝKo4}..T;o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]r$bך|Q˒+nЍ^q^e5_ <ϒ*Zjw#8z/aI2oz7m7q+F[fd$?8ɜw?c W}(2H(]ys\ |cb*}/YƏm$YwxJdp fT|w0(M$A1/$l~OSgvo &w5^~S]/;I'3[YԖn7ƈLa_ҤkDR檨&PnХsVOfL,eRPǜtǯQlmC/Tz>LUr:WI̘ gHYIȢQM:%DffocP\h敤;L)#$fH!/ 4Ѫ;Es뵁q4\G϶/UnI&eek51=Hz:$=sѢvEș]rԷv$c2uf ?ԊtiͦnŃ>vzz_69( -14Ue}Vo80ZUm;`ydy)8n(6*FA2PV;2I?盛ۥMVxNӃ3C`? QITn1bw6v\:-̙ TOW9oϭ pI=(ޯ4r7[GP沑E̼P:6 Ҥbu#iLg+#I.іA²8T:q1ŸRo.&l=`p}nj3Ik ɳ .[h_ܿ9ܸ:6.JEԮ& gVB+v9}銻Q3}ltCas3CէYO*VE,hP2IzWErȶ;rsZu`E/BU_:qDc%,n{9V9eI'E$N::8ڑ&|W -E,UED߀T`d$o5׻戼Gmp$d' svu ȥQɴiᱷtG[w$p1'~uJYCw `#݌gn^#P̊1+g[U ^Uv1RKgzM2UFD[ss'UbA?<>V-#{TWy|笮h+Għ5$v2f,yMĠ-\n!i$+)uRG c?^c+"^QG%O 8s`ۇ>,<>{O9t϶/G}fEs\+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf._"_|88%%޽9aI8k~)k^KZؗH8Ū,]iB٧Dx.39wXg(84Уg%x0K}$$ѴlU k;IH2C+G'~'~mHtt։/!ܿRMfG688- ?"~?>?xJqNFv径Yo% s^P l\v$]#?SI}5A ]Hq9Wt k Mh}?>?MGqC,/$Rx[O /#[coO&M'@k1(F ;J=Ro?O7M'@چi)Yq}iV\ %F$h#ߒ4N/ ״bT#M'G[~Mȶd JUB(UP0+ߒ4fO&9{ ]{< I$gd/ |ײ zMg$h3ߒ4TA \4Mr 9?S~I}o?1{3I,EQf S=bg?S~Iw$h;U݉Q92Ϧ$I"Ł#c ;ߒ4y?S~IvͦA'!3߿_J˪Z wvU*Ǒ'K'I?RI?wBPo8n*}}Ӭe>I?RI?RK=cJQ2p{zVVWKyTIvc#tL/MT/M>VY .ʼnUuM6=Ncv5?'/II?2Km?I4ՀI?2K?2KF) toW'[qu/[\/M'//PZA5bvw<7UE3˗~e)6K?2K 6[5!6]?vVAַtM'RӯY Z%% 6?2KuTT * _{49 a#'s? |Po\vW(AfOO^mIxӒo]>mBc %:?2J/t㳶GS rQtD[JOa) )())M% JSI@%)PIA J RPh()( J((4Q@%PIEJ(QE(4Q@ %P(EE(4QA %Ph(@ EJ(QE!) QI@RPEQE%QI@RPA ]"uqi7ɷ6ccנXs>qWM$ֿէ֧Uit[j"{0/8zsN}B) fXQE%QI@RPEQE%QI@J(4RPA PhE% RZJ) -% JSI@%)PIJi(4RPhE()( J(()( J(( %Pi(IEJ(QE( Q@h@c FC^s:Md2J)1zM!7ݲ\FIZG!zʿQc]p^g*"R8%T(4Q@ %Pi(E(4QQE<3TUUΤjfW3Y_K(:%!ԗ€53Fk/E)ޠ Lњ_RE@5ޤ:z53Fk/EHujf_zE@5ޤ:z53Fk/EIޠ Lњ_Q3Y+GxPheh+'xP_PghiMfh?WA5+Ӥ&W֓E@y&Wԟ Ӥ&ԟ Ӥ&ԟ Ӥ&ԟ Ӥ&,wj!,> CJi(4RRJ))M% JSI@%)(4P-kЩI8l;EK%ђWi*o*~)k^KZؗ 8z\vGXz!,) )PIJi(4RRJ))M%(VFv!+Nc5xrr !-8;"*B^d֮?ǫ_¨ *np91?2\kcúk,m+nx\oʗ˓VhF:MD%@G2@ xVIen)9 3^V+gD:RNdɫM&=2c[q*ǟ<6?5mȡ #ueV]\?r=uʀ$ %Pi(IEJ(QE( Q@ k!ؿo*~&i^kO^qW 3FO_kb^{85+v&R%TQ@ %Pi(IEJ(QECq+Gy\O?_XbmI 44   \{_Ј34oX27,??¢'x#*ALEe  G@O_w?܋?G"p.`hd ?4oX2R۹_?ƋwFE'Q"*"6PhxBOp=} "(ѿaK*\_T\ GoX2d %E~OG./.g#/,??G_X2i~"'??U3 G#/,??´s?ߓQK*@O Zd%E~OEEE'Q@O?\_T}~"'f?"(EE'V./>s?ߓQp3?a?"+O??Ud⨸d ?aK*\_T\ G_X2d %E~OG./.g#/,??G_X2i~"'??U3'Q@}?+O??Ud⨸?G_ Zd%E~OEE>?Od %E~OG./.g#/O'V./>s?ߓQp22h?µ>s?ߓQK*@}?({E>K*\_T\ G_ G#/OO\_T}~"'e=Od ?2j}~"'fd;,H GbIaggii9q a8댟מGOfIy+ͼy#ͧcѳU>ѱ}ծ\~Ad CKI@%)PIJi(4RRJ)(4PZv/Co0ךo]՟bI8#ykb^uz&\_ODYJA4%!ҚJ))M% JSI@%)PSGBWBRU:QI'$+e ?Zi*[<^kc*VmV]J [SK.b?.1t's#)W_ZIbjnމOˇ̪Ѭ7x*MYԡIִy;u$K`ݍ0w/p˨@)VY ,Ovy}}cEyj^-|Y@^XZ+(X|r^5USѽƱyݢqrCQmW7/5vBJy+7)O]Ik\ bdxUlcgе5YÚꖺe-D*2x+Ǡ5j:oiw Z)62#G v xxNj QWGeND)U]r}+I%ՌV7mdYug:joYEsz-F}?F!u`uoZ{S~M׈m$8DZ)A69U{ዻ Z UHbbnsTZ\ҭ=:c5Bq0t* XQEV%MqvA 0Q#v'Nhz +h&|!MZJ>҇(Nqp>4t(((((((+2Y?3ZuI?묟 Yםǟ<6?5zU:y+|}ǎ?}uO* $C@R(EQE%QI@RPE_&wVsc!o*'k^kZؗG$??Mu$??Mu"QE(E (4QE%QI@RPErǜJxp?Yk̷Rݎb__S<]^U_Tjnɫcß+<9! ?btox+['f4ݥd GZ.ZV7V>pAszY^e*<đ\ЊM𿍼/6AsHNA9g&Pzo+p~'arA:lc'ƔαM@ٳZN3ۗcCǚ}&lü\x'zR]-_M5x3Q^k55Xpwv$tS_ jYq D̈́$ wǸpBġ#Bs]wfg.)_ h^>y%ïeJZLB0sτ_J?\Cjqe_[:$tH,/)~~Qt5 ?N;Q%[AX ezc=A-? k'.O /Oѭ-dD"P%`9GM4/".gs/6gggM0zdsk (q[ :xSDef71 F(naVӬ+x2JO"P͞ƾ=>ql[St贍"N `vPbf}UAHܫFso܊ME$8߉--j[]@kRV걦'~]S,|Y/]f-nH+alUK!ʴjʖ(IvնQEQEQEQEQEQEQEI?묟:̇O uψ,Cǎ?2gV_q^kcǶ FWIF~r'ZRQEQ@ %Pi(IEJ(QE:CפU|PCzt"I8#%y/kb^q@5W!.y"R%TQ@%Pi(IEJ(QE(\O?_v|Qr(RŪ?O'3b dg8;骘BWBRU:@`Az?+, P%x[5w$Ix#OC{KڕyR)U4"^r"  3ֺP`W+|A0}ݹ_K­yU0V*|P;YUI\bo/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~(d_ݟ?U("EX+/~*Gad<{VfCO'h>$; O?l_6jH%$>q+~#~ ZAٱtUtSGD]\?rM-upʑPhPHii(4RRJ))M% JSI@ӿ`&mb5I8(oZ˒oV%uDWzk":RJPHii(4RRJ))M% JSI@O+GyW@lZ ?We\mk_I"NoUNjBeQ@Q@lxsB#cLJ?!'r?PK$(F UAbK=aXpFWS^ծM+\6n13+z=%j:|:7dRp3q'[k_ΊKjR弑Dv+0+*I#%]ձ.F̩:4_FJ%yW$uK]lzuxżG5]hO+h$s `@v_s&_[(u˻bo ]A6%6[.{;¸zmSñOM%DB s3[!43&,:yq]ʱMCardl䜶Bu$M`Z&U$~RFsg'5-=&?yjQ=Ē}?.wXȤn. a,Iͫ7UH:xu{NtwBRINџ./}mo3ӨS@mh`[{dS$LDa7R5j>!ao[n=C[f;xvQ=gu{;Nw-%_U*1[MfVFc⡥${pn $ޟcYZnn q\J pC(r xU}Wv:Z'R2;fȅ`#E,m\  ~}6]䶷'JLY UXRA9#<4kWSL{Kx|UvCip5 Ȃv%VL -/0zI||z& ,R(tYYv#,Bտ]RKNP4r`':_yMIM[kmm8>޼Z.]n-m9,Q$1)1 [IAb5/IJyg͠%m5Y^Uc/LnWM{幗CT[r\ʿ3ooAR wQE ( ̇O ֝fCO'h+Ry+ͼu#cWj;yOV GMZ}>ٳŮ\~fY%Ph(E (4QE%QHhC@RPQ8I8(9~fŷ8θ3i»JҧC8u9WBRU:J_ YQ@Q@lxsB#cLJ?!'r?POE6YRYj"b{ּA4n[m jIl r!F|Iu9U/4u2E] >~py;n3b4oc9>ڼ Ux,ms$rO'''gwS9m>po*3BqtW sMgNf&{{h@1*30 ( 0I l///kxV!9˙IP͕ p[>اbS^Q?;E /21_\\xO7B"tޟE &#>[` 7 fKg{]d]2};Rmq#4m֗;+Ѽ{jo$i,W,12VicC5r3nY1ۥ˰X cu*>nh\Q{%ĈSEc1$9b9 \2Xxnu\[1A&ҩ'8%ڞjn"O4n5 CAs/Ppi7h߷? /y.vW Ị^h{kd]Ȉ@Pv+6cI"֝[J -Y^A$J흊B<`jkc vQߗ\ӷ:\\4F A rŏjp˙,MRu e7WW`.9 oΏ"YXfU L 8j_wN_H_;WqpO#5;Y Q%~b*>| 4mqwc-7Z\_jrIpoGU!7rsucD%am2g7vhfcq3Ummu"oΖ(0(((zI]did=$f25^5?ѐWxG[?H3g^+ͼo#cV`mhqkW)ծYIIERQEQ@ %PIEJ(QEGI8sג+C1פUIylKkݾ/&W x3M^J]*FQ@%PIEJ(QE(4Q@ q^'9~ q^'9~=_ kwk`4a]kS>7J_ W5_ K!T#@((BOz$Gd%C#B?nRSծ-uT)1]q(I5 6Iy 2_f { s95,r$G#n<IؤvFܱbN{ е=/R]B9uK\>8*rFrr7o jڋޛVZlI7)V5EP9kAu-cRnn1 Cs;~U럺9}cGMbekYm[ٹX::=J,Ƨ*}- )VV@8< ihD@{ytn.[5!A#odZPmsy1ܸKEd0J)!;r&iV $0Jr+9pAtzRߐ9?GI5MNXŨQ*c_$z}%QMLY˦^jE,${T('wSG<ݢd1PG2G3SEQEQEQEI?묟:̇O >!?FA^k_'YŧzO 5V_ GMZ˳?nhqkW)ŮYPhE% CKI@!PHii(4?%Od!_*>%~FIV%opHO^kc])BE%IAA RZJ) -% JSI@!4rǜJǜJIIv=0⵩ΟS%/S?uQEQEVLJ?!'r?V=lxsB#tQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEI?묟:̇O .!{OFA^m?'[zO 56_ GMZ˳?nhqkW)ŮYQE(4QHh %Ph(E (4 E^qW +C2J7zK\/Ŀ-?dkb^u `q+:9$\?Ev&"QE(@ EJ(4QE!) QHhC@O q^'9~ q^'9~-_ +}k`4a]kS>7J_ W5_ K!T#@((BOz$G袊(((((((((((((((((+2Y?3ZuI?묟 MsB֟?_8Y:?5zNqפ2 oc`tկ3~SE]\?pVFQ@%PIERQEQ@%PIEJ(n/C_0Zך+_/p?a%ђU{0]JT4qVbɏ'E RQEIAIERQEQ@%Pi( J(()'/һY+/Ҁ%}k`4a]pOmL+jl9WBRU:J_ YQ@Q@lxsB#cLJ?!'r?POEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPYӬzI]dakj?*'Id/ٟ7_Cr/Z%J(4RPA PhE% CKI@"I8# y/?^qW ;F+O_%ZؗDMrq?O]])BE%IAA PhPA CKI@!ǜJgǤJIIvY<0޵3_ K!T!)*dhQEQEI\[1@=Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@fCO'kN!'uC4 פ2 _c`WkId/ٟ7_Cr/Z4$ %Ph(@ EJ(QE) QHhl;zM\7?dXz/Co1ג*;' DWdiH"%PjJ(4QA %Ph(@ EJ(4p]rǤJg$i»z[ ?WqZgOBWBRU:((+cß+<9! ?b:z( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ̇O ֝fCO'h _zO 4?O5z_?)i^+<_#mGMZ˳?xohqkW+ծ+#BJJ(E()( J((uI8#y/[Y?ESyI4yI4O}'}' U?O*O*.QT?>?ESyI4yI4O}'}' U?O*O*.QT?>?ESyI4yI4O}'}' U?O*O*.QT?>?ESyI4yI4O}'}' U?O*O*.Vd=$fyI4CbT` $t?)i^+|_#mGM^ Zפ2 _c`V^/Zam-u0В)(I@J(4RPA PhPhf?7p ANK$CפU|PFIV%w1>O]IV/'`q+ Ph((4RPA PhE%)(I@O+?zK\W_X{m`4a]pg-Iw5NtQYQ@Q@Q@Q@Q@Q@Q@Q@Q@6vqq" Kz MU(쉔ݍ*+7v7Go?o"fO4/ E۶_ݼ=0}e\h4o#mO:HLj= UHѢAH2{U_{s ׄEAe*?_?G?_?@?P|EP|E^k[ Ck[ Czo<5Tڍ fEWqX&H TU{{/,L;BB"#;6:T*Zxj/ Uk"k"/QT熡?熡Egk;E,3%8"+F)#P? Zפ2 _c`WxBv?69?tկ3V~WE]T?pVFQ@hCEJ(QE(4QAC@=zM\??di&v2J=N/'`q+Z/'`q+ B(Ԕ%Ph(@h@ EJ(QE(4 p]rǤJm`4a]pVg(+o kZ */$vʐ,I@$uS:\qa&`V8բ#1QOk{SՂm!Irx"{,o=-M,BN2cҦ_aw{MW*"W*0'X .V}6rUl&RX25m?VgIn|ɴF>b\慣w>%4鬮Cm)U.%m'q72Еm9E]3.Cp#/},7t,47 bN3ßwpA$v_#/K$*σbd RUO/!#^wۇ ft[69`Q{3D(df$"$E:5,љm0*J\n9giSFKks*!FFSx u\֗N(Ӯo]%.m ߾ʎ,00Ry3ҵ?Z2}I\Fۤ5ulᐺppˑTƺG,mq{pm(}ђR ɑM熦Ț #Uݭ,eUAT M{/j2iVAmv2IJHwDH7`sO=mZmΠvń'2w#ЃYxOItEkfͅ\szʵVg7Ɔ38RQpI>1/CЗ4uT0heo\G[}:XUf!UC#FX?} ^yl$,eM9| ]}cWZ-ݮ ImbHd2F_$HV>,Gi{ Ia!cRpNkV XnY`ȇ!? ^"ۭK-N2X PDkҴt&N.abB,@|7{ܷEPEPn _69*iHL"$ 8Ђ QcOv,k of=>=^hf͛pMAcx/W-GR]R-+Gmt; cH-TA+-n4ctN;wucv)V0fsx)%KlK{,Fv e2Jc#-;Xלj5ݺ%Mu!Ry b31>ttXu%KB'b=d~Vmn<,X[X[ FE6_&?NG88殼%utVԭiY͕љQAP7pGcK:^"J%}8}# 8?Üq;VcѴyz]y{vmAoq*,zyiь][OA` &P2#Eo^|)VFkQfq~7l8:o\2Y)XzU2}msc^O{l,ຸī=I`zK${Gy+IA՘hLcp e-B;JmV+{#Zp$Jwm7lb-]b"w\~zbMk.D$WDZK n*8uǂA犁aE$GTQR,^D*ev@'O7c_Vm<7}?K]gqZ_ w0\ 2/Ȳ)7)mSЂ{SbGQ滎0n.eo-H1g-;P$W=oȱWcNW1}EziG2w/CO/>TqmBg|yWp©=ɣK3[n۵3N4)Lj-5{}ej X??smLLE$s#odc؃zze1nb8#ȡPH'#Es5M/PKhKj`_%ќ$wp9<'VQFEGRMWWe<"FTg<"?Ңl (ݳw/.*+7vy"?,Ңl (ݳw/.*+7vy"zy"04?? ( N޳w/zy"04/? ( N޲OQe.:+3~?G/"0-Yg%ۂ>9F) (ųv]vbm۳o*<5Ɨ/"~?T$!'vgtlv]vv?uʟc=<dzc۷m۷f11GO-0'tlv]vv?uH^R[26H9P@?S:Ddzy"/3K?TcAKoƩ (޲w/.Ǔ_Q'.տ޲w/~y"0O ]߫5G<Vj_"H,},?U5&gg]"UQ/pnQAflFIV%tQ?;ע;K c]  RPEPhE%)(I@Jd*k]qWT+:SyΕF{g5͔EʙI'aV  898?XxhB~Z}UJ:qn?Xx8|Ek/;U??)??)Yw6>XڣGA^?XOX?k/;T?(c=K?_vG cEj'A]?4?_v>j~{Y D G cEhώڥGA]ώ?a<_v`R`Qf%Xz??c.:j?~{YhF?<_v|SQG{8>Xx''??~`Qd?gO4?/;G'z?Acҏk q'G=c㴟h4_vc=Ĵ=\ԃ?XxQcҏk q4?bh<_v&>:k? ҏ/?J=ώOXz7/?J?(gC>:hώc ҏk q4?a<_v>Zk? ҏ/?J=ĺ?[\gz1McW ҏ/?J=ij ֍>EhFMc[ ҏ/?J=ij ލ>EhFMcW ҏ/?J=ķ ލ>Ei?;ѿXhTcҏk0q.yϦ?<ѿXhSgҏk0q.yϦ?<ѿXhRb??J=Zǚ`(*IQ>$l~FM֫ͩ]@vƀaTg='k+VIAS)[(\`*] c *8% i(IE(4QA %Ph(@ E,O6NdFC^U֬Ud?dZR`ϤU|QG-@կ$??Mn_NSD)D4QEI@i(E(4QA %Ph(@ MeA lڡ6*{UC@>¾}}*! a_J>¾~a_JI@>¾}}*%P QC+GWүPa_JI@>¾}}*%P QC+GWүP+*%Q CbP6+*%Q CbP6+*%Q RG+HlWүP!_JI@~¾K*%QR}}* ?b_JO/撀(}'ؗUI@~ľK* BGj-{UI@ UPIJi(4RPhE()( J( G1פU|RCzcI8#5y/kbz_NSD`D:A[ JSIRPRRJ))M%(@%)( J(()( J(QE(4Q@ %Pi(IEJ(4QE! ! %Ph(@ EJ(QE!) QHhJ(E ()(J( (E%)(I@J(4RPF_*>)k^KvZCyI8ןr_ 4|$-0qF#hBLIH"QIRPQE%QI@RPA PhE%)(I@!PHiM% JSI@!4RRJ))M% JSI@%)E(@%PIERQEQ@%Pi(IERQE(4Q@ %Pi(IE(4QA4QA %PhkmZ7/?]nlFI]5( i/V̺#d?dkb^Ce*ɴdDWY\ ' i(4Q@ %P(E(4QA %Ph(@ E (4QE%QHhC@RPEQE%QI@RPEPhE%)(I@J(4RPHii(4RZJ) -% JSI@%)PIJi(4RPhE()(%aY>/q T_h0^qWKFk__ ;H䟧䟧%)())M% JSI@%)(4PIA J(()( J((4Q@%PIEJ(QE(4Q@CEP(E(4QA %Ph(EJ(QE!) QHhJ( ()(J( PhE%Zѿa%7ֿezK\o/m7[c|&?'`kk̓} %'KIK>k5%QQϴi5}_ƍϴ>f_Ɠt'@__t'@3/IљOƀAo_I4ϴi?5Z &&i?5LM>~k4LM>~k4fi?Z &ٿOƍϼl'I_}i6O>}/Ad\%!ysϻK4\%!ysϻK4ySϻK4CN?<ƀIOn?O&}_SƏ"}_RSƏ"}_RTEI{ƀIR}}_?GIR}_5@Tfvh5@RTevh-oƀ"s<_%oƀ"s<_?%oƏhJw_OhJW_>u<_)*]}/+}xƏ}/zJ>w<@%X?`_ 撬xƏi*}?K4XU?h_ןK4g^}/SIVo?hͼ'_ y<O/CE[̼?ٗ_ fy<??<@諟wG]LJ4#I8#-y/ZyɷuҸ?2ZגoV%w>OR1mf%"?!$K~##dF1G$??MXw:/-v F"q=SRq.XDҴL tI6mvoIo]cz|WY;s (.ӴNJ ]#ikѥ,Ng`',q'o=h;i+gs Է.?iA#eP'F\ZBPYH ! [sm"3 %YY >:mmX&`.#pZgkAj:W7djaFcvlNy`S 5!q>9e3d m3/UaHuV%:t9%wv@~x2+2jQG:<$}0}L$}8,G+gMqxNn4PhzmyCKR)l޺ʯpʟ+f<xNѥI5MPA߷ñ[^"I N &H$  ~簱ặ{{6$upk 1z\GA FR[tјHdXrR \6@bFC_Aokȍ=;/$®>[ +ɻɛ1~6q>Ŏ2 =ksG/ GQ{Pw4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEPC֟? y7IC֟? y7[4&PXIW̥Wadr=a>47vN, НWÜW AGh  0>sA{7^) AGh\ΣO4i5=w?`t}nS-s:? AChӰj{W.-}|^׉EgP?"?3Sv Oo}͸\ΣO4GkQ4qA7Gm/?x$z =sZ?ѧ`ۏ _0?n?1|?#?5S)ƍ;fbqA7^! AGh\֣O4i5=6nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Oo͸6nC=sZ? AGhӰj{u/?`u)ƏH j?FSۿ?1}|ϸ\ΣO4GgQ4 0>qA{7^% AGh\ΣO4i5=7`t}nO=s:? AGhӰj{gn?/}| ?x$zu =s:?ѧ`^+ 0OH ?G$zu N^ӆp1|#?3S)ƍ;g\bqA7^! AGh\֣O4i5=6nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Ooθ:nC=sZ? AGhӰj{u/?`u)ƏH j?FS?1|θ\֣O4GkQ4qA7Ht17^# AGh\ΣO4i5=܏0O\^׊GgQ?#?3Sv Oj?c\ΡO4EgP4K _0>sAk7^+ ACh\ΡO4i5=?at}?n[-o:? AChӰj{Z\0icnC-s:?GgQ4qA7Gm/?x$z =sZ?ѧ`ۏ _0?n?1|?#?5S)ƍ;fbqA7^! AGh\֣O4i5=6nۏ _0H j?G$z NO`tgr?/}|#?3Sk)ƍ;n\^׊EgP?"?3Sv Ok?c\ΡO4EgP4; 0>sA{7^) ACh\ΡO4i5=W`t}nS=s:? AGhӰj{_n?/}|~qA{7^' AGh\ΣO4i5=7`t}nO=s:? AGhӰj{o.?/}|?x$zu =s:?ѧ`߰\^ 0/H ?G$zu N``u_)ƏH ?FS1] ..dThTmU^y GF-fǰݏ5ŭSƩ{42:%òB G*/T`I endstream endobj 73 0 obj <> stream xY[oG~G?n$le!۱&UX탕D0dCjI\`׀j3g7Wz]/_?/~|?7f> 8ŝykɄx|p'ΟجIl~mx_ 98/*&6ǕnbS۹,X]vΰc }.Oښj]2,,SՂ{4Yqw,?}){uwi=eO/XxtS蔭[UP ~^k(kj}Qަײ G)|PLߗ=S+qMaiP1۔ZYrq2֫x%b46=n*Q?US&(B!a>zE47.GˆW&-KWq [֒ RH'в'l,Wu͔6& &NUE6Ȱ8#WdtRUAydByR]/׿邳?(&DY hZA6'\(Qse-KS"#nRI&R_\y.!-"voIZ^jv5mܒ W^U%mJ-*UсDśXFTʖq^$%u@>CGn t{ t4G/[՞=-lkPݓ]vt\rRXCH_ciK\/`iđ_^s hF&[!n4`8i<`4?ysʪlʊɬw>,$rli3Fl0DMLϠE qDŒIɧz?:<|C@H9qDy*i mR6mp&xp"MzEwoS65Wsqqֈi ITIY':]x ]qoq .z^ gٔXhӨpƴo i].\}K6޲KO*$M;LZZsd̑.)/B$UT[N[ͨ{s-l/4<9"P7=w9C.?Z%%):eK_iP2nMGhA7˚25oUvTSky@;@MUAлHJTbGEDlkL"}DiӴ`PDmpl q$R<*6%3ۺ44Y9 ibI %lի^ɾcRb.Ra2(> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ? 2Rԭ!NDƎ2!IA$rHt24$_M#E%+V*~âv|Z(hAt-%"%&e8P _oa,-M ӻD4x{I??]I@=#QqtHiLb)*br/v_ &⹯4:i4kٯmy\'>ZL$ n"43ŕ欗aSt{r[^鑑m4g{"Hcx_`GE? jjQ` F q(c?Nԛĺ͝S%#V1c zv&cZ5 x{A_iU6ouiX*@medxY;t =s֭\ܲ1M'obdFtZGCa??&왦OfiK H/_"ò~v;? A4@ЏiwkF9hq# ZOCկ22Hyw*6 @?$;N+)_8yw4FiK HZpq.yw/`h??&:5]G`r40=#!iˡh 0-#!k4Ozm;=]΃iJ4 дg@F*{i\`q?п?M_/&yrGܩ4OiVd54ǭ {<+ #"itIzSB{ksK@#"ijȒ`r#t>teG,i.E9r #"i??/&M4-9r#4ӠxxH/$Fyٮ`x{:GE`x{:GE_=iu'=/xHpt1Io30f;Gށ@ #"ho@5ẉ̥Ȼ(7HC:GE]úth_?& Ȼ;P>?M4])C4Ze]ƅдN1OIirGsx|H?41͑Ryr.}_GE7H.E9r#ts@5{}&\r#tڇB4=)Oڭ+c#A#mOUr4؏QV*2w-xgbi^G-A,hlPc֭ CM?qw6? ?k_ xh_4p(xup\.eY@KB;.'#jatbtCnx*9t}KU؁rheiu~mi]ˑ?#%s{STbm\4rxIXd1ȍcnXc#*=q׃S? &qym k$ð2aj'?VrԚ(Jz6hp!HC A8 dJiAOja2pɈ% d |I'5 %x3{1yޑLG?("=5j?շVzsGԮtS}BtH-u1 P`1<)mKM_Q3rb-hʐ1#w^y5P'n@}C{݇x)'4ກ|&;6_3&=wezKc$ڥqD@؋4æk?o=Gf@C>va{Ph o մz֤-.G0dr{IapD'&-GLLyVFEe ;!1/g??o=V`գ#vVzͮ*K?#̹!"2ynq=A{u7zߝsb#D"PY'qC&_vvW}\׭3},+mR+yiQ 1B {gYZPhp `HQ$ݿ K+\,/fmMcﰢB1n;FkBڮNa@mV0ボm}Ajⴻuu{xc1$C%K){(;EKqnšE4=ojຒ'kEJiZk-A}}Ai`?}}Aj;2FbPMo?˱XFM C7v:o?ϱisRPM:o?ϱ(jک5{Zo?b?}}Ah}jQh{Zo?/P~ئ- Cj\@;GP=;bҤHjP_ {hwe>5=UBǨ"=Cvm؎@;G_P^ϱ Ս^@;I-C7vksS[UGjYa7v-0;Gq{)vI_"}vks&i;}տø{9v+jgҭy˱Ymv7@˱W{RE=ߑ@_"{Xwg.Ah ȿEoh/}[=;a(/}[<_VvkJCN/}[<Vvka㴆vk؄a`ߟ_Pi?{Xwg.r)-@&M}}Ah] Y:~}}Ai?_P^˰YGȨF_Pڕ-5Mø{9$%E/?/@a~]Iw}}Ai>@;KCrKs—6A!`̇ ATfE캇/?'8>PbخGdq0岻/?V˨"m_Pڎhw*V[+/?~z)G}6/ګUP_Pڔ}㴯㴻_Q}??zn-oh}@[㴻 BdSA2`S|~M }P'vk ՠca?/"_a?t; }7PGx9E.O?Loܷ,?_'}uѾݿhvk'Y p 1*%9o_7X9?lQ![ymhD`An:׋|kuFZ5DÚR"4O$ؘnlK-k8@듃Dx?H+t >o;ٸ1׏ҹ+uUvK2c=:6FŻ*2?\73 \Al>R{dB˻qeʲw0} dӿ~_ݏ&c/\Ƿ^zTOc5F4m<}L<ܮI]). y~Zi'C;v3"oc f,I ZšGWdX,v,Rd U-R{dB˻qeʲw0} hp*䴟Ǥk5ifxR $y\s3޺cA}1_W e?t-)I,u$UM۲ck[Vͥ&i/,h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂIviq+>6,6ZMuO#FI.O" æXm7RLG9^+ϡ& ﭥm|A C | :j J*no7>_%: gzM2UhbEsgk!@8FUx9S~y.|=a4ZGY8ySs;s4Eo2UR鶌7ڲ9I'p,T.dT(H.ܬT `#r=cj^NZʯrvּFer4c53+# 2HZ]6i>??p}Hě< Nbb]vfdI6v\6ɒ5yɘI4 O#W/^׬Ntao 涰M'Mw"ը.&.'ȀH93\\Skzib ?*>\;;)PLUq7vC̼g؊|?jI9o.0=(ͮ q4G'2c Xd#X"o5UFI7RLCw-gk{6fIc*D&:컐]#0Q^WNm5{vV,k?/EYlቤʨ,M̼?8yҫha$~߮+^_I{qE屴u iR2zUQMԠ}U?,h:v Mߘa⋁^DCr)hgj϶/^an[A?̠Tz{Xe .;l",hN7j q:CӴG&Ǫ5 h=9B[Kv^Sz.gzM2U^4%I=e$W`2|c* q&ǪJϝP3lhhvNيqln^ZH2xq\CHndg:}7TZ΃~}mdM^cIEX8V:_5.e:AѵXn&V'+J`#?]gVM!v @'YJӉ-“|vw_3a#ĤsQ,׬OX`M`rB?QֹtT.q4K:_k'WLUݾgڌyc Q<}-R)fBM̼Ս7VZ+EݜsjֻV(@zʨzӊ#i(cv#ʱ-E2I:) ~bqԁשh >Ԍ6?_*mam)dV*&'y';y^ޏ4E;k)$3 ?)9cE*MkO :ݳ%V9's)> Rd;qc8,@=EO{rwmqx.dU?A\:w5heB+ ȼ1ʔZ]Σ>o b2"ӛ:? GұifcҿG=esA^?'.%?ɩ#C1en%}Ajuu I!YK޲8@T3z#AY:J9,x`7q N#=@>aߢyΫ>OU}f?7U+A[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp2Z87MsoEL&P:WBB'_~3ߒ4bkXJI#8#$uYxKf$TFxֺo?M'Gٟ~(ڠz W-xb{hHÐItfO&?S~I-g/aIb*5j|?gO&M'@ڭ휶H:ǨEa}1"IF, 6{V~O&3-.m2 7]̟&%?% ![K oZz\i0匋FN9u'Ҭq3: ~d('Ds=6ЯŪ,]iB٧Dx.39w\N)'+C[#+'I_$Yl8s-;; 衖5t&o_79/QO˜/xZME y$Ph> +FXϑ# =O=O<?2~Kfo_s+zzO“t'RQ~o_t'@ğ? Т?+W(F'W('W(F'W)< Ң| < Ң< <€4:~_? Ԣ>~_ J++ϸW(? բq?|R}~_ j+'hW(ZM7Gn ע>s? |Qo€5\+}{@^>zӝ xƧϋCF^,BcWjLx9?lH"DO$Fz4 :*삐ҚJ))M% JSI@%)PIA J RPh()( J((4Q@%PIEJ(QE(4Q@ %P(EE(4QA %Ph(@ EJ(QE!) QI@RPEQE%QI@RPA SA^spג|l9F^#_? y'Ƣ-rkE#nH+׫!@@H+֍séSdQHkC J( ()(J( PhE%)(I@J) -%)(4RZJ) -% JSI@%)PIJi(@%)(4PIERQEQ@%PIERQEQ@%PIEJ(QE(4Q@ %P(EjAy^K@rka%#FZ/|#-O%P[KVSz 04Q@ %Pi(IE(4QE! %Ph(@ EJ(QE(4QAC@R(EQE%QI@RPEQE%)(I@J(4RPA PhE% CKI@!4RRJ))M% JSI@%)E(CV?O-zՏPלUrrkE;X-Q^k _ПIEz]c!3 CJi(4RRJ))M% JSI@%)(4PIA J(()( J(()(IEJ(QE(4Q@CEP((QE(4(4QA %Ph(@ E (4QE!)(J( ()(I@0לUrrkla&#FV!w-L'Q^^Oh`ӎ?^g׬/syQHjŠ) QI@RPEQE%QI@RPA PhE%)(I@J(4RPA CKI@!PIJi(4RRJ))M% J RPh(@%)( J(()( J(QE(4Q@ %Pi(ECV?O-z qI8ɾ5ʳxסӓFV7m?1^_?,?"su>IEQ@ %Pi(IEJ(QE!( Ph(@ ECEJ(QE(4QAC@R(EQE%QI@RPEQE%)(J( PhE%)(I@!PHii(4RRJ))M% JSI@%1o*o?3_-z_7y?/4/_@?  p?"5rSwb6RZJ CKI@!4RRJ))M% JSI@%)E(@%)(4PIA J(()( J(QE(4Q@ %Pi(E(QE!( Ph Ph(@ EJ(QE) QHhC@RPEQE%QI@RP)!o*4_-z&'#V`Ѳ28? w_q rwb6QAa(E (4QE%QI@RPEQE%)(J( PhE%)(9إ H?sƅCe@ #``鮿oW͡h,G,Ï}=?]xxFPwsNqyv㯪>Q"mSPt$P|*~Êd^#g7+[o@b{4+B`t N9cz OYj_`u,^st{:}i’m{]-5S+=ފ=-yu;K-Jh \F+Ǟ~=0KqzxV$p@,WZT䳔;B )$TW(&6"{yp,xJ,ע[i D%fկO]~^~kzjE|n첰Dd~=;K-%즼17>o9Jq ŕܰ" x~5ⵖ=GH^ +tg_<$X܁ ;ڏCG]o+m~}n+wm_}^ޛict˴ Uo]X5TD@Cc,Ydk'-%-p"tX'Uo8 цBׄVJqn冩'Iݾ{m;ZInuq Bpk>ڈeLr``=YZn;]B)tm> .yn9eh^m@FDP߻3f?}yjI|eFV3nGر[W(8ꖱuGy]qTbw]o ho+ +"VIR=&10P>^.ϣצOQKMO]Wkfȷkʮ zqJ֜1_4d#'>NowiU:A,IPc ŜCqew$m^/(m[b50VN5oU1sڷ]:}^;vꎱ|A=ׂ?6r>o4Yk^Zݬ m`@"TGenD6~{Uay%ľ$g"( ]9*zg…Bͮk~(oV5yZ[WtVZ曨}ev sZY^DvTU2OSZV1c)Nj%)͂PIA J RQEQ@%PIERQEQ@ %Pi(IEJ(QEEI82է9lr/C7zF[/`!_C?"Erwb6RQEhs%PIEJ(QE(4Q@ %P(IE(4QE! %Ph(@0 AQo 0#4 @P=1ҤpRu>+g>O3Bck9j E-bU-JSFnI\]K#K;p'~3z|?i{ Vpo4¥:9jzE\4X$q/YQXj>%׶VZ ,6j/ֶjTniv)R6o+W7m-#[:` 2]:xck+y"b4x`G_ܬ&9дщcB1Sj;͖_f.[|$d71Y%4l6Z*bh)QdXdEBq[Y=ż@!pIYڛ}H=̮COCB*慶edX[[1F?\ }żQ!h%$P{Y3#qYΩqe% -8Edc*s8Am.'f:2ҧ~x~όy[zcf[k6W#Ų\Mo#(R;6\.q'%13F;U(TtdBtk7ѫv"BŽiLb08=Qm˜AcEoX^Hc@2V9U=p FH{u! 0ڔFP$sekz][C8SLҵC-o2 !@B+?J IDLiINZ Sf6X6TWXd*4P! 8wCYRiY2SwhlqG kH*S4 ()(J(4RPA PhE%)(4RZJ))M% JSI@%)P-9zM^OF'bCפU?lrke?EH? ?"Eré݈>A9PHii(4RRJ))M% JSI@%)PIJi(4RPhE()( J(Ňʶ Rˁ/#?ڶkm]I,f;"KG"+ 2#Њ+jZ> &c-ɀAlIiFnrVU)RDZ,/iQO`s}qIz`E$+~}.^pYW-y1MˌӢt-`cBJ`w]x_[pIF?.0($tH2 ol]lZ,vn_p:qNԭYc ЃK}M T[g2E<1$XӧNceȧᇵm5tx%9{; FKkk%)6H*I|B; 023G6B;d/'_vnIQvOu0_Ef=MUH㱶yFϰ ۛiÜzں=;EӴqcjo%$ڠZ4M,v1JH2JNHNAVޞO+z}Z_UvfֶnsS3iZqS9+i7+g")ivD."w79zbMkr۰<=qZiPa|ƼҾߡ3$O?wPijVQCb+vɹ[+IφbfWGube-) vR( (yE>G,3Amj4;wTr2;׷cW&ĖJHӞ[;/CK92G -Į8'8OIycg-Զ*]w,[h@(Oq FdkJ*YGeAam.VY`JrU#84NX6VeQ'%~-Kh$P}KYoNtU]RPA PhE%)(I@!PHii(4RZJ))M%@e)#>`Ѳ׫"I8>0ϧ9l 8ǤH}k?"5sG݈>A PhPHii(4RRJ) )PIJi(4RRJ))M%A s d6sƩT-f}ni&ÙTj[XZmbU082O5;5Bn#?违T`DΣRO:eq'*AٝGj'G`()( remo [nkw!Sδ9鸢Io8KPg^EGO޸5-y..$t-$ۨ#յ4*@?(G{<^"MSGζ.6'v\?XI<=KUd`c?t}:eZۃzOS_G|J!/IEIEJ(QEE d(`Y #`l&r~:ƅُ`*RG{ !bı'ڴWZ+epvri)Au_*_4i_-z_%)#F`Ѳ2<D+jW P8WЦmA(TsEJ(QE!) QHhC@R(EQE%QI@RPYڶqGA%8#=pG~U5K 䪳P$rG֢MR4q܅.腝y>SZtC̏@|=>h>?oխ^)~|nOI۷qyT-ZtSFy[a6n>^91ZjF/iOt :5ɸdKUo."2LnY"hCϵ$7\\< 欪 $. .28Yh4RT)(I@J) Cytv3+>018}IHi&Jܻ r۽\a)-Hٖf p-b5cQٲ1)!۸pG8=h̓Jʼne]+r1Gf/kO^k,`STzqQǪYr-F2d\n#JjޥCKIRXRZJ) )+[Z{$( rp{vJ*UbӬvxbFc!5YuAg"A29**ydլwW@Ŀ8 60H}*)D~kKXwm$U|1ߛجbI@>l 1d!d8=gG(ADģ1'i$)Um4PjlXH>npOqVZF[;%)PRPhE()( J(()( J((4Q@!_*4_-z%)#V`Ѳ28\iB:Tq{hu;+m@)( J((4Q@%PIEJ(QE(4Q@";h*%p.G.:nx9O"u#ҽyaq Y ̛Ք 9nr%k.c`-dnU^úKPŐ;@ފpwu=jiFF Q9;g~-T]yI1Txtc_Xv$?#ZEnh I$(#uݲ? KVl3#>j뎖,OIF%K:Pe ;V߇2m/KY \'JMо|.L;2Ǔ$ۉf㯽 =E]AL2 ` )>i5r4vqpl|ynJ]{z*i^4V,nfy;A\l  Z67Myf< AGRp;%NQWhhI=KQA4(4VDz_V22xB$rٴ.F2zD5י#+i 7E`XȨɌs#'ۮ}~Oyl 3&pUת9}{_N3-2CyH,I?(:S?g5Dǖ[)# [)hFo˅9(ZFae:jo}}_%Eo:|D#hwcv[BHtKګgg~滞748sqvd0<Tgwih2 :0r1t|ooB-_&Ohڒ3a yx0_>`iXn|&wnmߥWZHxbF8ދ;tQ\\ʋtc0I:1 w9=ZDٷEc J/.bE(7(?{s1Nx=qLR 1r+?c;\ +?Me2mJV=N㚾j%fi k;V(4kx02&ݾiA9I9 u:5Nst.mgH)đVp9=c7rAhݥVWRP XuK&ڼ>`ܫ#-ijf8b Q_җ];;M)YmI-bĩg _F G%U{J/ExdhsMj nz\ڬ=z 2/ YOkaG#Gnl|ynDR!:TnQYʐCL3 I W-wjywVȧ>gs#I$MFC:g8M}666v@͂Ğ3ʮ(q:p} 閱\VMһ"w>U}0|vWǵh)I`A⬚uCFByAYXI A=zV% ^IēR*\Vlj1N%R()()f[ e󑜒'uRH;A}֘t,06»•\3קUI#ò)dوMg/^HR,GUʭQK]ò24sg|-0`88Txg`:/H!]rzw}AVM(҄U(6k ̛ W(8 HtUw#ڒ(O\Q'=6Nm.yGat:}#k ۗ$x5f\?g ڕlBfē;M袓mdk#dvP䐤OAޭB[18[V E(PivO:9m X)e PpOvU{IdPM7VX+r2(Gsiq#<Y]Fl)e]cF.1')s˸:pTM:;=U,zOA_U|ڣy3xS҃++Iam$KFvo2 A I$A==jXaX"rw.2IRڳcQwH %R(CEP(QE(4QA %Ph(@ EJ(4QE!_7yW,?6ZkO^qWhed2ʟ? E\H{ٮhu:mA(Vb%Ph(@ EJ(QE(4QHhC@R( ()(J(򭧕A+WAQMxd;I4ţU}ONKTg&,V2A=imkcΌ>>VT)+BBE%)(I@J(57 ; Wd"/vb\ZVώg`r$81^{̩)8u=Y"9dzPjūp^ȹ#v4ӳ ) -% CJi(4q(dJqѱf#lqIsFYHӪs$ HzֲR KC8֧'d4)*8'& 2+#@4RRJ)(4PIA J RQE(@%PIERQEQ@%Pg!ؿo*69?l&+#mF[/d ? T\H{réWh%)( J(()( J(( %Pi(IEJ(8S)F9, ؃۸uNɨ^t]COֹmƓ]=[CSjb2vG#&xw g(`yB9 ^\}5ZnJֻO7cWimW{eqcg{ hVr< %{KK,d#pB>Hk6)nu7zQEJ(QE!) #8ROKq#ʌwOZ%td!cYsN0|áZ91w]=b+Xm>Ƒ^qҹ]AcV0dNw.>MYW°쒮z?]$ a+^1RzEh*դd_Mݺzq(1@'$~W{EQE%QI@J(4RPEPhE%)(I@J(4RPHii(_7y_Əl?6ZK?^qWhed2d\H{ѯO`(W,:uvPh BE%)(I@J(4RPA RZJ) -% JSI@%)O;]ЄoFN.Χb]`F۸tjݍ+]㕣`;AǷTOR*EeFLzC86DfO3r8$`fx%{xĘkٴAON='K/򬶾Zı1ݵЃ՗,b.賺d`ǽt9QOX_ỵ]vK?!lgh.-DY7g9M%y)H B':}}`'iq#(Bs -: 8H۳q3Vqk*uKffRW0Xwm=Τm"{d%5RI ;}dM&)#xXP# 7s}Յʮ$@Br4l2t⛕+&0ԝ'PO{ؿvW*.=cߪ%w2'p۷'=*@Q9Eʍ)i'IYRPEeW^ȎTQ<6)9w=? p֘h$LS'mܵgY6ˉI @;SIen99=G>M}{YR܋%VvL x܀Ct&4w[Z5XeI&<I?^ ^M"@"c++`'=~T׵^cؓgnz|}iQ\+Y+^EIuɡcYnWe(NrOwNE$ w+d«6zjm2w.B+#guR:qN)<±U18r\VOu\yf2K+!Pn}*ɨC @I$NO'ԕv6(4RT CKI@W Y[t>C* GNqIzԺiZl7J|)m01ZMx96. .O p=$} \wciS].7SC9-FO˂d]8:U00! 1&8c9G5;^Vj. aeRv-KjU`UN㚘XZ#Ff-'=}imDe=7œMe j'4 JSI@%))M% J RPhEQ@%PIERQE-bI84a`Ѳשv?CGO-l' D+kA?"5]^IA1 J RPhE()( J(( %P{0>|){sKymU,N u%5ZB_יJnn^G;]ڜ-o"K)L+0EpG~k9}^8𺕏|8 }܀瞹vTVN?d9_y̭O%ڑLC]ĬH %vIRwC#F3$fE>МW 908Z|-k^^d_3pO!a^9rr?kn_p<;n9kOī;H 2D5 V8 gU {;;P2NrLglQS*i]ʍE@QEbth:aԮph6mٞsکϪ_% n*s9,Aө4I%m~=NoYlI-n$H)ۂӮHn-n"srBȄ- |tj%VsW[hZ<+K *[rs<x^E沁ghSwʓO|gGPhU fn<[WQ'F(5nXqMJ(Ԗ%Ph+:nU2q`֍!]Ȝ9ՎS]`"Il[ q H~H+dd`s]MF"A;LIP3k94fN]٫Y\7!)pprUnLQHH˜v##9 Dk$j,;mJZF;, y;;XmpidcFmRݗsM`.%x8>C2# nV| q8OASպG!ab)s;RI\b ()(J( ()(I@J(4RPA Ph7ygƏl?6Z;^qW|hed2d+qx C? ZS@IVdQI@RPA PhE%)(I@!PHiM% JSI@%)PIJi(4RRJ))M%(@%PIERQEQ@%PIEJ(QE(4Q@ %Pi(IEJ(4QE! %Ph(@ EJ(v?CGO-zcI8>4a`Ѳ22A`8Wׄ' D+N! QZCEP(E(4QA %Ph(E (4QE%QI@RPEQE%QI@RPEQE%)(I@J(4RPA RZJ) -% JSI@%)PIJi(4RRJ))M%(@%)( J((?%,#mF^c!_*ߍ69?l J qwVƝD+kN 4RRJ))M%(@%)( J(()( J(QE(4Q@ %Pi(IEJ(4QE! ! %Ph(@ EJ(QE!) QHhJ(E ()(J( (E%)(I@J(4RP;zK^[F'FɶפUed1ѡ_B#qNG(( ()(I@J(4RPA PhPHii(4 JSI@%)ҚJ))M% JSI@%)PIA J RPh()( J((4Q@)(IEJ(QE(4Q@CEP((QE(4/ϊ4PѲקWV/=4/_2?!E|,HE}\vW>i( %Pi(IE(4QA %Ph(@ EJ(QE!) QI@R(EQE%QI@RPEQE%)(I@J(4RPA RZJ) -% CKI@!PIJi(4RRJ))M%(@%)( J(A?_yg(N_M9l%-#V`Ѳ3/xg"B+GemRRJ))M% J RPhEQ@%PIERQEQ@%Pi( J((4Q@ %Pi(IE(4QE! %Ph(@ EJ(QE!(4QAC@R(EQE%QI@RPEQE%)(I@J[?G^qWfOrkl9zK^]F?efOp\ B+'qk4 (_ƍϴ>|/F_ƀE3t/I__L/IѺ__Pi}h'@s7I~}hoOƏϴ-ϴ&&i?5Z &&i?5Mϴ-l'FOƀ CK_?}/HivO>K4'whѲƏ.ƀӼO.ƀӼ<m!yWM@ 7'q>}/i)MGq>}/))EGq>}/)*O"}_=@ >s>}/{oƀ#~s>}/}}_*_\ϻK4}}_*_ϻK4}x7@RTe }/}x7@RTd }/KCIS}x7GK4 %O;'K4 %O+b }/?خh?AIV>u<Gnh%X ?a_ 撬}xƏ]}/sIV~w<G}?V4g>xƏi*u?K4XU??h_ٷK4f}/CE[ͼ?'mǗhf^yƏ/3E[̼?w_ tU.xh/yw_/U-fnI?yOC_-l2T}F-LDG$s#odc؃zzg?"2;(%ڣt-;,Op\skgcB ?:]谉xb'xyr҅$ȣQ1&-ΠaKxD|,pv"?x ?h֟ڨrIm<\I$*U&4%Ja/;J;"mXh2=~e>axҴL tI6mvoIo]cz|WY;s (.ӴNJ ]#ikѥ,Ng`',q'o=h;i+gs Է.?iA#eP'F\ZBPYH ! [sm"3 %YY >:mmX&`.#pZgkAj:W7djaFcvlNy`S 5!q>9e3d m3/UaHuV%:t9%wv@~x2+2jQG:<$}0}L$}8,G+gMqxNn4PhzmyCKR)l޺ʯpʟ+f<xNѥI5MPA߷ñ[^"I N &H$  ~簱ặ{{6$upk 1z\GA FR[tјHdXrR \6@bFC_Aokȍ=;/$®>[ +ɻɛ1~6q>Ŏ2 =ksG/ GQ{Pw4QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEs^%[-JF8dFA5^%ӇW|NFj/eDry:q҉Novzs7uae$FKeBOb@=!k@q_~vbjM\X]k?+A!FǦA\1j'\W:(%{5S?e}ūlU7ūlUhg=Gf?ߝ^?ߝ.1j'J<_o \SF}~!'}aūlU-_d]1SGMhF&W??07 zISB򞺿5?#?#1ǫtU'W?54? j~mF<>Ԁumx&'W?_L!yO%&W?OKMCTj>jzw/;o1MB-_d⩧&W?}ʟ~$ym(B_-_d1j'TO4?_Y/;o1G,o*1j'G%&W?z,s;o1G,s;o1^Y b6O*KMCT4??YZ~vbYZ~vbx1j'G%&W?A=KV?ߝ?yw%&W??/7 ZPS?fk}s;o1^^|_o 1j'L9ĝl/;o1R=hF-_d07 ZPSֿ`',-o7&1'I c:O*> _uvbǫtUx=_z,o7Fx=_j'ƹ r2 8Ƨ endstream endobj 75 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}귋o|3w}0{A`H^ng{ϧi`Qi?&-)-i V ^LZ+DXԩ!|e]suti7t%Frc.ddB`iܸ$^f@?# kZ: VE}FB(bY~MGDfCQ/okp>ZPx84&h6FYCs V,4 aK鮄`GMCnrGq_&J[Ά\Ӻ'u玝+Gmw4W@я*t&tk^^Wk5ҵ갪$忔*zMia An-Zc+8@ :89 3ӌsWDl3`'N>q5k(twyblYͩyxE3߽h7-#.N Ԗ(R'B0( 3s\nh&ӿ?E IѴ+"?z$hr]<ɌA!J퇈m?g1%Tܖc9뎙'\#/tɤi# e9!;# nKZEf(bBqڭGS%m/.c(!XٱXIG9ǠsNHš4='wG\\q[[NOd Y;cGr6#4nQ5]&Esך_+6mN9K%@MӱM^,mQgkoqƜvj֖Pcnq5GOY}3N#?].1Ak8^Zm}%i:vq>b|8ۜMuD1Ttp:SpVjm3O/&4-'NŠ6;vb,8 R+Hd!48 Ϝ_MGk,>CqMD.;`rF5-iGa-iF[/-;N(I\ZgV5Eltei?&fwcMM5rHI+}'K`3i UNH­E68fa?(ӿ?Ntno0}-%5`w9i(Zv3>q5i2 'Gӳ^ "-a18*z;u)2NHµ@U[ǥE4m?ӿ?F };# EY7t,ryѴ*i USE[:(ӿ?.4+y2Ea_H ̸},4m/JLcGӿ?𭈑HQS]BIZH SŖ$Z3N[Hi`+30};# Akw+a4߰K,Ų`wGOXNHµV1JmzRHXi;i,?$I ;# ԉjЁHz]3JOi TJӿ?[5z]6"4$RAΑ$ZNAڝ%Yzk]06I?&i:GrSWAr(Α,VVӿ?X՘mȇOi M@B4m;c GS 1J9y%Gӿ?͎?$]jg`?4*X%AwGJmš,*?Q,PhBt|82(=+X U{_Zt-*aNX£ԥJX/8|OFfD?wt!ec 0?#_oz縸%ԑ`*FMNWjqt^[?>v3:YN@9;{ez0ޞ,"<'q -۵Qլ\]GN)>B=.hc B.-Q|;j}G3@d աBtm;c Hm]yF3? *a/ SŠR䕶+gy #CV8\=:Sߜ%/WCG/ gh ZvQˠYBa$FWp=qAhӿ? IkqnD$P#W9G5swQ*CFO 渽_7>dLMnxN2pܜb.u ?鄿uĶFIIs֓^P U,T{OB~KtH9,;I#,2p"|vvZ;'HkDh_6UOXê=(@?+ABf? }iDڇ?$ 6gM FYo﬙~h쁐I8U mG[M:kķ󘁟M#/ש_&=VBԪ|?_\j7#(]`B<3|V[%mh%1 R7~nMly㴞m?-4N n̄P iVS4sך$mksyyqXmO[ůjgr!w %}s(x=Դ+gZݢEP630pگ }i;1ݙm)t0>'<=3ڤ–o׷~|SaEPNh}v^h^m T.u[m&iQ 1$h6+F.lm\(}0<{S{@k;I_pzZûʃzmdû(F[җ?FڰkNaAv0+>O_p.J_v>v-uS3y]ej #Mo }i|_pR咳F—cQ^^^ƙWlj65u?u?yƣcQ^^`ljO-/y@k;Gy@k;GЭNU|_p<_p*1VDsM.jy@k;He5 2r\&K0k;H^vdd4{@{;MM=0mEa&", |?}}AjE{=,4u?u?AfN\Kͼ5/{@{;EY5&b@nrv7]V9Ro(M=?npWAfN{?6rz.ݽT {;R0[;Em?6]B./ }Qq}E]676F?Џӿo?h5,?ӿ;~m㴿i5,ͷ7Gw3tϴp.̖(f3M(MFjNO^;,Rגo^gqm##Hi Tlfzy/m?ctPs0qkZܖ , '[ʨ?y{޹??5hekWyE`elkoLB~HRMxp=Gzm-ɷFr,$u=tv}" NJ쐷Ub9pfeggɶhfzdt@n]+Ħ{ww{h"d4d?;{kBE+9+ AVuxRS 2Fq+gWF͖ N#@`r!Hs$Lo}*H5{.U3XZybmﶵ!7 zZq"D]2N?6'G*~"930ua4o5#&p9#T,;ig$leA1-tY1:#+Oʮ{v$X|$$*L\E $kv`־Dr#"f,0zh)E_3{;Oc14B  Do+91EۏRYcWUAV]ֽ4zًKxhLy b_zǭXk{XyZVEvX$̚.sn"@ѬnB_IM\.\_ZWڥL;yg9JOb$"bi G+-.ܣ4hĒqH^e}a*(K[`x TekIb> ҇hXՇM{y%4T8`Mg6 vλR>.ǝ4RΛ6׾֟*inM3gi# БY7XvpfeggɶhfzdtⴤR;*3 { ?:9t f'"Jn-M0Їs5rİowQnq-Fm<`zyR klI`e]22}:qMoaj٬ =r1WkK6˵3Dd [< [~]U:>h]]we>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr!I1ŭ_4(>#9%ђW^?Cao/_%KA#oP=uWLn7sW)I`q[Kq,A3+qtcZ1i!~'k\~lXzm7V~G]-7Wew@yUOұifc^T7UK3,j'$/cLtU" Cn\3F;jʑw9ڹq&MrpR(F s&H<|&a$Ѐ"E.{{A ˴aͫC>LUyIoq2Rv҉att 3(MKs$8Jr~7 WN?hg2@66$ Ym/yO}m7U{l$Li]5xK+>v2C΋FN֐ & ̿UyJ9½*Yl`0EҴY#AI?lY>mfLuiqM;f*3ҡ{]j) ʝm2;Qp=k[#;$>jô/Qj: A5y '9cs{\b?0qZch|R2zFayZTNm)Cuy[¶427u3VTg*N&8x ME~_͇~NO F`^_i?֍a6dm ;x}GZ[iRȺ,X}G xq]1Wvsj1ol.wFrv+) EJ6 I72V6YjYvsuN3Z,ZhYe[*uߧN(yR؏wG*,b$褂R^4R2ᵅC[Zx< u|zz<H̀q®b96<66vX2pΠ3iKLUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*E jͤ+?o_2J-SCV?odkbz|%'UŪ,]iB٧Dx.39w\%'נ47`G%x0K}$$ѴlU k;IH2C+G'~'~m7wS^C{̏wmgWppZ~D54}5Oh✍=}-J 5/ơ5.\VIɮG~$kk*s]6A4}?%X_HOX_2GiH9~7McoO&#[xc(PI=w1r{ޥ#ߒ4doO&3 P;R׃1t5}Kc{?S~IF$h_h?)j so$/ԩ=F)eoO&M'@m;$ɀЪP0`IW$i>7MrycH7'}^ٯe8?S~Ig$h6ji=9|0s]?ٟ~;ߒ4Yb fX8tz_69*~?S~Iw{g-?QXseLHEыG w$h~ KLO=ўB T g~gUӗT쫼1|U"OO&ɓ~~…졎p%T:Y >;a+ɰ}9jɓ~ɓ~ zƔ58kj^o_7|T_n~dW(?I|P+?t'FO€4(ğ& Ѣ < Ѣ O2€466€46:~_ :+3θW)<€5(:~_ϸW(R? <€5h\+hW(ZE7G. ֢>s? |Qo€5謏+}~_ z+W?j|PuO Zץod,ݿ!|ZO1}y,dKb^]I`a醼?I( 44RRJ))M% JSI@%)(4PIA J(()( J(QEQ@%Pi(IEJ(QE(4Q@hCECEJ(QE(4QA %Ph(@ E (4QE%QI@RPEQE%QI@J(4RPF7od!?o yג*Ľ8O 8zz⣌½C] AEJ( ()(J( PhE%)(I@J) -%)(4RZJ) -% JSI@%)PIJi(@%)(4PIERQEQ@%PIERQEQ@%PIEJ(QE(4Q@ %P(E*7Id5?e^K$Co A^k&~FIV'Q4nojwIåM$x 9'Zr|Bmu4y/tZ(duWj.$9ܼ8I&_^>_Mh??/&sb8,qd=~2m&h丸h^3J6GȡKvUtMsmGE@ #"k3R񍗃/N˒gK-H?_MPcqCY$IRQBN^[2{dE;` FFG 4]5t7"4}GEw5{Tk۹-#2 L \E?0@98隖o[%2[x#pv  $ţHCHϟ'Ӗ11/%i@(63!By#3nĻh?/&G4iZFӲٛ@ #"hs@5EAvf7Hִ=Κ*رDmdp+s8X=88\Vutf5HW&pп &?8?§[O?K%X`)W46'dӭJ+rHm #<&)a"5a22*E-KlJ\_>}h-Fva9ַ>X?Q\dikq4oYsAկJVܫZİ2T\ ==O?»Mq5֤n-k^4a9&,~49+s)%زF8U>Oރ+XǬOu;]Os[*SM ZC PhE%)(4RZJ) -% JSI@%)PIJi(@ן&ѐמ|Bŏy%z%"Id51c^cFIV%vN"vO^kȣ#H3d&z:!PHiM% JSI@%)PIJi(@%)(4PIA J T3Rh?y§пmǤJk}&RDpPH ,*OL~=7TЯ􋗸/fy¼n9C1C MM[hdySheP;$^c??'n}Aj*Ns0x#HY|v?X8mtMRkgRn\:!1]Pa?{3"Z/ej#B F$)i3]xY{d0@2v6(<683qy@;Gy@;Gz_HZ 1_i%VܻB^92_ A45]DpQF#un|&A`!Pqӓ>vϽEPeY1i%ݼ} LdR1leJ!pA5gڤ3^Mw"3;s"pJ"^"МR7vdko a bEǘmKIs~Rr6rgxuwifcxxV(C)# W 0Fx=ksͽMo}Ah{V{Y/ qxvAtF1l2P!јeUT#;Zo?}Ajܛ>J Vy@;Ny@;O=(A^"qjGZ$vđȠ<|ۿP<ۿPMū1(?_'O?[m?m?b}/a1s??/ \ ](v珅.__'IJIOO62M 71䓖<Ǚw@{;N,o5$3AVa-ߵ\)ӋLV5i2]_]nJ&I㮻FPG:ܧCE(4QA %Ph(E (4QE%QI@RPEQE%P_7l+.+zM!<!/2J/q`FIk I10f"QE(E (4QE%QI@RPEQE%)(J( TSʖO+BIIg=%Vo'3yU&EigRYdw֏.~c?|VoSA? <S@yw..~cP]C˻u=w?P1?]OEA? <S@yw..~cP]C˻u=w?P1?]OEA? <S@yw..~cP]C˻u=^6n)dEh؊AQ̟CmZB1 ?(.q~m9꡹2 J&I㮻F\%W]ZOq?N:’EQ@%PIERQEQ@%Pi(IEJ(QE(4Q@n?+zM!<!/2J9-zM!<!/2J=N8!O^\kJ])B*J J((4Q@ %Pi(IEJ(4QE( Q@hCQO*Z@W_iYI|Or+Vŭ?O'p&GG?|VoX~(ie%{;}A&pF#ieR\d+rޠԴ]+XXT,2Lb!=qT::ޥtil:L+r8*#T x_-:OҼ>X.,{УfV\Sgo^~^Aalf[<`rY.UX%kd/_*lt}ou-zz.c((0/FɪGui -äfYq)$ut5^4m8}>j??7ſ3 4zM0vQn[~SC~_9JA>a2[+=E 2bL󑟘^2mucÚ)Y\ٵΡ6I7#M&#nKkY-n⸷mx@ЃGXQEgnŢU@Bsև{0I+Ե{lTW$h$<093K~K (緎&O%H ^@~#M'HYWM쬄G3 ?Je١me1p8$^&5 : s*JL~Y(do'ux\ԡ nJ9aۥoZhN pivVG/ "۸8l3`X GMIl$}s@. i 5mzYd;0BFƯ\ޥgB VbO ؞#ePpcw JoF3mϘ7W܀ r9Dv hGb;nl{hmզ\- gwm¹XܪB(Jc}zðLzuش5 ̐]#8l!w 4]F]FK\1ۢ*14 4];uhOS1 ^8b@9B0zlj@tSok,׺VGZ1Km""06\rr+kJ5ӣⲳXfi]Ǟ̬Y]nXnlnQZwVwb7ZHŞ !Vmĕ#%Xkn-Ւ*Z u \$У|A{^#pBc>!KozL<|Eѿխr~"}`Y}ŤcdrHaA PhE%)(I@!PIJi(4RRJ))M%)M!ho yo אђW!ho y אђUz_# `+ Ph() -% CKI@%)PIJi(4RRJ))M% JSI@%*ME?ܠ//Ҷl-E 8_ǤJز?U[GqUdt3͟uo=A?|VoSԔC5ݵ{-;R (G.˷K˛'HYNw$p w>Lf) #۠8TڊgSp[J=up&襀diι `ȠI5 ߷G}cuظ?֦qٷDD/GpK!&*xKSVkouŨB_Kfs[jc ṧ[gv*$GV򤎪xGB  ZJ<*LB,Habrw11w)g`AER(((((((!넟uR%+gB1 ?(Lpm-<ģ":oxIXt-:o1S} EE(4QA %Ph(E (4QE%QHhC@RP)MId57e^CFI]ƩzM!?sXאђU{`+?DWriH"%PjJ(4QHhC@R( ()(J( ()(J*)KP q~'9~~ŵO'C/ҭY7[aP4aZCu͟uo=A?|VoSe"B$eHbAoIfbrXޣ e~6}]񩢖9D Ic#׵G oBgHnӓO}uݻR>f1MRg9}SOkl<-"xr#T2mxI66^Ǵ1'v2@'ƀ4~ E>dtϹgWvڧ5[5kmbO2IFD\8*JX&}DjR_m q8zEPEPEPEPEPEPEPEPB1 ?(*CoOZB1 ?(&CmOWy%VOu7Zu(ZxѾԽƶ:X:C J RPhEQ@%PIERQEQ@ %PIEJ(QEg^k~!??d7%ѐמ@y%ZؗȌ"??Ew J(()( J((4Q@ %Pi(IEJ(QE(4Q@kZ9V,_aO[j<>': 1 8zcu5ϊ*4Μ-՟,oV^CZ2F@Jص@I`0JtH;{Vy  ?Qg^<՘cM]/'?-zާ!*콻T;2?ݙ尷C!WWocwijhq D9IOݒ9-%yD@M 2(׵(uK.zmw/bHX;i{ciZ=Vc|3#*x< xsC.LѴ) 4֩8%@8{ k;ˍepnAydrU؛< 7m#KIv|:ZKw=:b*w3}]T+QE ( ( ( ( ( ( ( ?IGYg'mOZB1 ?("~m)mIǖ]58i*s_u)Yؽ۴Q. ;: `\CgU>A&w;WԼ9-O1v+ld85^U"vи86tvsͤSr(e3"֝\Vn J(4RPA PhE%)(4RZJ) -% CKI@%) E^kϾ ^Bqפ2?1$[=?DWnkDT8RD(4RT)(I@!PIJi(4RSI@%)PIJi(4RRJ+.+z929֙S6WOpJ0qlldFj89?֟ii›≐֡v ?V37-[;z>l跩#Bڤ1Q#yv*T{?L՛{c/<SEeiѿ9̑ Gz7W2Bs5#e-zT~K <3!wI-# aRO5bĚMI5`lNg0Fer3o麖?MlS* .CcǀzncjX7m o5UѲFeR7 X1&fvwpglߴ_n>a" ;h!mJѱ]Q Gg:0<9 )e$}\|+-?T[X)9-U&Xd| .'?N=(nt泚ĖШy&DR2 -8 #֪]xHyͽ?hIbEUNk>V'vSgdze[;ʨ% ܰ'U#^fQOleT.̡pNw (e 2KLJ~+G-((((((bQ7uЧ!넟uuϵ=4"EL*;9>&}[i` V/2X-GcxΧLg׽zʄ+JN˯~*UxZwp_ZLdAZ5(4QE! %Ph(@ EJ(QE!(4QAC@R( u8_ y XטђW\N/FC^} C??dkb^"*DD8ښRE %Ph(E (4QE!) QHhJ( ()(sE`DH#$gʭ^^Io q.J> 1N p$}jhȼ?1|y8Pu" ok#Gn=kV|lO%j6X|eLiǾ1R[NSiws:3͟uo=A?|VoS3Z[\3)^6?:fͫm1#($nǠ x8rnR W/'YeJԢFἒ;B6 (ufZ h&٦3FΣ*#%EWk8{Y]0v;u@Q@Q@Q@Q@Q@Q@Q@Q@\$У{XK]>П\$УwYnB$gQ'6{E$-g@#[M8 ^@><8[6H.Jp8MԌRmpSZe-m,lW NGzŭQeRRJE%)(4PIA J(()( J(()(IEFBפ21$AR/FC^C6??dkb""+D48RQRPRQEQ@%PIEJ(( %Pi(IEJ(QX?MS`gKRʸ`#7qeG4_'NؗZlW<8 unj9u ?U/jR n12?Nc w` O^lIEi{nmS\O6տ[g][EO\afmlH'Uwm38ɫ){VX* a;cPͣoҢ{:u{4Ȫ-D`|9t:ejZ::#)R@%x5QGK[ ֝m{;M:bZgh,HM8PBnN3ZTQC((((((((!넟u.Bc!넟uW\[Sִ~4e[gjˏ]>bN v`yk 5g,-Sn'3MrzBK>$ۢ G<3;z&ֻ6ˊBb71pPߞ[Җ][u)dkX;yA|n皸 9FO(4T$ɑ|\)Gqϯ|ZR$->@gYZKmmV2ΘMߦ#)2 5wO'}?QC,1V& ZG*a׶9Ӡ۵ /,HF=OK^ER(((((((!넟uI\ko zbQ!˯Ч)|H RRvrb>]fds$s޹gGOoW_}Ť"}r꯿q` Tԅ'z`UW}0+#<'j=tX[Iѝ̃kCI rOOZVh\]˟̒iT6bIEE(4QA %Ph(@ EJ(QE) QHh&ѐן|Fݗy%z &ѐן|Fݗy%Z؞""닌"CJA(RPQA %Ph(@ EJ(QE!) QHhJ( (T poOi $ypJ27#֧R| jL)ҩv6տ[a`@iʕvR= 6EP}m2T}m2T=/G/@P}m2T}m2T=/G/@P}m2T}m2T=/G/@P}m2T}m2T=/G/@P}m2T}m2T=/G/@P}m2T}m2T\$УW{[SE1HdE}Jw$ n?oOZR>y#x `#6V[u:-j`-Á=h$hvcx-X20" JSI@%)E(@%PIA J RQEQ@%PIERQET E^k#n-zM!?!/2J=OD h?EvU?'!IA)( J(()( J((4Q@ %Pi(Y. qr$hEr ==Ь-Em?1kڤ rqΦgmLČ=)! X(>$.p@RZd˹T|9j顧 It 3hN0(.$!$""3cA&VeGKk *$ݙ$,y3nYvf+G̬}CZ]LNpkqn*cCD^}r7Go?o"໙mHƾ]J7H!Q |=F$,QKrߏE}LK?@f=GIcY#et`YNAW 5KB{LHJQ\Cf پLBdK"z24k"D|xL*kB :oK!U?ʳ5Jk[ Ck[ CFYv=ΧeSo;\:a^%`B2x%muc9lۻ11O pAַ (ַ *f%T.b4ƅw(/?1{+tk' SլHH\))pX:EPEP\$٬׽=uX{o z UsGobDGG[mg'9Gki5)Wy?,~5Mp&x0 f8f hGk#xvLq 7zKZćG?i£ CcI⧥EVAEPXڣm֬O;OE[5GP C,9$DgAjrQٝXBȧVEjGPx3-Ź7U$`YC鍯AK7G Òc1@]K%#`VxN0Eρ'd?O/'?nxw V@:gzE ޥN}0p" ;kxvEp% )^F&OZu0wgpjhb] Bp=/<Vj:69[Ydb2aa Lм(-ܗ =,ɵDCPy_o<Vjy?)u~rZ :m-5(un#Z#0FY~!Tr.QM&&_3%`2lM udh(4Q@CEP(E(4QA %Ph(@ EJ(4?CפUPFI]ƞqE^qW@Gi^K$[woq+>94‰E(@ ECEJ(QE(4QAC@R(EVu\\mi$pѪrĀ>`F۸tjݍ+]㕣`;AǷTOR*EeFLzC86DfO3r8.q< >s< ?tE'"ȣ.+]Mk+8R.[OR-o>|=m~GޮA {}O>>āP|!hF>1U{X)}T[{ On玧w?]y@ q,<?43=q?k'K[%.;e^F`Asʃ+V@`zp>e?=y,n =HRgKG.𥲌 uFitE'Qv)S}YsQ˟.:_j?sא-o>|OE?K.}`Λ\tQ˟.{OQ(r>笛=KcYj_sה/o>|OE?G]== Os#@绕p7HS^l<%j}I4+i!§*hf"Q WėzD3ʋ<ƮA靠k4'Hp}qҲt< /v|R[y&c81#YF[0޲lvtsU;P%xJA*0?*ǧqJ}""30 Źl9qW 1dϒ+`5I8FIZ/V?Abr&d8%E(@%)( J(()(IE^,.~ϟ?o/\lm }F<K(vAI`pGCtVeRבwWv6~[Ȓ S @Ǡߚrf!.cw 09x]<;j_s+rm6ml+#BI]FpTme 42;c2Fd\!m %r czsME/mO5BJ֖ /nbN4[u!fH~2-\A%FP@=jZ2}†q`a y1x=_iig=bs}^ki_y]kD6vӱBRT9s]\X]ڥ )IsX.spw=6(dM]: ԬծDaЗ s襆nY5;QTe4F @01Ϯ6P3LcH9NzTn>Y"'9#-v J( ()(J( PhE%)(I@J}^nӤUO +E_%wG1פURCz/sIެ䜧RJ)(J(4RPA PhE%)(4RZJ) )PIJi(4RRJ))M% JSI@%)E()( J(()(IEJ(QE(4Q@ %Pi(IE(4QA %Ph(@ EH?Cϊ_3Zגo]# /qf%ޭlOSIޮb+ WDWOJA QRPJ(4QE!( Ph(@ EJ(QE) QHhC@RPEQE%QI@RPEQE%QI@RPA PhE%)(I@!PIJi(4RRJ))M% JSI@%)PIA J RPh()(,i!%/גo]4w_dctFC\ĭDK>z/lKbS+1 ??Mt4 JSIRPRRJ))M%(@%)( J(()( J(QE(4Q@ %Pi(IEJ(4QE! ! %Ph(@ EJ(QE!) QHhJ(E ()(J( (E%)(I@J(4RP9d5u{Aȳ6J:6dCoH"P8K$[=#B_@Qs@ҐD(J( (E%)(I@J(4RPA CKI@!ҚJ))M% CJi(4RRJ))M% JSI@%)(4PIA J(()( J(QE( %Pi(IEJ(QE( Q@h@h@ EJ(F_*>)k^KvZ?1פURCz=M8no *4U֬`zIiH"*JIEJ(QE!( Ph(@ EJ(QE(4QHhC@RPE (4QE%QI@RPEQE%QI@J(4RPA PhE% CKI@!PHii(4RRJ))M% JSI@%)(4PIA J((Ώ# /qf%޻-F_*~)k^KZ؞S +~?'`k RRJPIJi(4RPhE()( J(()(IERQEQ@ %Pi(IEJ(4QE!( Ph(@ EJ(QE) QA %R(E ()(J( ()(I@J(4RPF_*~)k^KvZ71פURCz=N?'`k~#|&?_RQQϴTd/RQ%/KѾ__Q}h/Kn}i7K>~k4)i?57K>~k4 32ϴ}hnfi?5Oϴ:MI_bo_'@ A'Io_m}h?}/Hiv>K4'y?) .OƓd6O>}/>}/Rw?I>}/Rw?G?@ 4*}_ɸwh&}_n?m%?ɸwh.?e%?ȸwh.?e%I\ϻK4gwh'ݿ>s>}/t/ݿO\ϻK4%KkoƏ\ϻK4%K[oƏh*J?O\h*J?>s<_i*o]hoƀ!u<_oƀ!u<_W_?b_)*nh ?Wa_7K4\U]}/ i*.hϻ_ ƒg}/w<@%Yλ_:xƀ+Jy<Gu?U4k6xƏhٷ_ͼ?T4U/y<hٗ_.x4Ny<4ex3G?Cߊ_2גo]k5wZMA8+#%y/kb^q@5,#&m"[R#D21DlA==3OSDՋGs,(jдl)=pG55/mi1EO#uuNc;ț6. E6ofnu r[$. ch%I&{DGӒKiI%P)W1*UgG }Q+m: @9)+FFyv4N&>,h+m+D̀DfaTOU<_g {iñ'0@(r;A U<Vڈ]]1@]|}2Rv֍úvw0]KrCR8V^tnr H"Xuqo 88Yӭlu RfR>Pw8 ~ƣs{L6h9Wiv̬=?_RS>@A2Y f9PIO-Ui[çLcWh\7Xg!ҼC&zC,GɒG2r{WVL 1,,f>|-.kM,?7 o*{0׍[)$^xc[Iیe ny ;UU$P쮯 imd0RH|ߜ;qPM.{ ^w`iG_,1ti u%M>餆E( p%+d$ml8EkzʶA r@ \*尻8Ҽ<CgX(xַ4}"Pu.縊(qjaU\ jHEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP =i^pךPCz=i^pכ|OCz=NBh5 z>pUvG#؊ 0}#CwdmrͰ px9q)ƋpaW?`u)ƏH ?FSھsA{7G/}|?"?3Sk?)ƍ;}n,?x$Zu -s:?ѧ`_0_ۏ _0H ?G$z Nٷ`tfb׈GkQ?#?5Sv Oo͸6nC=sZ? AGhӰj{m/?ٷ`u)ƏH j?FSn?1|͸\֣O4GkQ4qA7Gm/?x$z =sZ?ѧ`ۏ _0?n?1|?#?5S)ƍ;g\bqA7^! AGh\֣O4i5=:n _0H ?G$zu N``u_)ƏH ?FS>qA{7Gn?/}|#?3S)ƍ;}n^׉GgQ?#?3Sv Ok ?b\ΣO4GgQ4,n?8icnG=s:? AGhӰj{u/?ٷ`u)ƏH j?FSn?1|͸\֣O4GkQ4qA7Gm/?x$z =sZ?ѧ` _0??1|?#?5S)ƍ;g\bqA7^! AGh\֣O4i5=:n _0H j?G$z N`tN`u?)ƏH ?FS ?x$zu =s:?ѧ`^; 0OH G$Zu N_d?auk?)ƏH FS~sAk7Gn-}|ſ"3Sk?)ƍ;p1}|?"?3S/$zu Nٷ`tfb׈GkQ?#?5Sv Oo͸6nC=sZ? AGhӰj{m/?ٷ`u)ƏH j?FSn?1|͸\֣O4GkQ4t1{7L6w#bnW=s:? AGhӰj{O.-}|%?x$Zu -s:?ѧ`^; 0OH G$Zu Ncw?`uk?)ƏH FS>qA{7Gخ?/}|?#?3S)ƍ;n7`u)ƏH ?FS>qA{7Gn?/}|#?3S)ƍ;n\^׉GgQ?#?3Sv Om?`\ΣO4GgQ4 0>qA{7^% AGh\ΣO4i5= иEF|݀(%I_0zMm bعq`K{ \Zޭu> endobj 77 0 obj <> stream xYn7}nQ[b1^4F""er=3v-,F(Z3pf5xXN/Gxbr qp>h2l8ǯNGheZeaNZ/Ģ<j1HG=-j&W#7;TMW7ώz3*N4 Y"2ce  -SbSڬiWy?e/s}+VOyC68۬u<:m JZa ^N6ʒEo~J\6l9_} i?3I\cr9 +LVVܥLT:{1FϬ;!HzHO0 \.˯ '}yް&*c[HM4Zq݉tDr9y8( mQ ^h3$CU#R'cv2Y1 ɪΑ6t^p|{Yw?*9rXcx kZN6= \[RKIR7ܝX#cp(m?'NcZo)[.3#zh펅tm 4LOJ۷ݹau½N4 J.bmdk9B X{jO[(<~\MDH3ZpvDDh-.`5Iq>v}9VrE1SU]gӖHӾ:wve6KmoҺ${ 4 kuWSTMJ$};J ;yJDdvי[~k[e_r[6n~hZ~[)fbyRKJilALk)rlMZ5 .yH[eH/ LoOs`P^Č'/JR.*Tu,IZؖ48PA]6bE/yd.'[ bɩRId fz_rަleM{NDs9J!PmxΉgE%7qrJ:-#o%ͫ~}u1R-{W#CDAKV^z(Eu|]%d\s wMI-{W]Qtėuc.i3n4L6NgCJw>ٝFb`)%þŷ!=7t4Qw_R(Mm9[CI({V䛜/h>TVv3mx'j˄ nM]4|E4*6B FMX;zDj4V7z'Q \S(/*YF> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|=MKMZmO>86C*A$rHIhJq^5σO[襥O9V03{ MB9J+94:RGCdnSUOwqh˗6"1hJ2(7M5f/ L945M`h>kipEf,d+ܜc2BqAm5$ p>n JIkoj_sOmOE7?_MfxVKN[Îa}^pa ^:Gr,&t .XN'Z_MM>G>?/&11ݼ_m40G>c @'q6[q ȟltWRrG?LU6oaE7gq¾?/iPM &p>|J$9Br`u1S|67"+4 ?0vm<9VfP@:G j>Ј #"kOOt^7Mc V%IK~(m+i0^$ƩcK;4;;t24YW=Wd+"(SFfGqWugLǙ7G$*|Eny/˝ nú @E-?7t=jZzeȊ;{s  RnR94D^ȶH̡3}HSn i]u5:43ID¨eqJnd'z*ۡi#!k Ew#s >8XޖV7qjZj7r[.3] %ޟwݪ!- 0\J_KDСoZ3|>F[vҙ2&Oj]v免v<ʂ\1aAe#1OHQy ,*s3j#\[N^Ck]ItEokޥ=ԑtQD_:+CtsO}x1]JT 4'B:#H彬cgk؇z+Gд|!k7PдȁM$>&5i+?hCu s3Ae؈dpwʎ*(cdέuyQp8^ i馛sm'tEnţhC3֛iJ8S,e}]m8mBO6L@F+͜R[h&\O3Kmh#"jQP)>Sc9sDѓ84A[&停RJ1%)w+âht-#!jGtD ǰs3 :GE;EAZ@|?Mn0Ozc9s҄big5m('A?&_6H+h mSiI'5bs4h:_MHrx{B'H@GEֈP)٣v3e740 #"jдv@#5"Z)ZGCֿTv"G*ϹɧhzG jHt&ZINzQʻ3VDЛtq{@?/&sKv3F<5214ׇGE֌rdSQʻ39tM @?/&i[[5 Y\6?/&MB'@:GE֊[ s2s@#@GE]Kú FWBҔQ 8^?U-ar:c+(߆ _M8xgebk PKrfXc>04׈?=fbӹ|36ߟ{AHY\Dp<$ƪ!..eY@KB;.'#jatG=p31Q$F,i;+;UPCc*z0iHТ+Y ڲ [#1V%ۈm].=cq,|nօ>=A4|h^O38y2Yi/-ز*7G\j_j\X`p Џ41[iCk,~t;m4guin6~,ڞ?nhzzV4R4?h6ыAѩ3MuF)&ߕhFb r#X۶ʂ\uugh/H\^pFvk |Q==O?¢UړFBTԴM R!}Tw[:p"*30|lGnU?!:=xֳ:VtȠ1pC1(\/miNcr&v'q javj? 㴒pʷDKKvvʷf R1f3p1+xj[egl-Vh ecã)32}kC}}Ai|G7v_sn ca K#y"I)r:*q1ƒg\x;óꖺҬỷ7l6HXeܞ[w\/QM}}Aj {UCb9˾B^6,X;iڟFfjqF.M(9- el*08zo?^@;E=ı<̪r; `14+PEɿESre\8o}}AiG}}AiH$fBKտVvpaT~V@{ӄZ/?=Ò]fyWyW{HIv4/@;G@;GpaqI""HN"+0;O ~?}}Ah<*SGv{H$uDVvn@{;GpasQZ}Z}@k;F_P9i O֣kTo }}Ah}@k;G->iv#ԛԻo }}Ah}@k;G->iTۈ_ы_pڸْ'qsM,i6l=0?4~}}Ah05!?m~}}AhF\yT7vzo?>9+.ESMR-A}}AhpbH^ }@{;Fp\<4=}}AhqK梹n!)G w㴞U?'(?b B=^ʼn?\L*U/?;={@W_lwҰ>c ؿjQSW`ݿD-oh{W?_Qbk_vvM@KҼ{ȿ/mB<  0}#Cb y׿uo;Q*t͡Zs7`B_D!a?t>uo;K^bcJ/[M1?|vv:ݿQ[1 N2N1)IcUrK1s|aa`Ѳ׵tm糹i1J7/\u#}FZZ*6+s[o' '!0 7Z(cp9ʁe?mL*k.k}:mp쌘>dF~2*B_ ׌gWPh߸eFYgˆFp8+H8?h-5wDq:Dc0,>`AMEu ,Z7b3RQs̸zg,k{{Y>$H6ZW2nS29p]\-gia}cU.6@⪟[6eoq <+vA[w"MN??ΚkBI河b0WWop;cx,Goso&8-@1Ӓ_2=(GWo%ռsƓw$M~.zBU-oGR ;7&>M?KKb@4גOI'gh$Mj)!*E;UЮ_rxM7hR"@r(; pq$'+o&wfݸc'PkOo }KN<* 6t?2ُ\H|w5ʯw #f:C$2]C/Uøk@W%6=#^PiK0vڔI# 䞫q\WH^gT%b@72zr@}1_W e?t-)I,u$UM۲ck[Vͥ&i/,,<7B?.+o4}..T;o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]\\ u3ť_9?l@iO%ZwWFI.ٯ[[cP$a[Ln7sVKo'۾YY 82gX%8ӽ5wքa)no7>_%: gzM2UhbEsgk!@8FUx9S~y.|=a4ZGY8*}D7UK3,j'$/xJdp fT|w0(M$A1/$l~OSgvo &w5^~S]/;I'3[YԖn7ƈLa_ҤkDR檨&PnХsVOfL,eRPǜtǯQlmC/Tz>LUr:WI̘ gHYIȢQM:%DffocP\h敤;L)#$fH!/ 4Ѫ;Es뵁q4\G϶/UnI&eek51=Hz:$=sѢvEș]rԷv$c2uf ?ԊtiͦnŃ>vzz_69( -<Ue}V$#$5 ,i  `y~m`~5ڞ}uDGUY[B0nGSj^Ț׍4+۾M:龝YMцURd6C*@o\C"*<,Whl2qUi5τʲ|۝Y+kVӠ8~1 ]k 8N)1x p$ݪUqrk`"[mQeQ H<FTQ]VVַKiy]wz[N륏v϶e⩏igǢ1fXA1.j7e *v @C򠹙dw.KsiҴV2H"^N++R#ZLUmO^>: I`)Y cs\{__8 u },/ GbqLo4=_pyY>}ea, y D#.]VBv@N+ OA%*2 `u?{_٫^Nt=k[#;$>jô/Pj׬zY8kA 'x=c9cs{\b?0qZch|R2zFayZTNm)Cuy[¶427u3VTg*N&8x ME~_͇~NO F`^_i?֍a6dm ;x}GZ[iRȺ,X}G xq]1Wvsj1ol.wFrv+) EJ6 I72V6YjYvsuN3Z,ZhYe[*uߧN(yR؏wG*,b$褂R^4R2ᵅC[Zx< u|zz<H̀q®b96<66vX2pΠ3iKLUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*E½ r3g>wJ- 8#^`Ѳ׵_;x/_ =VIInjj<ZPi&K*NAKo'觸pd,z(=L;[!&bVg&YJALQhjQaA_Pe$W]nZ$r;YH#5ί40kwFPؿ Cb xJ.pNFv待khbvE=S779&o&w\u6hjWd*N]c:qĎ?^DM2iy1ò7f*һ-Q<ާm㆛aA_G)NRI>c_n!)Se43Faiy2Կ4y2Կ4Kޗ3j< :Z֔-tG;JSGq~uɤ8`,r?"&OO&&OO&yee̷*hvw=C,k`*M+nExLEBmg<|ϧ/d[;JAR§,[{FHŷIm5->+o ԗh#V$#X ^x i$H yVGfcq(Kѷ x=+7Z,vp^^Bp"h1OWS nhz:]褖 n#=z p) hXVtb띤a]eD UIP>2"ƊUF-qn\|D>&bEuZRu鷖dJ0˔<uj֯ssW0hL)ǎ+7?1y)<zWn"#o^Fu\ӡf(#(((((((((((((((((((((((((((((((((((((Կ;g^w2 O5 _-{f!?ѐWhOjkE#լ[_'⻷ծ乸0@pvIIlEh@SSsI'Rkx4$~[ # %vƨxN=bgXb| H"F7ȭM_3"c)e 4ni?֮@sI2 v|ߏ|OmhJcϕۿfnn8JUxLD)Gni??4 YBq5nk4wD@ 8$չ|G[{DI,29۞gnR%:'_GAK/O xVc0{:DZU$#cs]7fr˒,I_UhʕװՍKۡRj OIײO:&wgv,6nw<^gt-Hagv3ZZYD\KDN坂w$ t1hmţ Z?im|Wc5<7<0ȱnUf9 {zv?SţGC|՚rQKl{(Qo[Gy^ڝ9q<AbGۣG?mly{Γߥc?b[t(@n-}?ǝ'JiĚg$Vs|/2 ̳4[djʹc$ JCbGۣG?mi_X`tRtm##2?eƧM..@!;)b8OL GC|> Z?h(_\<, uEbdtRF lkcΓߥc?bZ-"_GdHUMUJsuefuRŰn-}?ӴYNeMO lr)x浼?SţGC|ԎiKmmѕ z5''Jt1hmţ Z?kcΓߥt(ţGC|U%]:B"r@n-}?խc4 ,'Xyw Z?kcΓߥt(ţGC|G'Jt1hmţrosj/H}!'+MFA.ff2W<m 9sZ\G{fp\VqZZz]@5/ 5g=o,JyV݆Fd\?/#޽`y!kh2dne.f)1wzeGBp7^ kQ%;D͑kLO#)_<~(A@ mZ!;.s`{բ5#;*5s;*5s;*5謏s9*5s?9*}3V wATr :^:lfsNDJs*"dq"mCRbgs~$8îrU'uC#4#4 m_.gU_%NzWg>M/EK)!ʌBFebc68}]??>ŮnU,{TV/ص CATEb}\??>ǮnUmXd?7*!PMsp.ATEa}\??>ˮjUnX_f5*k@4m&MRLRXHY8J89G<$Zv 3 3 /Tg?5*9 -:톥I$2%2(E Br 9c8I}sP[K T֗M[-VblfDhl :8KHxM-71 C9Azu^FATy!U7q~)_Ee{i 4e4 r?v \h-Z S0-FXl8%' Z^FATNATx0edžƸ6I Ud6P}0Pp 'dV8 v9:  |s0u Cw^ -d[h٤q 2킸$dcicGi ~HM#`O2z\kI Cc~1g૙dЭIN#p;qU|nbgb-j~#_<~*ѐѐ.λAx TdXx~Zɠq4AA5 RRJ))M%(4Q@J(QE!E%)(4RRJ))M%Q@ %J(QE%)(I@%)PIAIEJ(4QA %RPA CKI@%)PIEJ(QA %RPA RZJ))M%R?ji?4G!oѐW|[Lrk|E!oѐW|\MrkE3'i"-IuRo_.[O-L+F[w4Tz:CEJ(4QE%)(4RRJ)(4PIEJ(4QA %R(4RPA CKI@%)EQ@CEJ(4QE%)(4RRJ))M%(4Q@J(QE!E%)(4RRJ)(4PIEJ(4QA %RPUnIUR?h #8mFA^'sF-3j1ƭlFA^)darkE3'i"IuRo_.kOL+F[w4TzMJSIY%)(IE(4QHhJ(4RPHii(4RRJ)(4PIEJ(4QAC@RPA CKI@%)EQ@CEJ(QE!)(I@!PIA J(QE! %R( RZJ))M% J J(K/jU'fߊ)m^2 O:`kWFA^'SC_fO=JD+o d]r֟![ ?WS/Eh:QIYJ) -% JSI@%Pi(IE(4QHhJ(4RPHii(4RPh(4Q@h@ EJ(E%)(4RRJ)(4PIEJ(4QAC@RPA CKI@%)EQ@CEJ(QE!)(I@!_3VU'tU!KѐWT`lO-FA^'WC__2v ?WQ/Ekiºez/sEM4QYJ(QE!E%)(4RRJ)(4PIEJ(QA %RPA RRJ))M%(4Q@J(QE!)(I@!PIJi( %Pi(QE)(I@J))M% J RQE( Ph(@ UIY?_Κ+m^2 ??t(z++{Lp֫2v  ?WM/Ekiºiez/sJpoRZJ))M%( %P(QE!)(I@J) -% J RQE( Ph(EPhPIJi(@%Pi(IEQAC@J(4RPHii(4RPh(4Q@h@ E (E%)(4RRJ)(4Pj?5Z?@^?FA^%_Cg[xŎ53Wd3 ?WK/Ekm`4a],2[Se8u7hFEPhPIJi(4RQE(4Q@h@ E (E% JSI@%)(IE(4QHhJ(4RPA CKI@%)EQ@CEJ(4QE%)(4RRJ)(4PIEJ(QE! %R( Ukҿ/Vj_/FA^%gF 3m/-FA^%kF 3Wd3 ?WK7Ek}m`4a],2[Se8u7i(4IEJ(4QAC@J(4RPHii(4RPh(4Q@h@ EJ(E%)(4RRJ)(IEJ(4QAC@RPA CKI@%)EQ@CEJ(QE%)(I@!PIA J(QE! %V+uf\_:h bn?d_a?:Zfn?d_b?:Z|O=NIIto_.湻?'O&M#%軚U6^SrE%dh JSI@%)(IE(4QAJ(4RPA JSI@%)E(4Q@ EJ(4QE%)(4RRJ))M%Q@ %J(QE%)(I@%)PIAIEJ(4QA %RPA CKI@%)PU+ubW4G!oѐW\Lrk|G!oѐW|\LrkE?+O'O&#%軚[ ?WK7Eh:f(5QHhJ(4RPHii(4RRJ)(4PIEJ(4QAC@RPA CKI@%)EQ@CEJ(QE!E%)(4RRJ)(4PIEJ(4QAC@RPA CKI@%)PIAIEJ( %R(4RPU+ubO! +t^#ͷz+ľ-Ŧ9t#ͷz+ľ-Ŧ9tQ?oL+F;w5١}lL+F;w4Tz:t4 J(QE! %Ph(EPhPIJi(@%Pi(E) QI@J) -% JSI@%)(IE(4QHhJ(4RPHii(4RPh(4Q@h@ E (4QE%)(4RRJ)(4PIEJ(5^ҿ/V*ҿ/M? ׭OZgGK^kn?d5cm9}4֋26_NL+zz/sX6_NL+zz/sEM۠IYJ))i(4RPh(4Q@h@ EJ(E%)(4RRJ)(IEJ(4QAC@RPA CKI@%)EQ@CEJ(QE%)(I@%)PIERQE( Ph(EPhPIJi(CJX5Zoi_??m^2O*?ek??m^2O5i_-j'fG+_ ߟF8?ދE3ioO4a]41_.MCi(5E) QI@J(4RPIJi(4RPhQE((@ E PhPIJi(@%Pi(IE(4QI@J(4RPIJi(4RPhQE((@ E (E% JSI@%)(4Q@@ EJ(! +ub! +tƿm^2O*?egmeѐ׉` 6W̟z]oO&O#Ek ~Z4a[軚*lSjV&IA J(QE( Ph(EPhPIJi(@%Pi(E) QI@J(4RPHii(4RPh(4Q@h@ E (E% JSI@%)(IEJ( %R(4RPA CKI@%)EQ@CJOPK! +t:m-FC^)m89lbM~ѐ׊|e'ӗFZRmk`4qZ軚ȱmk`4qZ1A_.M٢J(4RPA CKI@%)EQ@CEJ(4QE%)(4RRJ))M%Q@CEP(QE!)(I@!PIA J(QE! %R( RZJ) -% J RQE( Ph(EPhPU_:jҿ/M_m^2_69?lW0׭WGO-hd3ӬZ ?VPv_EFL+w4TzMIEJ(4QA %RPA RRJ))M%Q@ %J(QE!E%)(PIA J(QE! %Ph( PhPIJi( %Pi(QE) QI@J) -% JSI@%Pi(E(4ҿ/SGJ4E# zk~4a`Ѳ׵_m^2_69?l2"fÏIzP JQ]PplRZJ))M% J J(QE%Ph(A RZJ))M%( %P(QE)(I@J))M% J J(QE%Ph(EPhPIJi(4RQE(4Ph(@ EPhE% JSI@% A'4 ҿ/Mj0׭ xƏl?6ZCFo#mFZ?+(W+f'DO&軚}k`Dq[?1A_.MCE5 (4QE%)(4RRJ)(4PIEJ(4QAC@RPA CKI@%)E( %P(QE!)(I@!PIA J(QE! %R(A RZJ))M%( %P(QE!)(I@A'tҿ/M0׭ xƏl?6ZCFo#eFZ?/'O's#Ek IIn軚U6^Sb+#@ %P(QE!)(I@!PIJi( %P(QE)(J(4RPHii(4RPh(4Q@h@ E (E% JSI@%)( %P(QE!)(I@!PIA J(QE! %C't ҿ/M0׭ xƏ,?6ZCFoѐ׊|heW̟zE_'ܼ,J#?%ʍg GX_O-N+.\c@H?Th)O7Gۓ} o&6?EGl >ܟ{S4}?h  QA~"@>7GS} o&6?EGl oS} o&M;6?EGl oW} _&>/O  QA~"@{bϽKԟa$*>c@H?Thl_)>ֿ{r5'l }_&96?EGl c}_&C}_&  QA~"@!PkPkc@H?T}߈>?i>?jl _?{r4}_&}߈  QN׿/Gjl W{r4}_&}߈  Q>hA[a$*>c@H?ThO<ϭy}o_&}߈  Q>/I9A~"6?EFRM'{r5{6?EGl 7Msϭa$*4{r4y>/Wc@H?T}߈ 5h[}o_&>c@H?T}߈ 5i<Ka$*4;9<Ka$*4797^Mi}߈  Q}/_&ϥK֟l OI7> /Za$*>c@H?Th^?%i7I> /Za$*>c@H?ThV?%i7K> /Za$*>c@H?ThNeK̿{5A~"6?EFdf_I3/$Mk߈  Q;{5A~"6?EFc~|_&ϝKl %h{5A~"6?EFboILM>w '[a$*>c@H?Th&ٿ$i6>w '[a$*>c@H?Th$h?^$Mn}߈  Q['+d{5A~"6?EFal|O&hg7kKTInݎIu"/9--"dGHee A9-FC^+F'F\-,x~x} ϊ'_2v_NN+OQ1&-ΠaKxD|,pv"?x /'vO'a/;J;"mXh2=~e>ax<*dtϴ(0J3 %$ٵaU%SuBm^if0k*u1uI Ng;2 $!;o'QNgatԊެqEB,/Mثlx$$#mt$a[eH͸ 9v?a {:E`%攲4TR2lj[cҵ?Z2}IF۞HճppˑUugPm K[knP8 j-c@$X%GXC-A$g<5k:kkw2F\[32wB6cz:hX_i)%_2e c V5YYm+tEZ)UP,$HhxjsfBp-qTq_CiR{Xܬ1}iC 8#$__@jZk?gYe5?f/7 ZQ b6O*h Kٮ/|ƨ5?| b6O*KMCTsGZ]ϥ>uA{5Gٮ/|ƫKMCT_o =}'k 0>uA{5_6_o ūlUs/"jɺ/7 ZQ b6O*h KuAk5I]ZW-_d1j'G4{?˺˺?/7 ZQ b6O*h KwuAk5KZW-_d1j'G4{;e?&˿ _0ūlU-[d`Gů?8Ct/}|ƫKMCT_o =}'{ 0>uA{5_6_o ūlUs?]^Rjk1j'G%&W?9-.ҟf6_`Ug%&W??/7 ZQiw>=?E?| b6O*KMCTsGZ]Ϥ 0< 0ūlU-_d`Iy_`Ty_`Uo%&W??/7 ZQiw>./|Ʃ Cbjn1j'G%&W?9-.;1k5Ijq1j'G%&V?9-.ѻn-}|Ʃ6VW-[d1j'G4{3TU%&V??/7 ZQiw>o(?/7 ZQ bտ6O*h Kb1k5RGbjn1j'G%&W?9-.ҟf_`U_%&W??/7 ZQiw>5?'ٮ/|ƫKMCT_o =}'k 0>uA{5_6_o ūlUs?]^Qk 0ūlU-_d`H47cbj+v?+}|ƫ?KMCT_oo =}A[5K 0ūlU-[d`Fbj`U%&V??/7 ZQiw>wAk5Fۿ _0ūlU-[d`FuAk5_8_oo ūlUs_`Tl/7 ZQ bտ6O*h KuAk5GuAk5_8_o ūlUs.j.jp1j'G%&W?9-.]?]?| b6O*KMCTsGZ]ϣ _0< _0ūlU-_d`GM-́4v|'Uz^?_nđY@"8ffT*&Zޥ<r2B iqE*e=,n endstream endobj 79 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}\XhfO._Gh?+̊ßPSi4};M#N>5mNm#NH³]It}fK1mh32N1i1BqAm5$ p>nr {Z_ssGF5-G+Vڽ]jrNd؋L20Nh45yʬDV$;<.0c;'Oi;$VavwGk)c6om`{ #|>c[ @'q B mt]_OmBۉDCgx#9bMr܈X]F?ӿ?𪷞ҶF??&x^Qn{q({(y NсװLkWi(o~` V#yopxhtZ҈iqHio6i{6{i@85xk:ޥ}m?E c],A#X1`7=*hmkc>?M$O:i V>D$ ʬ&&"h%Tr#fhpeیj]_C;# ^ZOpvP 44;#jӺϜMnnƛj䐓dVNgHӿ?C>[*lqQaѰQ$T/4%ˤ# aZJjs?dP?g|knKd@Ng# OEjZcRqkbU#v Se4e>j!Jsjb"*w3FX#NH“KAwG աQCT9fӿ? ?$]jVlE/id#OH¥K (#OHµ;J( ֺ`l.$MMoct+Q'8-J,Q:;#OX­G?,Jm1,+ӿ?›&$hwbrJ1Ə$Q$NHº lɪϧs.=?Hi T:K74+B; *ۅ4X.U]G ģNX¡4J6-PpdP{zVZ) T!6GKqy%-t9_i~qYBGMWğ,@͇+(:B8`GȾqq ٞK#Y%>T"S? H},gtЁr)BmG9/)'X=ި7Vf"&rXv?SGkm>Y ŧ#dD h jvOA,։DJ) m?R}:k)@SRC؂3j㴢mCvIF̓mأ{^yE%5qʪ@crsb]CÖ]'x$b)#*HV_pܛkri#.;|BCam*Hx#<#5N"4ʯ!kfl2yַ}@{;IѦ_I_ywKƙ-J8^;ǵD{rbl,G,aBJ!U$99[o ZCsחW\&)FaHU +{vVCv{$y_7Ы9$'Gyë[rQ,pJH}W ?!Ӻm+S:|R_^Vrd@n!ad.qb~_\n'1M A$yc%=}@;SZc[6 "nݝlt1[R1f3p13xZ$KeMgl-Vksi#pqu5v}/? 1_mM%Io$I%.GUEN08P~ۏrUƕg aZG*.vZ[}}h/}}jS2Ց '0w]Řy|?SԬյRѺ%'%"mVckC̾=̾=u5,B(#yT)@d=KUmo=Ve2*pa}C}}h 23TC#`vjfZUO2v$p9YF^^Һg4A^^td@}?&p.̶ubK0{;N^_p.̳})y]ouvξ5,,sPIo{@k;K^җ,$Ђ6:v:v4ʼcQ? }}h? }}h0 65:v:vccRyli|_p<_p=0ƅjp ^^֑Q%ݖisU_pC-?UY42^_pBs $.i0poo?,Ǘ4yTxEm/?, 1ae$Vx[0;R+ޯ?Af^iV }}h? }}h 2r\>m?!{p.̔Q4Mw^G4׿㴙=,$z5o9Go?!wmҺ 2ukvKgauom6mDpڔOp.fXNoo.vq@[ҋ-,Ǵwѱ6ބޟ?6]F./ }hE?AfI?6]mh5M?Af?;~m?ӿ}vtdF1iDm0UFrp2zߵyg&Czk;iDLd0Rc7Mk)i^K#C'ZX<`I?.UF9F2zc'ZZ㶞o*c!l;=)2Ed"i`w1QޯG[Krmќ$g;I@n@}}+2]-ݮ}H$-X~Ew\'ٙYm7rG>8kJ)8 =Ğ`БJ@$*-2@ P{^T+B J;EчľleD/qCg=c5oMaЊH%YH$ zΏEy7v{098ZuYGl1X&ߔt'҅,]j[ZY nH ^A7y8dR%vp=zt#Ҡ[36<*@9"8{ml,V#mg`+I!gJ nFarbysV*{FXp;|Fl$Fxj힖sH!Wn6 ͉Qʮ+_htL#.1 ?gk.FHɜ)DH,~=<1Y8PG@]>wG-ELrNiS@j7,(# 3q*F;qQIݾX5ȥ3 3G6h.nm s!Ђ,rF‘<[yQ`6ԖXd@d*yuMb38&^BXV--Z(^Vp]?'&˧i{4kx!:qW b3@AңoتFI?yjpn3ċK7(1$4q;ad'~R;׮nhcxJx6pX0ς4+uapƞ|If #"m=r1Y͠ndݳg:TnKMsͼuʮ#F=z[n#>YHt$zVMw\'ٙYm7rG>8)NʌB2$Ύ]ҭ[S{!4!f\M\,1[컣mgwd{Aa{/;Xo|Tj#[|Wx9 Nf[iĶk(a(*lBFOAd#fL1#}#VߗUdN>jGG*cƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].fkvr1kqk>(di1Oy/zq@ؼ:eu$ɿ$~cub~"/m|A C |8jﱭRݐ?I o.|6Kt,@=E^϶e?Xċ.Cq-P]XF<{S5?&FԼd_j*89'9'yx47hgg,k$fVF .eRѮ廊yd{I|6 Z9ƙ^ѼEo^) }IʹEb9 WJ5R{3Ь^#q'i96v\R(CLxg mf(#H|H,#'QY7 i:q{QMl'Okk t<tr(Zbk]2x,㑟5u6GV p3X\cdt=n ajYM̼Ջ[˦jZ^"sVN%}28cb*>?\ pŦܒ G]6?'7Wwnt;|˯?)p}ƤcҋqmKpDr~&0ŀ/OR5)fUTdu(Tȿ7w^RvKl'k&d2(cF:cދ6*y\=Kmٿ&_*+h|V$L3 s]R,$XdQp(&arӢ3mO3s{7m.4{VJy3\ɚNHhHՈtu.gvo \2_[ CԞ OZ9hp;x"nsLc˹?[k;xni1:Eq4Weba_ƻ=S=b\f̑ǒU8'<$$С$Iu H7C]LC Ű+5=#Rt b 60nGSj^Ț׍4+۾M:龝ڙbYc$APR{l. b)s\OX](d@@>ʾrygɰ KAt7IάiKռ;w}(o\g .O'kgzM2UVWTڬf`W'|M,JqbeY>mάC [Rݵ+_fiyrK~h Yn㵆pgg'OwksJBf#j8iX2REύh".! {q}k'XF Ru Bp0:ֽw~^o/Cˎa'Vܺsrsmgii5íHɒ5Jtao 5V=M5Ҽ{=G.qq18Uu k)\=^ujM<*NV'R6!FQҺ<[dBd+*NKYc<[&/fFa?' I'0YX/Fl2Ir嶅ˌ>sb魴d]Ji`ud,`#N`<8|97K6;9d;]Zy["kDR$xǫJotW,om9:'?խwQ n4Q,2-P:ӧF,urYn0F {}]2SDWN|;o2Tgvo 4W5΂}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/Vh`k|ZCq^a7C_2J=WCVq +!/_%Zؗ?OZZ֔-tG;JSGq~u8=Ž'#!dxבI0sIo60q[=~gi)HbTb2GaA_G&Iu&{{5Kw/s?1Y: N CȆl?5(Ѱ?/g{Gign[]+xlQ(T_@+<q.sylca;Fl`u{W_aA_GvBߕ3H k!D&m;#vb\x}+v8i6hjR$81ma"?Cbx^ | gaA_GAE巍f2>ԓsW GL/ML/MA Zq\ u*OqO&OO&&OO&0 iݮ&L tT"Q ɓ~ɓ~js^,rRIA$㯽:_;5 32Կ4y2Կ4*rڇ.gx&d_ 9I?RI?RI1g/aIb*5j|?_?e43Faiy2Կ4y2Կ4Kޗ3j< :Z֔-tG;JSGq~uɤ8`,r?"&OO&&OO&yee̷*hvw=C,k`*M+@F/>'#9]JBaM]9ΫSZt,EtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?y_ג+5_ Zץodkb^G$??Enwog]sq`CJA;'XQ>OZ#=軚LRh)e 5ɿOyutTVRf?-E;sӿTOb $#cWDpRB;lw_ۚO,!?Ə'_\zޗ>h?:ti&B|ҹ8NuûSLxywݷݍgiRԪ?_'_GAK/O3~&-ލqv#FxȈV~r::/Kuyyoc(i##U;sӌ5?WѭU⤶gQRh)e 5],u:gHSʤ$lcpkJR:{t44 YBA{76ID >NŖWGΜEI <қ8 kBRK(Kv#ȑ)ۜUXn-}?ǝ'Jkv5^M>,B'\ n-}?քZs]kᦊ4/E}NqU:O~t1hmţ Z?kcΓߥt(ţGC|G'Jt1hmţ Z?iu1˼mF0doVē3|PM+bGۣG?m-o泝g< ʬ!@oNֿ'J`c?bZ^4\)b2e}-+q}+ܛS0A8n:g> Z?ht1hm:O~y{ GC|> Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥt(ţGC|G'Jt1hmţ#x[,䕊.{~;=&XfPY BlY@݌di\~ Z?ht1hm;kwknTdpFGL㵚)%Ô's,GI)bGۣG?mxTK뇒8nȬC nH-ly{ GC|> Z?kE$K\\IJPNqLX eME9WM&5 35kML)s^Z4A'>SjEy~7m?^}|v ZIlG&XN=W!羕x䡉(=v:jtյW9GM/D.?j햟{#;D`iQ}&w(9oC{iT%OYJw)Nf{2Y\M"6$hxJ$.ۂ4ax uaw[ oh$@0o ȳk]'ѭUʹ5ޙr>A#H,@rYJf)WVߢCAK]>|t^hzME)3"/`d0c玵oVlJ/mfgZ*gV2B)Uz]Z厇ۻit0جFJ炭 kU+/cb" 0J8+O+]???C#f}Y&x[G-O5̋sҶ{׷CL$-m&Y",̥l2A8/]??OsZ~=NWqX2YIJGhy-ie+<#h ^8Yٚav],{VWfAtٺaPvUٺaPvUaPvU!PrU!PﻦJC'/4 䫓a~;A'6\}b̓(6Xgҥ6:$rqU \iSLjn{fkY"a̸!Ƴ=?Z<3 s>X-Ԭ亂;J5ɥe$"yQH̬P pҸϱkGGص CsjATc7*6OG C +!R}]??ܢɮnUe7*7(/Gu CC + !QmsPƛ#\;tI[iV6 #9:R 焋Nt?&q !PG1sBŧUԼ$X${&[eg Tn *rjw|v[Mf%;bg`(_.@ba'9ŒgWA}wP>ϮjU+ia[ Z鴋eL_mȍ G^@g|=r؟ r ԯ)!b_2 1N5*#\??#4:Xk謯m!f̳f0>ဠ.G+]AVR3fHrQm}+K5*?3*5;yޗLָ!aw ?*,v߇_0].|;g"GPaqq0=fUNAT=]]kŬݴwkm4$QWgƜɭJ=$8t; $)+\??O+]??wVh{?3*/]??C:+ c3*:*+ٮfU5 Ccj? /ۮbU6HubxWVc m5KxgMP2M@鬵{5džmEUB3F!r\ M`-Z$c׊vs'a]VGiti'Ԫ,fHm[pWk+ M1aJէet];[n cic]??1bU;<zi.K,fŚ4G8d' dnU4,~0h| 6ߕII?3Dp F@Kw?yA T,s5i#)4[rb@*ׂoB}>V=7EO$pZ22bU/* [4&Wgh$;ȻHm#+ιAx T/*K[5?/*1PMEs c~Ax T\s߮^UtW/kGZUuG} тyAV}ŵENuJϩi7Z׭gdmFA^U/C_2J/sѣ~"[F{ow583:*(5RPA CKI@%)EQ@CEJ(QE%)(I@%)PIA J(QE! %R( RZJ))M%( %P(QE) QI@J) -% J RQE( Ph(EPhPT?I?T?I?@hz+ʾ%_2J?k6q *sאђU-zDODVm_.#?@83:*J(( %Pi(QE)(I@J))M% J J(QE%Ph(@ EPhPIJi(4RQE(4Ph(@ EPhE% JSI@%)(IE(4QAJ(4RPHii(4RRJ)(IEJ(4QABjS'3M?[yO_ XאђW-;\+ʾ!͉!$[xBO[/#5軚ň"Fkw4Hh() -% J RQE( Ph(EPhPIJi(@%Pi(IEQAC@J(4RPHii(4RPh(4Q@h@ E (E%)(4RRJ)(4Pi(IEQAC@J(4RPHii(4RPhauR?tC4Z?d?/c^cFI^? ׵,*ĽE "Fkw5`+qfz/sD ABQE!)(I@!PIA J(QE! %R( (E% J L2(@I篭KIQI篭Ji*?=}i< u (3IEG/'%֓_Z<ր$G%%Ff_Z< )*?9}hր$4 44Q@h@ E (E% JSI@%)(IE(4QHhJ(4RPU.IuN?h #ŷz+~!b[_[yW? טђU-{`+qfz/sXqȎ"Fkw4HPh()(IE(4QAJ(4RPA JSI@%)(4Q@CEJF8ͅ4VDj>0Ӭd=QIMt{ӖHـ\ ?hƈ׬]]~䞻st1?ƐI?pd~t~'Ot'sGF|ѧ{?YzhG s{ ?I ?<=_4zhs=G'OEzf}37y''OGסoѦWy'OGyW~eW'7p?i?yW=_5\HN#V|~b㌹G# ޓ?4wn.pojA+z 7;(J?m[Zil|+󐜅fR xF/L"n+83).E-} ֕?NOinVIAnp?oi#U"1doR<~<D*); 86:Xkb ^w{jdmХtnBG vKsZcjoE5TSRPh(4Q@h@ E (E% JSI@%)(4Q@CU.IuR?h fn?d??5e^CFI^ ׭/*ĽBDt@'Ek /DV3[@E%AAA JSI@%)E(4Q@ EJ(4PhE% JSI@%)ܟ4>=cx?*ˇi*|y Kʽ=Ʈ)LJht nYmTFf6d.*dM/-Ei/. LVd* vxU9Ya])a[D !!僒Nv91<'ݺsk[oa,=S$3Z]f^xMEWQWAo8eTH<2[<[{q[.t'i~+$Lv>FTsu7KbL!+)FTJcoK$=̓ %ؓ8)$v0Cޣuk acS}K)Tݴ P݈N~iy4pмQ^=QRv0c ,q:gN/hV譬%@!v(f;glS>ڗu}33HГ fFҤƒ iX 9}'$24CX5K44md9Ƚ8:mn.a0®I8 1e'HEչʍ#; ($N@SO^mXu>ըGU[ϵK y4]N4\qx$SxSơj 1yre jktZw\ܢ[F!r X3tQ֒ZŨO~x)q 7V\xgB[yXVI$l쥌AX|3:u&q\[Y[mRIgu+Q%s Ɗښ_=]RJΥ]=!HO^jݞc1kH|a')oŦ94"XÒ$7m0G|[5ż7v[\&d]##9#iI^- r355aSP]5=@}VONOP-yTgC7)shRsƐ$. %$q1:ܸ~X♆SFz5_?o3W,=YCK!UWV_fu>u9r3ys3C(3C(aʌeh>>V_f~u>u|9m[|9gտٟ֯nGٟnG<gտjekS?_?_"2[|l9/ύ????"??"v5o4ys3C(3C)sFgύ? .cKkhbgFs !YA(׽iaWvVW lcAR?;g^w2 ɶ'9٫oCX:٫oCS-Q!%Gܩ*F((@ E PhPIJi(@%Pi(E(4QI@U'fUKi4@q[׭7+WjjWV%HCNd/'#q-_շ] Rʝpl*8_[\+4_YO>$3d]koq$v![lriz&,(thbHVrhڌz!r\4K2wN11XKXIs Hz#8I đ ȑ( qYֶ,JD`{z@VmRm$¼JO6캽Ιm-/bMw| ⣿X {+D.3;̃im"ƬN\T[[C}>[{6f0T W>['BE;o[nn6տ[ѻ_qW?-vC?8(<ǣoCcѳVΉ!? FZ'Z:>Hj8~IHaIJi(@%Pi(E) QI@J) -% JSI@% %Pji?5j_3M{ĿkyW^WkyO XטђU-{`+rOmދE$#'ez/sDQIPPPhPIJi(4RQE(4Ph(@ E (E% JSI@W54<%r^RāymG^}^'FX3_Q\6dKti\$У!넟u=AeOIHQI891{ոRQc5 @=)PEPEP&;)Wr7QTƕ2M,nF}HM_*jzz-hVk3E&mqpGZ$E{^aw~ӫc'p@'l.ފr7knw$?6<80,YZ 睗%;9$G@  9Py\A#"@ X]dAm>9W/Q&vH9ZR{A[TPEP͟uo~) ?|VoYڗ,FAUɖǜxshI?ٱճ}ŬOg`tշ}ť-RTpy0J(4RPHii(4RPh(4Q@h@ EJ(4QE%)(4U[/jѪ?_Κ-o^2 1$V/FA^SB??dKbz`q+n_mދE$g(T8/Eh#xQEA@i((4QHhI@J) -% J RQE(4Ph(@ EU{jW<ǟOw:|҈/?#]~c_Qi B1 ?(zF/'g^".d9T%i D؜ FeVxtf^A=\' YszUSO#Wpp}ME`x;q_Ci>ou1cYT23 OvH%MKh縼p7!blOSF-oqK#-軚Ŏ%q+j_mދE F!())M%( %P(QE!)(I@J) -% J RQES{h|y KʻmS҈/?*?J#!"[hF/'aj,+b՝Ύ0u *+tF/'OP[qzGϴ^Z<"{Ziw_({.쌎p _n6O$hG&KxHTtn9ǧJhnpxSU{.DE$7247$!>'v p*)+jWhq]{5hBvN쏘﨣@9FӛO4nGw M Ub;}+v/ \$ВQI 4*M$NW(g>ԢMn?&x[E.$^u,uGg8 :N{i1Ik2*3;#qҴvMn?&[S=(aiDXrR1i )a3}ԤmDj Ք0hm|ѶchZ=< VNHU1lݦ2 'G2FUMQ`y7[P;4Ӗi ]Vhb$;)PU_K DZEc VٷI `FQEA?|VoYi6տ[^!OFAU-7 GM['Z GM['Z%1duʐPʒaHii(4RPh(4Q@h@ E (E%)(4RRJ)(4Pj?5Z?@hx>2 JX%{`FC^]&52J/sx y"]qkqXI벛FKw40FR)(I@!PIJi( %Pi(E) QI@J) -%^j4<%ro](7R?oJ#!"{vXdiXXQx ?ݤ?]OEfYw?P1?]OEA? <S@yw..~cP]C˻u=w?P1?]OEA? <S@yw..~cP]C˻u=w?P1?]OE@ In#eHJ+qejIdXzŧzO ĉ7 GM['Z>3l:j>/vGYܩ*8~HjJ) QI@J) -% J RQE(4Q@h@ E (E%Z?՚qW7ݯuѐחL\xӒ+ԯa[1Zג*Ľ-O]d2[xO@w"&]nQEA@i(IE(4QHhI@J) -% J RQE( Ph(@ U~^7R?oJ#3M(3騢+U[mn̷1!aG|n?mV6={N`p|U/O?ƿuoGt?߱Y>d+66@Yb{6V5b2F2kKoҰo'4˩\G$ #9z:nU;=/_r'lax(/,me (j7EaZ+MWYK@;_5Z'gg0d_:/dtV c)Oӥ}w>Mte;NP>h<$#FrI*2I$sTt/@UGʭSHҴk,-gktIf]ݙA$ j,h^,0T%%Pi(E(4QI@J(4RPHii(4RPh(4Q@h@ U?JY_Κn?8k>'i^K$M\G bFC^_6P!?2J/s?C'o-ދE=rC7Ejք=M RZJ))M%( %P(QE)(I@J))M% J s X.Gh`҈6v26zWLna-\EpcB:ȹ޵hΦhsOT?o=Iݟ~'IY:wusksfЙ!GnCST?o=AuA/vzc8f5fIkxXK>í  7Qkji-Ǩ[Vdg:t}Zng-ǩU?e-Ǩ v15F 9ݍشkM= je-Ǩv?zJrVPPbV[-fXPD},0 _-pz욗sگY >ݪr4%&>vfj_kj/jg-ǩ>ߪ$dԿMK|9CW,PGY =D욗sOBg$ #6(5]MQ[Sz{9\Ʃ?vzO~?g."tV'ѐU}S~WuxdA1d$gNNJIe8p/D\׉iD }{?'_#t*Q?T?r5?rRPPhPIJi(@ %P(QE)(I@!PIJi(_:U+tιm^2#'\˒+5g--Ln5 zdZ2ik 9&M#%軚/')`qjydz/sS"ѶhPPQHhJ(4RPHii(4RRJ)(4PIEJ(4QAC@RPA QMIM#"9b͍q ҵ mrII$䐮R{ת\[k%\8XnxvM?v Owߋ?*? [?ahadq~+oo_ݣntՇ[_uah_ wJ /Vn5؋9roo_G3TrxxukOE,O\\Iݣɝ{Ň? |WAU+7]w"vE,Gs_tnxVnE؋9r_W6M_O 12#rݣA bK3I=ɮL؃Km1P Hd0P(4QAC@RPA CKI@%)PIAIEJ( %R(4RPU+ubO! +t-ʆ%?q^gIx.Kzl2׭ y/7[r&F;w5_NSDo_.6)M%AAIEJ(4QA %R( RZJ))M%( %P(QE! jiWҥ0MI@y I䯥Li(/%})<%E䯥')"Wғ_J_JO%}*Z(# Ry+Rh/%})0qz/sUP>'&O#Eh#lQEAB(QE!)(I@J))M% J J(QE%Ph(A RZJ))M%( %Pi(QE)(I@J))M% J J(QE%Ph(EPhPIJi(4RQE(4Ph(@ EUy!_άUy!_ΚF[o4#5y/sm^5f%ީlOSI蚚z/sP$??MM?p@JSIPPRPh(4Q@CEJ(4QE%)(4RRJ)(4PIEJ(4QAC@RPA RZJ))M%( %P(QE!)(I@!PIA J(QE((@ E PhPIJi(@%Pjҿ/SCJ4O?q^iKFk__ n?8k>)k^KR؞u8541_.桋I蚚F(?ދE FRT)(I@!PIA J(QE! %R( RZJ))M% J(QE!( Ph(EPhPIJi(@%Pi(E) QI@J) -% JSI@%)(IE(4QHhJ(4RPHii(CJX5^_i_'n?8k>)k^Kz\2׭ y/7[r&w5G-蚞F(?ދE FɤQE! %Ph( PhPIJi( %Pi(QE) )(I@%-% J RQE( Ph(@ EPhE% JSI@%Pi(IE(4QHhJ(4RPHii(4RRJ)(IE(4QA%_:B:W:e[O_3Zגo^?q^iKFk__ ;h[&\軚~&\軚$ؤ4%)PIAIEJ( %R(4RPA CKI@%)EQ@CEJ(QE%)(I@%)PIAIEJ( %R( RZJ))M% J(QE %Ph( PhPIJi(@$_:BW:e[O_3Zגo^?q^iKFk__ ;8@OWn?b]SD@5nF(?ދE FR) QI@J) -% J RQE( Ph(EPhPIJi(@%)(IE(4QHhJ(4RPHii(4RPh(4Q@h@ E (4PhE% JSI@%)(IE(4QHhJ(4RPPI!+u=A't@u3m^5f%޽.mCֿ-v?OVb]TI 蚷s#Eh#b* J(QE! %R( RZJ))M% J(QE! %Ph( (E% JSI@%)(IE(4QHhJ(4RPHii(4RRJ)( J(QE! %R( RZJ))M%( %P(T2GJ违MP!+tL2׭ y/7KFKo4#-y/KbzOD՛ɮ$9]cYnp~uZ?'`kVh`pi3Gzd$_M)6?EGl B?"7A"7Q߈  QhEc@H?Th?)>ܟ{S4a$*>c@H?Th{>7Gl nO)>ڟ{S4a$*>c@H?Th~ڟ{S4}?ia$*>c@H?Th~ڿ{R4l_)l ϶/M'} _&  QA~"@#bϽK{>c@H?T}߈ֿ{r4}ϵԿa$*>c@H?Th_k{r4j{r57l ڇ^M'ڇ^MOA~"6?EFA>׿/I>׿/V>c@H?T}߈ ik?{r5c6?EGl v9>N׿/V~c@H?T}߈ hk{r5k6?EGl >׿/GM[  QA~"@*y}o_&?{r5s6?EGl 9O<ϭ߰a$*4i<[a$*>c@H?Th9h}o_&}߈  Q<[o9A~"6?EFg>/G{r5A~"6?EFg>/I?^Mh߈  Qcϥ?^Mh߈  QcϥѽkK6?EGl {r4o}/_&c@H?T}߈ ϥKѾOI  QA~"@2I> /IOI  QA~"@2I> /I_I  QA~"@2s/^$M&e;a$*4#2ϝKљ%k_6?EGl >o$M;a$*4{4~|_&~c@H?T}߈ \M>w /F&;a$*4ϝKboI?  QA~"@16>w 'II?  QA~"@0>w 'F$ks6?EGl ?^$M'+߰a$*4 d{5C9X]"%KwPrH}߈ii$z<(C+,1A>FKo3#-y/#I bѺOК?2ZגoT%w>OKkifP0%"Mn8;v[ G$??M;Q_jw:w>EE NK>c;xFKN^;;lwhJ)D+/ :7PzGԵ'gcٵ[Kq,B02)ێ2E=|g+'.AiKYN.1MRA+?}u7NaJL]߻GbcZXu8octɆ"*.9@jC6S:|rg"f_!]* #iナƽc"4׊Tyf][FU$p8$u J Q<LlS&Ih8o[ifoym{#g9;]*O`)d28c#h\pFsۃnj4SoN6,giШDzNJ/-׆5u[$X'Ԡ{U(Uhe๑㞀.Fw>w,Mlɕ D;g[][ Ua{vmmVYDAv\\Z[ 28غg;qڵt )M?cKh aqs/$AP'zY:uL]j7C̨&Ird]5"ŷ-Qivо#/ m<*[+ * ;H]=%O4^T{l8duǭsoSM>U:cDӾЫcEp ^4:m<:]6KHO^F:u@3ų.$vv_aӞXw>tL%V*pAbAo[[_Kes3ߥWiz3$0q=.^ֿC_ )RIZm*0N㎆~4KpjvH$@:*vb4F}RP-e eiՕ6Ș#`P'{y7{/dx(KN3Z?!|q_ &(kIq Trrx5jŚTdFdp:UivRA "|3=$XcYD,sn!ApGN]tBpcX7y,3̄'څ4{O֌ag緒5uld.:2{]gY,u{->䷖۪*F??|+2Zk*X ' imAj&wP g`PI浵O iίi{m  ̇xЍގZV6ZmiF(i/󌪙Bvwmk[kmQcpU@T. '<0jmG?#ِ0#Ke\E>\r'z99ogԞ+ bk(Em6 `/K1&%(((((((((((((((((((((((((((I8k~(k^KzLI8k;'k^kZ؞y4RO b@~e*#E] ?p>vffrqA{7Gn?/}|#?3S)ƍ;n\^׊GgQ?#?3Sv Ol7bn417^# AGh\ΣO4i5=:nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Oo͸6nC=sZ? AGhӰj{u/?`u)ƏH j?FS?1|θ\֣O4GkQ4qA7Gu/?x$z =sZ?ѧ` _0C\_0H j?G$zu N^}nS=s:? AGhӰj{W/}|?x$Zu -s:?ѧ`\ZK _0_H G$Zu N?e?auk?)ƏH FS^ԃO?`uk?)Ɨ=s:?ѧ`ۏ _0?n?1|?#?5S)ƍ;fbqA7^! AGh\֣O4i5=6nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Om:};1{7^+ AGh\ΣO4i5=?`t}nW-s:? AChӰj{_/}|?x$Zu -s:?ѧ`^; 0OH G$Zu NbW`u)ƏH ?FSqA{7K 0?H ?G$zu Na7`u)ƏH ?FS~qA{7G.?/}|Ŀ#?3S)ƍ;n\^׉GgQ?#?3Sv Om?`\ΣO4GgQ4\Iwqs"FnjG_JXM=u1l\0%=}AV-oV(.5K١^9.zNN8Tx M endstream endobj 80 0 obj <> stream xXmo6ny|!0 ڡ]CZ8;suI#DĩIsG캸谪˛]wGчb:l15X-r/8lYbip0:8J_VrE-}%M㣮φU~ Aå_a^u@FlT+Cq;5Yj4sawluwf>;͓ni "tjWЃ@ ^7Tn.4}~N3)>LR-ijvzuG_pr_|Zc3>c6C~vc,H˞m;d-E:'!$&v+xY6\zXZzzɁ ch#6aɢϓɹ)mxnNJF!)Bx``!h fX}-0WtR"<2ަ@7C7ۛ_L'FU.l#^F jibrPͥn.Mŏdv$M+ǥ٧'46U+L$s؜z۸%AN}]4 櫌u5 d.a1*eڀr^5ǵrG(VHr?BBK:%y/]beZiwRn퓾}S*w\"q :e_r"M|u9j/`i%c胓0R\֬\ҁm1-8^u{F1x昉ѻb>eI9&i t`Uڙ -Yǵ\)8rMr[ <˓D_/1Y,&QfA-O=(tĺ--R4Sn1f=frKRzFV#鈈TUq+yD &8aղmae8)v0=ϔ͵oNC<g,ru~K )*0g4}NMy 4߿2Bӧ#=|ҏ3Wcƙ7BEJ=6<>N?5j8 DjE@T3G-T ]Ǚ?ZlH@5I=zj Qk\U~qqZs`ӱ ơ(Œ'A;bzuIO(ZȼKVxJO@"u-S;,Y'Q2EȞTG6'Ju%nӨkz ;lJk6eM_۔Y[8AįI [63-::BS?4t endstream endobj 81 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}\XhfO._Gh?+̊ßPSi4};M#N>5mNm#NH³]It}fK1mh32N1i1BqAm5$ p>nr {Z_ssGF5-G+Vڽ]jrNd؋L20Nh45yʬDV$;<.0c;'Oi;$VavwGk)c6om`{ #|>c[ @'q B mt]_OmBۉDCgx#9bMr܈X]F?ӿ?𪷞ҶF??&x^Qn{q({(y NсװLkWi(o~` V#yopxhtZ҈iqHio6i{6{i@85xk:ޥ}m?E c],A#X1`7=*hmkc>?M$O:i V>D$ ʬ&&"h%Tr#fhpeیj]_C;# ^ZOpvP 44;#jӺϜMnnƛj䐓dVNgHӿ?C>[*lqQaѰQ$T/4%ˤ# aZJjs?dP?g|knKd@Ng# OEjZcRqkbU#v Se4e>j!Jsjb"*w3FX#NH“KAwG աQCT9fӿ? ?$]jVlE/id#OH¥K (#OHµ;J( ֺ`l.$MMoct+Q'8-J,Q:;#OX­G?,Jm1,+ӿ?›&$hwbrJ1Ə$Q$NHº lɪϧs.=?Hi T:K74+B; *ۅ4X.U]G ģNX¡4J6-PpdP{zVZ) T!6GKqy%-t9_i~qYBGMWğ,@͇+(:B8`GȾqq ٞK#Y%>T"S? H},gtЁr)BmG9/)'X=ި7Vf"&rXv?SGkm>Y ŧ#dD h jvOA,։DJ) m?R}:k)@SRC؂3j㴢mCvIF̓mأ{^yE%5qʪ@crsb]CÖ]'x$b)#*HV_pܛkri#.;|BCam*Hx#<#5N"4ʯ!kfl2yַ}@{;IѦ_I_ywKƙ-J8^;ǵD{rbl,G,aBJ!U$99[o ZCsחW\&)FaHU +{vVCv{$y_7Ы9$'Gyë[rQ,pJH}W ?!Ӻm+S:|R_^Vrd@n!ad.qb~_\n'1M A$yc%=}@;SZc[6 "nݝlt1[R1f3p13xZ$KeMgl-Vksi#pqu5v}/? 1_mM%Io$I%.GUEN08P~ۏrUƕg aZG*.vZ[}}h/}}jS2Ց '0w]Řy|?SԬյRѺ%'%"mVckC̾=̾=u5,B(#yT)@d=KUmo=Ve2*pa}C}}h 23TC#`vjfZUO2v$p9YF^^Һg4A^^td@}?&p.̶ubK0{;N^_p.̳})y]ouvξ5,,sPIo{@k;K^җ,$Ђ6:v:v4ʼcQ? }}h? }}h0 65:v:vccRyli|_p<_p=0ƅjp ^^֑Q%ݖisU_pC-?UY42^_pBs $.i0poo?,Ǘ4yTxEm/?, 1ae$Vx[0;R+ޯ?Af^iV }}h? }}h 2r\>m?!{p.̔Q4Mw^G4׿㴙=,$z5o9Go?!wmҺ 2ukvKgauom6mDpڔOp.fXNoo.vq@[ҋ-,Ǵwѱ6ބޟ?6]F./ }hE?AfI?6]mh5M?Af?;~m?ӿ}vtdF1iDm0UFrp2zߵyg&Czk;iDLd0Rc7Mk)i^K#C'ZX<`I?.UF9ƭ2zc'ZZ㶞o*c!l;=)2Ed"i`w1QޯG[Krmќ$g;I@n@}}+2]-ݮ}H$-X~Ew\'ٙYm7rG>8kJ)8 =Ğ`БJ@$*-2@ P{^T+B J;EчľleD/qCg=c5oMaЊH%YH$ zΏEy7v{098ZuYGl1X&ߔt'҅,]j[ZY nH ^A7y8dR%vp=zt#Ҡ[36<*@9"8{ml,V#mg`+I!gJ nFarbysV*{FXp;|Fl$Fxj힖sH!Wn6 ͉Qʮ+_htL#.1 ?gk.FHɜ)DH,~=<1Y8PG@]>wG-ELrNiS@j7,(# 3q*F;qQIݾX5ȥ3 3G6h.nm s!Ђ,rF‘<[yQ`6ԖXd@d*yuMb38&^BXV--Z(^Vp]?'&˧i{4kx!:qW b3@AңoتFI?yjpn3ċK7(1$4q;ad'~R;׮nhcxJx6pX0ς4+uapƞ|If #"m=r1Y͠ndݳg:TnKMsͼuʮ#F=z[n#>YHt$zVMw\'ٙYm7rG>8)NʌB2$Ύ]ҭ[S{!4!f\M\,1[컣mgwd{Aa{/;Xo|Tj#[|Wx9 Nf[iĶk(a(*lBFOAd#fL1#}#VߗUdN>jGG*cƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].fkvr1kqk>(di2[~FIRu=(+?"aI2oz7ȿ䞧in5_%H &q<5yN0nkF07d7DBu˟/͒ QW&4{h1"˹峵n#*?<>V-#{UʟR]Z}frtFeYDE*HW2O G$kpbV*avaOOɱѵ/'`Y-eWڊ;@I^^#29rF1C pGTtknⷞY_&}̈́Bs֟|1׺*o[z׊mGRysm}pRFMnqԨ$+nn&IZifp*ͽ.6$>jYcxe=6 (+unEZNb)Sn"i&_*7#ĝ7=܊?VXL "A#8gqsMQU*5;X@F[?8Za(ds/bV隽֟*ȧկ_L؁,ʏ1i$&2e䍏oo2U۝&2qb+q$}+|\[k6-Ɍ1`?TchYU$J2/ ״j ə%J󑎘j-(eJA2Rgvo GJ11U9 i4I"\ 7XDܴAjKcҴgie${d#:!rf?5R'hcubv8?Ƌݛe⪭i6 WrfP5'SV4\ۜ4Cz5w[DbNGz\n9XvGTXG%13$m何@8 ~u'4(I]B6 kWSEPC2~=l OHԾ:C#آB 98ۑkB1ڨ׾<&M8+若Nof{,vXXI#ac&;AԢ eXo23V7D#vxyOY2l?q~'Rr] Rsr!mo}7C<˓ZޓLUx"6!X8{8m$K'fVOs1VTwm|ٚtuܒ&>Vu᛫ac4"I76ܡ.۵JN;nTy,ZW+} < J7ܡpIʟ~8+Pm=O3QRPkZKi]tޓLU1, pXUf?lԖ3&#U F!%\b\(r~T3,Eӂn`V8 #=V:_4\=^EqepײjSrK\Ƀ*͵I'AI#,e+"qYBNkOk'4~>\ҡayڬN=m懫7O+'OL?%=Եs"6!He˪B({Z5|Ai$TB@b1FA\ k5{;ߗIշ.ܾ~\YZMppR$g`2d3R>ve UzSk! h1$sz,n~s|˜`LG+UlmC/FA2WCڬ7wO+Jԍ0ct+xV&FY ʓR{XIh;vXORIk 'Ѭ0[&̂0R\mrr\غkm*YRX%Y HXO+*3mF< (YVee>ȩZy@&^?қ+-]"`~N~k]E[MK ` eT~b{4PJ\hX"T$@?18@jF@/\6kq+OGU~Q/^G"I1UԂSW"G&5nNQm)g 2Kfv1 {;CV2* @{]nW42{V\F^zJj-.Qm7TVw1n̝U\ziX1qR_qgiԑXX!7>swԅJoY *f=zyFq<0'}n lLT?Uӟ'>LUݛesmٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(WAZa;gxWMFI^n'ѐWMFIV%z,_OSDVu fdҬTlf$??ElOqoj.5EY58Pݶa//l綒I 4mw`4{94R Ĩzd FPؿ Cb Iu&{{5Kw/s?1Y: N CȆl?5(Ѱ?/g{Gign[]+xlQ(T_@+<q.sylca;Fl`u{W_aA_GvBߕ3H k!D&m;#vb\x}+v8i6hjR$81ma"?Cbx^ | gaA_GAE巍f2>ԓsW GL/ML/MA Zq\ u*OqO&OO&&OO&0 iݮ&L tT"Q ɓ~ɓ~js^,rRIA$㯽:_;5 32Կ4y2Կ4*rڇ.gx&d_ 9I?RI?RI1g/aIb*5j|?_?e43Faiy2Կ4y2Կ4Kޗ3j< :Z֔-tG;JSGq~uɤ8`,r?"&OO&&OO&yee̷*hvw=C,k`*M+,[{FHŷIm5->+o ԗh#V$#X ^x i$H yVGfcq(Kѷ x=+7Z,vp^^Bp"h1OWS nhz:]褖 n#=z p) hXVtb띤a]eD UIP>2"ƊUF-qn\|D>&bEuZRu鷖dJ0˔<uj֯ssW0hL)ǎ+7?1y)<zWn"#o^Fu\ӡf(#(((((((((((((((((((((((((((((((((((((7i^+>'g^K$S7i^+>&g^K$[=?'`q+n+{=ZKC W /?JďIoދE`O'_GAK/OME{˫ҢC4o ,2(9۞|a;[l(cb]X) "#M_2"c)e 4ni?֮@sI2 v|ߏ|OmhJcϕۿfnn8JUxLD)Gni??4 YBq5nk4wD@ 8$չ|G[{DI,29۞gnR%:'_GAK/O xVc0{:DZU$#cs]7fr˒,I_UhʕװՍKۡRj OIײO:&wgv,6nw<^gt-Hagv3ZZYD\KDN坂w$ t1hmţ Z?im|Wc5<7<0ȱnUf9 {zv?SţGC|՚rQKl{(Qo[Gy^ڝ9q<AbGۣG?mly{Γߥc?b[t(@n-}?ǝ'JiĚg$Vs|/2 ̳4[djʹc$ JCbGۣG?mi_X`tRtm##2?eƧM..@!;)b8OL GC|> Z?h(_\<, uEbdtRF lkcΓߥc?bZ-"_GdHUMUJsuefuRŰn-}?ӴYNeMO lr)x浼?SţGC|ԎiKmmѕ z5''Jt1hmţ Z?kcΓߥt(ţGC|U%]:B"r@n-}?խc4 ,'Xyw Z?kcΓߥt(ţGC|G'Jt1hmţrosj/H}!'+MFA.ff2W<m 9sZ\G{fp\VqZZz]@5/ 5g=o,JyV݆Fd\?/#޽`y!kh2dne.f)1wzeGBp7^ kQ%;D͑kLO#)_<~(A@ mZ!;.s`{բ5#;*5s;*5s;*5謏s9*5s?9*}3V wATr :^:lfsNDJs*"dq"mCRbgs~$8îrU'uC#4#4 m_.gU_%NzWg>M/EK)!ʌBFebc68}]??>ŮnU,{TV/ص CATEb}\??>ǮnUmXd?7*!PMsp.ATEa}\??>ˮjUnX_f5*k@4m&MRLRXHY8J89G<$Zv 3 3 /Tg?5*9 -:톥I$2%2(E Br 9c8I}sP[K T֗M[-VblfDhl :8KHxM-71 C9Azu^FATy!U7q~)_Ee{i 4e4 r?v \h-Z S0-FXl8%' Z^FATNATx0edžƸ6I Ud6P}0Pp 'dV8 v9:  |s0u Cw^ -d[h٤q 2킸$dcicGi ~HM#`O2z\kI Cc~1g૙dЭIN#p;qU|nbgb-j~#_<~*ѐѐ.λAx TdXx~Zɠq4Ҿ1JnWր&J >Ҿi_ZP}}i>Ҿ=!~Ҿi_Z7+I *ri_ZJ %F&SޞSIE(4QHhJ(4RPHii(4RPh(4Q@h@ E (E%R?TI-FA^WC6_?d ͷz+ʾ"jlK8EO[O#5軚ƋDT@3[@EAAIEJ(4QA %RPA RRJ))M%Q@ %P(R1l) Wbf'\,In䶳h]-`yƝ=FKMXα1_+Ҵ4]6:|3cF'oVcOTcrdq^s =goj?]?^#˪]="Gz + f9s3"Gz +hh]Ý'@=gڏOWyȻ@=gn?]?]ߓGG"n_]?G@=gy4y4r.wROKz +1TlٮsRd!]W(ԳrI;x~|3K ڛepSmֿ[?G֧@-kv]H G<9t HWCӎR?k_-kSmsu}w=pT#*X,s_CdKy5֏wotcLNDU"1cc涞k 6/OZ g*9|CyoϤj$){ H25ڐZ/O҅U'a:qr:_#A*;k0 em{ >F#N0)>>YNQQQRRRPh(4Q@h@ E (E% JSI@%)(4Q@CU.IuR?h -CVq *!/2J]{CVq!*!/2J/s??El#5軚ƋDT@'Eh`E%AAA JSI@%)E(4Q@ EJ(4PhE% JSI@%)S?pxOnfhsW><%r^_Wtva !T`p u.m>Ky71t9=kR$qfs~mD(+;.!vs1cs1 H-gHitQ , Y$xܻwEsw#]i֓\hCt|?f^+KM.as8-B8p$2 g^7&_EO{JPQmƻflqߍd}WC6mA3԰xVUR yHY \s(}li&:GV4/W#KEd }@`pirZE_PM]_9וl.n-#i$Do˕ ^u#Q#+HʸMWTee"%*6ZLդoaֲH'5@K6rϔզNhM]XZ\vH'4M^|9gxA{TzM#Ko veI_ogb@p=nNf7 nqN/=o_FhlvVS_uk{dv;;o*z I@!PIJi( %Pi(QE)(I@J) -% uOZ5V?h -wCvq *!/2JmwCvq )!/_%R؞"* ٓFkw5`+fOmދE G@i( Ph(EPhPIJi(@%Pi(E(4QHhI@WU{h% _x{޿O}J{v;;o*j 4Q@ EJ(4PhE% JSI@%)(IE(4QAJ*i?5j]_3Mkvq!*!/_%z5cN2:Ց!$[HEO[2o_.汣??El#-軚#~T( %P(QE!)(I@!PIJi(@%Pi(?p^?CG^y^'UO>[e(;Zsv/XQK{1,$K v#tkY⹌ 6p@,;A=XUv q 5ڔ#+N^kM?SG>VK&R`*Qᐼ ՔL@%VF܎s\m擩RW lm3?׸V7mEXЩ8?_V*=z6 /rrz_3k3VG=?Qƭ PFu 艫[˷PBNu/kLо-lvvpTơ04RPh(4Q@h@ E (E% JSI@%)E(5R?UnIFC^UX!$T'FA^UB??dKb^G"" ؓF[w5`+b_mދEQIPPPhPIJi(4RQE(4Ph(@ E (E% JSI@W54<%r]Ì(?5(G>[Dupّ-ѳYgJR{C0ʳ2%̩ȸôA3p9*OV-N!D] 741p2v>U<̓S5԰ɸã\8;Ak^oc=E)wY$oIP[~g@@ >aٻݿ%x<3涨 Vb] bg(Cs>穬E]^[/E{xD(K u@ t鎢/å7\CR٫Ƞu d3>v˖rpa{r@k2@)MWM`Eu[x_txʮl 6u%(u\0ch bMq,vkv뎿Zг(-9uKgu[JsϹr(֫:3sڿSjBO&mAo_v76.?hڿS?Fh]m!ƀ76.?hڿS?Fh]m!ƀ76.?hڿS?Fh]m!ƀ76.?hڿS?Fh]m!ƀ76.?hڿS?Fh]m!ƀ6.?iKleR]T vֱݶL-!ơe9''[_kZ5_}?N;[}?9-T%!PIA J(QE! %R( PhPIJi(@_άk/M [׭'l+ռC!oѐWD՗y%RؗȄ"]eG" ՛FKw40FR)(I@!PIJi( %Pi(E) QI@J) -%^j4<%ro]zG\W? y\Wi7~֐ّ=EaEPEPEPEPEPEPEPEPEPY/DMZ?D㸥n?5oCT h[V?S𝕿JSC@RPA CKI@%)EQ@ %P(QE!)(I@V+uf_:h Ofn?d?5e^CFI^jn?d?7e^CFIT'Ȅ"]d" ֛FKw4HIE %J(QE!E%)(4RRJ)(4PIEJ(4QA %WU{h|w Kʻ-H(7Q?:֞{+#@((7],I2*=A#7Sw.$xwa2A;9U?~ q/}[vB춍vya6Gv&>^zwZy]VдM"n1_ݚV`(U,Qd_|h.nӰ$[6(#'r<*!Ia6.oeϼ2X ;U(B#FS5w jdu|(V>itU-қsIĽ7>sǗ!cgZatٹ۝ֶ6<808 -^]Y!REvFRp@:D6qڌ-d,$|JP^Gco-aymY [p>KZe#&Ͽn8u?־1ى; &i+v8لȥ^RW|뀼ںJvro eK[h_I@M .rrX=s:Y-˗)f%v._7 l^{ѵ(B(kfA-TwBǝ@ ժ>=9?޺{CN쭾TJ %P(QE)(I@J) -% J RQE( Ph*_5Z?@j[yO אђWk[yO אђU-{)`q+Zo-ދEL_ idz/sD)* CKI@%)EQ@CEJ(QE%)(I@%)PIAU~ yǎ y\WeQr^6XS:Zˈ w0HSwGY##2;ִMmig-ǩ?5OԽD(kST?o=AuA/vzg :Z+[Qݟ=MR[=% !q܌J_k6ASƱBq1n0<0n.7Y xOY 긩ZrPeD5ٛvu|ٜ߾1.4Mu6f~ݹr66g8ﱳlc ۵_}U?o=Uzܨ&3wnO3[?61&۷;S6qavv?zjg-ǨNOQ4Mu6f~ݹr66g8ﱳlc M]M߷nw\͍-lW,'_^`4- PXزc*V5,̱"^ǩk~?_zj_,g(N.VGCEsmj/vzu}P՟r+DccT?o=GƧ?vz`:z]7_DKTO wW gUKd9N4䘜c|h] լ\G.٩&hi!/|=k[DSjj|LpQ}S߄-AaA JSI@%)E(4Q@h@ EJ(E% JSI@%)OWW?@j[yOYאђWk[yOďYג*ĽFD$87Ek&?DV2[6Pj ) QI@J) -% JSI@%)(IE(4QHhJ(4RPQ7))dP1Y#  մY$V-NI0I# Or1Kq #sutXɴ5'a/i1rgG[?WAU+7]v5,;o_tmvk?s09+7K1qVn5k9Y$.I[? wJYݣG3Tr_xxukC/haʎO\\ IݣA tA ub/i?s093xՇ[o*o_ݣnxVnQ [ݣG3Tr_۾+:ߊJWel">+:"vhݣT{M346%;RO&*b)Z-k) 1@ZCEJ(4QE%)(4RRJ))M%(4Q@J(QE!E%^ҿ/V*ҿ/Mnn?d??9e^K$V׿7m^2 %ђU-{I`q+ZoދEL_!'icz/sDt %P(QE) QI@J) -% J RQE( Ph(Fi54J_J +RP^BRWҦWҦ4JTƒ"Wғ_J@y+I䯥KEE䯥'-})c@H?U:I))6?EGl B/{S4 }߈  Q|i>)ol c@H?T}߈rϽM{  QA~"@{>/N  QA~"@{bϽKc@H?T}߈}i>ؿ{R5'l } _&MIA~"6?EFE{c}_&  QA~"@"XkPkc@H?T}߈~?i>?ja$*49O9A~"6?EFWO;^Mika$*>c@H?Thoӵv9A~"6?EFUG;^Mhk_a$*>c@H?ThO9>jl S?{r4y[a$*>c@H?Th?<ϭy}o_&߈  Q>/I7M^  QA~"@(>/G{r5{6?EGl 7Mkϭa$*4?o9<[a$*4?9O1kG6?EGl }/_&1kG6?EGl }/_&>/Z_a$*>c@H?ThfK|{5A~"6?EFe}/_&ϥK֧l OIMϥK֯l OIMϥKַl %i3/$Mk߈  Q|_&>w /Za$*>c@H?Th9%h$Ml}߈  Q߽;{5A~"6?EFboI17$Mm}߈  Q|_&ϝIl oI?MϝIl I?6>W '[a$*>c@H?Th$h?^$Mn߈  Q['+/a,[7c@H6?ENKKHY#GRYaGBh0׭ y?d1-tE5$ Cr_%RؗG%<dZ6ofnu r[$. ch%IJq@a/;J;"mXh2=~e>ax<N&>,h+m+D̀DfaTOU<_g {iñ'0@(r;A U<Vڈ]]1@]|}2Rv֍úvw0]KrCR8V^tnԵ'gcٵ[Kq,B02)ێ2E=|g+'.AiKYN.1MRA+?}u7NaJL]߻GbcZXu8octɆ"*.9@jC6S:|rg"f_!]* #iナƽc"4׊Tyf][FU$p8$u J Q<LlS&Ih8o[ifoym{#g9;]*O`)d28c#h\pFsۃnj4SoN6,giШDzNJ/-׆5u[$X'Ԡ{U(Uhe๑㞀.Fw>w,Mlɕ D;g[][ Ua{vmmVYDAv\\Z[ 28غg;qڵt )M?cKh aqs/$AP'zY:uL]j7C̨&Ird]5"ŷ-Qivо#/ m<*[+ * ;H]=%O4^T{l8duǭsoSM>U:cDӾЫcEp ^4:m<:]6KHO^F:u@3ų.$vv_aӞXw>tL%V*pAbAo[[_Kes3ߥWiz3$0q=.^ֿC_ )RIZm*0N㎆~4KpjvH$@:*vb4F}RP-e eiՕ6Ș#`P'{y7{/dx(KN3Z?!|q_ &(kIq Trrx5jŚTdFdp:UivRA "|3=$XcYD,sn!ApGN]tBpcX7y,3̄'څ4{O֌ag緒5uld.:2{]gY,u{->䷖۪*F??|+2Zk*X ' imAj&wP g`PI浵O iίi{m  ̇xЍގZV6ZmiF(i/󌪙Bvwmk[kmQcpU@T. '<0jmG?#ِ0#Ke\E>\r'z99ogԞ+ bk(Em6 `/K1&%(((((((((((((((((((((((((((URŠ? yĄ#]2J T-6$5 ns%ђV!GIoxn; b@~e*#E_ /?q>vffrsA{7^) ACh\ΡO4i5=w?`t^׊EgP?"?3Sv On}fb׈GgQ?#?5Sv Oo͹6nC=sZ? AGhӰj{m/?ٷ?`u)ƏH j?FSn1|͹\֣O4GkQ4sA7Gm/?x$z =sZ?ѧ`۟ _0?n1|?#?5S)ƍ;fbsA7^! AGh\֣O4i5=6n:nG=sZ? AGhӰj{wu/?'}/?x$zu =s:?ѧ`ϰ\b _0?H ?G$zu Na7?`u)ƏH ?FSsA7Gn1}|?#?3S)ƍ;nW?`u)ƏH ?Fbbӆp1|Ŀ#?3S)ƍ;Sn?1|͹\֣O4GkQ4sA7Gm/?x$z =sZ?ѧ`۟ _0?n1|?#?5S)ƍ;g\bsA7^# AGh\֣O4iZsA7Gu/?x$z =sZ?ѧ` _0?1|#?5S)ƍ;g\bt _0H j?G$zu Nfb 0OH ?G$zu N\^}nW-s:? AChӰj{W/}|>uA{7^- ACh\ΡO4i5=_`te[ΡO4EgP4Զw'bn}\ΡO4)ƍ;fbsA7^! AGh\֣O4i5=6n۟ _0H j?G$z Nٷ?`tfb׈GkQ?#?5Sv Oo͹6nC=sZ? AGhӰj{iG/?Fl?x$zu -s:?ѧ`\^K 0_H G$Zu N_cw?`uk?)ƏH FSsA{7Gخ/}|?"?3Sk?)ƍ;n7?`u)ƏH ?FSsA{7Gn1}|?#?3S)ƍ; SsA7K _0?H ?G$zu N`?`u)ƏH ?FS>sA7G.1}|#?3S)ƍ;}n\b׉GgQ?#?3Sv OmNr'EF|Ѐ(%I__J\3i[Ck.\av>1]O='W[PFQ& # endstream endobj 82 0 obj <> stream xĚ؝Tn%R$wǞVu37ήq:({Kht4V}A HC8hR[( <~j SSSwЁ#C9-G}bSo?SD#Ǟ5BZ8gC 3rdpѽ GhaτgjC<>pخv;}[vо.exi|1h_O#Nw#{ܱ}`֝lnO[׿8k۶|-;vo5m`h]Cס}5;~zPY{A:BƊt4|F`8uSڿm{ ` fonl8<]Cۆ6{ۿyK_O?y? 8׾g[^o/wl׻Þ]xyhw ܻc`[|/カ+[+om׷l߽wKa >{Coܳeۮ׶ @S/:ij˶عu.۽w3[3mwfᄎfXKӞfFL{vA 9L=rtБ탇xYؽom\b`ڻ& Z?r9f?g0m{ȣ_5mݽ< 3 j_oZ p蓽M[Kf$3A_(1r?}/7du٣yaxᡑCoiwϖ[x{;g}2uxCV!wh/Ql|h߫'v){}=2}dh>2kddsshddhˑs9}P{=zX?J嫛Bb%:O!38o~=;k9?~=?6VMz;Gf^4:: @D"J0̭[B_\6kz{UkuFW ]Z-U/1:ZN^1wkFZ+jTЫ TkM4ީ]+Z_a>蒭Y#5;kj{^SZk5cjUzZkuy>W+OZ+--> c\rSJXkau4ubUS//%}ZQFW*j)Y)DB ysY7vd(;ZN'mT҆mZRvvYW,XL+LCJ+\SrU,9D OeR. ^*KZ dĺffR\RT*AT'Mq) d½V V6*p1$ Pʴ'{ BY)ךhw$kf{7VeuTN֖*Tѥ&ɪ$ס\%eYi5B]&>m~8CZd5;r]RBMW4܄IJ&8Vީ]E[m7/x VlTx5f^u֞kswf[kzZbF UjZfCl6$U-jYUjj 6Hj"1Р6koYb^+훮錾М C34MWu]5JV [b5]_ XbhojKo7kC* f >齂oy%ѯhL]gkjez*y䚕OVp*hcF@bMRz?MX&Y>^9=[zOF]ǸM-ǂK^o,8֭v-ڐ(fWhlA91LNqFJq%Z:/kR((b]j/UL[y9"\07Jiw$sHI!gВ\M#Z rsCbyDԪ.T j*lJF$=7tW@,t"nRҵ*yRhtLS;%[nv&鲬d$8(3&F_|[p_]]^j~{16Y9l=Jy\(Opt^eK:_1JvK <RgAjU_5~R5"RVvBh=.ۢpq>T J˱ƹ]2'+-0%5[PR3[jp% -0| 6PKx7\>&o^>ǿ鏏?q׿|_OO=3X >ܠSR$}`tstk3n8/FO~ 7&ޟ7?ԥ[gG^=yw6c:t 8[j4[pp{l|ssbG/~p.{'.~tfś箍]3ymjPt>y)6WB-:hn!UR;!!N7-*/~qM2S=2eAӎЌ#)w PB$Sd`JMt\Q޳8ɛ +dW9Ŗ Ќ@Fv% aqƟpeww2wmen%xCl3.hΔ D2qTTՕbsNх=|SҲE%zN&sдh^x WI 0$kzSlqFu\P dzv%Fe\.e,5M>|*aKcP)rۭz2Zx_r2)p2˦ $Lc\$","ƙ'8g_UfHH2Re%/r>Oz&AٚR6!KR9tCki>q!HbR8CO%`:$jWdT BГėښ#ZOSuOo/\Y5+ TZdJ:#10"lNd`M;5}j@?࿥TPIDHHPAi!skV!>a)+ebvuxRo=6:׍jwsjt/\Di#-Ѻ71S\AaXe WJ*z0Ol&mbvUWp^+7'JAIri4I~\[*S|k+ BU+ߺ<:Gj.o9WV3"ܯN;LEwHx@B-mrW3$3w+_^I$Y)'PL|%OO9C^Οt1O Oc- ЅTEzDQH_|՝9+R;T]Jfk9eU ~k}("jb *sEc+w'l[3{3yi1O墬U3k`(pHs hl+Ń*p c]i=KjEvgt)-y~+L{`ޓ(`0-G0@=(*|5KT2-^8dl`XNB˧=s.3qn^ ~pN}}ѓ7޺x^;WF;8dim쯃# -:>o|v}l{/:qOΌ~p".8w;>>wę+w>?wN_U˹nL?Z‘16@<ps}z~?:ӿxo>9'.jlv|MR|$oD1ds7pj.I'p9:_/x'!fs)O IsB ^# mFG /2Fc278j*OǧRxl1wRXg)$""R-%H·Ȳ? $%#~F&hOH0XqYI-{3}gĬvHBh$L#iڟ\fQ`D.p!.f3,ь.Ɣ 4BJ)O/y7nf=ь(+BPVvI}'q#p"X村Y3 ]&l~ ҈#p YF0,g 8{ +lZ`ƓڄJckmK3"siX( -azZb @)줭ÿ;Iv9eW:Y0ZPD/rf4MT2SĴ;4f^_Z_࿜Ng}{s/|'bK=:9J.b`4 E9ͱ\}ϾElO_yջSm3G0NQU)Be-!2 #6.#\&/zc8K ]<\07$²U'"?_ٮܞ|tfWO?w~ąO];s9' 1f`mJ2ȪHȶHq!(x [dlw=62|um+%rAJD&ڨfd*G g)+qZJcVtd3U/UZIsL_K^N^J^L^xcL&c3B4&Q*s,TH98dXׄ(HX[ks]RJ 3feE͔dea@ ~EfI<B?FP< )MYzA 2o2Fg$ o: czN.0-C3l` AKJ@*Ynkf5/["ՌČ'3~/i0 _ȡTKs8Dg7FXC79 l4ycY9 (E>AF$8H=1,XfW;FZѫE-|{5a1j:<\Z-Tԛw'$b BP=Y '"$CHj݇rgƨ:F12|b R{p~oNKU,C\Eg:JPpyorkf9÷ |ZN֐:FJaR=͗b4TǖEwhg0鋱J$|vi HlWѸBJcP1\9` Nw:# NT,aYnIh NUk״dU)$ah:glԔ/z~?rYwQ&K bV*RPb]/7Z*bA,W2)nt͕*Zڅ.U%r(*\%;=o " ʖ|-eѮb!h\!ȪYQ _<'岮Lr6u_ ,}<Խ_ݻ?wg?ӟ܉tG.O|{/3 >&_Q,/eohjrkrԅ1wܚ16;>ks]4?+0eHaJ`-/ɟ`lԒΣk&/|uKK˯],"!; '2{WLݟq,SLU$P+o`) 3,h=6tݙcP~N:{:, mXl^)^ɂ M06qeђlœ*"Y?]"1:(~~"qn<~qa2f[LP0$F:ODKu|w3Pb1 MRa*%@5$caU͐O0WcK1{з31"V4`1Fy134BGј3 & kIR_&9L~%pbv}xeLI;A27C  d䇒l~ҔI2f `0׵Ȝ+2³T™y7I[pQq˾;4kO|8} 0cރJ;Y3fT(JIf N0k+r T3c~36FxL>4W8b%ŐH@ wv($z!0e$ޯM9R?]Xh~&tKB\$-l)W2k-"I1Vnf 3z'gQRZȗ7>ȗxFR|( w{'_3P_$E4π1U?1N|qmqo%&c(+?zi]#_>h|(h$~Ke+Ǧ-fa`7ƁS9,E<$)e9̬*ʤK eCPKdt)T-J Z}Ҹ!Ԭ:NxA `o8`#M, u 0VJGŪ *5e.*ZuNبˍbӹB(+(v!FOF5Jͅ R\iBAj+Zuhvul1p^VP֔V,yхt\ـ9Sn{i//\˩/stJd2E^RE/U(iS* ]/'V+uQ /f\<j=g\O7q7}OGåsO._]ko?دlSz'Lr3/Rp" FcWTǘu.co0FacTcucܟuޟuL#"Ŗ\0-F8Wƃ3W31Rv3&or@J⬏pf.&F.Lύ.>JXȎ9r~i)ZP0ЅJ>v@8`& h~(aJ)_0RB-Wt6ED`[7/&3:-5 76~g g =ƨ%0cIOgcPDOT$AӉ`4ű>c0Iċȳ&-<9lJE0+ۼD$_MR+;z|A>qA D faƚQx4-ay1\JA(?.yb6OƓ*j@ s,3c¤!I)\Bʼ-_ϟf&c\Z }1!AO/0C݄=0Q6F40/! ZBZ<džC[x0'ZP3c|M:1Fz/*(B"#`#吤fb & t`{0<1,[%f35W" 1ZXbjV,'1d<;wvo $1:FtȈUT*Z*[2I=D0J}sQ1a~+E-,6ͩ\ӝӜ9R_4vNL|+\T2fI__+JU۝4"]ӅjL,8ɞ\O1 fH\)0E%/rMo(V7ZVBq( ۣ ś.Ϯܹt{mqmo#~!M R1pؕOx^ǀѯݏ.~O޽zwN:lMXg q%)rF'^uKn^#\%0\:9Hl&n삕GD03$g>ˢmX Jdq^VE0bQ[vNQV,S&lzc36ÀLz@uE#]U{lGIp+cz"2]ӳ $wlf1̙ lp*[dz=N72u\]' @7(5lUH:xQA{)cs9(lMlO1ct! q TXΕJZ;d1 c%VՒDPXCS /;Ot 4'a#F<CҀ)9`8B<_@X6s9N#ZA8\>\ɬe7B8 3x^,QR*0q>QD‰? 3`zcpX 7 peaeď1nJ{V"id(|*!cW crqǠDd c)c<S?F֘x3+$ LCČYd<Ō4Vҟ8ݛ4] qx? M OBc-cΝU+-K:^?cher&p)Q,<{w7b۱TP]VƹY"tfv|P\|-3E:U) !ȤZ \o؜3B\1pZ怵^^^x3R1(61K#Hm|6ྷه6<0 v^nfR]Qh(vJsfiv`z7a ;c^glbp%WWR+\c;MoZn$%%fn5!0`S?^ "MOwۺmiiuM.BBo1]:xyj7;o//}[wZ[~w{7M}+?k.rԂH\TҲT*#04'h6U@nlǗ7Eo^r7g+9XluM_6/F.{Eh7n۾r{o\^X|{;d)Ybs4敠BrK,ۇeh$o۽pkK t I*_>\{qa~ư042|dH> 6效~~-[Ym#%%+JO4+4O%,zZ11[%$eT>sCLukJ,8نh^J viSMi\ۤnVoK1n=-dγMJzf6&}AI9ՀjtUf.ڬ YL ĢN1I6|0z's1uXa.Z(VOYл^&X5t8 Xt^P$tzbI8xR]PJ U˵<]Ó**U9eh(/j BRTܤ%lԲ2Z&g*|S|o!GHBTkG"!TbRP#*$0VR=,mrςmaIB]!8J 9hխY;q0~MaJ%A w n?`_UXH#UB5)fKs:~7|Ā1'1ofww0ڒ}P*bXVe7Ԡڠd 62ʘ|t]t=N1F0^oxnnZmۚeQ}tSn/NJodnl>荰4cz4f{tXUa,e'~F>Tc꾰ߋQ~5&*]jvj.x~ ,D2=nǰmݔ5)eYJI.W(ߠssw?ZoW~~t?䒟3%&wev`S$ycDB8S;Xj=X9Az/?Ȕz! ?ae`| %(),)h2w+ +;WvoFm@caHU $ՅMl\[?\Z.,|zm坥>EȠGI_gz e3baE^ލQhΛmYVci*&_cp?&c4M\*0CDuWW;UYlHTԽ{hu1 ڝ(c݂l)-Zr~OJGVJ2J&5o0-h1,%1c|z煠DLYӄ_A`hwFxhi=O^0A C_.Z& &[Wrgu@6]$o 1ß`z?pxGXt/kt&th(D55뒕Й28D:y&U'saE,ԍ R0𪸘a$>|)6&?y6:!h 'r֓Dܭͼuǰ%ᒐ1~ j_+j~AߋЯ! =6zvHśoWǢCǁt6ǎ?R n?-nzNwlț7-8>nbA'0SI̹TPk%ͽ{;ҖPlhv9'Wm׮4{v DO끍"Wb>2Fc8n)BHI5v^Q]ΧXy_E,;;8;w4{Y!y%w.]ץ- ۚеdIP4FT(F,TTNL UH|ݬqpEHݰT-Č;M%!Z [1Tmze֬`bJMJS 3tB%7)Vke^߫+Tu95N1t'J$Rl6esg/UE6\jvw>}GmČQ+ߊDފF0FK"lnUş G|T׬mw(cyW&OnI`e0~p6uoc%*GTon? v:Vj0. G"kG1r ˷_D^C ~x\u$Gꮻ.mw֭;-g}MvjWy%[m, :ިc2v٥#?@0 c8&5M+m%0 xuOg3}!M]ȧ/sZrn wWtiOWRVf`MɰlHZSuP-7ҥ:L7g⮠s pIzqBoGMaJgǧ8*`*`OhjVJ@K m%K{٥䝍nj ,`=TbI2#1g,0ٯ%g`meYa/rACCevR㱺[31 3a2E1ʼo隚Eq ilgXbn1QVҴ^`Ь6 <c`f_ -0|\ g>FNDDW֙0FgDc% |1)cpU带u[u 4: a˶):p*2H,5$& hؐa!|i*i:ل _7Og;T{ 1WykD$+YUNhrTw 5a9ì6g8t7i4<Ѭ3a<𤆘 gMrP! ~R1T%v%'p[5ѪF qbh0UJ̤XeRì4) eV;bjdDFfesŒ21ژ"lj8d655o(N# d zyYB;Xä69"c#@FbƩ7yƘqe |7݇?+{g} W'&Ǔ2[>azG7c_"5޷ ׿ԕup痯™!i '?+0CK<>_05FKʻaojCm* .1Vtz$Ч͞t |k , tYFՈ0)ck&kH514+hy'`auӧ./ r\ep3# GF!cqу.i`TGit{``$K.ٿD~9Q78GGщ?~@Ktϐz~{#y=ڃ`G^%cxgcݾֺռZkoN"WɦguqT䖁15"[.kؚa AjQqWWEfoaj MW^-_kԍzCDQe]\mC4&,I K7ET!uA1[rH~2< ++[(1P]3txD oIē6LGHYZ*ԊuZhW̒-hEa%`,vGE~2 -7Lx&Lb%$bZj_2zRJdi51!*<c0 !c̻2X 0v5s 0㐒4e$oe9E)ٺ^Dpj24]ԗ;GFwN c`/+qDnB?=NǹVv"l>ԪB[!]'+ct^uc%))2Jz`)ʛNrϔfЌ(-˖$)hh1%+Ȗ ++t+y Y_yӦF >a{$+A1YŤURk(;0iLG0p Mc߃?N}Bז/ZXY@88{] L?5Q.\M`d$acT< v.΄v'X洅jհȰ*#}2h"ybF)3HOLJG쎰k6GκzI+-0L`\LJ[0FG.G ϿYNckZs$f@G} V@<ֶzn4/ Vp8 Wa`ʼn f|z3_|sp aa+0ö ˎUdq}&~~k7L\iFno&Ӿ˼`tN;;"?۝ ꛯNƪo``Cz-9ڇnL cz~A- cPꊗ_}r 䵳%?:gU." I3n`5c,X@rG1rF"*Kg#gVpdGJp!fK8(Q҇q]/~`L665=șeWVD~r[0ʙr=VU^ى3g޼ųg">K^ߴ{-^Oޣ?j`a1 _t6 sK/K=ފK~'g~dp>3|ZV6_,,[Zj rm=].5SNY|ںQ`mFnb.Snn{@o=y||Ur4a Łؒ`%=Fo*LEbDJ F1a\̏r%Tũc!d q֐%r^$LdIl.Vʼ]lJ^HP9u_t6O 'VᅉDi#W׳u-CkFkYo% tI3p{L4y:H-GjKsv Qmo.8<ݜOVƘa ;a I&!l0ƶFܲR]n1vۼ-bf3\NGc&4&S|hL,9 ׷)OY>'mrFU5.V04}C6mSOf޲iawvo:>tN^ m  v^|mb1,`ha]ew6 -\Hl:2FF' Rdf^=ʌ7$h2T]X88 YW(LQ]:&,U r X{C $D&)$a:I; L|ƸrJ8 bZ}o|c4+U3z/wtz(DgIh>\#3tbt3q:7|MJr<|2F`0AJ-Rp5sJ=X{=22]T7: }Ę0D@&F.&`3׉7#=kaOCm1THO|3 2a/> A{39{H*vtgJ{tHn>DA:#&#3 Ƶ`L2VCGx lr_G!qwdq7 %g$ZFu-.m$򽅕b/UV~wߨvL lJ74^oA?VX51+=9ԕa_S+ ^ANkvIhWvUnӓBU,Tetg z<"<ifP2f SgwjGUInR,+D}1p sDZs(+1H^ +J^=.M1[5@ w HWA꼤V$Pv$M :h=j1>feMbo6Xj[Bs0 L`>4͸aڮn!f0Jv˲6_:C7b?4Rn=gйZgf-nazjHj34H5RI2IM| A`ԑ‘P ܂cHĘM6f.fAN!!= rSЀIMk:n#B=bЃq^Lf3z^\ Pafv# B *E=h ߼CXa՜!><ۇ*n%ɂ)cT?c lb/ F"ݐY+H|Ik(KB|Osűks-S2 Qx1>] ƨz_E}:ߔ (KQt_%0QƘba Q0Gŗg~7sb0xHؽK;;Q?7;7{@CO6'(~'H™Aՠ7]h6MBc*3hD0N5FX+쒼=.wyRrvKG#諸W3S JfOeT8X&%xN 4*E9'd1{Ts =X(!-kh 1Wdc4\o|7. .) {luHd4(GD"ՖU>xV$-8f,Y# T`΃@*>ٓIҚG\b| IQ},^*X*v9rp|7D(j Ӧ>?9F@cG.>!#6כv0rHl6!h;i*1Bq) Q5C;p>XoWskGsυ;hnimkPƈk{PKq>Ͼ;1̮ Ktiʉ%ĎGCk>H3Y @mS2y5$!!31]nQ901"dʫ)o8AA0LdʽY{T-\~ThOI;QMk?+5L;K5uu$8 ZV0uQmp,&S# JL1>1 aD>Sݹ#TB2h7)>ER:^u\סlaⵣҪ[@'mC?fH0QcdF6UWZ 3lJLC ij.d xկB %G-'R}4^Pi@ezga Ycu`fȟd(1O9iNúB4il123<&ՙ۱!Ix|P]3:i >d̆2+d'.JHS411ERX$3&\chO1~Iq|}.wtcnQ&3|#> rQpƊF+,qFz*'|q{aͲK C|4TA-B9%j\cXȌh^MK RatYnsk}+Bced(lp#GX6"6 PRlS8) NN` N8eV!-}M}?ݾk^:=- cmG`ptn7Dx "1DPF* p >c0ZzD[ńe2\cYѢ`04o~uhR|gec%Oo%M3Җ]f8aTr( 4:) 0e }4 `*̝J5 ؑtKh1%LF SQ{Čb@%?GFPcGaҘ 2bȐeT?i/93t~!/|CNOCjr]R$t=<I|+7 UL> xOx'=nOs#_|A֎hvձ۞` @ l( gF B#7,%OJA(#70cMa370,ȒMr$BX4clRV\] HTd/bAi!ȑk1<Y<5)ϽN!dЧ5AB'c\^R6LEʵj*S1A< 5i?ҙ.L~YcȔE8B6~5p*Bh's|1CaFK[ޡb1 rIWpa^h-ovo5 8 SIl8Ѽ( ߺn#Hj}O3"EF2 Fd.\DP4kiSj-.>{&Pʔ#}%F "܉Q3>P3;6cYuuw}Fvmdx< _ɾguwh<\V0ܣOFwAI :RwAldظeSS :ccGȣ|JsӝS M )7Q|H¤1x`1Z(0!$cέ5F J)cTncBi?-GIJDOuIg;6m5~])#CؾC'1h}=$g 3AR$0J4F$F =Ֆ<*.ErzNꔚs.w}Z4J^8{rjŪ {JI^p7Cr'UdZNn31[ulP9/+D Qh: j(dme(DMJ_hD1",0;wZ!ƚ ]\ ex%T9MLr4`HM'kABB5S ᴪ94<cja|Z)c,묅DvNJ0eY0)@Q 3bmP'=(0bL]`G0'c\@U%)Uď@)9C9C "JHpHDHUф?4&"S g& @#F)gP֋EV(hO@8LfD-R#D1FŲѐE6Fk 6ʌ˯8eV]OsiqzZV7%ڮ^4hwy;\ދ._ ـ7U_4 1q}~:Tz t^ĄC-u*)iO.GAiC~p1-1C2"뉘hegl,0=cEUI?PSBPj H\PI!S $ DW `S_H=زqwVON,6qZ位+}oZ56`{_:v9x;̅؉%d>9|zz^L].{J sW{$30)RZ.2 ҠiP(F&A)QiT@em9 ianp@lNƘi{=ndd'a=N0)G45F#Lb"֑PQ t^QUa"I1%naH350ǹ xr]`-F2c2sL)SHOWjDp6jBB`uGNrITZȌ8 S8|Not/&Ny);\S{@xª' ifݥ+שd@VLQdpHl*ϽkJDy ; H4p F/CGʡ`&#e2EUlWQK9C g3wѸ]L Ào 8lW7΍Y/Saj:kF*9M0i 0i `;=I`xX tcYY i-@Β23;b @xa')Ay>[P,TT?uw]1BM`$FKvdG&! fPF=_w~ y򉍊`WFp9Z"Ї jr$*`zwX88Y&^'F4M^3]iX0U%˘~ Dk$U d R$uqv]HzN"š/HrL ]X=.ƶ*kH4D b%|=n(=&S6z5]oPQ(O7%'ݡ( Y#rAFDE0,#@(&(E0x@"oHD< pqDt H? 1;ACu+:].AK@ʪ{&UD-_ud"p ];778v8@q&vaΉq#܂a$K"E&xS9҈)5#$Q^e15AbLɈaPwԣ<:%= gEUt~tVD~)B {h5ћi8R[Ή\'!?P)Zw#zEPcDfdBT$‡ xpP -OiBV̹O1Abqr)Z `ߔ5/$;LA%FHAu$pD3*i0,gP[k(1{8MM9)Ť&Bxj}ؾbzWRQpbXH rm (˚oѣGzUfHMr\c\(R#jQ%Cc/.W;%_F1ֶc"&[.`{LR,<&^#<&i3%yLi"LzcR:1ygDŽ[k?QR(.!@QKPΙ%Aqy7oJAJ 7!_ ̓d)%/|E׍dCqLq!Bty ߊ P0HAkPw@4_0Ĭ&-LPbJ5AFJL[ž9sBVi8OG3P&O5jU` V $p5bYԂ mWP 2d%/!R HǤ@XTv\#R 2H^}8 ct$.$\@1EZB)GsúưnvϑbP.*jF2C2fb3:\E7)ֱh0ip( 3 HF0 <ΈOC2OiJd9]'zT* va1<0_9R2fLbZc\ h~,!!2K}ګC,vu䱒_!8M(Q C*7ȣ͍IӲA@$B)Q#Kz0IJaplOzhpW+[SAYҌ/6"C33||"LQ";_y.b;<;QU3n)䰾ޯ/I%.%Jf~ok}ĀT Ś%%zPQT!&5A _dӰ2ALM& 1RPA”QV,+Z!gF&-#4ĨUXEh4,"4xFȌ=kVQˀ iyTb)J !.嗎3#4 Hc*B+Hcxp.Z)GkpgE4A-1%>M# wsBxp"a ]/h\ɽ(#RiE  a!TJqX?.bѮQ2\<<}-|LB21I|/2q㕈02='9%!BqR˜G1&r-+rs<{ %|ܭ"7z. kFu?,wZ"IϷ4W^}ަ˱v| ?k`n) ӊd7LpAUq_jDQ4/bE0ˡ0ROcD3)t~@,uD2U1#1+76c0n攻ոfYRjz3~#BBd@0HwcT2ET2DP%&TUUVu{9B9PẀ὞0u/)C2!w9qFfƈ'ӧ%7qC#ܼirdixDK.4w7iSq"H2[3٘VL'sd9|/PtNj Ot ?Mc)Fnf-I5㓓 r4m=ĭ ͸iMPa6"b\ʷ 5B$Q<*b@ÖBn7Jˠq0=:l @U|YbL|xrG TyV5I٫.raR6.v,_n'%^e\xo !i oJڅߋRO^,p.xÐ5Z1qf6Ht#:*_}ˢK-%.9&5T(dc`룉~ODYjF~:x pie#7 K1{4'a@(޸iO2YY9|3ѳ?]y~̩qs?;'/{xe @ 2 9t삗}{fO{܋sN$--EǼx}]/=ՋsٳExV.xΫ=a~a~fx=/ógu=^' W1 m2]==ʕͤ0(zhu`,g._r鲍M5`1ny_8lv5uwI/Js'.G/T yϿO< j[g%σ@΍T yϿ`M]iKZzƦ L02Ln< =go!Dמ+i&a56ԯkA&=EI):cM>TQZސ˩r{Tlllllnj`xfKLcP1i~tkW'K=x \XSˏr5|T{ZYno{kNbפpiaJM~-66666Ӂ _Jf RzYGt[ =l$s/ԪQUimgiz.5gzW=}χ)}S7L&~\uJfGyg=CnƘ#!h!aQ׹Q5)?EYTÛֿ{Wbm&9U#Ǵ\U-~^opY⛃f?mq=ݶuş^Xy(>z &zy57OwHac\]焘xوw%V5[GiM,G׽mش{9L#'AXUaҩ?[ɏVGկl.;G￰ t+qA?'*QlZV wY^[L[;PTGTzjh/$L0̞;?e{N֤rB 5U:E*ܲpɖcVG!n޼6fU4Vش} (%k)r^q,˪]0τ }^Qӷͼ; ƴs$~|N,12I W/ڑZc^cӴM,X8,`-oKnIXVv %1*?mj+.*P팖7&_^Y.[k=V:GƝB#2-#[fgsڨÛ@ЙZcsa_bڸ&;;\zYUajk[Kw^-#[;LF]غ߮V&k(֯XTX/[}w+=):UK'j666667)L0<@T3tbI&0̀\.g =59366ׁ֕K]հ0dƸu}x[H칉Ԙ[eEhz\V::y)Ǔ8s_H.v]bPtPcsC&#@BGˌ}vk;^^l]}.vQJ5F+qC⍮u)/r7f5) x5Mza{}nK,]b%1I 1~#IfG_168}_+of,Xs^WUiWoeu]b[Ͼepw~BO5u[eʕ+,_wmiiD"8> .Z5_}H`䰌z}tF;9{u-˚3Olt{|l`G(?Ej?+}m;xh(r+~12VOZ+[hadv?Z[Kxvؼ=M}.XԪW]_zls=IUޥMV-?zo}{kmË7/^ppUrCbɍv*=C]i|kƛ+>c)%VvsαK4/.v=)5'IfG4F$| }w: xko۰铡 k=?ϫt}խ[-7gpm.vuwt^lkKl>og,]>#6(?Bx0}mZ5k|ݬUTKݶn*ÚZ*cYV\Xmhhhի:<<駟{ˮqӦM[laanذٵkWOOO5_ 'L*d\XHaœ3^Vu~5Vr''Z~|W?޴}JOq]z曅oO_Nݣ(J-BЮ*5;{{{-rر@08rJabɂ,$.wC~Nbc:?v^]l;x=KWw×~u:?_g5&2_쏤45EX1v{[ ej|/UKl|6Nz1O H(wFY]e#5z[ r}_9e[sG.3{,:]P# Kt/t>?lx.gu[|@kVO&%ΜYf xAQ Nga`ҼC򟺾|[˖-c?JYu,_y?_ {U+{Ggʳtwiu#io_ bZ_366֥KV@G<}L)h6wWtuCdw}-G.~p bW\|+{ky/UKl{Ǔf66xz8@m3 {={XƖv4Qch$o tOFz~ꪷ{ Iedncg tm#9} ~SwVr>}*?,Ss,$x"O;VYY):52:>.]B10@yMھv2JqqqH;(f/' OrQxOHocHNWOU+^  {P u RݦOrv}훌L|)\rO Xvτk!24'jJ,2TUUsssF54>S]|s'( bg:ɫ4c˿TL I͐.%8o߹1x}pvT_ϴmoiMG #`1*ukq d62zxʹ{=ڸZ1r #Y}-%k3fLI$bH۷1ܛI|~TIuuu%3tЩA[`{*Ug1OWqIWzR6bxΜ9siA31 m`0 T`{`]f@"!NH38x$]<1Q@=ޓ@<111lt :G}pC^s_1W*^(,,Š:Fgwx9+ޟO}pSgS4:18+++I%6:!'kjxG ] (sz8(((){Aĉ1G8#;o z (%>.B2%^. c=}Cw%>^w gP! ]CcCG 9b!;71? h?}*擛^힙I(C.: b.ͥ})GV 7 s>Y\gccÐ6 fg4ŀ#cskI]cE7Gy174swT4C\w}"fW퉁JF!9|ro-{?$9ALެ[p+n^QIiդk)7sZkNEn췾tmU 1..+@*j%>>>22MZHII64y#O<Xsz___X4 .ވg`+xSK!@@6 ZP)8Zx> :$^X[|3҆ k† :B{ 7)lDc4/3>2heTWR}8ӐŐͻT222z(菐`?ܹnaJߜ"WN55cI emM%Ay h?IE5n=uP-">mPx@CշI2go%=\tߪgr`,rI覎c\LEUJjtt!D6 o ouJhqNFr?]e8L:9s`Q# $]KqOW~뫷:˛zwE?vڥ 纆 2lFn1YŒ3?}qՒ,+;842vwxνQhQUS\]&ɾ+IV9r4yϝt$Zf9$YxQG8SkBN_ridVK \#:::??jɉ2$ B @<ٳgDzd0MRJ.^!`;? <z+k `B@c@ A#!u tww]"CCCm|MMڔ~)xZ2VBؒFM6ۧ+//oŠqUAyNOr|h韢$n =BVVīN's3)z֭[~((&92V۞ϐ*&>:eQ0C߷@-w ^®Yv$yW$U8PHȧ-9EsRSDO${{>'8:$)559b!%e$w48"gop"+֐ݕɵ'RtM-"07M+ν/D;єXZ.ͥYY~N E5Tjx|e_mMai b+ fVsS8948=7<2 bv > &xkpBr̉#ZFmxg ;8?kO# R3k#ыZ?jQw1_1@' ;; v pG׿@\r6LFn9| &҉شA `u4qssmг1MRe@Qc@ zt " sFwOꘔ*_o79yacE]fff;wBcvoROIOƾ0I?x===;;;%%y׮]9{3RC>Dp?cPk=m)r˪ׯ_ ??wލ'K. Rg uA$K߆/-- Q^NNy7xr~mxK \uL^^ʱJl$j$N4FB쏬rBؗK(fk/-sח1xG5Yz%"LŸm*J̹dƛpRC f,"F=hyݱ{++ M̄"72=Y-cvihtT$%G$Kbs .[v R V8Wӡն9>^XWSYr?a`r=]M FH[c/f(H9g=wd 60AF];+da5Yls%O+xewB WD8zq:iqb+]wgWK7quh#DJe~~>= @/Bw$<<<44vՅNt(fM6hkjjXiQqrrrss/YT>lD@1`h2(4ٕ8 {{$Xw^;;;8JtƏMou7ް u(rO{_V%؎٧M'K% &H CHu}TLg >knQ9\?SMM;v1޸qn*j#$:U?&u@i8V ۠ mllW"ȥ@ME7#UgٸIG{jp YdXErs?O34:Ug4w̳qr NFbtB Jŀc٥3\UiNϚjCtůg751ʉhR˪C%Ύv***^ C~C8jE.`V1MMM^?fx;ʜ (Ⱥdݧd'=WGkpHQycJ.1 &ď;l.f$7@^Ո r A }.Ё&&&1bcc|LJN8(!_CRQ9Ӻ:ы,`G<4L nF6f@zgggMA1{ǀm8|\]]GGGǡ6o Vukk[1:7* KNE arCbl71P---sRSn/ =X7"f~*]BBB|bA\\C/ 'vaauӳ08=YT79靥zr#^?LMW5 W{I7%.QsMmZZ;vx7O:{ks%ff:z: +Dψ4|ny4{uh1zjZzG 1O,mgIm.]433;:R2n@ZpZB7M:ZO-@06~-QII D` șchs(EGH۝ } =:(8"L ׅlx'gqG0|e,\]<2͔U\jՓ͵CCC$9xmJÛNgW߁Z3(g```TTHr2>t͠AϨ?B588ԩSǏ^Z$\@0YM4#"::eWjj*Ὀp !0WCvqq`3Au 01X}q-][nԼrѣGד½_V hy鶟*_%_k6?8x\?8!{!JΝ; Wm%' )T$ pPEPUB\|Q.P/!T }Eo{t"tkuqOO}y###MwSs{OQeë:oZ#g((({wuyX&~ zIddGZ)D^LI>{24}ɐgF Ϲ0K,>HmC$p%($8O8Gnǹ;Ԙ&%(+޽?P8F􎡤pa{}̎c!GF`E9ڧ>11b=wR\M[l3 "ᎆ75CW&u{ހ /_ȨhnnFW}60755UVVk@+nh%E"}o4w|Al(0`#ԟ.LAlp|ueAc {As>Yǀ47h!@Q鶵y&=n&}4ԺI]u5 a#cҫ~>wOGܶ 2M?Y6r/{+/5grMw422AI.q\<{yyA12X"vRN0qK7rf`U:^AHMР.: )< ߬zbُ^rK_o۾#.zF )2K>IF\AKK6Pa=]]8uu5eee;vwc0L8FI`fpAۻl@ndbCobb)\B Zh|ͣPCCCMMMu85;@t/1`hUЋЋl1CaXq qKKK]܃cA A%5*]W.\45@A@}tsz\8 U;)b A?_E–%%%2S, !* t,:dWD4Շ bjF]]zz=Pmll|}}.1kjj*?-3( ;;;86@ GM7A=@̐fffpFkjjm^t 9%\vr8 .XYY/'Ŀs. 1Ž 9ߣZmt[`Q@{\>7'4vIVM~55l& 5]TӉ눅g :_.y2PBiCa(BAw( +8@TU9o gŀr|I1_ĜKZ/(PnBgp!1Q- {GS¦]bHv辮N`f'1dpFFFB0x hd KK1jc*DĎ`0D&].)-A:ƄZzH&'Ljb 1֧ Bbw 2,Nf10 e>t J60(fBA鲸x[MvfAwBP%v6ĥc`0 ff<ҎA7aY$f imJ^?Dh4K(DFn`0L8FQ`s^v4}Dwo1S3į@puԂ'Vk|."94!lFdrhv `$2muj֎!fZ&e37kЫk^YW~ Z./+Rf *]&ᶐ7- oں~!_-T- .VLUcܖ1Ȯp1J\r[}q(SӼM?>a!drlay.19 M: kAR5fV P_0 : U1Q/J6[lLfLKAPS)2ffc#ʘc9!Aѳ :۽#;'ɳ2°vxH5]P,J_Z1]X-al;o[`SOf+apm|8Hl)`_Pd# Q`!#)0psWH]dRU \ܬicԱs7/Ҧdq_4Ir'K[Ы"̛fBaA`#ae#PX4 ~XSH1kIS'+'0FN 05ZX=ʅ@;D}zLc a" t9f'K9L`(G+M.tPO pv@SНbRGZa9UU(gRz14,3aG~$!1^k}2SZs|Z Kc1nqľ;C>J/wr[J^<WFui#a5wWW1(aAP@ɻA;QX4Z2uyR+AMPz5 ZhK&|h)ìt0: "/DnƝZbrƳUDNnW1 ZaPfqf&S 6h99E[ڊ!Z֢ǬF (uNs .pAfXVXT3 ¸j!, sqE5,B_xa (,ǀ SwI(t}wi'*pK =4]7vey09=VZ#h[$Q ]g$zv̎!USXdeLb@Ӱo&\.9> cPN݁ny#c_" +\ S~y1}9Scz8dqyh0޸>:v*ԂW²`xH9SdgM/8/kyJ_=@,)CTr%&&.MioE>y|i118$?cca݉A0c1‡u JX*/  DQX .acw ؽd#iK"e#cXZM{i1l9R b( "¼ Bˎ^Kc_q}ʻ%|I;,Mifq5MFu/YGxP{E)ɔ^inth%yubWDh,"T 0   W{^;?|yquzm]ZqS)nMѴFqcF' i` fJV^Q9FX 7%  bL-Hr`=;^ci.E2unTݫZTbq[}7ֽi ѴhZV#nd%{,:%9$! ՟B; 9FQ,}(K1.|>Q "` f+qKj43Fט1[~ӌQoofZqRE*hZ}`q÷ ?L6HXH\;.1l{MjU{MsM}ceI%! 0D-@*&+;ڡ(NjXtBT6MyUf,h`p?8_Lq+UJiw;Ѵn&QCD9` ALPBiƟUO(0ٜZ$cbsyuϒ,TCXANf] {8xzLҵhV1j{zuXQYbѯŢÚ~--.v4(6Pq++nyiir ǁ/ ~/8h0ipnjӆ? F8ǰ:+[5V5kTmǘK),jƁn8fc@O.9s_|cgT'hR=ʞQCشl-KqˌMˈTbw+۵hZzlڗhZ}7x=ǂpN p*47؉fU!f bc:1VgyiFckuSc, FRO&D0b.A*p"tH]QRcMشK[JlhڅG>M7w1k)nƦM;o[lå \\E _h&:1euz]eh9F\" b"K266IFOOp߂$(ӧN:kiɱiI1k1hGicbŠM;M86شiƦM۫홏 DWp ~,...++#A&-] c)NQQau;Fz b|YaZc/[UU ɓ'>2|[¿D˓KoE9?K?́Ǘ*Gc/"4陙nݺ}viiiee%q  }q,̒Dp iFKECkcD\zY1>>_HB0z{{ … ǎǟze_~znLN=_O}1)LL|5>B0J GfV*`"Bp! J Pm|J9_ Z/>KP(&ab`OffEE:d޽pb~GL3HaFSSͪ1b!p#c Y5e:-hEǕ,,<1c &/^ Ie R ] +23&K`F i(ODmM`+V'G L}.`3#1s9%!`Gt` 1 2L'ZL:Ӹ8mUކOCSgpv.U݉tڝ hsb2"Jw["t;)&Z)۰r_s^ " A *Zy Ri8M4f[QP+-2h0ZmXkCAuWw]m ]qTua:)@`uAGB@/S Pc 0 E˖ZEGтZxI> |ߥ e-[A.d YÈcbF9ӏgz3L;"˚eoef:4W32>qS.kpzg_\\ gz2iF3K2/AQ.aq12 b@c&//D< vLe [&P&n1n2$t:#!zazq"O0w aQ+DN=J;6%SuJhmր 1jo1GC#auϏ޽^:&Qp pVf \6gYGQE dL- #;$`pJ Up!';FQ Pc#i"F!:IfPDvQL9F _k4hF#cbkF C4eL'1 u>1|s ^3LCbJ4#8ƎPokkkkkkk@N:<9鄑H9|9tWN3;ݞnN7gf]ȼfkj=h2؁p+$q4vZVVVAAAII ɘ444ja(c19QA4Nc3̋c, 8|d8 btttqUZZ f;Wg{gǁ襏>^C̸nnۘ2jrX"iE7 Fa7]fz==D`fxfO~KD$;!@pģ6nlL'VXqehD;8G^ 6M|"@i9+ev.]mwu6#;DX8@0(ER+2!Ŏaa1<8dV3 Q(1 ͸Mc;Z]N3J[zd1($Pp5Z>!$!c FfiG+ł4d-%cl } ]O3]O3LLLsd\W<WWÙW3SG3(dcX TTTT;vӍ+kW]v'=VW {`sƿϏY7Mbbٳg/\z 1)++#&6bu ]8cb1<Q0Q/ bUWW6lٲ/o8\w\~nA$)aOLc>cbg}hq03Y a)Ҙ 'E qN8 N+0t כ0 0wWU47lt;(ᠡ TP .0Z%1`O@ .]PjACC4d2&cnI( F$6Äc! hXnk4HA53 f*;܌{c]ЦϞ5h"=o1rOr ,H! L3d8֕Yj{i)i)Ci))jjjqwpa=xٞ ]p#.:...1ƴW._ ^4^4UU6E꣏>;|G'N.]וPFMMMcc#I̗c,x#`Dp*5PCfv"}W fIc %CV;;;ZmUUUvv6u 4-SRX3r8rc?+S'ӾK\tҧO-O;.w]:t}H9"n˟GƝr֝rΙrΞrΖrΜr0L9ߟr7|]΋e-G {Gv$&&9s= e 2WICd,xc$s%cT9F{Aʒ:FVuO>cj> i4`ENƏf)$1 nbBWH](ktO.+ߴXa¬B, ?cFabxEzȐ0`2(~rV.oՃ ` YR}c]3.qX%PpQ( KPF I@  j1P ZGaS$B0echC 2 fk$!Ќij4(6 +b.;9pc"j6Q(h6 4$14C`aMl4uHMCdZ^3B8X3OmuMO=>ptr'O?I8l8s&l٤IllvKB|WD#fLb3g$u|~:tR$ݩO=̀c?~:tISXXAxDc1l(KcGl!(ijj*))zǑc~.<+h@`B~Oo1cᡘNe3m,e$6pHDBa B8_,(fA.$0vhm !c5fH4]M4 k e`hE"DQBhb-WVQ04<\o{! igP%F hIcL@l _z[c-֐&Ќ"p.o54^iF4X@w Q'=^2 4OG5#i?cM#f^h_Q~ݱc ێ4?s`p|c=:x_ Ղ we=y1<0N>q=;zHs<h@m8o~Gǎ;wŋOܽ{ b (K2o1ٜ1zϒ"1ÉcX,p}}}qqqjjjrr2v?:)+h2 EC]?̤3#dB-'עm]f#3 &{0la)4ZHBbEx)aPP NZ I1ыiQk7.s:#ma4!5fr..),r ! GEv `v ^ ;FJ8 Ͱ2HCdcrۨH%cpmيF0  Tk4bӨ떘.Qf3 6UckA}B g.H`/5'Ln ioWގ#{[٫=as‡>쾕 {v v1^}wyg߾}III|%w)//.x$j5CV_\k>dzMRQ[[[XXxD\c.h1Sk S[D|wl W6l:{JQ AՂD:G9Oty(?Fw. {:?|I2Wsssp28b b1Q:R bb cfp8*((#ȑ#1pabђõ3=˛2i=  |LZnn @11މ$"| iDqF LPђ Z`LD-JWecZsSw QVpAa5qqh4L6Ҏ31t KeLbǠ՞tH! cمT05e!!S*1H04V2(bEBfc%d2- AM#85Ϭ`j5.1jl5!LNJM#(uc]Q8u"o"S*E1L#cxSG3^x&d(G 1F jV7Jp'v6g9+$JZp#] dn(^0ab!C CEr#U# M"bxc.xj5[fQF9GEQIA1 ^35&X3 "i4! /B}J5#iHׇ vth f^zEޚk)^Lڧ.|qyͺ 떫/o^\~y#d]\ ]Túj=USk*Yx3zEY?X+Oc{+!㭷z_?BNRaC/,E60/ϞY g$<˘9nMVUʡ*lyUgKlp5}1:V6ojjqIU~pd8hI5]9 :5]s 2BF9ՌpL1#4h |4k dR yab29Th$QFC8!4ڃR']3Pͨ#L@e!Ռp"7 ycdU9Wn\UqUѦUśVnZUiUզU5V5l^մy:~.~eK]@$zbV]״ye5VVmZYie馕śVmZYqe9VfnX:9FS8ƛo qR gWfee%I%AXdIXXDYq֭/@c-Kmq[Q^`Zux#S$GjcP(?zU=Y 2tbc v FÚV i \݌"8dY1PKjWvnbAS>2w/h'Fi4 : zzVl 7?0R>WBCǠa‚jLNr>FЌlfePFq/g8r^('spA8! D0yt 1 5BW$MĕS]S F`, ];ʄ^K8i\Z!4 J3& h4}=V0 :A0pʙBl1WjsՌHA?}W_*Rюw/ٱu~cmkXB-ݏ}56_x | vra2Q!j>kD&+p ؄At=Snk9͈t ~\uE3J0RF(Q[r%&iqrsd]xD310j.f Q).i4X](6 |:f͐P34cx f!T#Zx[ȨؿtoW yWo5yK-͞tvmlۿcNOE|Sɚ?m>nBM7Y5U[Wg܄=!5fs{OcD]#c wTw9LV.W2tE`߀c\p1|,W2,Chu(6ʆLJ8.s+_:S%:oDp5/uNZ;s7đ&dT,Z/Kfuc8(-Z!,$doLQztJĝ*%%Cކic܅'$qa' aNSNP0v!RQ;P&bU]GCM̅s%q{~:MJ@@cWT(!3c̈rv!I͘`P†2 (c" 3^~֌< g@Ujȸ4X3JtqTEaMRX&Ӑ4\?Е4DF=o4[7AUj1˜V~9j8Ƒvh>=ÿ9ՇvnKݑ^QWyU/͕8vxIIIgΜ3ch4hc11":Ɲ{*(p XETS6 ?f xtI0]50EȸQ~2XKщW  T`BUyK. O %x dp 4hFH YJcd⺔a~A4F'h<UOctqoJέW:cS1@#UEM #`_>v@5uڔSk -]6vb 487:q &c:"ʒD15zƔ{Gao0ywC߭uB̸%eHP 4i7bۜYxUK;LhxT>j7Nm6kPެex-[TK>W798@$9w7Ѝ+ h4hc#c|_B.'mC .Aq e*ilAN<.12ȕs1Hia *W43#i f 74䫸"flJcLq P=\5+R f)H兓ARQT9ѕ3Fc7hNef%ҟ46ƞ1B4J`é1֊'97cc[DV/Nf0;_yZkHeqfJePU*&sfB 7 _RwYm""+s**4Wi?:% H-ƵͧS{s,F#1R'klu2`LPcl^W"TU0M fw3o͸2敤Ƹ7a% 3 !]߄]~+CtNeYǭ.e8z23U=ICkk/)3MXWbl ,()53F̐<3LMd!0dc(0#^1ƨDlPibݖ/*]8^Ōl9Y=b/ }C^C'iBq70, a/1hfH7%32vC)cQ\*cH݌lbX{1JW2ꦶ1Zahe3c ǨVY#e$}\9U-xgCNUEI_鲪RҕFJjc8]U3_4.79Ʉt"Pr.P1 !六άN/54%i , GUeچFq\W0!3&J5)g Ty\pd 6b ##M kc`f1k ߛfpj1X,R2[ V,. \MTd6Ԅ7jc{U]`-/./{00P$>#20Q*6f54 meo)D uT΁ڞI1diXc.É+ldTa 9-|Z.>\iv.o! k(Bw>+_dg4fXQag _#fC C`L&3$cĴ5ƆK 3 cecg16 Bc`ĉ1E}1شc vnI#fXC+L13s1fc_ [\=M9 V 3֖=Ņnj;4Peg$ 2t"'%IcJcE)^#P媗z1}*Cf{bwPZy 30M G11s;0jb85FxĕC?pjDEzZ N*Tj&9M%*RIn(5u|H&I\;+k(':-ݫT19~eVEŷpOwJ?_K;$|M]qi+KevfVdz"M᪥i\mb7TS4\6dR6=Ikckc|ʻd0cw0ww.~\/hYZSݫjت^_ۭ3R3|W_ڪyQԟYԗ}B}I[ݠԋsT_lNwefѨ-ctvv4$n51XMs\GƘ_HXo1m0h{@ 1#͵2lʕ+^#M 02Fc-;>cXcggǑ1P1 $\#uİ0cf2k0M ;pj('@j~dd0cJխYu#DpdJbi1 $aƐp71cGb(VFI2@ HB11?J"03פ>3st#c9Sc@ `8Sٰ15J1z1373ƈefdNѪMz@ ?x}ċ&1 KTƘHVGWcߙ1raԢ@ H҈1za 41lChkw(3xc TLGSa71@Z2z#& Ubc\GƐdƨLES1ʌt~}ck@ 1>#\M +c _cCfk-JuÎ1~@ƀ@ F` 91^z%/Q&)3r#M =l  09bcȻ}op8mbq0㺑1U1 bl?ݩM3xc|K_i h&ƸScl"c0fƘDXI{QKcܹs@ aSc<^#M $Ƹ'b ɕMm{ $u#;bƀ@ FdxU@[m/& cR1<0FFIcpp2D"7 H"4FoChMd{Ƙ@Ɛ.#D$ 61# @ 121p&1Fo021|%ifx[o @wDÙ}o#4,) D8Cckę1"fnF2+qc@KKKfƈX1OH7'swl3H:/~yv4-.&QG{ßFV="!"+CCC6QFbcBƸol \&&0Q63MӠhbq{`xF'h"zHmF6\} ~eoU~heȿcScjE\qӾ10Fz`4'} ߛa :Jjac( -\^ʛL2v[Ade*(Oyoѷl.VOOl؝B=fmL_ΰ??G1p+K_`Rmj cjXAhb42Jba$2Ƙ̌QߍQqR-l $ost6RyNJOA*27|3aT<Y_VgChSv5DdǠ+yg^20׽s?O<5<6niWFJ 1Hl61,ы1v0Cd4FFI#N+iqcH[%ՐF-۸n4SvW.uO/.Dkd*f2٩!(kp?|ꙉ~/VVVZ@1׊j.5cƸ1|%qq ]ieM1țfNJ|}ct#.zgQ} ? ~<^@ѯ; WK 1Zcܺu cx WƐ11Ĩ'NG;VKQoq] /7J~'g(0*=noog25Ҥ>]{Sg~ןxz9U} H`bjz(I2JX1Z6OQ8fSkichv\EhǏ kJ` BOKG*I,CwOK|:]YRcN6Ɯ{BíQ cL02r>Fc\` O=0o |MtW|.q6me!H /1Bİmq1rgFI}+o\`  ľQݟOwİ0FbmČQu.@1;Rm1<M 1611FŹ1Noc@ H@cfbyqsQ(+蒌A_ccVmbHcc@sc,&KQ/ALcp4Jb_ש1;ǬDtdb_~ caVƘD1|obx7JR16wYԘcr*jAhbx1JVSd~}Xɟzn82CjG1ƀ@ _㧈1]Vjc;w c!4FKg)(I}M 8aU>xƀ@ `;XzU061 :m GIİ4o~ +06ƨķʬ3F>JiCl2Fxbch=A"Uc@ HP#0j'nxm617J1cĨb11h1 $13Fz:<~h1bf26+0c%s71%VU05;\UP"O^#M:FIC%à!713Je*'R1 $13FǕWctt cxbc Lv PcLn#D$\!@3c7U\\#`4!4Fch&Sc'T`  lLQ;J*91.4A 61D|cTf61 ZU ݘR;L^#M c NCK19ޞ5zc Q1u{2u!^}c@Bsc{0F 41l1$fn ߛ`85FqXvo^-ˡ?2ďO}` Hbf^f 8:e;wxa 41 1|ob2J7F*VGh^ }{KX}` H"0Fvmc(]cfdh10$D13QTce7oÕ&]c !1#Y1B4J\ 3Y:n/^Y W̍qݧUwM\1|%q66R)xc6˵My[lQ-=KPc젌9W>d?cq oά&7ƛbpb#1.]dNIĨJ7F(bNcwdv7F!hoh7lYn3c?*k*vl[۫EnoHH{{gVa#l^Bky؂>0$DcWe c!2FJl uE{(rb 5,1%xL?.(t-~BWҦB(K o3:ޕjX*]BLD~vyDBQ@ywt33;#$]$v݈yWt]2N_FS^9#ݥ-wU7 ^=}_! cxr 1Zј1R^&M`82Ç*'CCmdeSKtk ;'I7/_pD 푈E#2O<mߡy2C hw~9,$~!2ޡ Q`?!3 Q̌qpx\rAhb8J"2Ƴ6z%7JdIWѪM=91u*_i\ 0+jc@ScKY\DM Hf&X+Y{(ICH` MҜ QAcabc%3wMRf瓔ctNcc43hH$ U!}c@B3cxc,e6Fc3;~1Q#1B4J*cc47hv…d2Yɣ Q01E/0j49bc0fT1F؛"c.w_փGL ̘jpjy09fHƠ̰o^p`61H^GGL֓jh1cuuU?ƬU01vʦ1zzz<2F0ƸOGL4&c#L QI1 $Bq`E|@[&Wr0c@ Hp#6cFe7n%0Z"2F˄[1V\0M FI4fvd` h^|?|ھ8U8[#`4adĤom3-cc wA+I>A#x2Ih6Z5lNfg2ef=y!6Wb7vYS7x_c@Z,fH c̤c23~Q{ƸlF-9JRV1fHM'|4vگLwꁎvwId'1tƨT*VA)w6r=F۫z"xm]Z0bn]d #`İ2-fBhQz*&5$VWDt~*-7)ԒPy=DRv(`ې҆k} #c؉W^A?#geSu~eD=N!Oy KyFS<b11cf)cT\7FNA~mRK Jز4 PuM"96j^{Q/Q 1y9<ga/?y.A4=fӥ1Xc@Z,x 2F 1Jܘ1Zacxch&McK115" o 1$9hb|!x 0q4ƈpi1M Q1(0|7y =0nhJU{aHwuCF=JoJ403Zb|ԩ;;?=fVOAvxZQC30`BƀR!Ǫ̛Ahbx4J2BbVƈo01ﱒfLft0UrObs0̯S6J6t\ s7Ud)0Nz&*ӧ>1"?u' -p:b15F=bh1B4J$uc* nAy.?9fiν"?lc_+qAƀR̍QL2fg /&d 1}9M 1Ơ<ȶ1 R L<5!w. f̵~,U~Hc_pc@Z,fX 1tf#M `lEc9c9WCWЗ_.E`̨hm!mbXi1Z c49cW&hAoJ&c5Ƨ>)71F쏡3 6FchdD` cCNch .?y ` H+l O{QƸhd ˱ߛM%gvѼ86x]A~oޘc2c׉1v#cjXCcM 7l82‚1M]J1 $132x1cw#cx51ljBe 3`$,$411F@ A17;d$M ct> x1ƴd >UCox<.68.06V1#!3C`Ո1Z1 c`  pƸ9`̰inh&K})3:ƈgc!ccc@ Hca T&03FC|pkDcL&cc`  |Ơ̸1|ob4>JbA^#$c`4Ajc@ 7F71n3ŋ=2F`GIq1h1!%qd|>ocFq41l-TuQכN!c@3cc\Q߶o '$Aobq31|\wKcggǾ1(0Pm1 $15ub ̌ _&F#ƘHv%(1)d_$5ʌ׌bM Kc\65nbL&}`86 al#0F~`iBcf823z{0D@'ahj/5M /FIP*}cT1$`   xƸQu71%#Ϙ6FZ!%qn#k01J`Xi<1~(Iƈ+Ǯ7FFI61ccc41`*` Hc6ư 71Ƹ5Ɵ#xĨkCamm'4uUcnҕᵫo|þ1 ai+][\ck&l΍Q1="znL'T&85CSq'/DmA%/1f i1A+!%qdmWUC j0jbs[ב1$fh }ċ&Sc1 $ \bc[6d$M 161Y+C?Q;@Z,bc|`?ϼ0F(AJ3V1JѪMr\m 1F)09=c^ɻdxd ߛQ111|obk4M FI$%gؓƀ@ i(1n cW(#c;wN2Fl0c@ AN#ַ12Jb #D$u411FwMi33=lfzg `nc 19L#H Ic'MB0`M0؀߷--ےuƀI?oUITT*x?T}uՏ̡c "4ɇJX;eEew n߻/V`0Ʊ1P(bdu&1D]юQ!D#hΜIIIQߊ#a̻_\]`XD!#qcciH1j((ǘtw ":D^֭[QO9 ǥxa 0a/Xf?@X`0|sÇ +bxw#\.D&>A11 :0 :10uFͰh4G3` 0a߾wnY]º: G`-`$cw~;F1ꢚ"f1D/b%n1[gwgA c<9H7gm;/;uW|4ܞ;51a|c1Ʈ^Erƍׯgddj82s_T;E ]/rr 夆r 8ƘkwY0;U01 :ư8En4.o[Syʓ(cdffRv|cL#-- Ήp@4Qd@*[cP}8$1jf놬 :FA@0BmLftۊYټcTOr7SpȀ; n/_\\\RT|p 8k wIx8Fm3;9$s1x:Ʒfu1"dm+m#W c<9‚M.ll=3ޠh>|7~-9^^^e`\qڵWfddcHVpu *,!z$E OO7c Z1<":FD\- :OO]OTN>YtFfwLJJ1`_}UZZfdffT8LMMc466 V-t)Ãcx~W' A3:Etm9q1uBEq99 *2N1,`yBGrgOf5/Ϊz>_*MŶUN:Jxb$.]b:wvv19 CE NA1=cAu ыc5RB:d :u p@OۉüZn_NTF?7iFT6D+׵]}&6]pA.s\,(ǀkR/4BvvvMM+ycyAAdCK^E $144Մc1:<82Gl t $pFT̿U*yݗn|_6&گȦ'&fCff&8.11ݻXpf|ԩh4r?c!Axw:gX`;FvI|pu N HCܸ;F/OeϏ.Uw_t]=@O'+۷o/,,X PqJ*_|gddܾ}NZ׉ 118:&I1;M3SL1cHK1JW 4p u "s6nxr rJ1qlL?OKrAohi7E[}׵^;ڑ#Gjkkr9rꂍiTWWOLLT8;p-b8B.Ԍq:$ "_Ǩ7V /cﲠlP:n]:xr 80pN|ɟ}rd}Jg=w-cӟ?Ek?38wp\&! /8O>s|X. _`$E o !5b:F1cjjcI0M_8t $1z{{x&Ow_Oa۷fffph]zFH \HKKǀsFA0rQPP c^` A1fhǠg"{sp}>#4#c a cq4 N;==ĉܳĞe7&''2@9h3WYY/\qJ8%1Gp ыxqI1j!cL1o5@3ơc t $sV񥻻dbpN,..{˗SSS=:;;. ǀYfffT*`[[[uuuIIIMM \.`AB8F(wI;F=fco. zc?/SQ\101N( p18̫馧7_cG!LCc ƜE ^a&֌qt1ebc/Q1_1xHP`wV-c:h0C. / ~c@1 10>8>>c0U/Xf?.?xcǸ|!"W( ckcuhPc "gΜ9wJ*a 0W5`$ƀ;F1XCSZfu`;fcPQ֣Wj1XF{N~{ 86?/1D/bp /QFiFi]E 3oQu A&h!z#]NaՌ:7(Җv X@ eq?XǐJc+ .Qbs : HB0BӻcԻ;ckcf(1ABɓODbE PNjʬZR$ǐh7Ǡ4A$dq!!CrE oN||1xw1n޼1: Hh9#9~;F1mxc1D/b,QRR "E|p{ 1vI:f1%A@ W:F2 nC. gh@9t$c: t9;$< CB]? ap'n!z"p!z$E OOСc >0422c444VڈaP @tǐtcL1< ctww{rR1tDrr2D4i 1jkkp ы!zC"]Fdw Z31 ,9VEti GL>/c^K1Ȉ!%A@$HLLYXXEl1n3QYY)c`DtǐP1 ǰ^ : $!!^ t:W`vsߘ\#[B0\~?]1p c `\sG-b9F6ǀG$ "$#fǘR h(̲NGDncَȋc \`q Js0+bЎV11|iY2,6F)s;Jpw/¢KN$`D:;5!6m ųy;Fh]QCB]^a09F: J8؎pؒ%*KWe%e) .~ }7;W#!ob[,C1wI*bv.t Ar!nu:/9ZNL" ݧ8xrui.wsDž_2,3r$c1F c\tciH1&1UĀ1=(;XڥGlYofǫRs9&:e 岣->z}F¼6,|t:qC*E8NnE u f|"`\ G.YHzj,} F5*ն<NjNu1X/VFߟ}Fr^gl1ގQH"Fh:E ^]sq#G,11>v A,]0v c^KB HJ8!zC. PvAB9F~1N8!cHKcpv uI|+b1 \ ǽNx9\eU7M_B0BK" A!11q||H7`[16 1|v J0zFZcCE cc 4Μ9s9J؋ l+b7&rqx!CE Q61ew P *#E A!)) ^' ܀m[qK; d , 0;Fmt1}57LsӐ."SZ>;E $%t A1bccp ы>tIXccvŤΚqpeV9498Ie0cc^NA$|r 8q %*uI]--c\3cmOX30[ؽ7ǐPc Rc puT"5D3[r ͽ [:Ӷ]{iǐP"c" <wI)bxrmc[-]z=HEc0:F1LLeDC@ ]<:Ƅf`H9F1<9ƆmUt*o\* uJm۾cGrAD9F!"cT5[SI:k+\79cn Pcg1D/b>8@ABǠK;E FG'[TQf~p PoMS!z# ]w 'A$dpw1jt ы~vIXƘJS\^D ݲU:FO#<$8]EAB1HǠNB8FhvIXcӖImYC7.Ĵ?"r J1J+AABcTo4#!`1bWw\P\&Z37vҙҚUѻ$-bu AAB1fpq{qt >M.bxr-oO:LkMׯ\3cQۙ*bl1==1A@ cܨ 4f0cdgg !^vS-}-}J*+nXQk_"t V1J1Ac @"'xca%@-@0J; inރu ыw9_C "-(j4161D/bx O#>* k7n)f̏w{ѫc^xBswRt AQ09EvIXcރ:ӜKZ`#_1Cc0!. O-B@c讓AiE? c~īc8Yxܧљv+PoAr̊Lc1 qvXc%ch+A@}JpLk)ϓc|OD2E O$\FcXADrPa f8s!"^ɺ pa@1µa$]='ru"/YƖ G1C1fTZĀ<8Q1yL߽?!zמeIw|6s k103gRRRjF cyD$ ͬ 4]0Xc71]t'rޚ =8ƞo32:E $9Oz2wm2za0Ʊ%&&,,,*0  #ӈHWr  C"@]$̎MAETf\$J`CB]Oǀ=t%W'"T`0Ʊ%$$|ɀpa}iccuCHqqwyc.1<9ha𔉎iq^ɸv`hX+Pķ"B@&E;yŅ0ft 6F B;]#٧#f:ћ⢨Ϯ{G#]Z.%.zcw */(0būcyv:"t91c|u .b9Q3pћtNDxkW֛h/B &p~_/_0Mr:BfνV,B!;o41!n%.nj,_(H3 -bxt14:c075u =|&kKZp?Fw( \Ҕ!Hj^͎Hj5'EPO5sZvXXXsXl-[|t|1c pv ">8p ыcY:clY&J=kzYU9}}.zFC"c԰;ߣϴ:=܊E|0)镈G.r 1th:qa*]t!n%u*:)&u rmp_NǨ ?E oaCJETfT-NDmBcHKbB@{GS%9M^s c12[9#\8dɱ ;4w.x+3: W(p^1D-_+/q$=H&:c%1:;;1U=G9$-JHÔc+-yw,:ۢ쁵;'.G˖-wV~t =.E!S. q[0;_\#]0ǐzcDzHRu[M8FA*kw ы,cc B8F\w\Ojc |1p c\Uh핬H1D/bڣx9W(G@|+f;{ 1OGj1^1 KcD*T9Y\.R^1£K8GvͶwHo%51yyy#<$>cb|2vauvAuV~|tbޟ+P1&&&8:F16c NKkWX8vJ 3: 7!!^-[T  56(_wI[pt)p1aru= t ]0Cza0Ʊ%&&tv1ȃ4"҆cfddЎQ^^"_XzbjC1{>ì1:::`ptÇ8F91D&ϫ6,4?^X;qlpD=wJ:B\`0fypFDPq1?N;ƵknݺXU0:ڦږZJ^"333<J_XtWsu"Oυ-)))111A:haA{=1%1VVLu<{ԣ֚팧g c^(~8ADb8U1#$>8ƪu13KD\18185cݱg?=#c^r N^ޏau =: pp B3\).IwWDoқzGս>Ō4ko=#c.1J*1A$c8FJJ{>=9]!|c݆Xe_ Lze~7wIL:gW c! 1cDFFz\!"G8qBDfI *(Ǟo3zr.bptGy11AcqqC//b;FII͛7ϟ?-YSՌa[~e7Zv=oK|c6 Ȗ%{0g;C6m\m~VNY/D(QN\9{>}X+Vؼy}: .^E $$kߛ ě.lX&z{T !5{0P!-`t Jr98Fsss]]8FNNW_}uqc鴎Y@3Z:(X2x)s 0MtCFճ }˱01q0!J*m i!ψ2jGԖi03){\c cTD\3 =9~Y$: 1)Rږux/Q3y1#왦B<9=v9Ͷ5uJ5Y:-m.Y\|>(}= %-c<XjU\\>'c\~`CB]v5Q.AcuF>8IGc}c.cɱeeewܹx|_"5-Vʠě?ʺe]DJ=sMq٣.As:)p}rzaB-V]BdpYG_KPg3V+1xJsn3!ΡR@i؀T:R䘎.)tNwM!v:≘.hooVk{4Ʌ<(mT!8FaQd;V[C7 ެqf5YQQw%,"0㭚!X;Fp,^2yUuUU6Y:Y6UB/!gd}أ*haJk2&k5#&e<;cFaÆMU-mMU7}+z3!=DʘBD'Ú ,ɠ.T^裒O')qJaZ{27\sJkN{ R~Yf֭8rϞ={+Wcܾ}^rcҎ!.E O}~&3c[q7Nȴ޼m. c c¦.//{.fgΜٴiӏc舯tp ̀]0X1DډichijX,6 0 6p^NQLv.nËc@9fP:1yIGhaN1Xc1F#1p 1jc:F?pv04cN]B3f4L~9p 6p 'ci( Ϧ4Ќo@3*a ^fgp b:fpL2k'D0ԌqݢW_ޱc=~g_~eZZڍ7&8Fiiiee% ][w֙)4)A-VvZoiQЙҚcHA9VCTc֚'/_79Wn;Q+nw oQb ^ 'jF;fT Cia-eЂAz\_fqJ1( ΫfD05CvVǰ>fت.a׌1:욑ͦ[5DMáqh`AЌ1b %hAs7` 7$Hi RridTY8Sgva?qr fz {E0\1 F]x Gx3/-oݻw^RR .\z5++ ^iRQUUcH1;55vQ̑k1^%ңҙbv0.bܠ~MLMMc_'~}`gݶm~A3OM$ND89E0XR6]Z(j&Cm8hFcB1 VV`s >v\ʰЭW+\4XZezA:UͰvL15A00:hǐ;8FGǨ짚&T^ͨy0Lh1i/ 5~1/b8wp3 v&2Fsɳ%:&},AHE-e=Κl`dЎ&,.v1M`dU]?ׁ`|o_zӦM۷o߿?Ք/ L 1-c^Ĩw1tu5Vۨ6=웤3ݺ*b A}D.www-slrr2-hƢ㟽ayȼ=fx=&B,y-B`{5O]b@,B.Sj&*~t8m@-3732|OCGyטԴE?K~ a={[.<{˗/gffo,//1|뒰9Zsc~6rmϘ irlg\E v jPoɠ%YYY.]OA3lٲf0/2K~C~{ه,\Oa@0Kt_o6nHU0>|ĉ>ܹsT~3ج>ʫW". 1v=騍WDmZYk~>f1=yc/wpk1%}}}WWWʦ?O>9~8.Hmbcca^~}:1X+6kfuJ0V °,XD`ua#gLL fܵkׁyx yԩgRZ%yyy.!`1ySmx23c_>vMLkBGk~ck*:]1.eQߒA޽{7oLKK/?S;$}7`/I#@!6ۅa0l-' &V^MbQbc0Dxi<s8qrr OSZ~՝{G$$?mh͘qtU51[t ݪY"Dg;\pijJEK۩RFqqqnnnVVx|'III'N=ȑ#z$11NdmaxK a`/{a0WOA{=z{̙3Ν;1\pmf 1<9{֘+t7đkb8u)bЎA}UP`nii_YY {ݻwlSSSϟ?{Y-O>.}>p/k.8 n G-[76dg77klԓՓ ?*ROb ƪl *сm [=;0]$tĉBbc.1#~G֏M^Lywx07.fl:#|JH$r~+W:::8sɓ'(Xw޽pLlܹ;۷o߶mvoy ٪'Wsz;lѓj˳٬'u {k]`G1_>p/#ѣo=C1%F-Icѩl[oBLb:w=|gDd1oI܌!~3ܘp:qСo۷G:'/d΋zS:;lt0Vbc%pWuMa{ vCp6܀!ntpKF1-IcẑߺŌMeߺGWna+SK"f8 ј;q@'Nx뭷h|G/Q%=ٯ?HgN\?+cyU -Eg6[2âªG|i2t 8uꔸS@oIjd<6b A1cigpY-vщtD3%!1܌ܒnjk׮]z}wh-1cT`so qҥ/0q48D9UItS&&LH P P 1OtJ {J^Qa(<=a'SٮI13t&mhZTzu ߻JKb`0tFoooOOv:J؎@&*$ҹ6D=AZքyJzy~S זhHKRcd% - -aBKIbĵ%%1[}#- -^ZM0XbВqmIhI %F%zK1ʌaBKIbĵ%%1[}%aaBK#%i01LqmIhI %F%zKBKb(- `c 1[&$,1-1[ZÄDĈkKBEb,1I P Z0XbҒhqmIhI Ih&c'1%!-&ז@oII %X$F\[ZÄDĈkKBKb$$zK%i&cjI4I$$zKOb$,1LhIXb[b$Jq9e((3 -&ޒ0%'1[&$,1 ANbɬ2 %aaBK,1TĈkKbĨ1rd0c H>ƒ#ޒВ##- -aBKIbĵ%%1ΕVF c3cDz1_|51XbqmIhI %%1ڒВ&$$zKxt~x0<.g~0`Obĵ%%1LhI4I % ->ޒݒ?f&W $֟T6Ⱥ'g MAKb$,1 iI4I % ->ޒВQ1⁖lL/ɉT d Z-&ޒ0%'1[Z0Xb[bĵ%Yb2>J_q`G`ǵc5k3 -&ޒВANb$$F\[H$͑o8uo_0 %%1ڒ0Dbĵ%%1@oI>?:c8SbƝ ԇ|vOm1beKsC`ĈqKޒ0%$1[_qo>V1Xb- K U%1[$$zKBKbF]-2Ɨ?zvW}G_uM` &$,1 iI4I @ r%%1$50]=[wx~ϡ~q뗯\]@oIXbҒh- -זD@oIhI$b۾+}u`?~sߩ1@oIhI t '1[Z#- K C$zKbPe¿\sÖ޺{[^<ީ1L- -זD@oIhI %F%zKtۗ/j ϽMÄ@ r%%1ڒ- -ޒ4Vb2ugG޼cs_پ嫟u$zKBKbĸ%$1[Z#->ޒВ- Pe۾Ϋ^yaߑݯU!$zKBKbĵ%'1[Z%aoޒPů+_~uׁ7>wnܻjuޒВ- 9ޒВ- KxK Đ Ukӱo3~ߍU0 %%1[- -a`В- -w qSkm{kn,ch &$$ AKb$$F[M%%1p[w38|3}rb׆SkYW14K ZZÄ@oIhI$$zKBKb$JqY%{g\꽙J?hƐ $$F[M%%1[r%%1[}C1Vl^ĕɉcicXb$$zKBNb$$zKBNb$$zKbPe\39ymhܺ~1- -ޒ- -ޒВJÄ8[c1cp8Q1,H-dpfXbEc1cp8Ñ1`p8S*cYf p8n* YÌit7zvZ^Q1Z$Éu<1Ub [n>ZbO y O+a)-4Ww[yon]rU dK/^ zB)ƨX J lUr⥗HDGʼn%>p\`\^*%ƈ^[|DF031\1g[[y-*;[El-U~T^/].֍G=aW2+p80Ɯc.$.XSPu%0~_ゾ{J0+qWDR)v-ӗ;(}%|+GGnEpxDWg[pTSCKT0F3B#\W[- #gˇ xXb֚%k KrLƴ5yW&z΂C4_%gq앞SY/1_>A? wo⮩A[OEu0qȸ`,Dؕ0ENaNKU3PcxE50F%iT0fX[1`F=16HΈ/t`NhQZ03UƢ3iIQ4^!984V 5}8d#^1R3,3N;wU1cL3cX*Œ!ش3b='lU$@ 42FiH`FcI>!)4`FbOf*-Ο?ݽk׮;^-&ӋA3|g7&U1C oc"B2c4D1.uTg3ݥI=QOcT:fXSjLJ!7i21|>vܻVƈVQScR (*?K1|yml(7&`Fm6CMeٌ&Y.NT޽ʕ+-߳Fxo<ul77v^\񎩥<)?p6{Gְ2;EUbf]Ǟw\!f@?~\>G< ⭡SOeY<:E_d75T۞%L!s?giBN 篧x>D"144qك:iã:;w> stream xY]o6}7Gh~ڢ]!(gY%)YĮMm{xI^*jv5xOKr18_}+|-EA'#gg%,S,ߐy͘zlx ~Q<8an88܂#cd{ Iw)8КB&Bp A9ulҚ:99M3*yOoi'&$dR^BǓ8b'7Iè!SC λ~I3(>tZ,ӌ4t70Me|]~JAҚI u r*Q-4O.a|E{a"0`K!* !EILnamI6#0d*<Ö~A><\Vۗbms"Fn``ΰx_$`9I:~{^ؼۏgiJ~U.q t 6$[s%fc3͵Ct(Q$~֝]HAmS|/Q_S aZaRSRf $ A0`+9Um)3A%Om{8lZќj6V7xIX)J0g/bw-pwl"!^pRuntW95rV؃kOp ^}x83hMBj+ܤ0iҋ'?ϥM"_`M?tQ'Lv<-dA>J >aa|Jr Xr#M17<< sQQExEXS\'s,+n}I Mx"3TZ| KK&.nDžr"p},߻"._/?"W.$7-K嫤p|KJ> ΓCn<9,"<*tlV?+L#  HEʽ4F8\e\aLVvjR1`q{D?w:cW]!ݜ҂WG*zY~# qH3 =`Qz %0DNy+a Kv =Fkسi~(oX"3͉?^ Ia Y㔄NH`"Vn2!dr1TWN(J\ ]RIX"_ K=AϡSF)d5y:sE]pꮂX%쾰xaM',_VR\QaRX%\$r B"" 0 tp=9yGz9%"` 62:}f[ տ@q?]7un7А a4\(AQZS8{~F >[|u =E|mNFiW.'< z+ӊ+k>;(~y|lejɪ& h`f8y@3W ZeΛ*k,*?mC*|Ta5TM |-)^ ؖ UeZe%VSf M(n<{JT ]<+C M j} o endstream endobj 84 0 obj <> stream JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!222222222222222222222222222222222222222222222222223" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+_h8o]R=K(D1J?}[|O]iSQ.Inzxw+S蚽].aTlĜ'G1u+1sexdsG{uծmQ^Y ߤд=wON&p{;NTy ROcF+7;_ M t]cEp)w; m-Ɗ9*3&mr(3n](AAmB8a~i裟\J|kF/5}AO$5TiNJ #(2դErkF;wT_Һ]z?G6LIܛo%uҜw@QEEmB=:[C22X~5V *Zڪ) $ 6z6:d*ɣ.tAqfҁlߐflARb? q5TӓãЧJR*Wow> jw34ʩ| <JtB=N.Y %^68 . G[Mg[.&QpU s\߅Cwk<7F6rv5φFά^ x}ox_bQ]gWŚ,~ ԑU[@k:_T3]-c[6dU*Vӿi\SAfo|E⫝:̷ӯd3$cBcJOxPN'l \ړÏQñZ\|G7${J*+:SM`NT0ӧſe?#ť̏qе?zL:8Q;X_"Y~ 3_::uo> e)ԶQñ|~iGU9VYt.4SR'KEFؠnYɑL+ASo;Rz #ޥQ$DoK^%kvc(=2SWi~xN_^)Եe"K39Ov_J[%c jT{^k"! (罐Wf6!VW)zUdz7V0*}G> g%{VnRPc"s˩-G9 d.^ƱMe89INWc'&cpt|"sեӬcӥWH.~qGLqϭr却xZa,2ptCӎTс%ǜV{df]FAȨd ڳ,hU}*Gk%T+wo?V"O IqV}l,n F d1>K&[ ww$Lf`Ɵq+IF37Sֽ_zcgǑN2+-7=z9hH]eYNAVO\sMMO\ ʝ=Eg&K{˭r?P3PxXh^'V5BKAIh&FX,C?6;h!mȡ+2h[ٮ }?֊>RUeO::_T3_Zx' Rʕ2$J_#j-uwӿi\SAf/xD /ξe+)Um{Gm}Z@g.k[STծy)>;d\e X|v~TmmuWi#b,c=_@Z]}i մH&@zwL_~%I$Ͳ ?4:Vib[чk(e*#־| 6Nr69yG=}:ta ^Ȝ-=KOjώZ49|Belq@VSױ(ᎉ\F5jxzt94Ẉ0#SmvS4<&<_xW^~=V%nԼNÁu=?OeNY2}b')sT YYOĈOZu 0w QdP@FWx׆_ j6nno!0HJ?[G+0hayMHKV@8PX+-ġR'S?`;J{(B`{L!]CX' V!`>ƾ_]*v[Z{+QdyPZ<RnOzw*m4F=0U\wŽP Hʤ{or8!:5wL9@Fci99:沝B/߱:'%ȭ܆x]D Uu HgyOd8x8V/##hd}O(Kda,ͻU3s9ReȪɤNs;}zwS$^(nՔBa^^GOu)Dk4BV+{Ռq۽u]Uڑ-9q }zYn!ӣ*tܛM=[<WJJ)k5|n|M \Q] Q1$QT@TvRTO>{WUNv(0=(h J( ` P*(REBC/֗e;-1EP@Iiako\aTBEQ@(P1EbQEQEQE endstream endobj 85 0 obj <> stream xyXu동{gyWiӂl;s[՞n%pڙ=ƙK%v'@Y YAHb4!0 `B [}~Uuj;: }Wo*/!5w07x 7Ц@㊊,_|u>o|Cv8 <;;x4{4N8 |&@"o|Ir8m66#FoN[@D$<E6hNY^e1ׯo,oE DD7%Tnk9٠9ify/@  36R٠9ifyO}~@  2șw%N1X2kHUlG(5hNY^ewv''V1v֮z`~3S^vsg%3Z@ ȴ㗶6!ڥ/?`! jf54',wƎonO!?XOb㽊tKwY(ws9;0 V'D!sSNF> ;;~/}&GCyhNY^ {q(VU=|b};v}va/drQ}vs "vuo\\/ĺ7qMZ:K M G!dmfWYsxUrMw:2yqCpS7 rHkJߒ!zCY@Vף<*;# W ^2p)k㯂%;@ b׬~G d3ːCMh()UɛH VKۙ.cTë6Fǭ{C 12m HW$MChNY^y'.՛'^exKBWn)7NB[OHXRq`b*XBU]֣.DwsN_ytxD 9_W>0wTXIڽj(Cy ς9\^7>墳-??e4wy,ixVR$4Q5߼} x]cԟt<7^w @ ȴ΍.I%4m:k4fWyOjb9WwG=Se?{m-5__9f$|yl4':OӰZ)cԟ ḟf{&7><<1 l[w@ D撟ߔ?椙Uh=/k@ }x+QsxE @ 6 89 &93~){}`_uxk@Ěp~@X`_p/p88 }`_p/pݹkWoSP)뺢œX"\vxbbfC !S80?VĐt-[**+FASJ+xa _,8Dpf,$};vlhh03CÔS Re3yErʋ<|"OXbI JeC)6DIJzd:]Gut}"Q SҴA.k֞lh;rC'n:EbuE·|z~fq/~[a.+n!_/b.;}#RCT|ce;]a,mNJ .rH!4OA;|ǎݼ7inoBKk{k["a;]lš㾧r?7G[O=us!p`z`;]zʞ,!w,PɄaܷ_q\9gWO\20plS3.,5ӧܲ雫jo;-ulx,\vߒ%f}d$;vgυ}do#oWw7ZEɿaˮƦ5rmŖXiiOZIb_Y2졫: ,e===M-m:LJui b=uS=uvb>XpT+s*?k(TVUC g/R~Aڲ)+R\!䭩|}G7$A(tU; ?4(&,?yRNѐj*hNi.PXD8؋LT(hi]q+3*SUI{o:*-d.dUKV9b^:5|R:+&K*ȐONΧS E16_"@EU8#FDu)lo,>(JsiK[FOZ*w[-P$t)&CF9u3uy~y̝Ҽr:^ωMMSP]Kh9 {A'jϐj?KO\~-Y ¾= 'U>K1iI,e|||q\,>qI$NS25qʌrxR\;KM_@X>\T$\kFDڧ!]Ez %HN)Px êLSg5"?w\[[iz\_\z>`%%W%% )PN$ΥH%kS/Sjq…rưTPX)%%\ѵDZ0{1#RX*X+tp`#f ŚU17{1~=FGG@[ Goon<88R=GA,;O612X!`8 }`_p/p88 1oz-50txnnKls8lRtC\B%`6[9|Zv, pKUOMMy<`&C}8^9c @45\?m~ h;|XA;X(:2!O`.J3ꇇ6d<"}^9ā,~[ַV09|a._dݖGw!T. +ꇂfCFW$G8&p@ UPl9ۜ<˟ {Ml~Nl-SV\1oLQ/2XTܽkʐz>m!V$$8EA1#/!dؐ)t,LaiUOE(YTJ T)O98s qBEf\aBل%6>pId].:Ю[Nh3ē8֟`؂ia`,x+[3å=?g%~ i>fB>11%Z۪{tK++ 6ONt p8MX^~Y++JR<{]}CKogpTw|HNNK*;;5mYOg+}ؑgmA9CB#pY82,pɄфW~ܡt8XC4򬴣mvBzc+|*#RJ%+k^ݭy]>>>!^8.nqy{;n_qI R[\V.g4B8I˅I1lH YSt p8MXՆY0=iY\vF + ̆n4{li˘y%Ѧw|ׇ_z$JmmC^ uIQR,)?^8u䏅S\I΅f,z`4!ZX 𱱱Q۸G-kn}IKKגKlb:\*U+LJ9qJݖ) ),c:D>o Yv1 "l-uݍKlsx:<;;~ނPt p8M"rʵE/p88 }`_p/p88 n)bKX["W`AS |pK)p>pp8pl9ɉ8ldWM)g Zҭj3Ϲ.a@3et ky[z<Gqh83=<ߒ>ь2\ wmؙ &CGQ}Ft}l(OKcR=?XF+7hpV>\aJt;4pBS5D=7p-p8;1uC~7.YgZA^\I"O=OJLFl/S}@|DVW:үcq3'Q> /? p/{PIfUEMS7T+gԿPCѼDLD;RBWk cq5;>s 8n)9p[ 8|N->A"o W=p88 }`_p/p88 ĖEVTXVuh*hu68R`B YY_ZjJ +9Vsud$TU/_ \.Hթİ=NMMZjJ/E>3z=nϕnsU"S Taٻ?*!뷹y֭|Aiic谷 v*ї[ 8b96W{NϞմrpew㇗h`goٲ@`׮];vضm_VV600@w 8b8<ةvp G.Ɲ_;W'rH jh86پ};7SLySN\.8|YL{bhҷ򙟏z.|>l|RkNίlm|s}ƊgϒBOqٳ7A7 3XӐH, Y?ONNCߩUg*Hq7ޚ MMw|\_wog~N!?x Z[nٲe۶mpxHLt8q{p"GDp,;W^ll&<SϾiݿeq?+X9^v͛IL۷od^^mI.]ã/b(*N9W=(O:%+zJ8b8mEg<+|>lt`ٵ]e;bŊ---槍iwaÆ< $𦦦a8<0i  IH<=\yt9.=[Δ78{{7nqw+O<[[[MNKP qG}܄+w㹹ׯxII$g8ƛȔͬzBa,YrNrڵkIЮɩA5k9r/(px(7)؛=G^.xß;Q[[֪%=uo9_~y:y9TCDiӦmI1S8F`N8o߾w}?~M}+w|~۷={6&lB2Syfrx}}+WB8np0 s!777||޽7n#755;ׇt:Ϝ9sȑ^8b89 is^SSC&4v_||N8np0p]SG 8k>--V>>,YYYV懥iE-3BS T<8[222hٷ ZjP%!;}`_p/p88 }`_p̓^н;fx'p 2++77w`` {Ewl f45999ATfѢEmݱEFfrU tp`T'@fv,s4Q?<=EgyM U3XB7O1))NjkMp`TpE MLLK/&6%sBKg,dX[(CiѮNHިkcpjSL cp8 0wjʩK?9,kWV.dX[(Ofil .9OX][00_WUpE`w<-pK*:O|?m씆"JR7JZS8[Q3kWT.YR*/~f!(N6@IpE w|q\v}}'g$A͠z6^wMZwh|MU[\V.O);'-&g5s*7hV98`Eccc + Xrhcp8 F`Wt@VVVvvv(0+cYx5Ƞ]eT{r6Bᝄ`_p/p88 %d!8:X8 }`_p/p88 ?.7AjIOO#UK5% dړwwn˙ZV k[;00}jFoh?p2wi KS \@RT 9[eh?UTam-m4T3U> dx|yel2VApUA5 (p2ϓ#_^f8BYs Ϧ4\ex{>n6zW':8|͗|y41M[\~;ng1䕓lM'ug`AȐ?xjǧcϛ}cLޟsOu4kw ˞gM=&>R|K ,!ʌ?OFu3Pp8 8 㽣ƱenJȮWwJz`wOV9UɪRo/\'3rR>4L !C<<4u∙J"7 W]}!j|B8<Ý s܂Nv`K* 6~I")+:34[nN Xp2σCS{M֗ nPI/7`@w|q)HzʬO⒒v:NvbXz!bA:U~n Xp2ɊXcccvjAP dxNv*hop88 58|ttnPp8 8W㭸4ѹZV kKKKuݍA$uG{g>h]Zj0-+++;;>PTs7ӤuieddО6*|Zy}`_p/p8a9]pgl' endstream endobj 86 0 obj <> stream xyXu동{gyWiӂl;s[՞n%pڙ=ƙK%v'@Y YAHb4!0 `B [}~Uuj;: }Wo*/!5w07x 7Ц@㊊,_|u>o|Cv8 <;;x4{4N8 |&@"o|Ir8m66#FoN[@D$<E6hNY^e1ׯo,oE DD7%Tnk9٠9ify/@  36R٠9ifyO}~@  2șw%N1X2kHUlG(5hNY^ewv''V1v֮z`~3S^vsg%3Z@ ȴ㗶6!ڥ/?`! jf54',wƎonO!?XOb㽊tKwY(ws9;0 V'D!sSNF> ;;~/}&GCyhNY^ {q(VU=|b};v}va/drQ}vs "vuo\\/ĺ7qMZ:K M G!dmfWYsxUrMw:2yqCpS7 rHkJߒ!zCY@Vף<*;# W ^2p)k㯂%;@ b׬~G d3ːCMh()UɛH VKۙ.cTë6Fǭ{C 12m HW$MChNY^y'.՛'^exKBWn)7NB[OHXRq`b*XBU]֣.DwsN_ytxD 9_W>0wTXIڽj(Cy ς9\^7>墳-??e4wy,ixVR$4Q5߼} x]cԟt<7^w @ ȴ΍.I%4m:k4fWyOjb9WwG=Se?{m-5__9f$|yl4':OӰZ)cԟ ḟf{&7><<1 l[w@ D撟ߔ?椙Uh=/k@ }x+QsxE @ 6 89 &93~){}`_uxk@Ěp~@X`_p/p88 }`_p/pݹkWoSP)뺢œX"\vxbbfC !S80?VĐt-[**+FASJ+xa _,8Dpf,$};vlhh03CÔS Re3yErʋ<|"OXbI JeC)6DIJzd:]Gut}"Q SҴA.k֞lh;rC'n:EbuE·|z~fq/~[a.+n!_/b.;}#RCT|ce;]a,mNJ .rH!4OA;|ǎݼ7inoBKk{k["a;]lš㾧r?7G[O=us!p`z`;]zʞ,!w,PɄaܷ_q\9gWO\20plS3.,5ӧܲ雫jo;-ulx,\vߒ%f}d$;vgυ}do#oWw7ZEɿaˮƦ5rmŖXiiOZIb_Y2졫: ,e===M-m:LJui b=uS=uvb>XpT+s*?k(TVUC g/R~Aڲ)+R\!䭩|}G7$A(tU; ?4(&,?yRNѐj*hNi.PXD8؋LT(hi]q+3*SUI{o:*-d.dUKV9b^:5|R:+&K*ȐONΧS E16_"@EU8#FDu)lo,>(JsiK[FOZ*w[-P$t)&CF9u3uy~y̝Ҽr:^ωMMSP]Kh9 {A'jϐj?KO\~-Y ¾= 'U>K1iI,e|||q\,>qI$NS25qʌrxR\;KM_@X>\T$\kFDڧ!]Ez %HN)Px êLSg5"?w\[[iz\_\z>`%%W%% )PN$ΥH%kS/Sjq…rưTPX)%%\ѵDZ0{1#RX*X+tp`#f ŚU17{1~=FGG@[ Goon<88R=GA,;O612X!`8 }`_p/p88 1oz-50txnnKls8lRtC\B%`6[9|Zv, pKUOMMy<`&C}8^9c @45\?m~ h;|XA;X(:2!O`.J3ꇇ6d<"}^9ā,~[ַV09|a._dݖGw!T. +ꇂfCFW$G8&p@ UPl9ۜ<˟ {Ml~Nl-SV\1oLQ/2XTܽkʐz>m!V$$8EA1#/!dؐ)t,LaiUOE(YTJ T)O98s qBEf\aBل%6>pId].:Ю[Nh3ē8֟`؂ia`,x+[3å=?g%~ i>fB>11%Z۪{tK++ 6ONt p8MX^~Y++JR<{]}CKogpTw|HNNK*;;5mYOg+}ؑgmA9CB#pY82,pɄфW~ܡt8XC4򬴣mvBzc+|*#RJ%+k^ݭy]>>>!^8.nqy{;n_qI R[\V.g4B8I˅I1lH YSt p8MXՆY0=iY\vF + ̆n4{li˘y%Ѧw|ׇ_z$JmmC^ uIQR,)?^8u䏅S\I΅f,z`4!ZX 𱱱Q۸G-kn}IKKגKlb:\*U+LJ9qJݖ) ),c:D>o Yv1 "l-uݍKlsx:<;;~ނPt p8M"rʵE/p88 }`_p/p88 n)bKX["W`AS |pK)p>pp8pl9ɉ8ldWM)g Zҭj3Ϲ.a@3et ky[z<Gqh83=<ߒ>ь2\ wmؙ &CGQ}Ft}l(OKcR=?XF+7hpV>\aJt;4pBS5D=7p-p8;1uC~7.YgZA^\I"O=OJLFl/S}@|DVW:үcq3'Q> /? p/{PIfUEMS7T+gԿPCѼDLD;RBWk cq5;>s 8n)9p[ 8|N->A"o W=p88 }`_p/p88 ĖEVTXVuh*hu68R`B YY_ZjJ +9Vsud$TU/_ \.Hթİ=NMMZjJ/E>3z=nϕnsU"S Taٻ?*!뷹y֭|Aiic谷 v*ї[ 8b96W{NϞմrpew㇗h`goٲ@`׮];vضm_VV600@w 8b8<ةvp G.Ɲ_;W'rH jh86پ};7SLySN\.8|YL{bhҷ򙟏z.|>l|RkNίlm|s}ƊgϒBOqٳ7A7 3XӐH, Y?ONNCߩUg*Hq7ޚ MMw|\_wog~N!?x Z[nٲe۶mpxHLt8q{p"GDp,;W^ll&<SϾiݿeq?+X9^v͛IL۷od^^mI.]ã/b(*N9W=(O:%+zJ8b8mEg<+|>lt`ٵ]e;bŊ---槍iwaÆ< $𦦦a8<0i  IH<=\yt9.=[Δ78{{7nqw+O<[[[MNKP qG}܄+w㹹ׯxII$g8ƛȔͬzBa,YrNrڵkIЮɩA5k9r/(px(7)؛=G^.xß;Q[[֪%=uo9_~y:y9TCDiӦmI1S8F`N8o߾w}?~M}+w|~۷={6&lB2Syfrx}}+WB8np0 s!777||޽7n#755;ׇt:Ϝ9sȑ^8b89 is^SSC&4v_||N8np0p]SG 8k>--V>>,YYYV懥iE-3BS T<8[222hٷ ZjP%!;}`_p/p88 }`_p̓^н;fx'p 2++77w`` {Ewl f45999ATfѢEmݱEFfrU tp`T'@fv,s4Q?<=EgyM U3XB7O1))NjkMp`TpE MLLK/&6%sBKg,dX[(CiѮNHިkcpjSL cp8 0wjʩK?9,kWV.dX[(Ofil .9OX][00_WUpE`w<-pK*:O|?m씆"JR7JZS8[Q3kWT.YR*/~f!(N6@IpE w|q\v}}'g$A͠z6^wMZwh|MU[\V.O);'-&g5s*7hV98`Eccc + Xrhcp8 F`Wt@VVVvvv(0+cYx5Ƞ]eT{r6Bᝄ`_p/p88 %d!8:X8 }`_p/p88 ?.7AjIOO#UK5% dړwwn˙ZV k[;00}jFoh?p2wi KS \@RT 9[eh?UTam-m4T3U> dx|yel2VApUA5 (p2ϓ#_^f8BYs Ϧ4\ex{>n6zW':8|͗|y41M[\~;ng1䕓lM'ug`AȐ?xjǧcϛ}cLޟsOu4kw ˞gM=&>R|K ,!ʌ?OFu3Pp8 8 㽣ƱenJȮWwJz`wOV9UɪRo/\'3rR>4L !C<<4u∙J"7 W]}!j|B8<Ý s܂Nv`K* 6~I")+:34[nN Xp2σCS{M֗ nPI/7`@w|q)HzʬO⒒v:NvbXz!bA:U~n Xp2ɊXcccvjAP dxNv*hop88 58|ttnPp8 8W㭸4ѹZV kKKKuݍA$uG{g>h]Zj0-+++;;>PTs7ӤuieddО6*|Zy}`_p/p8a9]pgl' endstream endobj 87 0 obj <> stream xĚW]P.:[w+m8a\wTN^ĸ\Kr39't@@7@Iܕ+Y:]Bh_x>Tղb333#O>vjI#@-{.ȉ7؂I(BP  5x ㇆Oy}\jةa[e,kڀf,ٞӽ;dF{ڨk*:.-b S J T%*55*uSkh?bȆyǙϜ3hLV-IʪY+p'R];VqvY0[e>yN4TӾY\׷?jZV2-4T!zQuAE]u7ja`TfOfyݩ)[}k=8c<'a 2,0uLC 2hkV,S5enZu`Eն*;2[ڒ\'m:U5M9 DhYEN9%v4[e4:^,t8EsBҤc5Br+&xKNil4JUjrUZLYPdae3. g+7fNJ!Uk%P}\oUmKzGntj7p:yqO_cg.ݼp[SݟsyX.J9XŤFW3Tq1Z ?Zvw˯z/>t cݙ7ļ "eD)MI8[M n&Gş|qs+Wn_11zwc׌,K)68ũmooAlT;E8ތJ)Kqq>Yaƛ$gCC<\ EFq.Y(ce*y^+uRj@ùj kVdm9(ihVZҤ$(70F"̔xߕR"I?7]J%F3e-(XH 2T H xd,W/x43\fiI .(A0:AUMVPe#dsbmVOzpF17ecU@_ҠJ(XJIE/l>˸2`6 9cdUlQd9I6,b#%, X (W ^u_WMbJR3#Օ}Sv9lgqdʓM9ry3!\bfH0f!M2L]4KLPP BnA* /tZG͏p$aCJ1@l,GGT Ix'Iዃ.Sd8dګdtZ6nIU0!Ϧ6h7]M_peڨ oO Z$=?\ ̯D|D‡IQL=R]׹`M6+a 6fXZsLžV|M4U䫮#7dWb`FNaj 2J" ,,kXq1$8R 0Id1Z]xj ܈]|{?޾Յ<?xNx+덋}LUq2p9'ҳٴ ## OλnN\qӗg[ou/xeGF?pW/Bq@yzyf=^qӋ_/хw><FO_FR`%6X(b -Y 꾜Dy!DMGrtr)<Z`7T4.0S3uIC[i834TUM'i5b Q9̑ < XhSLNT&ؕ h풰B:Bih&4 R`@*‚ΟDVvYLAhc$ 7N-Vآ/9xK.2HCۡ[3rA#CB~\kd3+3jsf|+i8aW5X*[b)E(p0 zO|!q%,B ,!Ƣl\M#D0a\!Udl;Jh%PfpilE)ە*0 25kCmQa1 ჯj$#{⥕0bԬfRqZ-K=F`c. HP:}BVO1y5] /~W菮\}r㿺x濍^ۛ0ՏfO_MxOc}"˺1,KECr 2=1{kw\csWo_9qYל;y1j n lJ*xpGKG_2K 7.L-],xHܲN~ڝiΏхg{g{/zkN,8m9Zd3F/+ѢkތJK1~.r%' ~[GˡyopN0beh6l tGBٌic4`XۄJ j @t6(PƊХPǦ V =8#] `EHL> ')HT U+ƽGJZG1FcPVɲ 7xcfnQid*&)xs0Y9(5Cr"g-Ts͔QrSmhMk*X*&_IZr<#7Ha'e/EVeJ5^6DIʹ)9E?:UF(AS)/d糉{fs[/+~x_}޸c?~t&8忐~cE|92p2P|fP}ΣK7|qm囟1ۋ]51?9Y>Vcd>N_\L_o٩Hم)A,[ϗF،AAh@mQcIb8o={N C-;} <#1#og 3c8I c]콣A>zk{Fo_ř;PzeuA W@=.[swOyc_q}qʭSK]I4 ~2c{<8yNic|#1[ `gIbctwY?J0<,Ӵ "J5]L R+R/;x1j 3?|{󙱙cT$vqRqF+ Rq@(='Զ Ib \aW Ki QN𢡊-@dlcc`]ƨ0e1B&Jg& , %1[cic!EI܂Dz4,x;|TFR57E.sy-L`h+.-\znzߎSzնh#JdW9[e2w7.\/\;{K7>t7r/d(А+,0 @zs-vGnKO^/k.Տ>{)hru c%10DgZ#Z z^͝Jb%X K`<%t:ir2MK1ND3D{șĠnEprM3IiѢǽhm\ݬ]ZfPPKh~Jk16eP]VGoc$P:1B MĂP2: `:f5ëÐ C?8cs'!IYgVciD6 A*0ܔs5> _s3` G8 b38@@)s Yܜ-ٚaƌ1+B40L\4b|+)(eY JFRCbv)ԯ#4HXdH!f (lĐ4` tANP!CM#cppSƈW3nlgC8 x]-PR0q0/Uwbz+#Č1za n+vC0. / 1~"f]nK%F§22p2-f~ J@ 0#>cn72HLѡ7 N݀uܚjE%3*;#QVZu Fi{b70a(pG#wx!a7z ]ۑL-rbV4Z Y4 \ Vm{v`0σ|`t<5x6wq4)D)F6 ͕-o*K6:݇~ ƀΞ`ƢʝV +)`9o(AQaY,d 31 ;#bo|O0{v;lZ+81;F{KwT{Swf7nӎTor7<[7:1 =w]N(+Y־W=^u7ʭDXSԄ#m{NgΟB$mWwzeiMUHbZlU*OK흍n6Vn>C>Q%{.]d}[jL\'ϗ/֚ 0c;ۈע8LT!d*rS~ JKPR΢+Ueo'o",lXٹ,%HSa h6ad`/k=~gW]}ܕ>O|p~w.,?rwf_Sb#$/s=_56Gj+Sޟ/C_ل Q f)X+GTK]əd\Wժ`a .FOe u_lE!#w1y4aW'@P 5s^ pCrP I&Z&<ЯrW1i>Cgoľ2ÏPҀE{\Qz1]: *J7qͪhtBg)h,IݿF <_ ڴixLӰa| nI|?z6̧DW045 'rIWNG"o 邺#XXpIiuݯ~YJ_TBw#g/2 kjODޡz'ypX0?qerGTɎߴ{ u/z$RXtGE"R@,#ot 33̟4l~NMNM[ km׸l[m=Duov{mtQI`fn0ry9#c{mi-hd1+{y%]<Ջ_U$swùn[3oY6=g'sխqM6Xq1$ce< p 0[npVW,EvShifT?9\ȥ2K Ti^YjR5yCfoM䴮V4XtSM^1ZcJ/Ursr~X$}sBoEMaJ_n˔ TyUY*`OhjVJAK rk/WLWwsw6S777b7+;x~+U(1Z= dGc9` WDvi9e;'Fsn3B+ 5:h`HAncs̘iRQBSԕTU"mcwr,W9CkŖY ƗP;1!C?4C-8te@/DنSH )c,T8Z(uX@_|@ۅ9"jGRA>}{4".72E3' ՘0Ɲ NB.jcdW svв4 3r3gæ=d!8C%y` HW;s8peqovK.DS-8~p0#rL tϐz~=y-Aќ[ρ1~Q[Gl!<hI/}&WүGsBڄ"+y?o&Ӿe_D~ٽ ^^Wc70H!A7z1<,՗1(wdv 3%?<3Ԁ. I3c5c,XFb1D"owDܔ;1)\0?)f&Yt}]8yllz}vw5_^9 bM^'mSFUuͪfQ7r=]-CKFh̎n7CdmZrtd-$4SC 4-c蠬gXtl%3l"db]eH ]FE [.$6F% 0ce?eC4-T ~!CӅw W8LQ:Ħ,E`*: H,NSHtn43 qpĴu _A?x^fx/vtԼCt~Vh3(N?E:1H:{_gG..h1ɔ1FG_\`=Ǔ/ŸrCfC4!W9:'7\=) 48!י]#&1ڀx%9v7Np.!_M:~oH]ǀ gB=Ә3AcޞpșsP W;=CGhS}NO2g~ +#88 ^2B&ԃ EL*dZ >0tIOIbiVbN :̙+1+n^nVnMrI OiVs1D+y1Ƴ`4r @up3F=1¿jb]/HɬNd,D eϙ> wpٓ_W;`No`G9 zЉ%FƉJUE~[P֢3}ZNjWQԪZEz5n9e4 sʏ Nٰ5}H&ba jhuLj> 9LbjQQn4-niF$eQ%'2? h_/̀z4NT; Vn`-dO$م[g?oe1H*khӟ165 I0t4fNd"W(HbqXFCsR0s1r8vMasJ5>wC?A12(cLNVx1jn旑G?Joҷ~9s1OVe IefƘ zX4K OC_DAϽة{ލZ1A^@yI.2 [ď%{Ğ\5ݒ6_温k%Mͨw΅Bp"?x| =ES{݈.|'rݒS^ vraEV#Ἱ2B?9h$G&["gh5<ʍ_vszwMs^6/~8DZ_6k'MZEQdIDI)H$e"mM%QEHCr84F㞋$RUu3$EZ>o^OB[߯~&5:у @' ɮU,zgtJ.j4vk NΎ3Df Sd?yuwЯ:$9AM*Q$2# Ҹ1"k4|D z6 vliңd<2c0"|8|5&PX)jM)K XEW]`% 3b4FX (|nO(x>Q_( JD t:JmŴ ./ۥ m#hQBJI TFE>.ɾz J+PL igM2>@ 6 űK0Yc)d@!džBm`'1H24h B:ibf* |jԬt` Ԗy.=N#dz8JkqᏱ$Z*|URT~rWʡ#@2mZCs`!'8hӧd P9䈦za-EUAMu71PSQA5#TcnBfCsmmj?Ypxdhֶ.% %jHƘj .9wGuE{fׄ7 wʉo; j \0 Z-MCYҩ' 1H7hn%è)\f詼 j*q6<;Yo4O%$:F{DjvѻS: _񳰲!+`yHHμXWb.)5;7#;16O`,hʈ9}fMdhg*pZn) J`PQzU7͇]纶|v)[x]V`+jXեt'=5`4iY12E#gެ+-aAc4C ^ h@CQreTfF/HTiHYta4S]ͺ[:C@zRX %f1;_Pfc}FcR̤@ Î I#<(u@Q5F ̀=1 z' ٘3l 045A5JBp)?tM.W$xc(N&i+ܲ}k<~t \r/7 ~_Kh˭rWQ >iUCA` Ad4Uenu1,dF|7ܦEHf5#̬pA-YIJ n`Yj!DFÁPi@0pr&`SVYj>n#d&m aƒZ3A`3g| ;)Hnކp v=g@0`L1D\cdҡFMTKh8Ehxi#*G1l˭#9Dfk,1Z F͛_ΦAߙi#Ud,+Yz+Mo2N ,jӜ(|JÔ2h` V bRF3s[0yCZr~6L()}lYĈ!N.044bƹ@-g`F?O?:-F{k} |P-:qmxOz9_`"X@Fq=؜zth( 3 SdDnXH KOA(Fn20̂%h)!>zZD`} iVTVL]{砨p!tnǂB!tbi<{U5)ɂ`̽!h056 LO8Ͻ$mk1ΤƫFǜ,\IGt'ϋCESFrq hgj!pH18C!B[Gwh gcyAW0a^m^?c1":Dq@|4 }%p:x*<[漺ۆ&O$׋Կ>Sd(d2)9=?:|7&_7^As`ϸRGw4Ph%a2v Ml  *zk* n;AD *׃q 1/GM)QV-6^4,*+4BFeB)QD~ώ@Td L'|P{mMQO ) ;e 5&pBTʶ|v.WJgGXs{vcI7 6χO! _={NK;9HS>pk/k8:; cImtI$Yn EttZHT=',R&YHY dǃB`0..g %&MR#;Bhds+HDt%)Q^zChJՅ6! K؈1- NeFP\ ӼVNo{msy]v9?+:>2tܾ_R٠/54)L#??&66thҪdu}B 9 LCh@hpDK(-1L 0CA !\ۓa_rr^"7g 5ih@܂j *SM)w *IBM&A&(peUm=o{-_༷r=a w6¦׽eݻ [o} Ǯ}5wE9Uϛ:vua@A4_Zzdw0z$'sSj2՞dS(%g-`"ЊzLN 7ep4**2-gf)-LL q 򟄍tI9#Tc4$&(%rJ8 D+)D]D@4ɧ`0 bf'3"t8q4:),KQ̘q-ꔩAf;5DA6j˯" 1F TSi.3Tf\w9cN?n2G]ӭO =jּaH36.\qN%EF25vFd5DlU^jbHXf5raDZ.{Bc1ȇcx4Nv-Y*!'xم]8n& FA*h0ۢcH6T㫛MZ/aR4kF*9cCG;XN-+^Jgo+=φ)#oXwb4a  gI"]H9l ,5 Yq:'h?6K\Tҥ ptj"4 maVS%Ó$g?Qeh ӹFEaFH=1@fسD"f0הJj5ZUkT7]! UۧY412O i\I\c.6dFRqB.4KKP)"ll4`ӼVD2d?HxA]0* 8 } ㋎#~"0Xܥh@%4cStd !49DB/c#4!#F8v?>JYSct?r7+ C\Y 0k >C0T#$ AT"ԢV5v$ɢN`uiD53U[0)T-j< 4> ?DR<=KgׅᄉZ_Ջ!i0eV(8wau{|T;N~N'7 킧vU> gWt~)s# Țnh| ՈqPG ꟰1% jDFTI^PP5 '<0A [X(D@J>gOpp !!½!  ]2uC:^RN0$wDve+JH"x| b ]9Qi`00%e?wT44~"fc8ƻiIDBWxh C Fb $1LΖi*(Ki!39hYou_6t8GbnC{Ŧ{#1'"k"b4q(B$gBv!\CILOS„)1m; qg4MW64u{9ˆrQQ̈U Ib3Dn"oB7)ֱԚ!hp( 3B`0eFEQ1D3ba̠ 1ØgcK8d1[SAC rihvYKLb Zc\h;} !*%> kWbgvuiScC%qӛ`Tn+3'e+BORG EYKc T ٤ w¾5 LJ%|b21~u0. ΧVĔUn>)Hc‚U1rVÉݍ"3ֳW%]a C/>SS~TTTf)$TrXYBeO 16 FnR3lV&"_#ej妌Aw 프gV|*XEhA,NC1'lM**thBZaDX\i%xȪ[5Fx,B4F"45E+qp ߥ¼HR'4BӔ9ޠskƒÆ3 Ac\~q%dv KL4(XLv0SÂqv ;Șak1)($cqx/f9Y) Д^bzx1yDxe(07a =4bJČ[o>hX;>Ƹߟ䵉|W\iJs@&8@ i8cm+LRQ4,bEj r(4 /8cl@lQLä_<oVf1ƿp佢rca3b0QVc2TefFh 4u›?bd60FZ( P0~ n!+𠹈 xz -!zG "Z2R~N]>vwQ>iZq^OOTǗ>M;}z+ib.<:;O^:k7G`l\ %\ߜ+Þ f]dždSfM]bcccc37`XdvRL Mq7.3;t*]#GA 8v-n*T߫2ж%;q [O0oAÏxFLىwQ!w 3pP@x렕?h5;q77./m'V vt+Ћ9n\ lS,L rPop%x"m_wޅX9l#gKm^XK{G׶͵  <ʋ]%[*?C22[yhjt[-`\mؽpw92O ]fv40#^`Y 5/ wႳv-y |:(Jmyff k".ZӳR Ϳj`gTtd}vcٖs59X͍cYcr,Hve_;a}+U8駫m/ݱG~S7Վ Y@&KҺ\=V &̌߬͵  <$=1FT̻.>vmcWOZQט _vlT2o[lGvH:Z;ZVdye~%Gt i4KOVؼ}U Ogy{):e^Zm[\J \pËxܠE 7n 3=N$~c7zZV9m/8^4B:V5/ھ dwp+~d_]+5k/~=zE7P* o% pҺ\=Z#fj95 -\DDkd'h~{q}K!cVh:kď:bm56.e_邕 ~xcòeW[ ōKv+!lYofVOK4chВn9ccsqV;mN_+t`tuoŒg{ A6N&=Jy͍~J\G5-wܛH函Qx2.v]bʃh c̻[/1i܏O%b.v]j(1zF}Qcv̸+O_oYf5-VZre[[[$m~*nRյ+P`h_қޅ,ظp]u+ZY9 G(?Ejl(ÑooxZn/Ɨ#WЂ64<[ꕦN9ݕ̒Bꣽ]>xytw~i>j߼s{%~g?^ͧ<9UYZr6erܪi97wK}lٖe+PXrssԱK垅8bpѦ~wO^_)O{z- p\}'N4677K4|^vVAk1Kf.%n1#nx7-lM텰1oѹ k=O5<6nH~ږg;ATޞ޾ήGrr?$o#؎;}:'Nɣ~ZrԩׯHTk۶mR9H$^\q`0XRK-[nJ{5wr qBB̑ WXBB/'S~{v M KPzo6}+pJGŸ }Nߧ(J-B*W]3>9v, _X.rd sqtկ ?ĉ{rB_}qS7,]Ze=pgYWYZ֞ _L---ehr,5FWO}/4+{O|ZOztp%%%O糐\y%d}n o~sŊ'S8k_InؗsCκt_stVzccG{~x b5ŋ/\8u"y/*泙'}/,=}=["o}bOٷo2.vK15F"ED*cAc .hw ,?/nZ>N0 |7e|mz^=>T( S(dj+=N^).t3S;Afl[C] ?U; +Soҍ%m+iBZslg%3jh.ظq#p8\}c+]\ bFʠ *UV"tωޛQchD?{ŵޛěsoz^$r7fƂETJi ."){Y; H;g2.<|ps)=ef60o ml.|,9kAS$1niF{p{0ݿĽ={2D |y~NaѼ֗[ͩkjxǺr#REۢF xoobݚ;}^a6bo ̙3:uɓ3 x||<$XjH8{,0Lbb"{.8@HH! q%Ix0c zoZO\\<&~>Nm [O񗬭KJJ{a%pƟx_ԕ'(w>>'s \pK@GpxM(H7RjO MJmlҀ$%1Z'W7&[NúuY膆ÇSX2ْ8NQnÔG B1͈ot(RJ9AnK-/$ȥk^P0 @^.(nQ߽30K%1qf" %5>>nҐM" ";\]S#9wwsvS6pz$>Bd%'ߴK3\*_h[' 333h2#~+nNs7ޞS(¤ * (5<26qktqx߭qu-39TEC \qC ;n{agt Yp*'c5a'/h:>jmomh+9e.1u}w#jA z߅f ,???''k3=2H.}0DqԩӧOMiÈ… ,ѣG ~V,!C`` `ƀhYG0 1b4]"###B577;uX(weNJ99ƛ6mڻWW]]9-+1xe?~ҥ}:Y<^'ЋԔ|t˖-,YRzᠼ%_BjfM>Mk--$=[rQˎ $M_@N`c @tY-KJf&Qzmέd IJOOg%.HIe sCb9 CDzru[EbmiQVp >LT/b dJllɴKRszN];v$G+K-yʖ-UPRQmnnX螒1jz NKE][C;sXMKWK$ǀ1xCce1FBjlQ&\Ш#eMM]Wo=B!cY!]u"?ՎL7rnQ|aygVYVS]clf!oɛ>1]0H![[vIj.Au˹A*!}JgXkW:76V "k1Df E`V Ʈ#ڳ>mM!] LFX~Sv(N;`xl(> Pv ԱAͫQjS JR%I,SE9{r=uB n/1#6] t #|d61..}dU"##@w1ק9ș60 @,ZbccT\\\<<<|||`? ,ׄ x4F/91<<HppϞ=pSNٹ߮7[us<4y57rq+%+BѴ?Hus#ƒ|W\% &J CH/@)G2RR]]/`#W=cϗikl߾Rk4\>mQC !ѫP.݋PE$Q#ԗ!viDKJmw夓az,1<’86 0C41+^0)zXhoGh=Ggֺ'DlT4bYEKκW83!se h ؚOwmgj GGY:;""1ƀ1ov]M]7nkBԶ: l@a]FXQ5z,XRh5BP_{Sx#V{yߕ%*nqJfԷ/d676@}~r泱#j䖍\#\[fUI@J#O8d._x #_]9&illǍ_dWɀ6Ȑ.|YG㮮2Ï&1ƀ_!>>>>99 r1^]ivǕC;y!o i(qjq+M6oQ7 _M^Fx1zz4@%ܹsgXX TiQ$*!! ɀ(I("j>{}}G--cSWWnڿ+&ܧ[#\Y7)QDWQ5KV{+n$.sCc:8Vf:OZ3.L#\լJ,-, qsHJW-_S̲ V4<@CKWK D2ay |,,!%斖ήL:,0+cҟ;{^l瞭_Tԍv{6|׮&(5DDt11An)emָpEXͱefM᧣)sCo-=(AƋ_ntcW;xdeiϩg췿,ADu߬6nB#:ܾB5joojfukWغ]]]<¦K_ Qjhh(0X$p.erMLxEDll,~I@+==^DH0`ussg>>>8*3bPNNNPl٢}ʕ#Gf&)C띷5rkq<@bw/PEo߻(ȟZ`}qoKP8%;v022\zHEmcj STZ ᦜ!"##srrUB]˔f9VL-}ݫ裡JKMzS?MLL 93K~GQ /뽊t:=0~q {PꆠV@$&/3I7mqїu} |0|"?D9r=d~DmD\IIIv©8Q7,_5-Z`\k.ccc*]:ChQցFmN^c/v ޱܜrpjҳ?U ;`ᓒ***^!])K OovIdB5hOs{`b7mMt/f=̀ `N@C䋜i; 6Ha[[[GG4:0ӥE(Y& 30cq L/xͧ1 BAE(`?οv7+P۳G:t\4kA cdX{v'֍N"?wU;rH wwjםl9F)XPI\t9)ۻ:PR|N Y6RHvdRRc/4Te#xY3)4}5Xڻy4Bj|4[(hwxg5XW ۏ ǣ2f;׵Q?U6 *˹JSY [{-R? eN|#%v ZÁ%9ٹ9yY)-UTT555;c1@NhXҰ89T7? aS3g#Z͒u=Coָ8 &[H55[ ž\s!!Bfffg y?|sOi6׵pzg G Czb`>RSS rssR!c V5=_8|%~'9k_a :KK dmjm߃k\>/&.a1& :~$88X0Q]}=xǚWgܾ5d 8ⰱEg< }hXXi $L76yc|rFe3;LLL yPds}X.A ʽQ)2X"4Riǯyd\5:l`wYhmz?'7/m]=]]]oB!OE*_χO>cVӭv1uȄ%%|Vjb~@T2]\A%'Íhjjm߾ؘKHR1Jӛs%2hn`{2~ލ,Xl0ʡB_.X!Z#_vA?d\BEGGKF-+c p\5?hCAA R7t]IHmmmx gdҲ# N|&h KCCC!r N$AG)9 >(O^ATP\_hls瀁?XTXr 5==0i +++TO(pLC kaa-Z[[h0ŋp)g %cc`ABk>{,; /$D#"f`9 NElULxZa_N{^@iApgL̯9?&,^ ~\>5&Z ) K?LQa O'1`&@@pɩ -m&+6@p yn ~{*>xa+7EIE6i1*( v m2?Ts Rc 8&A߁eb^  Wǣ2S"]bILk x}c\3N` ĹM1cHN?_ݜ;" FGGTG< B w4u J .\"""ݜ;" B211:s,sD .\""2g GQQQAs͈0o!vhl1F1Zo DDDDDDDrkFцF׈1E1@hNbg k>䗜!\{y/BSQ5@c cT10F'0, """""YQEC. """"")qƨ6WBccɔ;2]8Iū3x2%.~$9b3 cgYD?찈xɟU(C{⿟oФ]N|bJ KR/1d 3Fc2_AHcя 1eb޵EJiW2۩%r b' """"")c:a_ K8[1H:k:ҙ# ?dc.t=yyJX578FLDDDDDD2%d oSh!2Hp(ӫ'fL 4XcR;ԨJ]BmDBc4cpEcp@&cЇ,#:k[*TFQʡj)M.9!0Dc)̸i;H̗13:4(H+Biw]-y&a """"""\?07'P= `b iGf͌LI4"<2FzqCmy̼1*-reOُSQjha """"""ŒQ\m=R[^Ɛ,a!^e O#QOPEť<8.>ơ\?W@h`:c4?7x`Mlj;HL|_䙄1dj6c4fa EHR*ca c}6c1_ht """"")`.cTƐK1d 3FD\Ys%1DHDQ(11 `wF6ld#؆c4 7DDDDDDD#`i(g΁Ʈ1X$1T{10ct 4 c03F/_cX0Wnd#F6lA;1 <DwH.Hb]"źe*1vv c4 N3FPPм+,]+R RXH.<2ea 8#c`e ƇcDf&b~%kEuA)օ'#`ih=WG俶.-K^^!/O!!Ϯ 8_ȗf X>aoY>KȋkC_b/ }U1H.Hb]"ź$1 0&3FKq&7;slS׶Xg^y[Ve+9OKTy-["Og7FX"ź EuAbseYR*T`{F_yZ=qGrQ/xܰ 1|j6ﰠo'쒍1T+ x_y;~ SR #;.4’mYA_cc>7aB4k܁Fd?wׂ VLT/Ǘf[JW*iavR{ ‚TOlzB%499ꄣ N$حOT œ_)BIܙ{ bȌMJ ])1G ClFx9 pꃠSd+lQ1c c쐓1O6x]!)Yٻ ؍n+JʘxeD5]T¢Z;J),\2Cz2XrȐI3@wK = t12?LifI Hv@Hwνߜ1ʹٜ*)nKFZFl:V}RӒj!4)rJPueWL,,bl[1P! +v''+tLڟk 4ϊ ZtZGGD.~pTzCCTx@i$kҏL}|aYKԁH41";_*>Yݛ+m;3*N.6Tgz:+m#mEUVy2 Zaudvc+b(I)~Sm\ZŐ(kIe](Q\C1 GO gL*Gl1S&y e׻xg _1hap@W0VcqX<X23KBʩs+MGܓ}D13|a)=ߩfg}Hg+OO yٽYd*%fL{+AmX43?1ASyG8gj8fWCKZ{fWcND7o>aZCV ʴI).=|jF 0``\9,hR<1 , O\8 >8$#jdn Ms׽w %Ƹ;aCKN#,5OL.3!w3.|! )D1Th>OEex|Mԑ-{r|IƠэ<a7 {C ;,u6-(%iC-o'։#ϳf]gԹaBsZ*XY>W"AJ6.&,SCRXU-R Zs` ; m֔c~adK۸܌! &Ɛh]M@ϛ^݋)!MyMPh|BgW100j*+\  0:E2chTBT1CecjI[ʹ-,+Y|h BZ-Z`>5d.T a SzO IkRI>m^z.4|FxzNVcKT3lD<<;,osaz\ K|zaڭ+?{gGu.xkΛ'gf^xyIx;$$A lIZ}_Ի6ېwﭪZRIv[w~N}{խۥ/}oG3%G'Kޞ)yl{!OئNB\g E2ݗ̏ĥ/g8Vx%_ZܭrМWKK< v6Zg,]):N^2?j^[?T uT&?,T/!uZq-jBc(Np(q٧}acK۶m{s8}Y4b-b-81HT&V!5 T5!jׂkX1h(iŽ7rSqsgcsLs$,L&NÞezuFp8 }>qNn[V FΡ/r8shj19TCP! r /'DCX1-a5` ;<8J A8͙Le0/'LckխE󫣅#Kȑc88###59?o[1 ƲQ$(`1d2 "؅l䤆3 r2.ծe6ekYN s!_Q '8G?2aa]Cd8jh1-fVhE0"9ECӚd@$Ieg1!kI'1z. NR8Mਆ ԒƑiwնM?Tu۵ T+NrѽZQt!:8G;waaNcO W$A9q1cՓLb,OǰtfcϢc<9JbpUObp'1 F  8*ZT]VuJʂcJs!Z͜898G}qsrbīU  8a`N N "`pW+D3"Mf,XKb\p8$B FRp ma p123O>;e.Ę8FspQP@,PBVlO!jm,72$>ˉ2C8X.,=R$f*/x뭷fTWW5tP*:^ڰPejLc8IdpQ Xc\L YΑD*?P` uuu{`g)Bb0e6%0b"S`40*Whid.ƝIm0X"<0Z") YXs1z~̀PLC9jCA*L<3m?ɤjPm5P#/ȋ6bMD/I^̧(-Ka)^DhXXX=x"ُN}{]v>|>(--jhhhoò$4jsid7ZUE*M"I5#%Dqi@K%ra&̌3"oڴ߽{#G@3N0AcK嫽C40smgPySh1̵ wэ"2Zgv -8Fli9ZfI؛& [ӘqHM zQ[VB @@rz*꫟x≗_~y߾}PüI]pC]x|0^dMTxXc"53c(c*(1$Mq>WsĘf.PhIY p A~yd2;p044}޽{~ޓ4xS_K)?m 'B;l!ҠXq̋ k_'E%H06^ ~|J EqP>,B/kKM&ky䑧~zǎ~>䓊2t=qw+ $+.$b 1 Q8n s%112矞){%]`/]~+[r/!G8M@ᬁ3é Ns_3Γ{_Ҍ@ ;F"fcgBAPr X7$t,Z‚PcJCT3ÅaRH5cp.?gBE MTaPbP׀_G/A;(Pㅚ0% S "p{GھvGaZmōڄ@m.¸-mnjka 7VP#o0GqzP#)CPQT €2o #FĐ q%: b#&D#",oFd#@@roD5%4nf.LFIvHN Sd:3ec:n^zMG0DW{7ػڕok}ڷ5k>zdǑ=nnߑ#G^G^?ss=QĥA#{G%rUou5!;9o߸|ǟ}W_}u݇:vǡک%tutttuu%ދ1;afx9r)*&1q _(6*ӁfH3BlbLj HD+𻫗M`,`g0@0B6Ͱ7hLx?Qq[OW_N"fOWVVvĉGܹ'M!LjU7T#!=|cЎQA!GFFN C,VlK:a#-` n -`+BK m1I0ir`A NQPKQڧ+zu"hY6afH0Lu%|冫 ^Wڽ}|v=M6sv7`y$|ٵw}¼ep_E+tsK c1o\yu߸[~t?Ο޷o+4C>}[/}u/ɏѐZ.chKb,`tHiFZ\S/.1!X. 0<᷏gh29f3S 0I^(LN2x*{ag8ZTkid{~g|9{_vPԽ%%%'=)O ]%%`\IgdgUPRԟ1=?=!zr* #m<,$0!L-19*Pl#A?CX.qK44D<~r(/Ln'M!auԏ"T~cswԎP]&`;aBT | oQ7*P>Q)c32WJSXOo,Ŕ!ք$"D%GT;[M#Vİ0%OЦki$ޭH`S}JIWN)CK:v+<Y9Y_ȡE@v17^ {DSӷ!>F[[Z㎛{q'7 (rtˍ-78ρ`4gfCi_l"Q)IB; a,ވ6jKT!/lm'^k_p =PGQg}%(ɼ> .}䵑i>4|܃qǦ]igt6(/kexڕVδҙR8 /@فԖ !L7Wh0 TCӀ(2GrODzI7 =q="AIbzCjA3 ;Ih1G 쵣4#6FP5laVIBTPXO| pMazz0XkbR`l.B l9Y" z`% <` v5˒oM~-lVŒ9X4T'L z̖y=twJ;zM풣'{Z{aF`j<& =_>à Fh5#nt.K.:np놦[7ݺouMF7m^'ټNyr:A{_~ ͸>dwB wo^7i]umZvzXVmnP{ћaMb4칯|뺭'~񕝯;t?ukplpL57V;t6/|j `j p*#BÁ08̮#|:z6S@"qÊUq D4C 1):?H8;,o{b? gŤ`M#f|w.iO$O$[G;aĬ4puB;$wǚOW7y;v}oϜ]iW d`3.}oލb6d. $1B$Y/㳾wbŦ1pFgqDCCCww7T&fh=cr&1r@H3@x!81 ƪ'1 ƒL&Ѩ=G/M<3KT $̑ LdD,bXO4]*鑢{CFOkv)18P=8W^p^zu'q KhvDuOxSZr:u6.)=v&T_BJ ~oC^; 7ggIi#'θbgYGtFf,sh6iZi\l<,T;peN -sȆ1:j|]ũ64 ʍ$#r5ܨ"*4,65 MFcfv|.m2!VEm hDF!!xZ!E 0FQ=FU,xQD }B ~se>< * cjF c^['DS4r= &^8$^BL6mfEhE[6/@2؅Qz~md@EA- 1`81l#Q0#,-p!QHܘFJ19s߬{c~{7v߻ލ{7ܻQpFo?C? +H*~9{), qP>,Ռ Ku5g()Oz S۶=>C ǰ99-1t6nf0A1fxc) 21ܴcu67_ 2`@IJd0i?W(ˀ)O$%769:[!?W^U1qw1){d}YW 0N+ ! 9P~Ƴ @DRgWXzAc`Y{-2k Z³)4k Ou,~`MԘq6), # uؖV >fKQ$pqܯ Xt1|c %|{0݀*USӮ69Z=Eo4In6OhzP')DADj@b##~zgS)DRU0kD@8PG&|_ E$4J)f m)Qxh6oW;NLen؏p&ҧؠ!7ć H-] ֤Кb#0<%&$ȞwЖt>wmׂ_?ܛX3{or7$dInv-r,N2JlX;AHʙs (J2y99}[4G#8ݓ;q| ܭ8}q WErr8 LJgg?+-<ݶ7o۵x7/=;|?̩Z4Ljc_ck~+^rc1H(ïwHC cf͛7o?d[}X A+9~t1&8a#H@C bPǠ=1D ٮXz>& ,Pxf>csq" t1%DCT$dѴ7Q:K5ϨGe=c0cK(X*;USC| u ״)\.izU O/ 1m f[4b͈.Q U b쥖! 4#Hs&':@i$a3CB F/GǾW4, (E$zAVQ"]HRu V3yE8GGE3+rN_룔V)13hfXZqp_!Ak@p|JECtRT.ӥu#`S.N1@>Ġ1I#aIc2=;MZW"Lf <wIPq\_={vڻkC{:wl[OnQ?? 0=\ӲC8pd8>< <<#䗘S*W1;Khj8w5Y 87Er%4Q+ۙcP2#Em`VGxcy6A4NJ8{(i28F$F,#æ ӌ~u xBK_e(5.WCt N3&ޭ+fD;8P-ET䵘{e#2# CLW刵l)* 0@BD) %CT [tnjϓ8xᇬf1P3K쯀Ft]W1`J01{nܑpP󂁎!,܃(xHQTx J4E 8}w|U}苇dLbnû/2.[ >ãõhpL8< @JsKd%:Fp;<9pW_}:k1f׏WJEr|K2fu cx7q w2%mmm/_dtbl}Ǹ :ƨLje}9Zƺ1#[։ 4!' j J̗dn> s ^?P(0LbYtX $r!&$܁4*E& .c`W/޶4cGJ2@39Rq>_PF$pv- F>.20B̩aKjĚ 1Ofi^-<,r) oGgQPT%P-ٱGoj=9˲#e;$!ˇG_^9h>zz5`{5ؑX8G,\5W9wxCOo?sAchm^0# w~] fc(dwϘDLj&:!΃c|ǭ/^X:Ѹ`{ NQt Fc-c# $   B)Y i̋!15#S&3[X.DP<&4c,2fp:9_[L5\G$iBshBnp~K ly+PʇP +û-Dܲ}!Lm[_J9qۍMpR!6 oN Ő3-ƌ#%w‡YTʱlxX c. Jqz8HNZze6&L"$xF` Zvq]Z"Py)!]%Po F'`T h ǠnCC.iT5x htR`# W!i™F3qi$f`ĒdA3F1]By4t 1 Wef(|L4fƏ~EP".!$1ԝN$y,= &ǧO _s%1UWcBi0S1.b4Zc ER׋F}t  }љ3g.\000@C wt:Ftu% b#HAs F"˅/r`c_QϗRRP?@<(D0$d%ė!,4H4dzh#qW?8 ?hio|Γ43P)8cEw|·Q qi$.F *D9*D"":A U qSls 8T Z&J#ZEf1 > Z x[U>PԌ39LL9S`;# li;;@7ȦՑY`0!*n)":  A0I?c+TT0.k Z)2#]t. 6^Au]piyuP ,lg\EfH 0R4]58Ҁi04:$iĪ ~bӠIj}D5chƐY L`@cY$ALB4&rl(4_ FCA:Qʩ7[Z/(@+BJ--or+m Yc]P {׽-yA;19#zL㙙#/Uq^Kwwpۆˆ=ɌisHi1;aNbi&p(ٟ1R5 3N7`"v2ؙ2CtA-g@^GQz>_P5!чq@6#H^ \L9.Lں,æÆA]\ΎǬ']ӞKeuGbL`좏E.]\ERDtHߗZ.fX෠;HC(RǨf v!]P Ucl;K;DGۅ䖚A7'!zhi`%+x4D6[/j4 yV36iB@A3 bG3ĚQT˲& Wr47B3s 1ڂ! bx}hLC|.L .=t ۍ7NC'Z+9cįc`\ ubX1r2yS4Q :F Z*]=I^6~?UJco(WQȕWD6 {-/l:#1Ls>x'Gߴ_~RǸ#?WP8ULcӐ[#*4L,N-,dI\@\d4<ƝΛF0Ō-6mʨ]#\TD2#nq= qEEp+j>z`f}eyIf0aEhԵ h[ԧ{ͩ~@{j@wf6f;?]T/ch.Fv`D/ۅR)v:Mc"-cv1iP3-b*z-B,UiHfp-5F5jQV38iftI:wIMVhVq tf4&v 4Dy!рfib[kU; wc_F1( e]UKlO1"q=99Zƺ1cAZA4 eFW }1hDFTvx]>+u [GSCec宽G1 Q꙱i}9EPH1b:OZJj\I3vUFe֨Eu[L`θ N x7%on$ۘ)"и1< J x:jFrh.r7ЧcKc~;V1*tcڱSЉ,N#V{b 21ZϽ;-- Wm 4ѧp(]Cjψ7n>8J0 OF9'dʕV:S {Bacش9*3E& cx0G'-Q->Hឞ ?f5gU4:#>mg,4Q' 0 肣Ш>4jGRI+?uA fXXX-cߧWp ⤽{cΏG mAݙAA!a3Jd. ^T/k"\op L8 NŲ䈜 F87j't0L,`vA9 .dpE4ҠZJ"qRI-4㴔y1ĦAWIuڋX"GVNji ۥ 4ĚgLbqsj057NK@4cFv+ µ͛98}•Q X1 G+#;79_dpT_u ~Ie bq`41<O#a&I#;[r3.-\7X_Xmnc ecX(-DϺW8,d>GGD>2|8J:ϗ'fk=§=f{WH6|k s~O 8{PFqSx֗ ƛGOpiT44E&@l҂GWZ*ڟI _D]Ĵ->eō$2st„1fqoȤ"w5{W)&d5FG ` j0ԐOzp=iZ g紷[ ]Ri`v F 'U_v6̓jq塺]Qഌ^F4;Ȍv!8);F]Ө26M{WYilOxl57"S'ݺ4H5cj:Fi͍fA3EL4 A3fj2|]kF#F`v11)7wHgvx _$Y7GXJ( B,n80O0se`w?8}:a5vHR?'աXw G( g=ѼA2Ycv1Uh(L{ş4W2&>VHu"#R8 T,Ge 6`}>{Hw>x o/ i<j] ]STGc;r"PI(çxsJl)-3x~!^@E%9/p| CԹ(*3/ s,)$R %Pb6q0@yc9OhKw4Lh1 i2aX@.K[pTaVbC`#YfŐOڣPao(~`M+_M^%2E$^p_/vhtg,Cn! O^Bŕ)#zbU9y1z r3_O{÷Hʇw>ûwGm7)?K}#.ĄZ%3c`AzfzUȘgLyǰ؎q#18F8 ʠjT\`N\՚nk18ߚ--bA ?{Ggzlߖ]>~pCc327c^=ٸcvC\_8(47uA0\eR! HD 0%/qv_ h-.<6u]7~/1Wgi;K4=pjjjm}`O!clXj1܍ 1"pcp?Yǰ"kXc%Pp56|~X +:r1bcĀE %R8ǒj#+SQD*KAxz"ig0nFVFTCz=_ݾ149x{'j溩qm`g~񳺎W1bCYf,s fyǠaH387 X1&T3`T0uD.A-Yp&b4Dx,nN#A\@B#X=aç6:Tgpb߉.8F1kUkधj q;Wr cT*jCʐ:YQF3 zps :-(/[u>\9Fwn9愝iV-I %HI V]FPt>4 M*܅޿|ڱw?wc\%ldc5Ws5ח{_Vڲk?:a]R} Сc+cE1$ gP0(*Z1juqK1>cd `"q7Zcq;L vAbS@-R!JG( 5 ?Ó![;v6_ k>>0 N(/w֣xgߡ\'bej9kj/|bXr w-Xc~J ;?z;ƍXQ0;v͘iiZX_nAb\jRZfBz䑲b%9OXRY&0)(VJkGuϿ7܉aD5U0\%Y5c_]%Ar9|bרi1B0n F=Lj&D3$9F9qX Fケ*xw `=׵ЯqYk*{كO|ӏ>#=Gڶ7?cDyco \\_U #_<1aۿ??߿g뎟=ӝ<;cڹ]{i);kguR߀q# G#?o $4i Q~zߵw=Q1X5+_>+.j4|h4\.L600 oDǘx1n1KXUߗȗugGٷoocǎ+~ԓp D")8Y7EhF2S*?1R_1n FDY3-=OHq6qk;69W^Xzc4Ws5hU=l߽?YX0<%p7cj;F___Ѹ`܌AC;FH+JO|c-1;-Bq82s;T\o}U=s UX0 ,YpݤAfS͸qC8!Ms /n'큔+Ixf?ZqK1-1㑽MǸAM\*j89\)-޶ܼA8FWWWq1Zm} c 1I*7}:Fq1*5n%:q 3(%I1n'k-b5f.1qԩp'Ѹ`2-;XqTIatu bt6׿U]gϞ=s |''Nӟ?~_?rÇݻyf8!/\ոڕcA  ʴc^A3c 51c2W`/ ZH_Xj d W1,9J_{^PG窻 #ly !̾C C"Dƨ R 5ơéiO/?o{O? ӝhA"t E%thB(tB+sKk<3BÏxka`h0F'*c7F,XM,11"Hƨrd s%;wQY e:*&c@L1Ё"ښfB@Ε`#5P0ƚ'pkfƐ!dykZ/`Ĩ c,G  [WW߈{LJcZ1!@H0qE11*0>0mb f W:11Rs1^d5н#L:ۣScA\b O^/jNITi ` 7F4] 4F7ƚq01F+2F3]"5]9Olb`x =]a+ }#Ozd˶5υx=m+_Rj5P3赮]%ƘA듙+#(LpƨZĂ2_1ר/.7 d q?t_Dۮt7=u ߠ75uƀ4Kd 5$61\I9c͹ݮ9kC(Z`ءdc#j1I=ύZfVL=` mB0eݤf(1*fFc{e߻JJFq~M11wZ*0%9& ^x$~ZWd(=W0"H!rigX n"cp,\ k Ă7NX\5d_f1 %t~"ci Z&\)C0O-c1!5Ljs%ƨ&1F9cFScsc1K@$Rs H1dRf%dٙMƐB\DHXdsF8/#S԰bh3F(ƠJ``b6k=\ɲD,M LcxI6z/#g_{Wˮ7xC1o3e\uJ={jJ[E16Z mjHblc [#3Zb z3R^=?51ư^10ǀ6ƈe .I6F(pͭ2K2P04#N+#G1YY0}ƀM' |nqÌA"0*4ƀ.]a0P4Ftcln#9öc@L&c ckb`Tf |`TP1$͌I1ҮEτayؾJ [WWߨ!uu{Ǵ>bBoibC,3hcLcX 5`o_ZAlШˋmjV{?DY䶠wFwCY(fh|q0Ĕh0v(UpVA"04Fcp7' 6ƒojc&>0j]jcPC*7PƸ?=.B*{ q1bMۥfCSc*e @DjY `L"yƨ7th8b!I(m/f;A#ۥJo]qɫ/bBlndNov8Uhc>u4tQc-F>M 5c"o<_cH4r91<_]!UAgc[%"5/FS1O1 &h6 &FF#̳ցQ 0.X ņ݌}c1!ڌ)E1Ji Ы` 7o S78 z%FaJiͧhc.pa] J⺋s%r@"c%UQYa=Ć`X@v0*0]u?oH* c׍؋ 58?Ķd+KDc ;&1;k< 3_q/m D38,# z.1*4gƸ8cЕ!c<¯mI6_N5:c20T1(oE0uWgV5ÑM 9`# }i +8!v\4 Ƹ=肪e c@L16 S0H5Ƌ>F0 ##ZN,i3>0(5Yŷs^Y1w1X`l~_ A((Jd4Wc cا 04cyyY9|co]Jx(kg\Cj>[A?Rȟnݢرї|;wer[Cz'pH䌑nF,8蕓h ƘR6\I 61@2i2Rܹ%/QQz>>F m7 /#cܹ+ηͷζ|skrq=/ #*LyS^|ƠU1H&1^vC<0d#a&1sps|i5F\|٬e.vmsK`;3=ssra=c@ AJ&=yTeI6 i |`Z!g/u NvFC&oP(T+mY⩳q/fcaDb j?c'e+ [暺ݡ>^@ 1&cx6s5410}aCc8 %c䶼,Sh64toD/QvD3~"e>ckw2::|mp acy8{@j$A1*Sc3khF71atĆIkb0@ߐкpGJfq/}~rm]Y]^X@ ΈÍL2ib1nb #am%JCcxi|InMvLxփ'U5{@EcfL8h'xư0Lhb(}`oeïl htvj T= vp闎d/ "kdaܝpRc$f4lbiGt7žHff@ v11xfԔ1HAXo3n"ff |`p1v?X/DFl aX~i)1\cF2F5P2'pwojeXn #a\C16!ڌj)޿r6M\ b|*0 1cxzY_cc3z̘a 2FDdW3ˉ"U1~iHƀʌ*u`cLQ1M |`P4{z3c-4qM c`ݜ1>F #ưmccyxJgcاJ_iZcm}.5FX'c ˛iA޻Z4Fhc H10Ąh5Zf1EYc &71_Q4Fܾ0a #dNF=o1 &dUc1r0B1L16Wn !f03&BcWm 71T2 IZ!.\xe7{?DXk` a.SD1C31 &D1F9cm!FaLcwc1jetnBEc,y')c+3>0,obC1(fd6Fve/g/ 30S DzW|rSe6".]`i` j c3Ɛ1I4^P0[W;)fH^Ej #aNqE1>281~a׳C [s'Ql':(x$u<^mܳ7.yuaxc{y"/2U:(=/w\DT1 &c0 1D`Tg oޠ.ƨ&z 0Ƹ=B1C?=7 c0g{qDܟ߹e 874 6/7+ǒAƋ\ǖw}>{MNJP>P#` mg TMqi1aUČIYcRd j]͸cXN/'>Yc\>.륷poiKDj e_^^Ft ;\chc@L6cxfd5FcI/c8l> jƤc1ֵ`X( cl]z%qoTᘴu EK !\ ņ~ƈ$?4Ec(Ε} 1 &~#crƸq1M c,!cQ̠gLּ{`d #'8? R|2_J]y,Q4 Fҡy1o͐@"\ 1_eJ#ĕXXg4c)183ưXƠgL<Ơ޸J1Dbg!=DrW"X( ̻: ™07*T5F\Wy"5"i_~1 JX'<3$hnn4}a1iQ1ay~xcYcz~;{.5 ߚl^T0/@tMc@lv1f#q蕓h #a }9071$XZZbhI S ?P6hU-Zp1PUf JƸ˷2Vݕ hw[]k##+#U~mHƀ2v1aO61@G31б!4&s~{}ocfs7}{.,-zxUD0Ąh5 B6Fo071TA1o`$F\ݻ_+1{罱TܭƎنgooDu!K0Ąh2 m i &1hfob5qu7QwG/[]_>۵O~ɒL(1236ƀ#a0pLdq]b 1jA1gZhg>*Gk_19?}p0a1ayl ̉ϟ{31N]yuurc;яK}\bǗ/ǟd/ =`d df0l6j2Ɔ061PɤݍQбwWY4Ʃ;w==W򟾻3KS}]X=, b(cƠo Qq2cLP(ƛذ}%$I#E q>o[!c R?X>Et+ _s ˛%Q6FSdee.ư51R1|-6slvZq?D?12y䳖-#^Z yFǠ|c߹H2/ou}jv=3 b(c h ô&1 l 12=y>cw-\8EՂ;؁6 bKoe 5F2 ?Q0OkH c 41ԍAc#D1wxfi`i%<c!cp E ư0lbbFA041TPcqDvOո˿L?olQ7 bA1ccöM lc7Fpd#%1[<05Ɲޗڧ#7#Qz8OB D<3H62FK6ibC&Fu}݌a&1BEc$H4ƮS8[sT^^@$P5R~o t#M1f{G4#t*3jhvJc 7. 0nQ[w.qMs%cD!y IFb9\\MX!1aS1A\C3J1wÑM U`8E\c6jO:Y)@7 @H{u+^ҷp*(RcΪ<"x_d^c@lMD,fl>'N0F&1Znp̨pX7up1rxt z8VvJ*HBƀ5ohe  M`!c^061cG{K涯OFODZíP晃d/d9|B 16y 34 &FXP4AM |`l ={Qˈe<[z76 $` d[0F7cʍa0,ob#o K J*}A4&J"P1F3Œq?7_wB*o^^@$c@L&ct';Yfm 101Xfi4 A1$'T1;vx7ܱsw4{Ws_Ϣ]>vVD9` n-'#P2coeH6WB,AMd2b gϏM; ']-c\ =VD9eBI~䌱ߜK ҍ]1AtCtQ 1WًTo P7Z P[mlƛسȫOǛ1{Ḃ߿8pB_/KVa>9dctxc Ӛ*Ƹe#c2Fzcs޿4χ~W=uup䟾ww0g>NC'O`^@ F5AM |`Ta k071\pj1o {PtO"c9-1 DS/_;G=1  JƘHI7FȬcP6d :%Ơ/VYĢ){`dU#][>V/`c0s%"c1cv[/Oh^@ D\4ebF`XĐ1P>aYY׃}bA͕wƞw\kӧa=)F1̑m.`mUdN cTM |`h2ƪ=!fFT泮YQ2Wߧ|~ȇ?8QJ} b( fƘA1Ì5o1&`P6 ˍ! {WwIv}LkgOϬG^M!rX nLxfj ?c.38M |`Tk zJoh*еtkKg;='M! Ƹ>1efL60S:`XP6Ρ&1R$g\\p_,Ot&{@UcܘMl.-ƨ&Fƈ&3k a0,obƸUW+ty,xZ eo6 b#Doej ?LcpRCdaCޠ![`bع~tX1>k] ^@$P5R<cNE['#437ư1tM `h015v HHndlm&>Xe/ 45 G1QnƸ5<1|c kѩ`x  Mhmm匑"roΥڈnCM" bB4#cLc8a᫒d{xm1M civbBjԌk1N\Ō*QkM 0{1!1$7FN071ԍA2EXGƈP"c5Ы!1‚+` uoI]n֧c@LHoNctttXk ˛jA̘HA_tF&2040Nakq:,ñWdM6OCy/H1C1 &D1eQLUi ka\C#:Q[&2͛Bclll1I=g>uY~{r[1 _tLӣ]c"L3#:I ;w9耏i |`X1A5Fm61TCSoq Zh bJ>+nhny}#Er[3k5J^37pŚ:c@L1~c5AU+c8b zfHe} |`X&caZ u e0xiG/p#>jPAnqʾx064GWB٫a ionb(kcz a0,lb0ƈD"@c3Z̕[NQǎ%`?(dc{K./>^'ki}3W\!Čmdga kQYjH"],1 u+B2| }XhkJƐ'A1/>bB0̡ˁLX2}#Tl #ayO%cts.c RaD}7\1{KH$T|n]K)0]+]Y\ALc@H 1~b 4l /fO?Zcت!o1ZFPi5 c˨hf1td.|`m_c&~t&ytyQ:"jJQ+U0 őbFhy4uogW~}?o8q>ԙ|/Ξ{ㅳ.5^l:wYtrk[_ 6cX sƸ=c H$` 8FcΏm0ב1\ |1u'x׏;2NBGf4F:(B!t[[[%L|G1yLc&>0*0ud ×2CC58'4331ȑ#?.\hDFpD :j[R9B!LrcP1F(͌RcFCkt71:` j)fطo_e?s [ZZБ }Z}Rs鯏0lb(c1Fg pd#%.gtg<bhsC T+i*c>}t/=>|2:iun #Q}C1!6Fx~#jOc ľgM0̀1 &D1?cK.HhGc01Đ1hflBZ`h2FP4F~ɟ@Kc@:CAP;uԕ+WM2ƐưmC<3JX1ayH)0qjԌH2c\~q\Μ9si311M c(g wt_661eƀ@ Ό1B_QUf uI43@`矣?߸q `حb O| } =<~m }G'|W.!f1$xL/c8n c2ƐV`TP2F*@#δ2b` Ĕ=6Fmd&cSxc9y$ 4}%Za0P6F[c^pd ƈQƈ-rc@ G1^::K#(0Fh~J>E~xftbBƘ#`01[c&1A-c3ę){9mJ'O;Ht sΡa: i@p^sM5d*l !O c@ "k _`<C1~mtBx?C>@{xMt4KR1Y`t My䍁c#ADC}.mz&>0*6<2 )8/ett1S1-8"Q iG}p  4j%1M 9c짍юg1(55aM63Q0qb䍑A_D1\.ĩSб>Vt;:X a1zzz50.1`į;x[jvumՊ^(*jQOTKEo ;n|' !/$B wrC1?Zh7 1-LxNLMMyvO>hiiQIaC/^6$e% 47c S 1Ԍ;kUcԵ!ɌANc;a9q3ZWu33F<ԺͧX1:05g.1Hf9 CƐșmcdccp$̾&6=sb>Jc wuuv&11et!L񲡚@% 1Tڪ3Cl ZJtAcI/g+a1XS\%PbL:Ay6=,_8uc걘~>B86yG `dzY2Z՟Vbc:(ʄTd :0d>mp1r fX14n.Zh1TOQ7ʗJPz]S84`c{=cHwrz&7F1Vstc(+1FQFQc2`rcȈ;W.PIchF`clQjt!V`k b OP0byOp-J!W47ȐGOHNFa#}Õ2Fd4+GI6Fڱ\bȬy c̰c;zO,qt5ǐ}>C]:ZDq%8f=Hjmư!'A0bȌ00wA1Ò@<ͅcuA=a%$I.Sc1Ё1cd-2184@1(`p}A1]aD4I?'DcWwnN(*y3k6F!-Ơ1P18:Đ1nUc0`c+]J:rF QMT3`}iM7F>C l s6+<;c1>Ȣ30l #0F9`j&cl 36+a6ґ`_w}lٲ+Vlذa˖-;wtuuݻw8 q7]9r5bƠ1 &cXCf\7 l s.1YD1 ۢ)c 18::.xy!~ cl :1 `} +7 l 6@tA 1c%N|;w"##aفv"RXQAbŞK2jƀU:fk :C+b ןGO[\܅/[QD[9ƀLLL ~1Pc:.0Lnê2$cPш`vix^Cx^cx~cD~s_O>eϧP(lii}}}Pخj &1`waư!L%%%ڌ!h]68m{Q}) x_X\L!ct!Xl l k`6&IJ*zF?=`K.ݺu+ p?LkjjjooJ" fh1MCϟst&cl `ra筈7#^zvdX:'nٲe'Ox͛7333aV^^^[[igggOO ͛72Fcdee!1Ё1p!h]Vnt.m0;8ìˏx_?Q:̅Mʏ s[#>;ԭOg/>{^q}/8MⳅL P< և0---888+ $KSzh'n޷o߉}ɵqɓx+/1'TlK-D\pݿ'XPlyyuuuMQ0cO i'߯%+13F挍A0Xb55G.<\[[WWGTsVyAL1=` 1,!L6` 931p6A4ƪMKڮ<κ(+!=Ǖ]v}4!!!===''t_.+#F|>Ƥ11 և`V>Đac`cM1p1lvzfsx{K1֬Y {gϞr劏OPPPxxx\\8Pa>Ҋ XMؿ1;1J"98 kjWr/B%gͳqrrrss̙3+LNNˣFJ$Ƹv11X7`}A>3-66HK/YrD*r"q*~G8ׂ@ޕ$O.O*O%ptt۶mS{b-`˃œD6v7j?W^Ҽ2F<,1Zϭ S퐾Ɛ)(@8F(&$ TМcPj ɊB`c0Dclr_$jϟ_~}ݲeVXaccaÆ-[8888;;ܹu޽?py97cTe vƠt1 2Y2ha꠆)mƘJC%e8fDclV! o ܿlݺ/ HNNɁ%"X`Q)X{5.F2:0Xb A0jf 1]+Ss.9Ɣ)Ĕw4bNl h-.΁ȗ-Tï?tǍQercXÒA0=0l c"~j{+l Ơ1s `c0Dc<()lycm5h :aC VaC FYL P%j.1s8tA4];F̚96C t`pa10!}>|93k:նWf]0:X q LzSWUǕ`cUmƞ.5F%1,raFc̍.0bX1f[886U+7fƠ#$#~ ??(c$uQcs1Ёè_BA%!4{eڍJBBB=zw޼yʕ+^^^ۑ#GvekkAk|p1hN,Jo]j͛]]],>_7>>>( ,SX10j~1:/01C cˤ1>@2FNcJ}v|||ll ca21ku2V{a ƀIc"8888cw1c0b*(t!1ȗc"[H34իW0wYc ٴA5!X1Rch5t!&0X710Yl +C9hn :A1 h4:087 !ERc},c+Qi1ga1C l X1J3Ѝ և01T1O1̐Ô36,cH&Ơ 15z1Z}NiC׀~cpqd 931ppp'e\ư!k%rcL"A0j؋cPc10[Fjł^A{C?4,A0dӽ'1Z888K2F2,`>io`vVb{=n hp888F2Ú1#ةƮfq]o`u! և3qp1bc0 <_c/\/\mvڑ#GܹZf~t8hlAcXXcH]w A058g~M7o1_^vv?ߟ ៣2m 1Ё1clo QɌ. a wa=C coal ͩؖwѷAyzz7oo៣bD#Ơ,15y0Fa]4}0!UC8L1טouep Z}bb>frf01:tv!70oVX 4!!c(A>'W6!1s-[kcqom`,el]`10]$U|r(lWE4FeC8L21 _Mk` HK/YrD*E66ch t`>@ذ^:4&hSxÏ]!1mrfK_cc0ؿMk@lR2_x)_,'o~: È[Mm<Կfѹ%K_X1X3yyyFclCJ9Ёc˚0FECD`,1'PRg~@&oх2EwxKO#~5͛>] %? u|&酯l1_ Hss DcXXc.5,s 2FW\1r`2'0X,~#oSJ ]oK `~pы@DBdϒ:k8>T"le&/ll &c=HJJ!410k]!VcŢ!ʡcc0ؿ& {T) <{Ep҅JQZG Cq<'b3<'>OWq3/{^TMq>k^o te`c038l +A7`}y=H0A]`46ECc9zPn6cη,//uLLr!{oS.E,\c6 D~bѢ"ө{h,:~:ySOd3B,M#V70:K 7Q2\ff 3bLMCTeï`pbi LC$3iGV4*l?{w5o|ŗۀSKyv(_Jp!DH}FޢiSNL;Hy"㩩'h?:P)dx1RzÒb`t1h bac;7Q#ͨm{倍H`]J8J7~rkO<ާ&x*?1v)_l!cԣm/߰cS.:r@~Jy)Rz`c0{W&HR*ǍAv1BBB և` _۝0/1 1tìDx쪚1Z8i X#ob;JK ,loUQتD1fl ƲŽc y3teʕ+`da@U 1Ic(" tudA{#C=+q`.}!cpQɵ`c0ڤET^}]{pkÎ[vldyM?l/ ^巄?ohvnn/gmp5ܨ+fl b봟^Gwp9͚= XK߾/?Yv7mhgeN.<,PS}ݥV{ݽ[ԡik׮!>ϧ 15:087ilԵ:cc0-vϭ`pp ZիcLsl-l3l9?G͚m{*%> UTŲf>19{•[y8aDBX\zdRvlz~BfArNqj^iZ~dZj-ljsFvaUtlš5knܸJ1Ё&1O&50!F `.+I(VVVh%IX Ca %0C) -PV rc׶TO1FTJv #0 3AY"FmtSD8b7bk k׳mΝtN`kaZ.SNU,'Sa14l -P7`(Q -mXkѣo cdeewư!1*9a sj> Mvis ū7! ]P,tJ9ޮ83_Z탴:t`ڿq)W"Kv˄DYGG:OcDaR04b QR-O\a޽{qdddbbbzzzvv6a姌A0yfJkL/)!!ʕ++~^ h 6(0$|'O&4He c4>P#)Ka ':Y%IUP_jMusZ\ppp,1+7,t^{q9%c%1ΫD0FTAc0Qt`UU60ǏJTI11e X"G)9Yz^˨vg#jno(yQX8TqO0X6r;N\ٝ Mbm\ppp,1+6(k8㼋!DxM[\;zg/~ ~C#cR3r(*-W DͰ45uvuIvVLFįݴf=Ν;#!!!---++3e b12(clc ƠFF@P]] ?8@F;Ǎvݠ-kolm7ohv~^krW,q?߿~ү>[OKoF݊ߎ)hYmd ΅53z7s?Ϛ3w_> %_~+~^槟׮XfɻB vѣGݻG# <<bPJ 1QiZcC *ʐhmmmhh)--:&%%EGGGDD=y$D3#t~aժUvvvήnnnǏٳ.\x˗^ Kr":7n߾}},`Üa>C t`hCuA>&yQ^^^XX?LLMM&ɓ85 $^#qqqpx@ 7soݺVTB6888SQMW31曟~ m۶;vݻàӧO-a~Mء=02~VȠ  +6yDFM3rddTiA0yf a&3jkk@B|'d#'K[@;Ϟ=8؀܂|}}uȑ۷0 1St7Z|/ߚ.jgTw2gvM&itQh:+Ta=}; }<￷`۷qĉ3g_7۷o߻wܡ?z($$$Ԙ<'a 'u߉|V2 1 㥹|  A|>QVVVZZZ25)2&^h~؀ p>} 7jO:_|8k~o|_BAbyRxD߬2^ojZU7E VIjS?藒yUM=D{*+AV*Zhvk}GUfZeRuUķ@<$xT5@*Ubq[gBߐϔmn4:Kʹ?kOU4?M._iϞ=:~8ҥKL JUM>yQY%x ́ à‰ s SizE1Ya W~P$ض,AH4!ڇju5]Wkikj4A|EMVT$W'W'U~ 2߄RKދko|-nd}Nގzh$[o=%3N w ?H(O, H*LJ N NzV(!zӠUZ*=$]@s }b nG7Lxa\Ts 檕8s84O0/EzCydu-zD 8]ٳgZnΝG=}ŋwޥESRRRђdC^.`̈́*)`>@C $c41Ё!`heFwwwgg'HԨ䈐#pN]]9WiR̈ ?N<{u'sseg9x9:," /*8lQ= HXtB{B,ַS[~ WihU@ N4rxpf[J~h|RΐU2 l>)镙0R"F>! < r(;@3"5reV(Ɩ^*! ှƯZ|"C <,@bF%d֞Qsῧ,l(<0rO*S7u{80P:lCK`n/s{ =Ϫ>FOXZ6W.\jժ 6Af۶m9ǟT8 h'tǃ‘NV 3_<88.1a*`Nc 70~ĄcƠ^%=NӍNWpH0^޹~zZZکSqY@|M}gr-bn).TY/JOEmNSX5i<`$l +҃\ vo DX)@*-#R7̏gI)Uu?|O<ܹs-[vZ~'N\x1##g:YMr+`īĀM4 ACuR2ˀ.G2r:;;75\>?رc_~Mϟ>x֝,_JAA+8{/zZq+eʐfh0 gTzYi:RY\,aM-I-f(JAR]m@E զ ~@aZNiԡGW@r;lc9q+Z*=bJN/G3*aJeXDup"3i_pE֔ k?빨͇EmJlI=3Z4)Cu̢d1+\RREBJ26!= * ST﵌QZ΄Ρ{1EYwټy3\|pEt .k`nuĭF٥UO[!Ƣ0F2{$02fXdA; /eeeqFzzS> ނ ~gL86_; ߔ.r2L _T[oYue*2?kYW{'ø٬؂3_1ob{H_TY܀(/'vKCG~ӟݏ3gŋQ[ڵk޽G9y$w+ Nߥ1 H7GU0Fa C`xWbBD 溺:5+8qāvϟ?ԩ@1?@\l'8G?m}ᇧL2o޼%K$[lz:t())I+W5~BӠ0-#yx! 'y1C` bP悗Jff&+#11۷ox7.]p¹sΞ={̙3f̘KJ?K4ٙ*8/ <'&31 \XHVX[omܸ?ܶmAb/I$p6Ú1!Qw /J ьAC(`|H31]999\e>|x;wܼy3֭[f͚+WoUb%;"1yMj 1/; <1+;s䕘YxK.[lk׮cȦMn駟СCǎ;}tjj* ]2F\J <`Bx.10aKwwwGGGKKK}}T\V={~g۷o߲e|;6lX~=PZGyKL7dURLVr1Y& Kd "0,x)_Gĸzu$\p!c W1'$Sammm\e)we\v--- 0#)))!!a߾}_|Ǝ;(o޼|D?b򞘼+8t ^L։3#-Gm۶O?# 'NK w?!1Hb8 3?x?`IxÕ`ƙ3gPݻ.@vO>xcm"U@(&Ep>|( Ƃ:.&ŀM;^۹s':v\b JDt #3{$0K <`(C2{M)))IIIpd8t"={|)Unvg:Ntvv VQ.6vxѣGᲅ~D/10F\J <`x1AC/9hmmmjjcƵk._ q)88;v  >䠀N Wv|]9]`,rabX XfG%"11C$7K kƐ $1CEcg?5̀ `p|ol:Ic|Q9b'a;9$ pWKg]Nx.1!]bÅA`*C i~ޤW FvvᰐѾOEɐt΢sNN )t9)&rVrQ mv7 >>,p٢F~φs L"`Hx00fh&Օn a#++ @ڷ*˗}rdetѹ$8i\Tt)Kmڴ\'Lѐv <ǿp H C`1<*1 _Ǧ1Co34op/`$kOK.:osti'щ P"CXh 1\xc``}a3 )<&}o'qMbcx0\(1,0M#ښ ~ޞ=÷|SOي\س{rVD0 g8px:|t|O:oC.1%#1#1!]bc#fpIF}}}@_% T؉Q˅Jip+G &i4|&"ְtQ|8pm01=t#-6 ?JbJ4NߤiVȑ#ZtjЩ?:-%n X\"V8krw6.<^ ƈ ͌Ea~%|Є68opтK3:M4`'"pBEr OM NOU-NudG7:VT/!Ë!]b$I AC$13J"]b#.c< ʪmӺ\')ab !]b$h $1<$1$1<$1a1WmջW};r~'c "CI Hx Qq)12Odp(+GDe %0HbC $1Dt %.1!]b|>{/yK~t[ȣOĐ1#1!]b$I AC$1<$1!1%mZ~ӊܰ9;?1{$.1Q %0Hbx.1Açc_~WXּe-ol8'7W$WFIK <`1RbCI Hxİۯ +aۺ?l_v>SE.1A$ ! $1Pa1ʪ6~-=l$C`Hx.1Q %0Hb0HbxHb1cW.`v|i]XV9& "CI Hx Qq/12}?˪j?lǻkqESM5e %0HbxHb0HbxHb${FIK <`Hbc5;vޱ;a'k" 3/L cGbCI $$010HbxHbcG6wlcOVT7<7mf8c0Hb $13J"]b$h $1|a픚= jj^>͌!0HbC#.%0K <`HCt #U>d]SI) -f|CI $$0\$12J2i.cv -5͘=/#.%0K <`xTbCt  $1&(12O>֕c֜=AC`Hx Q$13J"]b%1Pd)O?ѓ|139Umc[yMcCI I I I <` 0KHe|1|Ŷ _圳J;z_1#1!]bCI Hx  g xЎ[S_`e рAC`Hx Q$1DK <`Hx avwgC/eeuhC.`3I I <`HCt e[vEig`m1{CI $$0\$12J"Ebë́oW^˯\dG#.%0K <`p(t  $1b(12 /;0UTQT zmJ:R?bs3#d魇9~Zm# !e0H'3k#Qva_X~ߘ]A BPd 3Ҝ1  8U~Pu7ks~סY0O?y93zdQa2a2fDRlPz1e6c0\w7[eov OjyKe1c  0ÌBSƀ akHxrY8ib_}8?݆tB4OCOv ;JY'0Y*7e[;s~LU@/-m11l>ڂk7cP(#Mc1"2v(B9&hgFa4dxjsưs0 wAV*ʬɂ] 6J12}#~0=>P(uq#1CwcpC~A 6XIX}z%9+Q JB@$|7dΡj.ψN_ac6~|^UbVc%;fM_<|b) b1Qh1Eln~ύ_xvc9N!c:nM|Mz>| Duן YU/?v'L\Bf[/K2dV/>G ?MP(y 1EGԓ|P(ģcBas2If e`$v~) 2C00cP( Ba3FZƨbb(1BP(lTȊͽU BPBP(J3o⨌GLo'|}0CX\*+#%rBPb˥w2]l+4].qCW@ƶ'}_wCwEWc&%bۅ./llI*R1P 318zuD;Zg[&3_/ٔll̕%b74vﶣY걣jbֻ;/lȵ|}tktGk:o1H߀y{<Ɨ^a6+b3Zt9mnV{ z~CXBeANZahc* V̆A2* xBqPe{$;o;۲at g{ K\ 9Y:{TĠ]mzƘ;wnk*f7?ͪ}]ZycWyCWyeeu&`^Fm1k[mEִkL;IaaB6T[}խmfmT(V_>6kUclS CB^ 끽x~w}bUy[ U\P7+V< m+ca6CṪ[bWkvݺMS\-,F{[մ[ ղ%wJ6Y *]Ci7G-k-AKr5YZj oh-뛩Jm>ouޛnVͫWn`i-fzM 3'QP ]TS\ +W^iy2s<#[fhnKYaksvA՛WmuWr9$=8=Ve3gOQ2oZo">0~72/d^6fUCE) tUS/ =w~gHd` 'c(g403p1$ fo)`FlPQÜ4Zx'h0F8Ur 3(3g [Te E#+x Y x c1CaV媾b'}GacHCC fČ1IU>bC ! =c qC c fD (b)cfd2bª =cFC̈6#OGN#F̀QmaXwdډ2ݚ4t/1Cf J4PR4fY%ccF0&:cdqnjږgmذ3f˸71r~fq᧛Phb3lf4vU4u3ѬS1pcD 0Fct`\jP*czZ1mnwÊ10$1*=]_fv00j|o3LoQc4E1 1a `Ca8c({D%%ưFP023،E0S0sxL2*fJk-1И1oI3~j  j32F! 13!8L2KcFIc/?}|;w>싀# ͟3\wk3Ô1݈ ?0;0Ì004cPbX2Ff9+CFL*uFL:t_`Zjfa=VҤ( (e 4ZemUVöʈ0P)8 Gta&ڈIW 3TExƨb ܈IPbD9#&mF^6Q1C.Q0I')ʈ3BFL.GŒ,]3sp|5iĂ1b5JRPCYU-7nꫯ 3f̞7{WG}N-VUEvdS{ju 끎ignmQڹkT ~Fwcc:ٳhw{L֪{F>Qn&J>Cbohe,q4`iW k_v=sZ?ґ> Rvno`v]6.^5x3pZWW3hljLS.M>`ٳ~0#%%e_ֹK;K94ǝ8T3&ٱꋼ'ؗ%CgIZM33bg' > R 'iSfݰaþ}8`$$$[ endstream endobj 88 0 obj <> stream xZmo8 IEIZlDI 4ruoo˛EY86 3gd.6v.c}>ݬ~va,u3D\0mt^qreW^M}z9=b<,69=9fr?=V0<yBw=|==)؃(w'n~<=B7bJ xY:E,@űP\WcZ*UU"O,ufULGsf"p`o/B'DYFНf(UnF 3ƌ#tR{L$_L%&]ͮR}!޼->)1}˿RcƞXe1y~Jͷ7mY&:E: \XKc@d#{*/AwFV<2J#вlv<)2UńTyAJF!9(B1pQP0SXZ.'Q$Z@[?o.d_i}՛pKQDh:In^ec<|’%V(IyqAf:v09Wo ))\)D%ԫr rYJ(`/ný2h(m3<$w <"%t֯TτEPc--j_0o91\J*DwӀvQq.Yޮqc0(C+xlDbxKY,]8c,vAN- \U[Z>s\G)#xɊK&{7O}S0Z8BK"QU( 1Qi||P]2M3YFR;9>JRf N+̲ip"3%7po(nEb߸6]Ź4{ïXqU^}=3dFLf臸{9>6qoEaf7CІ$h{F)бǝ֭H0`aJ EQlKKȿ7aY]vUSuWIF.) *Qn#yeːn& 1U%'DqV;YIo|.UV+hN~L2U=a6=|zѳaktibɈ<ՕөQ]qT.Бw!җ?tҷ#ڰ^ҭO>e]T)!49PR %b+-}95|Tp pJ0-?UAv}(:v:nfQdy~EajJvR»<&KK;լf/]<0vX=d.8`aqR(f&KA.NC?<<+qaG߉<̔I"!3Fd"zE6ZT=*FT&AЁAȭU16Who>2 f[|c/ݺٽȵ۱E$ u Y ВEiWWTw}ۍg|,k; lX~M UcZA;5N Lx(UBa+¶)]NԨJH t8|QS{`4鵅O\w=`7ٰ#w)jo_;ȣJuBq8fjjWkT있i`{8<:FDXamIkPߣe?cn=ê&ȹ`y\s(e.֞q ǵ}.`\.o_ eʵrtG 4Ln Z|(Bbj ~@ZO8z86e#}ZL8ר8]?LQ9ڝ0Uʉ> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?,"uKca8nP?.vI *i:Y%v??&ӇSWyA֤H䐁8<淔4qrLtm)i:wҮiZ"=2g%N3Y#NY<~nȬ9h"Tfޢ>ƕMD4M4+N8TN]VsH wec998 njqaC7w#NDV5;?w\]$qٶtCHҏ4DO4=[ʌiP]<_l7ț;UqGͨA嶏52'Nz:+rG?LPޗI 7iúW4xjPy2E?JTvm<4m ϹxKA:wջMH?{Gӿ?&Z&Nc= V%I_' ԯͧ_v *cc>hrIظ'{wE)ӿ?M#.HVEa4Q1A*,qGkwwZ}ỷn㶎DyB,/sY~\ɿwE)ú/+"?OiWB++!i aA!T.7A!"IEvFeci9M)`wiM;q0;# i4i Vm Q!vCHyi˱\ȸܲ8uON[[- Iy9E!Td ko0$K#OH³ wַ5KCmUay@W5U,-ⴼo#YaHhenUppîA&Iu'o#OX wFZM,$_Ggr]mo]Sʸ*r!Xʠ#9K[MFxb[x];$0I\8?.9t;=GF?4*3ĶƧ=ܑvQV:+I!9FruBoi62k(G!IH*ssGF?*wxw w yw"\U(>ŷzƟw xV{H2) ŰT-[[΃ QNH´0#? F>:7*(a]:7(ѿ,ZQ`NXwE :7(ѿ,ZQ`NH-wGi(\4-wӿ?h4_ QNX´s;E>/+F,34_ QNX´hs4/)NX¯rR\@m;S({D6E;GOi G#'O(\{D6=NT ѢGOi G#'O(\{D6/+Na>,Ht wE0,3#OXšt-E4,3?i Ra?")D,S&>X+``@m;S(D6^Fȧ`3O_ SNNX´!`t wAѿ,ZdSs; GFW4J6-PpdP{zVZ) T!63R-*K0Z`s$Sⲅ򎚯?X??hӿ?eG3j|Ks<7fy.gCHɱ _.:۟?Fi& _ Eww[[**ehK-$][u(>8[kfRY3ݱf04S[H/1&-2,|{TQ@6qCm"!kzl>cHfDhxB*s7M@m;S*뭿3? *a/ SŠR䕶+gy #CV8뫇QXjp󛄶*htW?wkNJ9t (^L2$ВH8<5swTyR -~-ŸhÄ` <HhqKbʳEhd'˅P4x fO /Jefyg1A 3wVKG^YOFk__ 44γMOi_ZJD(C=I?_c*A>y ŧ#2v@Uŷ;Z4*׿b8?y.=ȣQtlA1HJ 0= *o#P=ohuVvyTmqK9sX ż7"ʠ"*ǦNy=1--^OC4 dEsDrC)\+O}[O+Q=oig{o ڗTxMʥ P #iRGLK:#I0єᙰpu_Vv}[=5->5߅-nS \vȢ6 ;FW;{<ֽ=ͬGu58Y}"Zg}[i-Nt =tM.-=/n6nD" c'޲AտV-Tu=C_Pb8|q.y2LDRJI $;Nt-H="=oje˂{/=bKH!ّmʨiglsW%o>k`[h6OnV+H% 'ux?/? }jnͻr-帹h P*H`F *@NNV Zuw\'d#0* =t>{@k;A?㴕jUӴ%oţY-Sq'6@3kVկxXQ;b>t" _pCuz }}i:Nt侽ȊnX!ad.qcF? nino.Zhe7&܉E]zd<֛M| }}ie?%d&vHTgnֶR:ك.Tp <$ ī`lK 텪nb-$cN1pSWCv.@{;OOwctl.nRYdDR}EN08P~ۏxvUƓg aZG*.vZm?/@{;EjfU_JYMA˾B^6,X;iڟյRѺ%'%"mVckCο=ο=]aVyfE 3: `)5WͿ=Ϳ5t+2W;=Ϳ5,tUA-?/}@k;NVe*}@k;G}@k;EYu?u?AfZu?u?AfY5[;5o}}h 24k?ο=5te*o }}hMo?C/QTΡ@[;R 5VeNJno?*^_p.f_v]te*. }heo?,˔U?]˿p9Y(l-s .QTw@[;G. }hAf["EUeo?vde)Ussy@k;Hn/? }}hAfLE4y@k;He=)Qy㴞e?,Hث r+4Iz?}}jE_p9Y T]?k5,$SHj577`v'5 hؐ9{*3=?'y@{;EYzVͿͼ=ͼ=t;2dmӒ i][qGo@?P=5,|vw@[;Gn }h 1^ h[pGoB?Ow@[;Gn }h 2MmͷQvtd];tywmn-㴮̚wYJ$nѵvdNʾ*k^Kz%Meqm#F'c!n^?g%ހ[?'k[AIr6^w",O[2ͫmY\ L%lȒq)˸6s۶1뫨Et"= VR0}#޳ceG5ҼNb8f'VYcjM/ly(Q]A֯%Š A >W<M)C@ݻ8:P-ywdfc`A ˞W] ^EMmP= 0`6UEjI*8DxvGҟor#01<}|;o[ZDI=-l.%WȔIʮ+_hOٝ#?zHˌ}T,=ld 69Hr}%i0 !8+svCT>PH/3ˇ֒C)|2҇hXՇM{y%4T8`Mf vλR;Kf:Wm-ɷFr,$u=*ijK3+;>MFH3'ӧ"Q$*-2@/0M*U7B` w%+{ ݗtmwCor4,?ukmC]k`Oڃ*?>ᑓӌaj٬2z c&}7s5m/jf1x<·h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂ;_8_%: gzM2UhbEsgk!@8FUx9S~y.|=a4ZGY8*}Jvij?ݛe⪥moerNX _CQ\\>-P]XF<{S5?&FԼd_j*89'9'yx47hgg,k$fVF .eRѮ廊yd{I|6 Z9ƙ^ѼEo^) }IʹEb9 WJ5R{3Ь^#q'i96v\R(CLxg mf(#H|H,#'QY7 i:q{QMl'O=2/6ǜoDk3m,2yn|xMpzΩysj..0lg.*Qs7ȭ_;-.aY`剹WFCSͅfI72WH.o^O@aYXc? N%}28cb*>?XNw_穥99FVebnILe#ݛe⫉:Mmueן8>WKNRI~Vp1Y\иmu%[9?ib'y2I?d_h?)k;\եٵ2KT1#1E[FP<.e϶/\cak4>bs&9)hE2(oNei'=6=+yiqu\H%pOs126VcJ4<%?_L}}s7Wq~i8E33om'm5B\ 3jlvܨ?X,VTxdo+B>qW}?f9Օzf"]^Ӯcݿ&cY@"< ٩,f7LF 8aBJĹ݂Px7~.fY7pG9{u iR2zSe"ԧ䖹hUoj׾O=΂GX$VECⲄ=(N3i4B}K B!D3X{4W,nVOhXK^{j"Em4Bl˗U]P8>j#JIj:b!JO^jw/70n]9|OdHndg:}7ToCcI^=XX8V:_5.e:AѵXn&V'+J`#?]gVM!v @'YJӉ-“|vw_3a#ĤsQ,׬OX`M`rB?QֹtT.q4K:_k'WLUݾgڌyc Q<}-R)fBM̼Ս7VZ+EݜsjֻV(@zʨzӊ#i(cv#ʱ-E2I:) ~bqԁשh >Ԍ6?_*mam)dV*&'y';y^ޏ4E;k)$3 ?)9cE*MkO :ݳ%V9's)> Rd;qc8,@=EO{rwmqx.dU?A\:w5heB+ ȼ1ʔZ]Σ>o b2"ӛ:? GұifcҿG=esA^?'.%?ɩ#C1en%}Ajuu I!YK޲8@T3z#AY:J9,x`7q N#=@>aߢyΫ>OU}f?7U+A[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp38E Cb ?l?5(SVO@pwh -ROo{%\Awd$hd$j )%wȥe7Zbp4j*ϓ'K'G'K'@E!B\@6BJdbɓ~ɓ~ =7"wkI(+UTa@d$hd$h׳FqFI8N{.H ǭt~L/ML/MJj1\ዙ #A'5y2Կ4y2Կ4Yb fX8tz_69*&OO&&OO&)IhR^,oe$T!<,s#GG-sfs!7ƇOS8ʌdD6:||bY|3=zp*wvM<+\`y+Di6A EVt]3#Lyg.@y2Կ4y2Կ4F:Z8Q(km֣b,2O \p<km\As"h!GzWc?RI?RIөN5#%SHa,RhGH(irOZS7q靎FG<}Xd$hd$jثYXм'cx]C?RI?RI3?UUQRt>޳4Wg\`ܝۈɓ~ɓ~Whe)R1jt4 kɽzF2(d$hd$kdwGoevdg[>Z4KNfx^.#my2Կ4y2Կ5uTT * _{49 a#')k^KZؗ']}? Z l5y^RӟC:]K?h\m2c\9QV~,5;Ho#Y!t3PjZzL}Z%wp40Ϙxq O^%w}NxtG575w->}6;Ȥ&i\BY|  ojZ}W".G91X?~c?y-"{k-YĢE.F`=| ~ ֮\<WP*H$ pa0A)/:Eť^Z=UG W$;j泫hZTN»A Hߐs;+z K;}6->K;fB"S~b.pWk^7VSLțaP3TKsG[a'FxԨڮIb3נ='rKoFgF N>0fzō1α.,Dn[G 9hk)b!6;'_GAK/OZ=jK4qw:4!p>i\ 'n:a֍t< Z?kcΓߥS5můu &YUal '\ n-}?քZS]kᦊ4/E|9vV Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥt(ţGC|G'Jt1hmţ#x[,䕊.{~;=&XfPY BlYc$ JCbGۣG?mi_X`tRtm##2?eƧM..@!;)b8OL GC|> Z?i$J.6$q+d$!X*[@n-}?֋jH46oURY:6 Z?j֏1ÚY݅QZj+}g ݴHn7)gf?b[t*k\jfd$?Ssڕ_GC|> Z?jd.$liz.zqǮ=:֗'Jb1 Z?ht1hmId'b@i$LJN{A8iXj2Yp\[3d47Ѓ A  bGۣG?m]ՅՕJbl)~t(ţGC|G'Jt1hmţ Z?kcΓߥt(ţڈW&ܳ~TI0g qzv:O~xY Ё t2$5f%޽2omCֿ-{\ ']cG" ӼIעKi,𿻹ϡ.ރmX/$ܰêI+['Uw>:KȎcUYP0 3x:V{6YؓKQn-Y`bNUIH>5z rǛS-:\׾'4uPIuOگm=G^AcjsןzGƝjlG&XN=AC}+UCNQz;ub0g&+js~ʛL_\2;->]Gw3Ήң~LQsӊއ[IiًKT'Sg4d? ?=.wx_VI/ˮnUnQX_e5*k@Vٵ CC6ATgM]vj:o$-+{T㷖5Fr$uR9AQ =%$L~?' CC [kGw9; \6$[EI BHo1aJէet];[yJAA Bcic\??1bU;<zi.K,fŚ4G8d' dnU$,~0h| 6R@m3|3!1RUR[h6nnm;W#E G v$&'?5mc~ZG xU!!\0+ιAx Tg]??wp2,<=sm.Їb}]&itF0" kg:1QstuQ\wݮ^UtW1]??7@=o/*?/*:+5 Cc?-*:A#V"'u%  g~l2׭ y?7KF[o4#5y/Kb^S@oދE.?]934RVfIKI@%)(4Q@h@ E (E% JSI@% %Pi(IEJ(4QAJ(4RPHii(4RPh(4Q@h@ E PhE%)(4RRJ)(IE(4QHhJ(4RPIKI@%)(4Q@j~?U/?I?@oܜxn?8k>)Cz[׵ yגoT%uƧq83HDVo_.} u:EJ(4QE%)(4RRJ)(IE(4QHhJ(4RPHii(I@!PIAIEJ(4QAJ(4RPHii(4RPh(4Q@h %P(QE!E%)(4RPh(4Q@h@ E (E% yO!f;!4׿0׵ y?cץo^5?a5яT%uȌ"Fkw5??Eo?Ejt2i(4VFIEJ(4QAC@J(4RPIJi(4RQE( Ph(CEJ(4QE%)(4RRJ)(4Pi(IE(4QI@J) -% CKI@%)EQ@J(QE%)(4RRJ)(4PIEJ(4QA( T'3Vi?40[׵ ym?7L?8k&k^kRؗO[#5軚)??Et#5軚 : RZJ))M%( %P(QE!E%)(4RRJ))M% J(QE! %R( RZJ))M%(4Q@h@ E (QE)(I@!PIA J(QE%Ph( RZJ))M%(4UKjѪ_?@om^5b5޽2F+o3#yKb^M?@3[ ՓFkw4b):IE5(4QI@J) -% J RQE( Ph(EJ(4PhQʽ?OIP}}hJ_Z>Ҿ=%A+@J+GWր&4Ti_Z Ti_ZOOEAJ+I *'Wր'M}}hzJܯ'Wր'M}}hzJ+I %C=e=@٥4QHhJ(4RPHii(4RPhQE %Ph( (QE%R?U.Inc[?2Zךo^q#zpיQCz/s"d]gğ@!@'Eh#4% %Pi(QE)(I@!PIA J(EQ@\yjMZk60<@׾+/~MsrF M+jqUοYlEox+O¶( =)wRHԟ:WI> ͯXz¬7cAMT"OZ +@jB532Yhne1( C!69v5y6j򖞆Χ@-g:UԶO]Gyd*\E \h,8j@P$r7n-95+u \R +'M;]5' 29O]gq-֭|m,vHnK*9gV)ƶcy'w\r]ߌh$}%Pi(E) QI@J) -% J J(E(5R?UnI?d[??2גo^?q^gKF[__ Ľ%Z2o_.気q"ݓF[w4HEJ) -% J J(QA %RPA (E%"N+W@?OпmMCѼ[ncR܂C6 z7}qugDŽt1PovRm%XF In|vk1+^M?%m?fLRk 9aG2+4ˀ 6{Qf/ٖh ŷ9-8t{Ҭdۡ鵈lTaܭ;m1O㏽FzBX ͨ۾&+s&LkEO%).8ӗ[6+e#ᘏFA$χ9nFzRG E$#-2PA"n|9;LEYm#`,'{ҳy4g]yt9!5q:`Zlc=wsv/i/Eu-b_Hdl.P]m`֯5[h|| KNX#\51; FhT@''sG-tԭg?8(o4..tv7V;<0'w-8[ G8!D^K%x|v\'ʹk- X. $dgj-4,<$س2p2x8 -['lx#pئiZih 0MZTks,*T\9VbZb/,l9t0YiY~kD#\qӣHzҊj6=F[hs6%ƛyZ};C!Hj}$'?-uN6*H0k,oÂAyOٿ݌c85ҜSKb1(5D4҃@!s(R}W:RDIxE7R2PA+7,tG`Ɉú0XM4yiScjsh^;RrP  I?W?r;W?r[4Z*5"y偹h,ŜOϒoU=RJ޽;;2㔇úa귿2㔞 n\͕ 0S9OKk)ppl:o#UpqOfN&7;YbNx? F]QO+V\E+>YݤI%J))M% J(QE! %R( QE%)(4UK/j٪?_@tw2[׭ y/m7J8kO>$%ީlKcU=9?ez/s\x!WOmދE F4QAC@RPA CKI@%)E(4Q@ %J(3\__vO(KF6~ӮB0i X[?dՇX_I⺻%iNW8G=AIXr5'}W=W~6>6fW*)}V=G5o'wpo po *)}V=Go)?]eeaʊ?bտ}V?aR8?Q8?Qʌ_l?O=M:fե8?Q8?Q.ʌOlO=GV??'?M&_*M&_*ywTed_cr?u/9?j}m2T}m2Ts˸rDZǨԿէ8?Q8?Q.ʌOl?O=KǫKpo po ]Õٚz7TV/G/G4*3uO)?ڧz~6>69r;;TQIǫGpo po *3O)?ڧz~6HnLfQF g`G$uf";km$ѕ*0r^y-?+P׬9+ͼv66?5Sw-uO+2 Ph(A RRJ))M%Q@CEPi(E) V?UnI߽?8k>&Cz-C_6-{W'H"e]TI 蚷/Eh#zT J(QE! %R( RRPA CKI@%)EE?ܮ+/һI//Ҁ5YlO'O6տ[%fŰ0ޮKbb'}WZ6S] &8( NOjlQQ\ඓ%afWHo8` * >&1^ڸ̷Yw*xԗA\*r2V-mN{Xhۼ*$rqKR . oVSE}Qo\ w0 Jy:N,kxV(LȮ78#ȡ 6\τU?*`H`59'mmh$Veu˅QHӑ&)%KDl-Wsˌhfs>QTn |Csk|K/<Mxj~[#'94;yxn"G<c%[RZuO}GQ|'_6Qvl~P[/&s.nu ӑN0GpMa\|>dy~ XC*mk{%Hvп{lWӞ懂}꺔QO 1J(p̤G[ۊNk׍y;hrcER:$I&?loY68SR:C,4"Q\T0A&みpRXE8ufϳH? ih/#oQ-7PE@LNvmse:Mt^\9#q+g}A~Qg>߱=wM|~RBs}4}:f+}myf]Hw٥rxǠo>} c(ϳH? wԺ]WngKm96>ZIikjvB} c(ϳH? _VOi[Id\He9A{uX/k]ZmG7ІrKJy%=1;>} c(ϳH? ע??? z+#>} c(ϳH? ע???~aқ?|VoRE P)XHԜހ3u/Yם?;6?5zN!?ѐWxG{?}kD]\?rMupڂ(4RPHii(4RPh(4Q@h@ EP(QE!E%)(?_έqO:mCoVצ]m^5b5ީlKt&#-軚85b_mދE F%T( Ph( RZJ))M%(4RPh(4Q@h@ q~'9~O+?zK VNL+hTxذ,ʕZZ ?WmZOA? <SYA? <S@yw..~cP]C˻u=w?P1?]OEA? <S@yw..~cP]C˻u=w?P1?]OEA? <S@yw..~cP]C˻u=w?P1L$ł%rJ{ҧ1? ץ?;6?5zF!?ѐWxGk?>l~YܮOD]\?r,QA %RPA CKI@%)E J RQE( Ph*?5Z?@tW1[׭ y7Ln?8k'k^kRؗG$??MXFKw5^/')`qj2[@CKIPPRRJ)(4PIEJ( %RPEJ(E% JSI@%\W_v\__[uk`4a]qg-ݯIvEVeQ@s!\|.$`1,)%v>Fq'^ Xcfb3 c;J_K4ٹ۝v6<803t H"i`E:+;33c&ϵJPӼC6o˨Esm 4k$leN獜fp}O cfurp92u𶝲&-ﲶ#Oa6qze>$pٷ}Ů\~fY%%)E(4Ph(@ EQE)(I@!PIA qWV+t%vq^gCFK__ .?c[??2ZגoT%w9OS#%軚ʎ,?Ej#%軚$ܢCPPQE%)(4RRJ)(4Pi( J RQE((@ EPhǤJ'F^P=(k?'O&W a6B({OZ7ڨ?o=[J.IX2IWvf?PI"!,r;-H# 9*9T[Qݟ=N?Okg-Ǩri}S~/?vz{H5jg-ǩF|ԽDk6?Ƨ>3l:jK)"hEncfBI˶~^{⫈nIkK8>|~NETPwqkW+dhIEPhPIJi(@)(4Pi(IE(4QI@J*_5Zҿ/Mm^5e%޽&Apי|P[Ė Ǫ[4&V3qM#%軚͎3| DV2[@J(( %P(QE!)(I@RPA CKI@%)E(4Ph `jb0ZHUl&[*kFDPq`T|fmsŠc$z ֔sjOݧv+#o[OX GvfG t~,+7]v%,;oo_Wvk?s08t^h䕿k?s09_$.I[ahadr_x%o+7]gv59QA 䕿o_ݣ*9/H<]AqVnH<]AqVnE؋9YO[CU [ݣG3 #_W۞+G"vfG# [?|WAU+7]w"vG3Tr_۾+{_ub/i?s09?U [?؋9Yϊ"hXuV&+xcae@GN4Ėf'%{EP~_2>Zl-atm8ZB 8( Ph(EPh)(I@!PIAIE(4^ҿ/V*ҿ/Mv:FA^a۱K$]K;`GpיP/ %яT%t]? ʽcz/sY1Y@U?EkM#軚#nE%AAIJi(4RQE( Q@CEJ(4QE%)(4RRJ)c 4%}*Z(# Ry Rh%}(Wҥ>JQ䯥KI@y A}*ZJ_JC TԔWҥ_J"Wҏ%}*SI@y+G!"Wғ_J¾JTPFWҥ^JRy+R_JPvP -% JSI@%Pi(EJ(4QAC@RPA JZJ))M%Zҿ/V*_ΚF[o4#5y/sm^5f%ީlOSI蚱7vEj䜧w4HhPPQHhI@J))M%)(4RRJ)(IE(4QHhJ(4RPHii(4RPhQE %Q@@ EJ(E% JSI@%)(IE(4QI@J) -% RRJ)(4PIEJ(4QAC@RPU_:U_:hmCֿץ#-zpך|RCz=N/')`qjic]C8541_.6(4TQ@CEJ(E) )(I@%)PIEJ(4QAC@RPA CKI@%)PIJi(@ %J(QE%)(4RRJ)(4PIEJ( %Q@h@ EPhPIJi(@%Pi(y!_άUy!_ΚF[o4#5y/sm^5f%ީlOSݠ85jz/sUOh?MYF8?ދET)* CKI@%)E J RQE( Ph(A RRJ))M%Q@CEJ(4QE) QI@J) -% J J(QAC@RPA CKI@%)E J RQE((@ EPhPIJi(CJNj !_Κm$?q^gE[SNKzm%zpי|RLxCz/s<cWw5ɖxJ,go8z'w4Hi(%Ph( (QE%)(4RRJ)(4PIEJ(4QAC@J(4RPIJi(4RQE J(QE! %R( RRPIJi( %P(QE!)(C@RPA CKI@%)E(4Ph(@ ETCJOU_:hKlϭ y'Ķ˒o^1M~د_k&L 2zdK'k ?"?b]s8|Eq#Eh#fT(4Q@% %Pi(QE)(I@!PIA J(QE! %RPA (4PhE% JSI@%Pi(E) QI@J))M% J(QEQ@CEJ(4QE%)(4RRJ)(4Pi(U_:BW:[;`C $|FI^xٿFC^_6r o[%ђU-uiI] P ??MXw4HEJ( RZJ))M%(4Q@@ EJ(E% JSI@%)(IERQE( Ph( RZJ))M%( %P(QE!E%)(J(4RPIJi(4RQE( Ph(EPhPPK!+u9$_:h V?N2)k^KR؞g `jP1ȿ?DUz/sDI@%)PIEJ(4QAC@RPA JZJ))M%Q@CEJ(IE) QI@J) -% J J(QA %RPA CKI@%)PIJi(@%Pi(E) )(I@%)PIEO_?#_ΚF[o4#5y/sm^5f%ީlORz$\Ob]rH$@|WSs# E\ FQPP(4QHhI@J))M% J(QE! %R( RRPIJi(PIEJ(4QAC@RPA CKI@%)E(4Ph(@ EJ(QE%)(4RRJ)(4PIEJ(4QAC@J(4RPP!+u1B:WE:e[O_3Zגo^pqKo3⥵%ީlKOaDVdQ,Tl 8POR?:|&f >8 $qǦI@ыx^M'_j?a$* $Ћx^M c@H?T}߈hGc@H?Th)Oؿ{R4a$*4l_)O/MIA~"6?EFG{ZϽԿa$*>c@H?Th_k{r4}ϵԿa$*>c@H?Th?k{r4}ϵa$*>c@H?Thj{r4}ϵa$*>c@H?Th9>?jl _?{r4ik?a$*>c@H?Thoӵ}_&}߈  Q~N׿/G?jl S{r4y}o_&߈  Q>/Gjl O?{r4y[a$*>c@H?Th/8ϭy>/Wc@H?T}߈ >sϭ7M^  QA~"@(y>/G{r56?EGl [}o_&5kC6?EGl }/_&1kG6?EGl }/_&9  QA~"@3|K{r5A~"6?EFfo9MϥK֧l OI7I> /Za$*>c@H?ThV?%h'^$Mj߈  Q;K2ϥKַl %i3/$Mk߈  Q|_&2ϝKl I?{>w /[a$*>c@H?Th7%h{5A~"6?EFboI17$Mm}߈  Q|O&l{5A~"6?EFbm|O&l{5A~"6?EFa|O&d{5A~"6?EFal|O&ϕIl I?m.R R+  S)HxQԆVXbЃ/3 ?C$%я^4 /$x~x} 8#%y/Kb^e?"|Nm5{#sc&7qpKA-H6U==G }Q+m2 @9)+FFyIg^M}mhl0*)ナnj,`+4-q1Ygi FI%F9V<Vڈ]]1@]|}2Rv֍úvw0\rCR8V^tnZBPYH ! [sm"4 %YY 6:mmX&`.#pZgkAj:W7:djbFcvlNy`S 4qg4}́&eʲ0r688skx=2-#MxG&mEռeRJ 2G^jtɩE82d㌱w;xzܓN5}KǓo$^޻9m1ޒNŚ-v'Ƕ c \pFs4 5ӶKt*mޠS|3u}@R+(e"D$dwx.drx {Bj7w]ަ;o45TP#&TszZfeA!X`iڱɠj 奺Ȋtn*<ыL(fs[OT4 Gw2Hrq5ZY֣m$1:ʀd,-F@P98=]R9[zm 8н6j.ޣbŲ'iky$ʕpmr_ q˧jGL`wwcl|H3SF{\-K_iishNhrye:sΉ72DN,H 7tkl)B=8 b|(I$sY/uv+.֓( *䪒x嗾 Vڍ_24aFZB#4K_4myn qo$o/21*9.b[ymEiG8%Git6M٢ܙMsBJl;1Ixr}VwKh-^#If !6Haz] yZ|X4 +`t1I'j?dA;q;:Tm-#slHW˴g#.3궚ik,I-ͣNPDZ|9;η7Ѽ{#E XqG_ש2,np]k^[DnB(Tw%wO=*k)/^kϵDlSGN[qj~Ct+ .KD`۸$e<ͪOIu,rx1PI EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE{([c>pטLW g+ti5kP~? yOx]u z*ĽOIc/ b@pUvG#؊`f G 'kkphN+=>$q!Gh XO*b1}||/?xJ] z N>T`tySbׅk)ƁMwZ?ѧ`S{b׈֣O5] Nio+ 0GT0&AGi%&AGhӰj{C#o?J,=57_?5 j?Vc&AGhӰj{̝u7@f׆KMwj?Q/5 j?T-Ox60`_ 0Mw)ơ>$5S-; yƯ?;fׁԿ)ƜsA7^' AGh\ΣO4i5=-?eȞ[4kA*N6tu;/66b,q c skzAq^ p3ЂpEzuQ hURo? endstream endobj 90 0 obj <> stream xX_OHﰏv%ow]E@҃+{@} Sͬ׉MMt@p왝`*7 `\6&WlpyZ,hD&GS3Ή&p˩p1Ye_Hy6vM.N,˛~p#%NĂ=F'U@¯cw "/`ZSTDD@} [hqI8Au=E08T'R}$A_Y ³} F'cF%@7dlG2vZc͵*T']~ #dhޟ!CXˆqh=r|cZa)OPQ+ZYMeU붐Y^i OtX'Ar!*ݼC@j)Ӟ, 4:&rT hٔ :2dY˻L"&\d`R,uf OXCbE0'# uI?1>\l9[v54 '[ |ݥ.P(5]HAM$MB15~D(#L $bԘmBf ˽DKƟ[{8ظhΠ[tX)JP|0Λưwې)x_87ɃE#uppEBP:~E=$P pnGXw?iMaqf^c)i[WIR+> v _ u:QBaZ2.ghI.|@#MO|J9 <:)hjTޘf8s`n[~5xrE;|,XgWnVu9)+.v}SfFjSkVTiw aqyD%V ;RppZڀ[=$\E =moKx5( ~8ǫ@gp!\j'Ú5c/) $UV >ӑi@G~ؑ(1 X >2͕l(n@mҽ |(cG .q6#688wo]Ӄ032eDˠ׈W`FN1&RJ:kTCNӏ_~dlQf{&u u\\”QN 0л4HR :v $۔e*l:WL"JBj,Y. c:H-iR)MDbRub;R3G1Y O qvTwmP5$-Ӯ-TGŬHlmpW)rJbє+FD:-M\tni71,H %;Mٗu#ovU o~e?oZ endstream endobj 91 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}\XhfO._Gh?+̊ßPSi4};M#N>5mNm#NH³]It}fK1mh32N1i1BqAm5$ p>nr {Z_ssGF5-G+Vڽ]jrNd؋L20Nh45yʬDV$;<.0c;'Oi;$VavwGk)c6om`{ #|>c[ @'q B mt]_OmBۉDCgx#9bMr܈X]F?ӿ?𪷞ҶF??&x^Qn{q({(y NсװLkWi(o~` V#yopxhtZ҈iqHio6i{6{i@85xk:ޥ}m?E c],A#X1`7=*hmkc>?M$O:i V>D$ ʬ&&"h%Tr#fhpeیj]_C;# ^ZOpvP 44;#jӺϜMnnƛj䐓dVNgHӿ?C>[*lqQaѰQ$T/4%ˤ# aZJjs?dP?g|knKd@Ng# OEjZcRqkbU#v Se4e>j!Jsjb"*w3FX#NH“KAwG աQCT9fӿ? ?$]jVlE/id#OH¥K (#OHµ;J( ֺ`l.$MMoct+Q'8-J,Q:;#OX­G?,Jm1,+ӿ?›&$hwbrJ1Ə$Q$NHº lɪϧs.=?Hi T:K74+B; *ۅ4X.U]G ģNX¡4J6-PpdP{zVZ) T!6GKqy%-t9_i~qYBGMWğ,@͇+(:B8`GȾqq ٞK#Y%>T"S? H},gtЁr)BmG9/)'X=ި7Vf"&rXv?SGkm>Y ŧ#dD h jvOA,։DJ) m?R}:k)@SRC؂3j㴢mCvIF̓mأ{^yE%5qʪ@crsb]CÖ]'x$b)#*HV_pܛkri#.;|BCam*Hx#<#5N"4ʯ!kfl2yַ}@{;IѦ_I_ywKƙ-J8^;ǵD{rbl,G,aBJ!U$99[o ZCsחW\&)FaHU +{vVCv{$y_7Ы9$'Gyë[rQ,pJH}W ?!Ӻm+S:|R_^Vrd@n!ad.qb~_\n'1M A$yc%=}@;SZc[6 "nݝlt1[R1f3p13xZ$KeMgl-Vksi#pqu5v}/? 1_mM%Io$I%.GUEN08P~ۏrUƕg aZG*.vZ[}}h/}}jS2Ց '0w]Řy|?SԬյRѺ%'%"mVckC̾=̾=u5,B(#yT)@d=KUmo=Ve2*pa}C}}h 23TC#`vjfZUO2v$p9YF^^Һg4A^^td@}?&p.̶ubK0{;N^_p.̳})y]ouvξ5,,sPIo{@k;K^җ,$Ђ6:v:v4ʼcQ? }}h? }}h0 65:v:vccRyli|_p<_p=0ƅjp ^^֑Q%ݖisU_pC-?UY42^_pBs $.i0poo?,Ǘ4yTxEm/?, 1ae$Vx[0;R+ޯ?Af^iV }}h? }}h 2r\>m?!{p.̔Q4Mw^G4׿㴙=,$z5o9Go?!wmҺ 2ukvKgauom6mDpڔOp.fXNoo.vq@[ҋ-,Ǵwѱ6ބޟ?6]F./ }hE?AfI?6]mh5M?Af?;~m?ӿ}vtdF1iDm0UFrp2zߵyg&Czk;iDLd0Rc7Mk)i^K#C'Zyr-\s럍[dO[Z2ͫmky ŴqO֭/ccʲ`~^Pe^K{@1K!A+}F?7y8dR%vp=zt#ҡ[36<*@9"8{o-`~lڋ Շ60Uip$3р> rFarbysV*wkn̶!7 zZ\J)Wn6 ͉\Wпs{pП:G&~ΨXxQy3(@ŏҧg K9'c*kN嵚ȩI\*~Us؞ V%a!!U"fn:@|*/Ico kG"2)fb *ѧ [7ù[y9sM:TeXR 'xX=,z0 O"֖]Z[cGdKǠzՋKVt\lIɪ?F$ $%c7pm|AjJ\*30:}){H'7mQ;Nmr=1XiwW&9AJG#aBpW#z햇7|/ʑl_g1Sa$S eб]4K5i[ qm  3muiUk%w7c=ҥ}tw Ζ)sͼuʮ#F=z[n#>YHt$zV Ug fVv|aܑgON+JE+9 HU[dˠ_S1h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣ "MnюF-n: yA/խ1>_ oג*Z~DV,6&M#F8}m-Ƴk pd;ư) W}hH(]ys\ |cb*}/YƏm$YwqT(:Ej-Ymas ,Mʼwr0?Bl-UK02Iz AwxG: ͸ Ǿ;qWEq+%QBv=M)7-rHc)v^H϶/\Mݹkk/."_wNgˁJŶk-oL?H6UQMԠ}S"{AKY-ͬXʤ9_z.2_4s/?/}ft _!X0@@1vHD/aExuK-Nʹ< ơ1[+HvRGHr:C^&i9#U"v7V!khmٿ&_*6kMp~!o6kEcRz+>ukH>{EMϑ3I.8ǩn-Wu!H.dӛM^ݕm}OmrQp!#2F\?KT`GXxB%(Cm ] u0_OU$3/c? KӪ$2=*xd*pÓ#Mޝ{_"k^4ӂn[M4vgjee6=Bc{tJ-M&Us(c9?5cxI4Hխm7WYY^R#j@_xW6D+}k d:= 5oeJWvȭ}A],qc5g[3I)qĜS|ci=ݬ hITdAגeErڣ$y]x ㎢5 άmo1%uKm7S2EYcIc1b0]Po U%+!As2o]8)c=ߥheJE̼WW {)8G$̘;B|T}t=&R, $d1BqIX_* ']ޙhzct}DXKQ>7/cidF\*ǹcQWLKUI$# TdZWy.9[r{%͵"Fv s&H<|)i&_*[X6pփOJz?wr7 ~`V2ds/?y:wq49XHS9GJ<mi enl#%˖/w.1͋ҥu+YՐ ]A8ub8c[,\uiVSAlmK7 nem)\-뜜gVDX5DжU@'NQIEFUYn",AIIN+@id _2Uk o>K"xQQ789n"y/$\<1I !I]H(5r)Trm3Zxlm*; dI@fҖx$&kcb*{ۗk;as"" d {C/j`]dnE稩nTuޓLUEomgsX/Pj?%χ&H+3.o_79+ v?q)MI/Sq(# W7{HZI ]Tcס ȱהjQg(bw62Ͻt%Ou]9z7Qmٿ&_*\: ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY}oկIViy,dz?yg,dkbz8Ū,]iB٧Dx.39wY=O[[ڸKQbr2GN=y7`F{i-FѱW|F+sGOѬ% JW@l?5(Ѱ?/mW]nZ$r;YH#5ί40kwFPؿ Cb xJ.pNFv待khbvE=S779&o&w\u6hjWd*N]c:qĎ?^DM2iy1ò7f*һ-Q<ާm㆛aA_G)NRI>c^.;%FFǡa<h/$cQ Ѱ?/FPؿ…9%dv)amXB$DzUGzO&OO&&OO&Zj|V\czZ~.Flb2Կ4y2Կ4_h?)j so$/ԩ=F)I70b1trG9g2|hqGk153\^̨JKtCc <%ͳ8P <ש|7idQ´FlDQ5cɓ~BQ^~~'fqVF1OՆqц#ߎE?4Ȭr@?p*ד'K'G'K'N4asuW2j6/+e17c%ٷ0&| qgv>L/ML/M:R]= v:mMqk }5T>L/ML/M9?!]Au]. ^GC}3Guvu}~\ ݸ ?_?7ד'K'G'K'D=raM[ x3_R8Fa6q'9údU!gU~?RI?RI/z\pM(j<ZPi&K*NA?&I' 뼙?_?}6;Ȥ&i\BY|  ojZ}W".G91X?~c?y-"{k-YĢE.F`=| ~ ֮\<WP*H$ pa0A)/:Eť^Z=UG W$;j泫hZTN»A Hߐs;+z K;}6->K;fB"S~b.pWk^7VSLțaP3TKsG[a'FxԨڮIb3נ='rKoFgF N>h?:ti&B|ҹ8NuûSLxywݷݍgiRԪ?_'_GAK/O3~&-ލqv#FxȈV~r::/Kuyyoc(i##U;sӌ5?WѭU⤶gQRh)e 5],u:gHSʤ$lcpkJR:{t44 YBA{76ID >NŖWGΜEI <қ8 kBRK(Kv#ȑ)ۜUXn-}?ǝ'Jkv5^M>,@OR( Z?ht1hmH9Mi+^soʬy{?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J Z?kcΓߥt(ţGC|U%]:B"r@n-}?խc4 ,'XViw:,nR2Jt1hmţI4Y$/h(]\zu/:O~c?bLɦO}2/#I昕T)%>qҰeᠸfhn+;u(CţGC|ڻu K+y7U#?>SV?P?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J wATr :^nt-9)H8rLJ䵛PLEb,fئ߼ >l:oGI-w[CiW3Qx.]JΫʾK(#Z|^RB!M7 m+qLAT}]??],{TV' Cz!P=spATEa\??>ɮnUnQXe7*@Vu CC!PmwP>ͮjUYb띷z|I5Km2}J xdTsTpsEjs:jn }8ߏI}wP#ޣ}êj~d IjLCD "2U?!9sBr ;!Ry!Qm,1Vm"oc2#Dg<(^)z5>"A^,6SK{C+ľeP@cWjUFAT۸#4:Xkجm!f̳f0>ဠ.G+]AVR3fHrQm}+G?3*']??OTpsz^<~}2Z\%ު@d@(>^n  8ëYk~m~ݙ.|;g"GPaqq0=fUVAT=]]kŬݴwim4$QVgƜɭJ=$8IJF1<w3*+]??wwAm缽s0 cCEs^A Tl?3*:*+ٮbU&sڏ.&vMjX7(U [MRUFIW5?FڭHS 71 [X߱?h/?whho ^U/* \Kt!&Wgh$;ȻHm#+ιAx Tg\??],ntW3]??7k@5o/*1POEs c5 cw5 C0U3\??ϸ}{HInBó>4!oѐוLy/SYzk&~FIT'>OZm#=軚ˋIދEJ JSI@%Pi(E) QI@J) -% J J(QE(4Ph(@ EPhPIJi(@%Pi(E) )(I@J(4RPIJi(4RQE( Ph(EPh JSI@%Pi(K!5n^a5oѐוJ9׬dZƵm^2 :ݗy/lK'G]eDߠ83:EC@RPA JSI@%)(4Q@h@ E (E% RZJ))M%(4Q@@ EJ(E% JSI@%)(IE(QE! %R(4RPA JSI@%)(IE(4QHhJ(4RPIJi(BjS'3Mfn?d5e^CFI^bӵ!ݬr2J/s"??Ek?Ek#ދE %(4Q@h@ E PhPIJi( %P(QE(4QHhJ(4RPHii(4RPhQE %Ph( RZJ))M% JSI@%)(IEQAJ(4RPHii(4RPh(4Q@h@ EPwO!fKi/xBq *!2Job?d5?3e^cFIT%z4G(D@3[XFO[O#5軚$h4RT JSI@%)(IE(4QHhI@J))M%N(i)@;< i*3:y@T~zy@J_Z< ր$փ:T^z篭IA_Z~z/IIQ֏9}hJJ̾y@J_Z<*?9}i @QQHf_Z_ZO9}hJ*?9}i @QQI/IAր$49}iD(hEQ@J(QE%)(4RRJ)(4PIJi(?գU.I-FC^UC6_?d ͷz+~"jlKHFO[O#5軚ŏDd@'Eh#4Pj (4QI@J) -% J RQE( Ph(Un'5bC5k i*j~+Eqdop9k$H-jx3H &W4Rnʊ :+H: <#ƏO5fOG ss ?Ɠ#G̟oΏ}:9O'|̟ѿ:9OthI?lz?i9?oG ?W7z?j3jѣ9=>=(I?笟ѣtO ?4i?_tOnz}='O4wO=d!i紟ѣ9yi?]紟ѣtO~a 'O4̳m'iq-=wRwwbo'iEO'zOGwW}FW=wRuWyW|Ghy'ZWi_>|G7} ֕?I ֕?]q";Z*]~5$ΚeY]i_uWD5ۏ4ڶ{ #\SyO W-!9 ̤ ѱjlt+֕?G':WAtG\{2@BVz `>b/5+A#4RPHii(4RPhQE %Ph( (QE%R?U.I5m^2򯈿!$V׿5m^2 !$[8EO[Ro_.c??EmI#5軚#4% %Pi(QE)(I@!PIA J(8C\__vs\W_nx_E-)k-&O}tm{lEmz2 hKRhZMy]YwO3|$9 )؇Kq#Yj.۱Ü~Sis ɻɼ4—E`pJĉ Q`׮NzB>=o?싛-7,l9eO@A{viZu2Z&yEbpT,C`8ӭhl*x#?CUE տ56Gfz/A ;5X2Q[xG͈䞛N7-%;Watkkd$-ӚX|Y]ۣW-s yŻ(VNrH"n4-:Vhof\)%C"8V'=il"%I%ocv;&M&t}3j7hyBN"8fߜ )FnQ8udG:E"Gm}on\UTvdڹU8攺&:·7w2<#dH02@3U~AcH^iZXKŽkj@/A\G-1IeII 6Ѵ#zWI¾LI$İfrK9Iem|pJ؄Pf sR$R(YΛc V? Ϙvd3)ᤵD>nT32U.>+Qt %$amq5Ԧ- іϸyFi$rDc7|3q;gs:8UᗙZ\\ɦFU[Cp.s)`YAh`)*@⽏MNHݤr`, (a0rJ+B/j;w(C<%vXlV99`mLJtY,^+8{9fݑ0\xO-I~c|ѭ}SDvZ/t49!pI,p9#ꇆ?o3G#qN5<-Zn]|ƅxJ8Kn\ilϬqL) r= ɪy^Gbzmh>'fTp)B s r<@{esğimUtͧcѳWwhk'9~-|ܰ,0Tu!`Sҵ<_|9bY78乒4HC2c Ri#8gYsp/3Wu>uvW*)gX3Ic|l9^3C(3C(aʊ9?5{?_?_*(cX/3F55?_?_*3eh٫ύ???"??"v1j\90j\9j!}!6zK?o3Gصo5gۯQgۯQ$.Haտ[},9l!}!{I$L_jgh>fu>u=&/~>fW|9m}!}!{I$Lojgh>vf~u>u=&?_4dտֿٟnGٟnGrD.>V_fڷYs3C(3C(}[|9/o5gۯQgۯQÑgտ}[|l9j}!}!sF_o4}V/3ZfEfE.v>>6_fs3C)$}iݕcPzO"3[yQ2r={םGOfI;g^w2 oi`lۼDluk'ŮYIIJi( %P(QE!)(I@RPA CKI@T'fsO4q׭?,d~!8m;\+"V??dKb^"* ړF[w5`+jOmދE撊* E) QI@J) -% J J(QE()'/һY+/Ҁ/Y/[;SP$q]Dg][EsIٿN+>l跪ؘE%xJO$Zl(0Nt5%4[SF%2/!i8F) +ƙsf N'! H#rˆW,53T᧒% 9AUanHu g$} Ң{o,OXm F"Pq+ |YNVQ@%pѳ()fQI0P *ȉkp$gv3W;\2+WR@zlY\[[ K+4EZ?,`}nJs@E ~䴆Kq"=;1 !HO%7SlX֐ZLQafm6CcoQY-&6IzJbfCF0U5Ьh,Me:Te7UI t +Ŗieq$7i| .@ G#m_jz}m "}w)~4y$$!w% 8'~Կi[?loU<^IJMԿkVR+K<O&h /i?>ԿkVR+K<O&h /i?>ԿkVR+K<O&h ȦIl  pB=O6տ[ӗ?oiM>l跠 :; _x6?5zu; _٪=up4O*J$I@J))M% J(QE!(4Q@h@ E sOZ?_@_'FA^UX!$U/FA^SB??dKb^G"* ٗF[w5`+f_mދEԔ4RQE( Ph(EPh RZJk?zKk?y R+KTva'+>l跮NIIu͟uosQEAfFjW:kk-RѧWW(x"`/߭V_No<^QwGB$g9(wz&-w$o%Ɨt P*L0X7Fx 5z0Ѣ@< H mU2x;fh1qخ-,7_5ךo4Fzgo9U3zeͬ GPH I |IOʹ#CI!#psַl!Ἲ] Yn<嶎}Xuv?-꿂HgLI#J0AAUaI UʐpGP} PU?'GWzLUjY_e_s2T}PU?'GWzLUjY_e_s2T}PU?'GWzLUjY_e_s2T}PU?'GWzLU*v-)͟uoHClKYpR}O6տ[vfH?cH+ͼx',ى'6>Ou#Sݟy+|s#cU>ѵ}Ů\~Ad( Ph(A RRJ(4RPIJi(4RQE_:UI4Z?d?1c^cFI^O ׵,*="?DV̿2xCOZo_.7)(I@%)PIEJ(4QA( Ph(S\W_v\W_Zqm`4a]lg][ErVN-L+>l跭'"I袹j_S[[ M$R;)r͵U89̳ĎդB8Eɒ6#Ɉyp O#8![އkE`&B<ݵACi olZ{R:j[qv/`6pykP,H,wW  )# ]#8\n6[*22dWBb[m7>i͓ K+du*2(N_I7xg`c,rc~&Ls)źzZL%etߓGF dbp@S؂i\(hix'hфr bxQa5Ɵo5.]Ko <+pq)tI")+nm|yWMoEjPo§iw6F̦%!6no[PT>R Q[57R ;ry>c'N9-b5̳8! ؜fsZP:x_HS[yc$̱ؤ9 hXXiz}~UMŶ'$5bycI]Q,~;5/[??TPvmWhӰoQQ@i_NEEKa?Ə;5/[??TPvmWhӰoQQ@i_NEEAsy$NaSv>l跩 z5g^2 _g`t:m?FA^k,}oE]\?rM-uP̲J(E% JSI@%))M%( %P(Uk/Vj_-FA^QC6??d!ͷz+~"flKBOZo_.c ??EkM#%軚$ݤ4%)EQ@J(QE%QAJ(4RPHii()q^'I~+?y vN-L+6I#nVLg8##5Y6O&֕:éٟnGٟnSY}!}!=ٟnGٟnS@}!}!=ٟnGٟnSWVq.g\(ϦM7?_?_ۺ?l!?Ə?U.ǹg?_?_ۺ?l!?Ə?G$<{~u>u5 VğOkqfEfEC.+G.gp gA[O2ٟnGٟnU B?l!?ƀ,!}![{G'VhٟnGٟnU BK]J"C#X?_?_>u>u?_?_>u>u?_m,r=**Ge5=f'ѐWG;/IN5OFA^kOl~WܮSE]\?r4$4Q@@ EJ((4QI@J) -% J U[ҿ/Vj_mFA^SCV_?d շz+~#jlKxBOZo_.b ??EkM#%軚$ܢCPPQE%)(4RRJ)(4Pi( J RQE((@ q~'9~O+?zK Vg-ݷIv<0⵩ΟP+#@(((ۄFu":ҬAk6?g)+uO++QlF6X1p2Ag' '%z&h.gh@X+*?G:lUE$%IJFc,U$|0I8d܊J2T#ۊk_ ^˪Cw _QIQF@;z]\QK+J=3O+P/;GV?_v-ZTů?{~ej8;o-{EjZ[%1ƥ UjU2InT]8ZF ٢BG1` Y S/$O}(??-Aƪ=.f_ՏIǨ̿U/2j2je .f_ՏIǨ̿U2j-H=KٗcQI$B{%$Yadf*C(;`dYms|Ty|?)}AƨRiRQ _~P~AbuW# _~P>}AK5KH=N~}A[5G/+}AƩ)Q\/+}Aƨeo(?AbuW# ~P__VQ%wB??8X9?tܖi\ƞfϔ"/R=+uص?nCgn"8gv/ꦜ,,y6~r2]D\ MGE!)(I@RPA CKI@%)E( Ph*_άUi!_ΚW_ݷz+ʾ#n[^ݷz+~#nlKXBOZo_.# ??Ek#軚#nE%AAIJi(4RQE( Q@CEJ(4QE%)(2ZVU8@Uho 񼵖{k 4oLA^CW\&~Z2hq{XLk?>o*?Q(ϱX1{XUثk?>_*k?>_*Qݠ?ƽAcƽAc⫿Oݠ?ƽAcƽAc?Wث.{Qk/]*vE}Ac3XWثsX3X￱೯X3X೯X3XNݤ_Q_Uc/h_\ vAcνAc⫼_?^Tg^Uc'hOp8=vAc⫻Ottpk/FWuݣ@&Q_Uci?\vAc߯X.,:/αO寥'!ykIJy寥'(5ҟE0ƾZS4,zQ u%)(4RRJ(4RPIJi(@%Pi(E) QI@WBWVBW5 ׭?+u ׭?*=ED$8?pCOZ軚ѷIA %P(QE(4QHhI@J))M% J(QE! %R( RZJ))M% JSI@% %Pi(QE)(I@!PIA J(QE%Ph(CEJ(E% JSI@%)(IE! +ub! +tFA^UC_?dFA^SCv_?dKb^"ןF8?ދED_!yc]mPh() -% J RRJ)(4PIEJ(4QAC@J(4RPIJi(4RQE( Ph(EJ(4QE%)(4RRJ)(4Pi(IE) QI@J) -% J RRJ)(4PIEJ( %RPA CKI@%)! +u9%_:h mCVq )!/2JmCVq )!/2J=OED48?pCOZ軚$4Pj (4QI@Ph( RZJ))M%( %P(QE!E%)(4RRJ)( JSI@%Pi(E) QI@J))i(4RQE( Ph(EQE!)(I@!PIAIEJ(4QAJ* !_ΧCJ4!oѐWGݗy%z!oѐWGݗy%R؞"׸w5i`q+^F(?ދE4@)(4Pi(IE(4QI@J) -% J RQE( Ph( QE!E%)(4RRJ)(IE(4QHhJ(4RPIJi(4RQE( %P(QE!)(I@!PIAIE/4ҿ/Mjn?d?7e^CFI^ [׭7*ĽAQ2/q+rF(?ދE='o'F(?ދE FRT)(J(4RPHii(4RPhQE %Ph( RZJ))M%( %PIEJ(4QAJ(4RPHii(4RPh(4Q@h@ E Ph)(I@%)PIEJ(4QAC@RPA CKI@A/t栓BW5Bq׭1εc^CFI^kN265%_%RؗşAWDVPeo|!9 >kw40F4QE( Ph(EPhPIJi(@ %J(4QE%)(4PhPIJi(@%Pi((4QI@J) -% J RQE( Q@CEJ(4PhE% JSI@%Pi(E)  ҿ/STGJ违4En?d5T62J+Cv2J/rG:dgIw5j$F(?ދE F%)((4RPIJi(4RQE( Ph(EPh JSI@%Pi(E(QAC@RPA CKI@%)E(4Ph(@ EPhPIJi(4RRJ)(4PIEJ(4QAC@J(4RPIJi(4RQEB:WEjO_ob[1ג+ӯc@H?Th#7G7L  QA~"@M}?{S4߰a$*4ox^M'7IA~"6?EF/ۓ} o&'M'l }?hrϽMA~"6?EF'S} o&z{S4a$*>c@H?Th~ڟ{S4}ia$*>c@H?Th~ؿ{R4l_)l ϶/M'} _&  QA~"@#bϽ}j_a$*4/9>?j_a$*49>?joa$*49>?ja$*4ڇ^Mj{r5c6?EGl v9Oӵ՟a$*4i>N׿/Vc@H?T}߈ hk{r5k6?EGl v9<>/Vc@H?T}߈ ~y[?{r5s6?EGl 9O<ϭ߰a$*4i<[a$*>c@H?Th9h}o_&}߈  Q<[o9A~"6?EFg>/G{r5A~"6?EFgy>/G{r5A~"6?EFgy>/I?^Mi}߈  Qcϥo9  QA~"@37^M&?%kS6?EGl '^$MKOa$*4+t{4n}/_&~c@H?T}߈ ϥKљ?%k[6?EGl ̿{4|_&c@H?T}߈ >w /I%kc6?EGl $M;a$*4{4boI  QA~"@1q7$M|O&c@H?T}߈ \M>w 'IoI?  QA~"@16>w 'II?  QA~"@0>W 'II?  QA~"@0O>W 'F$kw6?EGl ?^$MFo6H{ f{w@rH}߈ii$z<(C+,1A3P 0nVd2Jh'sMy-7[;'|Nm5{#sc&7qpKA-H#z&a/;J;"mXh2=~e>ax<)tzϴ(0J3 %$ٵaU%S5YiWi[c(.Jsx-4u4c)Ҁ ,e2'?u-;Exaݣ( q*A듙jO BWkIfY#40`2dR mͷd zChVO\&ef*\b2*:V t[(o%c”w=jşƵq\ 5DU]s+19灁OOӇ:mƧҙ26*Wc0ʂHxαE(ȴ5dVѕI+78yg!ҼC&zC,GɒG2}=rM;-/7My{zdl=tzK>;hO-$f8urU4SoN6,giШDzNJ/%ׅuK$X'Ԡ{U(Uhe๑㞀- iwz1Q@XRIYUk^ݛ[kQw8Ppc|`qjESs8cEn T޼FkgSZxc* B|@ivMHmgZ]/HByz-ǂHm'/*V@^=r2:ֹ|7g.e1YhUq"@N8i}p{.{u}u'M:ѠS;;/,s:&@J8 --K 30_a̠$@f's2"NΖgHZO3 7@I^.S}X_j6S|ч4b6 1i c+gs=/_$F6-FPv~`8ǨҮgK{nY1q` ;ay%`/Ґ\$vң}8j{_iSK dͲK4 #e_;`^C.qTϪj]A$ 6:Cljo:Ft~^T)b@>_{?_^:wt౺]tMp与MrOxJt^gPʭ.H#xTZwg+ bk(A!ۈl@铕c?P ^iK,EL&!m>:]+^'dj][8d.:2{]gY,u{->䷖۪*F??|+2Zk*X ' imAj&wP ghPI浵O iίi{m  ̇xЍގZV6ZmiF(i/󌪙Bvwmk[kmQcpU@T. '<0jmG?#\ِ0#Ke\E>\r'z99wg+ bk(A!ۈl@yZRXM/ƒc?S5kooc{UCFy>iN9nO;sfmQx4/ʖanɖO[6s17^$5S MwZ?ѧa{L'Y`uX,l_unJok֣O5V?kNFl'a7M{9}|lj5ݿzB$puSv;H{7SE/?x#x]!GjxIkQ4(-{7^&$q!Gj&CZ_Ni; l_0k̝u7^!Ϳ)ƢĚ N 1}|/?x+x]֣O5,$5Sv O|/?''\ 񦯈kQ4=Oq{idnέ{7^7'Ϳ)Ƴz j?FS8\l_0/ߔj9ICZ?5 j?FST; l0B\f׃/5kQo$7Sv3ȿ`tF?xi& j?D^$s!GhӰj{2N}0t0/MbׅKMw'Z?a& j?FS>q17^$q!GiĚ5Sv Or6^~To3SU]u4y/}|50H?OOΣO4izm?7ȟnUGcC:??ΣO4i5=mg?`u fׅGcC:?$s!GiĚ?5Sv}o 0? ] IkQ4=Ov|c7nL?3}|—Ě ok֣O4i5=> 0he}|Ŀ$q!Gj$s!Gh5=(;u{7Rn"Ě?:)ƮkΣO4iZK _0>sA{7^+ ACh\ΡO4iz; 0>sA{7^) ACh\ΡO4i5=w?`t}nS-s:? AChӰj{gخ?/}|?x$zu =s:?ѧ`^nO=s:? AGhӰj{gn?/}| ?x$zu =s:?ѧ`߰\^ 0/H ?G$zu N``u_)ƏH ?FS~qA{7G.?/}|Ŀ#?3S)ƍ;bb]\Ȩѯ8ګҼx]i-[.0 caPk[ծ RhduWKea+ӭ(U#ED^}# endstream endobj 92 0 obj <> stream xWnF }7Gi~)q j(}P&RxwԿ,9){mq<䐇lO񒜜 Ζt<`T<}=et:OOYI-:K q,~w$*1 GGNѤnrybWA#򫪾^{w?~Tކ_ ¯0㩗-Pw[A3Ӏ*3S5utq'.:U}M?8Nd+?B'7IèN i4u8ĹVcje8Qs=lj"N8\6=\Sŧ4Nt{<1Ie]Ӈ#v,;::^C@.Q傹;y8yu)ձrh2O%ɠrYf$kj(|IQvϐ2)$0SϏzBf ˃TK_[8PYU4gWFE!]nV R4 L7K]CkvB}*M:ezD4tN+*1zKB+A5saܫMT6gVD3*+I!RWuv%W&Hp-^~5EY*_uy1>׏4c&2ai>%Q'Wø ZZ*UQh w r[#qטshډ)> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}\XhfO._Gh?+̊ßPSi4};M#N>5mNm#NH³]It}fK1mh32N1i1BqAm5$ p>nr {Z_ssGF5-G+Vڽ]jrNd؋L20Nh45yʬDV$;<.0c;'Oi;$VavwGk)c6om`{ #|>c[ @'q B mt]_OmBۉDCgx#9bMr܈X]F?ӿ?𪷞ҶF??&x^Qn{q({(y NсװLkWi(o~` V#yopxhtZ҈iqHio6i{6{i@85xk:ޥ}m?E c],A#X1`7=*hmkc>?M$O:i V>D$ ʬ&&"h%Tr#fhpeیj]_C;# ^ZOpvP 44;#jӺϜMnnƛj䐓dVNgHӿ?C>[*lqQaѰQ$T/4%ˤ# aZJjs?dP?g|knKd@Ng# OEjZcRqkbU#v Se4e>j!Jsjb"*w3FX#NH“KAwG աQCT9fӿ? ?$]jVlE/id#OH¥K (#OHµ;J( ֺ`l.$MMoct+Q'8-J,Q:;#OX­G?,Jm1,+ӿ?›&$hwbrJ1Ə$Q$NHº lɪϧs.=?Hi T:K74+B; *ۅ4X.U]G ģNX¡4J6-PpdP{zVZ) T!6GKqy%-t9_i~qYBGMWğ,@͇+(:B8`GȾqq ٞK#Y%>T"S? H},gtЁr)BmG9/)'X=ި7Vf"&rXv?SGkm>Y ŧ#dD h jvOA,։DJ) m?R}:k)@SRC؂3j㴢mCvIF̓mأ{^yE%5qʪ@crsb]CÖ]'x$b)#*HV_pܛkri#.;|BCam*Hx#<#5N"4ʯ!kfl2yַ}@{;IѦ_I_ywKƙ-J8^;ǵD{rbl,G,aBJ!U$99[o ZCsחW\&)FaHU +{vVCv{$y_7Ы9$'Gyë[rQ,pJH}W ?!Ӻm+S:|R_^Vrd@n!ad.qb~_\n'1M A$yc%=}@;SZc[6 "nݝlt1[R1f3p13xZ$KeMgl-Vksi#pqu5v}/? 1_mM%Io$I%.GUEN08P~ۏrUƕg aZG*.vZ[}}h/}}jS2Ց '0w]Řy|?SԬյRѺ%'%"mVckC̾=̾=u5,B(#yT)@d=KUmo=Ve2*pa}C}}h 23TC#`vjfZUO2v$p9YF^^Һg4A^^td@}?&p.̶ubK0{;N^_p.̳})y]ouvξ5,,sPIo{@k;K^җ,$Ђ6:v:v4ʼcQ? }}h? }}h0 65:v:vccRyli|_p<_p=0ƅjp ^^֑Q%ݖisU_pC-?UY42^_pBs $.i0poo?,Ǘ4yTxEm/?, 1ae$Vx[0;R+ޯ?Af^iV }}h? }}h 2r\>m?!{p.̔Q4Mw^G4׿㴙=,$z5o9Go?!wmҺ 2ukvKgauom6mDpڔOp.fXNoo.vq@[ҋ-,Ǵwѱ6ބޟ?6]F./ }hE?AfI?6]mh5M?Af?;~m?ӿ}vtdF1iDm0UFrp2zߵyg&Czk;iDLd0Rc7Mk)i^K#C'Zyr-\s럍[dO]n`}|wpixH` bDBm,1zz=z[n#>YHt$zYz?ڮ$۽bٜl}ew\'ٙYm7rG>8ٿ<ʱ ѓI#AtjY=Eb ېTrxL%lȒq)˸6s۶1뫨Et"= VR0}#޳ceG5ҼNb8f'VYcjM/ly(Q]A֯%Š A >W<M)C@ݻ8:N7r@$19IF ؊6C Q= 3_f>!Hs$Lo})k"3 \gڱWÿFXp>eH H]U|Oʻqd~lM⾅ۆ930uB.FHɜ)DH,~tǐEf㰲+ZRF*Nҧ+؞ruIfG&HHUHP21#XZȌY09: 4ih|VA?(a@?\Nc6 >V'wslbƮ 2!SȬ~hV2a~q;bխ"i]9c2j}FI ~' M\.[_ZW*L;yg9JcxR62ITDŎӆqLVk2\.責7}ݿ)s%7|/ʑl_g1S`.ZI JbGV7iĖk?ҷP& g#5(-Km:n{cJ.ǝ,RgMxoO\ inM3gi# БX7V%w\'ٙYm7rG>8CArOE&m*Z a 0 xջߐKO n˺6YFqpz#HƑu|UC v >sj FON3C5GlQ PU\ =r1WkJ6˵3Dd [< [];"u,}cU<9Po4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvC5ȓ[c[^iFP|Ghs.K$@ukLϭy_2JF?_8xt I~H8ѽfE$??Eh[Kq,A3+qtcZ1i!~'k\~lXzm7V~G]-7Wew@yUOұifc^T7UK3,j'$/\+`8ϩ\U oEZ#KVw[X\²#r܌І UR% ne7].΀³nǜ~xJdp fT|w0+:PSJrrpŦܒ G]6?'7Wwnt;|˯?)p}ƤcҲqmKpDr~&0ŀ/OR5)fUTdu(Tȿ7w^RvKl'k&d2(cF:cދ6*y\=Kmٿ&_*+h|V$L3 s]R,$XdQp(&arӢ3mO3s{7m.4{VJy3\ɚNHhHՈtu.gvo \2_[ CԞ OZ9hp;x"nsLc˹?[k;xni1:Eq4Weba_ƻ=S=b\f̑ǒU8'<$$С$Iu H7C]LC Ű+5=#Rt b 60nGSj^Ț׍4+۾M:龝ڙbYc$APR{l. b)s\OXM(d@@>ʾrygɰ KAt7IάiKռ;w}(o\g .O'kgzM2UVWTڬf`W'|M,JqbeY>mάC [Rݵ+_fiyrK~h Yn㵆pgg'OwksJBf#j8iX2REύh".! {q}k'XF Ru Bp0:ֽw~^o/Cˎa'Vܺsrsmgii5íHɒ5Jtao 5V=M5Ҽ{=G.qq18Uu k)\=^ujM<*NV'R6!FQҺ<[dBd+*NKYc<[&/fFa?' I'0YX/Fl2Ir嶅ˌ>sb魴d]Ji`ud,`#N`<8|97K6;9d;]Zy["kDR$xǫJotW,om9:'?խwQ n4Q,2-P:ӧF,urYn0F {}]2SDWN|;o2Tgvo 4W5΂}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/Vha^k|ZCq^c7F ?_%z!OFA^[7F ?_%Zؗ=OZZZ֔-tG;JSGq~u8=Ž'#!dxבCva//l綒I 4mw`4{94R Ĩzd FPؿ Cb Iu&{{5Kw/s?1Y: N CȆl?5(Ѱ?/g{Gign[]+xlQ(T_@+<q.sylca;Fl`u{W_aA_GvBߕ3H k!D&m;#vb\x}+v8i6hjR$81mky3TdlzKqyRkrF>E Cb ?l?5(SVO@pwh -ROo{%\Awd$hd$j )%wȥe7Zbp4j*ϓ'K'G'K'@E!B\@6BJdbɓ~ɓ~ =7"wkI(+UTa@d$hd$h׳FqFI8N{.H ǭt~L/ML/MJj1\ዙ #A'5y2Կ4y2Կ4Yb fX8tz_69*&OO&&OO&)IhR^,oe$T!<,s#GG-sfs!7ƇOS8ʌdD6:||bY|3=zp*wvM<+\`y+Di6A EVt]3#Lyg.@y2Կ4y2Կ4F:Z8Q(km֣b,2O \p<km\As"h!GzWc?RI?RIөN5#%SHa,RhGH(irOZS7q靎FG<}Xd$hd$jثYXм'cx]C?RI?RI3?UUQRt>޳4Wg\`ܝۈɓ~ɓ~Whe)R1jt4 kɽzF2(d$hd$kdwGoevdg[>Z4KNfx^.#my2Կ4y2Կ5uTT * _{49 a#'+o ԗh#HF?vIb=Q"]n0AǾ{WzeծY CڨW$M80Ҙ ^JtNJt"ѯ-hcܪ#ޫԁx5sY-*}F'ha] oC=Vͅ%՝ӳ]H!)e?x18+޵lt}߫)&dMAo0S? %0zKϱIWvһqEzm?Nz3֝ 4QEq!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP6!OFA^Y7F ?_%z!?FA^Y7F ?_%Zؗ=O[q]r\E PҸPNxV$OSDVm_.jni??4 YBro/]]&xyddAiޛgXCOIHy,jAK/OsI'-wGOθI4N{{{kFTf|67mwcwZT**b!O=sI'Rk߉*tgN;% #34Ö\ig,ǒOҫFT~Nj^ '_P^zMͯy4{8#8ϽSes?nRC4#;кԒ$]$Jv,G V&wۣG?mn-Iҩݶb׺Ǔlϰ Ԋ.?GC|> Z?kB-R)嵎pEJv;[t)bGۣG?mly{Γߥc?b[t(@n-}?ǝ'JUdwMژ ˃q3?n-}?ǝ'J Z?kE$K\\IJPNqLY )_KbGۣG?m;JU_n*,/t s0yo:O~t1hmţ#iZER[teA8G## IIҀ1 Z?ht1hm:O~y{ GC|> Z?kcΓߥt(ţGC|G'Jt1hmţ+MJ.ff2˞ 9V x^cYE7D`o9dqVVAteGGP8KM}h4}b7kUa,m?oHZ8LDY![Kمe( q]^Atٚaпp^ kQ%-O6E1<|Gmkuk/3\???5#sV?;.wZ;*sZ;*s^9*?\??آC#!PﻦJC'/m4 䫓a~;A'6\}b̓(6Xgҥ6:$rqU \iSLjVn{fkY"a̸!Ƴ-?Z<3 ŮrU;p8| ;J}*2O[ep YyWewSxkOKHD")X p;)b?9*kKsjAT}]??ۢ>ǮnUc7*6?kG5 C +!Q]spr.AT}\??ݢͮjU'ٵ CC :oZsOTQ|I&mO[ڤ3q#!pr xH^gM^-A#g_>ϮjUs^oXu[ Ȏ -^ɖB(hUdFJcܚ7#Sٺ;bg.`(_.@ba'vp\??O#]??- T֗M[-VblfDhl ߐ2_\'D\5+ņioqer̪ p3Ӫ5 CC5*wrfK {7 ylf0%s|k*jVfuLtI`J-</h:a!QIoK\xk\kdVH h x}Xuk;MoÍ{4@EolH.:0'u C?3*t9 x2X[-;fĀ# sZә5AGӤI H?.Za!QkN-\fU^A Thw3*a1PEEs5 CcٮbUtu[Qeq.w⩲CK%Jki_j6| 㦲UXbIgU0$hW% ڊf h-աXbA0xPxc]???~xWUGii'ت,fHmW@y# W6<;-icGi *h-fd'GO1*şfA[sslڿ- b9 w^7!>~qk"֧8e  ]~u c:1S;a|Siw.>3M5wi ds]s9?/*KΚwkFs1Q\??c~Ax TfAx TQ\ZUfAhTW/F kYi;q(Xvp[>5[׭gdFC^W3C_2J/sѣ|"F{ow583'4Qy^NL$< ih*m>A+"~`HߦkۦG$_鞵&c[R5RJu%*Z~]w.j3]F#[VO,E'*mRc/l'Q*XlV;su+If&8#Eo⸿ԖTÈ&H9^l>=JsޗW::JRZ<%]װgM`QJO3ߚ4]?ZEl(鞣kP/cuʝkl{Z5~働A8nfaBbX9'j=AKPƔ)((7{}֩Kim,t3sso5ظ6rF e/}Ӟ3mVg]G ggt"aE$hڭbCê9KPE,v fZ[ivyFޯ8*rFxlmcې$*6208;~_*/- ^Ax4uo gM&ڭFsYӆl=GNlkmTv wT+mz&%ݾi"HN".T(]VvVaʈ`lN>UJci/v5g`%fu;>y%|Q-Tv*bK\E+󘻸 6%m%ڵeDQ9E arp;v!%ƣuA.iKӑ$Y^Āpdqd AgeiZ%6d0FRZJ@ J J(9=fZYK.`UÐ!lFkL0gYHfU(8mL்5+FmFLKҵ&Djʬ 1 "I :|l~KpJ7yuMf֖/H#Jpwr;W [31nݎgךrz>-.(`]VDt N -Xms}i~..o/-%K8]cc985jZk|uW#VBzRE6y̺qayoqxmKx8H$fܠyd]&iX2aۍ2y&?PXl-nR`* p*354Z[om pHPtl'_tQI@J) -% J RQEn ]>f0eB#+731N;c';B}I[.[]q%4c Fq:_-g:]3wROSBN]i c՗ڦfXŅN+ d18殞/ V-ibJ%?dHl.HZ] GKJW\@gs>nWeV3c\uo:$s_|QOscoۇYfm?p^x8 Z 4.Yrݿ{>Gw3ķ }MʬUBۏ`I rNMtk?$/JX 8±#'!(aH*|x$q$G,B,y?-R1RF d{\|-NRo.#`hfq,灜 ('q:X`2E|;o`i~F3{wcgf ua{ih0`!DFjg.Khb')mݓL0N$gÚLP[$)CBcgM:oh[>"b>^غ֚׶2]}^h!&#0ːGG^-搗Q^kt}6HHQy-,-)Cx-J%HNDXyˮǪ귦1LyqžI ryއJӭZ >+ANAaUtҷ aH! t buyDEf9H$:5ƭsi%ђkךIJUW̍ {8]/ m90Ĩ=~P1T_ h+fki՜HЋDX +gއ"ys:.U!ir͍<%kE~1 )ɓ -BrOmv fddϠ[JTer&W܎gPo }5֙>fkqYv ܎0g!>.si~umB ]bfU$%_d`u)i@GZ$/X+GF9^O95sC;'Ѵ洍Bǩ CP]?eѴ; #kM~F8Af Դɓ\Ӵ,Ϯ\ñ:nsV$W[b4eo->/n1j611p?*::3Zk|_K{%fV0E)"f'yqEAj.u וؾn}i>ؾlU_/'ր-*֐/Z}i>ؾjb Ub}}h%Vb}}h%V7I TT/k_ZIU־k_ZIU~־}}hѤk_Z>־dU~־OzEFOhJ(4RPHii(4RPhQE %Ph( (QE%R?U.I5m^2 !$V׿5m^2 !$[=?SDV̟3[hEO[2o_.))M%AAIAIEJ(4QAJ(4RPHii(4RPh(zPɱO5k~"]=0,6 @x==+{Pj|5^xV--1E$i ~'_֚Wbni2t 2\ۃ'*WeswiZO D\ [ ͼs*K $+>,zo gş/MVrˣr39Iп7,Q9Ps39F|YBo+* mh2]48'1vr*\{FqxWeo9FZ7od׈ArwC%DӼrWwB/|K/J ^5om."\!w$(?7 `SBWաԏۮ4+TTbD˕s 0Ry[t9R^j~6ئKhʻ$qsŽָZu<щk$$|x$9 ,d )TPY(s+~:+.vXV];99v) jvWo]J u}[hghncF U_ĺݞgoes5!tX Є,2xVqhz +wW'nM 4O$vbbCg#x}4UG}dy$˴vbv>bxǠZ(H8 y$, gbCg 튢<%7'|3L׳>q0`q:[tP":(-!HnUg$ĒFp a]UcԨ``6`OOJҢ0m[}?h6"F3q8bΗ ֒$wP!Lcg c-w0-sע1-4pخ&X+X1I4SDK-GB{1Ͽ|٢(( +ۏ(Һ҉*<{oUg>+GN>,) RRJ)(4PIEJ(4QA( Ph(A U[/VU't>#z+~!b[_kyO? אђU-{i`q+Z_mދEL!'iez/sCoRQEA@i(E)(I@!PIA JSI@%)(M= -#t4\߃7mp9 _=T>"eh舫R?DUJ[lQE!Q@Q@Q@Q@Zh:M(o1t2DGFpPO'tߵ7n-\c=73IT_<v6o3qL/%~VFZ%!D&|Ι޸&s޹aJ}- jVWv:͜І2nm] Hym Ԍ$r74In^;Y6bH* 9T_y.zhvO鯿knݍ[1zo\g?9$n˟3gs39v_]K–i2$R:Fq!m+' KFnb#hqd`c%FQYQ@Q@Q@Q@sWqWA\~a_Q%\7"gO<_^}^c?uzvAfE)(I@!PIA JSI@%)(IE(4Z?՚qW4C!oѐWD͗y%z3m^2 򟈟!$[="?DV2[AOZo_.7i -%AAIJi(@%Pi((4QI@Ph( RZJ)4. s~ ߈ݵsI\7mPaΫ_I"J?UV)n8QE!Q@Q@Q@Q@cUq:yݰg齱rL2E#0V(qg_"cȃ8w5Af#cv8rqGvR(ϕY7VÓ'B$"E,dHE9U}STi267mܓg'yh> 4I~3 4I~3 4I~3f)aD;l~4>qS5h|U9sTOQX!EPEPEPEP\x?J$0J$)D<oUg^+GM>6J((QE %Ph( (QE%)(4RRJ)(4PUn?JY_ΚS[yO_ YאђWk[yOo אђU-z<_ idz/sY1Ȃ"]nQE!(( RZJ))M%(4Q@%)(IEQAn>s'~ v]&>Fk ^А Hl~upvZ?|"*Ԭk.oOgIY 0C:OoJ'oQwEdqo?uym.WخdkX@oho;G+آ?? vW9Ec@ym;G+٢ ]᮹;G+ע?$MnI@oh}VG v?{ms#^;G&9_`F vMr̍z+?ym! vW9EbCPohw26_Hym.9_`F B?;G+ڢ"]CPoh`F U㴿^;G+ٮkM?_҉*$ @oj1i_?`G4{IwH(y/ I .? M_f=${e. M=~ ο.7 MZfhW? g?Xжcڪhfi.glRğS`G4{IwH ? mG,Y[o?٣KrG,Y[oOXж1U?4`Gpb1mci?aAп٣KrGO?]3G'к15o ?٣KrGS?\3G'и15k?٣KrGW?]?=i__aGpb'и1fOqcj4aGpb'и14B_]Ò=GˏTu_ݫئm24B8<QZHi9QXyAWt-*#{TKEJ(4QE%)(J(4RPHii(4RPhQE! %W?Պ?4@kk[yOYאђWk[yOďYג*ĽFD$87vEk&/DV1@ %)PIEJ(4QE( Ph(EPhPFj&7jPVSڛ5f5k*L/V4OGҭhҏ/[ d_J UJE6W)(҃hn*}}(6V(ҏ'[4SGҭ(ҏ/Z*EV }("U T"QET*}) UJE;UJc O4RRJ)(IE(QE! %R( RRPIJi(_:U+tFA^SC_?dFA^SCv_?dKb^E"֛F;w5I`q+Vz/sCm(%R(4RPA JSI@J))M% J(QE! %R( RZJ))M%(4Q@@ EPi(QE)(I@!PIA J(QE! %RPA CKI@%)E% J RQE( Ph(EUy!_άUi!_Κ_^շz+~#n[^շz+~#nlKXBOZ軚ɏD$8?p6(4TQ@CEJ(E) )(I@%)PIEJ(4QAC@RPA CKI@%)PIJi(@ %J(QE%)(4RRJ)(4PIEJ( %Q@h@ EPhPIJi(@%Pi(y!_άUy!_Κ_^շz+~#n[^ݷz+~#nlKXBOZ軚ɏD$8?p@ !PIA JSI@%)(IE(4QHhI@J))M% J(QE! %R(@ E (E% JSI@% %Pi(QE!)(I@!PIA JSI@%)(IEQAJ(4RPHii(4Uy!_Χ5ҿ/Mnn?d_7e^CFI^nn?d_7e^CFIT!z,!'ic]dG"ןF(?ދEƍIE(@ EQE)(I@!PIA J(QE! %R(4RPA JSI@%)(4RQE( Ph(EPh JSI@%Pi(E) QI@R( RZJ))M%(4Q@@ EJ(BWz/4@k[yOYאђWk[yO אђU-{i`q+^F(?ދED_!{z/sD4@)(4Pi(IE(4QI@J) -% J RQE( Ph( QE!E%)(4RRJ)(IE(4QHhJ(4RPIJi(4RQE( %P(QE!)(I@!PIAIE/4ҿ/Mjn?d?7e^CFI^jn?d?7e^CFIT'Ȇ"?b]dDOZ1A_.6(I@RPA CKI@%)E(4Ph(@ EPhPIJi(@%Pi( J(QE! %RPA CKI@%)EQ@CEJ(4PhE%QI@J))M% J(QE! %R( RZJ* #_Χ5ҿ/Mjn?d?7e^CFI^jn?d?7e^CFIT'Q ڸw5%??En軚$4QPP(QE! %R( RZJ))M%(4Q@@ E (E% RZJ))M%( %PQE)(I@!PIA J(QE!(4Q@h@ E PhPIJi( %P(QE!B:WjO_FA^QCv_?d շz+~#nlK(_'F(?ދE=5I롹w4HIJi* RRJ))M%Q@CEJ(4QE%)(PIEJ(4QA(4Ph(EPhPIJi(@ %J(QE%)(4RRJ) -% J RQE( Ph(A RRJ))M%Q@$_:B:WE5Dq׭)?V??dB]zOk>%@_QdKb^s!??El軚FW >k.h`z( Ph(A RRJ))M%Q@CEJ(4QE%)(PIKI@%)(4Q@h@ E (E% JSI@% %Pi(QE(4QAJ(4RPHii(4RPh(4Q@h@ E PhB:WEcP?t@tzψ-FC^a9qO_%zVq^c?F;O_%Rؗ-]7iI,J#?%ʍg GXF!?EtCˇKI 8$ Bhc@H?Th#7G7L  QA~"@M}?{S4߰a$*4ox^M'7IA~"6?EF/ۓ} o&'M'l }?hrϽMA~"6?EF'S} o&z{S4a$*>c@H?Th~ڟ{S4}ia$*>c@H?Th~ؿ{R4l_)l ϶/M'} _&  QA~"@#bϽ}j_a$*4/9>?j_a$*49>?joa$*49>?ja$*4ڇ^Mj{r5c6?EGl v9Oӵ՟a$*4i>N׿/Vc@H?T}߈ hk{r5k6?EGl v9<>/Vc@H?T}߈ ~y[?{r5s6?EGl 9O<ϭ߰a$*4i<[a$*>c@H?Th9h}o_&}߈  Q<[o9A~"6?EFg>/G{r5A~"6?EFgy>/G{r5A~"6?EFgy>/I?^Mi}߈  Qcϥo9  QA~"@37^M&?%kS6?EGl '^$MKOa$*4+t{4n}/_&~c@H?T}߈ ϥKљ?%k[6?EGl ̿{4|_&c@H?T}߈ >w /I%kc6?EGl $M;a$*4{4boI  QA~"@1q7$M|O&c@H?T}߈ \M>w 'IoI?  QA~"@16>w 'II?  QA~"@0>W 'II?  QA~"@0O>W 'F$kw6?EGl ?^$MFo6H{ f{w@rH}߈ii$z<(C+,1A6Fo1#y/"fmvٞ7OI^i5 %ђU-{\aӞ?}GYH7:9-mw؋$q =mj>KNRȽh[i Z_OA^223:ϴ(0J3 %$ٵaU%S5YiWi[c(.Jsx-4u4c)Ҁ ,e2'?u-;Exaݣ( q*A듘('gcٵ[Kq,B02)ێ2E=|i+'.AiKYN.1MRA+?mu7NaJL]߻GbcZXu8obtɆč"*.9@i6SώiLyLd+`A$mv&k&HZrp{? se-.$qezm]G]ec$N6OnIo+ /9q\㳗Ol,*8r gW>N[O=ig :sצюh l˩t9 ndc%UXA~oO%Sƅ{p/0fPI u^듹'[gK $V]'PUU$/|u/)dh1^13Fivcniwd#\hH _k#(e;A?0cSY\Ypňop'$s}"&i4[4`t(WiR택p?*LjtZlom;f٦ t gǧZz]|Ko?gkyD }8jk_iSK dͲK4 #e_;`^C.qT\jvzA8iÔ$%BQ/'{y7{/dx(KN3k@隋 wԳp9pl,*IkZZ;y˽o$k;Qr>RҼ7>IObmeJ͸ (Lh$w1wN`0rwcGw t^iaWg0,E1ު[xŴ{ 2;#beDp8fۑkmucԖm%df>['*x#~]尊Zh63Q^tPmp ZJd̃2mFzkreܖ9%LnlH,=5E<5:x@__k>pGFیms+b Qnp9NVWQE!Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@'X_O^_![v?2J UϤ5v\FIZ/Cmxq,<0}?LG _0|}#CwdmrͰ px9q)ƕ{Wn1}|Ʃ>uA{7^- AGh\ΣO4i5=W_`tb\ΡO4EgP4; 0Qet1}|"?3Sk?)ƍ;>bӿn3|#?3S)ƍ;ffuA7^# AGh\֣O4h-Onͺ67nG=sZ? AGh5=67n۟ 0H j?G$z A{wmo?ٷ?`u?)ƏH j?Fٷ_`tff׈GkQ?#?5SffuA7^# AGh\֣O4huA7Gmo?x$z =sZ?ѧ` _0?1}|#?3S)ƍ;gb _0OH ?G$zu N_`7_`u)ƏH ?FSھuA7Gn1}|#?3S)ƍ;}n]^׊GgQ?#?3Sv Oj7Gcn417^% AGh\ΣO4i5=67nۯ 0H j?G$z Nۯ 0?n3|#?5S)ƍSۿn3|͹\֣O4GkQ4ffuA7^% AGh\֣O4i5=67n _0/H j?G$z Nٷ_`tff׉GkQ?#?5Svfft _0/H j?G$zu Nat?1}|>uA{7^+ AGh\ΣO4iZ+ 0O^׋EgP?"?3Svn`uk?)ƏH FS>wA{7I[ 0H G$Zu N+gt/}|Aܟ0/H K AGhӰj{wmo?ٷ?`u?)ƏH j?Fٷ?`tff׈GkQ?#?5SffsA7^# AGh\֣O4hsA7Gmo?x$z =sZ?ѧ`ç_0]0H ?G$Zu Nc?x$Zu -s:?ѧ`^nW-s:? AChӰ=W_`t}nW-s:? AChӰ=W_`t}nW=s:? AGhӰ=7_`t}nW=s:? AGhӰ=_`t}nS=s:? AGhӰ=_`t}nS=s:? AGhӰj{_.1}|/?x$zu =s:?ѧ`]b _0OH ?G$zu Nq\ 滸QO7` RqWҼ\" -fǰ-5ŭSƩ{42:%òB G*/T`I endstream endobj 94 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|=MKMZmO>86C*A$rHIhJq^5σO[襥O9V03{ MB9J+94:RGCdnSUOwqh˗6"1hJ2(7M5f/ L945M`h>kipEf,d+ܜc2BqAm5$ p>n JIkoj_sOmOE7?_MfxVKN[Îa}^pa ^:Gr,&t .XN'Z_MM>G>?/&11ݼ_m40G>c @'q6[q ȟltWRrG?LU6oaE7gq¾?/iPM &p>|J$9Br`u1S|67"+4 ?0vm<9VfP@:G j>Ј #"kOOt^7Mc V%IK~(m+i0^$ƩcK;4;;t24YW=Wd+"(SFfGqWugLǙ7G$*|Eny/˝ nú @E-?7t=jZzeȊ;{s  RnR94D^ȶH̡3}HSn i]u5:43ID¨eqJnd'z*ۡi#!k Ew#s >8XޖV7qjZj7r[.3] %ޟwݪ!- 0\J_KDСoZ3|>F[vҙ2&Oj]v免v<ʂ\1aAe#1OHQy ,*s3j#\[N^Ck]ItEokޥ=ԑtQD_:+CtsO}x1]JT 4'B:#H彬cgk؇z+Gд|!k7PдȁM$>&5i+?hCu s3Ae؈dpwʎ*(cdέuyQp8^ i馛sm'tEnţhC3֛iJ8S,e}]m8mBO6L@F+͜R[h&\O3Kmh#"jQP)>Sc9sDѓ84A[&停RJ1%)w+âht-#!jGtD ǰs3 :GE;EAZ@|?Mn0Ozc9s҄big5m('A?&_6H+h mSiI'5bs4h:_MHrx{B'H@GEֈP)٣v3e740 #"jдv@#5"Z)ZGCֿTv"G*ϹɧhzG jHt&ZINzQʻ3VDЛtq{@?/&sKv3F<5214ׇGE֌rdSQʻ39tM @?/&i[[5 Y\6?/&MB'@:GE֊[ s2s@#@GE]Kú FWBҔQ 8^?U-ar:c+(߆ _M8xgebk PKrfXc>04׈?=fbӹ|36ߟ{AHY\Dp<$ƪ!..eY@KB;.'#jatG=p31Q$F,i;+;UPCc*z0iHТ+Y ڲ [#1V%ۈm].=cq,|nօ>=A4|h^O38y2Yi/-ز*7G\j_j\X`p Џ41[iCk,~t;m4guin6~,ڞ?nhzzV4R4?h6ыAѩ3MuF)&ߕhFb r#X۶ʂ\uugh/H\^pFvk |Q==O?¢UړFBTԴM R!}Tw[:p"*30|lGnU?!:=xֳ:VtȠ1pC1(\/miNcr&v'q javj? 㴒pʷDKKvvʷf R1f3p1+xj[egl-Vh ecã)32}kC}}Ai|G7v_sn ca K#y"I)r:*q1ƒg\x;óꖺҬỷ7l6HXeܞ[w\/QM}}Aj {UCb9˾B^6,X;iڟFfjqF.M(9- el*08zo?^@;E=ı<̪r; `14+PEɿESre\8o}}AiG}}AiH$fBKտVvpaT~V@{ӄZ/?=Ò]fyWyW{HIv4/@;G@;GpaqI""HN"+0;O ~?}}Ah<*SGv{H$uDVvn@{;GpasQZ}Z}@k;F_P9i O֣kTo }}Ah}@k;G->iv#ԛԻo }}Ah}@k;G->iTۈ_ы_pڸْ'qsM,i6l=0?4~}}Ah05!?m~}}AhF\yT7vzo?>9+.ESMR-A}}AhpbH^ }@{;Fp\<4=}}AhqK梹n!)G w㴞U?'(?b B=^ʼn?\L*U/?;={@W_lwҰ>c ؿjQSW`ݿD-oh{W?_Qbk_vvM@KҼ{ȿ/mB<  0}#Cb y׿uo;Q*t͡Zs7`B_D!a?t>uo;K^bcJ/[M1?|vv:ݿQ[1 N2N1)IcUrK1s|aa`Ѳ׵tm糹i1J7/\u#}FZZ*6+s[o' '!0 7Z(cp9ʁe?mL*{.k}:mp쌘>dF~2*B_ ׌WPh߸eFYgˆFp8+H8ޓqktl´VtIk#DcQ˯A*on*fƏO #ɱ](wnœ{=?CfӼ'y~7q;稫2K̆?cwv9"z+mr]?كz}֤+Nw6eʲw0} hpzzW%6=#^PiK0vڔI# 䞫q\WH^gT%bqn d)8b!g?t)I,u$UM۲ck[Vͥ&i/,Fזt8?#˃t knBHcGWC,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣ\\+`8ϩ\U oEZ#KVw[X\²#r܌І UR% ne7].΀³nǜ~xJdp fT|w0+:PSJrrpŦܒ G]6?'7Wwnt;|˯?)p}ƤcҲqmKpDr~&0ŀ/OR5)fU@&PnХ];[^decf.K{aqGJ.K+I2ydu)gvo ?\-kf*=v1ZEs&9T:֓8$r!R+ثu+.pBK;pOE$[h7dI.Rn\FzgPM6svQ<ԙASC[Ӵv# ̪(m'y2NpjM4Rimٿ&_*6kMp~!o6j Z6<ʼSV5vEș]rԷv$c2uf ?ԊtiͦnŃ>vzz_69( -<Ue}V$#$5 ,i  `y~m`~5ڞ}uDGUY[B0nGSj^Ț׍4+۾M:龝YMцURd6C*@o\C"*<,Whl2qUi5τʲ|۝Y+kVӠ8~1 ]k 8N)1x p$ݪUqrk`"[mQeQ H<FTQ]VVַKiy]wz[N륏v϶e⩏igǢ1fXA1.j7e *v @C򠹙dw.KsiҴV2H"^N++R#ZLUmO^>: I`)Y cs\{__8 u },/ GbqLo4=_pyY>}ea, y D#.]VBv@N+ OA%*2 `u?{_٫^Nt=k[#;$>jô/Pj׬zY8kA 'x=c9cs{\b?0qZch|R2zFayZTNm)Cuy[¶427u3VTg*N&8x ME~_͇~NO F`^_i?֍a6dm ;x}GZ[iRȺ,X}G xq]1Wvsj1ol.wFrv+) EJ6 I72V6YjYvsuN3Z,ZhYe[*uߧN(yR؏wG*,b$褂R^4R2ᵅC[Zx< u|zz<H̀q®b96<66vX2pΠ3iKLUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*E¼ v͝wJ- 8#^`Ѳ׵_;x/_ =VIImj<ZPi&K*NA%;o'gpd,z(=L;[!&bVg&YJALQhjQaA_Pe$W]nZ$r;YH#5ί40kwFPؿ Cb xJ.pNFv待khbvE=S779&o&w\u6hjWd*N]c:qĎ?^DM2iy1ò7f*һ-Q<ާm㆛aA_G)NRI>c^.;%FFǡa<h/$cQ Ѱ?/FPؿ…9%dv)amXB$DzUGzO&OO&&OO&Zj|V\czZ~.Flb2Կ4y2Կ4_h?)jkdz +z_&OO&&OO&np/o}#bkuM`yL/ML/M:R]= v:mMqk }5T>L/ML/M9?!]Au]. ^GC}3Guvu}~\ ݸ ?_?7ד'K'G'K'D=raM[ x3_R8Fa6q'9údU!gU~?RI?RI/z\pM(j<ZPi&K*NA?&I' 뼙?_?2"ƊUF-qn\|D>&bEuZRu鷖dJ0˔<uj֯ssW0hL)ǎ+7?1y)<zWn"#o^Fu\ӡf(#(((((((((((((((((((((((((((((((((((((;g^w2 O5_-{^!?ѐW|hOrkE#լZ ?WEݽw%P! +s_KN+agz/sDAAK/OsI'&"=iQYJ!HF@KNQ>0fzō1α.,Dn[G 9hkg,D#uRh)e 5G]~.Fd.+A$^;Ѯ4ǀ'+ ~|q֕,-J SE)e 4ni?<7kb4h'UlApI#rķW62&?-;Y,ePs=8Sy=ܥZ.*KfuۚO,!?Ə'_\@񏊬52YӬat|;,H"F7o !廗%Y14ѕ+_aӫCGsI'yaskdtM=23T Z?kVkƂ˕E,BF]OAEl/Y{jvH"2mL~ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'Jt(ţGC|mI;&FҢmTc/S5âf'Wd}?bNҼUg:ۊy$t!k[Γߥ01 Z?ht1hmHVT1PN:Ry{ GC|> Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥQm~4Lܟl2vd8*z{RXbGۣG?mL%M/URB!ON8ǧZLF?ۣG?mn-<]ld],R1 $iUI’\cp'+ F[8 flpA#PH=A"> Z?ht1hmZy{LQQB35oΓߥc?b[t(@n-}?ǝ'Jf N?xzONյIҸ#AVrT:;dC mHc6vѐWiOjku?FA^'F?e_ =^IuIkEk&ŭ8xUD2j 0\\݉B.R6%M :bQGs㤼9U 3Ks;!f XFI#\JmIa rosj/HсYNxVoĢ;-k{)Ţafxc/.lnMs5C~Q #]?qC3S tBDmԡ{RVfh,ljɠ'lV5]stFvI[}p5C~Q #]?P_WS #gR𾬓_Z <_i-xض䧚UgdfE9[O=,HVR6a@A V,w߱Bb?U7a?\U\@:q,hy-ie+<#h ^8^A #]?5C~Q Ea/~WG,w߱}C0? +dkއF >_ja?{5C~Q #]?P/?0?=Yc(z?b?_ژOEx,w߱G1L'J׾a+ T&Dp.O;YN+&r̓(+NFqڥ?uI-O3I`L*ןjxcVwsZ7=WpE50df\p?OcYU\\\hMZ|Z]YHbrb3,w߱OtFŷ/N66m8ç1NDJs*"dq"\qy-f>-X)w72H <{F ?dkއߗ_ژOvTeb˯Ro=+֟.%DSMF!#2@1JvWG,w߱}Ckr+xKߟ{5C~Q #]?P/ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#aWG,w߱}C0?7F-w'wɨ$T'ԭmRXHY8J89G"kR񹄣V G+S #4/5TdqYj k ݪ,1]$e3ȪD4y pNzs|D`/%b%xPߊ,w۪߱L'  \6$[EI BHo1aJէet];[yJAA Bcr5C~Q #]?WqL'TM;ɦ\,YhJ)͐vQT74T4{ߕII?3Dp F@O,w߱KWFfA[sslڿ- b9 w^7!>~qk"֧8e  TdkއF Q}GIa|Siw.>3M5wi ds]x,w߱K[_/<%?=Yc(z?b?_?L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#aG} тYc*]#W4^9)Q7Lu๥*#-_#ѵ/FA^% O-{v#-z\+~6q?eWu=Yk-N+37޵s֭Um`qUsBu;[+_m2Hzzgߦk;hHZ㓏o}[VRl"a$)ŒֽMBIsǖ*V\[=l<=oKvga$RNzs46ѬT#0ʥb.[b3 MHP+*xKB cPH9%ɯC0Ƶ*iuRJOY{k{MypT.0+d/Kn1 ? Ɉ_&a1WⰿWDn/ĺ&`j1KK|c̛z,-~ݨZy?:Uyۓ |InIy'd/+?b/*0*.mu"xzWTbKjb+yR b1>_c$E]`&KX#i]\ XsB1cq>8.' ڪfg.ݻ1;gzZH~}o즓OcW6H A@*pzOy̽Nq,sQLk Irr1pix3ƒ2[Nx#vy x,+&f,mMެ7xJJW_x97ӣZu7bP{+nin6zX mVl̅@6?zDK)Ju~nO'sJ<r`UK Uao/ FO,>_h-ȏ|/ӛH[47dF*?yxWW`_#ddr𗍢M7)*8u@9=o⮽M9_/FszVp_Ȗ}W99 UJ|{9'F~E⫢5$<-w&73_@nu UcWN]z3B;-&=*;Va83%K!GH91К|G P/*8B8(Þ{g+V>0hxZ2Y whI$aTSx+W<<;ԒNt+UYÕRi?hO7#Q'?Qu꘏s9+ğ Tx?*Qu#v'<U?*Qu#v'<U?*Qu#v<Ux?*Qu#v<Ux?*Qu#zX[X\ y8o;#U5;{Sk \n&$Pu5\0Փ֛}hN%yRʄ(v9# 2hv:s\$>uܦ@6Fxx=}xX..VHxW2W/Bjxsm)nAM":ǵaKu{9'/Ԇm7ZyW+vo ,C7 Kk 4{CLcZwP5ߙ+!i0T>`c15c"9-z=5Rҝ>,Eg%vjvL3춍%ّRz1ȱX]jkj4f5/$rTG#ppx#P Fѝg2J Fw~T}ƶ-0$ꪒz5;|k^pu}޿^Ƅ[Zs!(90rN1q2"JXe$fmk~G'q|W}72[y$YKf/>]=MC+if[^O&P3 GVs_/e8Ɯo1[: Kx A$fLLnlaqǵWuo7F};Nlbp]89n;RmiRKpR$yAqJ45XNV-3XMPBʨ!6G#0Qst>F@#vp#`Le޸5J~*QO<I-ҳ tjҼl pf3Y )IM}ƕU&7_f}Εkoz`h)??(Q1GyG5TzQI- ͹xEjrp$#9oB'_aB7j{m d_@B+\.sI8Si~i8ӪӳwܬMmR,.ݵ|1<@ڠn^"J'{{!e$3l1#Af@  9}ŲJ.^EjH~>lTn^eZQz70;EҞTk4UwZwih۲eI 9Kmq"_F5%4-* 761~cn盥ߟ]۳4(0 /H'lΉNV]:)N]z>2⸵1j&9o鱁pq @_0S =j4,Ϸ2HY8UAҭɤxX$I/ /^I$n???惩i~#ӧk1['щJTdCDҿfzf#-z\+ľ6ߧ5?l>&Kx,?6ZԽZQm`qZO#=軚Ȳ|.H?\Vo_.憆К(%R( RRJ))M%Q@CEJ(4QE%)(4PhPIJi(@ %J(QE%)(4RRJ)(4PIEJ(4QE( Ph(A RRJ)(4PIEJ(4QAC@RPA JSI@T'3V~?h џץG1jku[X髌YjІ=2IIt#5軚[aP4a]+o_.檦Pt4+#@ %P(QE!E%)(4RRJ)(IE(4QE! %R( RZJ))M%(4Q@@ EJ(E% JSI@!PIA J(QE%Ph( RZJ))M%( %P(QE]auR?h ~({\+ľ+{Lp׶Bq !3GKZ/gYmL+ދE/g"Iu#5軚u6^SIX!PIA J(QE! %R(4RPA JSI@%)PIJi( %P(QE!)(I@!PIAIE(4QHh %Ph( RZJ))M%( %PQE)(I@!PIA JSI@T'fuO4Zn?d_??9t%z+,9tOiº]r! ?WQ'Eh: Y EJ(E% JSI@%)(IE(4QHh %R(4RPA JSI@%)(4Q@h@ E (E%RRJ)( JSI@%Pi(E) QI@J) -% J J(QA %RPEJ(]_3Vi?4Iαm^2 /_0_-{w1m^2 /0_-hd3B0OދE/g"Iuo_.抛/AéRRJ)(4Pi(IE(4QI@J) -% J RQE( %P(QE!E%)(4RPh(4Q@h@ E () QI@J))i(4RQE( Ph(EPhPIJi(@)(4Pi(U.IUV?h "ͷz+ľ.Ŧ9t!ͷz+.Ŧ9tN iº?ez/s\VO&I#-軚*lRVFA CKI@%)E(4Ph(@ EPh)(I@!PIA J(QE! %RPA CKI@%)EQ@)(IE(4QHhJ(4RPIJi(4RQE( Ph(EPh)(I@!]_3VT'fCGͷz+.Ŧ9t^%8;\+-L?_-i.̟zVO&I#-軚,B0OmދESeoJ(D4QAC@RPA CKI@%)E(4Q@ %J(QE%)(4RRJ)(4PIEJ( %RPA CKI@J) -% J RQE( Ph(A RRJ))M%Q@CEPi(E) V?UnIⓍR?du/GK^ [׵Ot-hd3,A0_mދE3g" Ito_.抛/@SzVFIJi( %P(QE!)(I@%-%)(4RRJ)(4Pi(E) QI@J) -% J J(QA(4Q@ EJ(E% JSI@%)(IE(4QHhI@J))M%)(4RRJ)(UnIY?_Κߊ)o^2 ??t){\+*wKp֋fO=RD _ ]sVOL+F[w4TzM(5PhE% JSI@%Pi(E(4QAC@RPA JZJ))M%Q@CEJ(4QE%)(4RRJ) -% J J(QA %RPA CKI@%)EQ@CEJ(E) )(I@U'uh[/Mwkxoi:ZZn?d_=8kE3'g$iºIez/s\_ ]6^Sz+#@4Q@h@ EPhPIJi(@%)EQ@CEJ(4QE%)(4RRJ)(IE(4QHh %R( RZJ))M%(4Q@@ EJ(E% JSI@%))M%( %P(Uk/Vj_󦀽o [׭O/[xŏ_-hd3l ?WG7Ek{k`4a]2[pnZJ))M%( %PQE)( %RPA CKI@%)EQ@CEJ(4PhE% JSI@%PIJi( %P(QE!)(I@!PIAIEJ(4QAJ(@ EPhPIJi(@U+uf\_:h ^n?d`?:Zbn?d_a?:Z gY=0o-ދE9g$iº9dz/sEMܢCYRPA CKI@%)E(@%Pi((4QI@J) -% J RQE( Ph(A (4PhE% JSI@%Pi(E) QI@J) -% J J(E(4Ph(@ EPh\_:U+t^#ͷz+ľ-æ9t"ͷz+ľ.Ŧ9tS{m`4a]2[rIItso_.抛/AéIEJ(4QAC@RPA (E% JSI@% %Pi(QE)(I@!PIA J(QEQ@CEJ(4PhE% JSI@%Pi(E) QI@J( RZJ))M%(4Q@h@ U+ubO! +t~"ͷz+.Ŧ9t"ͷz+.Ŧ9tR{k`4a]1nIIto_.抛/AéA4 JSI@%)(4Q@h %P(QE!)(I@!PIAIEJ(4QAJ(4RPHii(I@!PIA J(QE! %R(4RPA JSI@%)(4Q@h %P(QE!)(I@%-% ?_^ҿ/M/ ׭OZgGK^/ ׭OZgGKZ/g>0oދE7g$iº9c]6^SlE4) )(I@%)E% JSI@%Pi(E) QI@J) -% J J(QA(4Ph(@ EPhPIJi(@%Pi(E)(I@!PA JSI@%)(IE(4QHhJ*ҿ/V*ҿ/M/ ׭OZgGK^/ ׭OZgGKZg>0z/s\o w4l%)(IE(4QE! %R(4RPA JSI@%)(4Q@h@ E (E% JSI@!PIAIEJ(4QAJ(4RPHii(4RPh(4Q@ EJ(E)(I@!PIA J(QE!CJXCJ43m^2 ?1i_-{g3m^2 /*-7Wd3Ԭ[ ?WG?prIIts軚U6^SjE%dh JSI@%))M%( %P(QE!E%)(4RRJ)(IE(4QHh %R( RZJ))M%(4Q@@ E (E% JSI@%))M%( %PQE)(I@!PU_:CJ43m^2 /1i_-{o3m^2 /1i_-j7g$iº9c]sOL+F(?ދEҩu6%J(QE%QAJ(4RPHii(4RPh(4Q@h@ E PhPIJi())M%Q@CEJ(4QE%)(PIEJ(4QAC@RPE (E% JSI@% %Pi(QE)(%_:! +t#ͷz+ľ.Ŧ9t#ͷz+ľ.Ŧ9t zo ?b]sOL+w4lMJSIY% %PIAIEJ(4QAJ(4RPHii(4RPh(4Q@h@ EPh) )(I@%)PIEJ(4QAC@RPA JSI@%)(4Q@%Pi(E) QI@J) -% J J(y!_Χ%_:h _fn?d??b?:Zfn?d_a?:Z g>0F(?ދE7f ?WIq#Eh:QIYJ( RZJ))M%(4Q@@ EJ(E% JSI@%)(IERQE( Ph( RZJ))M%( %P(QE!E%)(J(4RPIJi(4RQE( Ph(EPhPPK!+u9$_:h Ofn?d_a?:Zfn?d_a?:Z gٷPviº{z/s\iºz/sENS`QEdh!(4Q@h@ E (E% JSI@% %Pi(QE!)(I@!E% JSI@%)(IEQAJ(4RPHii(4RPh(4Q@h %P(QE!E%)(4RRJ)(IE(4QHhd_:B:WE5|I!oѐW|[Lrk|I!oѐW|[LrkE3'i"EIuw?1A_.YmďIEv7?1A_.抛/@SbVFA JSI@%)(4Q@h@ E (E%RRJ)(IE(4QE %R( RZJ))M%(4Q@@ EJ(E% JSI@!PIA J(QE! %R(4RPA JSI@%)(5ҿ/ST2GJ违4?1m^2 ?0_-{gmѐW|Y$gGKZ?HEwO&\軚m(KSP4a]50sEMCEV&(QE!E%)(4RRJ)(IE(4QHhJ(4RPIKI@%) JSI@%Pi(E) QI@J) -% J J(QA %Ph(@ EPhPIJi(@%Pi(E) )(I@C'tƠ_>lk0 _ivӗGK^߫q!1?eW̟wʾ <aexY5ĔG+~K?9mԏμ(vՆvbGJh`pi3GzdU:zEыx^M'_j?a$*CBOM)6?EGl h|ia$*>c@H?Th)Oc@H?T}߈rϽM{  QA~"@'MnO)>c@H?T}߈jϽMoS} o&6?EGl oS} o&M;6?EGl o} _&>/O  QA~"@{bϽKԟa$*>c@H?Thl_9OMKA~"6?EFE>׿/G^MKA~"6?EFC>׿/Gڇ^MMA~"6?EFA>׿/Gڇ^MOA~"6?EFWPkC}_&}߈  QN׿/Iv9A~"6?EFVO;^M'jl W{r4}_&}߈  Q>N׿/Gjl O?{r4y}o_&}߈  Q>/I9A~"6?EFRM'{r5{6?EGl 7Msϭa$*4{r4y>/Wc@H?T}߈ 5h_}o_&>c@H?T}߈ 1h}/_&~c@H?T}߈ 1i<K/a$*479M>/Za$*>c@H?ThfK'^$Mj}߈  Q{Kt{5A~"6?EFen}/_&ϥK֯l OI3'^$Mk}߈  Q9|_&2ϝKֿl %i3/$Ml}߈  Q;{5A~"6?EFc~|_&M>w /[?a$*>c@H?Th.&;ϝIl $i6>w '[a$*>c@H?Th&ٿ$i6>w '[a$*>c@H?Th$i6O>W '[a$*>c@H?Th$h?^$Mn߈  Q;'+/a,nݎIu"/9--"dGHee A9 FC^+F?eedi5b:^3F?eW̟wֱF|j|iºMGYH7:9-mw؋$yH ͟  %sGs^P-\̧ W쎟Ru>yeFq[iZ&d$6 7ʤx⦱ ->>M9c\L`@BIQsUFtLe:PA%LTdGh6W2ܻwP"@=rsjO BWkIfY#40`2dR mͷd zChVO\&ef*\b2*:V t[(o%c”w=jşƵq\ 5DU]s+19灁OOӇ:mƧҙ26*Wc0ʂHxαE(ȴ5dVѕI+78yg!ҼC&zC,GɒG2}=rM;-/7My{zdl=tzK>;hO-$f8urU4SoN6,giШDzNJ/%ׅuK$X'Ԡ{U(Uhe๑㞀- iwz1Q@XRIYUk^ݛ[kQw8Ppc|`qjESs8cEn T޼FkgSZxc* B|@ivMHmgZ]/HByz-ǂHm'/*V@^=r2:ֹ|7g.e1YhUq"@N8i}p{.{u}u'M:ѠS;;/,s:&@J8 --K 30_a̠$@f's2"NΖgHZO3 7@I^.S}X_j6S|ч4b6 1i c+gs=/_$F6-FPv~`8Ǩi1ڸgݙUbw6NH<E-#:M6ivh&itoPҥ;N Uwڵ4w=Lc@'N~G+~%Q)$u-G6Aݜq־0ҦinNdhGPʾv]95='T ?Q qqf+(IJyOS֢_No<^QwGB$g9Ki~75 g(6s$XTsֵa{%v{H`vl|195xn}7W7o~@i &d;q Q5 u Hlcn]Մ`@ AM]oT 8./'1*paE3X#cT}iW@dw+yg6G(ʉ.pͷ#5o뉦ǩ,7K "|NT9m;VG (a=lg ΢39ڽ1GP-ώZ6&3dfPpFk77ZBf,wHLӥF&k﷧Mɺ<9#~m692$vAܖp 8I X<䬇WmּoX\I$F%ЫA߷ñCupR\% EP7?2+7Bk[+:;OGklCDg9-j$ѭeƝmck]&׻6bJmKgo-cqg1u'<6cYsv}W/m%*,s+J}(C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (15v >kž08oieeThO xM_-l2S  Uw*ydt P\iz]isuoA;5_?_oo ūlUQr˹گ'}AƨU(?| bտ6O*KMCTsGC]](?8]_PūlU-[d,Bbj}/(?| b6O*KMCTsGG.)AƨAK5_<_o ūlUPs}To?/7 ZQ b6O*h(r˹> _P7RW-_d1j'G49e}/(?)AƫKMCT_o ?}jU%&W??/7 ZQYw>}AK5F _PūlU-_d,C̾?/7 ZQ b6O*h(e̾o)AƫKMCT_o ?} _NRyU%&V??/7 ZQYw>'AƨE(?| bտ6O*KMCTsGC]ϠA;5G/'AƫKMCT_oo ?} PONW-[d1j'G49e\_PxRW_-[d1j'G49e}/(?)AƫKMCT_o ?>Yw>}AK5F _PūlU-_d]ϡRP^jx1j'G%&W?9sS%Ϳ/7 ZQ b6O*h(eͿͿ/7 ZQ b6O*h(r˹'AK5KRW_-_d1j'G49eͿ3jbj{1j'G%&W?9.&PTi?'AƫKMCT_oo ?{ڵ ~P>רNW_oo ūlUPs߾רJQCWߔjūlUx-[d]~fA+5Go%}Aƫ./ ZQ wbտ6O*h(r˹V[1K5_=]_o ūlUPs}To?/7 ZQ b6O*h(e}/(?)|ƫKMCT_o ?}jU%&W??/7 ZQ,C}/(?| b6O*KMCTsGC]ϡZ[1;5Q1;5_?_o ūlUQr˹kwU-[d1j'G49ejT}P1j'G%&V?9.PVA;5_?_oo ūlUPsjTi/7 ZQ bտ6O*h(r˹u ~P>ӨNW-[d1j'G49e(?//'AƫKMCT_oo ?} P>A;5_>_oo ūlUPs/>wj>wj}1j'G%&V?9.^}(?}(?| bտ6O*KMCTsGC]${BTEzxi&> stream xko6~,-DĎkiR']`֖׋ګ4? %^Gl\S82g83Λ9z*뒽~},w :,]~[G|1-v*n`6I&2MÃ`à -ћю/~,yy{x XVr=~K%=$l?".><8B,՜eS#V #ug ki<ɢ~aM0} QYxqG~S46AJRIn* W%5\Sh>=Ld 6,66E m]%Y=JDk- ĦGj:hB2J`/`68^TS8{֡? nʽA$B?8")_R@ w%u Vg7I^b}XsŗPݫtDg^SoƎa:ˁٻ}*vt5‡w,9e(_LΎ(x~`/%I o>oxv؀gJE/y?]+TgH .oGN32Zw p<=}ԌjҩġtZg5j+No!zvL\#^G2 ךe"mD]fo1|iSt†|\y6&v !CVW՛'h5g]X//}F#iBоA9Ua|\FvSpZ9\eok?ְ z iUrPFzH}ȵ D#5h߲xbLc_]MPos,`D/Uia,^U;Z` Xe<%ֈXhv d(Vs#^ʢ̧Go%hWh.*߾\Yΐ9:bԘf X%u3>q-&n2T@z%}΂{ 6kP{w' _Hh2,4@l@`r R+mG[(ߘn$ X =3''cQ"e?nBQ6,TjH,zL_U`*hoF7v;P:B-1z㽒=%ޫ~|ӷVL@} fl^Ww~g.Lp<] #tnQp_$^4ۖrZ_C| e|Lm2S)  AUgʐ+.jڌH%=7+`sP5^iYɯ16͢fhUl٬|{x5^RM a{Wa%-d^vq}}Ru{p:iGB[- 1 ;G> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?|=MKMZmO>86C*A$rHIhJq^5σO[襥O9V03{ MB9J+94:RGCdnSUOwqh˗6"1hJ2(7M5f/ L945M`h>kipEf,d+ܜc2BqAm5$ p>n JIkoj_sOmOE7?_MfxVKN[Îa}^pa ^:Gr,&t .XN'Z_MM>G>?/&11ݼ_m40G>c @'q6[q ȟltWRrG?LU6oaE7gq¾?/iPM &p>|J$9Br`u1S|67"+4 ?0vm<9VfP@:G j>Ј #"kOOt^7Mc V%IK~(m+i0^$ƩcK;4;;t24YW=Wd+"(SFfGqWugLǙ7G$*|Eny/˝ nú @E-?7t=jZzeȊ;{s  RnR94D^ȶH̡3}HSn i]u5:43ID¨eqJnd'z*ۡi#!k Ew#s >8XޖV7qjZj7r[.3] %ޟwݪ!- 0\J_KDСoZ3|>F[vҙ2&Oj]v免v<ʂ\1aAe#1OHQy ,*s3j#\[N^Ck]ItEokޥ=ԑtQD_:+CtsO}x1]JT 4'B:#H彬cgk؇z+Gд|!k7PдȁM$>&5i+?hCu s3Ae؈dpwʎ*(cdέuyQp8^ i馛sm'tEnţhC3֛iJ8S,e}]m8mBO6L@F+͜R[h&\O3Kmh#"jQP)>Sc9sDѓ84A[&停RJ1%)w+âht-#!jGtD ǰs3 :GE;EAZ@|?Mn0Ozc9s҄big5m('A?&_6H+h mSiI'5bs4h:_MHrx{B'H@GEֈP)٣v3e740 #"jдv@#5"Z)ZGCֿTv"G*ϹɧhzG jHt&ZINzQʻ3VDЛtq{@?/&sKv3F<5214ׇGE֌rdSQʻ39tM @?/&i[[5 Y\6?/&MB'@:GE֊[ s2s@#@GE]Kú FWBҔQ 8^?U-ar:c+(߆ _M8xgebk PKrfXc>04׈?=fbӹ|36ߟ{AHY\Dp<$ƪ!..eY@KB;.'#jatG=p31Q$F,i;+;UPCc*z0iHТ+Y ڲ [#1V%ۈm].=cq,|nօ>=A4|h^O38y2Yi/-ز*7G\j_j\X`p Џ41[iCk,~t;m4guin6~,ڞ?nhzzV4R4?h6ыAѩ3MuF)&ߕhFb r#X۶ʂ\uugh/H\^pFvk |Q==O?¢UړFBTԴM R!}Tw[:p"*30|lGnU?!:=xֳ:VtȠ1pC1(\/miNcr&v'q javj? 㴒pʷDKKvvʷf R1f3p1+xj[egl-Vh ecã)32}kC}}Ai|G7v_sn ca K#y"I)r:*q1ƒg\x;óꖺҬỷ7l6HXeܞ[w\/QM}}Aj {UCb9˾B^6,X;iڟFfjqF.M(9- el*08zo?^@;E=ı<̪r; `14+PEɿESre\8o}}AiG}}AiH$fBKտVvpaT~V@{ӄZ/?=Ò]fyWyW{HIv4/@;G@;GpaqI""HN"+0;O ~?}}Ah<*SGv{H$uDVvn@{;GpasQZ}Z}@k;F_P9i O֣kTo }}Ah}@k;G->iv#ԛԻo }}Ah}@k;G->iTۈ_ы_pڸْ'qsM,i6l=0?4~}}Ah05!?m~}}AhF\yT7vzo?>9+.ESMR-A}}AhpbH^ }@{;Fp\<4=}}AhqK梹n!)G w㴞U?'(?b B=^ʼn?\L*U/?;={@W_lwҰ>c ؿjQSW`ݿD-oh{W?_Qbk_vvM@KҼ{ȿ/mB<  0}#Cb y׿uo;Q*t͡Zs7`B_D!a?t>uo;K^bcJ/[M1?|vv:ݿQ[1 N2N1)IcUrK1s|aa`Ѳ׵tm糹i1J7/\u#}FZZ*6+s[o' '!0 7Z(cp9ʁe?mL*{.k}:mp쌘>dF~2*B_ ׌WPh߸eFYgˆFp8+H8ޓqktl´VtIk#DcQ˯A*on*fƏO #ɱ](wnœ{=?CfӼ'y~7q;稫2K̆?cwv9"z+mr]?كz}֤+Nw6eʲw0} hpzzW%6=#^PiK0vڔI# 䞫q\WH^gT%bqn d)8b!g?t)I,u$UM۲ck[Vͥ&i/,Fזt8?#˃t knBHcGWC,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣ\\+`8ϩ\U oEZ#KVw[X\²#r܌І UR% ne7].΀³nǜ~xJdp fT|w0+:PSJrrpŦܒ G]6?'7Wwnt;|˯?)p}ƤcҲqmKpDr~&0ŀ/OR5)fU@&PnХ];[^decf.K{aqGJ.K+I2ydu)gvo ?\-kf*=v1ZEs&9T:֓8$r!R+ثu+.pBK;pOE$[h7dI.Rn\FzgPM6svQ<ԙASC[Ӵv# ̪(m'y2NpjM4Rimٿ&_*6kMp~!o6j Z6<ʼSV5vEș]rԷv$c2uf ?ԊtiͦnŃ>vzz_69( -<Ue}V$#$5 ,i  `y~m`~5ڞ}uDGUY[B0nGSj^Ț׍4+۾M:龝YMцURd6C*@o\C"*<,Whl2qUi5τʲ|۝Y+kVӠ8~1 ]k 8N)1x p$ݪUqrk`"[mQeQ H<FTQ]VVַKiy]wz[N륏v϶e⩏igǢ1fXA1.j7e *v @C򠹙dw.KsiҴV2H"^N++R#ZLUmO^>: I`)Y cs\{__8 u },/ GbqLo4=_pyY>}ea, y D#.]VBv@N+ OA%*2 `u?{_٫^Nt=k[#;$>jô/Pj׬zY8kA 'x=c9cs{\b?0qZch|R2zFayZTNm)Cuy[¶427u3VTg*N&8x ME~_͇~NO F`^_i?֍a6dm ;x}GZ[iRȺ,X}G xq]1Wvsj1ol.wFrv+) EJ6 I72V6YjYvsuN3Z,ZhYe[*uߧN(yR؏wG*,b$褂R^4R2ᵅC[Zx< u|zz<H̀q®b96<66vX2pΠ3iKLUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*E¼ v͝wJ- 8#^`Ѳ׵_;x/_ =VIImj<ZPi&K*NA%;o'gpd,z(=L;[!&bVg&YJALQhjQaA_Pe$W]nZ$r;YH#5ί40kwFPؿ Cb xJ.pNFv待khbvE=S779&o&w\u6hjWd*N]c:qĎ?^DM2iy1ò7f*һ-Q<ާm㆛aA_G)NRI>c^.;%FFǡa<h/$cQ Ѱ?/FPؿ…9%dv)amXB$DzUGzO&OO&&OO&Zj|V\czZ~.Flb2Կ4y2Կ4_h?)jkdz +z_&OO&&OO&np/o}#bkuM`yL/ML/M:R]= v:mMqk }5T>L/ML/M9?!]Au]. ^GC}3Guvu}~\ ݸ ?_?7ד'K'G'K'D=raM[ x3_R8Fa6q'9údU!gU~?RI?RI/z\pM(j<ZPi&K*NA?&I' 뼙?_?2"ƊUF-qn\|D>&bEuZRu鷖dJ0˔<uj֯ssW0hL)ǎ+7?1y)<zWn"#o^Fu\ӡf(#(((((((((((((((((((((((((((((((((((((;g^w2 O5_-{^!?ѐW|hOrkE#լZ ?WEݽw%P! +s_KN+agz/sDAAK/OsI'&"=iQYJ!HF@KNQ>0fzō1α.,Dn[G 9hkg,D#uRh)e 5G]~.Fd.+A$^;Ѯ4ǀ'+ ~|q֕,-J SE)e 4ni?<7kb4h'UlApI#rķW62&?-;Y,ePs=8Sy=ܥZ.*KfuۚO,!?Ə'_\@񏊬52YӬat|;,H"F7o !廗%Y14ѕ+_aӫCGsI'yaskdtM=23T Z?kVkƂ˕E,BF]OAEl/Y{jvH"2mL~ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'Jt(ţGC|mI;&FҢmTc/S5âf'Wd}?bNҼUg:ۊy$t!k[Γߥ01 Z?ht1hmHVT1PN:Ry{ GC|> Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥQm~4Lܟl2vd8*z{RXbGۣG?mL%M/URB!ON8ǧZLF?ۣG?mn-<]ld],R1 $iUI’\cp'+ F[8 flpA#PH=A"> Z?ht1hmZy{LQQB35oΓߥc?b[t(@n-}?ǝ'Jf N?xzONյIҸ#AVrT:;dC mHc6vѐWiOjku?FA^'F?e_ =^IuIkEk&ŭ8xUD2j 0\\݉B.R6%M :bQGs㤼9U 3Ks;!f XFI#\JmIa rosj/HсYNxVoĢ;-k{)Ţafxc/.lnMs5C~Q #]?qC3S tBDmԡ{RVfh,ljɠ'lV5]stFvI[}p5C~Q #]?P_WS #gR𾬓_Z <_i-xض䧚UgdfE9[O=,HVR6a@A V,w߱Bb?U7a?\U\@:q,hy-ie+<#h ^8^A #]?5C~Q Ea/~WG,w߱}C0? +dkއF >_ja?{5C~Q #]?P/?0?=Yc(z?b?_ژOEx,w߱G1L'J׾a+ T&Dp.O;YN+&r̓(+NFqڥ?uI-O3I`L*ןjxcVwsZ7=WpE50df\p?OcYU\\\hMZ|Z]YHbrb3,w߱OtFŷ/N66m8ç1NDJs*"dq"\qy-f>-X)w72H <{F ?dkއߗ_ژOvTeb˯Ro=+֟.%DSMF!#2@1JvWG,w߱}Ckr+xKߟ{5C~Q #]?P/ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#aWG,w߱}C0?7F-w'wɨ$T'ԭmRXHY8J89G"kR񹄣V G+S #4/5TdqYj k ݪ,1]$e3ȪD4y pNzs|D`/%b%xPߊ,w۪߱L'  \6$[EI BHo1aJէet];[yJAA Bcr5C~Q #]?WqL'TM;ɦ\,YhJ)͐vQT74T4{ߕII?3Dp F@O,w߱KWFfA[sslڿ- b9 w^7!>~qk"֧8e  TdkއF Q}GIa|Siw.>3M5wi ds]x,w߱K[_/<%?=Yc(z?b?_?L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#aG} тYc*]#W4^9)Q7Lu๥*#-_#ѵ/FA^% O-{v#-z\+~6q?eWu=Yk-N+37޵s֭Um`qUsBu;[+_m2Hzzgߦk;hHZ㓏o}[VRl"a$)ŒֽMBIsǖ*V\[=l<=oKvga$RNzs46ѬT#0ʥb.[b3 MHP+*xKB cPH9%ɯC0Ƶ*iuRJOY{k{MypT.0+d/Kn1 ? Ɉ_&a1WⰿWDn/ĺ&`j1KK|c̛z,-~ݨZy?:Uyۓ |InIy'd/+?b/*0*.mu"xzWTbKjb+yR b1>_c$E]`&KX#i]\ XsB1cq>8.' ڪfg.ݻ1;gzZH~}o즓OcW6H A@*pzOy̽Nq,sQLk Irr1pix3ƒ2[Nx#vy x,+&f,mMެ7xJJW_x97ӣZu7bP{+nin6zX mVl̅@6?zDK)Ju~nO'sJ<r`UK Uao/ FO,>_h-ȏ|/ӛH[47dF*?yxWW`_#ddr𗍢M7)*8u@9=o⮽M9_/FszVp_Ȗ}W99 UJ|{9'F~E⫢5$<-w&73_@nu UcWN]z3B;-&=*;Va83%K!GH91К|G P/*8B8(Þ{g+V>0hxZ2Y whI$aTSx+W<<;ԒNt+UYÕRi?hO7#Q'?Qu꘏s9+ğ Tx?*Qu#v'<U?*Qu#v'<U?*Qu#v<Ux?*Qu#v<Ux?*Qu#zX[X\ y8o;#U5;{Sk \n&$Pu5\0Փ֛}hN%yRʄ(v9# 2hv:s\$>uܦ@6Fxx=}xX..VHxW2W/Bjxsm)nAM":ǵaKu{9'/Ԇm7ZyW+vo ,C7 Kk 4{CLcZwP5ߙ+!i0T>`c15c"9-z=5Rҝ>,Eg%vjvL3춍%ّRz1ȱX]jkj4f5/$rTG#ppx#P Fѝg2J Fw~T}ƶ-0$ꪒz5;|k^pu}޿^Ƅ[Zs!(90rN1q2"JXe$fmk~G'q|W}72[y$YKf/>]=MC+if[^O&P3 GVs_/e8Ɯo1[: Kx A$fLLnlaqǵWuo7F};Nlbp]89n;RmiRKpR$yAqJ45XNV-3XMPBʨ!6G#0Qst>F@#vp#`Le޸5J~*QO<I-ҳ tjҼl pf3Y )IM}ƕU&7_f}Εkoz`h)??(Q1GyG5TzQI- ͹xEjrp$#9oB'_aB7j{m d_@B+\.sI8Si~i8ӪӳwܬMmR,.ݵ|1<@ڠn^"J'{{!e$3l1#Af@  9}ŲJ.^EjH~>lTn^eZQz70;EҞTk4UwZwih۲eI 9Kmq"_F5%4-* 761~cn盥ߟ]۳4(0 /H'lΉNV]:)N]z>2⸵1j&9o鱁pq @_0S =j4,Ϸ2HY8UAҭɤxX$I/ /^I$n???惩i~#ӧk1['щJTdCDҿfzf#-z\+ľ6ߧ5?l>&Kx,?6ZԽZQm`qZO#=軚Ȳ|.H?\Vo_.憆К(%R( RRJ))M%Q@CEJ(4QE%)(4PhPIJi(@ %J(QE%)(4RRJ)(4PIEJ(4QE( Ph(A RRJ)(4PIEJ(4QAC@RPA JSI@T'3V~?h џץG1jku[X髌YjІ=2IIt#5軚[aP4a]+o_.檦Pt4+#@ %P(QE!E%)(4RRJ)(IE(4QE! %R( RZJ))M%(4Q@@ EJ(E% JSI@!PIA J(QE%Ph( RZJ))M%( %P(QE]auR?h ~({\+ľ+{Lp׶Bq !3GKZ/gYmL+ދE/g"Iu#5軚u6^SIX!PIA J(QE! %R(4RPA JSI@%)PIJi( %P(QE!)(I@!PIAIE(4QHh %Ph( RZJ))M%( %PQE)(I@!PIA JSI@T'fuO4Zn?d_??9t%z+,9tOiº]r! ?WQ'Eh: Y EJ(E% JSI@%)(IE(4QHh %R(4RPA JSI@%)(4Q@h@ E (E%RRJ)( JSI@%Pi(E) QI@J) -% J J(QA %RPEJ(]_3Vi?4Iαm^2 /_0_-{w1m^2 /0_-hd3B0OދE/g"Iuo_.抛/AéRRJ)(4Pi(IE(4QI@J) -% J RQE( %P(QE!E%)(4RPh(4Q@h@ E () QI@J))i(4RQE( Ph(EPhPIJi(@)(4Pi(U.IUV?h "ͷz+ľ.Ŧ9t!ͷz+.Ŧ9tN iº?ez/s\VO&I#-軚*lRVFA CKI@%)E(4Ph(@ EPh)(I@!PIA J(QE! %RPA CKI@%)EQ@)(IE(4QHhJ(4RPIJi(4RQE( Ph(EPh)(I@!]_3VT'fCGͷz+.Ŧ9t^%8;\+-L?_-i.̟zVO&I#-軚,B0OmދESeoJ(D4QAC@RPA CKI@%)E(4Q@ %J(QE%)(4RRJ)(4PIEJ( %RPA CKI@J) -% J RQE( Ph(A RRJ))M%Q@CEPi(E) V?UnIⓍR?du/GK^ [׵Ot-hd3,A0_mދE3g" Ito_.抛/@SzVFIJi( %P(QE!)(I@%-%)(4RRJ)(4Pi(E) QI@J) -% J J(QA(4Q@ EJ(E% JSI@%)(IE(4QHhI@J))M%)(4RRJ)(UnIY?_Κߊ)o^2 ??t){\+*wKp֋fO=RD _ ]sVOL+F[w4TzM(5PhE% JSI@%Pi(E(4QAC@RPA JZJ))M%Q@CEJ(4QE%)(4RRJ) -% J J(QA %RPA CKI@%)EQ@CEJ(E) )(I@U'uh[/Mwkxoi:ZZn?d_=8kE3'g$iºIez/s\_ ]6^Sz+#@4Q@h@ EPhPIJi(@%)EQ@CEJ(4QE%)(4RRJ)(IE(4QHh %R( RZJ))M%(4Q@@ EJ(E% JSI@%))M%( %P(Uk/Vj_󦀽o [׭O/[xŏ_-hd3l ?WG7Ek{k`4a]2[pnZJ))M%( %PQE)( %RPA CKI@%)EQ@CEJ(4PhE% JSI@%PIJi( %P(QE!)(I@!PIAIEJ(4QAJ(@ EPhPIJi(@U+uf\_:h ^n?d`?:Zbn?d_a?:Z gY=0o-ދE9g$iº9dz/sEMܢCYRPA CKI@%)E(@%Pi((4QI@J) -% J RQE( Ph(A (4PhE% JSI@%Pi(E) QI@J) -% J J(E(4Ph(@ EPh\_:U+t^#ͷz+ľ-æ9t"ͷz+ľ.Ŧ9tS{m`4a]2[rIItso_.抛/AéIEJ(4QAC@RPA (E% JSI@% %Pi(QE)(I@!PIA J(QEQ@CEJ(4PhE% JSI@%Pi(E) QI@J( RZJ))M%(4Q@h@ U+ubO! +t~"ͷz+.Ŧ9t"ͷz+.Ŧ9tR{k`4a]1nIIto_.抛/AéA4 JSI@%)(4Q@h %P(QE!)(I@!PIAIEJ(4QAJ(4RPHii(I@!PIA J(QE! %R(4RPA JSI@%)(4Q@h %P(QE!)(I@%-% ?_^ҿ/M/ ׭OZgGK^/ ׭OZgGKZ/g>0oދE7g$iº9c]6^SlE4) )(I@%)E% JSI@%Pi(E) QI@J) -% J J(QA(4Ph(@ EPhPIJi(@%Pi(E)(I@!PA JSI@%)(IE(4QHhJ*ҿ/V*ҿ/M/ ׭OZgGK^/ ׭OZgGKZg>0z/s\o w4l%)(IE(4QE! %R(4RPA JSI@%)(4Q@h@ E (E% JSI@!PIAIEJ(4QAJ(4RPHii(4RPh(4Q@ EJ(E)(I@!PIA J(QE!CJXCJ43m^2 ?1i_-{g3m^2 /*-7Wd3Ԭ[ ?WG?prIIts軚U6^SjE%dh JSI@%))M%( %P(QE!E%)(4RRJ)(IE(4QHh %R( RZJ))M%(4Q@@ E (E% JSI@%))M%( %PQE)(I@!PU_:CJ43m^2 /1i_-{o3m^2 /1i_-j7g$iº9c]sOL+F(?ދEҩu6%J(QE%QAJ(4RPHii(4RPh(4Q@h@ E PhPIJi())M%Q@CEJ(4QE%)(PIEJ(4QAC@RPE (E% JSI@% %Pi(QE)(%_:! +t#ͷz+ľ.Ŧ9t#ͷz+ľ.Ŧ9t zo ?b]sOL+w4lMJSIY% %PIAIEJ(4QAJ(4RPHii(4RPh(4Q@h@ EPh) )(I@%)PIEJ(4QAC@RPA JSI@%)(4Q@%Pi(E) QI@J) -% J J(y!_Χ%_:h _fn?d??b?:Zfn?d_a?:Z g>0F(?ދE7f ?WIq#Eh:QIYJ( RZJ))M%(4Q@@ EJ(E% JSI@%)(IERQE( Ph( RZJ))M%( %P(QE!E%)(J(4RPIJi(4RQE( Ph(EPhPPK!+u9$_:h Ofn?d_a?:Zfn?d_a?:Z gٷPviº{z/s\iºz/sENS`QEdh!(4Q@h@ E (E% JSI@% %Pi(QE!)(I@!E% JSI@%)(IEQAJ(4RPHii(4RPh(4Q@h %P(QE!E%)(4RRJ)(IE(4QHhd_:B:WE5|I!oѐW|[Lrk|I!oѐW|[LrkE3'i"EIuw?1A_.YmďIEv7?1A_.抛/@SbVFA JSI@%)(4Q@h@ E (E%RRJ)(IE(4QE %R( RZJ))M%(4Q@@ EJ(E% JSI@!PIA J(QE! %R(4RPA JSI@%)(5ҿ/ST2GJ违4?1m^2 ?0_-{gmѐW|Y$gGKZ?HEwO&\軚m(KSP4a]50sEMCEV&(QE!E%)(4RRJ)(IE(4QHhJ(4RPIKI@%) JSI@%Pi(E) QI@J) -% J J(QA %Ph(@ EPhPIJi(@%Pi(E) )(I@C'tƠ_>lk0 _ivӗGK^߫q!1?eW̟wʾ <aexY5ĔG+~K?9mԏμ(vՆvbGJh`pi3GzdU:zEыx^M'_j?a$*CBOM)6?EGl h|ia$*>c@H?Th)Oc@H?T}߈rϽM{  QA~"@'MnO)>c@H?T}߈jϽMoS} o&6?EGl oS} o&M;6?EGl o} _&>/O  QA~"@{bϽKԟa$*>c@H?Thl_9OMKA~"6?EFE>׿/G^MKA~"6?EFC>׿/Gڇ^MMA~"6?EFA>׿/Gڇ^MOA~"6?EFWPkC}_&}߈  QN׿/Iv9A~"6?EFVO;^M'jl W{r4}_&}߈  Q>N׿/Gjl O?{r4y}o_&}߈  Q>/I9A~"6?EFRM'{r5{6?EGl 7Msϭa$*4{r4y>/Wc@H?T}߈ 5h_}o_&>c@H?T}߈ 1h}/_&~c@H?T}߈ 1i<K/a$*479M>/Za$*>c@H?ThfK'^$Mj}߈  Q{Kt{5A~"6?EFen}/_&ϥK֯l OI3'^$Mk}߈  Q9|_&2ϝKֿl %i3/$Ml}߈  Q;{5A~"6?EFc~|_&M>w /[?a$*>c@H?Th.&;ϝIl $i6>w '[a$*>c@H?Th&ٿ$i6>w '[a$*>c@H?Th$i6O>W '[a$*>c@H?Th$h?^$Mn߈  Q;'+/a,nݎIu"/9--"dGHee A9 FC^+F?eedi5b:^3F?eW̟wֱF|j|iºMGYH7:9-mw؋$yH ͟  %sGs^P-\̧ W쎟Ru>yeFq[iZ&d$6 7ʤx⦱ ->>M9c\L`@BIQsUFtLe:PA%LTdGh6W2ܻwP"@=rsjO BWkIfY#40`2dR mͷd zChVO\&ef*\b2*:V t[(o%c”w=jşƵq\ 5DU]s+19灁OOӇ:mƧҙ26*Wc0ʂHxαE(ȴ5dVѕI+78yg!ҼC&zC,GɒG2}=rM;-/7My{zdl=tzK>;hO-$f8urU4SoN6,giШDzNJ/%ׅuK$X'Ԡ{U(Uhe๑㞀- iwz1Q@XRIYUk^ݛ[kQw8Ppc|`qjESs8cEn T޼FkgSZxc* B|@ivMHmgZ]/HByz-ǂHm'/*V@^=r2:ֹ|7g.e1YhUq"@N8i}p{.{u}u'M:ѠS;;/,s:&@J8 --K 30_a̠$@f's2"NΖgHZO3 7@I^.S}X_j6S|ч4b6 1i c+gs=/_$F6-FPv~`8Ǩi1ڸgݙUbw6NH<E-#:M6ivh&itoPҥ;N Uwڵ4w=Lc@'N~G+~%Q)$u-G6Aݜq־0ҦinNdhGPʾv]95='T ?Q qqf+(IJyOS֢_No<^QwGB$g9Ki~75 g(6s$XTsֵa{%v{H`vl|195xn}7W7o~@i &d;q Q5 u Hlcn]Մ`@ AM]oT 8./'1*paE3X#cT}iW@dw+yg6G(ʉ.pͷ#5o뉦ǩ,7K "|NT9m;VG (a=lg ΢39ڽ1GP-ώZ6&3dfPpFk77ZBf,wHLӥF&k﷧Mɺ<9#~m692$vAܖp 8I X<䬇WmּoX\I$F%ЫA߷ñCupR\% EP7?2+7Bk[+:;OGklCDg9-j$ѭeƝmck]&׻6bJmKgo-cqg1u'<6cYsv}W/m%*,s+J}(C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (15v >kž08oieeThO xM_-l2S  Uw*ydt P\iz]isuoA;5_?_oo ūlUQr˹گ'}AƨU(?| bտ6O*KMCTsGC]](?8]_PūlU-[d,Bbj}/(?| b6O*KMCTsGG.)AƨAK5_<_o ūlUPs}To?/7 ZQ b6O*h(r˹> _P7RW-_d1j'G49e}/(?)AƫKMCT_o ?}jU%&W??/7 ZQYw>}AK5F _PūlU-_d,C̾?/7 ZQ b6O*h(e̾o)AƫKMCT_o ?} _NRyU%&V??/7 ZQYw>'AƨE(?| bտ6O*KMCTsGC]ϠA;5G/'AƫKMCT_oo ?} PONW-[d1j'G49e\_PxRW_-[d1j'G49e}/(?)AƫKMCT_o ?>Yw>}AK5F _PūlU-_d]ϡRP^jx1j'G%&W?9sS%Ϳ/7 ZQ b6O*h(eͿͿ/7 ZQ b6O*h(r˹'AK5KRW_-_d1j'G49eͿ3jbj{1j'G%&W?9.&PTi?'AƫKMCT_oo ?{ڵ ~P>רNW_oo ūlUPs߾רJQCWߔjūlUx-[d]~fA+5Go%}Aƫ./ ZQ wbտ6O*h(r˹V[1K5_=]_o ūlUPs}To?/7 ZQ b6O*h(e}/(?)|ƫKMCT_o ?}jU%&W??/7 ZQ,C}/(?| b6O*KMCTsGC]ϡZ[1;5Q1;5_?_o ūlUQr˹kwU-[d1j'G49ejT}P1j'G%&V?9.PVA;5_?_oo ūlUPsjTi/7 ZQ bտ6O*h(r˹u ~P>ӨNW-[d1j'G49e(?//'AƫKMCT_oo ?} P>A;5_>_oo ūlUPs/>wj>wj}1j'G%&V?9.^}(?}(?| bտ6O*KMCTsGC]${BTEzxi&> stream xX[o6~7Gh^Ej(Ďk ևZ8b;suI;lɖR6%sFgj~WTYU7-]?l,jd|>! FR91Ln9.4%r8,@d`t@yu7pnW@v)d402Ï:"rv84 j"h&;BVP=@n2Nu汎ΧqbXEH}w'YwF,oDF-,"trLk6=/693xVב5I+ؤ#i ] Cvs&I4J/lվOJwHu$Vn]c; 6}&mi<1p$L2O +\ 5-?y"j<扆I'9N2)$ 1c寜{q>Pc'Sd* \$VΜp]gY,zrԠ$ z(kngP+9<݄Vk ,bj$vFMO.MԈ0 jn6ޭ5w~.]4):~l$S )=RnM : :l0\26D8ȓtnjoC z6;$|B"> Wx#Qy+4qXV:vm \CMEu38669#nkB%,t?>m"Xf95VdhZD;o[ڇA(P>C7Lk,Z}MTy,C-Pv_lohmÿ=Ar]!SS&R>9ːyHrc;o;Y-ik4_iHorimNG F2'3vzK;') nbP tiC6+R]X[sjLz endstream endobj 98 0 obj <> stream x׏Zmk`0l,}]c {0<~wv{wv½3޾nwuuTJs%F D%*PY"CB)pptEIQthWfvvMxWѴ3c5ԨB P- uPIOA@~˳ֽ4{m#kAYweL u:h3i{ hTWwS&^yWwFhӭ5 aUOYX@F>{}ř.8/Ftz\yuڹ8o'pN`EQAt'Czsk u-O:u>2NJSQ)8y6f$Tm‰pLP#8F9Js0 D"ݘ'k3V`DП9莍jYkc ;%v ݋XtB!K2U(VG(mvᒄEXFRU,Dy>glum[˕嵝'/־ZzՓW~WxųW7_}qrҼjvlSfuGH"s]9lp[k9rg"cOYS뮤Kw1~܉cs,ěS9Ն鋕s5olK޵ȎsђlOHPq$W/cKǁo"~=څO_}RevX5Y ӽi;=0 mZGzVeoBKr"}my+.aί[UjV aA*XNBEfJJf/7^:Ơ @mt l@NLyk~٘}vyv}v?3MŠhT88!&` sw:J \ PhB ?B&`H*^*7 CAQ}1'qEf G,Ҋ'DJUmL#$;L$RSC|)%x^_B6j 35ĩe-2SeT[^LDZ${A,x/Z[S.q?R KXd& 6d!0dh.4#)KYR<B)>Ur ȝ`y=G넋1VPgş=f\ܞiڱ3;Ğ3NW@4"8 = Q Duq@!RQPITPH*ށT|+ԟL YS$m_MLIDOJQ O6 dݟ`Z1T/^Q!.1ЌBFRR)hF1A20|UiXU+b GS"TP+F:\?,"Gt~:?.Ë膡{bBlvv$U)'+0SshNT`r'h%ESv# xjѬ0EdD"]W2 $`S9)DcKK=DO [ jxFo ]*CtMPGQ벖I,HQRF*#1^)), ;Qh Љ1ߜI^[| I sR?] #\Сd,Hc~:qєM|(]dkDLeN՜ cІeހ۔U\C8MTTaCKNi׭xm\FtIa+ R! b^F=}'**M99X`4iLf:jh^N3 pyD!x ~ `).M U'F:13 ,QxUpFH&,xY ̶68̹̕@Pd.0"`RFh35"(TDm0&h5^hޢg","yc$k-ф=Fq Qб CFa%K` 0~"D JQz3HR{.ܞ;h?G](B#_q زoMua",(1ԡIYPnFrj"LE^8HEyRQ{wWSubN_e!UQe ^JxF*m`WKNeW@KԼ 4@Ɋ6 :)o(r B .c|;< !0HEMl5j|z)j ͻ2X- ZLX, ޷||K{6VW< Gvś8f"7'}Sf1(P>Qhң{i (=3ӝt[Қʌ7S9JSQ"$QbCV/QPY$(d5;r$DJatH +P¯(W$(wiQQ?m"Ga_(4ȃZHhԭd̈́W`?`O` țE1XܪNNo}c!!y=6ʈdKxVrHICtt5XÕꀯ !Rh*y_T\) :*x ^#PB:1M6iims9۠ ro^*i7-wR'HRQtORyr 2Q,#lSwr@(ª0`+ -.1$輨RZb#*|izIC$Gj`R Z ^ SbS); ǕQI W!Sӥ 0P+=إUhd ۽s`NַV6V6ެ~׎͛&ۮ} c( SΒa ʸɜ \#G|޸zWݯ%]o}ۆО{c( @ʴn\Kxδ tՊ/cgm7.`EY?3 Zp1Pex&~f;0E?+硥} ^+Y^BQd>n(GAUEZXc/jFfI1A'.*9 xbū⛍FCV^= %(zVkZgx($˛eY>P}}zt}n,F!cMddGQ(#lX╇E0(h ޻T9!JPGsF:0YQy(<ׅѐ=pOȂyv5GaU.у|?x~,ouN%"_́;NNwUPq7anB Z9 %U ]1\3 2 Krd(; JD>PB<$@@'{$,n-eafH*`{Ivm+i5NoTX Vp yh+&TLTdA~[WxMQ hj7Fƒ7p"H)R0pe$o C(*<Z9 XIV@*\K芛xQ}!@/>TᶃFɄҕnBhѹ:ӕxdHWh,Jr7+sa)[Rk -=`C R"p4`6meZ0l(Uڠ .NKt}0g~`|)Lg)dDybAW,8 NdNefH0TX^țU_ m~zpE'nb=H{-q0GX!W<#; ,`M]mYQhJKV }v tbT^^Ygpqڎ#"2*Q+uC4S[6VH@E2pNy8JJ;{ QDR!^TPictmNVdyXKJn0 jѢ1\0jj_E\Q fe(gP ↇ:T tWs Xx?_Q\(jARhJ% Ȕ[@jFZ_ieRب6{WRw+LBg uFJRA ?iEAoh@ 8jI-n&i$eőd[KlǑv9:C3\prp!uΑ>;$EIn?Ùw{|w |y99ҹ{;WBY!?Ɣ{D4Z9 Kw/^H{>o(x,h d3i|Sxj= XiaٗrP@s03E(Y80{P?ؕ*&0CJ$b"Sgs Rʂ^r-u%Z jO{T@JO.2X-6@mEsK{D++ۙ*Įzc7̓ZPk.{f;߬rnhUUdeA.Ly(%9[V zb4V'ʷzv)eht:cԶJ?_mMkr%+!&4!eR2Ib~!Na9UdN"l+d Aa d\)*++lF (f`NW]%kn>dZNͯMέ]N.ۦV7\ӛ97DVB;?Gb*.A J3"߉'mFg=[pwƖl4uy5 3\P_ c#MmlJ3i 5ҵ۾ wk=.cf&gff~Z|w y86 3j@H]Ɉa$Q4:LLi&o9 ֥V?.p--?-X+'?EJnK.kXqOJ<1@>uat$Pqm5 qy%ry1tiM$ 3LU551/:>rS4*|R4~p؍,M 8Q`a`n(u&WjPY(f/-$Me-cF7pb3w%ͨG$BE0b\1zF,#2T"OJ 0ƘpKWJ,kک3JVLPᔑFx:S2ӊqϟa.^8x},iPۧoV9s:Qi?Ϟ$<9}4z4{lųgC?BϬ4C)c+"rFcioDp#'ۘN}RPFf\k:&Lf00f-oI6@8<'ՊIFVxQn$HIc%}pL0ho%=K\/+rm[Nn[HtPN]JVU+Jo׀FySʰjFɹb4sfЪbS i z<a @=ɭ/r͟ PU ŒcrJ͈PQrn,/kVIЪ/T6mDp'UtD%*3LݲF>_ޟr^m[.\^p ǻ_8x!tm=y#-A 1@SX{iN՛5V^qWlepyxX= J+f#9x7+J܃aM1 T.o%VYghcҫre;̧G+‡˰>X>Y\q(7]0,/Fkc0O۶骄%La1_ \ Vbۆ=`~3%sM (GDFD$D#nwœXwWBŃN&55_e吺i$IghhܸRH[ƔH8DC9af}@ c-d1'"BJkX e+#GHe1ڟ| &(4`RvbبI2RUX=Z\a0eÜ3̰&z3-d"Y$]ēBv"#p;W)u~@O#y˞iL6=ᐻW Pa _5fI)p -O3HP!m PQx*G5v"ڣWl_-o$JXa=bX#9+[Ir檙\btv%8aD^p蠀PQd;C7- f&QJ@E )0C"`X:~XmB0Neao jg%jvqY͹8jOE_?T͓'s'OJOf/T/]8i~2:y2kϑA62{dob8z8wo=$lUԱ4| Hs@һ4 =aޛ4b%GVB2%D=3-uB[*43F#c:wH2020UZ/_2EvC0B} !"fibH1J4q`%qkM@yPF;V*kv6 -.? ިsF=:o4|],8eR(Rjw~Sld?g uQr^*ynHY-Qi?eIٛe<{e:GJa5CiF[+vRO-}v=Gdf$ h xU9%l:9OnV6 Ckc Fm#oqr~=ˁ]夬%|L.E2 oYW\Qb#vDX"'%U@,FjRkrm ,:µ~[,ќOj րF]XN~Q7* \)˱CmFnPBŕu̸/챫O穏fq)sϖp3 MDks,-5F~vbp](6(v=}_qMxg:_v>8@m(`'2GbD2&T7I&I(QƔO­ܔ;+ϬgQvS jfcsA'QUp1T`-Ac>Z&c[ 0dNLi}lE+Qā(=qƓ{SBΛx3uoI׼b-W7آ=_XΊMQWu%LĨ :0 #m<b6[qf_F0PF EޡAk;Ĕ-=.;8J$=/ JR@ YJ4>Joni׃ *r]p [[^9tBBA `ҕY,\B2$+s3fNvJ|8${5ŲSd uP4'B8 %[bgk@$ArB}P1T Т@3 T0EKm@Jps5g,o$K"Y02jbnyY[ I H~#BHtA5B N@{'RgּUo|[Ɩݑ%'𣟿,*9;=kg+=m~8H^2h7}Ze oe浩gf';gW>vg6{#{GƎMٛ<ӅNNa 'F{80B,{݇ev虥.|vೳ ᭽'2t>OZC bEtO4w׭R\F⩠XFj:(eYPjexd-S .$ -\DDFÄcAqS r*b/vy\zB'NHok`tc_*VP;vUZS*w RK*b\|-VK0S*ujN:;v&Q[,kb[,Z-/ ^7RӬO޸8.WSj{,l-=r_m궂+}1(j^dII-y$f #v#6?c"vIG݌s$a_*t}[)9V)&J<[o\buoBHz3BIbj˵x  X"~2bӮkPkS90NLTBujNTm/; T98޶oXWW"/3W˦Gnf8dAA2(0ېTIXg1-siޥ릏⺻xՙ_w7[N+s-H|$Zmy2= )P#DQX iJwNbCMSV&}4ṁK :(AD: ;Aca4{Hj%@:K4‰Y̒j'PLɚt~Ɋ~$P#J=L&Q Qxio~(D?H$W,oM6JIdOjyh3T~*j t'XŦ=,Er'$H*38X[?,p T@E#'!TD*L&TDBEvi4}"؈Hlx9xA6# QEi"Nd[!+q܎Dqb廫qMQV/I{XrE,:# 0+@, @r:y= 'sPм#LJ'%_o7{z{zoc|O<eq? g·?ȵ]l爺/򽔱E+ӷS-:K9Jp(wNm;m4 AJ(B^xb9}PlkbeCˇ-nyFȇ=׿k9|AWud$FJˉߎLgm8tGvīgÖh+ֲE]TYP>~>S "52{j$Xٯ^^blseg^M'`яؼrr_d:uj4tM$ƫ:pK?" :mwvx&5*X?7`&ryE(dn+ul3E)o&X!]!E\x64K~0fLRјkS$]KӁl8*.K Ib:FÉ GWBN#p|(? $C`f=ĉYp.GA 3(*f+M(؆U2(k49_̂m6 }6s?>/¾ ߎۉD?$d.ٲ6j?:q:7m;Hx:>}rqS;;+!jf32o Mo9Qb.B_ -l+ԙn e~<2];\N!T8:!P\4AL}3Hm9R]Ub0 lɁ ĸOPӔ"QN@`JK"B(Z2$ IL&QL[(@aT9n-`ұ#j81L$I;#A1 y ،fw"JQx0s4-D@Je!0&Z2_!z\Uzt@zbW4K@|(!TDAԶB9|DUSvP#P*GU$ " OۦLpcJo?F}%Iu ~-2\Po{)WpŤ T00c2"T`0\ TB*/H]ZBY\[!T7tJ7 ER1W@E(;pJM PR'Ik=kq(~חer2_&ie^={ €OJJW_w:u?xmxw/M_4p"É'C;2_'/M/M^p݄txβF煳G>W3@E.B(mYwRR $ )#KP8tygіljg3QQiC݃F0EN Nr]$ D 7L:mO"`,guT[jW{OkhG{J͇O&Q Zd1BwrԨtk?.6[y=%&D)3={>2o#/c(EG-YN/W K2҅ا-<*S%)$^7 ~zꍐ DQŇC(N\NbBGOr, *NXL +I^8Kx}UH&%)WX]6`W֫|ۏTx.OvP r;hYAj ;j烫ƃH:9azZ ov euøߡ6/~)0vUnOG$RA*2` a⶙S61kOMf˴ E$$Q#X b(fˋI̋HW(`2O֣Q5`G'):'Q mKP1FFHU(6,eKٚ* HH{#5_B>xǚ 5rZN0:x'+Ufc6i=Z,ejg`fL(uRZxT5z:UI%+l$>!o(%dB Gɬ)BZLtYEyś.hFq4pOdS$RxgC?>y7qkb/;FQ_7`}[İZ͵oc#%R2F4ǝB?abF?KIx_QiGiA;k0 71doƚ66Bk SjCsRP;; S49񊚔Om[h\ΩWKuw,b xveIn^d.6Z(Fű[K{ފh8Hn cbժD*V"-NPE?ZOPri6ìs.m0z &YLijLcfrMMv3P)LE("fy:~VR7,=c`-kLF!AxrGs#(~T*TR2L*F\B9 %A(iZHEZ`"SgCF#AxŢJ Yf A͠f@bV FFN|b WQuwp9#%&0Ms`$MƦ0Bهw<;[#R& aʸaᄕ`q;/Jp#[F2}[tkx^cZǶ8vlvbgf/S>يlNciLR2)_=O>:_z0z|0/+!sa-Ip\N4MMMQ,Q0z`| wQ 2 #hrOh)fm(Hbh%)rHhvM%fE(($ɿf !suj،4xzM[Pax=  :kl D,l7TlOSe+JRV2LeL}n?6vlLW+ɥxq)~nbܱaG-By0ST՗,EhFim5DQ.Fp0;A|g-{\)E|Q2^}3Sd >e0k94vFq o#њcF.)p &5 ^^)lRWq1/ `8G [cpb8I2*pYo)#}0`^2Ԍ78Zq4@+y/Fnߤ>I9sZ.m22x`x1)p[ ){1z]&_Ě-t [j!τE'$(x0I]"PAZt%@],0bj= >^A?c5&lbB4z-E!@&fo.XY@s St1jC@f:̩pu%mV gL2/^gmaKp6ddd*42lq[tb&:9#h:;|ѝ!2obŧizLvOovۯxvG<~{oBi\۸y{#J&O= 3z3>nx@c,L: #zG0iisdgm  SSvoFA"E%hbNxy4)/1F1Sj%(rS`LHjZUl}i9=}|:::F GH)洜(˧9qW^_dzǡYP! W03۾3;M.]; vG^3 8&˯cG Q$ iY$$\A]S\H )/(2}f ]FМXbI Ĥ,+HTpF1@Vjg)V)*0.KpxDTg&x;!YF\œc8#`C)!څ'7VyҐ IL'31|NanB 2ŞqO`=D*|4R#T'}Qh89!ŗ:XtBx,yv VM'RQ2Zo|p'ܤ3rMZ7#x\ߋ[[<sQ/a )T1wZv5LJUHlv# >SB@(`mAd#9 ^,[!{"!&m'}h[cRX@R"Wy.;Z(M31k9З[  P1)P6ʦ@̘% sd ©+{޳?YX+Ʀ [6tncխw^Of†֬X+A}ᆿg/_\u߬_Z//W}+~뫷^~Vίk\.{JX{ekuʪo|o|Ư醯ݏ/E櫾wܒ.։ iV|~'zц~Sg`IE[Rmh?qywt)i $Hx S=txR N|41;ᅝ\1j*CY|[P$j!{h09 qXn]afQFrXr'gSJ$0x)N٨86}%pF!Nt:A Y{-0@U\!9ce'\a $HCV7 s"WLByZJ] 6t̐ݑZѸz/` mȒ=%Bfm# S(cCoQnQ4HF*9VKjO\H\b(XRK|i/`@t"KbaOH=I2[0D,>I#~j)1Nv8=Ii@Ơ/ hqiʉBJ2m 9܈0)serZ^~iuѤYjCVu]UEP#Z{W$"L9.#<&`,T4*[[:;_#$ve W'fX+;?r"υ)4-'W0 Ng5|-.DhQ`vЏeghFLu܍ D0Y,ESI/b6@ eE1LW=H|(tH@^ؕh:u;nǪ}3չ\ʬH0G(Xk]8OR G=ޜ7%D id#t$! wA?P[` lqɆ. {*+C+}tha N0 $˩WtO?K %p`F5xhB|P |4,!ɗJ)4:AS&Ba$_($@G'@*ll8: Wn$t™0" dV@O~Kpu ZS܀(G(7oJzN^7A'(޼Kg`F@0%RD3Qr$W6r#+"OJEzAp'ʄ1تw.f۽^It5NàKMV BA>H SE4~E{DOHNR!Mœ$aJk= LIf# sXR(xHʼbJ+AU< ՓH~ _YE7ޏ ?JC :L]hWz[.f.(9&^T}ybfȾ(WT+`9"F*(P* yKE.eD{@ 7UV{+$v[HoMIHV#iRD Gir@݋,#&ҌA8$hڡb(&`P V(YQoIÏOef fJ@qw" )AI,mdRN z@;9DfH[tA΍)NXtPѽc\0NFeuQh+!s "TMAhR B=\@HG%c7\'.C,pA5 0\T!瑋^rƄ p.tsfR&W#.JB+7$tf2^1(`G^E!K9IS)T-TH|UМaghq ƎuoD!! %xQ轪?]yXoP4 +8!&SJV.F E4(}*-L.E]M]t.P0 ES(xFA\*rRqR"R薊VYsxڪHb6 )zЅW |p&P`^18ȩ :W輼]xD*+ څWT W@% 0}*j[4^L-0BQ=y>󗊕%XF\ 3I"PxHh8uT|c|SXXsXo@^\MI}%DM2_qk"C}ғ(AXj9T.M{De*BiNCpHKIIf)3@.m_F[e[WA#&ɏʹ'IoiC'b_u$@mև w>LhN &v&|r;Ĩt PhͅS> ;k01/JYHA{gG@b09;晟H [u`{aH#L-RpffbM9LjKk` Z$@`a:L I.Yo) (f.2 &躿w'8 }L!:@ƿ \#L48j_)%QʘWr%*%EG=r.w>⁧syɹ){p(zDjT-z&l\HV*}ATpQ "ֆ @X`W.L`MJ2(+2hN% u|BZA~u>J|D*e Y#>p0E٥N6ӂTc R:4RX$!+t,tY+-r,RxZ(`7\!9'ugṳ+=L2ՂXz+lpǬ7ffv!]A U$^qj@m<\(f+@P^Wz-#d E7׋ zxY1˶mg{\(˄B}9_GJ^J"K$Y~m[ZC!icKF MW_ߕQhShSLi'†BfXZo]Bdͅz!ZkdPSZ)^+SIJ(Q6n}I'g8_8lF/Oh6jdѼ!eeRB<W`[2Bv@/P}Uz%FY`v lz(JUGoM,Jlz#1_ NLZz(ludr5 5nJGBRhm^`9Y\߲y-wЧ|3k5 g{o [pc|a+p'Ts?c#9i=v=(}U6$o$;œՆ-[}=Ôu02ȿ[N82_3p1OuH}v|W7J*YH//e-m񮟮 ]j։לNvyO}b_E@T;OUTTTTTTTVHEjd>䓳&Q" >N}yFqƭ撊J0lQ4Wmܺ>[-Ų/Cx9djR9A#NL=/љsBV_2Ž ; K޿Csۑs-d]tL=`B WEEEEE咆+6"*5W`5y|)KSdW{?ݦY޹9 y>KDnh 8$+%UjZ@՚)J Ro`{y WM wpN%^TTTTT" ݞ/&E JJK$/ NV.]ͯp|䧵k}J7p=յ묰KT\(lڹ;aeogO⻐ kRWk؉*|v;6_3?>~>nk]\aGE:`Ńb,H&&]r㣊3%Uy77/K~N ٖ~G&X{z%P(axQrvg]Ef!&W>{ ܲہyɚz\?Ga}P:B̨EBa]gH`q(433W\<n\hYi ?3һ*l~S W8rlO\)'p㇒7ƿJd7{,̷a;QDK[y׹RW<sWɟH0|C5X"tG+-xp (-g',]] t3o)pae2i0>~y{in~B|Exk^:6QW<sW~a?*****4DV@Բ;-?_ZE*<hxEitF3uXf^ ]w\z$ u{ #oPFQDcŷwlJq^^ϱW9J/gFEEEE/" 7mښ*6M\ 3|/hwwLTH^dnV흳p&鯻 -+ht |MdrՐ9;bj,YU\(+}v9bt#[K_YwrBᦍ[ņћ%<Ql-Vgk53 O`fUx]E3uBwCEEEE@Qdl4s[>@V$**Q]PQQQQaX%ɣ #]jrm)l`f.;,! S^X{O+TSEEEEEEEDVoښ.5h3@Ҿe{IIIIVFae sѪ@ھm:::: 0Q4,\07_{UIIII֣a2GnGLG.ѩ:::_FQ"pFk׮fyByLoҙS=Ȥ%uR 8t?7Cp-n"3ߛ8q߽~~̻LJhX,a>C5viN<ڳy5GGG_|={Ow޷pK/>}:NJ.kȀV.<0 ÷\?p Basή;nx3b7<5y>{ܥg>:_ޑ!e]#!b;?v,txȑ{y~~Ƿk{Ǽ^/9J+os[ߏ7;ksGp7H^=Mտ~D9]%r@`nn>7gP(AuRʉ7`bm.͜yO_7|4KGw {-Oj0ʿowk}OD*]d^xX4Bv0];J8qW_}嗉d21MLL9pn'?:D.k&>HT槷_L'bOn.+?7ͮMlz5fӣlƸ$FcG2H "C ( )Ҥ#EP^g>3Wf }79qssy~sDˬD&ކ2CCCϋ/J+XJQD;O "f^ P.1qm}eˣ>6!Z|gg<Z\DsshbxA-MNo ~kcvv&*+9퉳?䠷#|ʍ޺J¶6ʢjK祰[c}  "jQ44~>ozd|2;L(hxNօe$9!1rK^̦I>3=8vZ^^Ñ7`(@QEqcomTE1xYi;M 62ߺ;;=;3W.3o`x$zԦ,cխ$ @Qh4!@ *$<<"577drqT\VAeWwOG@Q浃􎤮Ę h (`dyꢡA@^jMQZcZAO* O~':jQdsI9nl#9j@Bѥ Nfy]>nK>-͎WFk 1T7)0$L:b5Hw "嶣.E 5ZFPvHQ@XF3}*W#j;7wM$W /Y\_%ؿm?~)$u?;tBr`_lLL||-v[5?߃(Bيx^VV&XPΝ# ş0 jJgQp_!>>>^^^ *RSS!HF ©Q~BV%*Q X@ʑ8@Qu%~<<<\^B 9лkUB1.R0F}nOn`i\dsR{: kӣ&_3w6- ?'ׯ7rbbED_\\Mhʍ gm=k}sssԶ >gZ\_YH30 S'ĆGƁlX(Dz}GeǾ.Rh'oKP76RW+Mʚ2FuVn$PEZZZ qG}JFؽIch~|8kƹ4;;;l ~UCy/v}: etQ_@ t U ۘ_abbR]]-шwշoG- gYscScȆ ˆCzp}B - e7Mt MN^?&ܳG-I('QVm MͭO[@Sshvv5bhT3\܏& S|\gP@R#^VS,..9:}r%O$KL&?6qB s;G^݃ڲ@7 DE E1ȬgMBv"c 5 *M 伶E Et{VY牉nfѴgo~B(c*E!22~@T(0--\#t'`Fnn.y#] I[ -\0p[Kjh) RT-,O.v] 'RW")D/[`H+ d߈7KE&K?pLޮHfyԻi?4?F Z8/E@?KBBkCJe}pzZH °k$jڹ8T?4չlCl "W]iEa9;F"52??oMq!wd GO̹'‘xG* r"*J܈_tjxD~I`瑡Aq.ݧcm3pm紲@C$Ϭ, 2schp0b8Jf&&ggySÓZ+mC_?;QsB@4㉦Ѥj+SD9 P D9M* 97, 胢/ '*++NKK z $C`7vڥK|q[_!B^.T8G;f{ct;9UCP, ;rF[QiknQkVNe&ԇyup>( (K݀vCZwSwt%ꈃĿ`~! uqwy8ʭJ#k6*$zmmXOEC^yى̢)"e_$q G.0 Brz/"Z' ł B{XiJQp8lBE?<̚f!#R~~>\R!' 7,m.3bogGVc ڊA9m޹}6ˌX[*+pCccD#"E[[۳2%^UR%5}Yj:G˘>_}\ku}9aE+ ⎢hRp1Zģ驹Y<)' IY"?`@s4B(т uD6oOwE1GLp_c* (.-AN)gDH\\+E8/عq VC%|zJ%Bbx0aW<蚪G7YX6F$''K[ xEjrAQVPѝRQ@x% #P x1-ɹZ'i[Pٟ1?~\FII G+gwڿٺW'Iy|#ncOziGMqק^6:'MM 'LT^_f?tӊ&z{ѵkg ?U0q?=k=R-E u?MS( wf}ӑ-|*hꖗS{9ڒ_em2#F555Tt8i$YXiD[HkG=MMM/!4҈~IXm=ѣFhZawdVFug=d+ 3GhjnaJ&rb~L(''W?فH #^B-g 4hhH F T/PiA~qT(233 Xaaaз%JOO6 R!11D c=0fk?@@Ȑļ555y{{@fbbbjbBKQ+ڳ) gM,h][WW'1odǛ[؜uNag2d_٭^oB|5?H&, bb_^XXXZZ |Nhi]U2F2)<_ݻs~@_M?d>$-'"#oK *EԄjkQg˶Fq[bOfy(**677K4nknG: mJ߷k 4jD\B켾yjK_Y|ZokS2zh঩V\\Lq"-#hbYYf(.JZfjCc3Kw^sԊ엦,W䬝~I@t PRV t2ȉmʶ6|es{+IKK + FG{JȧGK0q+?#j%9181ǟ;iG(r쟜HI>CkhԻu@m}We6ճ.KA\@ e_W(n޼ ȇ"XI me@nn񱱱{0FD#z2dB_RRԲ5I彨xmOͳ=~c_N֏Bn%x مBE+PlM 1*;5d) rEvh rqYQ,GYX|5~bMwng}R_0Z_=H.ϴs_{7|UrNl ‰HbWTUUHV[b~Yq1/,2F=r䈣[v{֊I0h~ !4Q?Hh3rbOMc!R$M=آ p(\,=&K܈+'\ *hqm>%t+U~љF]S49w]Q~5#6}BV(lma9%1Կ?'s[]X]h`|:.F|GLQwfߥ(h55*)ʉ~\ EՕ(诉 :BퟡMH;- /?vQiT%!"5D.P5Ian(DC$_E]89G]R툯laVfB 1 0n2Oԍ^?~nuo_A:NȎ7yNaf#2X((W.S{Pp"TcbbboaڮOF7ݢJ@{Ă 1=-+ȣby?hz p"#/x?Fsag$љ))uu(.Q]QWl'S,,aQ1m>SG_MYDh5 lUaݻw?~4&  A \(V @d|7(fbb"HR!4777 b (' BHP%̛ Hھ҈z0 :::0څC4K(`峓[7Xai,R G'o~cNӁ?z m0c*Hi{7 'wwyR +|~|׽L\Gm@n8?C0?hK`?}}vY ŹeG#Ǜ)Q<{B/.l#Hnn^ b5՟kk[VUWnvjPQQ155Ob0h]X(Ԍ=-L}㳽㳠%Fg۹3>Ԋ'x;1'X3b]͕ǒ<n'oOO(ПgffK!>nw+ 7T/\[999'`X 2 55dvwwZPD \O(Kl69?a0xTdlo%xm+n|+o QrD܀īOȊ۾};P>\ (Ȼ!:AAr8p#[Q e^Ƣwj/+e?ax !O|RbN6:+9JIH ~ݸq)=3st//4'y~v:&>+8M-$҉l9 (^i%\-%C{AB,({HqQ$"VeJkdF,9s%Sy!30!qrȹu7vheڒ]6sJbe3Fym[(K󶟒FX^7Ο\]QR\(,)+*ȶ;c J"+ FqEQs Wp"@ꢶUde!iZTSt`]2|x۞={444 BN A!ƺC؂Q,Tn%LzB'B=---Q#( cq@@t~Uii_sGQb4~y"齱x\AW?U}buGVR\\d l6  #0ԴNx^ ~r4}}}}i {x‹|@~ |^tQ\t#3(bWӎn N%.%FPm MM#Gpc0+HNŊ_3@' sxK3tpUz{{C>(r/oFA$%%%. \~hE2(P?o_>8QI(>N!++צH(OTq+v@a,޾n Cjvuuu煚PfEE]=H#?+p{]]+VyMpJ(oN6x3ϑs"2=33\#[ėABP:cccABP'^j 4\EEE e(0Zx VVVY[[(JM|<& V֮\bggg,R 3in.2J$d{B/M Ŗ2ۗh=?qJV`0=: E5gcJ(0 !YZ)XGrB( V2`0oo5B"ʶ~( =nLL.ߒUqJXQ`0 Cr[Q0JwE;AT)]U~dGnIj#~ *`0 d1R@k@('xm$8),:?5^0)Fa}1qP޺r(0 !ٯǝ,gBMPȭ(RՈۨ"vL/}F}n&q;hUS,"~+[N=%q5E[/WJ5ľTǔ3V TMU@ZRUm9ۑzI] M0p g +md Ks[ %i!USGjB8Kk#V qњvAjU (v( 1-˾ܾ҂}Db qT,€MG9iXQ`0 CaSc3uj:u\HE!X}dɨ ]n'AxfIHhŠ`0 gj:Um\F@QTvw=V((,P+ 1AA5G!f_U['>|ܲZNwlza4B8gPN (0 !9a0̟mꝄT.` W4LP&ye})+3W([PbC1/ym&=A(""\a8T`08i8ŸcMAN (gwLK(Lߒ bH+ `Hn+)v`{wT+ `HDRU@QM/PJ'EaE!(0 !9rlf4 z9 `E`0 lS`efuue;h7($`0$ 'gv$#}*x`07\v:HQϛ:*}p N8N8= "_UjX] vpG>x=`0 FV**~4m ͙]SXQ`0 YELMWAj SCau}(0 DQAbO1SMYE eƁN8N8RQS!54̰gX3#F+=CCc1XpIpIp=N%*zwO@j"H܉y%-KQDDDsOłuMuMuA֩DEp`x|oR\RM+kHSRFxcv^/\k\k\k Ea821<8 ],tԂhRwE'"_ȗ~zigċ;^QrcV4{>sO{ 1FmS˻_,DÁ/~񧘀F(*Z$Z$ZB1or-[ZT5RQ;ɽqm6i8Uǩv/NWldgY͎gV4{>xsO<>Vk\k\k\k EqLdtj^0;]]\JcӠ(ET+Fwkvlɭ7J*yB䷚ժx¸齉ꞏ>8'ϱKŠbjeobϸ\v0RZc!J13`KW^7 P* emP ( QEqRQ?v!u̢ő9n' FBkzr_2oE{^,##>!ĉ iON(UHi"mjZ ߃j]*L_)ggrTj=bAL2SqP( 黴D|s:%q}@@(΍ @Ӷ'V4*ѱ;j6[U,# qЮv,8yB E!OEEIIt n{dZqN؈QCRH>!+UW٪nYC[ 06BbBu|~/6WV:u^#a" 'hTˎ1@WvR yy,9G!c)eLrw~i&Mfimڤmې ٚ l0`f6`c`H1k,1`ڀWɋ$ˋ=2M3FgG3GÜ3s~zߑtTQؗą{t8ls-Yy*71.gB' ^ZqIG%wrpn яD%ޭ"q>~=ͩC)McQ=TX61$.,8KEw=H%?ߝsp-U8W.,DQGE]X:O>1x]e  8O Y a-|`m ِ-ķbȷ̶G!ĝw^+H=ys2bGrzj־c`Zr8s=p\Xˏ[1I<:>nl\⸔{Y0~$Eg+x' $ȭߚy^L,!zS܆w,vaYxs3?en@t`JV VQM3]w-m!cE3.wWLθ &`0.=V2,A܊ ķz"-QMyuy:ގ!=9닽;khIX6_ӎrE"EʦŸ襉B")97%QF>2 ȅg){=<Ԭ7gx9_ ]X2□BCu0-݈Ĺ) }=,e^Xp]'C8cXn@um IWk|Xk5?>꿬z*W|-`UHε-܄)ӣt D1{f[g=4ط}pE/D<P7wq9 ]8J~]x 7Ϗr38[B* ́s8(H\ɿ䲦$]%6]7:x1ŵ` rl@rJ]m|xVhnphjwfFrv˳-$[- rHj` VwT0ᒅgBu̐/K"ࡓݪ+SY?W!J1Aw=wkWW`]*4\,̅uhj;8ܵG1.sq>5h{۞`W 6kS,|miVζN*QI |VEAN#(wasvUIE=$ (nPaPa4C(V|SIv/fr#1Ф\~h򕇦?4#ӯ$*B;TԔ ONÔNKtyO{xՇ^yxf^pҨGAN[u)ҭVIQX;t]SUmihj̉#ҭV]t(:*zF:ӵSyHjlHI̠k["͊t.EU"ݪ?RCJ(aVVԛZ'IDDDDDDD][DQY nƶ!cDf'E)RHu$a QX; eVJͭV[)D1{P=kmoxf0r?uH#vo#^wČnwpӖm1K6k3-u"E)RH0QD:< Hv GRG/jS*1 [`9ɕ .~ L$̛/:zQѳf]jG/@E1w>¤H"ETW(DaeWCKGЯZԡ+ȡ* >o5{' LL#NE+xp ICB“O(W8Tyvو{+K d]9/>=J˱_Gd*ɕr.{u+^ڱljd?Y*{ӭ^guPh[= ֎NXF^WowzW-鵻I ]~ F? _nU}T{A&,ft3}5]`81w{~zs}@`h<f¤DJ5_9+WwV\߾-0Kॉ}ņ U_ΦyM#OG %aθFܣWK] x /qrlk[eR@UqBGխDxumk;CL5z# 81}>SݖVW 3y=`L+3%7KOW+?jQP/0m^Ѵ yGϪ qb|Ybg^|wƁ ;%>rS  .-BQ5K^Z)du/ Jb9}6 G] {Ėp"t/t7 Vp5u] H 5H/ n% Cm J6ҤUO3d=DI84:nΌ~ #(_҃*5`>}S^T; O 7's Q[ď=G{9OXuu+͜-n7O1K$v@"Yjo!"RS(}8a_o*g_yd^l7Nm/Cƾ=tEh w] L 5% au4QT2DV/DˈYYY'N|ǛS6\JJJz9=N;scEQoQu5`͢R,~_ n:zW_8t'=K2]_-x}9^FI{xs! "(88sg7<8Nv-n#z[QԵ4vָ›GB TZZz_;>qeraa!dO' +@;8EeRT;*2'Y ~/ݜgSݞL?^,3SFꡈ($ZQ}q?D(bmFs4NM%GYȝB~ =Qqg R[A ֭ ̬d^v˝j~ o+gy,sRmWٷ |E!ۢ(zV9nhW{ Zz'ZXty%"mo~ཉp*|ACc#\-ie A˦Ew(L Anp>c1D~%߁-CrO!tEX%Fg237l޴mrC^^`0rfBDlɣ,^\.^BO bnxIE $ N! 05>>4ʧ{ S^brQgͲ?]o8m ~:oCžO@{N7&Äo,>Q@l8nQTVZ_(>ȑ#eeer[ =Kٛ ^nz'Q$( 'A/N7 ? t,۟@&:x# 89^Oo(Ka'ܜ9W+-˛% ?~`0xAQ E#;QZLv`"Z(fۣ)7K8G :",Wȯ&`Ϙ`< %Y|lUQґYۼaK_^׮]jS b)R]DQv"퇫35'mJ*&]4%^jXv⤘jOi!{\wH%7b{C&"uMp9! Rf pQmlmD)CծDmժD-,[6%jF%jhh7un)n+n^9\꼦OFFD:tk!Q0!b.D (R7r%*R*QUDEJtGn-*TٺD7d]uEe+O.%%(. V[[ͶNWLqBQ EDN(" 8(ŖMkV\_kϩf/:bō5رcFQzf p x2$RnNq( ED!'"PDj"B>N(" 5pBQ ED!'Nňqvk=rB>NhPҋX1/a~vsu񹍟_jaהץ|w/{wkgD?bu<`؟v Ͻ!n,{% 5pJqp^qB(Dau23Q 7(1(h4>|hQ6[fΝ1b%P!xg&]6XlB?r5{:bDkM|࿺AL.&< yv/yށA;QX[nլ2Q`weP4$}w-^hrLLddDhh/V[Mv.++Tl.pnK 8ע / gMI!BHTGA E8A -xH Eu /‡C(,vCѣ{9xޥ6ES'ŠBӣ?c 0xX bQƉWgٮg=0!^|I|֣Z;2(x@E]s/BC(L& `d;7? `L ם>-T}3G{ =+ zNk9^ ),D( DܠBށA<ˠ@wܠ 涚XnPQyޡ(2͐.r/Oд"ixxW+Pޙ dz7B|5ǪcsR< ޽DH( y^A!E-qݜ[AX/E y BDAC y^/B QؾnuB/+N ^ E8A -xZ;E(eFy^E "7Hgb^ EZ;2(^8QPB(x QWoDܠBށA<ˠ@w͠Fg(ЫA<Qe"Q`w`gP ;2(4(ݙ bO=Da"Q 7(j( DQޡA'A;DE(O@nP ;( D<Π@weP ;2(ᄏDqE (1( Q1(A/"y PS < 5ppQp$(jP( bPh!ˠBQB .Eæ(A.BDj+DܠBށA<ˠ@wʠ&7`egۉ"'(DWyޡ(f[^AC%9NB yzNH EC2w@z5(>r"-m]३F BFyz^ y i8UE*;|(02(jrb-jfj8eB! "C=By^Cg8_ҖU # غu ֨M6K[D<  y^"(`@Evi,kށAQ)i07~ 5::z̙p˙Aĉ"7;p{\H5<BĠ F Ty Dq& ;TIĠB!Af֯[ DenTVL& "LY.$g\oK|>bk8Z--bDWBNB y^? E!C-vhU(AC(֭]cG͛6lܺe˶[6a|}W8ÛdA" z EQ,;Q@ ?Q 7(wdP bPh!PàCgYDQ׮Qՠ@w$ -_21aLЅǪ>+aƿ"~jϟAB(3SM`]YǙsHB;< t)+ BAC%By^C=B&NHEKFa=3E*(qB Q69yqQ&L:uԩk9z_z`ИӦό^Ν O "LoDaL< _%8E~DQޡA׼/yށA(n58* wӠ$ xܹǏ3&b-Tl 3:y՝>Y=i$83?! 8{FyzZ;tlPHi( Q06 yDAbwfB/3~a?l{S3lCɣF'$$+E`8[dyU !Q ;AoyށA'Ņ Ĉ B'Qy% y1($pB(,{ ^S)7xoTTŋ7ly[z|gXی'DᇄDQ|e q;dE*KĠr!M. ^tqUSM:ᅦ8|UUU n"}ILm;;3}qfR ފ ?eMz5(^^ -J iȼxv#$ Tx% q"P8{Q[z ^x1<;|g&[rB yJ^ yzĉE'Q[F `8{lBBԩS.\xرJMQ"  y1(wgP(;dM& ^rl6C5T4((0;3(ĠBށA(T" r b!  y^r ?QXZ܁ єqDQѕ BDAcbPhĠkށA'|6((6,1@wB&N 1(3(wePh!PFE6H.'Qՠ@(#A'2(ĠHA!A(l$2n;`rBy! H>Q 7(wdP ;AC=2"PrBy! "MI +Pɠ@weP D|Q`wePx%Yd&:~ xEۊ[2C=yށA׼C4Q+y;PDQޡcj G=J:Y)HwlXbPA-9DЎ+Vf-vpgq`(&r%8x:.DܠPxbPh$A!(ZN Q 7(jD@E[M*S^XXvjó30Q'%Oaő*WCYd'M -* 8A!DQi' XvL y Ao`?ɺs̝#蘭b%G^ݒsJYxUFMBBug"'Aq;yށA׼C="Py7h*iuS*Fy^SbDAGmmM-M3AzEN^BXs 4Xn|!!;p{A! yz/By eDqVnVxbD1;&.<|0o8RX6v#\ݼ<ҥQ0ГcƢ'/f% c 7$$dYYY1 =8C:;T2(x 510X۳&  1$ x:̟??<<|O._Sb3ZDAnS> y^>2"S Q`wePw`'E| T v' ^5aîoZ##JQ`w`gP;Ka~Fy^y(m-fk2z̭bY'GĔ-mgqi&,*Ss%)}W}~qRi3{r mOX ){NhoAߘ͉+WݼU,QگzO(ˠPh yށAC(ZL&WMɿ,oYkZǾvak<_Ymf)sdkX n %-)|[np,GTɲ9Բ/>igIwc^tq\/kl0l\r5ūKKkilo'gcgG9~ ^]+sj+3[)=C/ G,)_S1KU^e^6{adK_D궴f)5pѣnUX\.2Xa ds2=Q 7(٢DQ]m@nP ;lPp &X'Nf\|ɓk?AO-|p+/\VQeaTm`jlX W\ןq,f%)X%PCM y)xRn,YkDUVYV-~x3'93Fla_nڒwPe#T,kM gv٠kx{\O9v u,r@nP ;3(4QTԵeAPJ y 1HKKGٳ'N>9b^˟93+yĉ+W_YsK_ EPΫBVH,G_\#333N~DqћS6\JJJnHj )__Z 2x-70pLNo)!VΊ{K& %"4n盶lϿq[e#ʾ0 nzn=՘ <7z0se׫7Fyv+Q[Zm*iUDx;Dail27ZK8~FcyylƊ+ K̚5+:::4ls9yJ*Mk ys͝N ۗ__5% N[9Vwvv3v;&Z d cD&&M?t]`˨Gs!ݾssϦ:q̿-[lyi#ngt,X2(bDQ*:fp̼ _1_쿳}^RU_|4k,rݖ2Oӟk EYc2 {KMj5(wmPp^ve{n]9B0PК]̶]˖GdeeݺhѢ)S?i3nݹ7`2nt_8?;T KαL0`̸ @1-XXqn P y8۶o 3,o˪l(Q޾`jw -w@|P%]CGN[R O6Z;Mcp?>==Z/7]-tĂeu~Kcﶍd[6Od~ ˆA<ϠPTKnB y.([]S[i1R06?Ӹ J❒6XeӓAу(cj+*ۘJj/_+V׷- ְDQA (NpEm݌[*rIHxqN'0?3*D* =MĠޠ"*QyށA!yFW.Umtۡv~QdqUjTTl{<(xpB7Q/6@Bj5(nDaj5_h2\vHp~x(28*D* =. QՠPBK(Z/" QDa;R ,^BD=GDVB yL8IiE*Dry!Aa&Hj"( _DQh(f("7@nP ;3(wpE(\'D'A 3K_/NaIQ0,X8Y]]OH %7L'Ѝy靧=6KDQA ^"s7L*|I 1q?QP0:cObqq1TߓJUAZj!?xinhvhR]]7TKt( QxOĠPN8 N]]]wv{EIw {؈9 dŰ~Qc~EoLȱLRQxA Q8|(Qՠ@w2&nMx(áC,6h1L?Oӽ{>~/6qDVB yL/N oBcB6cuUs!' ^# :y(ȾsGwܺ9=t(N5O>ɲU|ڜ+Q^j ^mo>f'߾4s+ޣQxVlDf{W>' C>y=QzGj;2(؎}1FYBVyFn_//VY]= b# Ӎ_]78cګϳF}֭⯣p 4  ݻVH}]Kq"zan%@$uIC pϹI,0" bP >0(A᳼q컍}`W^)˽RՐw}G^}i[L"(]mUi\!RU uo&;1FsSÇ_7->2: G7hH.^d!t$ R4݀/̵@CNbPgPEG%2DZ6@B8+3rҳzS'r{joui& do\k5i;'dg!mCH%)%7u{D?3f߰?>~ؖ)suhXǻ>;|EZl;]`!~&bDB .A!e\}{ןdhTT8>XW:򣔔{# H@2oBDhԌC򒆮k-" pΠ)d0 ;|oPY"`6+mol F~zPo?I}?[ذXLEt 7qi?^el@+̫&\?$Ds;yRko=2&&p}g4? 'N8b~3~ľwv1]*.诩p%}Qgj˱YZ|G y|CQ' w(ܠ0if=K}9w>Wh6 ג2[Q =M6l޹xQ\\\PqA˖-;x`rrrzzN.ӣ"V2IK N{F5_d]W-Qՠ(0[M-ϽINN+--mll],=Y(DA hPp V,'GAּ,(ZL-DZ7[l)))],=Yljg$! p/ 'Ń<H<% C!7QLNʖ[ۧ>ٳg=/ߓŬxKKKFX ܈A'3(;,Da)|C8DYiapg NDO֯____ݻwUWW777 RQxc y|DqNPYQށA!o(%,o/oҴS&/'3H~v#FƝ!m?qkGNfVTjjjppŋ@ӎ߿O8z/D>+`;W2+Pt y|cť y^CtKF􇐪Kꆬ2}z/%aKRRRz=ی,_,:qAd$ִ[E.;mIt:;wuBJjK}WSS#QͲ:GJ9v% yvCB(KQtE'1(wpxyº-?9tː)AWUĶ|р(" lr.Mc%L&See%а0izV۠i8v߅  4 QQH^qDUJDA B*%  6HOOG wz/QwO}훤 ;ґILK.2S{\= WZF'Q۽Gz}nn%K(+QV$W]5n\FFft?#]!{.0)Nw.cEHFЦWlوBp (MV(lD؜yƾSMuKϒ111l$# !-\u%hكH؉.)D3 f8M?I;c)sq^F 6K]MOiZaâKKKTN͎7[Bv+T3r, O2K 8!(D^"  [ryޡ@(:{mmssb}JK/_`1cؾI ] G1؛$㣘>/ݣcl*>>o26Omq\ UHHHV[&ZZmV;f@PTk֬)..f(su)$ι)*zWf*;d2(;x"ԕ("  &NŎ;@)OzLv8lܸĒ%KKL-MmmM/XNZ 7 U?7mڴaC.;wܸqgΜ~TQ@R IQw:kF7jKye&(IBg!*.uAQ ;2(lDz>(۷/_<++ EN2eȑfꫯl&t]O= A7 ^xή3j ^GESƦ2J!ٶ$ͥ)))6lXb޽{AOkhh~Jڎ=沗&Q!! 7ywY{QW$ J+39BC&(d' H0[{~EEEZZիA5jĉ׭[FDzp J*b9IL&@ª*r2{XQRZ $ pBE^^Q\mN$ I e0zȑV%%%C (lWuQ[NFK+3ɉA/"*ne]gP)-Q 7(7(&YR:^d3! l4./DJ)nRh ! >wI(ByGDxTDQށA!_O.DíRFy^7N \x;y!(2-DL=t}aD|Ū*'N^d0x]|EI+ ]JVۘb#oBPCDVyaI.nWW^}5Z͕ޚܧ5O5Ʈ*YF-xx_6T0e,;EG[&Y|f}bVNbΝnaD>]s򘸸wq9\[+nDVBN@(*Q\*|@ yQ^j ^mo>fSʹG׀]|gcH[yu3畍(,\<x=mS=K(@UVVq`)Ӷglz̪б^p`0qJ>gyL %x8Eٕ`(Daq?_0~/<7oU}[O^ Q3g-dmrr_u uAn伛j]W;RI!ǣb# 2z}nn%Kà1jӇZ󷱟}FcLL̲ƉN~0A>1d򏁃>.--e+ۿfڹcioHXL= RܕƂJsJ3RQ`w`gP>' QwYۢ/BN:=AMz_ xAMok7O;vlBBBmmm9z&zII"`65'@ggoSفe-v& J0Ʀ[{佀eN `Z|o3f͚5^^4rp~q U7[WsV} p;8)(DQށA<(rQTuX6/B!NEMtx׫5I5>A֌xkK|^贩lEl2Z"pqlQ\G\/s-73@[tΉ8?F0??SNz\^-(^\[DQjI T6@w`gP ;5(8(-DVBL (nRkW_wKD6z/QnG~[eĿYhzN/PMQ0h3n3Y7^D6 hmvӦM&ɸ1Ǎq̙j7IW{A*ёHvwmRh˜J DbyށР%GQK8Qՠ@w0(؈"ߋ>:w+3'eY;ğ=#*N?rDȄ8phmg$ -;.Rxqulzy7d\עfjnn.--MIIٰaÊ+ -cT1~"] u9Νcaŷ։R -Ƹֈrw UjP‰nP]@C>@nP ;3(L =X)2 fet{Μ9%u:t`H@())),,1 y#^i(@nP(!ˠD[}7(ZSDܠ@w(Ӡ`# ^իW$&&>|ѣ\P__$B=Y=j+KQ@K((;2($;x⦓( _ʼCQ#Т\ւ^qLgK1w3W1Q":DQށA6(0;2(D(R(zHE $ y|rPAIrDQ Ly^{ DA$HEIN*6(DW➃( & b_($("!DA D:QB,AAHrQQDxIZ@nP bP8p(,Dq_>@nP ;3(8p"DAK %xb>Tk%J Q 7(7(QI]DD^yLr̠@Z(0;TfP @UWWWQUV`Q`Q`Q`#ޘǼC>By((/BN R@ QD!N" 8!((BΠPkAGlDa8yށA!9KrE5Q8A 8A ePp:B%QODJ;ABQ4P$ ,AAR"H& ^y^(ˠNDcWDܠ@wgP BD>pPA'AC&By/$Q 7(ԚweP(!ɠ=![(:%$ (| DܠPkށA<Ϡ@wؠ  dD<ˠܒ(0;AC>yޡd(uDVBTCϠ DA ! bP(! B  QՠPB!֠(uWO h42'DAD/Q ;A 1($;A<0fP$%Uuc#p۳FcLg3L. Br Xˠ}Ory!A!6`#k&q6jǹ[RVl<6ḫ>0mھGL !s QMj5(ԚweP(!ɠ@w ' 8A 73h=w)CG•ϿAԦ?2q„:f K*@nP5ˠPB!A<֠&+z@wJO5?[u2T7ƘS8{n k[>z3?}9A<  yBBV |8A%Ϟb;_}Bu…b-̠>E/|?OgΜ\__xQX Ǒ "l*xIJ;3( ! o (Q9q91HFы52뒿u3,F`ݻtVnE?1$T>vg#  8A uq(n(jP(!ƠEīU2jg̪֞.6ݫ*iz5g?zhphC`%pe dX GFGZJ`>4CyށAּ 1($;x rF8A 8Q|_pTv]rNn3wЧ״-ʂ C00;~${u -Q1(ԚweP y|DA o6ؾ?xV,]G@c,*664V& V> \<D(jP ;AC&y!(rrr$' 0(Dq!+WتUu}TZG~~puyN΋4 QM¿끑A< B y|Z (t:͉__k+5?yVuy WN="H(oAB%r# /9N`gP ;bPp6 J,QB>ĠjS\Qy׉[޴dH.?tPMM y__AģP<&   Pr9NQP ?~i݋V4cYA'L8^w%VEt(ˠPkA bn((DܠPq!A% 3g΄Xrmے\mm-xL̯@@weP ;AnBּ!Q 2BӁz뛚lk}-"kHZ y1(^C QBhQށA!UA^cHZ y^rΠ@wxlPHEbP BD>X@nP ;2(TwdP ;|cPp%" bP(| Pc y^Z y %rB 8!AAEx y^'|L (#D<ˠ@wB7y2(| 9B6(|w(0;3(! "H Qՠ@weP('2(ȉyށA!GLHnIN y^ y$B(Ϡ(z ( 2! ι 1(& ,G=HKx y rB yI=| ^(ˠ@w`gP ;2(qDܠ@wdP 򁸉yށA<ˠĠ0PQ`w`gP4DHnIEj5(xJ;2(>  BDQՠ@weP(!ˠ@w ' yvy! "H@nP ;2( Z Q8F y^;yށ֠(jP 4(ECCCrrrllƍn ` ]Fy^;yށA@nP(!A!(m۶jժ0KXXXZZ^B! "DQށA<Π@weP A<0+ՠH= (bܹӦM2 Q$ y^/BNB|EKPH}Wo (\.t>[h2:5 IQ 7(x y Z Q8֠E;Fg' (:d٩}/z>pQ'N`! */yށAByrB&PA! 'iP@jm8gO \P?l.رʇk֤M>bwBیA 2se(<(ԚweP ;3(ԚwePdee% >A (Q8QUEUTP"äkBkF7I23/8C:0&niI04HB|:LER8NbIa;X-ɖc;I'/[$۱ݻwv}^=y#N{{{?kisaoSq(S QwP[P AD.(d; "7xNi55-Z{g6waǿ}Ν8m84|ӝzEX$jEDPlU)[8GcfZdz΃M/-%( 9DAWABmA!?#DAQtw9WԎɯ]+gfΜYQQ΍#I9זzjO7b1=Zv*1h BUAwp "t@w}GP߹K0hoh59+?| ~}>lםpn0b 9Í(x"sq=L/5?Nd#*#@z;Q p A!I!HPw (% E^[cǎ_4Ljuu=s桇g͚pJvn/٧r#yyɜ )փ>53UvX#ˆ\BCP-(:SZSy,XOTUUmذ붉8DQ[>[Ղ Da(BOl}GII԰Ez(%(q "DPUP QLԎmͧ/^ZQQކ###Kgx Q.i5yeZIF8Xvjѕ$  }8Aw E^ I{ 6>H/($xDAWABmAQX"Q A"ľ#/Qhnnf8vZvL((}$'cR 2 EDA'Q p A'p Up; #,(,D{ } AjQ(HPD(%(d; CA%QAPQP"O;HPw}TrEtB' q%("ƉȈ\P:qM'HP-(;$ \} A!0BDAp\PwDPwDFIu/CgFG&>:r?_Dm#}gLM^E %(AQxQ 7N =--E/o|MkV usnD{B$ D} IA_PHE$("nDqiۯ˴\ym絒 ҾESO{.FDAǛ($($; ȋlO#OZS;ߡpvu W7k7{u놇" =Dw8NPE}TD.(.A1'Q>u'wn?q[_닧NݟnHl嬙l:<<F) Q*(T; ;Dt %( ;܈6Fmkv oJڴŞg}[υ(+(;97`>NwE " R{퓱*=uעEn%~ED; {%W)`PUPx߁KPqÍ(X=^#&6X5c//bܹskkkbg+{Qm]IԱ A; } AqAlQ/^Z󡫞̧1cѢE 'oHaD.(j CCqD; # >CCClߨ^dB#)}40XD.(\B%(ED;BDan;^omx9w D}.Ap!HP!xD.(b›( (} Aw"I"n* " Jax߁KPx߁KPDwD(T}:Aw}GD/(Il"ܾM;p @8ABHA!-Q(,(" J4O%(d;p #JA%Q(,(" TA\B;r $((('Q ;p ;p 7(E PXPs?Vhy-ݼD{x߁KPx߁KPwI\b(-h37CwQP (T}:Awwx>ukEDAD; ;&(D=({RJD.(\"NQPHE Q0l`o9sWbwK݁Z(႘b ś(x߁KPw}M 0A(ӦMӲSQd}LQ?a%(BAP ?DC# ;PKg5!JS Ac}mdH%)` D}.Aw}.A'SDP% ' UYa|d,fE. X9>x߁KPx߁KPwC\b7x15o;v)mtTc߯idABWiNh4\ʑ XP߅%@'(\J\Û(E9x0Ⱦ}={Rؑ:: l=>󑫅AuW?DA!KD; ;B&+֌x1MPDwx>Οd7߼tqwHe+ bm:'# #SR$Q $(d; 7IWش\feb‚Jݛv%vL}eKCkk+(lh`'\[BKJ|: #S$ pAw2x!xD޸:֌~}ZK xAA##at08_>qӣ_Ap~ 7W! D}.A!C߁KPFD8%"^˚ɋZHAP 7F 19D%(t%(D1NjF08fW{?d-$ pA'p#"CDAN}.Aw}.A! {`-1aĹ{fZw8ADA @'(\K9"6:lX D(T}:Aw}Ga(GF_0wY3ڷfo-f' c D\PE A!Cp# cʦv6U$&b ' P1\P }.Aw&(܈a"׽n9O|߷BaAw+((($(Q ;p \%(^vK_#'6gԺO!5񾑛e-VQ&QP(%(t%( ;<;gYl=ִECpb 3cArwFdw1 Arw; p AYAvGI/y҆?N" 8(DD AN S; ; &'_Fؗ # A'HP t?N" 8ABڂ(^Pwbt^6ﳦMwx.Aj߁KP$(}.A'HPwD,(<]VͳuZ~ 2 U\ A;p \YPx_gSV¦ܘđP ANPE A!C߁KPw8A'܈a"V4WlJMG7àDA;p A'HPwE(}Q0l`rS͉ͪ4%:33zA'HPw2}.AwE}Q0l`Pٔ`SӚ[Q w8ABCP%(j ``zk'm]t 9BCP%(q A!CABmAw+(܉b]lVLЩ[g! }.AwP[PE %(qB=AF /e{/Q'(q$} Aj߁KPxABDߑ(O?RD!'p U\BCP%(q Aw ˆW!HPw}8Aw A;Ş={EV(d;  }8Aw A! tQѯ[ˊn97,AP$(d;HPH"(qEP%(T;$Bb͎4T4' x߁KP }.A!C!HPw{KwXP"Q'(T;p @8KPw2xA#t A!NPw2xABC;HP;|E{thUD!'p $} Aw'(\'"b=w;3qxABC;p p AP(XPxZzTmޖ4dXQw}.Ax߁KPwDPwD#(E *NI2 P A!P%(.AwLA(T6uTmޚ5Q  $($} IA A ?DjsB CSI$( EP%(x߁KPDDrs}$OFC$(d;HPHw}.Ax߁KP`;Ŧv * %(x߁KPw}.AjQ QfBEeSD'  t%(T;HPH"(hW41X9)(d}.Aj!NPxABmAw(#(M %(T;HPH"(Aq;p pQ7ZP/( j $} Aw~ՂDAB;HP \%(q;p DQVߒƸP A!C߁KP:Awx߁KP `D8(.Aw x߁KPw}.Aw ?D|c 2*@'(\BվC;p ڂ"(2*[bBAw}:Aw} x߁KP /)G| %(j 'p BMS8>Q 2 8KP} Aw}G~heSQ 2 }.Aw x߁KPbb?$($;p A%(t%(q" Ql(}.Aw}.Aw}.AwH"(EPXPx߁NPx߁KP 2t܈+Me:QN2 ; ;p \%( %(\"N%(d;p w'4TEp }.A!C߁KPx߁NPx(4I]GϳD!'HPw2x߁KPx߁KP ?N%(t%(t%(h/oY A!C߁KPx߁KPx߁KP @B'Ñ;p ;p $(d;p 'N!lol (d}.Aw}.Aw2x߁KPw$2(ZCi=q }.A'HPw2x߁KPDwDLp }.A!C߁KPx߁NPxQQX7\$(d;p \%(t%(P7QѳfGIe9 2x߁NPx߁NPx(}.Aw}.Aw}.AwH.(jQEB%(t%(\"N%(q"APx߁NPx߁KPw}.AVQQ$;p @8AB%(\( \B;p ;p ( \B;p ;p #tA!Q*(\@'(\@'(\BaAw}:Aw}:Aw}"A! Q ; ;p @8AB>0Q 2x߁KP }.Aw"]v"z)%(\"N%(d;p ;|Ey}kDAB;p \%(t%("t$(d;p \%(q'HPw^D1xf{w( (T}.Aw8AB;p CA(00'/Q (q }8Aj߁KP$(}.A(;HP-(\"N%( ;"9xz[(x A!NP$(}.A!C߁KPQ% \"N%(d; p A!C!(HP}.A!C߁KPx!NPw}G1‹(NVmMVoK%(d; p A!C!NPw}Gdƒ(: `.Q p A!C!NPw} x!K>[7ҩ;xyQP( BxFe _$ kDcU(Qj# 8P( "oDр\P( B#,С!8:NDAP( gt?b(ڈ(( BA+6'd1EJP( (*6gEN3QP( B" BP(" 65!P( ?ihcCDAP( DqtBP(JI**!xq5P( 7ct2uc /\[V6d]'q\ b|Dmu[xiڒMS[bǃP( Ed1n\MOm5+# i? ؟m.1d)UP(qEꂊ|Dk;QM/g˔LkR'flmq^!s sp"was/ /Km}S:|b'|j%^kџ \I=YؕFU 2E('s b?y!_Y7{JmN϶rNGHs9yv|/ʻ<5CQm:߹A٠YP( (th=Lci-={g}4y$'r©sv۾0mssݞZqV<;NnsO^Df'( e0OCSbiYqv.lW`DV9YT.+e5+yppBPnD"Q'ysq#! ێ8,l]6~}6H`ܨ܈%<\ 8ܞpg6u1Skh>DwpvK3pS)Il:vYy|3Cmã72cc؄t1y?fS]k~ msp_;N7{. =xN0É}MXTL.4Z^ZOKYA}6γL݁gFYsa-;5arS͉ʦے5ۺjw޽zGjNgH96/zVe[X`k-[;ْ-ZՔgsfVfMʬ07ZC33LY},rf9?5ׁ[g4u'ȞfV]f;$ ayw>lUUOrՖ02gLw2 4uc&}*/텳jcm98>/:էSkY7e#yn [*ZWnj[<]GI9MfN+jgo|Э~0^SPw L+nD!^q`Gǟ6q|ersןadaܰHsEP~k7wTlla߮O)PI> stream x׳$ugE)WJbu:`Pz#E@,A@Y,A X;~zjSfwNfU׽sg4t㋎ꬬy~y2뺮_<}HazK_y7/]򍷯ko|&z |_t5Y7zd޹NVE s.[ꍷ._{._;wkrk#|7.]{7!$.]'|.!5. s+OW_E^e.p\Tx)/k^ʍq'{+_|]Tj~N^W.y_`!GpexKtd޸h|f o|__K߾x BWO[  R79eZy۾SW4ZrDum ^Fr+ni̡kOXޫ!tL7d'4x-'d*5)i 5]C9K޼|-q9ٰg_KWn.I=Ҳ A_$˯'Ր}.O=gӟ<۰H3~zf'=k}Zirڿq'rN:@˧p#/, '?I,F̏Ӵ}v{ҵnv}so鏼7d>i &2gg.̏up~_g_GEE%Xn+ۄ"MNlE[~7R=_K yu߰G gtF-w@c띱љ v-g$alm4wӥgN ӛZ՟ك38pGAwtyQo/4{|pQoFy_{S5}hBNcwt䌎ٟ޴ݝ4MuWm9*Li/QZNeףxi'U*т,fsJ4SOwSxq3VϭeVw7w7bw"ZYHJNI=@ _ _9|O{i伿ػ뱻PV OB釨yfhy)k5Rj UsPzvb#&^>ڈ^zɃݏ|to(O\DmI^n#^N+B+UnΤٙsw4oUwV5kR5uhȟ$O5;ӆ;x IT'}q$t|͟D2cphBC{xd!?#tWG+cp&T3#Tf:+7\,#N} k7!}F,&+{)N/I%[NɩYFc ѡ5Wgth &m\7rVۉB=&˛zyq/uU/[ˉkyc)Yu԰2VD2F$G=a'u"ɝ(Nڈ?^Zݿ`-YL{m'D z[԰"Zi?HکSB-IV.դz5@fnT ΐI;ս[=:厡cq39}0ʹE,J9ٛ-y ջ3`iP+K>)z_~LMof` n;#̏GD83G^`x|wmg|Y<p.Υ3> +D6;>33j^]w J3YR0bVPf|/o^_|WɭBnDnjm7C_4{J,zc ` I]„"lТװz^8!l!"yB݉vof wHA:#40?Ciw= A_[ޜR*pJaLx.Khۆ5P^Msu-SV~o` J1boDNFsD`9Ty7a,i9mb#1z1vf 6˹FOb̬6ŭi38B̾E M)HH&듡 ?yayfT#)0o>fиDݧ#D)7|.fDsxx[CE,AM3rhs/Q܉)lE>#!~}pEC/@DɰRA=|:)2X"_ =E~+^M"Y5^lfT8L2p?Ǡ6NA &1 [QXs8&Cu+@F3o:F՜QQڃ|k*Em"1EE\J(1q?NxܲI[y7u.뙪^Vht%1'(s(C_;[n%VNa&6ukЄkSL$iP4 Ð.B+#L=FS+#*х <hI0 Ih8t޸I·Cah?_ i`CHE2I$ ?9w3>&|`v|{u{vS(0(cg:T.F1#]fH_+Jh+.Yn?HwpecJlM/6lX{e8`yD1-} i6ڲ+MҴFi1ם@sPf9RtYa3i8;6<{awxC''"M{RG=@H0~FkukuO\눹h1aW"H=='#I*-2 wVZ(ԅt))IW,c9!9. +OE%r"F!/Ӱp!_ T;nZj/)G|oƐr%PiŜQ5Hx%ghR3RU'tj7["-c%U(Ҟ[6#:\kB ~G'NH3N 894-Z۩4b݀ȧZ0cvCM.^c|M1~$;Բ8%B+%h؆͙YwbB %"* b "EcP(eymi".zmk=AMԥƬCk(B"ı"!5},%!(lt a, `N#,? ) pJoK-  %袩4U#Ȭ6jzQ1Ju:P]cƫpfd+*ZֆDO*#!O;5jR_8ŧET-jS<ݜf4) ƱAτH["mgI 3("FX(eRRJKUtR`0/ I]ٙ16 )wv VHkxz \M6#R2+Y5VV112gHOݢ ѯ} M!=8v/8ȾIoC9P|h=&MV,5 d45\2ۘR=9Ga3Zax.|X2}Z(Xid+zNIx)tH3'^l ,J7-UW>9}K2Ƒ0p3 5ȥx35= KZ)W+Fmp>Ցea^ xD@0-UK/*71>eh7Ecy5FfLBHrdg҄j{THȾ<:m{+aU[N_|k Q{0y• WnGS JZNB}feT.hDsdBv cXumŌa1z0Mm.\ggnPC@avVwDbpB)PF[Dc1P-eQnO͈n]uU k'HQ'?]KFaNIyDK}\jS族|{s'XoPx@?ޕ!@|^A53 S3[ht+R ;!c٫)~}7ڸWSd[v֮r?%[nNϷcG Mx8XYLU H0d BSV1(2 zɱ+T />93<[m"&`iBfn=K<Ԗ DN\Fg*HcKu4iP7sh 0pdnHn),J$̢NՔ0F<>(6c|FnG0ƤжY\#bhY ȃ.5sؠ1KeסpE8Ц;"k5Q8KKZ(+NӢECR&tz !yX,`Fh<:J UltJ"Ȧ=/z`x ݋ݘ>cTN!ꚣ 0;-+A6X~wSc:Am ̘4o 5#t܎ڝ(^ۑV, }H74ū'w@h#Iݼn ^)$^%%*X>1cE.D"V ™hLՐ2o?gI Ƴ o\}%ɤ0d- -WEmgoӉbUmY}9&.37/3ܝ?^YQu@G_Zy'y@Bi'&b6TK++_(2*T\o_\vUUAQmJ"=?{anSmz++AʠJ¢mSeNeb3~}ek- GWiMM:)@%\ɐpEA @%D+hЅ55&S_ƌ%c[d0fm4AðA,zV`7\I" yrVij@DDڲ ،hӿZ[?,+m{(60DϦ)ÌpCϿJ?++/<ΘY&~j[ǿRjs/|JPXk"#|1PG]}ҏ$5 L)G~^V^x?KA N+`!q 8}&O˜nOQ^ĵ5Ǵ)=䧵 ;'_X~\1SlzZoJe1bDIHBDssygk{s3ՖsvOwOx>0E_]0c =yV㎧/%Lh|B_ PȬx*_Y[JLc?V$n-z/G/?”T ۛ9gr_VFg0Vͮ]^ys@B![-`˂d+9K.hy;Blw&NMtȦ J4zpACpBL×Jj`扬nÜMfW~6qB{gH#qrgSҙ`,jq(gTDR sK4gF34i XF€ "ל%pRE) ?N٨MsR6dgz<*iir42f/VXE qAwI +Q6j]A sfG &*XιlU'g~]w63Rɢl8Xн*I7V8O"yo,O  QV1 :2 Lq*-Bq}@؄ -3Du{H= [>u*<⟙jLm,֬?h>˿wi@"PM.}>L%7.^oyWj:$ƒ1CC"vqǣczoU_?-uprnycθWN1Pu{ d~#jÏ~cHY\ӄ8m;@\e)ScI7qWS)ej?9<C:_1$ŇC{B(sa"ȿcc]74磗]Sx#?|Ҟ_\oW1f:Ta*˯8߿췒ן~c{^y%}/m1wp}Emy~ pєlF|f+>-\YM:S~輹V,loޘ߼>A1yca{j}`c3L⁄.kkf֯ά_N 4{Mm0S$O`- lJLFTԢ N0tYqd2X1iĊh5ElNI |1irB#28Ѽ#*BYT?"֡trs+&I=pLp()gdi%"}<5.!ĥ/pϬ`r z{\0cl:s1\rF|֙XtWl厮K*]2-ka89Paz41J6w!`D0fc\%Ƙ!>!hqw:1&p2r1b9 [@uHy@%.r*Y$֖Fw3B!)XP/y 50ͨYMаG–rP&]'79Q:DC:a0Fְ%b]aF1fPӛpWUDu?0c`+/200C[*A)E 81 ` \0u8|sB F" ?.c(ٳ>]*hT9Y|w[gU ϯO1JF%Qp1}{ƒ|b;k[B=S9*lńHPBT)[n֩JG۰bNo'㞁b'JN|ڗh>W}V<̗jP3Jya1b`VkFOW[j+yT\}1na4L\D*ńCu3OՌq \ )p \zf(7l1%%%EV/N<_3jREϟaèHȧy@ytPF2WO:~x"~?yC2 p6[,0hƀW-t$8%4CĞظ_á00;1!oa ec膬oŒ #Qog0 Tg#Xnoe$>_\ |XqйB hTN_ˑ[Lu51*|Q ާ#^ tg+Xg]//N.|>}+υoy/\Om? i;&V:1^%5J D6\H W sgxi EcBk"p!+F@٧vT k42֩qk޲S[tn/2\Yav0#zShuq# FՏY3iƒOL!X%&bDLa{2fSE%?G0\¿؊"Ky:ń zЄ.7㶩 wF"+uG xٟls$e p1C11b V.KWc/qʞ?]TY;cHjOVcD50F(K8#xy行5("?kE'R1ehW) ,m9]ntSG?@LU-Õ\P!*ζCJ޻~Ni !,]Q[U:zRӕQ>Qrf[UYCo6cms0K# ԔmL:QFi7O߅+i]; {g9Hg _U©"̜0ʟ`D;v4lD2X.Ͼu1JyVgO=Wq%WR̻{ྜྷq=ۙtJ[.ΎW"1]pW,_ 1,fnjhǾ7%jJs b}lI:^I QxgK<ٝJ) ( @\fKumՄWFhVU4mp|bۜoxnZ΁%~MҀO!/ET_WYʍ" `jt aA ˮcxj >5\pz+fSY'z{Wr-ldOBP޶VΧ/'ЃfLnOԄsB{l jդXS, _ԺjXi)oC1xe7\2xs=XYomnƾ\ >8]^] \Y \8SF y\ݒ~<9eDaǨ1Ƞr2Ud&ȧke LltX{8C㉘~pm,w ) `9. ,dUlDdf]^^XM=tgJtA+;f *qr,ovjw|BsnQPlbO[P)*a\U;lmMŖF{lZ(\2L3cLƨQlrUf qqR@rtU g*sKWn(`&!hu16Èc4tCϬ:ù5LEZB5ξo{pQ;.$IbT|,iߦ{~rt8&TNCzz4gӌT!bI+aԢa͵*s&]CeTRS̓He1A)EYUjTiNzȞ J-:'37|Èp59 ѹx&cPOђ~e`K1\UAQIÝULMٯ1߅k@u=z>eao ywF0ޭPKzT >BkK $ukvͷG5BN0yvo? ]UY;`͵ӍO.OX6{{Qjl-42^\UGT eڭsRؤB_mv۰٬ZǗm8NYbxDb8TVu@OEiϱfhwYSփxRB7~Z*j[/x(GȵqdOf帪4wt亏1׸nT𚥼FJ}AVՍE-8|ZbR0?სb9C0lc˃HvhQ bNBUT=, SJ2Pړ Zlc ^ZD=4Xm^frb&Gt/] ٓ#IY+]{&Ux ኏(?V8GRFhλ-Y" ZYx1J:Jű Crll{i)2HeD+Ogyѽ0٪2.c:@mWʐ*R[qp_-JQwgV>wϰ>NΈz[{s{;w?p Hg?ysHYt1Jo?]:}^C֙ E%NOԩ3y4Ûo[^~.]BoC^|ka=[nsUaF?  (WZkO#f' O*Տpl9`.m K )sTjvT=rwڿ7e$paot3 xpO}ZiAi_)]|Vs1w bSމJW^h\Y+tA`k9FsQ{ !aƮQgV:!3w:jm02QIcX_ߜG$W5q1!Q 5D3b~ |XCDۡ|ӵq0 $j`{&`Z0!vCȨˑn, k"'lO 0XnnӢ#Ǵ(Ƹ zҦIg,8⃓z]=-jR4O;V2\O萁)T+G&y{X(X=0s%vqXgIǯİD0FF#{LjT,216٭<U@Zta &\ׄ/ ˚1&c~k=$asC=bb1{0I~5T!vQgϳB=b3TTE.m% =w߽R*դQY+*ū;FwDc& QDp6V ix$^a&>BamYkJ{(ax '!A۾IEð% aʴş{C:I5;=00P[N֣j=@ 8G52 c%ec|F,aQݲG8)֑ x$&`l眽4L uUm7>Q *3ɤVC$tFae%"Nv0* Ɛ F{?o cL=*e}GK?]ʑΚ.P]&loL**GB]=in f $^V d#g)Yj0 180qq NRp 3ud`VWI$aV ˈ`Y;ZӢb Z*"R=<P,jX+810BGE4Jk(-l_&K34fTq23{_O2P1SԘKV2쒿G[04%S34QGώeMX/nyTbvݢТ̡CУ;1f >vul ѽH:tƣl 5v U>7"!4W@mmxjF' jNxh90ېKR5k0B-SFW't>m=J:qcf0XTB%\9aacGub0Ǟ? avdb}K FmO!=x#&_ź*>0W}`]jo(Y8%K0d[}19 x1BpU9(״ -)GOgmPoC9ٟ t=BA0 R 1ф Wq;T7a&@D7{8.tP hGN:g92{4C1,q%\S:NES'٬n VI`{{sa"Ҝf)zAT  -z5P٨dU1#]U!#^[C4Kԙ,O`[hF3#`wf,O0Ns] WƗvOJŒN"[|Ը315yLo qVe-0iɿk8֍pc~3q ;wtK(; btU!-9'Y(ې5\o Mp'*Z@ԓȴeTsqsc;qݯcu7ŲeI!E"(MT!#$zҗv}ٝ]`wX$% 3w<̽f;ɏ2eJ#9duC%dw 9P:A UZ`Hr0J0艀<>!,'vD8啺(vgÐcpYgVIP\1B*q2DL~p ;rW"\WO,f-P0S#(C!jWс#^/TZ`=hAC,GǘѐDc?nTΒӠ9JщТ]c(J_]+5Qk2Ef`ElkQGd 5Sf(GcdezTz`X.!GL(Wʌ< p=g_AшO{ڊO%OC@LfຆU#R$BP)+bhM91Azʐ0Tu\TUz U]JD1h zD57CY̩;A;B63W  2T>"ə@^tRCQѓeZbTYuT)zgǗ}vsc,k|G_ֆ~ (!?W/'E+ w`I|j@[͕S|5ݪF{b B] $<},Y=.SbOfןUYxQrdYBW#I^UEJP8$ֲPdAqGt ]\`k_W @KgBID 1WSLA$4&)]Ej8r\ٜ$zC U'F75iVCi%*X1n':gVv(k5Ci éʱeOX;פoRP 3 rc}}mJlWj:xuRl2!֢\qkEbs4&3sODhRf(7-JBzzBzfٟC?1@l19WUehquP+_p7( |BVP Uo\@MddqJM~MoFo){A1/&J.-/Rg[,SU5Ӯ.JG8r6Qi;V!OjԔ5 ^uy|c׮1 K#61~րrWG&mmͭYژZ36m66E`ml tc+NY#ؾ=LY6ͬmp "Ǯ++V涵^"Oם?iԙ?'sR?'ģz04ny&Jzz<}?qߩ[sOʇWD0HZ\W Gv=J]Qț yW|RM0KLդ9 #!ܑ%& !|KK t` *4WdKAcX/*fhdJ142Hsv3s 9@0l 4zn'1nCSr|n/nzfA<9@ 4+@ZjT1G3 Ϛmsc`ڎufcO$bYqEoԞpVhz#Y+lJϨff$5 @6㫭;%oCLe3fV'esrAIr=GJI8+ T^n7úԏ<- 3+[}/ZH 0fxjF=,@%TQrj g>URB/Oo:ח8/;#O dh _"f@`lzhRA~D kMh rviۣq*S*wYiU_N-'ʙMlg*0k\E꘩8N]]~ g(VBbyd+/ ĺrbCH<,n6u9`````QdP+ 0>r@"k¿6O2.2 m"_r_WZMtha````Id_49TQ2._ ͽ-JF&$;v;z%**Xnѵm{TPfjaUpszȵ8hg\mi\[enJS'ǹja=(5ƊKiYqmz#]FUKal.N10|#w&[㽠%j(互ŘPjhb ϰ~p7n  MX|TgbXWfݣb.3+\ 1$>P"-IE J&֒ɹ9 @6 )S 0D63* -1c1cL3Z?IA&ڷ[ 's1c1iM-v݊ 좵wbrB})1Y1c7ض *r5 -@`L- jsKj{!rK^gR}#2b =.lK9BkM|+8vnrZC_cѕm-@mCSeumIYn+f1TkuNӷtm_*ĺx43yd7q`` nj}I' h0%a@p*WvzV&r1o2xc:q-gttTL)@~TU22=.Ƿ_Ps.? WUKϸYP]ܾ_im3ӟK,`.Eg~R\wdưWʀGbXkTWFGG8fTs /{jXܽfIgӀuKtuu566656畖B2>>12ks"H ;p!R ?v2AaST9.NJ>okB2#Xhh(Z߱ {Tx>ohlhlokni '/36?J1YsMO<*xԤ%ˎa}}}ZE +,, JJJjjjZII.^LJNN֥hKFh#fAIkDy iaObbbss3Mzu%p2+ b1_bv̨7Eu/o@a}to+p+zk´A}MǛ^ZBH.G POR dNG"y:??ux{~2(W:- {Tfk=Fe^r~~^s<*>0gw}`cc 1Sԍeq1!!VQ=7.ahxd`E 3&ċ/FFF&h^ޮ+t&e=E-‚}*_kz5K̸c0UPL ktw|r__n+x'1_hէY} d2$AՅ;,`ϡG{ r[WB#B%G<==iL,f%5~itEg7|+4 $MSc,---.--,At;MrIW.A>l\AÕ)%$(nXŋck⫩okT!0I)1(t!򉺘[>SF"{J=h=Fث^"ں!Kh]Y zR/ڒ>H@oǣΣѯly45;ԭ.ƈ[ZZ?z)[#z 3x<\cPDR`C~~~ 9u%p]>6&?+߯E~#M6ܠY3 FK_{Y#\}y5o{rr7)0r_]UYkz͈5^tQhպ,6Ik$-=h5*GE!,ٱaI7/X3 `v>}_&& hMͳDR/S^+{Is)X 4-̠涚4ar :ҠʙiQרR$ZkE89${uT] M+O5ȌE@fY.i%Pɓ˗N;_ɐN}7 x̠140z{NSM>y<]\6Ԥ5Ə&.aXIqBaUx͙1d2)0jϟKI0z' wه{{iUn]N1iNЂ l0̢3|a Zh4Ko$,L"T3bGQPxV ccRdOP۫$>…'i^daQܑ„hHc3/Dh/}3@Ak$8$]O\\ҚKX$Ϛ:7?19$ᙱ)FΛy\.\Ч1K5`b"!<][=b*3P`q(|u5 |W#$!ԍy4HGj jۿF?_<{y~rdJ8$Ȅ#b`gm+4G޸Nݘэ^=gk W|z[[ۆBC>55 >"<<ܹsAƀ9;;[kշАx 2"6&&ϚzU~v8|Z%<4(+-,-,M)Zz[L@m[WA4 $.]%*>>}Șɧwcc?ub3iž)>|{[XslhkxDZ ޸M=Omؾo@7qMr$&C==E5cM G6cR#KKe1UFcb]ԙ t(¬{NMA,au tbDvjcWzypN&_ ى!^1^NBh88h&<є X V Ę}ٜY;֩Ny&-w޶x1Ùo;mpmui}j.qk1r+Zp*BW޲244rWn؀꛿RRիW&BKj K+4 -B墛 g}̍uϛxpۆaG75?9>33SD(^\\_X!Yƈmn^[c@BRc@{0Ga4Fzz!]={8g1ݻ]\\v Y>{ჭߞƋ-[nO嚣-:X,!<:6d\ 0\@sv<:6# h!{K88Y#8]yol0:8tdE$C9O<5Y.,,^剫ۚ\&dhkq$QGN 06zԼ{UWNvuZXX014MX1]}SƄ|~L6`h, >yyV3Ӑ` 4 }xQF{_,u%wUaWF6M+(v7;+BD\<'3ܻ6#c mD) EXrї%$#iJd@  $[duLAAAP)ϯ6778pEyEHgAn !⒊2Bc#!,sRZ7 1j'h P$ RA]ۏq)H+>>>$2m>[=ޚn815-|2c፻ ?}bx,;З\ݓ.*> RfI&ܯӧhlD{,|3k**$11_dر*5Xy)IOx4=5P`;]LJH 4.D!09s54PNȇ8!i( 4x/7?up5qYW0)yau^p1\[-҆n_׃;OBhK):&999z#urXX/'''%%.Jc@APMuj *z`54a'6LhS]uYWt]+RԕQЕ|+>KƆbޮMkj [1hTTuh 8eaaaii nŋ!B^. ʼnX0W`ǖwaޒ?;VSR,{%1X히T$ޟMS C`(IIײ[[QJJd2db!w}̅,:l[]S"uef.f[epíѿ8ScX$>#mM9 WеFg{hũRɝF{XV6Vv'NyC$_9mOrBLܑ#G<{Jz5Fooo   Mԗ5WZt"314M!ԡ1F,T, 为͏M͏Ls5P(,8`a }PiQd<=nڴi^^^ZwV=.|Ģd{C)oɵ- 4 Rx}kW^ +>ƹ-vXXXr+yP{g}myID6Nhib>*@QNo1*J",Qcƌ+b܆>(CSO%Gnl9x%3wrסWc^z֭t&ނO꜏'?hРI&A-]ʍ^UYLH]WmAeC Ţ#^)o_$?u i|E̛4to%M+3`vwN/7nMH0wԨ__߅ BڵܹsnݒN d/~I$>WW~I{ශ7EKicN0QB[Y/lJW;3Y>ɓ'hշͯ.Ĵ+H%w},:\Z⢭C; ~Ws.Rug; n ;_JP5111a7HΤ6Aܞ~da# 2yd|vb!c3wZj-#&"NqªWJ31+H*S:'m<4}a=z5 ͇Ĵ|7xCCi2=ɿo{ʾJN}gq{ 0`? 5)))0!%pJ_¿ D0N>.Csh3oL+OYoǏ'''? uGWg}S*Tnl̠1 }ϧ1`}("08 8p/G~Zv)Tz;o?vݽtՎG `Of߃ Yf08n-_#6EFF.?린+Νw3bfϜ=x``{E.-i(g зS֎~unugʚA%NF V{tӋ:t:,-maH-䔔#۷}\8{vΝ6~⃙Ovr ݿ^8zLGy.'/vxNaaaNNp0q_Ңǎ~n_#|9]ꎮ8///(@81 &JUV<'WE1k,h?ƍm`ӦFMu3o] h!꓂lsc;N Aᰓ&^ ?>?qأ7gw1;麺̯p7S{N]NLη-i붝/{ʧ>״龤) ӃySwsJ <J鐯cf/\YKN:omS~8Ĥ&97kiQ;sCVN0a Bsg2ټmWQ>[ݶϺ'>Xj]?IC_2qRę$ǥKg[:"ԩmb`cXa?|1cF9g'OGc "rx L Fla*~ .B0jK?)9\cǎ=z( K`v}ب @0!Q]{Nvv1ٳ!!!Pǎ]-ZT_"RC/>fW= sM|:Gԯfܹs0{0J߼y300'Vz-[̙30[;@Ϝ9p NE`^O-fA?SxM6rӧOLݷo|j31LlB_駟#,xBM40 DН/JJ=0ni͛7as/Up/,L_spzP0L!֤ON1G),MR M* v m5³nvl МhRp,3r>ę, e8sJP7̒l" YJ|gD)ǂY`$lj ڧ_[ 0,(g8:9<9ę8 X> 8`t1 BP(5BP(J !cP( RC( BԐӌ1oV BPP}XBP(C9{%( B$ᄐ1P( r(d 'BP(CQQf]%_D\}e.D@P(ʡ,atcM$%BBRuvKx{/YҎz}̶X.d_LF&( B911I=#"!`s{/Mhc^9M8K\! YBP(c s1xZl( wKRײԶDÑ9&1矟px%wD@P(ʡFưyw"UwOؖX)rHX!q?(xã2$Nyj( B94cpHl˂?ìe;su*ARɘ42td  B[3  ,c>|b_e7wddvTT2Md  Bm(P 1`n^ʌX$Z뺔1N^.lZnYƟ})ƀvBi4Jy-5#G}58W V(uZ\D8؅ĉ={a%߄.|V{*uk$0j :Lŵ_drZӾ flaH/ 2ضsf;` 9 hlQ9\[  %j5$$KdG t-(2E e]weZ>8eЕ?ƛLMudL"Dn7x͌-tQ[!-UAAy[qyU%sI6&XoVfo[ºah} ˛۱K !si[bpk-G_R.j9U}c o}V~9X8;4U9Qjn0x۲3z4b5c 3qGoLߌja n;djs71>cT7Rm)ޖ1KlYq > WB7-2~zb_GYa^05oY,%a}K$cήe\ #IV>: Jd,//_y ;=nReu g9cIٮ׆.@a?z4j5 c2h߸z+8YP L',HP:5&呅M2{[@؊ xAۂZz} Ė%a/N Oniܑ]Oe\-)˱뗳8l(3R6; f A .雒. LdnQ 2Yaɢf]RAwGFbF2i~L{IfIp!WL~j:m،AR10-cPL5x#k5xiqؗ0vor(qoMɝ cīUn~*/ӞBX,`SbD3KCЈ$c>(41:` #:~=$ٙdzM07Ee$HV=hy1XZRtʃ#ķcQz[s% 96u5!Ѷy9~װon$y࢚$swr%22 Rx'Y}aZ)\4'=n2=KcI/sטN ⽛5(yۺd+iƨưg A0:d1cvT ɜT !,&+0SS81X&tϮR{ߖbm9ϕ/(D1ol\ ׻Q¤J31.][Y&sSh+,[I6:. ?rK["{d V^nY<njaSNĉM`ǚ/8g/j]zZ7[o+[e];p6vgaζ*T(-G 5~nhL7Kr,!udz@q=n j5mM"ݧ[eE{˚\%q'WkcC(dBy󮚾9Z!?m|@֚sFsl6==)1ݖbqgll`ӔrZY6V;ʓ'#ٌy'Wkcc2Fcfvxk/< ow~WOLlpk&.?xkfNo Z{0㍀Kƽb@bbB ZLJlx)ןS@i'VVG $1 yQ18oTؼ=RX)VVcT/4X fmQn+VVG $u f(e  BP[1b(ư`R c0000000s2FUcztŋ?o6}d2$ Nv)fKYam#Aɴc#'c2`*IC1DKW#oZ6[ɒdW9/ >Gߟ#2vk׮ ¼|'=4b1f Lh]!$1wj:nEoFj"+Md/?FI˅<2)ZΩûv86m~dҥ0XGmey{oK63QKóC1FьQ~2ؿW16vd\`ٿb[7\X90軟 Jn=c!CG f4(!SO>dyOoY?~a׭;m:4kUov'9+( @~љuLB É@#޲8l_TgW}YO*~V~+?5VQƨ-(3c c2S7w;A]!yȻ'w~>w>]]ow*׺&o[k!-OFmjtp>ǐ??W|eQՠ٥}&wI_ŵn } ZL%M0+z%3Z9DoFrEM&G^nX_Ҷ' 5S `|حMtKGH zѝ,, ..C0zVt| ^tF^I_' X]qYVOk)[oX˾oTk@peGNl^JXUUB{VbY26:ʘTܷ0F2 KeOf;gf#t%ܛNKOMO.>lݡ&1g. ;6%A|y/ *u"c<)/dtuCoG]ZzN$'1[$4&Sєd} \xCp.l%ޢHDC``8gwgҞg w8Vd?ZB;]=S.|З=(Wp2:.c{\"%I wV| 1cUv*((3:OZq .ïn{SK^X|yw_436Ήon2]2=x@jRIyRK O\᷃Am.x輶=~񀤏\'ο-_~x|4@1`$ep2$} v7Hcpʐ.;!wpN%vjNc3(v6/YpmK`l d$֨+ N 2A_9ݾH*>P8_2_fӮZ&P[RMgL،Qd41Q1 ***ضmۣlyܲ@}ݩ^i WLs&S;b&RqF$b~df2E=T2EթhϫķμW[{KՑt#+q7`aUp0]W5h[/"*F)v$Ve7D#o^^Y$U'/W"vBhB`zV+T~Ws5h1:ƌcus?{q]]݃k0yK::y}K=% L9gM:b$+cDH9 ϾcO=2y籍i7>8g~acE|ȕ(b =H( Em.@uKxvwz%zԬëH֋I ͩIբ &/>*PԀ@in5BTIֻZes 2ZUcdUfWcHlXG]ǃȷ{SKjjjd Er#;t1XϜ+cŴCGw|"#=S_!*jScAfrCލHþ͝z+ۀe Hr9ğ41\RY7r֜.Z#e6joG`rj: gW9'мC^c_ڍZ=zW+o!.5V ,2fWSVFc8 %QsX{/&ƈ/^bf23>5Hyb8Foj /}RwlZ ,1h1ITtC9\,!4*C1ʫ +TƤJ1d=:)EQ?Eه'EQo7~o \hm_6{'G\b؈WGޗ8xӎR9X^wc`4>&#%c4\`{^IqyUB#1)1ǀ~s/ND(n!݂ȿX-\'CH^ԝz(Gb=D 70000006$#<^ŕUlP\ =.~Ŕ ۨ >, 2?63M6#BK0000000&c_ 0݂2 36c(O Fba+05 ݗ:%%*٪T"lU(Ql)QlȖAH eVl)Ql(Qle)Qle]%J;JDlݔT%![)J,[IJt]V]%"[(^\1֟1J32W3|PCcC>`(b 1 E01|Pj"ƐC>`(b 5Cc E011"ƐC PCc E!a(01)3jM E&R@C`0Phb8 1r% f14714ϒ@Ľ,=tҥJ^51ifLG?}ͭ*MVUPgi%EN)I<貅Ctgac;GmC1jTPauYՀaPswq޽|-hOxٓc}fLӥJ3R4ΚϘ&MEJӫέfL5VE+n يUD\!zWphP4xм&8 5F$w\t+f-QQTEYQ^Ur, 0JJJ0hwh<=)-i3n8$Ԧtv<Ԇ&A*:DdPA%+qA  -M01Cof#c- cԚÂe$4cp/HMMMNNNOd88[UO4a4[1)\8aqOE^%#[QhlRwaophPtҼ!sVCCsC`(b $#=c@a ͳ$nbb#///'''###--͛IIIЄ^(`FLO-8jꍨIRcDAiPHيPGە(\ekmQA'ڤ~' U9JF`g̠Ӡ݌ˬMdbcdUeZ1ҕ&ᄌ}vJJJbb"T@LВa(Q4Ψ^Wb+LmT hSGkek:Z-[J% UG+dkjZ&[?(buH\. t@`aHhCԩSgΜace@= KpV0 032NgI 0h#99Ĺs.-*`a6 ̟?ܹSډQQuuLATBB@FM ;*aNE9\+`akFQj(在 u:~gt 5k流&gj]X(v ^lfڵƌX_Uc4CcP1` eILmbdee&&&B 7m-6-_ZPm7͑Wu#ʔ\cr}dCTБ]ebQv-,Q J2Qr5 0$܁(Ž4"v\D15 s8'L1%hU)k$m5:,K\ bR"ts)d_HŴ ien]zVٛ3EJwzA㉹ǯ\9sJY/g#mAd"qqL:eo52qqI,ljM'} ^*q?> 3ϲCS{ U7W5.SqTϢ+8vP rbr_{Zީy$N*8l)݀(<yp[׹gM;N2mf9zXlӲ6;qKXyY"mˎe9-Q^DZRM$E$@B$]Jι瞻$mɲlo8W{B?|wΑi aex8ݜL4Ez8dK!KdlySgl:fC+T GuUcuUD]e2]WGNbד#$Pwl*3ucHexeV?LvÕɉٲOB3?ǎ=uٳgY'hq6Q19 cffLw!c#Ͳ F(u:O&piiW}Oœ\`("hC1GϺǴĀbUqF19Lt;2a0#A ;(PPcgA0a9K05Hqv h ycf O1BDpJ`nNt_d;GL+}a8HpgKqn z7}i5; * u3ؙk֠l싩p3&hb*zhi9lpUBaӨ+3(4ڸ+fqq&os@͐4#-4N6]fM1dedK5 Y( 11_yV U WTUWJJWdTeB"[ 5SUǪF*+1K\ \O7 SehƦMX4Ǐohh`(<,AE##=dt :ƲBR_ Hh4n7|Ng߾ˣKL-oR i= `n41p4xqEDr HX02&qدGaWgd  .^F`{$?n..103"GDEՏ0""F?[<]#NwÕ;H;Jچ\Z^C4P|_1l1Ty-|`)js*Y 1΀=I"{;7L Ȏ ygW_?+?q߾} 2ϟ?%jg3Q1h-E3fA-tL}ڎq̓#K"f`b$X, =n>w ER s)EBRܿҌ9f9I_b&ĴJ\E)G%!L2FQ n? kׂ+_ _j./ID`'aVEL kE2a VET O`p?8O|,GR];yѝZNNWCƉNS'Lz60"wCHup]gWx37J^p&ۜIGN 4jc,' nIi4ihPd͈f(h e 1 h%1Y3,nf Q3P-XVf8FAHs߽9xcÄ{#eo+({#7ȮT"l=ɲ]ɲ7eoވ]vvv{v{v$? Wc㎑M't7y۷o~ȑ#555*͕% u0]c;c\ U͒(D",QVyW_}c_5vA.&"*QO-(̇2H 8P3G KL =$q>8\ ^]0`z!2Oih1u0HUUI̊Ԉ >;20.J-0,sPpr0u~,ei{ENS&#ݍ`ѐXI@׌ZRfjMKeڛ|avz{* J?qV}pǰjF8iHRmC 7ӰɦhF?JYf14C/iXP ftk4F(iXozO^+CJPbd;g2~FOj6SPi)oi@K<;Kʨ(L3O=!A<6". P'C6#"h#3nAlE aa-UD݈R͗JO?辢.Y8-qHY3ׇmz]ho'ՀMxƤ'zR$:3` |I!hl`MCi(O͠&-vbMÉci5CVGfXGUs3N S(|omqk֞ҭҭ[^<7^4#n ;7EMo7Z@T~7򦡗7 itK_-ݥ[<'jJ1RL0c}ٳbkvh-Q1q~gI> p F +`bGwٶm _q_u _-R/]uhLc>娦3c4Ä֝EE4g"upέ-͐cZ\|+CPuqQѽG`)rzbG ^sDTL8AqJہkWxXcN&J\,uaoYd3*ixƦ=ҸW_*72b2ƭ={:# Cw )IdA#Je1WL"!=QtphE3P3X u:30"rJiL#,L4τRL#h ˚A TԻfPބFa͐jA̗GjI1q ud24i=/^۪WѪێԪ8s?zŷvj-־[nxŘm#A3g9NgJ1FaÆwCUWWwFp1%W$$ ͘vq]19|޺ZZZjkk۷uVB0c1Ÿ1>A `ȎL&h p\)hjjٻw/|Vu!eIcpH L"Mc1LjI+%jhC8l-*Or3#L1#^)21( 1}P5`hF#sWppfNgfҖEE[4Ռ932 8ƺ}}9g"a{ ӌdEE보 d*P D䖺;}1LPD{iR.~.,+ dy(;=~B.)@3  :FAӐ Nk㔢:t Hl"lL+ `cZ\31 M-hiU54ДB7]V?+︵[kWZwrΛyS]7sMo}S7t móЦcz>g3Vq+5p1uu=O?MJKKx㍲>ĉ%ʒ\ FAǸieyO1ydILcoŋϟ޳g͛M04FZQц^[TrymK"be1P^WW4\o+]_y?蜍ic}kt!߇kkj2րxYdS*T~Ci/nQJml+GF@Cv̤G`V<{m_֯^ \ 5}b׼vHǠ8=ئ|MQqFfX A=)vP{}O8?rזR *hVR+V\W\\`QRrR#=/9 d4 VVY;iiP eCu D2 e#Di1fiHih'k\bnu 4"U3`LgliP `@CP#iceٽxE}+N^qz+ί^ѲzEkVtYa]޵߳"V(@hGCvz,p.8cuݯpz^`e=%1c])9c?c\ Ƨ%Y1Ν;WUUo9+ 1wf4j1ThmIbBrSL j;cmw`S'(WBiY6v#ǐ*(h`F\q º}XE6H-1:I?^nP,żL# ֶYYS۟EGz("nk4[ AoBe )Jh؁ b8`zâ Eqd m@ @$o?D!'JEJF!Ge&XE ;F+,ʝLAYެA1l1?ޠO]p p%Gy'1JJJ^uxĸRYŽ1qIh1͸qeIbC]JzX`^ZOc0SL1(iR1vnsYİl->J"ZQsR#*C .8 _4O1Ǡ -18TJXH0JMۊ]qR$dDV2[dǠzx*sN2Dg@]Rf TG<g{Moh{|C:k_\`C?' Y\pƓ5:ڵkcrhQC%cr S5>cRͧ+K'r%,@w i焎w#:0Ȇ#tRdmX1Й:jAq:9o–je!4CgvT].6{"|#fh `x4CY=SOhz1h׳Z}Gm{Î-=ޠO蹍J9?Ocر :/c p 6'89[o /,Z9&|6ɹ%?2J6r/)irZp FJ(D_&2Og ) Ksh$tb* -1N4OI4|5!n]W>YcЀYi` /󸱦&UuTcy (RE)%3rw<`JNHΒZж8vsk>ucĦ\8iFΩ81XJ![1޶%8Gd Mӊ7;E'0Tv~ _TAcM՞UTIGU4/ ρ<؎cjG00barfDU-cS332 蒲!)^8"xhz5qibA'Θ1{MJ͘1ֽbu4AйpSB~rJ&PI#^cM-žfXy[LF/S4AηHZhxHh{l (QfLb 61"(w:K!j$%FuL3 ]I3L;$ƞ40uǛ :VC`?/A0phnL5#1b:V5CLpzC}+o53'}jਗ਼P_mAgg'ADzN73Dpv7䎌jq}eIc1T1 r#č|&$ٌ[9(Wr^OȈB>LNjS2'N!OAl<HM1YeNruq694Nży5kJi@HΩ%(~i~ҬFFliĦ)1#sܮ8JTK04 p h&L3'Z.f#ϝYٵ} PfIA eϤ~r >x:Q0T,P 9 EݖM 6BWQ!*KJJ!@u]4~v:i\4,3gb$XfB!"1H2 Ῥ]?n׾k_7~GoR~~놇Sk GA3gaݟ:g!Kr5:eL|q̓W*KsD"cJ>hN_J|B5 N"_R_ݔ\\$h11za]$]B K^㋳eM؊iEBWFu.SLyj*L&sF̑&Y LBcsHzV*:zgahD|&;I'mi:i9>e:?y~ 6-N$-*1)E0`)3cDO00NX5W3a }Eo'x-u08I?f 361xXkfVgkLC Ͳ<]>ON3Lc wd"[ q>z\-Yy b,]0qIU3$Ǹ11Ic8OYt5 ]kN\f#M%181-b4Ҥ:Ѯ*xϲ UpVjYQ-B/Ccbx\kzs1!53,J hyO0 (*y"BnEWqwN3uY);@k¬8"CUorg4uy;޵xR^`3ޣ'%Hӯ&4m-Gb킧H %K1b3y O{@i/ "U34NY1NhTYS&P5:'WL#)-ުFQ3tAuZP5 GHB?6joD9K;g!q5$w celiƧQdYN% 4|V \ʋ{(@ޓ*/vg$xlawƨ4BN ܌0 O´~Frn86>iL6/7s&~vObN?(Ę3ȋ2];2DĐ ,35r@0O6oכ6_М}U-dJ%H60U|Y]Ano׸|T>CZ|y/g26`L5=W2!*gD.heX@+~ysV7> N9rD%Hb@hÌ= z[r}l^X^_ꝰx'{q$NwOlsāV#4Śy iQ:Up- vMŠGۘзi#. bv:NpT43`]p+G$H-Ki 9`b\?TE-h_j3b͠4$fb1H Auaј9?䶺ՌaXFCp㳐%AsĀG.[c$<nrxKHOba`& x`fXsS c(0šX`X1p(9Đ`O#J}iWi mxo?1Ns=z0T68!40hC/`Lz$>FaL2`t392L3snNa(<oMxv 9ۯaGE48> ;'5@ʹۜL_i$46g4]ZVcl]. 1u!]K2 EKfȦoA,.bJ*6Cי>zAp54OҕheȦ!MM.\fi?Ꭱ( !4;F}}p4cǘ<=c/ cَX@ nAxhAB0?'2-j)?{w'7} eyƀh 6cd 9fHv'@0o/[u[*I%URy=Z%֛Q܉Jxˉ*6(,[b-+s".Ex/2=Lؙ!DozdP׭3 * *pSH1Tbʒ, ͨ5Ta Fy5R]k*5Z-G"ז Td&op7Vu_ ww;㮮 -5KTnU=s- -.p}3-K&1) l|]*06y(7̳6TruLVrmѿ|qX_#rPi J74^+( ݌ ҈54.XTYZ( Z5F71yi *A,cPcJJՊ?TyUFqr0W#,{3%wjWU <]sNCRK+;W-(6j茕. q/CߺRv#ME~q_h˨cLу{" =|-Fjx|=:NMpadzBuݞ$S5ʒ`DƘZO+jHVWbBZ^[,E#W[~{SFŁv£3ee/{wJ5Ygune[xta- eXKc|E12C*_ ̐(5iӧOaVhb1%e `J71ti ?6Sd1"P9PU8S9 Ʋr*@UW(t"lI1a*LW(/@xʹ'^O}R**'\Ԅ}HV咨h9)Sȋp/'務QyOb5~-GHYUP^\UWiŚQ5vU5/{33U3eqq<þ]^3 |E?SE~<ˋM O /T5WhJBjOIj#1 4%QPlr`|W;iUVseR[;ԨrW:e65jpmv׮- >zJP[=zQzgh}̐60$@SUJ3F$YD y3Ѵ0֔&1r1f#1Pd @Z#'4F+LI4kbH"C3Ky f])^b75MMcĨcJ"'Oc@ HKh& 05M $` 1hc\hpJ"tܯDSchJW\Qj!π*ZNI0Xu@SFj ҼÇ%b7|S ckJc䫍OI4kbHcttnc5 ROjcQckJҬ&F('0zC ƀ@ V5!R8rLc”D&FƨylbC1$E㐜)ch&1V71c g+|$ƀ@ գ1ڵQC&S@41nä6F+418%iuܯ-$aX1V1 ` Q;Ơ7,aRu0JhzC@Sf513FJߴI1?15%D).M c\.ic\A$q&)3ԔLc”D&F c$[jnvjbkc=g+~Č2t(cccjXM Ic3F61jC1̡97q1 D#EHd6nb1E718%# 1%T . 9q[(]J<"e {t+RĐ ic :d 0.c@1<1Z0qp3AOLRYYh&|`(5Fx-Jk.Iz-eWkr N3GM&v'_Nx!h0Aƀh1cDuoT M !edJfPyD {C)I"cxD^cE+>˳'҉&6o@A`S\ߜ1 0DˈJf-8)]04HJ <1)3F1tob>%Qd'1drIȹ^Y|Ge3B]=cU ƀh1cUhrJRfo 10ؾkO"[tEs1tobh0%TH*[1 M C1 ZFl!ϐ*C&1"̺B0b_1o# үtՍ̯X>>/q}%chO%chJ"mZXSp5lF=js}U>شu'ٰ<%%cE1Ai1TF41Čذj=v/1nGm.7W'I; +D&J,Sh x} .RXƠcsniba:q~ =nG ٰncknc@EKjwltP$10c&1.t͜{7o DSKi_8dC1ڵDB1|9R`V 'c@Lmck E0Vc<>?2tc eO i)O/؂m!6Kw@M $ :BcD2bDR㲍v1tob7%0}|%)|խ-d썓&/\:ch)bcpDcN2H"c7`J"a^z5H%y,p,Tۗ'Mxzy?sT:` 2Ӛ@_X2KAC6нQߔeg%'RV}:>j/>sw>JMnfev_e);]'y _RzD;Zჯx8x,m1t eD<2ؒOeC0F]ƸM&5M $uC{ "i?7;HہgNdr{O yb1jL]B K0o|!C1 Z1Ɩ} OId/n0Д&F`c\ 1*>,P9Im Cv)ƀhƠQaÇd MIa 1|"D&1з[COqƨ5q] S7=%7)f%0Dˈ72F>cobH#gcA3Czf%4‚1CR&5*R|hiVB)Rey8xއ> ƀh c.F[h 3]bPl /1F6Ԛac0Dˈ#cc tl1"(g ݛOI^YT`C1 ZF>Œ:N*C&`0F IQ2F/^1tobh<%,0-0.c@L c,㡇R71;%6Fd \acV(26" 0FK-#at)5ĄJ0ĔDcchJ&c0DHcDchJcr@ 3FSVhbqJ1ncFG(i f]C)M 9pcvmbT;c@8rbtk~$nǫ6o1ڣQ,32%c1Weh` ݛuOIP"4 T~0F i4FP316aFh&0 g]3B{C)I 90F9}t}1 mhH4l. ͌{)S`Q2F9ua)"co18`1i|ϤZhI2dc@ o\/I4i131M $ gˌHEKchJxc ƈMbEY!dd#χdt Ï$^P4h 7g 2FzD&1煍+cі8i" |>z1d& {Q~\ib ˫7b> 1 m[oM2vgՋ~; O".>^N/ҊMƸ|0f0ДM )cd1r1e`f%1R=X[[0mQ=*'w$?cKA1+A;.SoLyO7'%3O=Ƌ#ۋ9ڎ{~=`Wcw,3 F0cǎ0бM YƠKDƸ#Đ"chc0g|m` 8#R70Ȩ@Y Q)1 m@frӻiq|/:s -A hQŏ:q6 Ս~Mƈ3bHh ݛMTn2=}ݞnWcЍ mU` HG1ʑ:r}㞮K*g|q^>KK{(ۉ43NŒ:jC&L`H##4c~JR10L9eB cT"j\Qa 0+t|cUN.ٰeGckG *! ~1ۗ6TF]DK3MOIj3CO50jbxz;É=ljO>FH}|/ c@:=2~.J?Λ,p 8ŭQzaa#oVd뎋Yf(50ʔD1hf$3$mb(5ƴQ;RUƀqcјit7C1@SE@_IcQ1Hfu_D&1o  0Fi48o̠#o*C)zMƠ 3NYG$gc‹^#a)zM Ƙ$S@41`A2Ɨ_~1Đ633F]TOs&ϿtlHEdaƀ@ mR43Nٛhib2F3F1Ʀ-H"/3劇ٽJWavmbĸ(3 T0 c3̨i>L c!t1enY"Vl@,dCU{CD1~cLXS4S`  RƘYн0j#MԲj%0^ "'{l71T(6F3c @ Df&1;1 =%ex1|t7.xcK>O8sKdCa)"c?~o1d K cƀ@ -"ao'lL53%m ?;6O#*2$u710W` "ľ}0C|Lc>%Ѹ!ix)>&,Si۾E|c>%Ѧ!m/VÚ3eI~1c&h_Wj=o=4zil=

      и!h91c 'f 1$n @ #hƬL+a)Isbx LvO&Votk> 4%iJC1Ck 1 A133@61ȁb#R+o9v4i4e4m4b۞Ĩ6j-c$p1 DTU3s/M,93s"Oݻq+u} lbTf2F1)w$ ƀ@ ]7Ì:jC&L`cCdaٛAˢBؼ3wOz-vmbHC128SCǀ@ KT5MOI$Wܬ+Ԝ+JۺǶ{"E?]TPj3֖Pd ]˱k+j} )nl/5ؘ0ʔDO>Kei[:]x~]<1g IJ)Rcc,SV( 0-a)"c1v>;]'̉qsGcF71cB!_0ƀ@ cQ٦]c\D/q!l"q=.?uebѕVwxk0P"lc a0JcZdҥKjC&)IMc-H!c؎?."]\v` >M60M }$uo!G@ :33cĂнDP Ec_ 2FE}{Ȇu-$(kW1f8B`z_?Ѣc{C7NѢciq1F1Μ91 4%k06ƕE1~؎{>32#c @S"cK1:6? l)hBGgλ觠hEnj\>E3Ta)IM Qc6}}FW. /B[Lϐ 1tHo!.\ "f`i̇43Orc_!HѢcFG.,/Sowwu{ )%[cctl1\~a MIgx#5>yǘXeaub;_IOIibPƸpႠ1.A[0̠3΂']HSۺ~l s[7vې]Sn?oz"7Vf#1K#$+ouw5)kk.=άu[@/)mSڤjRctr18f44!j^Eu\*fÏoGc3+fQĠč188(h\1:61\X"T`Υ M x{O1S_Svum/z{];N1aevj#('o jzh=oNTnɬul'hc04/K}J}COƘ1銡Bx<~n|nWw%[6/T-?3|lj>uOyKг]_J:f c|~'P _y\!}cb{:f0Fdž5:*x0F41$/W!c<6M[ߴڙU7M辫mhdJD]0Fn޴zk7o|Si?ZG~?yKг]>؏n% 1d㞮\)_v]d!z2oD;ڱt]Pj en4~flUнٔ 41f̞wztO7vm@_:Ƕu詮?ax| xUrȆq~yGhц#ɳ1o*?S mKi5ctr`)7ơC0MfMIjc=N cM[ȜneX.N}TnecD1fgg3X2Sw&wG9F?{ _v~:[߯ܐ^޽/y{~? : 1KD/Jh7mشiÆ?{y-oL2y7NfKr87oGթbQVđk\b9X.-2+)QTc @ "%;ͼew;,,~?9ӔO*qbo4KƸg'1`Sf tRI,cm#Cwg~r"M ŵW:{}#٫^WBdDb$ca1h^~{?x)'S_|4[3Fq/5c[c$3FM cϞ5?4^H]cWp\1XS>q;3C?xL}5l@m4KƸg'S<@d\b1ƪ[|wj;BFƘ=D]`M`U@Ew0x{M'f1#1Biyu\X(6QIk4[3Fq/OFy0aCw;Cc̚=gSщ.cWƟ^YD pHz2F^1:%cܫK;h-f ƀZjY2=;`"cL6c8Rb13n i;;+{%cw\C-=C=CC#o?1#.12UICg"SP1C2=;?y֚PQ};S N9ڶm[OO T8pO/GX;1<]b 3X얡`cw.ȞpI]wpkdcwlتcK JM"c#kƀT痌qΓo|-Ctߦpj4)7׾A&58{l .1xTc}oߝ0{ޢl`6o(ڍd B1^}UW<0/0ƺ.ѐ1UK;c0rȑ0a(j* 0c<r#_v JWbTьa|X#C9r%1?ի6p֌#ÑfhhHg ]UV}d 9r1`g\AQbLĩ@C{Χ!c3Fd 9rA1(0wcǎpc8UbG cD9< 9` tPc$cȑ#G(3qDe h~+gϞ#J1b|Eh p{Be䵫L8%cȑ#G10fСC'N1%Jb[ hWk_P5߃ˑ12Ʊc{۷G#{0% U~#1ommƀ4///''>x饗1F@n}oftT*w;=;6ϲ=qnmVSKӯ^ӷ] m H`1rno_x]}A5Z neCp2jgc`s`sp,|f}p@aic3c;0u)ځ_pKEY孌n{c#ܞWN}.mInmޞ@M/ f *c̙K.ݰa0Ɵ/w޻wÇ5a=Ut$+cR~_IKw'{)1cpptuuʲ+W{/wG~e?wj{ fPۋQ{I'+ CM͡–m\E"#ʟG'F_G67-![6mCMP^͍@^5\2)1l \>/T\?{ O3Nԍev'k](v([֑S֞Sm9w#13#-%4c\ƨW#3zQ‡KRrS0@E,c$ta0[?Ka :cQBka ek1fWoOoٲe]>`Gf1K fƘxHS>`$2F 8ϝ;wwygڵ?޷w,k1w 3/ MfNC:f$9f22!`Lb7&Ia0#3 0Ø1˜J ] 3t8y 3L[30&2F0rh*E1F fh`S׺>aFe?G_͍xư I$F*3.|@PO284a'g5b e0`đ003!vqc`a Ee7]o|ɾo{lɒ%psm۶^z7߄[>?8} \RTTdNaސs>*#b{WIH Dg }>hiiNŋpdk˗/0?qM&Lb:chʈ!c$`F$c2-:caULғx0 3bUT1)>TƍI0bSף3:5`/ʪ5$֤qTH%9m'3uaFT1 cF12#1j8H #8h)&p/̊&1fDAEӡCWc13#3|JE1qeX1#a70FxwN~_xl@w27[>l39>gg333ϱL97;y`|4ßt8nc3<O1>|^^eee"ZuH 挡v5wi'ysnqluOH]bLe%1%ڛqiʀ I885̀#}ƻᄏk.#Cf˼gg޴=ok|OUncic`  8nnu8z'ߵ_XXXZZN(A$zD>3wzvc_pOAEOK{K/]ǃ1U&|ڛqiЊ Zpdfz̙Ǐ9rD#??|S̻|>m.>W۳$b0.'0F]N` iDhFNe.axp+<l߾}{MS> |g؞̇>>3LFH86Fc4piq>릉p.,%>8M1< P͵Thc \aϬo7o NZ/f6tnncW,2|>`~\p-Q +P1Νcɓp0|a>lQ9g۞C|923۳ۘal̃u2 u]t8#pᒇW\Y իWHYb04:Ì1^?|cP@h|E|f۟}zɡ<'Wf1&1 s@4f溺:Mh5XVVVXX.F^^^nn..\8o4Y9c{NS$˜3mO@tux}(eRJ4lWEC 8ࠅ4M_-K4c0#%cZu{j[=53.f^vg^gV=iɆHN6C -aM3\.Wcc#FuuuEEpU[\\ q:FMj{Y l{X&\3m1ϩR&.L\j5GM&DRNjѦOp ihGF $p%C,2Ɗgllh ΘuͧՏ}RW D&]b VL4fx<]]]@---@UUU0ڵtp2)=%|elO@gB&,τ 0ЙpI |_8pZ b8hW_EF|_ݣmc82F02D@@mmmn[ i=,`{YԲL AcB2<Ƅdn$$}ŃX̚4иB(tϤCXtUO/JY꼒?xۿs-X#M58p3` BNfD4'ihE30 2n2.24e6)ix1&$%ȭ:c:2 Z'CGr]hWP:t4?F!c,xjEgŠsg:oǧJ;CO:Zvܵ ץ֡g?z%Mb$bihZO^uztL`DF2N'CńC;h(Խѣ5]кʘ5WYRƘx{㗯]ɽNnn|>K[/u (kmqH 3O4F;,g{zmO"X!N*.;9$Z8ĉ?KF7t9_)c!cZs_(suyomzwv,Y[;Sƿĩ 0,hNCA=^a#!p9~HAD rI] c cZֲϞs>: [=2s?~zPMgؘ&cK Aa&tA3LB[At?THR!@U eUm]Uۓk;~iTONnːZC VoNd t!B%ab!Cf#iD"I#i>HzI]F:Ì1cno|97n|ӧge޽5rkFWFgltP%'1,#)rXtXi\A#QF죈&at7b0g^^tVx*s>Ȍ 3? Rf JObPI2 La0`Њ/L 0>`01 c~ƃ`SÌ1~8kŕ+#[Q3-^mp ;lWk7n CJ r>`01}0hI !%?a0I !%+c̕쯆RdSF'O712ճSd )1I VZCJIbW)1D$$z%$c<%W #012"cK ANbW)1D$$z%%1CJ gK a+xB΁zٰs]ot=:c1ZI8I JBKb9^IhI V)1Ψ$f?_xa!e5\i |:cL* ?^IhI V)1N$$`ВEb1L~k`+h\q mGf=蕄pj%C^IpD|a?LI[`멦-'6l,z cN!cHANbW)1X@$RbRI8I JBKb$ 3xtꛝC]le *!%9^Ip蕄@ rВ$յ=C]h[L2?1` ZВANbWZé@$$V%`YK״sÌO1%} '1+ -JObWZéDJ A$z%I1il=nӍ|9^IhI V~ВDJ gK JCb1k{n}|ǟ<蕄@$Rb8[bW)1X@$Ì1WKj"CǑgnی`^IhI J"%%z%%1@$$Fii!c,]Vצ@ 4-1y0$z%0hI JBKb8p蕄İlZF}ucLݶCJ rВANbWZé@$$JRcސ1y0-%1+ -JIbWZ蕄@$vce YII JBKb8蕄@$Rb8[bW$FJIbWZ蕄@$Rb8[bW#5蕄@$Rb8[bWZC%1+P#9cԥ蕄@$$AKbWZ@$$Figi cK &CJBKbPIhI JBKb8p蕄H$gxȊf cK !% pp%$1+ -^II JBKbLA%I1|c Z@$$z%!'1+ -^II JBKbWFNcWrВ蕄@$$z%%1CJ *IÂ1`H!H%%1+ 9^IhI JBNbWZLİ`ށEc̈0ۣo`^IhI JBNbWZ蕄@$J ;Q2F.1+ -IВ蕄` )1D$$F"`$e 0m11В蕄@$$z%%1D$$z%%1ҩ$ICIX17>0ВL!%В蕄ĘJaUDCJBKbPIhI JBKbWrВ$]ƸeYCJBKbPIhI JBKbWrВ$#c2c DD%%1+ 9^IhI JBNbWZLH1R蕄@$$z%%1+ 9^IhI J"H6)v@$$K$CJBKbWZ 0Вր1ccv1<0В蕄@$$z%%1D$$z%%12UIcHg 01UZВL!%В蕄@$cI 0В"TZВ蕄@$$z%I1L2FxÝ c0"TZCJBKbWZ蕄@$)2;1` J JBKbWrВ蕄@$$z%k1%z%%1+ 9^IhI JBNbWZ<1 1%z%%1+ 9^IhI JBKb0"TZ>``Becn1m2-CJBNbWZВ"TZВ<* Laa%chlchQ蕄@$$`H!B%%1D$$z%%1+IR(4c61m2$z%%1D$$z%%1+ 9^IhI J*1a{RbPIhI * -^IhI JOb"TÂ1z›Ƹ/v| )1D$$z%'1CJ * 9^IhI J"İf ]hmCRbPII VZHl^IhI¨fc3Fk&CVZHl^IhI &CJBKbPI0FCxƨcp )1I J"%%z%%1D$$z%%1xWqz30* -RbPIhI * 'RbPIj19Rb蕄В蕄@$$S+ -^IґIza70\18T^IhI * 'RbPII VZLH"QL2@ )1D$$S+ -^Ip@$bJ KQcȕ+W\r1F~c(߉1h"cȑ#G9r2Fw?0Fac#Jj}!W\rʕ!c\)U1Ð1<5cd %cȑ#G9rMe՗˫/\)3Fd 9rȑ#GdX?QfxUrȑ#G9qѥ0FU$cSY1ȑ#G9g1J/*6#1tsKƐ#G9r0Uy% fz}V/C9rȑc{ŒQRa0oxJ29rȑ#'f 3Jz`fT0\13UooTeLw1:IrȑsM,c+ѷ9_bF;E.w׼-3F%l_;Z}LRu$G92Be #`F1c(w7o^9Zw8ﻃ{3nt 懱"`COG}H2={ w4K5ȑ#GcK>o'#]߸;ϙ?FvZ<6Hʿfg0w@hƈ3e8 > R Seoԋ1|-[ 9rM+~ ?s[Ŀ;Qf#9rddW<7;(4_5/;1vxl n!$aX}_0K86̚H/u-nv̬ʪnQ_B*eWefW}dy":F[+k4Emҋ |~H6+<0CjlpC#x\õ|1uѷoT+n˯H)Ι>ը}! 17A3sl3$FaF?$xH 1xKt_Kep{E&qAyh~5nf-ƷӴMZlK :CTz'x֟h3CK) 0#xhnO4cpY4+ic뎱;ckQvCF5 \Ln1|d >xhFaF?vS1хf%eO VYB :O C (is[tF.u5ޑVoEǯۢ!lbƙР ug;oЩcaFp+!wUwWq&G[tz<_󩸥xwU8Miszz_cySBw^0:3**R=#)@9c_v c ~δg&gp/-FaF|qc1>8u /.#0#>`Ȏ1%nFaFg"#K2 10#0ˆV8"9n!CFaFaDѯ1a8FaFr 33\liw ą8{aRd%ΌO4ἂsu.ZƜnʙV82C01 t 7 1XF3*C#MT3xZhЙ=z}F/{sxWP+>L@C\m|ml+#_>y䩱KcNis:?qe|ʅɫ*`#Q#&Z>h8 R@(B33eh̡g&zG'zF׾3g'.A?\9 i 2 #eA1|#-Fxd HPTK_؇b +0i,w[Chbcwc3#N((%,(dx*4%RNd;.ނCvCrlK#@U=2 2HrjJz$,G1!(qJR!&4% q5i@_9B#b1/$aF@͆H2I"b4]fʱl%Nwsziil|ڳWxj&P|*TB0.!7 P<KGӅT+O_p%_x xv$^Tρle/]% \5|5]@W(JPEBٕ)Ьse&(7dc'=(û΅j=We˵LNjb-Q@_E.3zRWP|ՆdvfaJ>8MHK:oU-]7EFyDR.bHJTe9th#en$àCiB*6EJ)Xrz0Ye36Ɔk ;i u{05?' sKāHڷ@W`ǭn, fD썘=2!CkghU&( B JC5P}qG zR,qFKoA qǂ[U x8ŭ#Npq@?H89V +{ebSl>c{ll,/`_ †x._saܪĊsv1YOSl22LNW'  ?.l sv~Ȋ h)jlBc21TC_W:6.OPT_ԺZ}JO/*MQh 40Ȳ.m~ŧbS"yaqa.6i`-lx= lek~Uxqpr,g(Kی"EHZQ҆\}ǣG޼yo<\MWL!:_1fӕ,:F2qcǐ;Ռg jja-^tD@]1>v [cO]mFX[VsU*N=pKV 5&|xDYgO~eEr }99,^N-c,!9:}< 1`A4D3W!3]wgc{d`or`p75m=rDW?c4Mc8f5iΫK g)1D{BO8%Vnɛz"sƖ& % e9cx#j?q A1"iy iV 5c4RNJ $3֌- mW By{< .,.ء2icT `GҰ7(%]RW xwd^L/弪{'5?ad@olU;̜cxKCܮ+Z"0㯚t Y0xp8`8[ cLk;8AOhvh,;FP1 I*2: u D/.

      *1}bRr D":;piݟ]t%fm05Y/Xv c[\k!G <#x&OLh&;ĀOeTQ# v) e#eRBPƩX8&d?Em@]'_ID/|3EHHnEJwKVxi`I (8P 1P:#Sy $ q &@0>ׯ߸qcmmd2f|05[Bv ժ7z*,$奒H9Fe-͒+ TmА&$зT,:!OyVed2)-. UKD4W"%9zDg" mR҄ƒQ%x})Mb4Seha,dKBuZ{VK֟{!|%Z-PeLQgBܻlE<nEd8gp=+5(5ux瞼  |IA?^l5Ozo'xNl9L ╊EXqC!ii@H" և+yU']­ A5/HAMӴ]4+k$^4$Ex 7[KOBp?jijV&ZDAQf;;>?~wnfܾ}o<ҧGw#ѣr%trk_c9aJ;rpS/XptXqr}pHQMP8.pcw8y8xm]݃]C'O !u!~wjwx\m'u`pͧ'>/>#pƶzO|V@O tCC;{O;{бnCǠbl)*>!^7G̀&),Mr5TViY#EkdFa~[-pΧcI3_v͛D0nݺ"t endstream endobj 100 0 obj <> stream xX[OF~0J}DEn]>}p$Hhݟ6NlH6Q9wˇI~SaY7-^͞ =ËahG~kd>x)&6ش߫ńy[l| ?J8$&dߒIN?;^=iw :N2YYU@V.n!؂ \=!D˴R&-nA$M:Iq;bi'яxC;C7v1,pu|R{2$/&l$\NRCIi6/g aAu=,Q :ɧ_=c zY"d6) nB| B[_Ǖe˅\@'LqI8[v ;xVSu\grgBUxͻBur4C(p"81Qݗ ߘ~9M&7bB6l!MwS.5eScs;˲BMNfv.H[ׁ+OOPxNz_qdr$pvg4y+,$(Tk!W[{b$R[Dn-DT zwklZʭ!wvSZ>Jՙ&) al3ϥbNʭo^{Qqx5nd Ú24Ib~^glBLt:@ԕRjk[nh9{ 3vY lxAM§c&Fmo[C.h-8 G98,]h'Z`\X׻XVt_(еTn g4(+N, Ȇ) Hb %|jph8(bgDŽ8es,ei֢:da%u L"?YFUzCDl]+12⮍ 5p&\41 E~HQjsG* ۝ Jo ٜMɚ);;d-kތjՒl<;J;d>P-_!d3UERVF> stream JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!222222222222222222222222222222222222222222222222223" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?+_h8o]R=K(D1J?}[|O]iSQ.Inzxw+S蚽].aTlĜ'G1u+1sexdsG{uծmQ^Y ߤд=wON&p{;NTy ROcF+7;_ M t]cEp)w; m-Ɗ9*3&mr(3n](AAmB8a~i裟\J|kF/5}AO$5TiNJ #(2դErkF;wT_Һ]z?G6LIܛo%uҜw@QEEmB=:[C22X~5V *Zڪ) $ 6z6:d*ɣ.tAqfҁlߐflARb? q5TӓãЧJR*Wow> jw34ʩ| <JtB=N.Y %^68 . G[Mg[.&QpU s\߅Cwk<7F6rv5φFά^ x}ox_bQ]gWŚ,~ ԑU[@k:_T3]-c[6dU*Vӿi\SAfo|E⫝:̷ӯd3$cBcJOxPN'l \ړÏQñZ\|G7${J*+:SM`NT0ӧſe?#ť̏qе?zL:8Q;X_"Y~ 3_::uo> e)ԶQñ|~iGU9VYt.4SR'KEFؠnYɑL+ASo;Rz #ޥQ$DoK^%kvc(=2SWi~xN_^)Եe"K39Ov_J[%c jT{^k"! (罐Wf6!VW)zUdz7V0*}G> g%{VnRPc"s˩-G9 d.^ƱMe89INWc'&cpt|"sեӬcӥWH.~qGLqϭr却xZa,2ptCӎTс%ǜV{df]FAȨd ڳ,hU}*Gk%T+wo?V"O IqV}l,n F d1>K&[ ww$Lf`Ɵq+IF37Sֽ_zcgǑN2+-7=z9hH]eYNAVO\sMMO\ ʝ=Eg&K{˭r?P3PxXh^'V5BKAIh&FX,C?6;h!mȡ+2h[ٮ }?֊>RUeO::_T3_Zx' Rʕ2$J_#j-uwӿi\SAf/xD /ξe+)Um{Gm}Z@g.k[STծy)>;d\e X|v~TmmuWi#b,c=_@Z]}i մH&@zwL_~%I$Ͳ ?4:Vib[чk(e*#־| 6Nr69yG=}:ta ^Ȝ-=KOjώZ49|Belq@VSױ(ᎉ\F5jxzt94Ẉ0#SmvS4<&<_xW^~=V%nԼNÁu=?OeNY2}b')sT YYOĈOZu 0w QdP@FWx׆_ j6nno!0HJ?[G+0hayMHKV@8PX+-ġR'S?`;J{(B`{L!]CX' V!`>ƾ_]*v[Z{+QdyPZ<RnOzw*m4F=0U\wŽP Hʤ{or8!:5wL9@Fci99:沝B/߱:'%ȭ܆x]D Uu HgyOd8x8V/##hd}O(Kda,ͻU3s9ReȪɤNs;}zwS$^(nՔBa^^GOu)Dk4BV+{Ռq۽u]Uڑ-9q }zYn!ӣ*tܛM=[<WJJ)k5|n|M \Q] Q1$QT@TvRTO>{WUNv(0=(h J( ` P*(REBC/֗e;-1EP@Iiako\aTBEQ@(P1EbQEQEQE endstream endobj 102 0 obj <> stream xs[Wt;,rݝީݶlʢ  A L$2 R(K-5?LVmՆsνRaQz}L|{ν^lttӎWCKz^㼢嶼ނW_!6cxU*Z_gq%o ơ g[򦎷xW)NI>3|9sol͉?ᬞ_J}i{Bߐ7rd?8?PgVUmJp^⯩W_zx}2/? c32OЂ|WfyA2=|{:^8oEv״[wN 3_'M;lּ㛜U xD_~// |o~SΙ~᱖x ;m# G_=K/?Hz/#T tzJ|6|9}КDW-bFyɗqg>g|)mor_sqOǑ- |gq1j9)ܾu[!$qpn*qwr'p]3g;yܺ>C#BHmv [H%T`1?z{>?xp1>?zDŽ~!^ēa{r/ꑸy#'xt<=+o[_oKz 7I,ėW˞8 V2XZNr²`iqyQ2̨KB|q1FU4bʳ0y&BcnN*0 ̮*(̮63!8=,8_Uqz'acfG2m} t,۝+x:W.qN{p\iƁx̰9 XN`BZD&8倣{Rb3?@9Ƅ1ke8>3n\c)dD'gFm ;`fLT&SĔ 2X`WX,Fetpl5 07 2F`ww ct:z;z3u!W.ƕN2rrw宎KuڥNt].r_v:q n;}skdd5c}cC-x,` `PyD S "8oq2wt1'!p0=&N{]6 HƳ?ˋ!c#qФ49n7&̶Q9eq]4NجzЅOdz0vLv:vv L U%8vtJ0)s VKkeFfG/K|d~iq/__߽+ lqevthOX.zKomX3B  xHK? |bb5 E! l4&rd!,đ" DQ!Yd$c2YnCYc`UJxO4bqH\(] eVT|XֽhЏuL20|Ux>$a{a/[YM;3wpG9FHhYF =B37\e⚡dC3`2 =f_Q5î f`L0lNT 2"*41ftc0c E@zP31vu14ЌNBs{o\u} z1 >0M2!E `fW$@cS\'$̃}.`cn=4Ԣf0n41dfجQӌ1$ǰ+ae'4dh֌ [-gь/_\IN6CS`0f:fZ*QJyU[PH1`́1J3D)b#a"T bauѼoA(X+DB*U$ZX RR|i);BFdre+N3$:hl4Qx%E-\zf:\@,Lũ>B ƌ9ui55#GI3.D1 :XQƳi @M(ј: cp5CqI-SManMqc cfXX!&> 0f(cKR!4/ %=B3xѭ 4W:5׹ft1Ǹz 9/uSŤ^Y3:Q39 g -X(DR1H f&ý"5)BI!E3̢Db6j bMݒiL2~{r X1(c +&SI 1הbҬc" u擏o8?N3$vg |spk4c 4(#;ܬw~n[񗯾ʝ[A1x|^W E_h"?g^KH"Mfbx* GdguBBd^*2z\P7BiXJ39eTe+D=]JDyS3*:BqX-v \NQEF:QQML<TjB*Ti'H&2w\"9x"(M1V )wK*ˉ2hFx 4WxG<4,PբEeU1ퟖMU6ulZձZ+qbKX ioKp*!2 I3V6Kzi[מp M{ ۴̳Fk1%4C\319iLN mLcXq bY3H0cXc JihH3za$@OɦAu %jjqJ˲ct1fYoyfA3zI3FA2 D0v ` InAanZ0{r YĈ=,laccc}F.#jVLưb2e5&XWaB&ǀ}Z>1Ǹp*waj3 ff fhiٹQ_N׌X0[.v6wvv^l3=K2fQ.ñT$&@'rT>)gY$%) $,,4rH6W(^Q,ovS2@SkK#u@]AdЕZ دe3<2٠Ra} Ž"P.rH90q#aqdžx$r м`+$vFK xKLZ"eT@WIrD1Bx5F|XCLc1TO#PoŜMcV/me:o`XhZȵ;r nc8͘5Ci4%dpj4{DouѬ b;V3lh4Qf^P;2 T&fA4cr9ИhcCep03]j1LL32A}7{4Cu U3(cL3.kjFՋ7AWwa5k{iFو9hƨ-}L0D'bCJh.LiJb!R T."|Q%J8::Ht+&ؘa5>11c4ih^lv 11D#h{Й'MR!?c¢+ccdcN촘wnBDˑs٭\,e#lP #,dߛahbe)4caL#$XU#cNFSpiCFl4/Eyp*S 93)>K'66cxEuVMé7'Ih YdKQl4cFAC U 1lf J{d3MLCՌ)-4Ck61$͘PhUi(@2: Q&J41b9WMz_pW)\էd.f\cȎq@@ f\!͸LxovAfip_ߤ fQ@a`u@YZPiY,$11 IX%`=Xi|QWϠc ZcQc9R3\%iSxC6yJi*`LԌ!k4Yu[\+9ƨbv9Bx #q`2 vQ)W1P##I.)l9d l/!r("@IQT( *CB*Um Z}ju}}ss¿*pTwvo68">'wv;3Eíí͍Í!*G&(GAѨD-& 2{D`(5TY>PQiT֜=b(#{""ǀ?!gA60ӈWr (Zn z1v 7tl4P6F@olMH3XF!e %jϧsۅS/f|d3- i8c0dK\@^Uhǘ 4vЙ&h nrfr EYjbPoFK h ! `ːpAsKMb2;" 411e0@@30 6ft_鼦v\Q$WL@34fO,tbs)jFo & 81*DU RI I.!fL<>`2ʚt#L30Ѐ# hҬ\k%U јAKY*&zgzy~jB~AjFU*-4LHY<`PzдZZp01Cp 처_J_L'S; &֣ zQX:ő|"]HKi *z!d~pf(YlAeK%b9e0IS0NWljHKEg gͭMTs`xۖ=Enˤ5_N;5yӎ ç;{{=?z.ݱuԏ]Ν#n!lo)} 0zVݏ5O$Dĩ[SCryBT9ұu8 Y;/;ّ 1W @W)lͱ@f+KJI1MJ3˸AB| (PЙFv B<azccU߳1LeӸlhH+CVuL+vՂç74oʚlw v i(MY3cȚ1פLaǐW6kT=rp&֦u yfh #^3cMC7cxAaai f ̓ccf F85tA 8FE ЫVҩhFR7A@ǸAHkO.u Zh95܇1FŤFe17 X2L$XXa*b>Vlv#l E/1h=bTb 9⼗oU5?=E7ԬjĴ.s=`;lḤcLpd<+/6i[7i$cps V0ǰ8PɃG>7n^삱m6``?~kP kZ4 FCt .6a03#ѭJMa[$GP!)&`3w`8BӆSu6PFW7b},ylbvsĿx{G{H_> ޵iq`ށ^3g}%^Ti!.htugQNhL!/_mk1'W11^Fcf4|d$Y~?˯Gca?ƃZd=!F`d\\&oD5Ǝ4BS<9Z Uj" G%(sPc6&{Gi1G ^޳f`}}M*aS]YgF<PMѸzI'tN 1cAlGۛioMNOũRޤZ@'hGr {!p.sHf39@zSoAa1 7W;v.ISzbd WYRÃQm 8l,$[С3&Dġ:ڇzD=N61fu(f8dШV>bf(iLC=NʦP\LkkE 2 \h*&fH5ÁhLîhƬBfh iHqfiX4aChfXJ6q 5ʐ4l4 S$4C2ft 11 ܒ:K3{OSi 5 RAmikvhЂ֮7=Vs(AhtkGZ #| 2FM>~V1u#C""\1:Eç x.l%k\ձcLp i dhƄKr nL0cMFo8Ia#2KB0p^:J=O?9XGWrPÁ nE GD.^Hl%Hv`*&Rcb; e'aȒ`@gϾnS㽉,uew,:LeAlm`ZmUj=kX3}Q.Փ~k|~GBg}xA~ͧeM8eW7S3^ğf-rE wF#U}k{!r𶇋XPZ0(J08[ֵn1Ome72 ekp01>UBb ėi c19X0TPql%E^k!2vk/feph +4-$NfhMcV1 4C[=QR@XKaw ^3&yD cVY3fh{"dcT`niͰNH4ѤrTL8؛u *&#jń;(]2>a1jɸ۩ >͠ u3n(qIEpqQؘ9L6hcJ[61 u U=L0]ChfͪcHӣ}p-c$2 5'>B`L1e`(ǀ#vUi-6rq Ν{wc,rW( ˓___c ncѝ1*cRJ:W%hJ#[;|=ۭo@Hvk1yEpǠgF=qo,7`466}wf&vb4|Yc4\$j{ N ^xO(Y3 {h {{ pr}ۮg ÔiQq4|@36ݘ$,DN1G@'\~|D'1ÍZa4sޱDjiSa p}+={(Bh`r4#Bʃcl[JVRlU_6嚱hB|њF\:h*1e#Ҫ/:+ӢfrF3|& r K3fL#x[kVK9e"_E^a .4ЌnS' .c.N;cp;ӟ|q ?䆒Q(:SqۃkJ+ӓ{~@\y|Lq pW1+X7!`*7>'/zzthcsg6up49FWYlcTc%8.!tbQqxE]u=c§ܢY.SmE$1&*+j9Ɲgp I%vL WQ|$|vנb z"%! I~n빇j?EQ}])V:(h}][~U?ܬSGhb0ƶy4Q safzz'K32J#9a0`l}'9խ1XUstuUMzsC iLCբ6iixNV|M7ڙ]H k0`tv1硩 K+M%9ib֞ζ}ݝ=Xaf| 1$͠WkA땄C k J] g{@e;r}1@3zUǸ옲0M]C&s[ȅKL:uD(Sp#O%1z 11Nbe1 D-$Oc; sˎG`ᎱF!|"ӕ3t$31fT2 u9|AG6>tp`T'd8s-l8 ( ]VXT*p D^cqzɻ+c]*nc (߄! 1pDq@GS88fS=5M8sn).pNmgۧ߾>Lc3,R Gc,ctJ8F?Bǀ)I5l3Qttv*2s:5LcVɆFH;rrC2 )@]$[6wE6 e)1f2͠5E@3|' .16IJ!M@XPdT hH1>r.V&Bcg:Q'8 6<18@Jp>@4 DBp#&TGo`H c49ܾCA&X 9 u:+YaYLb8F>\#cg٘u&ӂ02%dcJ5i>Ȣ7 F*i.2ci(1&'Glc|N6+xhcL3O@-ƹTO:& 4zX-5E[ߪjy4cjOC3!A(h0M TԌ j5{a`ea!;F<=M3 mi48 Tfַh (O6Mdͨ}Jv)8SB3ȎA'a֚#5gꞅX}hfg-fzZmJpV?:4`"& M3 ;fY?xkbdC K<,<hE)H3%8=43!9eiF1g@34 ÃYXF1zFtᚂjT6(,(\__}믿t2k /.\rNO*q0 BL8F"OͧoVcRDg{q(:JȩJ7IX]bi{߿FFa p-f@Ι'S-ePeMyw-Hؔ[vVK; ;lĢ։[# ̉6n%cĘTKK`vA}w$jcs:p)Yo 9i %|L[EdQFw^!m:16&X1Y B?Y.+Y QTtLc LkP9%Rt'aUI pI%!kƸf]ueA I3hCӌ ԌI;zlffi]o"; 4as qh1d')fHQF1_rd#/ iH&ft44C >b )嚁ٚֆԌŒ7'f4eQ,Nu 6\YKSd)_NEx G|'pe}ǎq K1ĭӄq N2aiZ/fPBz:f8|Q0 K[P0&ZV88q1nbP;*-i;'upph45Ӱ gAj؄ciX AG͘!ЌSfCƚѯ8'{ 8/G"4-ncȚXM31fкiMlnFef@4,!i PǞAM#lnz1Q, hj\3itjIi oo OmMumL3i]Ԁ`h#&5=i5v=Cߺ+羻>ᾇo<<ȃ=}xo>cG(mQfG=Nx ącW[6Y0copK]VҀi 7''=߽w'O2OfNv?r\4# &`$rz"5Jz"{SHO.'2|.Iu䑜2 /%(YUKPmj-C ""YoI9 ۹#W?"k&KXgZ :7x!@pͅ*d7 ߚDnπYϧslb%/cH1^ 0P9?u [eM9-Il>M)@2 (9ztT"Y:J1 T5 <j2 hȦM`ƈ`h5cRӌq6XѥѠ12A1ԌA 4T͠1ѯ:3j=J q*qN- ΉchyȵYrrhA]q0M]R(Sh,5Nh8 6bM +U D3(A,qu?$T( EXEM/$xb&ց"ݭH)YJ WlgJj~?(6 Z鱭b|,d 6YfNS|#E3  ,ƒh/'0`w{I)"K]䝋y L$1O aOm(,Z˧mox (G:!B"'ܘƺ =)s-\%WR&VJEb< pdF;{meǠ4SQe&"2sJA ze#)=62 )G6Mc/L0XC]u'843 >Oke+SdfHE4ώ I3$`1,iư.17Jѯ: #(7 ynF^#iPe8^1tyAT͠AiFSW' B\3fԵ&t/kr%o&O7h3 b08SGU4u 45|1yhs-iH)40]4ooMbH[L3P$Nh :k4`=3 tbj+VWiol>MC̤NtZ˞!֜v4A1#TYH+Ut6D@1iS2zG(chA7 ƴ55wfab dwz"n_ _0ClL# sX5yd.I?@L-$@2YH "$6)XL@f) 2ٕ\ AK= M)5[VcB2s1lrkAAX =s<\yHB]_ICpAޅc"vĤsBՌItxYVyMՌQ,312rzfH 4 ړV175` 5a@#\3iT %5hC#iьm +h)*UۈcP4xxV=MiRO#&?f&f4C2Ap 5- xZ MH&1+4[yԵ6ԨAMiS4D0fPA͠7@ӌ\ʪi ՌZxj'@6]Uӌrq >ҫ1WQf c:ư.@0<1"L<:ЌoVG&W鎺<1=H  &JZ IPF#H^'@wÈ|@( S\8Dхh*G1X"ʑL.rPJiцJ谫F?E()l'$X0r[%(\C]YHC4!"D"]@,X@ ,DyS^DW!> 8TzWo3py4BiflāfSӄZ M/`Cm#&Ph[Y'-k털T6)#|, %Xi:jxmfԴ׶r Z~F6Ba bt0hz:[zu8h@߰xܣf F4JpiT fh U3N24V5Cv1>CQ hO[=3ǀhE ex4>FdOd!"؝+pF!8PH BNA:u\QINb'w) ;<^Y   D9mD 1N4څhaEB,\Zbc/FA{(Z1&(B?!F4,hHs~W;īQ>GHABХc^&Ҟk^<:FfHs3cte"gf24Z#&<1p Qj<#kF]ТtQQ1 f 4`L AGLꎴim8Lj:j5͐dC1i2Nd4q͠ )tЄC$mP-y44o %Ӏ\m M]}Ͼ41׉VB\3N@[ {i@GEVrJQ(%fLcH P,w YM0띱ygmYe!(ӳYO{ A#hu=hȫcla#l# mPl{jW#Np +rތכr@>$Q! 'k.DڞV:-1> 6T-J0o/RO)ErE!H,p;C:y X3n Ef*k6Aoph4r.2sD@ձHma9 HUGob [3[;g3̦l/Q;c@!/p'_3C;*q;Bۈ{B2W;U5 .7kxHp.k#݆&&&&&&&& C7!?c@6-(y-6?/&&&&&&&&U  9 a,69ƟoyĤ Dn'%'c\Zq1wMLLLLLLL@8!Ǹ #X 1~{||闗b-[q]('_*ϩ]eO&DÓ{k^B)W~]7SP|_HSpTLLLLLnh0|ӭgvd8'9څ_>߿ᬏn^xG[Uwvbw~Xzo#B7u,&&&&&" c PcO=_w~Я^OY8jY{C[Uwv`ɨp??M?ɇ-7&;ƀcTxS§ÛF=[k'wrO}O|*U=eKSw뎹U_;8a ܪk_>~P إɋ싽lsL*įrKaq1>Eưٮ\Dx篾ɑ䱕=uƛӓˑO8=x7XU! UmbgPv9NlK_B_iW[4"M@[A:e^Ql<ݡ͘SBaͷ=S1v]m  Ͽ) nnea!m%rNH>Ztr;ϮI_EíL|pqn|`Bz3%s>Mۥʰm~Dj1mo" oYccmvJf8t7x9+lof09ƨc쎫cߛX9o#@vA1nA"@ǀ8o~I0Ƶ"!;؅;v'u˯sߙ>>DZm5Cr+D0v0Vr MmSfnfnfn_nŏI9 !!#Ǹ nۻ's37s37s3<ă<Ӑ<uʏywϼp1u{K|7p{_ׯگ~_ ?77s37s37sȣMɃR~nU]1 BV a?|{_h8֡r?1vEcw `삪+B^z_|]vkl7}$ۿxlWbO7#bɃ<DqZY W^!4f`o.qne#φ3z$1̧ ƗT+i^04ϗA@Gn\HJ?zŕP*dxXbܞۯbFcXf-\n"3>t c\~cloܸ]{``B..{ >㚿uNy<,N [cppphhիW᥿?vD3uPu}+CyԢQgP(bC^yyy_&fmC'/1]z'TQ0Y<˧DbK*ܩJz^8_}'AVnbٳN.{fʴzۈ7|ex0 ,l˲t'j94OX,@tW U|r'~ M={M'5{Kz, U2D$dq\]}mg=_Fr䘄 XiD oS#bc@ɘ} I #.ϕ٣#wcԵf$3]ZyQJv9I0=qclA0] S}+t-\)(.K+S]kn'Qo  L~(|}}S_h4LY7H/y^-C򔾲;E{9hv{z%O^ S)2+FbC<=S849e\ŒhRIJm =&8L~66<8'-j_rKYYۆ|;99ƽ'Ǐ?e3gl4777x |<l0y%6 .Zlڴ>vLQۼޣ 8~*Iy{{s&?@PF<5N8fg𛕕_.ުI,qӮ8\wWlu O&m㻬uݶSݟ4wW_C;1<\O~< 4d㼼<<ևHxAWڸy֣wrz7vfBaJ(0pcP3QѨ-/}{/;5K-.vѫގ!ٳtzť{ BVBrjlBRȣ'Tq޸qc||O$SXLJu `O~S((T` S$b1FMM LN`#Ac0Гߕ|cھ=C>г@8ulp`d{w[USΝ;p5K_E }c\}'NYR~sdnCO&צڊCp+fH$`H e7oL76UD֭[ayl3q=*&v c?>!fQ/\_&bQ`n~⏟W?ѣG^ 0M=Tc?;v0׬Yxhh,O.nXa}kӞGx u=wmG֭[<SצOF;2a߸qoѻ7awuϥ9xw߄gw\m۶~vfvn.7%T[y×._0_{9=FFb]uϿpر7jv 6̔/]:fv rA4gk:%>=%d-ԺhԷ5WQf:(f%$K_['tqÚu7|7>c~T^yԩM7m1t4Fgk|Hb8lZ>I鷒8dM.>yљϾ7S<)l{;a&"ٴy3Dt䵛RORDDĭ#Q/c#Iht̙?D8}Yb{n2RSSa;;;&> RӦ`r:f& Dh1=djQ!{CnCzù*F=F~^н^ 0Ytk/x"#5Snv\]7&Fn(eGaΡ\defSO?~3.zٲ/Nf|KNizꀀvZw?tl鐕GB?<:gő{_sն{G֮] (5-^22a;v=0.mڴ CX[=clٖ͛]+V?}Oc c&[@  ]Iyz\twx?SL3)8RSճw 9(e, 7gP5kV?~g\ܽ-wP~P^Exua?~}K.G t)+t vn9nye!|s?ON~vC!y E}ZqϨN,\dsYj ?^17+'Cwznڲk;o~,? }n(u`ΐV>uݽsT'tٱm?=uآe)3={:~|ŖYxb`>_O]髽ٮw\?+ڕ+WJ(***++xg'1lZ6}c_{*C0F̵qɤ@e@chh)5_}_Z>64<2vh~{{=CyścE<:3(`H5%0 /6v?x }f1T*MZc.o:4G.^jf8rpdBKi:l{?e vhΫD0 BjpT?E30ѠIDÈH~40.HC\5F$QNn`X?ԫ4 mFׯ1nNoH?'dШɝFtý`w@WOJӧ+ [٭Sit]=nm?N7C<'R?7zW۩Q*5JZ!u*T]50P;0 4jԘZ{tCZ$ OֵmjmYӦ{u ^W hM7j$ho?ψZ?ԥ;} VEuieN  Uc XvgQ3ЍnڨᆮͰwXV"1$cт o@}=HFւu]Djً|'9=(Xu@tj-hH2K؉i3];)Ҏ_ec>]*H'H; Rj:{A U/ cMyA߃VsԔ@lFn4P]Ƅ=oS?کU*Z kJ΍nnjϨ{{VL٘Mc珌3 ݻoD'98eֱcn޼FMw3M+:jac0Qcxb{}FS#wY`h  OAе~ǖZB\ bBŗqycSk:_tS N!9Q4FHJAhJ~D*F)61KIeb̖Q M Q;]()dir FLGcB|.E^svG+U䊚6PN)<9ӌeަJ㉂\_=!t\αx8޸T㷱qo"9ʌbɲx9$*O& \%#%.* 'rKWW~€,UBY$K'ӪҘu-Y\ۙR*R.U;k;ĶeTW__]^t5Ɂ8ٙ[U3É[;rx\WU֒ !@fҪN` ^]tüYé)Ы5TY7 F Py \<+'Tޞk;bd,1$I jaCA%*+jwvDH˽#)E jIsM[ա(kqUuI[^^].uD^G.Pގ8m9@A^V H/moW48uZvRÄQQYW EHQ"Ur4r85,i]S|nI%HEc邌^FS( qtXF,CtQSȋeTB[$3@mԊܲlf%*EH$gdc3 ⱔ̼41#'?+AKTƭ6^VSgfᢒ)A1AB\@ 'i)j)Wؚ'@/'[2n*Hlv y!r>1TRI?bn,o2)UIaKq!0lbr%#V_AYY%Y@\qHv܊(]2e*ΟCh qlYudkk# o.1^r.JV5Rm<1(cs[(&2X q::-?55/>s=.'2!72t#%/& Wt+ UҺ\n Y 9xvTJU"QK7ټkY,lN,n_TOI?'ߊ=#ˣR{_"N˖;p WSTǰ8(N̈fDcyĢ|jI=ӳ$6bK\*BM(xcJ"bRn]1mg[9$4~!*e$8Xv4I}qD$MCyghyiqu6jAk!9%qkR{Z@GkIS:˶Ӝ7gYMhFc(y%"ru7E%1;*SMڤ<)\R${)n^hH$ JCӚ۔8 l#  }ǠGƧ4~] ^9Lc{hʱ9$s *7(A68t H{> h52r@aPgF3h'.gsay ]|:|VM/m}gv cx:eU\eWYUVzUw:?ع,l{^8wɤEQpN\svw9מ|ǠCc|k1^?I{Es'폋[ɩ;]v^s$UwWUKՓ3/ҫ:<< >FzAFQ(Ӌ@cRdrLʒ i! )H|kV)[6*h͓lX0t˗iy3mod=61qmzlq*cXĺ^Mǁc1TdY,Cla-0py)- >EK'e3jbĠ:ٮHE7TC UsKjb 9*ܐcRb\Fzes,i$% _.y&јoh7+F/b V/oj[/|1RLcc+=e Z08ơcc5Hq+l5[OJ&g%SҩE4S1YR|]@ 83prA18ƌz&1soYy)iF`8JbyǰV{: 3Mu4qQ seׅ%Ȫ:-t,*mXhMd%8 'MBօ*Q^>9UfԜXP,&1X1gGOxK*X gaA(8" )CsĪ5+v֠+CcInSw ӸlzA<4kdO {fx{fiPDɑ 5(KE2lw2ӋfHc8cgLrX3C%ЌpP3p4Cxج)#96fL}Xb%F{i4ɦ{ݗchw{ig{)g,k& 0g̙WcccW\a0+++bΘbHK>wǘ<Ќc<@0z#ݏi;v>(o}~듓v x!{vD/gk7~/_y_ΘJNF}>jׯ_P{G)Kn dW9H\KF5h`hCv?mr(rdN|G73t'PbśnDu!EflIa;QF;v` 앪n;^k@y|#Ta۟$]gc P/+nͳvbQYUR*5̳Y61fLS*8 -j#Kך:   F7:7kYIMnkF^ 275Itz- b(!ʙUZRm@GdkJS9Tͱs%2/\ 1Ǩʈ p>ZI(p<1&Ȳ sU1*e8Ϡa(!"#P}:t:aЄPz+.|J2KcpJg~vz?}V?yooNM+y#M.owokr:QO)=Y,և~!TE. y!l@:Ƞr_D}(a .UPq3\܂e0?]#ڣj2q$DHbE 0*"]KjoK f䚻^_hm?عK0 PӨpHEf좋TA]iSl;vn3p $]CE8ߍ`cF=wi)eLT= Ul=-tى'^RM*$ PF:%[ og-ޔ[ E.\+r.ӹR떈J瓪\|iQdc|5XxM!ӌ ɤI[VJ"AMyV.0! UCB6_Z\nLS6!o^@*]hP.qWג_6A39uda-نĊ9ųeE.T֔H00bwiMTs)^߱?_|>wSl9NI5U GQB!hP]eƈX?IݔoH£BDŽi{Na"K , +"j_m-9)%kBW/:`_Ëʻj򚏣 !5.weTy 18#BkAroC詭J܌.=Ib "<̭X|WIZH۴ :FG3zIq~.͑ 2/>>666:(.@w#ӧGFFfggWVV$ g?nL&aǠ%cL^`Phhhe}l=3r9.{*mi)oZH]h "*@>fq&l[kp Hn f[Lӗ{5*Q%/d $ğn9UiI7Dxb%w g=4|d0AT N'sG NBU ZgJm* )rPh'V?7L D *yK oEǨʉUڳ\[reZjj=nnof5.#|2-`j@C%2&qW"Ϛ_5eI`Ř3t+0:U{*BgkͯKĒ>ֆ끥.Շƈ:h^hDInКZ2ڊK&!%kq&6 Ix/"4A0L%E;͸7Yhr ,4ALާ{lP] v"Ǡ}pdFPo` 3X b8zH?^`cjF֤BEt&4AQُUcƽ8gTró><l3gRWdg 3WN?}}P-ëeL<& \>|:~tХ/~yR1p}9?+WLMM5@ t %c\c|c  `Nr[IHR p/Z%b1\.$J ٳgsKa t_JZo0 #_W268vyō젋"j*]E(t̡Wle[Y,;#bp[ĔN 4e`v;ULnߩv?n~2 | azpNA>( mt\s/A {rWKL}oҮ:Iնac7ZDP2MTymPNue(!ixoK|?3Xڇx9*Q$eON\&h%X5ܺ+ťHeֹu9s7{l$_qyʁ` Օ^Q|LDV%Si } #1ct͘ 9o1ewGTN`k k4PPuQU?R [^(]E 5 s-@ F{=WC8k,kyP45i!), y *$**&+ gNnKIA >,޺\CXh #-sABh 83lmYԄQc |Kk]k I c1>̶&Q(DKL*ZZ2ن S\\/E> ,I  (@WBWgJoJFʒRScݣ|SLhImI ;k6% !5F7h8\[~Ւ]6gMi5˳e]R `uM+8Fjcvݻ|*f wHGS=7qʭG=vIGt(M'sGAvAfEKX3i "'9Bn`Htf [3J@&;Iy>Rr))S'C'c''N.]@/,a*g G~w"0N"y;w" wgu}7)}/c31^}շzŋcccp NQ:]( 0d 7G&ׁ`1TtnӎAۓ.ƀ'M,OOO9s;8-{i,hnBMOUTD)X1JN_R閟Fg.nco{V^6ѸK'vw).+ʝ2DƧ:nرaҋ!.~1 E {4:8vx9CkR@<_:v쥹6J 6\%} ՜qkAOQJE)n! 4H3o?gjƹ}mHb YTM52& -R7_YKԞҕ"Kop-eKp\gx:K(1u="e(vߞR-ʶEZrDV\1;'",1@0pj_C# ROFdM4!I)ˉD" A;F@ufdlKi m ̢!2f-9JFqWx0ULΜ̞kJlIaƈ,qF؅ԙrOIr>fP5)QJLo~EWd>)yIѳO y}ғcd;40x?/~7oήd2zv } wM8cC;]IZ&N>;4wJ4q?]돚yg%}|Q3_pA*JGH3^|'/e1#YQ"ڟks^>s׳ػ 87xܹs333m?u: Ecec}S4O1FZ,lZV LLL{;]ܵ#tc\ȯ$$QҮ7zи ɣ[R`LjPXnf٠๞`lF*Z;$8ƷTk/;(] ] V±c<5c^^N /}Tǚї a =`0(0>8֛K7LUmX   *EA3C u#?A|] bf&4ek#B,J1U+Hl#YCr+ I5epX0t/}l= ) `49Oz5ˌlx5j*VQs&4QFpڴ3{c_}w9ʟ`J|U3P|@943'ac#bݪqzg_/~cN{ kڃ=1??&O:{1cկʁN8g²O%Roc=q؎M:FKK z[5Jۅ޴3gٳ:tu" x,ϙJ?vrJgCpŘcpRnY#YP /H7D|b }|hh \"'cy"!Iؘugg*NJ@,[QGgbH,iUdW\@gKFnQ,-WY6 0# /ь@]U! E=>_` jF,vm᜗q⒲]` BO3Urm /Mppai%y3rL!4Fv8AP oMy%Q\%vV2 8Z.y` | Kѷ|ɉ1<  "cġ4ƀJ)0QTZ8u~+A3v!N x\UfB/363K1 H d] A.Ag=' M tj🔧_35c9SΝzmSN-;tԲSOr)HX(bzM7E:gJɜ)s͙5g9S.?1%}SRgO{P7S!tާ~#JѩSqSKc}'A$D3")1Ν[| GQQQAAA^^^VV˗7oӧ=cǎ~8^JbـTI/k0HM:iE^[EL3TZ81TH ;.hd p d&d* 997M剱Ⱦ.hɆU>'j21{{4!?(,PӘ9 =m`ol ޳z؆˼L eB:oRBs 6f7/Tfw7p nHG'Y_4Z!D6,=>c ˄ʍ˃fR0hܘT~) w(i_+TkiN͔Z1cԺ B=tNӴ[f@j* |a'j"(<<zm1# .F"dQ͈mD3"A!;3+l\ ľ3y>H!!VvEFQ>p };|E6KzRx".iA 8WBD=0]c8@X'x~bℂ1Z1!Ќ 0 ` yD_b ^AxT3̾H`\N6Lb^714HyM<#l Yީe./uu٬er_6pŌӥ+W^rrc4#˗qv=U+VbZi˦.yQCc#"(CC[\6nX=$C"PL0 Q`U&"4L4LU&͈UFb 5>J3Ħi4!MDI8cHYWf=4<٥%m\R쒪MK-V>H8ķM Vn\Tatâ /[8מ^|a_%cZ_޷o[ouܹO>ŋ٥d筏ccpqu)1RS ) &8tݻwShfY>h n\.i*eUVR\STk U2ReتUZj/dv1*Z19O3_KHIM\ D*p=+$sR`:8 (#|`$q6~63o(`Z r|Z"ŎeYL.q (E8.̀ =^o(\(! :lΪϑcUȇI`٧%OD;F]3ET1RKvH$۳:GJz}^yI=cB+4Ùiˆ<̧{*8EF䈫2nl܏dc_) cQEP\ J0* l1X2dJo)Ո_AkJGPiTҍp% 60,]§N(ǐqiӐR'$c"i`Qԉ(: 0;fp3M1yBjk[ >(yu +vW\޹^{]ͮu{y.QWOkv۟Qn_'߾u-a6GެH9?zpr%1݋ٳ1N1tx^1Rr 1Ο?)]5hq*oQ k[S5R5T[`*T*+r钫A._Xk>ټV"$JhăI'hdIW I'u pI8XTఆBXI]H*5C 6R*xB8rی7rцߠ]8JQ8{q2\Ǯ I85dVK[%v c\(mr:Q}c~2_27c W"9|9n{S0z .1cZ3<3WQpf$L5oA#,6h䤤䤦9~yc|c#O Nm^]YQ$0V)+T: {ʰd*KKT8ܢ7";c|ʆdT j;9 q@f,s%x[6T"6Ӡ(Z .z0z tt6;>T"X8Jf}e{{ ł҃2X͉ ll շ *vw 4#ch"q%[Ba⮕FoyWZ)uAI@Ϋqָr@30 3rMی ZYr3*'%zyH삕ap\58oĘGB`$1f]5"i[jY `+JO( cOEY'~(ج97넟~Lk= m(bh੬ &l+h8LkTW2YLDsvf "7әZwfO7+/25iuc@]SU'i?A0 q8A.q!@~\]g7.I pE@_ fM>vXؽv],o< Y.Xirv°I ֌P]3nގ 11M<,(k)コ*PWVin0{K<ŵ"@&PBpޕ-|$gOv7'3ġ=W D Ov\I:qf- b%pf!7& !/hLF,tmBIkP;\ECT6d aNt ٸYT<YVN6.Dr,rA380q ~8' ez :v=玟 wlݷ-uIw,e\>.J¯1ZVLK2w,œn__,m ~y6ﮟιߟLjSP0cf:t Ď10ƍpN9jʕ+|o1jA)R v˿]^;Ohj_WL۰yJ_ጆ5zF4x÷ {xHN2QC֌/1ɇW `4G㉐h /`DH=ޫی /1OS eVR`Y!Uvs`_'J82"F[b=:7 bc@k% _̇FR9Az4Бcy c$]7- 掲ah0lEO/2O/}5!g!l* caAL^H@71p.!h }᧜]@=QW?=0eI,QS1M N!}9:8zqy_ zt3W1`䦦:ƭcC 8BHG/PP$jm76Eut pm+6|6xu*gΆ2 o6CO->i,DVnN4ŧQC`h`9SC=xU1`t&gU߆y;!o #X1$vWմ G"U8$ZOzw/w힀HP;\'9V>,dMb x瓉$drh}ĄJL8pZX ;0XDP뺲]/j Î.SlX30+X(8HF4h@.\B6H(hi yEW R&4.j [ߤ5aw$Kg %eCӏZ,hϽS4PЮn`q5jwΞ~μsNO8 !"򧗞Bш)PA:tiKs` A|Ak l6wԷt[&ְ[уTU&h ;vu"Ȟ,uBۄ ͐R'7¼ u0s^'-q"lH]6¯J4$˥ > Z=ֈcP iE X3-  Lj|t\1ww;}=9 "ycqs 1$i&,PƉkPaIpuC w>jXcko8:j OBmIhȌj5 i1E!g륺:ݍOiII>G'$Fmbق0zF Gڭo7ΚM#yagRRe@¤18-F]E)pS!29AM;#4S`В1wq+L#l 4FB8if46 BdlDg'P^-m(jCe sUT3:F1iUc chŎ!fL,8ǡ{D0r/8L[擏Ic\ v"yCv @$l 1~q7FێX}\'.fW]YW3pI}6 fk9@>TT* Ռڙ["^rDX.62Ÿ&<fX[:[;ۺmP`ru#6zuZ'/"ahAt#tf!4Q<].ѩ#`h|Js0BCZ{J<%uXAb#| \]璌<4Lfw #͘1`: &c5cF34k {Bi JawM# cA .>N3dB`ͻ"ЀFljR,cşQ/A5#:c42 fCxaqO%gcLhZr/'1:?Ξ~Œ<We*a4q g%?- FQf ׇkٺ%uҟ_Vjrj@9DmR_k%R"jub ؆;Cu5o"m9 ;?BCk5 {D j(Et.m\{<0Xn RW\^\%dɣ :ҒN& cj$Q eL(iƄ܇+N(cfL^34/緒"R6K A[L_YdD3d14+702&8 it0Ӏ=Cbh̘|(3f4ʘpaO13hǀ8"BlZ>2'7^I #{v[cOxIQ;/]T3W妠TJLgP@i8U~ܣqG5k౤ 5˟ws'iw^֍[un#&m8H؁B 1rN95 Uas*&@ 6^X-0x\D…[-:0hdAkFMꌉ+$̘LӨi.N3p@׊]g-B3X+,:<lsmb a5VP3&Nf&ݢI+1,Ҥ vQD1t5ӈc\$Av Y$HFz+$QsW:X!,kd;'ut躽D$<6_@Oh?lt;= n p80ʌ]]mrv= FOOs;4t]~DwvDc<* |xl;x^oG #CE$IDҖ_klh1˭ɻFɋ!vB9 NgIWO,3;^XeiEsKs{="z`$nzLƻc8iM6KԼ)SӐc/cp;P!4xʃq?f3i '_-敕6ܰeƭk6M<};WnڹXnkwoh`" qћzc%Gr$Gr$Gr;M`As%1 /(ǎl~}mc%Gr$Gr$GrNp`7 K10c4۬qw7_=QU{Gv[m/'IdBMZ$73ܴ&v^Dq +y ;FaŒ c1龞~τu?α~뾭}pݾɑrOOtXUW[)=1NE8Fbr qw^<~_u/: %Gr$Ǹ&;;VowU[a Xv1p1)Z̴Lvǝcxst }Q>:)ow4 ڎ>!o~5WƜo699?8Ʀ7=zQM;qƪg:]`X 1 _ 9[c\J+Fy]6Z+G x1# A<g]7]XT;:oz;h_&Gr$ǭtĎqEu|i[CኪmƷozv r % v_3iϜ;o%KWZ7|uޝ{Cq⍣yѩ|t!okv[1r 4i:OD_#1WvFC._ޢfUYr$ǭ#v GO`ҾIZ鈟IG2%VK6_Q | [.9W9ݓ׮]}Ç9s棏>JMMʒJuuuֆN蔊NOdG1H.꽿y%ҋ MVqxxnJ?>*q ?c`V)Ѣ=7Ш|?#)xԱ9ɑh16}o#?_\vz}|x?LIs֚[MקH`˞wwv?mJɮ!^9|C+=1gpwZïc_(HG[ǀ\}7t]m[q0{͹kgUMek4[ԯ!~v}萿o<)X.%ݸxP7x3$Gr|{'cp Y/ގ㹚~'*"Sަ>&T$?~?TY݁!'@Kh "1 )h(Qr%1yg8p7N=tv=}ϡ-;e=UOnpٟݓ;{oj{g]aEǸAFM"_+^^C E\sXCɚ5v܁ȣ ၉r $^{|NnH0G? O9O^z,9}cOFsW"?6zHޗ c ojOeiG(-diٳ.hO^3ϾWѩswڵ0:=:螵c9Ɵ5181hŎQz5Lrz-cXxmۖ +V?Gs]a ma5,[m&~71!.=SKPSC6BMG`tS9U9e/#َyM/5>D١8$>#|+ס5m. 2iƽx5_ C"~\O䘠c1u%Ӄ4݁I<LzK{!ˁL+MH0=1jIXcmj 1 =c;ƉSX3t5z1lk8Qz;ƢQsjĎqQcv׽=+ S*3{毝hkE:x؊ù'!Ca!71l~W\{VمnSUk(x>ɲ#~ۉpkp7D+:6?wpMމǿwm㴭mն^][=kUpoATTPAeȖ=EȖ@!! {e/AOH}!8UUUL&p1&OlΩe3rNC-S"^cвno^AhsC&,'-/x`QS ~U'Ɇ~~l6fC q:)(IeOa|ENaV꿥~^j=1LQm5ԲݔFcX=İ!9TT0|ΠeڅqeX bD.F @mVv v:GN>+Cx2;7Fϔ#gYSs. 3O_xWLzޭ[ǂ3Og$~z:ax;MD,XV#i[l}% Vza$'8S|woyeZ 6q-+wZJ4X+WJs,ho1xq [DϏ[0 eGjWna K13tVm!30Edme˰GjQ WEjaڞR8.c0fu`0GR5:cdm?U0r8L}%80W(øyO7EGo[]d.v)d#X^"يgWNLq¾d'o9xUoO%oV#*-ɴh!?ս"_CRU%*M=N]D\R .{9Sj+T+'iW}f?Nzޠ"iU7 qOnX9 YkUZ8[1 w'/%噛P(86RcͰV/4!}tBmwvhhb,{̹͑5qJ"TXɞ Cx5FL\<"%8O " #cdiQ1הV6F34Xw<|fAc|!'RDEKQ+Mgj"1v}_8dUk[~2_,IPz!kN`X>MQ)igWb2?\---%}q"Ƚ1jJPq '0a8VclreJ(mH.\u2r"LK.aWOcviP<9EFZ-X-"#kǁ>cƘf3F@ch0libbxW,vW`-P 8Rl$xu[L,_ުP8V<]cLTc$2 yCMWVI:Y,Ι9z(c<`*bh*Jm9D3>DP&G߾pp:?q]?%lz@k~jTw4rj[y 1s [2FCqPE2px-PϦVvc͹&:1BBBճO#cact8EFì){@8,\D34O vyÐߣ+#-i-eo,о BҮA~ .WnX7Dˌ'JzKLQư1Yj])loNpacGe|]6PZAP VF;9&MUR(k#:BPmL"oe}O>Ĥ 1~X1F/08Lfb;;uM2G8/?N2dz.wm67Rt3U]QEnR.l.} B۰XFmƖ?e74}K?1c>+ؾhwS'ް-~ݎ-%`n_:ѡ$4-1e8Zw8v$gou3T]_ d5)jjQyP( 2V8olͩh)ʶw4UcЂBy h Fc@`$)VFMolQ '//tP( 2~bnhIaR!vN2`"j-/o_Iw_\1b I1lFR,~<:ƸTianݺyfxx8DXXXhh[vk?*;.a%[,P^T: BL,Ŋh >xp4:xy/_qƝ;wZZZ9rn43$$ҥKpc 7p 7p#to!B  ōѷDc  Uưlmm;%ZYYATڵk۶mk֬Yd7|w>WvGv'rxQ( eT(qϑt:3g~sYh?b sssܺu+t (܌)ܤ +ܼ(ncETh `Ccpgd`Nāc&X v ?+}2k|3}|2(ܦf;3BP(骽tB6B9lt fX,= NN` p8vߘM*ܰ+Ȏ&{(cQhAC#I}jqpڴv y 7K(`N/9rg/Z_Łq14CQGfGVGVIaٖg̣P( 5}boOSLXۦhyjc e_04g qcHҫy3m0-$82nmEOvgOv ݶs:@ 4Ƌ m.\2Ů4O2eFQ˯hlה{\g+"E'1(jй@^cWp.ɱy111Z%_9q51`IO_ϭrl'Yտn9tz3^ mg2ٴY$}z-2 CP(ԳkXcl_Wu/NDQH 8xN[F12eK{l:A@`z2|㶶^qU_6ژU/6Y_kt.++DS3NB<|b?|%21P(4p|L#n /sp5F~rUՠ1`~߽A{a-X;fo0 G" )%nj'^vl-{?]inu` c^cK~9ǍU NY @( e kWXyJ,W3H9޽K ҳlHԤT*ڤ?:`lQ?'07gO GzY5?|֞~'e;6{`Yʌefo=,gDUUK[_tLx8;(fo,W_ پk7||NSVG,I~@02 Bf3+ _+ E?=]kl_^7*:c-4<Vuc9QH. d71-m{W`·>"lK_tWxܠYJC{QִkXes_8v/ (x瞽`2 =P9 \ r=2~^X4O#N 14ƛD"Lʜݚn~B }mK.ت6ƝA+Z7Ê_u@g5,-Y! Ac_7 [ #l^;9ÝZ b}`a(d  2͌4FPD=ā>1<9-34:4Əjc?1ƿ@xw˜u/,;rBuu5TOnJ,8zwЊʦb =` P"qclⰍ_c_|&NQWRD 1D .z{=n:Wr*S뜛k+12 BfB< 1RbHԸ8fCH$oY mïup`yޝIbBt +1CW9a1_&j^Eu";eo/[a d  2͌9Dc 8ԗ|~`isWCn83<}~H-#% 7vxeoK/},?ݝ߽E7 =BZ>ð [akX9. P ~OOPhwʬp*q΢dH\;| BL3#a5F wa:U@"{SLōLm H8r*>Dh s'Xi /~7 >*;ܲk==r*< x6!cBL3#X-y|1~'ҝ0c_TO gc#~019=莟z& oէOלRw!] p5?X;DOdz#C@P(lXc|Ғ.l@_$5-/cƘ9WsnTZy 50b'蛯8 ;^ dM\oC(? BqYx,D3DYk"cBLa1s%SrP5 ~)Uu]S4<4YOȌ~H cǰ>|Ca?;Aަ7.nW}YaHəӳfd%eedTVUO|1P(4[UHT!iTuMlpwvLe@f(H`7c#1:;;5Ć@PWWWZZJPrrr3cɱH}jc#..NcI~a'\8"&#/aVrnIV,?{gPG/$'&&u# BLaQV.E[כkcƐXMc 12?LHСAXenAP!0 x #PK+18>AEEEuY #%xYRR2+7d  2͆5-*)o(ۻ&Nyc02Ƣ>chk rr,9%Fm =1#2?kz\&ԌRI{4JHϊL7H9zH  +e% mmm{o{_RAT*Gw􆌁BPٰ0f-jn%6U{;S{q!#a0 Cc8;yN 0Fr8{`Ƙ:cv{i7ڳz\ q7%')\'Eb@ƨrKjp FuuuJG"T+u2 BfcvzYk1l|vt6c(c,C g7jagAV0%FRttMo( e ku;6J8M}1310h1ܜ] )gر3.0?1:+1c@?>"h b1\Zάa Ţfd2322ࣷlx 'g-rE.0+6T( ek ƈZfc| 4F*88CC?Ex K{B QK(eU\Q(oQ)Z3Ul6sxR۫]olx@$ŢQ_1!cP(i6y ^ss1"`2 WZc,5F\a0MMMSR 3ȥ 2Ee}*BL*,,x0!77Dʇ1 \3"1Q_1!cP(i6cpcm12JJ\`XrzdTyXc䏵ؘI系 趺ߕTEW\DɌ֦JKKKMM BLy 1I pw<7Мwl\;Z0 =˓RR+ba3<{<ٵZ͚+tyGIޯښ+W' BG@P(Xcph2>#cP:)k%D'܅v4(Nb7c 1E4CSkkk 0,!v>DXe'].wk~E 8::kjj\P(X`BL3Qc<0 #w> 94 qwpV1G(LJ)CRU*T)MXmƂ*[1ؽZ!g0g6bh{YY***x<nhhP(z( et>z01!pq8qx>1uչq8yu1Zc S1OϜHq*0,˕b,[ceJ,Kj9}t```XXիWw~c6 1W>bd  d19Ry%͆qΝ12_zD1쏞8ٟ3mdƨ`ha1z0&3syz% &0>by2*:1\nii qȑ ͣ"o ĄvMP8X-2 BfF)X5c<$Ac!-)k VAkwuCcԁ1bctcbEX EO˳3FSScbB쉣i)/~wҙ_왷P 3܂1LaXuWOcsɓ'UU<70ѣd>뉌BPƨPXep_ԁ aqc;qI8#Bmġ1{I4uvvhCc cU%svo߰i٩N]˼_liSCDfDMcXfVŋ]\\3rΎՑHx'Vd  2͌1FFhQ23aNa14Bc0FjLю6\ջQ<.!hb[yC9mx[*N]{c!9Q\0MMM<<{ŋ(y%( HcTrU*8Ӑ5{K 8"g ϑ1`QQUBmɢV\h}1y[Bq澙v7! e7Ai|G:8""ڵkaaaeff{:31P(43Mn\=Z]/9s5FHBHv @M poc须mE^e[ͲnYے-lsߙdْFf׳Y"d-Ą^5LcDÁ1caclz 3cĕ:h FK - Uc:D[kseT.-T**57>^$əٹذ0k׮J$.4ƀ fX7ɓ'1=3R2S``sc,1\q'CD`HHHHII)))QhFGfgfڛj[ՃCI YYY跀~ב6SSS555?1 }c|۸Vw#fX#00'cX=cxxf 43c,a1 YyYNVfnnBhnnPRT\XN,..t#T?#m^~-77f Hac4w kGZ11 p;lf1ߘ1&!1 cjժJe@xsNdddxxxXXXtT2F\\˗iii>*׿<0A041+1lb c#Q˿1Ó 3&]l &kU331nܸqكOJJJ4 =:)Q1 1Ɛ1z h]7W8y2YI#2F a[)1=- ,naEEEV1,0c72<\%ߺzTFF:]n1 1tzJ e%^6Q,)Fc0=;`01$34c@ 3c-4W2eAH.E!f{50c~(e rvc@ 3Lc ]C ™ in1J,MOIQ[[k&fvc@ 3cLLNS@o0G}ē1RCf4FT12y\Ÿ1,c1h4*dL Qq=\v;DVC`  ai D 4C*:FcxH cQD#4 c8İe FCg rF\Sbwc@=cт. LcYn(71 cO/f"gƘ0ci`2b ٱbIam?رz4ר'gqAX8Nt Nt">11Fii)10AgRChwsc&"cD܋Fp|a]]]X=B0 laq&0cX}@kmn7}  Ha2ƠQ}ؓd!wi9e7IcD#f"dql [`a d #3f8c١y"\ w0}o \ Napƀ f0 1OO|c^ԘPAdDa`35c݅ ؽ;cz@a 0A01ha-Lcd x0/2Xi"IQ%IQ݄1>7'$7~j/}fvg%`s;aW~Bv~5`  ae ha>cȖ1‹K2ΌA X|^a Ñg(f,w$ZZ7,}]5~V' HcR?7G\l 2zc{8lf qVB]Y,ic j8{ ZNƀ f A܃n4Ɛ cxxz!0FDq"..0cvf0` A #:1H$7S3×091 ‰>Ucp0Ccdi#n`  aq1*̲o +QD52 1t=#0A024ho vK :cyzu"#f90Xc8 ` {1 1&%>ˣ1Ơ.nj OIfgg|>1 {w'1X/1h!-+F@# _J1USc0A01rEqu{},ngl a`A3A]o buUϜAN`  acBr jGӎ`004:3c$r` FK |cRƨꝫ!{n@ ư Hsv~c^ͨV19%o oo3Ru%c$H )Ƙ#cl #081 ]cl6v^ bƝZg*0q7wXM4F` 0߁1 11(fX# /1lcݒ1|1(ȉ16 0N`  aǨ˭4c1˃(cJ#4Ƙ31LP10c@ 3=ZrIoJK `İkBscLcƀ f A cٳ'cþ1||Hfx+d21%Fs1<01 1:r @6We+/Ơa"dn cc^bC&Y5 Ha#6b1|c 8I_oOw1Д"6ƜEQSScJ3c1ƀ f{ b8a8F(a "`8b.0A wA { \ ck4  1Q"2c;19%1Fss31081 5Đ81B" Vfu111 1jU`j Da q?hr1 ƸǗ1l1f+Lc@ 3쳒Z3C,cvbagW,1,10000A0c` 3\~za BaǍxh |+122o #0A0cr=i<^hAocf 11kc(x1 ci> e dˌQLCl\0A |Lq<0Frcy0]`3 Hô1Fzz:Pm #U_Bɑd)Lc!c`ƀ fȭ31[c1NXa{3JSc c1` A qy3b0i $XƠb1"=FMcpĠ1==` ;1 Scca hqH)U+q2F';cPw1ƀ fcȭɫ 1J1#gUMmUa*U5ʪEeLY-UT+KⲊ<_,/.WJ5UjukgWh{WMcXV'\q'3,.fBO A$A2·14 #`#+d 1K1]6I޺7e۾ԯq(;;2/(X"A\ސTvKy-*<:ZTZ^:-_YܚWy'ۧJƀ fg%u16cD;1Yb#4(dUcsb K 0MӍQE"].Sx >ś76=m;V/vOk{v 筃y*SѯHu7ۧJƀ fƈͯ'Qo/^i  OL(c<7qϩƘ54Feuֽ|`/ۏȷʶK?(gxgw>W_c _}%<\g:Gd+o&1 pJcJ1BYiRj3%1\bi +T|kʪm%3o闁G|TwWW.3?ɞI.sTr[kUoxV[.5~|Ц6oT$fsTA wQPa'N4$q49VzԞ1ؾ0XC:c(*vK{wOg^_Qm nܺѯC/^GԞg6?_mNP'{?:Ϳ }quxG}/ۧJƀ fƈͯ71cpİmw(cCY +c;%kƐ2C7H XGoy_S̾|Żo=owɁM~~F^vcQoMV7 Ic@=F12Ōpww44i } ՞N2ƬE1<^Oő/՟ͪ=OU*0A0>+io\-1q*͌AN c8Ġ1T*]aIW\^+sW16iyf/O"_Z1ukp^]vnp6~|vӋ#[.~ymDj;: ƀ z7qa z`211F8ưpw1ʤ?dm._%C߆7?]dg%A[G %%6B\:|:(At%1 5WH#61 1X#91\b2FuuUcHw{j9[u&? i¡<:_"J %ȃϩDJ~jOL/R1 1nQ29ƨ@1RVajԸ򽁹[J?|e_?5Ǧ?O&.x@ۋ;zu%=7;(ټ䟱?ޞ& 1 1 8 $3c8 1|cHUW;*ۥΆ?TGd ͓{ %u%} JY?(w@{ (|c LQ^^zc!c0$Vсc +S(9R٫胃/?ag\:(y^qPr~xP2N|OtG?0<{ (c4!c510Ag tPBc1Rx4 0/s?YGۿAQ8(ytPi8(yhO ~tv %1AwCz8+ z41 4F c|e\-1V_H{.- =;1s{ZVJ^2S%ȖwAmӣӉy>U*0A0cb 3x2>0r91NC8p֖1R7=0Xc%H,;+~woU+ܨ~c'ޓ:(s]ƃƃo1]40Ac1f |c1*塁g67F ar4pana cc$^(=}Uϳ)/U>T轳хGd] |-7 ~LD7Njr~-6R\帼+ɻnnj.A8e;j1 F񌑝͇1dV2<4 MH%ʥ1d JcMTv+Eם/΄߫{wm_ Aݎ8|бC!aC܏yGySSR] zbd ΍tAkP~(6x'=qMzR=za[7gſW<ꖧ_[Wm3ol]Ͼso}_Η/Yu׮߾/+ƀ z4];wƇ1lC!)=H1×2M !I7$&cP? o[١as]/q=xở}=?<>[=Wo|q^5҇yÿ/˛-MR1 1R bAgғ~^^ާ*dk3d4;0&0-cDͼ~GmUx|u6.>~uZ&5HYZ-S*뛇mc==ɡQĴV7;y0;7??p'Ac 52FI]|Cn1^,#8%GI5S|c,]>+!fa70A0.\5FQFfT]lčfc1pc@ 3&h6cAc8İm cxBp =#c|b401}mbKƀ1 caǏ4iu1<}1C)[ntjc1f^!CfMe Ha#|0h!%ab2KFc { vK HJJZ2By496I@ZR;Dؿj1\0A02FXBfGÞ1 Qd 50C7PJ0ـ3Apь!֘4c }x;_)0F31cCc1q1qiaLw0ٽ q;0\`ƀ f A09cpĠ_a4i -zbAl3{p14 P@phōfCucƀ fH4Cwk 3cȖϧ1,b͔=.44~gPp3-/@A1 1 k+`2FL̨03<=RNC.1lCRWô4;`  Ȕs!JfH0 rh j&h4050dXiBvETïZҹӷ`  m3(clڴcö1D02Ú1 1J(ch-zcLǿN/.u'Wƀ fLeee4F0e @s`)UcX!ns1o/kc@ 3\cC23&04JIӌA fƘ'A0Dư Ha#` bt3mbgCNc?9 c0\-1VϮ1Ժbi[`  a2̺18f.#0=0IbF,>0A075 i |`m!a{ 7v1t` 1 22cnLa&cq -n`  aԕ1ȥ1.1$o n]3` A I&ca#55cȌ4FYqe}ƨ1$&ct:|c4#`1pc@ 3î1B\f1"q11 1Z1dfc1V555c?Aa0A Ffh84;``k1(`TdE̍1_?F1a70A0cl 1g`wJBo 񬄚%ct6*Jl%4AŒƍ|Cf cK YQ0~4` {1 ]c|n2-281#K zc63ĉ`tJ;0A06Fa [4 ljU~1S1Q:|V 1vc@ 3\cri t(/> ,jcXb˖ȫcƀ f7U`3O,7d S1m;c{ 0A cq`$e elR.cԳ3%AŒcaSvc@ 3'iPJJNAQ`pV80ƀ f2&0XI!c߉f/0A0Oh ?P?k{z(|cprJbiGڡ!ntrQ7˷(0A01C1r x1ڙ7?~/oj wf,uj0br nr@)Ӎkt>/AQ4T*=+q %)ePDQ8p37>s~,u?n0cz4kf,{f<{z,}z@@n(W7"ՍLFx21 @vF2Hf,*'ʰcp Ƙp1zrNe/][L/(Lt_ꏞNϝT,+%ӣ]Ovχ&0A0`tJb~m#h ;]va2(1' :cLPx88[9;RPvQ(X׭$乱ZvamacaU A$x2FJJ Ɛk 쬤\baw-0(chZ|c7LFc<-~?i(rbj4o) 3UKw7͎͎-Lk&:x>41 ˍba 3c<7O Hf+[LQ8abF爋+k3J.ΡsD+5ꁾ.uJ\x/5lI΅Φ<ہ1 Sc$b#>>cHͲeJ-A?F$6) QhAc@7ƞzdl"I]c~^?3۝XHc@Adl'`Ġ7Yd;YHcV';c47l̰041 #c$b֭[|C%0Abk>)c|zIuIʵr4z4}s'01ƍpJ&RVA=5qaT\\T&j4ꖞieeBQ5PQRxVVc@ 3Lc$b|291{֗ݻZtUtMOۭ6S`<oM^ijt1agD џOUuSU^[׮iSV6uD{'.0A0s1\bCZqn1+-% .VtbWS?6odg $Ƹt钙1]n2cg+ЍqWbΥ&ʼnrqw@78<7oUk;:{E"O20A0cn Uca 5\94{4w.)}1?Bgc7n YX-ch-N&.Ѝ1W#sEٙbO[3{4>~mvB;ƀ CCp|Ac*n1>xkmwsM^܅hb#c|,naB3hsakSI; ƘK^iYYe2eE]}}[O(J96-zxuN7 JJYY A$̄l [71ݪIclxsm:7|n9j:7~yc 18{eQwwA0~sa" x7˩Is XyMm ztcp Zc\tIX$9?19J1;h3}KwR1m`}lq39Wx"X73TwMNNEO=a-h1 aVn1ůlT(MA=V1+0Gc\}ۮӷ:G}z9>JfzT,Vk뺚Z } }čӃa0S&B66A\c 'u1*'܃0*E+>l 1f5Va 7J wn7ԭZ#ޟd&'egK2AjKZVk@ƸtRWWz}}}Yu T!4cӦMl 0{qw1cդ.|Rp"Fiݍ92&vom[mGiy?z$g{fBhaNǯTkj%byUU\Z+t"qiN艏tJ 3cBƠ PZ1~Tώ`dc1ZZZlC{2̉1+/5|Mˁo~֣CȈ.e Lmi:nVzMmwg-dċѓ@O%`  ƶ1]l{S2Qظ xy*q^Zu F1]]]t17]-uMd&tb/}\.)/+jRL{w}<bBBss32z1 qԁakWJ&C_ ?-Ў%{1 1GcZji `Bӭ9cCٝIR~Q-^۬oki0#N4Ѐى188xx+A݉Uc'ƐJc2FcnCtR0SGI~1J/Ҟ&ѥ:epCd_uwtspHwb Nd|#A܌#Ơa׬WWǯ宪`& rB;4]`ܿߥٝRZVrիA~n{K7 GGFEE666K J S01 0hvc#[=ޏ|xf0#<40jeEblllHaBI+ c@qIjuVx]J1^mdGq`H"2E`.1;q\A-bX3ƚK+ECV!\S1Z$9dӭWm}Y0ƀ fŋlC:ٍbIľ/N._ʤ…cڧ1 h#Q* 20F 73nc( \dM-Ƭ0}YfLVʌ ,gL&>;Slc50A7nt8}4ƘvǘZR_m`̝1L+&0`O#Ƙ~e#֌1S SV%3v|vR:1A\o 1 1Zhj%p( cO3>Lcb5`tb~YcL;a捵# 0A7cbրan't>nKڴ. b b -]cܜ# V35s| c%϶aIʎ1(:U'd1 0c i}Ӎ6n  YAnj"mc˘z.s>'}&z,V1G\$B| cln 'ar|N/ 9c-[a f+qc>ۑ4ȤLEb_-cV`1X A\c 'u1Eeg<ԁ/ƨCUO/b8m}` 1 ׌A6#AfL1v6a ` Vc@q3C P4E`67a r,訷C]r1YĘif0S1 x.4ƒj12ƗWXa ݶ2l fNƸư qԁac< 1p`R5Sc j dĦ1 2OlC]DL%f @Z0A܌#ƠaԈy~eawc1p`\Ҕ1l p7Tc@q3hh|6!!j khܡ.|w6 QÎ1]İc``1x<` *1 A֌~R2ơ>^ܩ-8J)KFCfA1ӂ1ƀ f!dlƠ{Ė1V/Ivf7ƓlXA /y7ƻ֌"i hCwƠ 4F#ca ɤC.M.$ dϚA%0e @R42n0A܌1 ñE kذz\*<'Ȟ#n U4 2nrdzk`1 Ơ 1F#c$$$a f5.ST?t'2Ƌ>.nF 0j/tn 6~:Fy` {1 ec1^İn aĸsWWK^|w_ǍQkF0GN"8A܌1,mH6!Ѭre(>4!'߫<2F uTd?z5 cA(s(ic8 kشfJ~ja؏݈'uQ'H R1EqjA90A7cQƈަ&cDö1f1y'c A\i aoq49&i4"ƸucD011ƀ f.3 Q'?4z"WcƐd]~èp>A܌ư xlc~C'29Nc1,K` 1 k6dc+ɰ01k_I9ZA`'{1q1Vc WW c@ ? i:0l{OFy<1Gx;?U~+h<>;CXqbakk+ƀ fl1þ1|MST/E]&&@Gg7SSA$3hd5W^)(W_aS_a-co~wKێ- ƞcװ}1v+ Ew: cŅ9*c@q3VlC,ۺ11ٰbQ]lvݶˠ1IcR4gKKsiI1N{.t4+ |%a_ m;-X1Ưo[nc5`4ƌbː;[ ƀ `tʎ1h-bX5q-8#0FGi.i?ݲٶ18}cWyg|MikkӢTbgaa`߷`?߲(o4*Xێxւ1 Uci#// clݯecToQ#دJTbj7K"XXa,%r֘Sa56Ah#10v_Zz!|⣕v%u(|i|7Eqԍ!h7ǘcE>9K?”V6B*U{.moư/SGr_G+bG wso^^t/䟙e|11AK1 =c7a M$졘^ƘiMaF89Fp!1Fkp͉1RRBrKd20?{*yC)Cدʱߑ}}<$q$"fT1.G ub^9Mc@q5H5]c\|18Jb^D{{ظ.rHyj?5TըME c1GJ.DƔV=RP_UUUTXTS%>^} _a]-~{m>&mtwčQc>1_^&0ne6EuAee5:ƀ j:aƈgn5+16 2+ oXbg4|YJP`~j#Ơmssgt䅚eTTLNիj{ ^``?~q8brISdzNv6?pv+U%2Mc@q5*ƨg/bX3kVQgxۖ11Ic46`y#k+fikSj֔g/>yƀ f1Df7ʥ5ݖ!Cȏ)E@R[[VAkGCCC!]cdXdme` jsn 1c-2sQT^Ě%/jy| fĒX1(ư'1֭M?0Id{  a6!c,z92<1hݨMc/+3wQ$?b~fC9 ?|p21 ]c0j ǀakVm ǍQǼ11DM_C[1sc&aS`UƘX0|0tA%c Q9iK1Ιcv']u`3F4 Y4i=bccOc@KG)Ά1D3a3;9L*\`2x=1h1&qSĮ1f=sc%v1q&L<8'~< _7Ha,bP2$cX^WBz?q} ǍA( ucxxxL1F3~Jvcbz< :d|bc@q3H7?Ƙ cJx$GV!Z0 1 %_Ъ8k cEc@q31f '1x]N|>1-j)I]\O (L lʷlhTh,bP1Fppc'c@A6c'OdkW=wcU~%* KѴDcot18 Q1b 8x uc8 XZ-= b7H]' j)3cvj1񺒛` 1 mc2GIlcnswEa'/AU#MI+1:5@i1ƀ f͍ c c cx97+1Ը.`8l `50A7sE kX7a=gј0Fsp(mcY!cPA͸i m d {,tJc[V`  n2c 0 ;8CTc'cC1\İfjc A\c 'u11LP c7+!uA2kp9 !ncA͸f *e )n 3q~t"Ƭh4` Fc@q3pcv#册d "|`4Fcc#A܌SƠ {p=dEx*y @r߯`1X ACG%%%.7!wrE<~b. i>` 11c@q3бg  V!!L7F{01<1^Ǡ1lc41ƀ fQFׯ_h pJ{&1ξ1\ĘlnhcA3Fnn.2ơXx1cx`  nFɼz4l"cxY1FBeZjei f`50A7c ]2ecdffa 9+DÍㅿj ] iTm fX1881>c A(Cǒ1XİjKk{ p_j22?M1L"0ƀ fԌ1H10pRcʥbك ڥfccl,b0A!0A7`qc,3Ȝ1Ucs7 9q-5Ky~Ơ nj!cP A(1(ñ$6ڊ%U";ucBcV"77 ~-ٍ"A1cjF$ 38*fN8itW+c<,nk *?¨l,JdV2 2)3A1.{1>^P~!G+QW:*7&cĐ8c,y.TcgxĽЩFMˮ|c/1*н$3ke2$c6>cZG}.ه_^[^x/1ZeGMi[6oOv̫ poJYh{G J=M3%ҷ<8PPPPPϭƱc;v \H{E{]-s^C/^}B[m7ȝ"c 1FGJnh-+[}4Φqls Vm]n3ncm>iHEצE bbŒ|2[^[kʷ;#Ɛd2CZ˗ٴ2Rz=:S?'E@ק38T&. бTkӇYc޽t0x1i}Z[v6l0] lm! 1˜T[~GAwBf]gRRbv2d ((D7cKmSU5v*+c0 :2~`[̕%1>Y$|nO1q1_}S#K^Pc͵U~5  +-y-_daOM:˛+Z+ڦ;L;]mnnc021'@d J1Rcƚ|s[ÀX!`b 8c#0F)QjbF]sY_/齫  Yckc㖘˯YwvY^Z_`r/iy5_ɎNLJ??"Wӑ7 >(*fMgUMgUONO7O_Ԓإ1jjyd ((K 5ϊqJ2EgIdd!U/ %8?iqAXm Œ 1(3 3'9ォ 7^XntooIZnX/q~MhJJVE5O+?7rWFD\/Ϣ3~OLtBtXۏ%%]Iьed :Jedt.mGZ7͕n%2F3`acRaX:#I(j1|V6 8 {wSΗa *30e`ƌ0FRZbۋo.P]ťFG4/X|`ә]qrFFgs?z#/F^E^KG^+@^800 )ȟ$׫>L`. e :/YsSCowFP AƀR)1$V!Ȯ[,wݪqv+4,c洰1#W!CCx#lQR>Z--S=R={&[( Gc, _^ vP;f' vp)=v:mr7ϋWbx ::}8]wp ҒҖ.$uc ?ɒˋgFXZjs#$Ţ)bl2FU:g K2RcdzglJz7^uɟD,eId' #O)@q?be ) j'cA1`"0}6g}do`w|2F]r ϴ ]rPx/ Q)k&̅o|:[,U L{5c'+ -bX|ՅUאD^BPýC0pq)Sr{{{El_I% #$ #wBTg 4Fae 1 rߋV\J |%aBƀR)1zGv5$Q46Ch'%qb+B(*L Qhɓa8-wr;E![C c䡀qh8c|V@b 1q5o>>k v/y\ӑb/n2+.Eϗ@1Hoqsir]cwҴ'')99u'jqq B` d&'KHkH!HJeHzVq.r~_9FL">-$r/v+6/(NL1C%2FPPQ/Rc k\^\;K1-~I)" @q~GLu/?qtiie/|byGo>(f¤z j>3j¤+vjPTbEc -31!"31؃,v/1p"Fe@`P*#%0FYGCi8GRˋ)k" rN@C!3`dd k4{j}|1ibǠ)1> cl챃g-޷Փzм{5_zpA\Aܑy1Gq֊ +6^U/ꖮ*-/KRj1N()cL_ ?!dDPc} Je(h磇GӻNx {:f l 7)Nwb[RsPC`>/1ne7bc2g\1]M5.q7\}ܻ+)1N1N>d@Gj:x=gPNP||}q^E_0䅈U_ߘ311~V5=UXYcCd|LJe %{DU jG1c4C3A 1xa11Vuՙޮ dࢣ,e \]֜gz?[=hsS6oA~NSS=@樸r:O[$D&Zd (#aiv簪Ԏ:cd4p11` R%ևqNQQ̈Q_E,q㳜1&&&X,VtRc_0ZN+_=۬{CAAAA)_1zYiu̠1$(Xfea^jw^GwB<ӂ=S=zR=SNWiƘqɿCAAAA͈0 L L{Ld`%0+ s|t--_t10V!c1 c(DoPPPPP3"6caM6TCc|J;?'ՎV;Y.)_dW䞊cHW"?`CUrKKs )quh(#`K1((XR;/;s.,۽;YuZInPHc\1۟#~Ő ^_ u2FVVcVnVvXaea^ۋڸV&%wWcJ1ʝ;PPPPҥK'O<|bMA0D1*-̌={,ZZ.} k4wpጛ1㳀1\w";y' LBO ΆMrq>tqى} ~ QmPٌ+9\|~UEzځ:JlcࡌqNcư27cnEantFW#3cuhoo'Y_Ɲ1KXQ,`2?uрw'P<žyXIl|׌?Z%Mn{ /qV Qb;V!q !UCJXjꈫQ0P,cPٜc IޓBH(^P?pN,'pLA$d 1T J¯fÇߚ)P@@%cƠHJJ1 1+A 0^ct4ưu1۩R|_bx!u(V>cq i{f. cH5NN5CK,c/K^ _AA)Y5ٳgRkf@dbڡ'/S cH c 8c|Z:C4x c>7#IZ(&2~1>TI@ٹ@;L#-JQOQ͢B1CEыCվ RƠ'de20?5ƈe +3S+N W%cK*1dbb Mu4SoPdf.7uڀ1cH pmfRmK21d ,<` D22N`)c(Kg p¾? \_d!IRY)1eVMi:d fçf$Ge(d)j'cԈaׯB"e 55FjѶmloߞ1\1|8FJ[q d Z%YĎp䍊 )M_zQH`\"}"!e&~ O뫩9_nn|0:Ye`!1` R:0Θ cVWcu5ki8w5T7!eic15LQcpV;`C!|ˆx`곳+5W;rEu5S!CjTípي16~Pq|QW죯9tWn!y{I3Ə?(!cHT+E%3WRS;}d Iᦃ ޥ H'~R 4]9_M+P;i#@c9s"CMfHw; ,cs6쨫 :v.ҹϷU d E}pRVPPJء IV~PHCchn3ɶomfd̟3m7=loyҸ}\[MfCG*ƈ!Z/*)1f:T cLLLԫ@{g*qQ(izf~dd. C0Fu Fg[eINGCN臌!I׋  U`dn8qݻwkUQ^vہ䌱g:C<`bY4gphr01x c(SR8 JϏt3ŋaBj(PQcR_snf[(chF榇-Cb d 9E}ըPVPPJ~~1aUFn&1` !)/k4*B<^vm5eҌ͐^2vTU` p"J3F~~RC=3=BO3:+ٸF&>IUkF j6JɌA0D1zfZdd,;}>F}%vG]%Kjia Rf.c w(6cWB\HKKC1((RSHM5ٶDlFƂ9l@c(cPb J*ƨ 2ƩS c@AAAA~c4)#::gL1#%hV:[ uf0 .Kvmef QAmmm1~#~Ơ@g`u2 e{.AVSfEO$0 c@AAAAA\̠t0FAA(HGCG }iJ6@|zm,x_T$ctwwƨ1~"2RǠR10#%PgV3p@]Eq& usu|Ro"!*3J, c@AAAA#Pcp+ILL1 0cu+cYzm3M(cl(R5uw)c2j cX[[;88b J CKDWiU7{'Pp=r:uSU7:cT0c M1)2$bC[]=#-l6L]R3).ccH>R1Ç!PPPPP7cl޼nw"cIǐ0D1Osfߠƞʼnc%J72"ek׮3F7cf((fGPmEb >20CMb# |p&N)lpgz\[Q׳o}ɽ]6fR055ݷo` prttt1d bd M4K= `}q?cr?~&HOcYUU0h.tgϞ_?0T?{D(?q}xX ?!uYOzY$$DDcJ~.r?"ۜ4OGh {P|D+m>D?7YH,{&ZO^wLq]tWq:yng{H}wD[#C"'٭w0F0w=F܅nclwQi=.ʝb|u&x 7WsA&&ImPaKEH(G^7=(0+:JMزe?nkkt7n #>S!Q/RXHidHNDs i,!w:`HÀ1߿T]]]\\ (..~Ŋ~Aj<tQH !?FAՅl?*l ڨ:_[Ljnpnhp3HNpvpv,7 e6pg׳҉}皇iSQ?p D'W'W8{N wB]QND纋ώTׂb bUFk &2п3+:I2,\,Ը4,5 $;$;τDO䭚 wĕŕŖƔwG+uA$kc-s9i-P̷݈ff lو:14 U]S[W_ڛP֛Pޗ\q' sc)8^8wiutwEuEuFa4>h9-hf66 ɨfג:u]PZ-ubsmgNGylμ3r: dh"5VV&I\rqCV6oKZXX8pĉ>>>ᱱW"sCcpN#FyYYǟ~8mmkM)3 Rd2KJJ]]]MMMBA0x16F10'1d a ?10bTE0?`aD#Ac` f%| 䎞 @18d!3DL ~~2?c0F%f:PbFli/j3bFSf䵅c&c (`p,1Nb1c4崄網1JK{CQ!cIlA1&3" ;" 4J"crF{Z` )C$cGbC2cpH1XZA0j[XKywzzzv:xɓ'g2FHcfN[&FL weg-Z0,q/[qg.ml+읇WYxy=}fgfg&83cVr$ATPEr$Ii18:Ց*p|Np~cxx*55ϗ'yG4Ci`[!E fPQ t>+:j6B۝@Ѫ sg Z3 `4QY0T;Mga;f``VhSʐpLCf5Ѧ14̶q 3kcly`cU>#Yu7jn xxzZ5+Cff*C(:4;vxЌ.ЌH3H)uf̀8j118A44ڰh*e V0H7ff -)`p5C`PCc`T'9goڴСCɗ.]z7,((t16ƆR0Wov<^C`|D"cs ]]]sss[[[ǟ;w~dR0;J&a8l"(-;1f!c__"%---d$'''==̙3`kZZZ` ?_Y',~C,͎?`>WA^zƍ988899"Ƒ#G"##OSSS322T1 F(Cu #16]֘\F4mWq} \`KMMM555W^=<4fTTTpp0(˾}7lmmmD|JXh1'{;Dwĉh1'=q+Ngf+&سAk@o12331J mmwBJT@wSkpTP.nkksNAA!hFBB‰'"""A@6ͽ:<===<<,^x/`vdd$t!E.o14 :Ưo#vWq-qcoᒑORʀ˃LKKaKNN>uCCC>|!|9 NI q'N|ʼn8/q2"T HLDX%hCx- kBp q3gΤE ٞ[1ޗ`sVD]5B'|⯯ |Br U*^Cydttthhh``kuuuii)ьWB%&&B '1"#|:u v'1!ͨIg̼zjZZZjjK.\q嬐!B$Ny'AirJH4\X$uW$1w]+ yΥ* OMMfW` z`ܾ}Eu81ƬcEz{%c,ጕc Ammmwޭ"斝}4檐4!"N.NKBrw.B}Xl1"1I]wH+RXҮx]1 VYbXl4&&O |a'\#%1#0#D+)Fw|?t R W3IAL Zڶ9777=6d -qrw뼓!$Et.`yH+a"y,)dTaE)WMAQVJ8l44>M H{K'= +h8c4^"1cCA3H)D3Ƞ{{{;;;ݻ@d 6 \)eS*$%⤘ww I> I./ ]^_5E$/C5E$/X*j M)6( ͅ !+ M /g]g v9 ~_U"fkPq t}{0@W(1`1#Wx@OOOWWWGGFss3FcccN=NN|ꄤwjwĉ7bw<,~"$PwťP<7N(HD2=*dC5=uRG % /w;|44 WF;ş}G).Inu .f&ⲬE'Z5Ylj*\C,Kc^UVThkj{*JiVp M*H01qiAi';ߛc̢4&!A4d\15G3"$g #PuHh5I }PG!jDBuHutHU(.~'Tcf&f&c7:FtЌ)b3 [PǼ3.$|f.$|53%9#вbU귴, ao a갗떃cQ`(gR>OG"$De"H]{ -ΈWYBZD6_E ɇj#UdQۈfC0;8>R jI09SUT ;Bmd6"HEī,."7(< u m շ. H iUՅPPcoLCERlDH#5Uڈ mcQ/[τ={.W,"`rETiEc{C! XD*jCA0h1ʋ LpW-jMLL J h1>"E A.!H0]C!ZI0{Cc!aB4qIv+h[{5p]?|7ǘ"Ƽ -b,Q(*b( -b|Ey%YE u8 cG3kccc[jcP( Bs GT0&Qc͗kq8F:5Uo~c@T:FYa2 Sc~RWeeXUecP( B(8իK L MLvik,iz'J4444444 7c&7ѐcWy;BFC֭^URom0֯(EfZ"|ʟACCCCCCC!kcYZ c]{1A ͵wsWBCCCCCCC!y:?UK:j㎸5T[ߊQq 3}ms}mp 87kv'{ɘrcR!D;T^_őuy:v9vkkt_J@wohȺ59.SoSǠkV311c|)ѨǨѥu ~Pݖcn͗m .Fhm| i ]*d0-4khhhh~8.ܚ0= v5Uwḧ́H}dsT{ta*7\y4ΆlάLZC2tEEw \ Zi~^#iǐ~8Ɵ?UK[üτ{=u6ܻnwW;s]:ʜNk7.vw6\FɄ ԡz\3p-Q4򭪤p44444njt .=3=mvYqџ?X\u&ܫs} v0[Y7,KQWo:W“᥄qpl.e(-l 5(1&S(QYa,֊#-+];cv)rT.Bg|]&(?ƜC4444%kcޫj~VcԂc$"H TrU}ewc;͔9'[@pwύƒ hrT͐c(lRɔW9Rx0F$)+r3笻Ky*V}EpW@chwSV!Wh h)\HDᅯ4ArtO+*Drs39Qx*L3T9 WQNu7s鑙O]P)PWVs1&(QnLUa+QǠsZ0/mOtI^^r5V*A!oRXJԏwvA5CdULhCKq|Ϛ+ ss]v|ǏƎvAPTGiG d915-{B\)jz, WQ3RL\8 bxⶨ_lj[%wwMP|D1e3Ш1hhhhKVXQc`{gIq1`w[dz[gөs>iU<(?$W6+U^BņRZ'L*-ʭR'U p֟ivHM-`Y3iZ̎qeMP|DyV̭JCCCC#3V\ENL jo;A-u ȢKfrٗy v`!a溄WKv(1hhhhhhh~YҼ۷wm vdT3>#!F{C%u YtIn-4c_EgS-r fc: ,_$M[uwlہL1c% L:u ~Y p m[oG}YN { Q ^{:mM,7m,cf}?T}*6@w3~$Z {~Ҍ.BfOni2ae0ecckeWLLusw2p6t6r1gkd~{{3gGsg's' }~+WgkWgWWW[7W;77{;qrpre؇ُtƸzzzyyyyyyyyy`|ݼ8O _)>R<<=1w *8yxw>W'WG{g{gg;lN;Zwgov5``e[2XHѷ7'att+~Aձ5ձ1Ѷ1Ѳ6ֲ2ci`NsftjD'=?h}˼ vnFಉ!b3bf#/eS`L~peOۆcʠu#bJQvr|h1|G)?|owq leǦ ۿ6l[7" ![Zo?Lfs۲YVv6l |+9?7; _k`f&w7lݸo[Ooב囵_ج |I5qz+ |5 [o׭FU7_V!֨`b +0kW]+IJ5+_˳ \쳖%e\#}-wYX(%a܊-#k K Rҥ˗.A,Y _ 8\tQkOZD3o-fҞa>g}΅=%n5P 4KokzZ@+%w4LR>Vw{ ;>;t7 kK=^u:6v76>'C/ɑ=z|/_|<=5x%~dzztͳ7oo_bW^c1oyo~y__)_cG/):w0o<x3vk+ě)iW)0_MOc^3zbgSS/_<tO=<~61çビ&&G?K>Hİn)] .;t1t>~0>1~} 3o 9#桮λ@GB;0 ZѻKg L;}-kTTPE[@&Ih@tphGT2Wޫ#TUAԔԔ7eM@U).PY(QPA}E2ӔdVw ̂Jaf-ZDKN / T]L3_<=lWPZ_ 4pÿZj+fN@{QPe*+X SZsQ]^\]V\UVTY Pb90)B L>2) m~nq~P \)9@v Ȧ)%3)%(/'&H8&@6!7Kp I "`y}kqA>85z!3)b߅HQK~RhD1rL|{<+'N J?tUz{5p Cd̈=xMhA141@ƉAcdqP÷d'N9 c9sMB$CnmRK3yN2NgɫגWSןz6brœ?{tO>'O v{hȣGvlytxwxkaЃև7?謺^>.VGuV{U潊k-%W.-Li,Ԑ!B}u9:\{3 J$dDLPXHjNnp NTXX{#63验S*Ɩ,K;^z98%RTŨ YNr줐[7|304ܑޏ?@0D<"+>84Ʃ7_bfP[Fy3wTAf%O' spcy8rw8!\ [6~l}|--<,s}fN)`8L v#@HO P=#zFc@HPP@`sf:Lm z|)fLGLW\WBWRONJ X[+}SЃ -]- =)R T!9e~,UG$.C]zwDܦc6aV v,[m,NO6Sz, YD x@pLǷi'ӉTq~ uL D @ M|"UC+^`@9ʈEEd:tӇ`,Q#О{('e'.7 2absV|pvBHvbHvR3GsF䟏*}DZGNI?Uqtu褒}!BFpFkCGգǑi015Id4c@lP!r1^`L`ǘz*y\SO^cǘ'&V ipQr /鷒o$_K1Ox)!1lt٣C`zF{"GGzFGFGz>?h`yp0E`ݵ:++k-m.m*iQu;Z[J4_n*Lw1\H*kn&Wg%UH*3+8]/G$w2*UeUgjn͊J >X/=_{8] T\=Qv%$4" .DcM#v2 bW>of 4!, 3NJ,pɯWx>Ќh}1fxK{s/F3i[0 7b !1Bl5|GL ' @@-"}ƒlw`  AkkmSS(Q.̭ FDD:#ُ9Hf`KrDǾ`O׌8q"x;y=ppCvζ.l|,]ؘpL\ Sg gs.RBH!EcзL#0aз1ԷE0XrV+҈u m0 +l4lɆJʆZ m 0'i;O 0 P5 guNm 0ilAW۰rlUXD˾EjoZ<3=VJ[[@5 tt"*k@\T'd:qU \Sx_^q/5|.E\xQ @8=yEB7p;ɔH?,EXpUAlQjH~pߋ> Ѿ7s9J_ZZt@1v a7~#z[r@}Gt!(G+p }V|U&[gع1"o\i-IW~zw^$9=W2ԩl&;%IIdr@7r^Mk]"MAAۊB(ˊJ/ubCzU׽**EB'@=${9d$|3:V̎(fsIJP)J{W,8‚RT/)'%-/Ӌ1V mc@`|aca 1 9|,N+i`&H]NLuOuMJLJ;ذtl w wCW`Z vȠ.چ[ztꢭmQoӛgXQ+Ew.^ެŵjAWCWT`TT<-gdR|xnx|ɥʧ  rHHȯ_\^ $WL^|4J+Fᝳonfƍ77 62~ظ"?`hK#T /.D AN꣜v?3pGnߤawıWTWNPy),WS\<#!"3PVRdVrd6ƱgXlv8tQ#ӨH JH$C'00Є(.SG+0*8q<*.0-aɇB$O#6, &?:D, F )E"||#Off`'4>BXj+(> {`#ț+NO~5`?C8ؘCfH^?yu"*x͉OAdSXǝ^f\b]`"8T=;{3wN'Nx33橸g^Ob1\/j_LwVfͬ[N N3.og&:t3#F:H",NXnj‡0& >v4)?>O<mu4JJ[:[ZF[G{F{ލwLK'S]r0ܭQN*%=#t|af|avR=7V*^0~Y\]\[\*rR%`AaXB?>Чğ_>|bI/O"P >.}i }\$`բ WR=f4RK21YjfR~B~\5=6Sʇ̤q<^F(WU1LS@&uL P^}hmhw $w!vs}P_J^*k]w6f͛&̖GнG ڝTWmG%#e?pevy4TjZCBUD2*Aʠ_tKg,gc7Pe՜izv%FlTUoA&͒jQI5R 4@p]>J  zP]QW%*TڊTZS^Z]VREW+WME:P!ǛRP3O1(%t%BXag K75QoWTB 1kRu^M6&,گۿřϲO w"uk [P.k7O{k{f;v[-6opڴqVsB[ˌa؀l90Xl0[( doa,Zj6k;m4'}ζ;l-wYll۴q>olcˁ]vmu߳c^]wzpq~P&q|?,'D `"?21BD $ $D(O/@"BoP\~w^ z|o/}m]耋N;=2莶[>pWز_=pAg 38wwm{ocg9w;7} 3l`3[MEk=` ؍;qdvU;K[[ Y):i;nd٠mh,iw=K_ ;dea fQ]jy_Yiίlﭵrq<YflSdf#Fc=Z:dcEĂc1,BCg!߭> jkN1hZ]f C3cF2@kt02X!eNhi`3!c"CSLq{g]yi}ԪFVi~K}kf[`VUao.[h} o5m endstream endobj 103 0 obj <> stream xW[oF~G?̣_*H6ʶ[%*j}p! N/{lXPs̹.d8E:v0͟> ߞuXbF#2>=+Xg;N5d{#~"cuQ{0[A%2;@vd1(ew~.@M Bk*0z-dgP ȭԹ5`-c_ĉbB6o8?R|YDF6vq:NF%@7dlG?h:qZ9}F[]':*up05m)_gS OPQ'=Z٦$2nayvÉu;,o4M ;' F ! EζLW2mbTy-8!<΋"~RֆJTMnM@ZI/1a V⾍&9Ċ`NEG:}A yկq"J~ϸsCv54 'W ~ukp[ dN xVUoj}3f4> 9:)ȿ"^$")> stream xs[Wt;,rݝީݶlʢ  A L$2 R(K-5?LVmՆsνRaQz}L|{ν^lttӎWCKz^㼢嶼ނW_!6cxU*Z_gq%o ơ g[򦎷xW)NI>3|9sol͉?ᬞ_J}i{Bߐ7rd?8?PgVUmJp^⯩W_zx}2/? c32OЂ|WfyA2=|{:^8oEv״[wN 3_'M;lּ㛜U xD_~// |o~SΙ~᱖x ;m# G_=K/?Hz/#T tzJ|6|9}КDW-bFyɗqg>g|)mor_sqOǑ- |gq1j9)ܾu[!$qpn*qwr'p]3g;yܺ>C#BHmv [H%T`1?z{>?xp1>?zDŽ~!^ēa{r/ꑸy#'xt<=+o[_oKz 7I,ėW˞8 V2XZNr²`iqyQ2̨KB|q1FU4bʳ0y&BcnN*0 ̮*(̮63!8=,8_Uqz'acfG2m} t,۝+x:W.qN{p\iƁx̰9 XN`BZD&8倣{Rb3?@9Ƅ1ke8>3n\c)dD'gFm ;`fLT&SĔ 2X`WX,Fetpl5 07 2F`ww ct:z;z3u!W.ƕN2rrw宎KuڥNt].r_v:q n;}skdd5c}cC-x,` `PyD S "8oq2wt1'!p0=&N{]6 HƳ?ˋ!c#qФ49n7&̶Q9eq]4NجzЅOdz0vLv:vv L U%8vtJ0)s VKkeFfG/K|d~iq/__߽+ lqevthOX.zKomX3B  xHK? |bb5 E! l4&rd!,đ" DQ!Yd$c2YnCYc`UJxO4bqH\(] eVT|XֽhЏuL20|Ux>$a{a/[YM;3wpG9FHhYF =B37\e⚡dC3`2 =f_Q5î f`L0lNT 2"*41ftc0c E@zP31vu14ЌNBs{o\u} z1 >0M2!E `fW$@cS\'$̃}.`cn=4Ԣf0n41dfجQӌ1$ǰ+ae'4dh֌ [-gь/_\IN6CS`0f:fZ*QJyU[PH1`́1J3D)b#a"T bauѼoA(X+DB*U$ZX RR|i);BFdre+N3$:hl4Qx%E-\zf:\@,Lũ>B ƌ9ui55#GI3.D1 :XQƳi @M(ј: cp5CqI-SManMqc cfXX!&> 0f(cKR!4/ %=B3xѭ 4W:5׹ft1Ǹz 9/uSŤ^Y3:Q39 g -X(DR1H f&ý"5)BI!E3̢Db6j bMݒiL2~{r X1(c +&SI 1הbҬc" u擏o8?N3$vg |spk4c 4(#;ܬw~n[񗯾ʝ[A1x|^W E_h"?g^KH"Mfbx* GdguBBd^*2z\P7BiXJ39eTe+D=]JDyS3*:BqX-v \NQEF:QQML<TjB*Ti'H&2w\"9x"(M1V )wK*ˉ2hFx 4WxG<4,PբEeU1ퟖMU6ulZձZ+qbKX ioKp*!2 I3V6Kzi[מp M{ ۴̳Fk1%4C\319iLN mLcXq bY3H0cXc JihH3za$@OɦAu %jjqJ˲ct1fYoyfA3zI3FA2 D0v ` InAanZ0{r YĈ=,laccc}F.#jVLưb2e5&XWaB&ǀ}Z>1Ǹp*waj3 ff fhiٹQ_N׌X0[.v6wvv^l3=K2fQ.ñT$&@'rT>)gY$%) $,,4rH6W(^Q,ovS2@SkK#u@]AdЕZ دe3<2٠Ra} Ž"P.rH90q#aqdžx$r м`+$vFK xKLZ"eT@WIrD1Bx5F|XCLc1TO#PoŜMcV/me:o`XhZȵ;r nc8͘5Ci4%dpj4{DouѬ b;V3lh4Qf^P;2 T&fA4cr9ИhcCep03]j1LL32A}7{4Cu U3(cL3.kjFՋ7AWwa5k{iFو9hƨ-}L0D'bCJh.LiJb!R T."|Q%J8::Ht+&ؘa5>11c4ih^lv 11D#h{Й'MR!?c¢+ccdcN촘wnBDˑs٭\,e#lP #,dߛahbe)4caL#$XU#cNFSpiCFl4/Eyp*S 93)>K'66cxEuVMé7'Ih YdKQl4cFAC U 1lf J{d3MLCՌ)-4Ck61$͘PhUi(@2: Q&J41b9WMz_pW)\էd.f\cȎq@@ f\!͸LxovAfip_ߤ fQ@a`u@YZPiY,$11 IX%`=Xi|QWϠc ZcQc9R3\%iSxC6yJi*`LԌ!k4Yu[\+9ƨbv9Bx #q`2 vQ)W1P##I.)l9d l/!r("@IQT( *CB*Um Z}ju}}ss¿*pTwvo68">'wv;3Eíí͍Í!*G&(GAѨD-& 2{D`(5TY>PQiT֜=b(#{""ǀ?!gA60ӈWr (Zn z1v 7tl4P6F@olMH3XF!e %jϧsۅS/f|d3- i8c0dK\@^Uhǘ 4vЙ&h nrfr EYjbPoFK h ! `ːpAsKMb2;" 411e0@@30 6ft_鼦v\Q$WL@34fO,tbs)jFo & 81*DU RI I.!fL<>`2ʚt#L30Ѐ# hҬ\k%U јAKY*&zgzy~jB~AjFU*-4LHY<`PzдZZp01Cp 처_J_L'S; &֣ zQX:ő|"]HKi *z!d~pf(YlAeK%b9e0IS0NWljHKEg gͭMTs`xۖ=Enˤ5_N;5yӎ ç;{{=?z.ݱuԏ]Ν#n!lo)} 0zVݏ5O$Dĩ[SCryBT9ұu8 Y;/;ّ 1W @W)lͱ@f+KJI1MJ3˸AB| (PЙFv B<azccU߳1LeӸlhH+CVuL+vՂç74oʚlw v i(MY3cȚ1פLaǐW6kT=rp&֦u yfh #^3cMC7cxAaai f ̓ccf F85tA 8FE ЫVҩhFR7A@ǸAHkO.u Zh95܇1FŤFe17 X2L$XXa*b>Vlv#l E/1h=bTb 9⼗oU5?=E7ԬjĴ.s=`;lḤcLpd<+/6i[7i$cps V0ǰ8PɃG>7n^삱m6``?~kP kZ4 FCt .6a03#ѭJMa[$GP!)&`3w`8BӆSu6PFW7b},ylbvsĿx{G{H_> ޵iq`ށ^3g}%^Ti!.htugQNhL!/_mk1'W11^Fcf4|d$Y~?˯Gca?ƃZd=!F`d\\&oD5Ǝ4BS<9Z Uj" G%(sPc6&{Gi1G ^޳f`}}M*aS]YgF<PMѸzI'tN 1cAlGۛioMNOũRޤZ@'hGr {!p.sHf39@zSoAa1 7W;v.ISzbd WYRÃQm 8l,$[С3&Dġ:ڇzD=N61fu(f8dШV>bf(iLC=NʦP\LkkE 2 \h*&fH5ÁhLîhƬBfh iHqfiX4aChfXJ6q 5ʐ4l4 S$4C2ft 11 ܒ:K3{OSi 5 RAmikvhЂ֮7=Vs(AhtkGZ #| 2FM>~V1u#C""\1:Eç x.l%k\ձcLp i dhƄKr nL0cMFo8Ia#2KB0p^:J=O?9XGWrPÁ nE GD.^Hl%Hv`*&Rcb; e'aȒ`@gϾnS㽉,uew,:LeAlm`ZmUj=kX3}Q.Փ~k|~GBg}xA~ͧeM8eW7S3^ğf-rE wF#U}k{!r𶇋XPZ0(J08[ֵn1Ome72 ekp01>UBb ėi c19X0TPql%E^k!2vk/feph +4-$NfhMcV1 4C[=QR@XKaw ^3&yD cVY3fh{"dcT`niͰNH4ѤrTL8؛u *&#jń;(]2>a1jɸ۩ >͠ u3n(qIEpqQؘ9L6hcJ[61 u U=L0]ChfͪcHӣ}p-c$2 5'>B`L1e`(ǀ#vUi-6rq Ν{wc,rW( ˓___c ncѝ1*cRJ:W%hJ#[;|=ۭo@Hvk1yEpǠgF=qo,7`466}wf&vb4|Yc4\$j{ N ^xO(Y3 {h {{ pr}ۮg ÔiQq4|@36ݘ$,DN1G@'\~|D'1ÍZa4sޱDjiSa p}+={(Bh`r4#Bʃcl[JVRlU_6嚱hB|њF\:h*1e#Ҫ/:+ӢfrF3|& r K3fL#x[kVK9e"_E^a .4ЌnS' .c.N;cp;ӟ|q ?䆒Q(:SqۃkJ+ӓ{~@\y|Lq pW1+X7!`*7>'/zzthcsg6up49FWYlcTc%8.!tbQqxE]u=c§ܢY.SmE$1&*+j9Ɲgp I%vL WQ|$|vנb z"%! I~n빇j?EQ}])V:(h}][~U?ܬSGhb0޽ՍfլtĄLud< uIKŃ0tp#lLGjX#&Р$Ͱ ģOOMXZiJ -(ϑNs5w7wwt99r 4c!i0H\s Z$J`XcTfPb` 8.+* uQ3ܳߠ3:Uǔ%Pgho^^Yra}k3tr2[Y]ܺtR"`8'Z=9g²c짎c9ƷeLj`YXcc9%t+L Lb}]_O;9؟xu}U;Չ5Y$.\ N ʱc8 C)W4O-)da2Um.u?:c9S21":8LH: %fZS`L64B ,ܡci0"ٲ'(i/K1Ќ18i<1, (a>f8tIU2 ir'R@CҌmĄ:bJ@c\31f M1QtFeh0 f(ѧ 4:ee͠&*b4 5iT44E3Z%rs5t tk-PW2@@ͨcI3x(( Jc%uaĄf=B4ga.4teݤvфE3.v4^Q˧ar^cpͨw[1ykg&g;Zzŭ0 ,eB5d[oWGO^=jӟG$fh6"jUcȦ`c@FW.M8BDc pؽ'ч 1]cj[qI?]N\\[FowFbq}}# &1Yc|s߾ۂ,,Mw:by~a8,r>S2wFy8S"3NiwV0p/X ^3?87|܆锸 DɹIY `u-1R=H۱||B/ L8rq'uOpmxa7p| 7i1\ 6G"M:}˩@{1$Ai6&r.}L*r<u>V#- q\漎afc֙2 Tx)4#; 4eT fhƸ#:uOf]1@?R1>T4cF3f6CӠaԠm}#uzhxZҌ!>tHr 4( :41PQ3&'iTԌjiiA@}64fcPfh,P9Z֢E3ZZ]r<875Z:hB*ibڱD4+/ 8&;W^8[kAj_i; KY|[ 4Φ[Pֵͨ"+2;7thDM(fԵ5A F w 4:J{kxYx VъR& 2fuKq{hgxf Jѧf ) }Br6B 15cg@34 ÃYXF1zFtᚂjT6(,(\ޟz.d./ͭ&pʡ:=D2d0 E"1x*r[/[-qFi3t"wc^\xo?r{VXַ# QX4\sEuKY,e T9FYS]eF4ǠA#6ּk*.hǼlu"}=s 1&#9yP{o]Z,,z=| ,6 ށ4>ӹ"(λe/Aڐi /ot,CXp!σc~g88JfbiB2$Ә`$@o@i`lnUsZcR hȚ1njEWihCYC 4c5c$ƤeAכȎA5McCf kickƄfL藜(5CgҠ]A#P|5CJ9Ff |zI;52tdM5 Ǚc%שK '1ZA5L7Np ,ej&IjF pq8G4C$ub+^ bh3+P* H4&14jk1ymiuXOFL Rcg )4 qJ8܎Tp ~:{O}oz1z1^Ⴜ4 p3-?Ok'=6ٝ J|P5E}9.IAtf1[h)x ;)t*Ӆڐ3[͊YVi͑z/B>OL|eXL6p W)*]͊R bp@c{f؆ýñe(-m$ LQҖVBH =-ҿc 8T8#l},a?+XgCbS( lX(@ ,![ҚJ9pz~n}>Kfr* /ƃX B\9B4ŭhatC֌j5Mkbs3E(5uPͨg I3X8qTh5ZEƄjFQr,\Ղ5f0Ԓ~,"dQģli=)ښژf0@HGLj{jn='V;_'G+G=$gzٯ>3O>S= ~k:y³_?BFP 4IiPi8E@C6 ^/^o8G0F4@3fs@ͰpŊ.u Ќư@ f r0fj5~1iVQRg W1t:hfpNCCsh;Fp jNitlB bnF+`tՌFYD 6hA \J qL `A 8慚c/:84 ұ TZ:]C*ϴE(=e']Է5ַE+jfTᝐE-q`gi'%DaB_p0!p"N"D$d|.Ȥ\\ͤr4:I<#mHW!UUҌ,Χ M :Ƨc64' ߣwBUXx⚶~'_p %>qu?$T(<f"1 (^HBŹ9(-݊d^jNZqXh}v_ͯFYJmE^d%KQ2s),Cpپ^.@'eq(0D{<KROYovw.MC̤NtZ˞!֜v4A1#TYH+Ut6D@1iS2zG(chA7# ƴ557fab dwz"n_ _0CLL# X5<2Pv$ uI ,$SMBtJ,E`n) 2+@O곣{j{Sj *DŽ:eb f1lrkAAX d=y.h$W.j!8x 1@ UrLr2E22sz#Z.%#KP1Ó^gA )%%DHǐL6 X$`BRbN,,AYU6NUm4iPPLCZoLC ڰЍL*]L8hƄ j*rPFYLCu3D3 47SZdcưfHja[W8z\hfjF%@`g#i@sǀit (:T=9&eY(e3pVfЙ4Ҕ\1.y|kPrc-ьcD3ZcW2UMC$FIv166 Azp+/E(Dk j'4:Z`4`hF+Rk'-=L+tc~Ԍ~{ 4Ԝ:`GV׌(I8tR9'9u.(v|c Qf8qT5cX6/j$v#.w@JPd.3"LF !(19 џОĤsBՌItxYVyMՌQ,312rvfH 4 ړV175` 5a@#\3iT %5hC#iьm +h)*UۈcP4xxV=MiRO#&g&f4C2Ap5- 'xZ MH&1+4[yԵ6ԨAMiS4D0fPA͠7@ӌ\ʪi ՌSSZxj@6]Uӌrq>ҫ1WQf c:ư.@0<1"L<:ЌoVG&W鎺<1=H  &JZ IМFBOP&Bp$хh*G1X"ʑL.rPJiцJ谫F?E(2)l'$X0r[%(\C]YHC4!"D"]@,X@ ,DyS^DW!> 8TzWo“ΜxtFeA4c3 E6ft\艩DiBLNBCHʡ6M=]4m>K b`{ <%C$Bp4c5fИ eEĠk- h&i ЭiE19/z&1(1ҭ5# tɚ/t"2J4&\3hHqR2Y4׵1 s g B3ج D |1)xQ^K{iƱ٠ .3,i'v*c%4Xf Y3@-h1ZE۠(XFi4I=hm8mfnf0?khh wCb. `1uhFN3d0 #Cӌr[Zѯw!178z (ip 7@3VhKM,6ك6G ]alxoDo8o~^kx _Kחz_:HNxi?}90f\(4 B,V(&9)!' ^v| 2m' 1Bb؎)I `$aY DKHIי$=a$iDJ vᕜ-N/CKPHE8PB|ȋxȳ{><= xU|e=-4a!X؅ߑ!|Ams$`!+Gƒ`֡l$V&aN6f5͐LC!/BJue3B+:7 1PbJ(MA` 䎉 fT3,f@ 6X1CVY348Ru1 L3F|yqF##&li(83 cpPB7 pn4טt3tZ]u G3ZI똨i"Aǩf(1.wiWf\PW` okT?b XA$-c#6JHimՎ@Ѷ#BQ=J_8Ap&˝zތ r aP&AF8h; 0;:-1> 6T-J0o/RO)ErE!H,p;C:y X`͸U<֌l.id]eN /c#d9U$L*h(#We1:C%ĝ3 iC-*1եM =:xArWnJfW Ҕ $0͘pN*b<4CgJ@j(4clTo#i0`1j 4/kR((ϧU2bz٪ hC trЇ2$hUYcҨ8 EZahVeiƏfy*Xz. 17v1GLgЗ+!ʗ4*e|,7 = yC>S\>k}+2|?S5>COp*Ϲrި|}{+s0U9 s='ܽwG[i?}w_GKs 1=CZӟlbbbbbbbrSff&=+Q?Ts ޤg8?sǀlZ0PbZl1>`bbbbbbbR" cp`qVbZc?MLLLLLLL@O qJZr"9UŊ|ǸL㷿{I01/W1|+9Ư?go1~DZoJH }6n K9$ޛY:{drVOrK6{ofQŝB*?Q11111HC=#;1.$¡_LJ?#KH={y ?UޮR<{db]'osGg111110܃13Bq?q1¡o^gyHeg/oUUւ G&GDs{?m|/->?@ុc1lc)]魵P ꓇|p9'>'W @ ۩I~p;u*FYӰS|nU/jp\e?`S?GREG^59&wc?uS}%LLLLL>aq1>Aưٮ]Fx7ˑ䱕=uƻӓˑO8=xwXU! UmbgPv9NlKB_iW[4"M@[A:eQl<ݡ͘]Ba?W1v]m ?緗n) inga!m%rNH>Ztr;ϮI_Eíֹ̧ 4:woBl.}}WmoɿK0~t Zg9_&)С˯Y e'$o **qf3:+p0iN(WϜfN%g­|QKӟEöz~cx]rտ4Dc@сwORp]C~o>geH}}quM: '<2XY7̊ө[Z#*^{:遭Psoĸmc?Q;4F 71111B: s1hA1ykkGabbbbr P1>i_9t_8so~&&&&&w" e1j!o?LL iso ;Ơp vrc@~?Ĥ DclUʐ ٝa:|`bbbbbbbRcb~ 17`s37s37s37s3=lcp)B0"p=gs37s37s37s3=lzaq 77s37s37s37sV1^E0nyAڎx(ߒ*AYVBvNvkvFKo;s7g}_u_y_z_G[l/_~afqy%3_r5oܸoUyOn{ og<ۨ?|/ d!B’B %,)RHq8qkE.\n{$7ɽۉ;n=8bK#.#g=w߽sg HU,zJǃ# ڈ<.T[[Z*8n:¡k[ze(־_ygr؜6ijM,(nޱ讖̴~X(+s:cc搐Ҵ1|ŧ5X>FdTg(^,p+ K|,ݧ>>pjK3E[NٰewOouMmMm]UuMEeU}CcH{ h98kHթ`F*%tvvJ puuh,I"#YQQQ@"X WfjLKf#h-1888444,, 5L&*x#,ދ"0ۘ^?v)2ogMlMOtww %|޾%4?Q{RUMooΆNPε獛wa,nuOʤIXDy)F"ԯjΘ%3ZGn:͎ݼe?89>:5>;;y2 hqK:{kjDgpgؼ<>?66Fl)R73U)cnt}7=xRVE8i8dg( fWG,}7(8cP(j;>T[i.(jpGѡ>(сiU} ʼG-C3ГC F80옜q]<==: g7_𰶶6oo/yӮP UP < 0ϓA܈@PAgxxxss4/IJvz%hh |?Ĕ[hVAY~cXs|MlX ӭKzzG'B##qeA=Y O}2wʹm"(Q45ɐwc]˴Np82ѐyɳ6" vTݏg!rm32{{{ rFn/VgOF1_qC _p9ޚ*8L9"M=_0gh?}x_fvq:@nndV.tnG2?S/*An\.Wfܿ%IIm8`LO#:242820R5SIc<*G msgccc8$>aR1Z0/wȊLaF3yV!tc~txBgYnI4Ν;'1>[m MGhnrr=t A,ƿlXWakb h~VNeMZRJ@?ǡ j?Q ihiWX$=\č3FG711qM!h.t}P̫S贾;Y{RRRdᱞPy<lu1I9-IN恟ggPG`é- )qvg1gkn``PWW'5n\<1ϥ׮po g4Ocz|j~?shhhhu ǒK@ҥKz"tN%I$ 'efakhlnqb/y477gOYHkD g&M/C!||*>h%i@+XPD[bfq'.I͞1s*\Lfuߜ]l%ߡVǸ?<c0K1~jD(h/;X_yjF c4LB ' Ͳт!xCgoO10㑳~;uT}cSfVvvNnNn^Nn~YyE_woܫ&5*QeQTix, 4Q;7ϘEC/\yFnIF4W奾cp+cdx"\P]b][s7o/L,ZP7ei]꺹r&30 B~qDѴYg"Budc<'/iFў鱾ѾAHo{OGS_[OkصFpoC[77F^6ܩpTSSNWVVn)\Z[SS#6WWWB؇_(_N 2rjjİ)6_o&.<  NxMr*cr3io(ŖCCqeugqyGnqGzaGb^GTvt(qMaM=iAG0.{`0<<<].T~}F[W1FhmǎSSSymϯnkMLm}xb70vdhDr0Mq8e@tބw轠Wb  =Q5f7ُcco]FHЛNGv`BXR8V@|>rDOo%?z;s˓45|b/9'%hbZ^YQ5αǒZhtzZ(TѮ*o!o[[[iT/b ՖXY]$z$L +QT7wOVhޱkj555|EJƨ2JrĈwc 8=͝c YP 4`:-K4en b]$P-}Pjq;cDo׉٦C/v~NįM[dmRkb=Ԋ,n6ӧOq8aU:::mswwgXDQ!ejbttٰАk'm?4-~Wy[艉&BB’ VY_/1"#8c@   0F\\ܚ:CCC^l '/]*(Sl.=liiy)(_f<k_{$fN~]cO?'̫-,B{/MlITTyk"*B*6#Ƕ08F).G< ˗.]6AmQf5My"&\j5v$sniC%:Yc(c`>Q;AmBZZZpx{1%+gfWRZ{ zou!Z]: >8ahh(r\Bhaqiu!FF2D/q:Y(^.ۮGv9o]騮kս$0)R+N`10=M c0Fo e~ɶviG64 Mu =]DihhP>Qe<#7JwnɄ.qqIEϩ繹WL5FR(V'NLtMKsflL]p ɥWƖ0 0c_16]ӵ%+uȺvɫy骇} f5ep/䪳 ?\hc&eǴjTۺx2 wtN >h@0J<.Gݣr u8Z+cιw}HO;99uifjtqVB1F!$:1(!pM bbF@cF185ws I]y9&(o u}nj{91gv=1T36hRO$`cN&U:6]iTyds>xhqZːs9Rˢ#@;fS ?c@!Ȑǧ4r}%t%]=8SPez&KV'FGMT= --mNPȢafV$)B"LSssG%Kv׺1:::BCB]J!=_9|>%CzC>y***ORą3sc|+>dS{E;e 2?2-}7s^Č1::Zo\)Ʃ=8VB}+ yl9pٳgW-{zۈc&я(vggg}L&&G^۽###|Q|kOۗ+ T8~B]]@y)Y_E@ /~*'tTY,p5 Ô6QRܦƄNj 8MMMCw;WPQM&J28a].Ǫ) ` oopJ j1~0?y򤁁u(}&lT-L>~fb\tĦq_j^WC pzpw&|\8}LZ -B~h&JͬG|uu} .)--moo'W PC nݐRi`c7"""1g |\| \]@uW& 3ƔwlR@/3߻=2~yTz?z3*4 3vAo#xJd)BQ .8H22ʮ^M52r򪮮rooذK||iCpXT<MͨܖJ,ٝ^S-w`!Ϡ{w7"KɀPJՄ3 *GK&dť VJhEFF^up*-).*(.ȶllH>)q3Y2Đ &ff~ˋ弉h6]hO\}Yᄅl䔘BH'~R+}L/=aߞc2#yE%%`_7~ZA01܏y@ x @"h?  `K{Ki5E1$ cPk?R{I+++Q!waJ0526yʨF G\7>t9dx⤑ys_%8R'y%2V"n.4 g}]H&dnDζ*࿏HW#KHZ4c#$7ѿm+#)RDwgH"E_]Bhpu`Hf `2I E)RHA8cWIpXA 2cٻ7)RH"EJc 3p)d 00ƾߚH"E)Rځ13m12/LV'C2)RH"EJN ` >I E)RH/1]$0-Lc c߾^RH"E2aB,axv-F)RHg;!1#p/c߫H E)RdjDs>%12`X<1d RH"EJ1j=T XcA2H E)Rdj]wX$b 02"hG1H"E)R4P'd-3L\>s6"~݉ţkzݯ׮ޒd RH"EJppwc Z12XL02f{R? E@DۤW }⢢&|jT)/*k_ݍ~ \$c"E)R2qߌ\/쉻kZiE?ъ4b .A)RH2c8{0CmQ(ff+3}>юk_ć,I制l:P5Ø4;\H"E/=;X=8cZd&,cHA 1qu꺻ﮰꊸWV(kG)RD, (!$^!`nBIh!{#9sN3!ܹ92v眙o%%^ ZkmQ,0]YWۊ06^QDc& !̣SXZLw@#.=FzfEulX DDDDDDve} a;ʷJ*N f S"eJ'fsNٳWb{TKGi}Uo&a """"""JcC3(&>C*d jO@s)˾5 $ADDDDDdW1ee3gc(a """"""~waʊ3!Ȑ1ƒk c"ADDDDDdW"AJ^lD(ǘJa """"""b371*!=R[Na """"""=M?1bsag# c S1Y0 m? c<#2,2FD(|-/a $ىyƣ8cPacX3cIH1pA@#^|);TWQ60ÜOa<Α?o[Az37 |.s{Y M>-N?[p p?~oÊc8H:H:H:dcP2j%L01ƃot~v[hY&xd{ՙO0_5|uޓ[J0!K,԰ AJR8a giViViVSVNdJ- !J;d19ƀ%iv'j%HoFZf_+0K i#;j"HUP79^LfEX.>?n<d$/deRa /[r鲌wC=~/t^iůFw Ô`v:|>󤖅zhJc1~0S3g2ːި F 1ndIlIL!> 0ȠsҜ1'SLU ͭ1vYÛ `S95?cܾƇ~j#>zh[RZ.y#Ei,{% Bj!1d.'<5=>2:'h&=7y~`b}0Ŗd -sS1'}a-^X,!N1DV%}vÂeW C>1j*ma@C}_,bdO7Z){%͒bbf R.)[4ᷓlm@%c7Z 'Lc3yq}ozҷ=]?`es ?"N2Kg6?^ɲC1͋<ݧnY*v95 ]XY130cg,f 0_$nɳ|pڸe? |򇥹]"Xd5e 2L5++ MrH1c8߅řu.cČgdl1VH:f1vJrI-oK2|{gs{w[}>'ݬB}{̇uK\r]{K.Ϳ׽ o6 OYRYRYO#kvQ#0N vt˪N)ҬN)ҬN)Ҭ'Ĝs.k;#< '#_X9H:H:H:Ovھ{b k3T(c n2Ƙ/!cxBc1``0I1Xux0[123dWK1ƪiW| w|p>>9>& _ӑ?[cΝ|K>,Zj==~`3`IN~䉉ےnޱuV\.  `Ќ1Y1|_{i9ugxm~))/YxsDo'7\P%UOl qС݀K"rl찥o옸շ`(XyxBLL+;f :ˈgQzL/;j?իb̟:;BJlK6M<0{9?SYMkPz3mS?2g>&ɥ9zsZ<nVc}J(GiViܲsN#lL\1~?߷?,σv ,.`A)^~䵏'|W~~l)|i+li}}:we'ݷ ?گw]+o:~n {3g {Ďm :Y OR?Μhmb<z<:?, <]Yg:^VJmuU4'wLjokurVe}-Vg"fˬn[լYRZY[ܬP*i{ncdv,~ͳ%aM`v>^ο?LDv,{EO[:>ޗĒs|֏ [0cmnQ_o 3 r?ڐ_9iE0ֿ:y#_M|L÷2X56 T6lWʫ nx#)_s0g)k11&lwF< [f 疐O=[J> s" i_2'?Vlf;tY9LJ1FZZƶ3S1C  k cdEW沊سo͘{ۨxk`'O. K;vז[oTV6/=,iA趻K+*ō^ʼ\Ǜ|! FK4j}dZEO7Q ލ̟?1u`gZCN`U\l-ZAO J;Kpz(V ޯ30;;~ FZۢݱ3'ޥ[hV٣m(iV9}6-3hxqt3b 1ޗe۝{޹}Իgf 5S c|bɴ.p \K qxš`jS[%+z~J0^JG>x=9Ɛ9 qK1SxoN|E~C># B!ﯸR/50BO+眼֋'Z`g0W򃑒,r?)ܢ91Ukެ:L0ƭ fd@xb+`7vY:::^[{OYY߼L^+,[t>hX,#-?K#Kq9 ThbB_*Y.夼oe=Z\ߟ<}y\ 7D,լHlK!؀ V.>!E"P%%?e= #4?|~vp))$f;)L;,~Nt* 6XrfbҘe1R#.JT1{dA+1R kgH^ %R4aHq?-~yYxʈѾㅭ?f)5xL^lsݛ(ܢ?x*yloV0*mFc96ƈ6ĄDFG4Uc|Niiio|')׮][O`k9[,(`1F1VNcHyiՏݶ..T"2Odwu-WxScHAؠbe} I|rК{3캆?]kb 5+;{BFd' {6t n)3 p2xUH$nQtgĿx+`6FǞ6hrfeM[#ؾi[N1bS#Rcc̔efڼk/^_GG>{gz~*_FXX,/X,,EF*: /9O'6k,'ɨȯ| \ăⵉ[7iV$cm^aƆ6zdcF1DSi1M51&}wuiԽoͻgd4/K"1u+?5p˷Sw?/IpOo \SWF583dh81 ܢ5I:c̋i0cGa 0Gs8Oی~cTD?x{xqxg9=Qo'os~FNFOnF<{J%"&'11111#unܺn[Y4%*XFR]X1 +DqN\F}mda5y BKƢ11 cl\aM33YH2vxY16^ YfcD[sjqQ~Pjt]UźXըO.Qb]TV.5T5jW jԦXբF͊դFՠFUXjTXjTFjTXUFUFŊUFUXjXjXj%-QxlX~2f@xa4fD1*PC PCc( U`b U1*0T1rPCchC9`b U1 U0T1rPZ*PC9`b d cnjAULB8yCC9`C`C-`C`C-`C`.`H1ƋV`0Ci'ӢMc>WIb^%1\{X!UÅWIb^%1V1PUyHrU7B`0[+нJbC*B ݫ$ 1T 1JbC* ccc,H#=Ԭ1 T%1V{p!UcWIb8BX!UcWIn1RpKV3F4 1WIb^%1V 0HUcP%1V{X!U1d#aegdepYC ݫ$ 1 1JbC*B ݫ$ 1tb0'ecECSnVg 1t+p*B ݫ$ 1t.нJbC*B yXj(`cn cb^%1V{p!UcWI b^%1V{X!rd0cŀ!` PC1E{{X!UÅWIb^%1\{X!UcZTI04c#EzLa*B ݫ$ 1t+нJbC`$ 1taT+fu1"ҭV+нJbC*B ݫ$ 1JbC*B ݫ$jl6K1u fp#:<-rZUcWIb b8BX!#TIb^%1V{DC16\j1ksuS&c8k{X!r !TIb^%1\{X!U 1d=rkPHxbcIQAQMce釲!UcP%1V{X!UÅWIb^%1\aJ1/qGvqwwqȁ,!pBd`"b C ݫ$ 1t.нJbC*B ݫ$ 1t+PJ#!.aK]\L3FeY|I1*CC*B ݫ$ 1t+нJbC*B ݫ$ 10K/KKץSq+c$@P0PX!UÅWIb^%1V 0HUcP%Q-ܬNIJ4ab)0PX!UÅWIb^%1VUcWIb^%C1^BuBKqbDiнJbC*B UAB G+p*B ݫ$ 1tܲC1-ᶈ81T !UcR%1V{p!UcWI3Đcx10fp#ܟ 1t1t+p*B ݫ$ 1thb$p*B !`a4c09FpRdM2!UcWI 1t b8Bp!UcWIba0cJ@tCw !#TI 1JbC* 1;нJbVVI0bb}C*B ݫ$$pC*B UAB G+p*zƌŮ,(#1fƪùC ݫ$ 1JbC*B ݫ$b1FU+,`c$F4jb^%1V 0HUcP%(0HUB c``J!c#8PQpC*B AB +нJ]UcWI?Đaeg>f 1nqD5m(j(mнib* `,l !P.hv0t0!b1>R[bgF0`LpbHE f>bg 3ٌQA3F|2VIbG0̠|w@$ı7ߍuo]V޿3eV7`ogH#h1Ccb U0qx1J(3ya#Ƙ(WI$FKKKSSS]]]UUUyyyQQB] Qv`<૷%T_"VZ\QoQbk 5:Xb:F+Amt@Vp@&sxV 2> 9 fdl3 MC b)i0\+0pC`/*++KJJas@Pcؓ^EڝJli#_5NW}[F}X{WjGV,XNF;Sm+.i̙6miƑ#GL&ƌXό %1B EAa1SaOi*C|'O:7?`@gߍڮrzrY˕f%}M\7B_.j-j]X/uEܓ_˸;\r;sخ`;v'cjή\r jh+i>#\|Ią}B`777R^\:9\g"gBk(WfZ]E;7bZʞ򮤲 b Z7k>t&tNlh,Of5i? 3io}= s EGf3x,eEi<%YM'>mt,xV2([>1M5 :l+ep1Y Lmgs6ˣ_cc Z [kBQkbQ[R1 )elwPnO]N;vGFȕș;+ЕJI#Kٶӿ#glL7՜YZZx4hhѐ֣!mGCڏt B>sţGz#Hy}4 !hfȐzu!! 'pJں/>3|||1#(((""OB~dІr}9W.]F1O&0b@1ctvv67ncO~Cy5 mW+/PޗSQւ`ri3M}/4\+墆")G.@.q>rr-tg56Cໆ653-ņEhC> PWʰ[h\)awqem҈\HcD ї[O;R6v^Yk1{`gT_LINJ)L.L*H,iO(j/l=_G8CFq&4thl:2rJx;Ō\ms˶1b#ixEsy*nf t! '0mA#fY-O'Y ELV#p*fEY|8Mjqc/I2 cP`FJ6S٘!$ Q`cFvcaM4d3ƤҪCkCBCZZMm=af3 .i__r6p5T'p+ۡkz+VEѸbob C UC1VXFc1#e* !S(iiiill.--= F9!'=tWߍ-*/\lGUM;z_EOxJEr[.n%Ţnhur=Eu݅x. n3\ Hp~+Ve.%p ck"p_QS_Q#2?hنL#Z:xbfuOFUwFEwzEWZyWjYgri{R8$RCI|Qk\a+\Sc s6ax˘}6t,jlcOG>5==嬨lͶmAΣYgNC綜ʥJ kQdK<؈x9ۖ/a~e5Ы 3@nf Z ahCDk C|#M40fW@s Mfi(a {!1&~)),`Uꀃl :ׅ$ .q'_ p%G)7DWڮ ,q\6nA.k!V[iW PfǥYƕ:d Ezsj{k.fUݙj*GcG2GZPBaY.s8ָ95f̢.7ͭ]?C|awq\W=cl8gZ^Ǒ gwt( w`X! $HQ"(K $F$A9t7r܍ȁֳիЍIuSzUAԇ{O2n;LIefڰ7 ҌsB6fKu9i0P5AR4[ 9a:+:B_4C h0ͨ'!(ij5#w c̢h[L_仾*ǁE΃E<|D}ȇzg_gС';z%~(/|h}C>}9zWUȎaс~?O׭[m۶wY(ڵkUUU,]1C0 Ƭ5c-wc`P'; ĸ,bDP(zNgWW|{sϞ=}cE"~ÓB|3S+7qgL ܌0ʼn"LUTg8U4QF#W8Å]=ׂ_Wn3\DΈ9Z15`z$*uxGۼVHky`~7}1 m48N~TPxcWף: &#h0"OCeوqCw2 f uxb#ZcVۣh. tPH6r":LCᦡhLD3%"F;hF4>A3X(I E3]Q5kЌ4j˪Ҍ~Hidz]~ѻw^x{Qdwge~GJhwp{EP=ޢ==E{E{=];ikGt7^y_yyyvڻw'| +K % Ƣ b cX1mpbkDlFI `a՞Gٱc8  >5pݗ@ȴ7Θ2'LzH+"3.`Cn :=2f U- -N @*S*)9ơBŝ0􁥶]1;ź67ߴ"'΃1oGI j lQv0ڏkO՚҅e:laq':XC* J?qhV}ph1 9p FJӐP h[E ^QFlAf1ڂCv4c(e0 b7E@iZ01~3RiF\1}e-; -h݂]= zw;wwB7{~N*}x Ytc]ݻp֝pp'c&oc?|7TV6'Ξ=&ֲ~\wCV$; sͰYp^ w>Ϯc,,I2LjpDI}}}YYlB  /B#77>AfC$u)gJl/!TDa„cܭJ8OA&IW/O P؈&06Bw@L B*ǵiRlwJdpލ(ŏ˴oxf#wݟi|"N NI6 62م4 $oX40RT ̛ISHt!Hf` |Ii"hl`ʦ!4'fd.bMÎci5CVGfUs3N SHdZ߹3M[ 7nlߺc놞9m9}ݑ~KY-`/UNq`4Ӿ5skN֜\r /u ~1.aKL-1o [i1GcTXDYbI%%J?q~~>s  I0P!.F`pF3!0pC `a)L\0 DŽ{t_]n z*Md#T9xhdC:yb,đc Ǥ3avwX,w3q'86 Nh uБZ\j1;90IiuQ6`U.8 f f\ZP^!4\`_eL F#i(7 t剮4(isZӨAͰnjan^34]֌4C2c<ͯlZk۴iږMk[~ۖۮq-X3@x x Bȩ^ș_חO釫y6aKö쇛n~M˖++ n+e` Ƅa|"\wѯwիWoH|駧NcՁcVvbI0nK#c3 -c"(~,KeeeII7nCH`?LA Θj3`,A1i|Z) /l? Q5HH :Fm̭ahb\:z ] [6jl qG99qkwqʷl iw#bڥ rL"9>4ɧz*kEQ˨=n4' D'9^ ~l&@'u׀' (s u&7&hԉj( 3v ^n]l .4+  BJ8פ *7Rƅ&Pi.6.фu~k+j2=@5ѓ4 4Pfc4 mFP]3dg/?G*~>x.=_O_'=qH.§xLgYhF1ad?G<p'jժ^{WUnn-[}p#GCx^}'^@O=`{hy;A'M1t #80 #p\c-;11V\ꫯ999^QQÇO8q9Q:q X\YĘ1rrH37Z10qbJ1n78744\vԩS~ L04FQ3+kgN}"+kk3oȧؘf_%bˎ{4%˲Vm*\VO4˕×&/` LwbSds**W& rڰ #ڛO,Z\%-=`!YlPC@W~NA'E:E]^a#SypyVv:s}*Eq&z7U-ɠU.mPR9}7[zJ1V8Julp;Fs,ɸ؊XYF1L9^6T@@$Pv|ChLCx|3L@Eo{jRF~։3 6C4D(C2Tn41ݿ~icc|w1eq#JrA bX7fiK aȪ5UjDc5.-`ዊq9FN0JI+ifPmSV֦.W(EBFd#`Gv ؎ϫ+woCvtJE.P-yBΕ\ 'I/g>|q'8FǩV~>1GpcžpOqT!Y/=_j>B nfi x<B`1yit ʰc,;mj(l"CihM(+`.Dit SpʕJrP.P" c@+J!jDu گ!ǠW::xgO-TJ$h;4p|gcdX+(m::PP-(.Z'MR4fL6MYd~L34ጧ aLi;vڷ.c׀_w^j;e_Xrڗ,vzct]w1^~7x#??6:ƽH+c)wbp %A '89|~Yk>r9WG)՟΄k)iRCSKP-p fJ((@Md0Og 1K=4H1Bh=>O*ƥ'<؉YcЄ)i` h1 _\;KZN }#`.J ̈̕()JlstW"^*+3Xŧ?0Q1Bl1fW4_ʟJ財c쵉%8$ g &P OO*`(8I0|q;TAQU0sTI q*?ޚw(B\WNqw}7cm*1'Aа572 %Ǹg:i:88{jkhVzr:]|{GUG1BU>]?,I M$jҟ('\q3Wƹ$iF7BjQ>.v:O=@'6,ð@ዻVyh9Ѭ:`dH/bʂerfDl4/*y7.U-SXX)g.+Vc?H>]^dYq}Xj!cd=uiǎ~=2uCzwH:゚=<#^Wޗf0Q)QIHZh&xH_K%`XD1)OTGI0iYI32P4 vq%03F{;ib7щ:VC`kT fM4w{r͈ch4UйG*pGgvuu/e'C𥓑K's'BA`4G puǀ70|cqeIncX,[7cl58Fj#`1< l$nleM>`=(WrMe(A]K.4 ]m#PcOJOl!Ԡ4D&ғ\4zSqHӫӀRVQRWO#}ZzìBzsKp*̊˴TX抷34pkgɎt3ۑ{gU]]]"1>Q}s Ke(ZZ%ͨ"PI3cFa9 @J7ǐ5Ct Շ8hF'Lы}+~?˿_V\/ڗV~o~o}o|Wķߺ%\Ɓ`LƇuPc^nȒG#c<Ѱmc.j @M8;rbܮ,1",+Z}J #L$``;qL:"PZ#JP{s]d쯵a$]$]B# DX+̖5a+M\T]BťiYJ5&Ü>sIf!"@똌uKކJZ-Gz,# Evى_4mZo'ON;Tb`#FQS#Ơ#X,:aM"6/8FRІ5 iWq ڷzJ%`QJf\h K-xZK 5gE3hr=57P5Cmo.[Uf470Αd{h \CdɽH_0fqM߾:Ƃ1$KrR]EWZ#_&|R[Mq\\'8Z5ѐϱ,f4\j/|FTK@X)}ڬa=hzEu #u# mj'hjɢ=:¬݁.fŅY=#a"=CUwr?:1~#x@>L.OD~5EnKla-MOn:.xDP$jC)1s0`O(Ţ^ĪjY36tR͐4"kJ U3it\3zxq4⭪i5CgT5 U3S2WdS?-tt/w!1Y;0clSA1H01QdNq 4|V Hohf+GU(_0)!ΈOZB A/8*e}10 pLr37kjwFB ;8*YB&@Zt 2o;k󌴺GZ-CC ?$qvkoԢ8QXR$K+Ǜk\M>n|+)N#*;`@£iscQp3gEtBҍ[ES/.f" JSBz;r-9l5p<3ި DشXq J=9VQKBjd8PePEO;Q{)p a@Or0NG9w}F})QWS0yQO4e1%gm+h9Z1Ri=:f:4(qO< ``@9WXеAO&4Jy@#"F#U@5ä7ED؅`VHUćYd>nbD$-`u`?c,xc$7at Ft 7!nFl 2NȰ02&UA-#Ȉq o-o"?o /ˋ*\ WGu1=:$qaQ:jc,,ɼ11_Q g̖2[fhFxhr>cqeIn%1cc1w1ccN1q̖2[f;99t!Krǂͤmq{51!ml-eE{ǸI o sZq:Ƃ1n"Kc8q"-evm1<[w{8a*)Yqwc2n1<1Ycd̖2"ݘc4-c A[̒c9XDY99ƕ+Wg̖2[fݛ'Ǹw2K2c*nlqJQV2[flmcC8F^^|8ʒܔc<aє$WrSY;Huuu7f̖2[fl7[uŕ%]A4c:F#s@U{!XAdl-ea3t:Xvmq7dI$1vKцqęq{5a*sr S@& -e̖nzK·ccAd4wͻgq10Qs r{pŒr1.cc䠺r[1 ob5%Qj_[[h٧c@1GGhJR@"h1rsDleFYQ"^1c4i MI}eduhQ0aH=#j;LcܹsG ch M>F9a)M eƸk\S` Ð1 zFCc3vT6$^41$Q@$evj8c`^6SÛ(cccvhjta|3b벓E%III2SRɊޱ@۾VVh!cW1Va 61&&&cd10) *VÐ1 zF ݣlx2?1d-1"}VV1F'cX!J1w׮yƽ5Fp[Ě`c2ďd7ls;{\nsK;` 3biJEcCC`H#;s͈[3cQsJ2F0єdD1\xk (mĊ}82G6DvЍ: a1 zF1 1FaJ"m}7߱9:<4&20a+1čax)"clݺgt ߍzbC\K,~X~õ!|v\=S',qWֺ> r~TdUj!Bc@1F'g[ǹ1!iam߈o P&xPdjb枏`NR hE.y ):x O)O&6 ^c'Nao t3Gű jl3bJqqqZM cgeٶafƦK sƸ$yN]OInb1ѣGcu`.WCQ6m .BCnfFv] K j l}m>JV8L/Ǎ1 zFSs]C\ͩa M Ic޺>eFI0iã1.\7~c@1纇'+lcǎ4?LIlblQ[16R\:kp`Đ0FVV1Ʀ%530>` Cƀ1cLOBE{mlbx0ƖB޺8a ç$>61ޯbf~0!c@1F&fh't2 |"`BXccP`xgjbv }O`L1#` Cƀ1c#Z'izm M QK6F{4ƨ1'g 1 gD17?:9Wi $61<CPcl^1gkqʍa&0c ?NvPѿ]sͦ1ģ1voFX44MMMbƘw١y0h1cO6s593謭1J"i >,3q1ƇrhS/Q;K@ zD\ij alCQцQ*1êSE2J,_RA!n$dw) $c@17;pcgC9֡(81wg3>[,U$c@n&'cضn19c0}752M $~;+>: Dteo>{~t cl6[0}0s,'8ѡsc /q|At]]eo 'c4.YFP=#bϑ1rjz-a&0Mdb>Fw0Ôkch݅zi7;,OOc6>{C O˧n3S1D1i#?k1k D  a)M /AQc\ 1\LpKBl/` l clٲE#chJ1rcčQzb^)M 1cnAcpB| t087%O`x`BnJ.7q1 zF]|c cyg M IcdlƠp1F.ư@CUUURvH*t٤]E/uJɉv<{H,4xk ^c@1kzxVb&03̠WaH=#jA>a `!fŒlL0O]5Q)1=cU5?0$` 2Fu/ /N&`H1֡*u2iaxC)W`1 g<˗/71ԝH87+8c#c8M 3MĒSEhoo6F5 0aH=#a,j RJ1L1%u^DS` aH=#m,]a)jر>Mz=i0|JbToƨBct2P$1C1)FM /1@Qz1FưX3FcTqc@ 3FDfUa|cid s51W@rV1aN(ycc 61;c `T1 DHcƸ6ưj#D[ctԖ<]ʴ2d1LPwJcxxX10[$QՓ2C1nݺ1 ob(x2FW;Bčq5jx)7 pc? :HgJ cnJ"tb›ԑ& } KNI}Y@ :FFDS%` |'}. J>x&hPj ` !Rƨ1L4%!aX!nƠj1 Ccll.SQxSm_^va&)|c2"@GQѝ2CEcXAc,cej^x TN];\Wp;za ÛMI0~0h c"c0710F.r'5ƊV^>w9.}X{˹55$qgcLc@ 3FxJEw a0ϔDO#cdcsKzWe^UWCw_vTj MIkb(7ty'Ïb퀂Ҵ)T%;.К@)c3H&(6F^2A'cܷOu7Uf$|p,Ѵ#u_vTd ç$:41<#>>g{l1F1{23W5{|Mq2R˻0$71$y0bpTcx]珠JȝskK>zKsc!m7nF)?ƀX8r4/AAAsV5J30|JsCycl8c}Y6O?PqBu2Ƈo(VmbŮ` b1ƒr LΙ=FQc.S0M ic㥧/uЭ3iio Û^OI!h T}` ?b7FPPPĜ GccpVmbHC#CG8G:o9t?1j1M }$^F 5g` RU1d!vOIHV%|j`"9czgX9cVi' ݌axC)Lcp(b=6C1n!c (26 k#84r@[Ȗ@1drw=M,;;| (r˂UO#3$ztƕC7_|1L4%Gv޹P$Oac `>wS1 4Fee1f(n1l\;7.!ll–`gm TO9-nNe.p=gwt'bIG龭hSd ^gq 8?ӹ=cx%V-v-xkNryinGŀAD1H>㡊G .-a'q̷ )}{;Kd'ȧ>!w]z/xގyʆn0c=@bHbVb 1>#@&13 9sek W-RP^WlcX! EƘ$Ơ(n1NTn1npAY Q"89/pVuZê$y40ŭZ p92"%^]<%~HG9*cqlD@?E[)~i`ShzM rxgg TR|.51TM1ڦڦj Ҩ>\r=U*t/$u4n U3ÿ"w=W:VyӋ˃Voqm?}..KW/\y|V1;8fxa t71dCe"tq4%(Q/71xa 5\N;&4+q1K/:=1𯼳`O!搞vw[*v'x(.+P\KrYaiC:Raឳv t5qYPв8|lآ?']-\q?"l$[[KXTǎ MF`1:91 ob>%h7Ɨd xi^i䇕\8z>%$-EV2Sy{zijō5B3J4p$-zͧhCmwY;sk>E]U*ܣ1܎"Ue@ LcOi\){~㼏nY? J|%hg)v-y0a%GS-EE 3#77W ceJ"e"1r1+IpVZ±29?DSuJ 5{Q>PW`5\c ̼4bk 13H7C1233DSE@_AcpM ߠH8S1 '` ?9162qsp.a،uS cpOIkb, k5~'œ {##ֱ5a&5А|cP`1>J Lc}!sZ3ZH"PbT-a&1:b'Gk>123[j([)i 61dkcNFpd#y`j+wc'1hVmb4Kz('ڱ>6|}J]Gd檬߲EΫ܎&Sac0‘cAAAMk4F Ƹy0tJ"ay0'=&lMtژ֕g?ˈ1W] 0a cphcE_PP.{ߦ7ٯϚК=FQc1L bxYi{~/}[߶4?kу6W10r~N-chJJQƀ@ 7]||ǥ%f+fr9/Pm3ڵk2a)c<ݛڲzO=[, ~-93]7$51#LI ZK$q2/^mb%y)6}{X(|-{#wu{1c>%&"cLPcc@ >` Œkm*#@bxǐ1"7~֦ϊr3wˉ1.Oxޥ=f 61F(3 T` >ƸFgϞnbH#"ȍLd,˟]Zwx>[=MQScP:%iÇskmƀ@ "ek2M ݀!eȐ"fDl'QYܒI(z7M M$1s/3#@ DMP'DqI-a)cfBX߬ ( (vIdb MI|c c4O"`41 DHJ^+-8Sc/'{[g/a)M /@1G/^7Ƒ#Gd)M O|~13Fk "\1Vp;7S}HNNv5FdN.0h)ck405عSR/oH:8T_K_1LĐo#nd @ D,3|4U3s\6F-EqR*a&;07F2,@1?^"Ƹ1 ob2%6F>~Og%P\?zq;n ÛLI$~E1AF@41Z~f[&SicdDmt7[1^x$4[WE1 ob6%Qj{Y41g%Q7h`r07o&j͟f(1@{-ƍJqu0:71QQQ!fƉLʌF>ďi@ 4O9-0єD&1 cϖlIUqn~:1e7]vm5>OITib(4݌q Q!18fxg mbH0+eo稢|j:73p7F}}'cg6c@ Qq3Fˈư^Cd 3^w a&1Z[[=c 1V @ ^0M 6>b Z1;8`T>#VmbHC1׏ʀ>j1Pij ÛOI$0 J1^|bڿ1L EhѴьNc@ AƸ1rrr0Y$xc/U0nbTܡxQ9%Qj1jZ{Z1@ FEOchJ+ i\!c<|o1:9`T9+V(2FooQul&TGwm&(5矪,>?m%K-j,\C] )>M 1_.hd|u`gA9+im^t3=~LJqv}?zlx4$E9{Q;{ g *DSUxʢ1a')EƸW1.j1vnbō.hdzFG%c6~#|?w N.Dz[_c!AkwY0ڂW'}(Q`@5b Ac۷O1 3Ɗ*=u`;\K&AHVmb~*2F2BI޶`B8{s]wOGAk0yI4_㸽F^aш2Z2M QcLUq^WqvЪ--Xo c 6M _$4@ݞ3r ] S11y[нAp9a%CVxF[/eKPua&40Čcᴐ1S0۔QzF>zuw9?a_#-0[ţ1d?9ُq6mE;^cyEˇo ʌagclڴI cPkJ"m꒼ӱc#NU[Zx0єD1-:MܒAAoO7ۑlA]yƻZ Z1"EH׃xsyGqW|\kc0dJ"i?ƈ<1jXc(DSUv0DyZ$m~IN4T##m?\ chJ1bƠ$c"cev7cՁ1 A5]V~~QpAk0HH"壖12%Q!1~Lʌ!ma&---ƸQ> ءgrţ1^190YR(Σ#U[g.N\߃˪M ߨJq5F #Pk۵lAk0^Aƨv7Ʋe˴0%`_ [? j2. uh&jb5%#--M`MHHH{{;)1OjњA,j1W10M lLՖ.E?۽*c@ Aƨ|z1ܹ#OI4mbx0FZ'wԔ,y/o-z\U nG_a&g w` 1"1P^/ZÌM 1c,ܓqUSg6W=p4U~rnGcX^)h#G2 @ :l4G{g 61y3FeaΉOEq߫,nLVV kcbJb'ƀ@ >#1*1]p1ƕ+W0M /$/}au[-T>\{5A uOWU}ȑx1܃P%Pc%1{m\]dGwc0q8:Ô)cc~ɓ'oooojj*..ʺ~@}뭷ǝ-i%Vi?M4mYٿf6 lvӯ9Ϳ;˿G>y/x k/kܼ˷ea~k_24mz9Mw2[ 3xSj~L~\4IR[a?ܨx7!2z}^+cd[ܙP|7v$XFxr ^*h^fv ~q-jQJ:ݿQ~f[*HzR$iZ폰lߴG[mSijM[յ$W>HyjIyx!|.{?^ed;,r!-kpZVW =#b^[V Q]l=R`[E}6Epaf7rزv~337qÆ [`+֯_sSNcyrrrff&0YJ+ɠI 1Ea4U=1F[}Ub]~/0:DE ÿS1,ы1l1 ctaB]0FCpv"`8߲am3F/'cԻc0Hf`FefbưSƸ%w:a 7oAM7ctaB3ft^+̸w`FGɕ?0ƨ~Qӓ1I1R1+ϑ𼰧=])bC< f0 @q?ۢBa _N]0f;?.F~C3Tlrrѯ 1aիWoڴ)((h׮];z(0ƥK1K g)jۦF7emLb`\.~IG ` t0z3?Ç͵qtܹ|gC_{ĩn}[4Q,U 3?0 _s[8 Eb0`8nj<00>rn3$f=1f8f flZU ca𽌯3qk{3=l01p0Ìv+t&޿Ynj=:OlFO }H*æ2n**?pVh0Bft:ct>P;ctXGfhd t3081n.k~r,ԐW^5k?\oٲ%$$dϞ=s`7ndee;c J 1fL(>뛣Z}`ˇ F_?Vv1HH ^Ϟ={)0Fgggkkv⩩pdܹsŊfdϰC?~~TLHHyfZZZvv6hxw1%F?+I]mxcw4*q41;W g BD1%mmmpfdd\v۶m[Gs3 `W}aup ~ǿ߿;-W ö_::s?Yk[Yχ3x+G yu ___?|˖-v튊:rHJ!cK$*Gv~m[`q^p8v.+`NU% c$.K/_}?8᰼tRllldd$`ƲeϟaK;܅}Ӑr;̅}èʾڎ0Wd_7w(Ϙ1umذ! `=W 33s 3g36o駟\: t> g̗`a\a3{fcGbC@y/q ^Tuxk׮]~7|һw >𙐐p-"Cr1O+/:sm*;41&cJAZb` ۝. V88O: Ν;k/x5ʬkVOgY!fc2aTc1X,?1+l|t(JIP_lܸDσ~0$11'ז}C6Tvg J*1 38cO?~ݻw%奧'&&^x0ѣ8o 㫯2pYl31^3_ /b31Y+`ֈ>,rm0ey ~ |hQ5^9`4H%ٞ+JCɟSb3ơ[ܱ- c\?VzQ}] !0d ~ K=zo*^UUojj* Ǐ9rP 8wر]N[1"f`$fL*f3_뙯rh70x{_}ԩ8'sRb34Q1gzf@H?lYW]]Y _|ó 8K1 P˵TO{c \e00SQwP~%W^C-^I$F3 ~?tvvf455UVV³ G)@p&%%1|u88˚璞(f51s^3gsZ60XN6F+w y8pb` /``{b,1t4:C1-,v7+Ϲx0ҡˇ.sɏ?h---\h3X\\.FFFFzz:)))Ɏ&I375 1ykbI<*(;"V;TR]#Ұkh xLKK7`pE=! ]͊ߟ ; ;5K'cUbh f\3x4̸sNSSFMMMee%T[PPq2M-Ջ1ӧ=z?CΝ;---6ꕩN2FT*Sg Â.ӎyzIO'=txÛ:? vTAx9]*o|Vb5¯% &ɏ j&2xakmHeioxwP%Z7f+M̸wFGGG{{; ֖^ӬyLi3Nϸ[cL;B2Z/h@K o>MczL8Tp.lgҀ!#7(qcIZkSOEf{oc$$Ưݧfؓw$ Pـk:Li3w4OMSF;e< ɴ.$3AKWu.i<XiТDq `:FcƘ: "hm9chMHҀT7)cW$FopF\k#e羞y:LoFr6"I;i']*]8$ n5Dq~8ZL׳)1fcmlmyfNtR|2"0#3Ƭ3ƟGb8|)IS<><*c $.;$Z8$?Uz]2:a%a&96BȔ85aT 0Y:N6?95SDψ rt8#s )hA|\n?J*e1fNQ#`}eՔx1F3(1篎q'FBt9 ]q$gJ#f $.ӈ@U>8²[ՔYypK+c8:]bPIt1/G u8FTdEю"& >]F$:c Xv+겢ƨU#]]r]71 YII 9TƤrYGhG]4ELх"zݍh ]^I\d;ư]WF}1\g J"NbPI0t1vV|Cch ]aAEcqC`$ XϷxacDJ;/-5 '1. $v0%80I aJ ݌\Wrg g=qH??܁-59xO4SbRbВ2TACJ"NbW?Pv54pe6kW+<{O4ጁ.1t-^IL!I%$1+)1d$$z%%103Ƥ҂ lfl)/a1yözNY`=lu1%v '1+)1d$$z%%1ÔƖV5Ƙ#~Sg WAВ蕄@$$z%1%%z%-12IU%p[dkW-Qrjl蕄@$0@$$ AKbW$3Ƙ9uReIAXFf% i(zm$+cKUV1 ,1+ -^IhI @$$+ ^IhI10 `FI[㢔ecv]b SbPIhI * -^IhI WAВUƘ1e=[׳ ذ7`Cuyh`[jb#NF&1%v0%$0p%$1+ -^II JBKb B%Qa'Vf[W1l{͵7ODbXOƠUIhI JBKbWrВ蕄@$$z%=(ﻯ5캪Q>ޭFLMw|蕄@$$z%!'1+ -^IhI ]aJ *I?%cmŎ-_PHh믾X}h66TzW0 RƍhN8ꑽעitWz450@$$z%%1t)1d$$ @$J `1^_uЮ+^wK ,1+ -^IhI ]aJ * -!C%%1+ -Q1d%1Xu+GvöUx$z%%1+ -!C%%1+ -^II JBKb$cS7Ƙ>ڱlcBDŽv4Tzt1dF$$z%1%%z%%1d$$z%YbQ~ _c3ncQ!1LANbWZC`CJBKbPII t0%:`mCyOGޛ%aJ rВ2TA0L!C%'1ZIhI$*1eҸW[wM$zXcĐВ2TAè@$$Q+ -1D1&+f*حVÖ+~Vl'oS]cЪ$$:`CJ"NbВĔƖeƘ$Q+ -^ILal^IhI ]AKb$3Ƙ8nLANֆ5+`7]q'%yYv1wVƐAbWSbPILal^IhI * aJBEb8c c=3\U׭Z[7|˼$Ņ'`CO+1%%z%%1t-ĐF$$Fpxfe|bg+~r+3'kv+61L!Nb)1$$$Q+ -^II JbJ D1ydYd2˖~|iAn/4}[gsuCv4x] :`ВF$$ D0j%%1+8^IL^ITc{vFj%.Y 7畗^zg{oW1hUAè@$$z%1% ĔƖDc0ƪ%W/YANЗ^6~tGC#}%zwBnv/f3 D@$ĐĔ2TSbH"1CPyL`2 CJbJ I$:`C/`ВF$H uXc10;h]J^_Jd蕄@ Sb[bВ2TAè(*c,Rc%1PyWciJ $Q+ - 0hI VZCJ"HbWSbPIT-+=}EX8?'{!(cp~lobLhGڵ'1ZIhI * ^IL!C%'1+)1DWr'}m~6c:ƍw+U$z%1%$D@$Đ蕄@AmtfZr_+|^~6V]?'1fb;0J"HbWSbPII JBKb)1-1ZI\}ToOo/>9Y/IMՉ1{nu",dĽJf * ^IhI t '1+ -aJbJ I$Q+H g6jdzJʢ z.9k0 `I2H JBKbCaJBKb Zy$3=rdZrϼy??+=猑xlMc$ņuc)1 \IL!@$ĐĔ)c525)k\`=LKcX}nf1L!NbWSb ZCJ"HbWZ0\as=]8{n0<7sƪѻ8f܈{s>MaJbJ I* ^IhI t '1+ -Ahbsc=1ѽTHcOGm.2 %1+)1$$$z%%1ZII JBKbe F%%{ϙ1s1Opk}K_>ݕ;*?vp.D@$$:`蕄0j%1%$,12Qi)s̝r R>S`CJBKbPIhI JBKb蕄@$#??c2Ƙ'0F {wƏf|F\Uu%ÔTZD@$$z%!'1+ -^II HKJ=k1صm*uOSbPIhI JBNbWZ蕄@$H u3{^L}>NnlX@#c*a`^IhI JBNbWZВÔ2TZ#:+\W2wrڧYN#6ؽ[cC6.Z0 В蕄@$$z%%1d$$z%%1V5*=%yyu*0Fs5goNùǐAbWZВÔ2TZCJBKbWZCh%Qa ~% .^܃1X(JÔ2TZCJBKbWZ蕄@$mtfjRv^S1Bƅ S=S`CJBKbPIhI JBKbWrВe1ƺe.Zsh/`yOg`#^0L!I%%1+ 9^IhI JBNbWZ p1SWy^+73^ǰ#*\TpKu{pCJBKbWrВ蕄@$$z%Pb8cniY;7+_K<*X c<@蕄@$$z%%1+ - 0L!C%%1z:cZk 1^1ѭvmZޯħ!@$$z%!'1+ -^IhI * -^IhITuIO[0Y2!11UZВÔ2TZCJBKbWZc**c3X쫨 _ c y mض| AaJ * -!C%%1+ -^II JBKbWWÏ128c(c\PNP#ۥJt)1d$$ @$$z%!'1+ -^IDb2F11}[[mŹ`lZ*>rp Sb$$z%!'1+ -^II JBKbW*c۝وbOGJ JBKbWrВ蕄@$$z%\b91mo@avwp/q#I JBKbWrВ蕄ĐВ1ƹkW 6TXc G*@$$z%!'1+ -^IhI * -^IhI$*1-+-m X;h)?pҊP%%1+ - 0L!C%%1d$$z%%1P*I۲>v7.l^ĐВ2TZВ蕄@$$z%cqsHM]Ŗ_1FصC`CJBKbPIhI JBKbWrВd%Sc_hY1] T6V9ĐВ蕄@$$z%!'1+ -^Ip%ǰ0Oƨ8h]a`^IhI JBNbWZ蕄@$$:c(u# mВ蕄@$$z%%1t)1d$$vPa̴eW(9tȋ+Fns{p SbPII JBKbWZCJBKbWZCD%s|][Vz WW.f5!1 V6Sý1z%%1+ - 0L!C%%1d$$z%%1+ c(Ld*Ks^yy/vaye[K>1L!NbWZCJBKbWZ蕄@$z%S㑓zXW`~0$0mpk 0 SbPIhI * -^IhI J"Nb)1d$B%3Ƙ0Ek.]T/YPHmcx00@$$z%'1Ô2TrВD1(x-ş.]lc 1\8c 1Ô2Tqè@$0@$$Fݨ0%K>c 1X%9cJBKbWSb[bWZC`CJBKbPI43[좒S2c89C`C@$0@$$ @$$Jw+ke "ݷDR]USb 1+ - 0L!C%%1d$$:`CJ1?{wG |{ggvサ;w׉Nc!h+7U2Ƒ=[;o% s_N__%}ub:1UW'Jub^%}ub|$?cQcn cOڵ26%6%.k-SQ>SKu?'c|N/0h'o*ɯ׉zՉůNN/~ىV8H2JV$c@ط5W=m^deXY|aAQEQVưB$f⌱gMean֘Uu}yѹ%2-ZhѢĚQce64gbijYԖ=&1(($2Ɓݻ r͵5u4-t,u+f HA.ymicOrA-ZhѢ-(6Rff:Q]jI,k2-ZhѢE:,M5zI{}TSap-ZhѢEkڇ2FbV\cߎԖGz1*8WB-ZhѢNA4PW*F^_$\SzK-ZhѢ%Q$c++C$c޳:>$`mub-ZhѢEkb3 P6d2Q?FxuW(;-ZhѢ13 DE8c۷UO֥FF-ZhѢN߳;1gޖڇGv-ZhѢ:g7|'~ 1~WP'C2F*ǠE-ZhmpBBSH p8gkwsW<`GgCyz?ϯƠ]72Sik<&ѢEֿ_q2* 4qd;nwr=s1:i3,` %ZĒb7+sǥwj0g6Bb!9k[pϕ^gqyWyhѢEߴ^ Xz;51^WtU3th9-4i~HS2j}ՠs3' ?!c51*hѢEֆkop)#ʅy d Uq.A`^[-c\n#z+jٶ5Ex(Ѹ?Gφyws&CjĿ{K/pbI̒`NU_F+ˮI"KnX)_R}92W!}{)[y1?C/hѢE}8c**]Uܜ;!cTBƈ B1#>E*co#8m-ƎK¾ 4N'|nILX5Ec#k;.kdlN1]08-Ro+i'\w>+c G_LgzHhѢE׾ݻr33uUtEe_1Pyyi 8t%ok$+JDbKO"|NI ⫖+(S |Sp6ɽ>OM ke ;~v?ƧwAbDŔ\b`4cТEϮvdh ss c*[UJf{NxIb23g#DDYn|X-[w܋b#;H-Z>ܑ&C ME ?~ug H+o([[h^+Vֵ`nUѪ7PHt=eօs~NƐFr_^hn;%vO: 9E-|f ZhEj(cC IB2FkgE,2ֺ!J+ً2#=Iۜs^{_9dx͒aRjevPl6UK{l8ϼ#|)EV,z[ŧ3ƺ]> Sn(w;?ҢEϯ;egqt J~]]wtL~%-Zh}ڵ}kL#VP#7|Zk9|n`%n^ݕ[ZhѢk維5.qp@XWKZkNvƠE-Zh{֎[2倆 U1.1α(i֔ҌA-Zh`ز4E4H8cS{}%l̀!f ZhѢEֆjiTΩ^8v%<ҏ2FU, .Ǡ-ZhѢڶyd gΪ\#O_}uϪ@ī+qW<}T 8)ǕW!'TNɝpRN/Dy;B:4 zJg֧RA T"8oNi ƚ.mySmShddlbaT- ,ԭ5L4MMl̴mtlul-tm-쀥p5v3q3u7up0st0wt,fll;ɑsqy<7ݑ),7 sƜ0GgAG'Ggg8aNNv6Vvvvvfv6 ж4F C Z諢wP~C s=U3=3]SeS%m%c-E#M# yCjUU멜U:tFGi-Ss|5.D.pDN"Oj!?KAth 13 Б%<#j@C1L9)BQ8xuya 'r8w 9G?823~"Z,1f=qP$8|˟b9-z(Sd6phN2 ;v>l) 頴'_ױ{`:iqL=G9ߍ^݅ Sd7؏El߷s^d۞`mv);ھohD&GVb؆m#[ ۹فlAlپe3y6&MVL43}3J$fȝp>|/Q^=X VeduX2,`+̔Yd08&N,NώόGG榇N c|0a wNVckjguSɾ le>9HHWpgpG^7jVPXS-sEqa-8vzz1XӈB\QFtԕ1u2̬ZF;Qq"Җ*(j(j˯$)$W<,`VT+U7mhĚ*JH## //UJKAP g~Th, j"FzjU UPP *+¼ sdybYŹH,B2Ai"o@ eeLrVx-.A4盌7d!yo| Yb<BV'D$ L7ӄ2@xEW oWaP;䞿&=">~ǽpȃpUO8H7}Dn\Fs^~x=A0a8_/N&KS%>y<_YY,͠:̮~]~vgW/IG3+wjff'&ގO͎N͎L Mt$蛘蝘a?Ljho/k-m)m*ihLk+Om-{R\Ԙ!I}㺜jdޫ~s:nUƝ׉iW AEj[S |[[:yPP~ _'TaSR*_U)O.KUUfѳO<{x%AD{YwC3Cc:>u|`Z\x(aPA!{]N@8w'pgFہHϋ@]@ssSSe[oz߸dwmU+nVnav-&ul !C$eݍȾmռЎ\/|z٭hJSy.aC'(Gy&!E]c}U(i42Icnj,Č~ ~e(c,Bc<_YYYYCnF~FaVqV 3I9T >+dE> sscoGg!]@@&'{'''ƻ'ƺƑѮўq+GGGGzGF ]t tS;U=Y9^ZRӔݐ]UYQU[Ҕ⤦gO<˼_rŝJ**^%Ɨ/bJSKKQD)I*M*{Ux]S[ d\5 MaT/ fDD!^/|*4³e&3HҀFrE?| %^`(E/X7'AD 六^pQ an8QA.w Abp%⋑qvXx"NѾN>8c\vq%kl f\2lk3ebIN&2#IC,ch*3 HҀf E6@'?馁hkB\-BݬBݭܭ#F@pip(Bǁ#a[::L0$M55S *kՕ%*0C1Lq!iaD 4p@DaCf`Æ DU eB̓(#8 (? `Pa(E4ˮqi~gX^Y̬άYy}!ICìGZyC1 `Uԉ_Z@Z= S8`Nϐ109ՏExXXhpnjdž;džF!Wh1212yqN,]466ewtQ^E xI 5A"Ī׷++^ŗB\QBEqҭ"@ Sço$,IY !$H؈N~%B&J7!%,IBI@(x|5!6rg߅M6n߆a#58҃!J1LH僠 rf&W&]y"}Ez' CipzI0sLC#sYL=sř91֗)י+%EX)WF1.b4,Qpv 4LQ &i °F#$`p;1p?F+3\P"FazTؾGf(b0`䋢iY"gjyD+ A6AN"fd݀FH ¹.~P;.AΉ }}99)g$ 3zog! ] %n?})sSAα 'ai@ۃP@=GU瑗_ JwqܿZEO,x avM6r6=i)|^YUOMz]@cPK4*'HҘo1=5N LNq$~//K%+%؇3+Ϯ񃌼! 1G0;1VPYN 1QƘ=(`tNvLO 5 6 4ZG`82bΪ.Q]'7>oژ!a={5w!`%T+O]B+,~vCS!2@1M|56l\/MQU4^FW!Ѣ&-]IaDu "1/oDxzOl=Ƚs/ un ̈́q'M"Dہ r{1?Aa _0P?!kųkE^~|PQ(1" "p@nLfFn/$ \%ngaBHe9F_ˈ!`2Mtbr]:4" if!fLpF i0] Nȁ(LA8`!1HEWgp#,3r)w_Hc ;C;˶@x}L\,],xV%]QƹB-\ppU |K=1YqJG { _!+l -H4Y#L7ѳ3ֵ5Ա1жײӴ:(0`j L5T0SDw>`$9ʦNFȅ#@r*p =R|UV'`"P6PW6P1DTYHT6đCCҸE=Q QA !BQI[QRP ?MP|t(P 7 Y^2P$S[^Wo'~gN!ݑ'[[M\;2ׁ m,X6#=MTv5Tvb#mHUZy**el'j+6f\ZGmEG +`SA5i͵}l@[`{`{PGpgHWhwhOXox_D_d`4tό̎蟟X\/ΐ;BǗƗ'WVWY[ʜ@0/,V"`ne[E޿c> >b߿c##{D|&ҏ wV a,\Go,8ÚexdauO/O-M.X|;8;03F&&NGw83 zU::`$hh'zbk=̏М)^6|/;Tt/㗘a3~X]h^S :*0xÄK(kAСGjY$A*D )ke#EJ@cG%Q FJdOob/xc%W1ʉZ28fmW` HY}eIW^ $[[loom?l:s]rlϖ{ػm >]g:{d{+w|߅/< AӇV:{D1TN^8&)߷m' a~QTܷK$nqhh$ c]tWեƻeLݜ\2kŬ5 fo:d8`:6.8W#s'xg.?<|s_. g~>y'G~`[usVa,C0\l; ؛O܆e|ws5/d1͇p;70}5/e&#aNdОEt`>3W&(\@|f?RE'ދc6 -OhG:LhڪxcEd_~NzWW|Ú!9Alj/"ɵ$P\3q!",)fWP'UrBCJUȂ|$mۢ/B($4% FdXLHɾ! C)^ *eOQ٣ǧ?>HdOiKdFN'FRIHARI"/zf=Vٍ*< endstream endobj 105 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?4M.[. CY {wvÙb0 JzpIՏFӋ :w־rEk,N"/cz:IB7rд94*ShNX­[r1gxO Ŭ\iv~V>M ߔqta0};# rh1>e5{ǹ2 QbB8T6ٵw[Mm08I0Cx=@a=/W:/=#NX”hz/4+Eݶekkiyx: Ŷ"S g''珈E#UͻrHb+0')Y>c]D?ӿ?30m;S+ռg)1AvTC"nO9VB rMr;-t}V"$磢 G$sEq~410m;S)?i X is^Mg!@79PI0:ֺ2E?JTvmx#cwQ@m;S*u֣}{ L/E;H$c*0X]^g{@m;S)?t?i W1EҵWH(a'r0ی295z㾼tF.ѦY 4m ,>\:G? R7_i W5"Ե/4˟*;{cP3~A V/Z$fP6NCB6|`M0ib84+.]O:~??&cDԼF4H]<(l$4 eخd\mnYpNFkj7ӟf-eb&Gv@cOp2YG^{ko0ȵc'OHl:i:G-6oKX+5- UK}9^{׼3R;K:;EY6Y :qBi[~ M;"M9t;iV UMvw%?*ખ b *]FѬlm.nm.\FxbKx];$0I\8?.9,btҴ3z=ԑvQV:+I!9Fr5iXȋ}K;<'B:#Hml/w4;?iOM ooiD!XrJ`E kbh4-+oͤiH¢4.$[@0hȾdOVq4Yi]_W94]<0ݤZz9^t};# "QڕCJ,TFt;c i$L%u'.\s޴PDs3}4 i TG4+:9d)zS>4gfҹiؚ'4(?,YgQޕo>X.jbӿ?.,Y/(+IESdh:(,YntX.EЇ)CЏ+&Kj{{wsEt ,MmFƏ$Vr3Oi6h\.t-8Iӿ?&[5ڣ=Xw2iBy?ӿ?&?J<`B|>[D)ܩQ%BB@4};# m'%:wѿF5~;hqaHӿ?&4bv$PҬ&!$4`>chjHӿ?&8Ҽ E+#b ?&hYVq5 T0';T6#M XJ?&n%Gj,T:.@ݤ TE?$Z@Qd"N:FJFzwVbdw-4- NX—D>6R :@};c iдQ0};c ֕\a_i RFF;ji?4oi U{GX`ȵAAV|.cՠ Tˠg`wquv@ q~qUu= 64?i TP:!:>@T_j\J^dRij .dؤm_,:r[̸@Z,Z_ Eww[[**eh[-%nmVhso-)`EnH뫸n!ro[i]E :^:i4nm!GIkcgG. m4 TlojC62Yͷ@jLXC?? ,XqIMlVTm'in~MֹkЗ:&pмe\m -E"L ~]"-|#JH->)'0OF{0k;IVNAkjlM m?Sӭ}:k)@SRC؂z }}hޏpI%\mO"pK^jFIs18 eUd915m5'LPG }}i<pzn+jfkWxK,P`J:go Maj3ȍ,&2+dFSf#'kl}@{;L2=k;FyuK:pwom#y ~]\[ wk$1Mj0&!uoV_nA }}hu_p4EP5ȏr A<_%jPj۸.y+\xJh}A >qR0Gcگ }i>@[;JɆ?xr|5u{j*-B:LYU p*0:sit [ɲxrP9ư57]le>{pɶP#0%RT*TʜokXn`+̛aFPBP90k;B Jv}$ڭy_7Ы9$I8ߌN)z \:}g+2ۡhO}@k;Jn/O?Ag1x9N>k/b+92 7,\p02814ZM s|Dۑ0OLǚ2ޟpn_pJ ~U,Mvke#ݘ2HPbWJTZ,2F1єu5v}/?=?n݅ K,HJ\ ?J͸_.5[]LiVp[6hդr2nO-w{V_p<p.S2Ց '0w]Řy|?SڶC7DD䷘$Q` qhyyCEq3"23: `)jv?B,Tj=? }}h 2F9o? }}h5_pwB!ji8l֞_pp{5.VGY,Te?e?.d;2i[LO^^C k=[}㴛}}h 1d /G?8Mz? }}h 1`OJz٢}?}?VdB lz }h^t;2%4հ"yןyן]DH4_? }}h? }}h 1օ:v:v({@k;E5216v#oy?r7}vbmӊ_6]37}v [;ʯ rv]R==̒I]Frp2O8W|O+1d2JٮV{+iDLd0Rc7Mk>)c[O_=RW??EhZܖ.X O崷 Q~`F2zc'ZZ㶞o*c!l#s/g;\xH` bDBm,1zz=z[n#>YHt$zYo~pET!ns ,5>ϓl<ѻ<47V6c=pY22{=5"Q$*-2@ P{^T+B J>Y\ L%lȒq)˸6s۶1뫨Et"= VR0}#޳ceG5ҼNb8f'VYcjM/ly(Q]A֯%Š A >W<M)C@ݻ8:P-ywdfc`A ˞W] ^EMmP= 0`6UEjI*8DxvGҟor#01<}|;o[ZDI=-l.%WȔIʮ+_hOٝ#?zHˌ}T,=ld 69Hr}%i0 !8+svCT>PH/3ˇ֒C)|2҇hXՇM{y%4T8`Mf vλR;Kf:Wm-ɷFr,$u=*ijK3+;>MFH3'ӧ"Q$*-2@/0M*U7B` w%+{ ݗtmwCor4,?ukmC]k`Oڃ*?>ᑓӌaj٬2z c&}7s5m/jf1x<·h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂk&h#߆⌠\FI^vjCj$y%ђTOJ "2idߒ?1:oqUp&YY 82gXW髾ƴc JvC|$O.Q.>1б{>o cG,[;Y n2Js b< ǹ^%ۙ,gvo 'MfYՔO1I;^yb8=} Eqs$yBFv.b`KLRvU} x䞵3(ӗ/oYd0UJF+y%gve (۹q[g^-,t\y57:ͪ3ng;$ |W8=qS׀Eދ"~Gʖ`eG&^; O6J$=\o Ѽ]{?fc8+8ፈ̨ `Vub;EYM$A1/$l~OSgvo &w5^~S]/;I'3[esBYԖn7ƈLa_ҤkDR檁MԠ}S"{AKY w&8\]V(dYH"R=N϶/^mP[5=|;T{89oop+.c"Lruϡ'NpIZB'~WV+ 4W\jw$I VnȒ\9dCҠ >m.)py#˩2:={W%i.FT.QO8Xdƚhv=>LUUm&pᕗBߐlly%A?yέwqk Mϑ3I.8ǩn-Wu!H.dӛM^ݕm}OmrQp[K("yd2 s/Iխm7WYY^R#j@_xW6D+}k d:= 5oeJWvȭ}A],qc5g[3I)qĜS|ci=ݬ hITdAגeErڣ$y]x ㎢5 άmo1%uKm7S2EYcIc1b0]Po U%+!As2o]8)c=ߥheJE̼WW {)8G$̘;B|T}t=&R, $d1BqIX_* ']ޙhzct}DXKQ>7/cidF\*ǹcQWLKUI$# TdZWy.9[r{%͵"Fv s&H<|)i&_*[X6pփOJz?wr7 ~`V2ds/?y:wq49XHS9GJ<mi enl#%˖/w.1͋ҥu+YՐ ]A8ub8c[,\uiVSAlmK7 nem)\-뜜gVDX5DжU@'NQIEFUYn",AIIN+@id _2Uk o>K"xQQ789n"y/$\<1I !I]H(5r)Trm3Zxlm*; dI@fҖx$&kcb*{ۗk;as"" d {C/j`]dnE稩nTuޓLUEomgsX/Pj?%χ&H+3.o_79+ v?q)MI/Sq(# W7{HZI ]Tcס ȱהjQg(bw62Ͻt%Ou]9z7Qmٿ&_*\: ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUYHB;g8N+>)DmF?7Nom?_3ZגoV%wQ8OVuXE ([4%vb `_NSD-\%ƨ9 #Ƨ#|a{g=HIhث@#ɧvd%F+ T6hjTH7wS^C{̏wmgWppZ~D5aA_Gs<%S8'#Ok;rBVv[bB\u˛c 7cݻFsں Cb ?l?5+'N18GxS_&4h<Urs]_oS?MѰ?/FPؿ”)$A1mu/]@V[ɝ#cЌW0 [ϴj]ے1(lhjQaA_Bz[E,`LP!oj{xc*#''K'G'K'PQOP-5E+.1x??JKWX1V|?_?H@@t 8p3һ&OO&&OO&JqY-RjG[ gjVpF:DCHzۈLr29jǓ'K'G'K'V.Z;6&K>&OO&&OO&ڮvZwF#>::~o.GNOnwL/ML/MoϛC/aMOڕ P٤MX]žO66Mr1G'K'G'K'X&Ӻ8&{+'?߱:Zu44@6Awkɓ~ɓ~(EƳR{vZ*f*TR W.6tM~VdރV'*`8q]w'K'G'K'Zz&g}wwJ$LXgIYGh۪Hy~ukɓ~ɓ~t<ǩ EƜ#XȰ8`tY2}*hg3?Zd$hd$h.g&yzuXE ([4%vb `럓I$ehqY }xEuL/ML/M)%(aŸ˙nT,4{{[XoTWy|?_? +FXϑ# =O=O溿&OO&&OO&NL/ML/MIDT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/M@0פ5f%޽#'mwJI|^qOFk__ Ľ/')`qkbCW-dE$??MkjХ E.,oN\sgV>*/Œik$6΂c pA=pVm"<&"! 6>\mseI-gp% daS8o6#-M) I}Y<  ojZ}W".G91HF?vIb=Q"]n0A{WnwVXZ吽:ͪxRD c)<I~ԮOxL.--ﮦ8 ʬ8MH'W5^BҧnvZF{܁\>lZYi]Y;5ԏ,BSp_Z'o :>noՔhj2&A T })ot=% ў5*UI,@Fz'S|?A)ohбB;IѰøl'1{ )3&%9 p>}*dEBJ[^#Ũ}MosfEh8ҵn/No-ʔa(x55^(a8S?WWrobRy3ݰD(Ft޽uOS55BQ\GHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEIaI8k~)k^KzSi^pךSCz/sIҊV(‚wKOҳp&7Ei0FAK/OsI'&"=iQYJ!HF@KNQ>0fzō1α.,Dn]Z&Kni??4 YBrWz_tx당Ѥ JI;q׾kǾ'kM1 gm߳v7v7quK RB"#4 YBۚO,!?Ƹ ķz5؍;" U[dyܾ#-zM xF@KTN3^jnF)VٝGAK/OsI' Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥt(ţGC|G'Jt1hmţ Z?kcΓߥt(ţGC|~4MlV+`>~ibYyAdK 5f v1yp!t1hmţݬW0I)P:6d2SkxlR E'ۣG?mn-I]R m/HWHC" 2U)#5IҀ1 Z?ht1hmԑ/iqq$m*ުA9:u3\:bdJ\ GC|> Z?iWUqWY&ӧ6^9<`Zt)bGۣG?mjGx4ʂpG=FGQΓߥc?b[t(@n-}?ǝ'J Z?j֏1ÚY݅QZj }g ݼ56ۍFA@n-}?ǝ'JiW\l2vd8*zq+n-}?]>I4Y$/h(]\zu/:O~c?bLɦO}2/#I昕T)%>qұeᠸfhn+;u(CţGC|ڽu K+y7U#?>SV?P?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J)k^Kzd2׭ y?7[;' #=軚85V}ɨ[3D` d|sQrj+vK\9+mK䛖uI%v8 p*Iysj*1f֖wB/46A)w䌒G#>Rƒr ?MxC%anQ'Mӻ[W<E:WR_;mIOhꠓ뎟I)_"{Eؼ?{>_:;{d,9" ,['v{H%5w̵w}r҄J4ׅzj[:OGM/D.?j햟{#;D`iQ}&w(9q&g"J9i2Y\bO+M¤N 4aJMcH6w&:UՅ o`/[X’zkѼ3"ͯtFyD3fCxV؅ jv۬)esX?,]*^Xk`Xj \Z}ڽϵܛڋR$g*D_ha, jޭؔ_ebe8U,eXS- sF ?dkއ?b?_vja/q |V7Oz ]dx*r_B6+r.๺#;y$Ͼ¸oYc(z?b/+S #gR𾬓_Z <_i-xؖ䧚UgdfE9[O=,HVR6a@A V,w߱Bb?U4??.x* [FK8HO6E1<|Gmkԇuk?dkއF >`L%?=Yc(z?b?_ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#aZ?%o_]֚nU0k?Qyd?ծZ:ep7);TNI%c)<iZk xnkA纊hf&L˂k;J0ɣOKVK6yI NTlC<ybz?Yc)C?mӥmsnM0m4D8R"&G*̞Œsy-f>-X)w72H <{F ?dkއߗ_ژOfTeb˯Ro=+֟&DSMF!#2@1JvWG,w߱}Ckr+<%?=Yc(z?b?_?L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#aWG,w߱}C0? +dkއF >_ja?z^#\;tI[iV6 #9:R ; 3%$}8_dkއWnsBŧUԼ$X${&[eg Tn *rjw|v[Mf%;bg`(_.@ba'9ŒgW; #]?5C~RZܿ0#jLitEo/6dF{xP 3dm lOijW q1/TgG,w߱Mq+S #Lx?SӔa2͚Lx\V4-u[ JΩn#,EgCF ?dkއ1 5˿0i9$,.U Ape@@^94EZ[k 4@EolH.:0&,w߱CbS ooxkŬݴwkm4$QWgƜɭJ=$8t; $) #]?5C~S'Ow_/<%?WG,w߱_0?=Yc(z?b?_ژOEx,w߱G1L'`ڏ.&F d5bxQԫ h#ajΚdqYj k ݪ,1]$e3Ȫf$C*_5-XbA: #]?/G|S #BºΎO5TY.ʹķW@pc•㍫Okv,vWs*g(A<+1ӚdkއF Q/?0?:=S7&r4afo,YA(s6BrFESO |ShAT4Cm4G +$d G,w߱}C0?5,s5i#)4[rb@*ׂoB}>V=7EO$pZ22G,w߱}G_ژO%aUܚLWO4Nfd]6w5C~Q #]?PZܿ1i/~WG,w߱}C1ja?{5C~Q #]?P/?0?=Yc(z?b?_ژOEx,w߱G1L'`?;_'R"YB́Jqje(P0$j7q^gOFk__ ?R׭ y?7[p&>#._=o$??MexNբ/6V؛y<@kZ-*o1 K{?97MxHIzETA9xlɩH Bt.Y|(q9vÚM̗y4FҳE**S瞄csῈxu`AwU Mcnݘ\xۻv>L^k_i/ RKzLoxcyX?Nx evKcrj3 0I'a#'KD{շ-2s!@P }OޤxQ G7]Fw<ҏ\1UR2Bh=0*X[CQa{EK6In&D|3WxvxONDn.ѧIl 1QO~¾:\2[# mhIUí 1P}掜ӣ9N+8/K =W9G*g>RvIo$Q-QxzI$rO ]ɵM樮3#QbLG?x???<UXALG?oxO@|M@G(:}Sg7Et?*@|M@G(:}Sg7]/!W.MA15e\Qlgi?7<U8xB&X0fAs #w^OS:esSׄ,ۋaqgme!$l'&23#Hi#S7cBoUݷ`f銑|;㴍Sz+\00FF8Ua Q(]n $(uOr!Dv]oZ4moo<-,;]0d*)⫉iY\cfcIniS84:8rM?G[ _x?/<Uo?ξrSg9Etx?*O7#Q?ξT#] $oG_;#Q?ξT#] $wG_;#Q?ξT#] $wGo;#Q?ξT#] #wGo;#Q?ξT#WAj426ʢ;g:2nyU\/ #wG6[?]|z1~1Q:ԤS_y,=x%fLn4Of;|lj0(.c#KeN1-kYir-o_ooѬ䟳m%G={QqG".ʣ#{V.^->kh}̘{j \y27FCx_ŭfm rnPORKZnO.a{I Q찷TfTU*Jd-D7Q)gfþ2uau$ʅGRNAޘsY-Gpm@n`9݊9.u0t7?"q{mSX(aQ>ZKţhl%ǹHrCgF5˹d6ăFAPu7BAڍQ%Ix+7 <<0OA=#\joFzM+dI-wk5'9yIJY/[%?'8dvr,I;T!~ F/U?ξr}WfE^agx&< ёK}ۦ㼶 BVe,pHF3GĶ$Zi4Oco":u@XAs1H̙̘} ]Ռ3u-f3t'{p1 _x{oJ@jWq$'zi^6"&!Ӈ1>~8Tƾ+ Ӫa3[IHYUd1&pfU'=1VCOo8{d"_)Y2IMߊ.S8Kt9-}7NZ dx=W})ZvKm܏cZKV0l5-_HcO%V݂E` }[yqcjxEB|PWt=B(^/MWcIΖkE(VwOLI!,q2e,N}ךYGX{vyVp,g;$8=I=);⻃C)n}6⸵1j&9o鱁pq tarZɥY'-̒4VqFń3PGti2 KdžBKנrIyOȨẖ BODgFr_zB:4-Wg+{5Xh5ϏFO*<9Z_-4Vp=4bkҕ%%PaG(4ٞrqKo4s[__ n&i^klKbt&?EjG- 蚶3[@E%AAHii(4RPh(4Q@h@ E (E% JSI@%)(IEJ( %R(4RPA CKI@%)EQ@CEJ(4QE%)(I@%)PIAIEJ( %R(4RPA CKI@%)EN?tC[Bi7o`kO0ךo^y# {\pיMCz/sŽOW_Fkw5F/'`jo_.:EC@RPA CKI@%)EQ@CEJ(4QE%QI@J) -% J RQE( Ph(EPhPIJi(@%Pi(IE(4QHhJ(4RPHii(4RPh(4Q@h@ E (E%R?TI߻n?8k>'k^kzeVq^g?F;__ Ľ?'`jo_.E$??M]ދE GCIA %P(QE)(I@J))M% J(QETo0^! *փxj@5SGր-RbJo֏/Z}hbJk@%Ub &/Y}h7@hk_ZO/Z_/'ր-Pj֓k@ VZ}}h%V7kI TXݯOzIQ)CEJ(4QE%)(4RRJ))M%Q@ %PuO[_?@t7?1׭ y-7Ln?8k(k^KRؗG$??M\Fkw5N/'`j3[@E%AAA JSI@%)E(4Q@ EJ(4PhE%&`5k"]=0,6 @x==+{Pb|5^xV--1E$i ~'_֚WbnoT:zmAL*WY}iz:FgbgXAքF9I#uxC+)`z}*Q9F|YBo+<,~o 㔙g ]@U!!rZUdlmC w.SG*38.Qп7,RybT.Qп7l5}#TXtRX֥H~5bym%xiˈ;.'j'ҎTKx]vr"йoOdo;FO f~g%?& O HM?doOo;F O Ԗ GAOo9FO Nd3ϊ'O'3J /fU@?.QO f4{4ќfV,ϙ7]rvZD͝`?gQ(F>Bm mڛvn#d$PH qk =/k7w 6ѻ?mjĖh뫍jK KHq1(TU܁u88rjQ{QƵ/mj6Jmŵ kǽ\ g횸E}4kk}cogpOyWJ~teK HN܊MWxJOĶ+l%܂4(E J(QE %Ph( PhPIJi(_?գUnI?d[??2גo^?q^gKF[__ Ľ?'`j3[q=OW$]t* E) QI@J) -% J RQE( Ph)CKH bjj|sx_=tZjq_=Tw-x;\Ӵϖ~Ѩ&19?~`EgV)QL9u<% Ms qEwhC`zW?K(=_֌emvt)KIbX~mB6AR=s1|7va D&Q4seG28Zg.FKD꣫0 k|Cʇ2Uz"0e4e#X 71Ըu?0^!$?VO+%VO>( PhPIJi(@%Pi(E(4QI@U'fUKi:;-Cץ]xӵ yZגoT%w=OW$]SI 蚹'Eh#~T( %P(QE!)(I@!PIJi(15_x;C v].ܵsGre[}uzI1#F9˞c" ^߸?.1uzOi۸$fd?1{~TWvj^٪ *(,}rk9EmwiaC4]ț.7QqAoƪ[]V9eRUXzfadfe\f??3}~iG3 #3&7QqAoƫN9Yb??Vj(*2N)߫5Ht'?Vj裙*1QVj(Õ A[oƨo ߫5[Q*1_Ra??տz(}ÕrZ[_I?-{~kQG3TdbKA{oƨŗVr+_ ߫5G4vjh*2TcMAoƫV9Y_b[?UE,i1{~b[բfFW4VjI'erF\ 8Q ݬM!2ۏ( $xׄUg>+GN>6GAEIE(4QHhJ(4RPHii(4RRJ)(4Pi(U.IUV?h -Ciψm?7K?8k%i^kRؗy IFI?ez/s\o?#H9?ez/sD&RT)(4RRJ))M%Q@ %J(QE!)(n bq i_vzյs~ $k!k窎g _Yv1]0GVbpHZA֫_I"(ӣe$6G#/oS/urT8mg#\6mf4y03M+K5xkR5;˘2k'uA8]dcnMFM\A`&[Yb*nSgwqZk^ kq MslV`#~`qx)]NAł!u %$2)R `8Pyv;+7g&:O vPT*wf@Ԇx[t-oe•vL`QFhzYiV_bEi$&cbŋ;0H# x[+i%OvQaI bQ~`s♅ O|"Ccrxfut/0Q{-B[(pN͠sHڊK. g@ L> U*׺.3~q<4ITQ5 WIU!#G9,=eh ҐH0$gbIں`?-$]>ZZ0zh!t|hOF#zEyBxkKDE;΍$K$`;1la#8;9ɬ x2Hѭ![}I,EHXk1om$ o4#K+-F7 28ɫiVڝΣ H7 3|ٝ݌c5r.h4"mtqW$9,r88˯ ihhfBޝ8h i-\I3 `ksJcHBjeF2T𶑬Me"eh舫R?DUJ[lQE!Q@Q@Q@Q@\ Y)99.#"ac.UA>e<'vmsc޸&s߫]L}?'ߵnݍ.|c1r_ do1bRZ[|:f#z9T_zyv[_R,%1kut!弲Fg9}4/lPҬIojYP` DP rHoXxOO}X&im3qL/z{7nKo>f1MRg9}${_xs˷ߢKVpi2$R:Fq!m+' Kfbxq' ”cvhѢ* ((((+ۏ( 紣҉*<oUg>+WWipTlP:Q@%Pi(E) QI@J(4RPIJi(4RPh[/Vj?-FA^SC6??d!ͷz+~"j|$?h'o_.$??MXFKw44nE!(( RZJ))M% J(QE( Ph(H -#t4}\7mp9 _=T>"gh舫R?DUJ[;QHaEPEPEPEP/Tq :q~U:YزhÏ2y8̈9c !{Ho٧3ѿɜ ht?loAVÓ'B$"E,dHE9D߳OݍwGr3g77]x߳OݍwGr3g77]zq@$ĚsO0w\[TBpu=7s+ֵ7lM4^c莞os{Ho٧3Ѽ{Ho٧3ѼQKKczʏ7{Ho٧3Ѽ{Ho٧3ѽĞiz67H<?MC{EO\5ݯ2E$43 ey7hh*iey%](y}⳪[rТ+ ( ( ( ( tۏ(*4ۏ( ǕӴϸ+|'VM>6GJ % JSI@%)(IEJ(4QAC@RPA qWU+t~ ͷz+ʾ"j[[yO_ YאђUV]bGq".?Em#%軚RMJ(( %Pi(QE) )(I@!PIA J(OCKH bj5x7C~ v]&>Fk ^А Hl~upvZ?|"*Ԭk.oOgIY 0C:OoJ(MJ.RV5 vU㴹_bEco7?}yms#b? v|.9_`F ]@yms#f;N랚Mr̍z+#rO;G vW9EdnI@ohܓ725謏?ymۏ@oh}VG&?_725s8M㴇.9_`F B?/;G+ڢ!]EPoh}TV/$? vHyms#jw B?]TV/$'W@yms#f4J$7?6G&`ҳH08iDh_ ǕWpWMOʽ3ME ŠJ %Ph( PhPIJi(@%Pi(E\_:U?J4!oѐWFݗy%z!oѐW|Gݗy%ZHEP" dz/sXoq+~o-ދE>rE%fXRZJ))M%( %P(QE)(I@J)435!>ԡ5u4EE1ȻD$AGXWhb>ʦeZA5~]PC̶cکei`Q%9#إ o?\oG?]Ò=_MB{/ W?٤fi.OˏG'и15{OhR=̺14 uqcj4`Gpb,Y[?1TşS`G4{IwH ? g?Xжcڪi?٣KrG,I[?14şi٣=${şj? mS?٣KrG1mcj3OˍV٣ =${Ϗ$uchO_#տ/hfi.OOdqchO#կ/hfi._OduchO?aAп٣KrGW?\3G'и15g ?٣K{8+' K .? MXgfi.# eiMnmSO NqFSAڡA 稭_/jXt@i9QXyA.]Ռ[PU-8E+f(RQ0IJi(@ %P(QE)(I@!PIJi(_:U+tFA^SCv_?dFA^UCv_?dk!w<?Eo#%軚[r|ޛFKw4KD4QA) QI@J) -% JSI@%)(IE(4QHh#5II@Oja_JI@>ƾc_JI@>ƾW %T"R}}*٢*}})>ȾnmғV f}("U S"QEtEV T"QEtSiAOJI@~Ⱦd_JI@~Ⱦd_Ji(ғVSGҭQ@ QETPChGjA0 (E% JSI@%)E(4Q@ EJ(4PhWVBW5u ׭?+u ׭?*C ??Eh#軚ʈ87vEiHhۤ4%Pi(E(4QHhJ(4RPHii(4RPh(4Q@h@ E (E% JSI@%)EQ@CEJ(4QE%)(4RRJ)(4PIEJ(4QAC@R( RZJ))M%( %P?_^i_7m^2 !$U7m^2 !$_ ;H5D XI>kF8?ދEך&F?.z/sZׂa9_64RW1)(PIA J(QE! %Ph( PhPIJi( %Pi(QE) QI@J) -% J RQE( Ph(@ EPhE% JSI@%PIEJ(4QAC@RPA CKI@%)! +u`i!_Κ[_ݷz+ʾ#nW_շz+~#n|$?8ρ\s?F+fz/sT#¾AWw4IF)^٤̱ Ph(EPhE% JSI@% %Pi((4QHhI@J) -% J RQE(4Ph(@ EPhE% JSI@% %Pi((4QHhJ(4RPHii(4RRJ)(IEJ(4QAJ*ҿ/V*ҿ/Mjn?d?7e^CFI^jn?d?7e^CFIVw1 ?9c]sQ18O],1_.zT,)(4PIEJ(QE! %R( RZJ))M%( %P(QE!)(I@J) -% J RQE( Ph(EPhPIJi(@%Pi(IEQAC@J(4RPHii(4RPh(5^_i_ !_Κ[_շz+~#n[_շz+~#n|$?("w5 8q#EiH"lE%AaA RZJ))M%( %P(QE!)(I@!PIJi( %P(E) QI@J) -% J RQE( Ph(EPhPHii(4RPh(4Q@h@ E (E% /4ՃU_:h jn?d7e^CFI^ [׭7*CCX x68q#Ek668q#EiHh4QPPJ(4QA %RPA RRJ))M%Q@ %J(QE!E%)(PIA J(QE! %Ph( PhPIJi( %Pi(QE) QI@J) -% JSI@%Pi(E(4ҿ/SGJ4?5m^2 !$VmFA^QCv??dk!Gπոw5??Ej軚R6) -%AAIJi(4RPhQE((@ E PhPIJi(@%Pi(E(4QI@J(4RPIJi(4RPhQE((@ E (E% JSI@%)(4Q@@ EJ(E%)(4RRJ)(4Pj ?!_Φd_:h ofn?d5c^CFI^ ׭7*CGDd@q#Ek" OZ?1A_.攆(5R( RZJ))M%( %P(QE!)(I@!PIA J RQE( Ph(EPhPIJi(@%Pi(E) QHhI@J) -% J RQE( Ph(EPhB:WEzO_mFA^QCV??d!ͷz+>"j|$?EOZ?1A_.OBQ3@s#EiHq6)( %P(QE!)(I@!PIJi( %P(QE)(J(4RPHii(4RPh(4Q@h@ E (E% JSI@%)( %P(QE!)(I@!PIA J(QE! %C't ҿ/M ׭/+ռE!oѐWEՏy%ZHG$o@j/ &ugg m‚zviZIh`pi3GzdRcF/{S4hc@H?Th Џx^M36?EGl 7IM~c@H?T}߈}?{S4ox^M'l o} o&'M'l }?hrϽMA~"6?EF'ۓ} o&M/l ߶MmO)wl ߶M'} _&A~"6?EF3>/I{>c@H?T}߈ؿ{R4}jOa$*4/Mk{r5/l ^M'ڇ^MMA~"6?EFC>׿/I>׿/S߈  Q}ϵ}ϵՏa$*4hO;^MX  QA~"@+}_&ӵ՟a$*4?hG;^MZ  QA~"@*}ϵ>/Vc@H?T}߈ y[M\  QA~"@)}o_&?{r5w6?EGl 9O9jl Go9<[a$*>c@H?Th9h[}o_&߈  QkϭMh}߈  Qkϭy>/Z?a$*>c@H?Thw{r4y>/Z?a$*>c@H?Tho{r4o9  QA~"@37^MK?a$*4/|{4o}/_&>c@H?T}߈ ϥKn}/_&~c@H?T}߈ ϥKn}/_&c@H?T}߈ > /I%k_6?EGl ̿{4f_I  QA~"@1ϛ>w /G%kc6?EGl $M;a$*4ϝKщ%kk6?EGl {4|O&c@H?T}߈ MϝIm|O&>c@H?T}߈ =ϝIѶI?  QA~"@0O>W 'F$kw6?EGl ?^$MDo6H{ fEt_a$*rZZE" : @:s@#ŷz+>"fG^-D~?#AMyo? XאђU`*ciM[ٛ@6XE n~@4c??E_|0ڝΥϑzBӬ@s20ddg&] ̝|M}YDчVV.&ͮ -88xOjK1c\N`VPv#`0 Qx-4u4c)Ҁ ,e2'?u-;Exaݣ( q*A듙RԞ*f֒m-IJGhadۛn8Ьh,Me:Te7UI tAֶP Kosm:m)3o)w~i(;zՋ? ]j cQ⹽&S 4k`VbsׯtۍL)s co ~v3 $(\k^!LH^)QIQuo-TA|㌑ךx2+2jQG:<$}0}L$}8,G+gnIy徥ɷ/o]썜ΘItԩ?[khgLXErUn#0M];ohBMe9*̾8^ n,bRVR$HIVG}G+'z^?й]ަ;o45TP#&T`?Şmwl7k_uVٵYeGs7V9{}srhCyin.tn*u1uI Ng;2 $!;o'QNgatԊެqEB,/Mثlx$$#mt$['*x~]尊Zh63UNvLQ: s ֍D%oLA 6 q=5g 2KHKIw¦7RV6  Rߖ}BȒO'\z)B$O>ybmGh2͉k7mAki^:Ssq [D-fiI<ʩt*=:\foz}>p cn0q9<'÷;+-R:p yY BxNѦIKi3#W1o!cKy.p"n ~dW)/nֶWuwVeL<ݟ6r[>I[E˝:RMvmC3fۅ tG7E{%pY<8lw ]I u={kVv:uuF b K78 ѧ+_A+ (Š((((((((((((((((((((((((((s_Id/c^CFI^/ Zפ2 ?!$CMGf`)U~b*ZW dFffr$5Snu?x$ MwZ?Ѡj{F _0C%(?x&AGi?#5Sv Og2ZSL׿UGz \֣O4i5=Ͻ77bߔjo=s:?)ƍ; S>{A[5I ~PH ?H|GgQ4=Oc]o(?l\ΣO4GgQ4 ~PORW)ƏH ?FBߔj{:>#?3SIgQ4= k:#N/?xL~#?5SN}AK5^; AGh\ΣO4i5{)}Aƨ}/(?x$zu =s:?ѧ`׹_oU)ƏH ?F^}ߔjRWGgQ?#?3Sv { _~P>}AK5^; AGh\ΣO4i5z,@42A*N"(sҸ?Zˬ֛-b f8n\dH'/F p3Ђy8*0 @S endstream endobj 106 0 obj <> stream xXn6}7ࣴh^%  4^>l HlԿ )9-9hn̙Cr._TbL_91$o' 9ᑠG xY#Wra8E7, k"i,;Esa @<95l|_D{?~%@z=Llq:NJރ 6de:>c Rύ+p\PXS m?4F{<.c$`gw^?''m ԛjHl0"0!057Q5og5eOɨ'O,_:2TpAHupy`p$ix%oW](W~lF0Q6дYK%6~C3Le& q6n(Ւ}]73ȫ΍BiV Nh Xs|7- AeyЦ^;ѧyi\N{9HDFd;9G xk[䛭R|,Sl渢x |;|I2C,ȘP(Ð}bV$ڡrꝄʹ8X5*,Vf67v k8$;S9E a ȏu]]y}Vځц P1$hHIls/CG,!wå3qV5C:K`t m|Ezi Gldo> stream xi#əWE?aak`J#d+=lXGZfӭF#i43]U]ͺXf;y_I&bUb]= L&O/| o/'IxCF,lH9y9z%bpk Ns݁ 㗔لTtn?@X`L*ڀFF}oo1azhhjrlk rmv}j OC܋hO5C΀ |/p:h Qκ~bO,. 嗄Ϯ㗯Ĩ9{: A'V7a"K L 7T9;VtVk^~hh3W^ԍ#gt'p~''t&;32ٜf9OjzO]etN@/(%㌍a9IF \; ?>N珞H>z/µmJyL4]'KxqUA:V2 {bA/l{NfՖYud֜ waS@ Ie?,$SPv]+fɚY燉^aQ%š~a,زS,X V7'>lZN&sj9=o/eHO)Tn @j4p*"A8#=~i엎"0rgcI5SH k.vɖ[2/ݟ%ܢ=/9 Nnů5#{u<* C}f@ىT sq@>p,Rz96CIPc}nHK^~=d%CRdɞ_uŝH0ٴf;p:x/%us "L(YߏwWXuzKf(=O? #?AOwcpDgL8]X [sGX BԌ=݋?O"| eW+)\ُUusnN5{Giڳ-GNu;nVr=0ÐtVƑ8Z:Ns*Yr|T%9I@ƉqT" L?*c%Ĥ^T4Dh&B74џ|ʭ>Piê:Q9w'*SСWW\;j>l ȚJz24(;Û,vβ^QWZ[ˍResea} RSVM|INi?Q$LI J+Yf*`a0 QN-KQt4!%wrҔt)ig(eBJ?1[?&F1cu"3Q|I}yz2r\fpK \ԡxk1l$S)#% tg*b Aoyr3mz ^vtU"2dBnPgÕ[wV[zْZمjOMA?en.EQ`\"ٰPMKzE i[wl @"^qE*).QRq(THVPCo汈p"O8#,v_;:W{A!N(U䪐 Q}:ZW83xD%3x) h n`0ԂL~% 8 0$#s+$?e4@7tbJ*tCW^(U?UwC%*k.v wa,yӸ9b8dÉhs.A!d(<սHD'>|Ot'u>.Fk)2 YbӕtA7jQP:LTw#`V⚇28w@鏣sdrqniR2QByr֜9Aj}F1˦H-" .aN4 9]P!^=U-9ԎڰaBuW5/ ^1 yu%@$%RDDT&aD9Dd" DkL2$E  K:a+"$ꍿnuR#UrP* MiT3}zRwΏ' $ᓯp^z<}fIGGeBc1О???'C^}F5f?~\E"?H<(#a6 |ݗ){3%ܩ;NLP͔}٪?WCqydKD'0zPF|˗5P)2E b'_]!WsU\T  `-%^&T͞n82M'vnb{Jg[=\ 0+<.!`y3e[X+8+dЉPutARPDw%cFn+ڲ;g%P] 6#hk[aeNaj6T0 JFa:Ht2']#=ۅ>'>$h 6Bt!#5#t `kC9,[ὈOIIlJ8TL,ݒ}_񝬣85D(/|.hvmI7y{T6H^ʠQZ#24u"(@`蚍pTNV⚛]vbGď?`?~Pb9zYw[QglJ8W Rr,b\\'4"APplHEE˗;m(<\&_R NtW{B Sܬh\.QF*KX422[1xqMAPF} )̟ -n"HrFC$Qu7ND-ԏ Q2̖qkJVB+εl# PA 0ۈpMc|-@TlU߳i<+d+& s*]UO0u 4';Bizf5'T-g M GBD'ext݄ʡ4vD0Z>OA=?Oixg3^ 5o<*: ʜSZUւՍpm+Rۉv*`Vw"F}v>J2Aۜ6@hPKtW>EY2B:d څcqOQ&BդHFUoƂ/6\u)Q*쌊$z~%RٍS3#5%rx C,=x'k ^#to(u ňQ`e聗˶cG}?VE=v% :цkEfXF~#COg$F A}hr.!odPu/NeD΍/o'( uq .XŸ F2&z B%x!pCu| b8ct‾vrw@8@as7T8T+0^Q<@Ab:204,䑎4 !02 !(S7`;ANzo e ! -?/DHI|9#TB5+ FLQ Tڛwkud¯bW{wK^w{w J*]}v <}I!ܩ;ş~r;d޿۱-웾OIߎp 4 XD _p3btՉE4NP[HW|Uj@OzRUp%HeRB(xF@}c=EH*-RzH T0|C=~LkXBjaDjHh uCT 6C6~L%t L4+FpjcGp>SҲdJJ$%6FBlc^T!5iqbnɣoD@<QIhD.Ļ I@vDu]mxX|oB? <\.ct`$5A~D'`|@ J9:a.op=ӱgUkT ^,aC#t.vܸ0 SgR001dKyܷEebJdи*ԻD+uI @"* [DWn:LTp000b {Ы H ĦWq[^q'Z셊9^AgZ.F6q}_G/01|Ƒ @/؎@+*dTm EZa!m|ij?&UZb+kWNq4_ 4O7Ph# W;&1{_ߌLf7o7QeB_UkZ/Gop~s|?S|?y{?A8t5.1pFM$;It|!NCp&1@C.4kE]E2B @!!vї Jc@8i eԏ^yuܫcq8 +HPyj0)WM DKWt!8:1_qs~j9\q5,Yh4@$}#*3M:.좿tG<.TF_ %^\A<3KP VX͞X1";0O4({1.Ha : @Z*Jh0MtZ諃N<*G/ُv?7~f?5>c3Vq!=wI .iɍ삽(,:eW}_@(McUPN ^H%òO̚W[2 HʀqA^$\P&! 8 W HE*H\4W'.޸22F=M#!EEQmu 1CK,8vn9d'#;6@FA(olNщwẝ.؎#1m7<  P:agZ\|!H秃z+(X`? f/ !gSIۘu8pQ%ܧĪ{1z?U(&K]5 KR0 Nr&܊pUGaŞ_qVbb[>q/W)~hٳ/ax=`GC':>j! y"/}/gNmX۸amƵk7M?0l~;[U1\uNW՝^֒޵Sy ~8"^=Uw:W9Ru'Ǽa{6mk5k+?x%Qef/OQ8l=:}Gޠobܥ'(!_x>~+D_H"n:CN 1B%.pp.fEĔ$y*9EBdB0(ᨩv̉t%rBɜen?Ʒ(Bk⵷^reƞuIxu @YXZOFG6WTféojpB G1PHT15BiW.pUTY㨇YrDV-j gNA;*4ZغGVK*-]-3>j]q8F`*m(7xi!/MxˮԲ *F*6?V%"O XjqSgt?D5ݞ6 P Lӏ4o>^ۂu' ӆ^dY[=1d0[Q@g3ԱM+B~O("lQnK<"õbB%B>C! ehH@>a@?~V Q'`:UD%ږ^zSV2iHH0f!C%+3 ݎ-d5"vxAu : `F}_BcMt w{*]A3} zY &?Ҷ'i}$ߤї{=9捰9FoVV*ctg`kys}ެɛfVG[O:?T!hXh M/RPew[ٜ'M0jKh'q5(оG/ÚXSךh5ѭ͸VZ6:Vwn{JoS<Wqᅷ>{o]+ܹ{״}{ݷ7}{]wo.Stb}@j9]vSn3nLQ?_+XW5QP@4Q0Q|dlrAIp2 #eDDAD1't<6R4Κ )t*DG(](r2oJٶWq <t J$h^ 9{bQ !sb'=է,/tO& jgCXx~ ~ HϩB|bc+?/a ńySc^Q dI(luJ9H^iB2EP**~ȡᝊwx5!+J8r7okd3+PzE6"L\J."Pb_D6TXE(5ZK ţ/D,vy08R`˟2>5aspzu.;uw<7z?uj#'uS}s vlwenjNN'Yo`~ NxTpէuR [779fGwPjF-9 hHs"NI5HQC6ˇ[39}S7'tJÜ9Lด6Kf,OHBFbUNɧt=}JO\E-8k: Z/,3tJQo*% x5p(Ic((qQ03FHk-DC tJ +%XT^Keo>aȏdh1FYXDI? mgG0dIEzCl&ZD E1d$;F& 0EM2!Mw-` Ogw^/ YY}2zW[7;)6\cXוpvnPZҖ]v?Dou(fn@߅#YǟM "(C JlЋ_Sjﺣ;^=k{moZn 7fmr}Ǧ5n5vlW}xյ66{mÕ n[7fX[.w}轷󞱹p-Q(] VBOC@ߙ_t ZVI˜xdbb ~E|}krqB>_7OyUD=IG*?6oXpHҴO 07%oU+pGز˞hZQ$*O:,DfAS**@M+?:Kzv\3' ?W&++0^ _ tp* ~UM6X=Mi m]9Oa``FDaC<RnOzp0X;C[n9S\<B~k(K0I@]=,a& %1T\((#. lΠRIZ\IX*'+EhOя47xޭuS8X/3Pl,%i'Nh).I"\Ff$݉fsFD.DSEjZMJDj+ @%;נ8Tro) b5#5}N9}'SC4NGGxJsBfBtUF409'jVdTԁ\qt/wDG،syUEPxs\K؋dPx&(:sŖl4G8/sLT{Ow }tG7-xXhZyw,AnI'[g ]`^"#<cpt.DδΕ--;w忟Y6P /@9Ju1>p>LÞDsy23p:0)Q`CŘByX(' |iql \*6ةo:K0і*D& V" d+xqHhT{#QpȂ!uC8`P"A8;iTl)8Dž:Be#QlxS31!PEl85~̳Z` EEŶYu*H Dfțb Byӎe-`?,@ @̀G@˶;Iީ<¾ M[xCPg-ß6jQ`DfD1xN3is2iTCrDR8Q =p&;8SsV:QwUS?`cQH+ K&%Nh!iչe0d7Zc4D:h~G%!<3pBZ p˜`((;M  &M MǘZa"gs-`V\T" |>Ȱq( ypQJBq"R"*TZPBFYbP1)*DJ{OF(=>,tBa{A3-d= SL @+oG$" ,DAPa`C9 "p{ F 'YǙq*)q p0N h4o:hl27àzPpC7nmȓOeƞVnW>U* /|{5UW6_+ߨc Ƈ5?t^ux[UGph;ql쾧o=ޣ^m ol8EPA%5Q0GqO,>&ҡE~(xZD1&bV*w\񩫈N'oaԴ +3[Ǎ/V?^1j"0F1;bwAD!@"& D%,~mTz+kʃV}}(6@ *̈́'fZc ŒDv.o۾nBtոԅ?Ekwɮ" 6qńQ`"fA9 Vr8VCM*PG0*mW]š!:x5cN|J(' ,R:a $8V&V)DvcDa nEP;;ӗ:O~5aw(ށm:=? EOΚbbuXoCL̀0miDQ`í*  4#,Gz .w#W&8h4$.Ŕ'5jD#\#/*\0H08A)5m8~ az,FGщ>\Φ{<>@ s\OC5Fv)&n !l(Yr!:48Ah|TS~X212, $cp"i!4IlLj*iEeV7LD%OPCj%b=DD`P)d!2Ra  ]TbA!; Ry"9.yE&(r2QE3iW"?2Y nf$Tt"Qts:,Q@3ZgN睔Sƨ~Yj$whc"we9^wguл\z+@ b D܊`'DP@X=pzZc9#uj=f=f;6p}s aQ7ڤm9@-'J,Cēz)q يrAE%Ztΰ'ooSݶcOuמjcպǫW=Qm~zW~;].b'i;y HQ.XSZNd u,&D+CDe~̳п Бz+>]V\X+XY6SA\wtXA;T!Q]4#3d3>)6?bjQpRcD!i zjX<QQ *MJ)IX!(u|80QCJuUY>V_rF2QT9b/ϙS' OCk6yޯwW|~w[|8?ۗ`N[ȃbіl$(,zXWc*/SY\*K>JUE3tK-yчDQfZ(,Z3t"z?G9t OtQxSN 0F?e M1bm 9bR! c`U" 3hl* UnJ7"?'5y`K5hYF׭@N9etOG_=GAPuW CbJEG`Aj{=񁶰7hC8Q4`vVc_pLiDP81 .P("I%(D֣^P618ދ_;a VvPP&qB,\Jg7D)8T)]9t\W\W* 4,b;R+^6l'P~bx$[0HŎ#اls9D"/>)_.Ži#\QWbxXbX8% PNzDXIF+UY^yHSH;8 C i1]쳮'큏54?l|Hc{pw!v/YcM4 [G2$rJZ ]%^gN0]`3[?y#vb{-R먉p)`A6{*-l%;IèZGӤ s-$q^nc\4('tq pX(VDeRA"[鸚[yh8(hż!QAT0T^F3H*L1DfݘEi'>(,iVPhJS)쫳 zް0L]3=nQprJH 0ǓYf@u `= y1 L!9f~~#xپ .#2R0ln JN+kj I>5X~|쵷gOhm~ɧH@%X$@FhK;|^EŅ%9,<ښ3^yδ{-w#v덽77p`og|&~C~T藁@OyxӮמE=33L_[>s2 TGh_2 sY25.[FQvDnT QOyMKHo L=Iwt.2|A./W/9C nz1V} iX%L!PRD|MDeqy+y$0\OK/:(ypreN"+$ao5\J|l QoFUGQQyn}_5H;dJ,7+ݣ- vvP|BR"Q·>7a7UcI(t_cCjfxQ2J, Ʊu*>a,hnQEo=nOdϛ'N'g]CO::vh#' }c։tpm';|hXa !VOFDYU@hIFX$0}8$()EX#a%CdjϢ0'Kp'{ M4tM EN)bQr*h=%Q‰%PĖ{VXYz",rrqy|jJ@\:)*둠ifr$e uU"RIy:1 qc{pZ‰HQ69Ma+M`g`R֣8ֱ{ Μ6Do+aN¹0Q܋x1i{upÞvd{(D ysxYNXKT%h>N%y4/DAjG b)vrG*}ypC~_;wħo߱ٽ'UR32!(r'7$8m||?ZRp8֩Itj-c]TWKZuy}y4y5 =)mä!mt׃]㝍cM PGSB>i:[ss062u('ќu}~HMe Koc,PPV{DH+R—jèrMŝr"&w`OEYyF;*tsuf}wBW c x#4^IS7oyLeOq cR/JL*Ű˫MKl(RRp91ESٝ2b|[(+fķZQ5(_Ke~SҀ-RZ/,KAR (2߱XrМ$&6.ʾc&zESVcFD4F I:|g5(42, q].r\8mJ7RY=,tarOw (`И,.ؠcD3kf@|6ف Nm(Wm<h4dF̲3H؂JC O 3MɎ s\*V~}MzoX`*"Gp&2mQ,q *ÓK(R%9 ~3epgdqbnLS](W]*%c}q'iy1M1Tsm>FF1Eת(1 v]%%41T<=ŮL, PLuQ`uTD !2ʆ;ANic;b9 ٖrf"{ bK//Y*N}D"]4,5k`dc0/0/4msp?8ec G&c> [tx?w<ݠȮP= ê=He_kTzG_/˻n]}7[]yo|~-$-7?;?xͻo)=}otwo_mWUʖ zOxrhTQp4<Ȯ %'N<5;t8<:gbv9ю[X[Z嶓IR5G T1:2.{0JORҬ"&B,Gx\rTUf.]* ~Sa& C.Ia @ʹIxZP 4)  !N\M^8cVmŎLDޘQk,Ēd%Jv,1N8%N|2qBT8šsqN . =nlk12o km)@ jm醡lHfj=jϱ$X{3=L|u`@=`,D4y]&zgp+d[%JH2z"3>%[0v }&ډU,!bIN:W,,X4mE3OJ2ܤ}4N0őI9LVl*]R4D>{F3BUb'Z0%WD쫉B,$ř`5&z`5WZ,{|zl(9.RsKg3 wyHT)@1 u,F*e͔OX w5#ad874%ApH8rMp@!q_m$Eg{Bgso1 cAh\HalpI 1Ɇsl=eҙ].B7g 0q@ aE)^#\%e^p;?Ai6F/)OKSDY>նGFA _f98h;X1&(X BD-jR`Cƒʙ"9`+WGY (qjFpq48D*iLc*%g*? RօIj0{1/TѓZtO,qi5VdE%x=QtƋcc$ '14]#| ҃/{u9vi~qrۉc'6.=;5׎8qLnIbt.HD*wi]m6sOݝ-s~3;;s̙992ͶiΧQ>|2 XQ݂uE T1hjh2mp{W.VEHv$-n҂ F:;%4yLؕ6ģftHyh (|(\ f`TOG pA |ܡ\~{WHwHK-Q*'o$䀌L&7pg%CeL ":Zsi"<`;=;8Mn#QX1lHnh<4(BDThUf-{23֡QF""'@M_y.Q6,y9(VDcveVMDF] \ c HZ@BEųB9#0@_+$.*9(*k#*٦lâk Ex, t8IՏImm^`΁Yi3*+&nj } 󶑗P;tY8#cA8 mEROHhn,Xe!bcgGC` ^ W3YFe!w4v"nD oN|E_ԐVr6Mh: +h ϵ3k:L4 O 5K@j;o VJBa)W#R|CUt5Jpx2cwoF#*`LtEN P3r V3%*qy-ڟd{#E<)󞻙ΊJӃ2:xpS-AᲠuWۊnEAn=\39KQxM)aqZ.#|""mDx0# CF걳5H! (H4EnPgJ!O3NqcP]/j*ﻁ9d6Vn~EQZf܈22⯐X]Qz5)5gEBˆEMHTSu]}`{}:I$k% ;tBBzy zDBjZ CO]փt3J83AHxa{M5%aB L]5?{^zAOiFSdZz2q!J wQA#)i!Oy'Ni)f]wN;R4m\Դ$ 2@T͘gc?6mxN48*J*d BA%3C%D~X*241~ ܧu(# 3[UUTRr!H}W͊ DO-(6<:L`E(%9(E1B)"n޶2NSτv)ȆO`̀[78h-p ai%t!-ݦf%.ʦ.sҌxPnq D.% G NDCp}^@=Ԋa -h94ngQ O\W #p}m7^ZګH4#MeKH,ȥDD6B2~*"Jh a'v?<%F&OAP,?A;40xO)Q\~+xR)*[FX]!UtÇVI@_ N_ D)g~4C"0D0([Ŷi D.Qt:Oɪw}Y/RHpMe73M4aFO/RNS 3;i*!H'.Ѭw:Lڤ`@|~BQ<+Jɋ Lestk r {c6GTp[BUql& `x#dhpQh0hܶd8$'2*=+ѨkhN%lJe7'Dw΁FDm1rhB>N"#]](\au!xh,80da!A-- z"']#W"@FуW.WT O\r[@<ڃ;5o[ ~00ВˠOZ'OhYLbA vC*cAjg8!aЅyT 0  /j.&OTY0z`5@h`.%9`v؞5<`.;fcԥHqz Cnf3[t1X:Latqtyt:*d|4 gaoz5 g\kG1VԨYr? n(gwsGBC{ ,rE6KUfi/$ ף $GjԻ^~$\98 sϥu5\! o vO276YuV*6"LNJ`%H́a2Bv7rTr(DBB> w aҏ,b5 KV\>c*a܀kVM_D3E8q]x6v|,z\+50l:y/xszSeKktVTp+P_ƀ@@l0@ET<Twcc#a`05zܐȡQsD@@@@@@@P0@ݿC=HӇŧΡmH@@@@@@@P0@*v Q2( (&N1ht9"lC}:;Ay&岗6vDʆB ׯ8q(A&{n6ʛ+M$!<{N|_P],sw@e:L;ZTD/`x5PFѤϠ^TaekG9%D:lje.x0+u :0WodFgo ͒#rt`~ (9[Jt.]6vkוE@@@@ʆ ۮq0k/StV\9_:)mg/waƢ~ JFab39.2Ea%k^ųO|t57 ΉQW\L?p_rhpj~r?a-L@Ȧ(p3rk ̡8wA R|"8[2%#k>J7L, {(l0;ЄYJP!ѩ Wj6*KDMe^Z@UǦ{Ó }¶,?q}LS9Oك21<稌zt 5鄁{f_W=+O S~YV˼z׮q5I&P0@gt8e2Wo4whWm 5zq-n{L< 'lwIk{)"Ip/5^6sq|=R>6VWx}D |Nebœ!xyK]G{\m% päy{RҫcNH!0D kkײGD&{=gwxwWNnJ''\5˵Kc骺8u{d-.S_.*xi^a'O}ٳΝ_Ԧ&?-Y`,ph}@".j~EԁηC6Y?OߗO|Pe\N*ܕ(ٽ*cl  L@rŘ -џM|鼼}q0>soO*7^R:WiiU'1ߒ\VV_Tt +Qo5jrHQ= 1('x3sO)bnZL~QQ^|PT yLZeZ=К3R6}p}(uo^r XiGFv]Yw }@EZWWǻ7Rv'-%`kU<籠× o֪O0j>qy!58}~o«+C+i" zȥ=OQQğo2yNzzEE:|tH}$$k%\o;%{={nXھ9~rGR𛋀 ?oP뺩OXD"UsY))gqC :AyS~ th7ܵk,:syT|unC#$UcccccC#cq`KJ na>zպ04fOLw…tQ!`\c*VQt[h<0v3cN!vOн߱]3Q,ɝZd ͗nlQ`~*H_O-Yw_Frb[" K p_ݳ+G>Y_tYUKo&N'(v&aMz#؎=z ۸DE0")<+V:u ߘ5W9ERHC: .rK:X=ﭲo}jkO_J1E6xɿy T탟م&'ojk-(s ņCe!!! U6[@n!Xu󵯬;4395 ɎܻQ(*F/BQ[JP'Y,_+dx-G4;4#G.]T*c=*Ѻ((7ޟ puXa9X'W3/~sRQId]=󯂙W~iqŏ͋O'|{%u+vau8X&$$?~ {VV0M@EKH_W}m_xcK'Hm9\bFH)MN2733s\ph_n{>|IW.ߎP/~sfKw^~c۶mP_3_~N2G˖Qw.XN']]@@=w ,ΧJvȎjllMd鑆?]>u:2J{bdآuX)m6*BIP+[EjZKB&/|'!jիWGD | K`IXNԴYM҆Gc WjQvbj:0 N_y`ʍ_͸4?|dɟl<:?oΝy;z(gٳp /n jn8&tJ6$׊>,(::RiO[kSD,vرxlq5pX+,VY]3vpiZIB%F7 پ}[YYYwOJ92>K)=o)>bѢׯC-?; S8}ԩRIߊK"eP(Fw #>AszXԚ.* iW06ʏ@ൔ+Jr  Κ`Q~h((\$g[`dddy~٪}D%e97򮶒W'Ri9MXԀ%RtYs-Qq+mH~: gΜ ++`_zH5OIHWϏ4&6Q1'\_oU`I >cK`l;gx~uŃ\uڰE5TVʨ{*Ywǩ(6\Wl{aW%1혺lÊ+kjj***^/yxIݚ5kyv 1~HHH8qD,6(`{ އ$o㎥&#@ɤs@Ua[8yŏ}r n\'Zko\}Z5m*|ËPyNRS[r9H@u{߂LwMz㟧'XAtt˫_;ov]Fj᷇@o7Հ #ŧԬ9)S(JiZcH?(+`, I[?09-[=پmQ;KK*^z2HAߚ [<نY;k _tlǎ4<(s[>xKBҥ j_[6MmjzelS*ڰa=qX)+ZP١ 2433~78<4ZcD`_+XPɉ%uԔ[˥GQRZQx\sȭ1 r+W)}yK=V#Ȧ&K3l=Q)&Iw"+WE2(_(fڵچ#cމDEG|.RaaC ͼ*rތH~cs_~UQغf 2hS9T^24gv3gp :pedCrbĂ>E88*M^uȯoHFs(0.Ov&L뙬,8ҟʟͺYYϸo{h~>+*{泆v5?q)5jE K.ic*HK5kѣGe2o"ϭZtS% z~[LD-mR+* TJk+G[-k[* fX)E`7mHdwpQi]TK4&bĖذ+bCAP& `CTQQX!YvUD]fwQy>;[fc5,;.Rlɸ[4kWZNvRWH\v|<~WWL '%K|ʁ9Gd&{K/91dM\W}qa^* aC+ y`JEۭ3̵ wyJ-qS-'ܫnyHvru{wND.'TQTU5*AP?)X=ٵ޳O:xk:zO׼Ã0csk"FʠE̴ha-l`%s6lhhhއM; ~{6/ |͌~Qsko<罦ۢ_Ti"`Ӈ D\ٸ7ɔ<7t+P]ƻxub_@?a?lun=EhO,sh9atxdLgzhr)jC'VP2{XnmI A}Cّxzm,=D +0:4m%ޑqH֮Zako؄KDv.ۥCӺu{DwTQ@,,<3zOĀqUs?xPgeBeUa~g&WQ3Y`9 *ղPn* MmJ9QxvEQ^^~j_s#MTT@ D}bmzAUZYx,_ϼjznwdXGTsŅs~*hܙY\R2з""By]S.K)xٲe !Ys$rCΝ;ڷSNE9 2{'4/ 3@u0C;3.,11"w>θC3ۿ;3~W3P󽽽z:p%쥼;z6/t.#n]P:{Ÿo EA߿9sfHH[+Wx>xoaO\mN<) HϞ8QNe͟ageov"GdyL?&G 3c_.tVXddDīCڸ(\l9fb++k7qό[탋gC:t tsu{DBO;,Rr Kq!,˫C;lr"k{ ^{uiwfۥ@J\oSrMK:( _Z\0k`* '(t)Bܙ lԿ=TUjkoUA͕5)^ZK6ޫ}Vk~B&[yrG]%?Jo3'V=ߒ/ǎ;wu )_k, {vi+rZZZ(?0 x==Z__?Ŀb)siD@j0iH\%D !2O2 488bغu+@WyĴi\0}{fG`>? I .. 7z=𞹘wBqfLܸ smşQ۷o?t_vnɃϘ1cɒ%o6mj;oR1J mwLՍ-2[!41ux$?C8'[m_]FI۔)B1kw#n$ӎNܔ}65:qjEW^-(( >p/FtbL楾+u1'd bc5\;E(K U]/[*Z++Ss.\2GTk[9DBwHYwD$}j;=:2+mv$p(aM!/ÝLD=iN}IG?$66Vz.kbbbs3Ve}?:',t Jslَ((vE«(Lv-mc+cշ[n(Z,+k+(ۉKc~DsF>r30`ެ0vVgfdd\9;cǞ^Jt ϧ9 S`S{ {4S/N>}hXrrrFB0-//cw' 0xa@YF6k+>|zsegg3?7 > 6 :PpdA5f FQ0sj3(|"[p;pť3 s~1xS~ӻզ˄r>G.;:2οkH[{_~Jޔބɔb ə3<=O=+sr痘ߊ )'@z>&L!3sd)28!! ';vLhD(ٹ}xPȯ\3Ao;NyxDƼ%0)1w̔NKB$kyRv9/tYKӮ>']N_@$}w:}v䞶H@ގPki \оW']|1}Y@Ƀ87\!XtnK]*se /1yfO-~7o{^rbdd 6DFFBXh!(;'g}H9r']~ m=F3vtt4/]J?$ @ s-92 zArB EQ\K4`uV#HyXcgbb nT起p`vvHQXʏ5a]]"';4Fm·+Җzz&wg (; ycKe`8Zif_~~>0A 5CB?4EɃL^ L}R:t(DApD eC5YAQ5p'FH'CQIɅ+.ɦBBYT!؅Av;w]j[ t!(jw|Jsť579(xolS7.ݱ#o =[z>#&*8aG225Gw1!c{ PA$VjxHSu%K,I,(4DsWQ76z|t|sy&/\?qIdYZ)8aFG}sQT A$VChbQ&)E~i34qŧSC.T,;e:3q/\{W_6,^v5S:lZN8P[ _ ?E*D?CLcsB(O)\p>(~'(>wjw*PtO^ AbLOTp &!ÿ`du2/A(,)11JDQХ7:Zxh!D#o7(ss^Є~{@8qg}xBI+)1D̆X#QL]L(ODлꑢTRVt1V1|Li\EP㥳2A@W|K~V-/IkLX})PiŽL?xbȂb&0)1E!TtFQ71jR=$t=]T"nU0|Te~Ig!z#9O3]QVuY [!AQ֧_,cjfie_&35-lA}SnDQSmda:">UtqF)T:aA I%}e2sPչnȒ&1\{^$!)t(Պ)5*AF C-`.RaF:O'BfHKh#GxY9~5 UBu*8>խ:<\5PV'{ jayʨ3I0Yͭ*Pq521DPs *v#q̴yxc[SƟĩg(^K+ LXfDHz=fS4ݺzL3trfPhVy0ϨVQ*۬ԗ[!Dv]iQQX^_.!2GZCHM%S'ٕTxJ]{pAr#\D]Z"T&%N'NQIU3RB#&Yv3]` n;m=:.(kMEEԢ:F3pGޛeV9ԧc9&Yz %t!ou{Q)T #'= cr Q@u{^ʻЌyaF"gmX$+}zSqՍ}d_iLn5&ة5,O4aFv;3XwG"6kBr'aOy(diŲڦ䍭hNٙiq! E?EɦfJO ΆZ^Mxpp#jH UH]tix EH/55Si56՜3G(nm5l됈{>I=J P/IUp(:VW})* C:9( gڐ0G0ŀ"(4DV\RT߬͊;1]߰Me.mJOi=3pJ9YNv,!qHz.U^R{9dZ)󭥙bEFfGGm8q9-=m/;m&m{Y9@|E?LCCCCCCC1QE!.7eDE&QfkږM;DľؖYWdobuuGNܹa٪VX-yfq *Y3 _Q/E]&.kEXYC˭fg=43:k7(KK{?E~]O%K"$UÏ/rx~?`M6wb2YzJ(Գ[^:g@wN .qE]pMTQ4Њ zBLQNx-:!"]D w"88m ʈLZcX1.7H݋YR=ʵau_t2KACC3Z[[8c (iERQҧ(,RcHgL}fZ(5!Of:Ht1^]{gGF2%'ͬ‹՚+O[%n[aG?**1*EQBRQϷ65o }=i:| Xvtc>B'Ó{p$wfQu4}aokjPWnwXdEL{\.R7u?NL8"}mKd"8X,+XbrrS:E0ߪ4n1|1nd]BsiXV$_Ʈ'Pa kkImu)ևgΚ:NoMGʥU7EEZ=Y#}䱃J_4\?'֡[xZʗuV˱V/έ""G(*1O.=}| "ccFwdi{˝_z 2IdrC+_⟥ iJ+oe?׷OU閠9Ћ |sm/ ˆ[߇x 2& ytqËnڧٍapzWl#5NwѦ'29udYJ9vz&@WQZjf~2s!_tx*~u++ >G?: ) (\hhOQj5..뱱^vܳ& ؝p㺏OAFOYɯJE(*ek1FJBAQLUP2awoS~zw39ӵO97wBh0AEŦu[KzdjuYݍ֩ڳy`ͤ4rn@N{2oG QQgP+Ki rOzJw~DnVwrUZ*s݄n#lݖc\OOh+2qwBE]}BU*ܹ@#Ia0 TYz؅z,{M_6ptR7>ro//_dBUTEWnZgW&v=<Ls{1$z]ϛzĭ"rܪ}+r_[fȉrYZ-W[[7q/dr9h& @G;Yɒ:ɨKEqPm*'T ("IQ Y2f (TOܦcY:E~s>%'_#vf*W=yfiY?(AEeƝ fYUWR,ldjQ w9ZjjX]9 ,뢒vfjO6YG;o#خUO[nt9q#uS*j(f;zFg#Nn8D׳:ɨLs,EQ\X0}AQO|,{^<WR* aL<d%xZ3{\>[>WڟOsvwBd ?g)/BQ;b=o"X3Z7nnK䃻VяڭBA(nQw[(M7DD/6Џ8߽u_Bvl*&3(Pu"m׈"dOz7.A̠fxOv 2mBzvBPQ T/4V:@C>&> [M 'ejEQ-AQ%F[<|3YI#>bu[?Ni;:vNߞ>k_Pů8ScP~AioRv?p}{vVWWr)=* *?+[{ӣ(*d57jLgA'>u zuâd3q.Tu7_u"g'A3نK2˃Ϣ;Ka\EDTԉ|DEQ;xy>}\@EAEf&(eUnʥcf \i @czh+pI-rkOtqE72nQX{M{r5ۃ@ؠ@CC3l5(@N޼1I4{p|3U{d-Gw+|2ZW ۰~}ffi TThhhmb܌۴(nU٭;-mK#ܓLdgЩ:r}Kl];so$5lInp"ŋuuu=WQ4oyaI{3Xa߱xPF }=eNLd:Bd*$Sٻ&s_9Mos>isNӦmsӓi%! Ylv$[ l 06`6x_X#ɲ$˛7i<H7cy#A[j p!UNՀ>:]p *u\u3lP\]v"JN% )8rEv{Ϻ9sGc+g y#P !OP@'* ]nT5SˁB NH$ )8("DXB NH$ )8(r"VxOLK' )8(ߛ|۶J/3-\_dr`ŚԤ|*|f Dv4.nT5WQ9A  (P9!"(iQtz}C (E m^SڽVk_WbMpmw濽eܜH2 |o~!uh! '{eQYC'G<, =NqVRp{@ (s{@ ($ (l=]Jaw^r(E^?,wCڕ{Oo8w{ͱVM5toyoK_ +3$\?6h-VQ-0%& B?GC Xg (P9A P9A0j03`])'$ (EI^^^چ ,={֔)ShM);^Ri  wN|wG x#B Qx񥞏lE| (P9(  8'q"(uf&[/xE!'AzDOŋsrr眯G߸k5~877^C(˃@Q]1xv#|xW6wN18Td 8'H@! 8'H@!u@! 1QgJ/U!QP(&D* XQ/'H@! 8'pN (bϙݧ(PQCE P(|Gds (PĖ!DqtRjBjQDjORp{@ ((P9A E!EDB N6Z劃( ԜP9=s{@R`>Ern" g=Hš1F (H@ 8'/=>Qx8a"y>; " EDP/'H@!N`( Ű (Bbim]**$ DsNQCE!'pN`(( PHPD(hQ!Q0k 7 " R*$ EP9!"(EG4*:=#s{@CDAJ/'H@!u@ (P9=Eqlٲ w:1]SQQ`((Hš s{@ ((P9A !EEgᢐ@Qf" R܊(e@BjN`(P9=sBEQ+3J;Ƽ;ƋE!'h?vvvg" R ) P儬DA P9W{b)F#[ȁAD$:s{@ (PH (Ζg-;_ёs#.+Q*];=|БÇaoZgoNS>۟]^]( f!xEDq=шKpKLpN`(P9Ѐ $Pt@\xz-k?WqBA=!mvORp">($L&ȠxS[^IHʧd={* Ntf4,/GkD0=%8{ءyj:ȢDiM1jTOG 9A )8=sBE9DQE⌶  :B NEm>;w… /^);ϫw֪o??nw,K9KW^DXBy(A$rC-&(AQH Pr{@焌DsԍS-l B(kxIIIzzyf̘1k͎9p+gi7eg׏c…A((gmZN6`Ww_L7QH Pȇ 8'H@HAEa؛sko-T~5n??,_"Ű (PH PH )ة)um}?"Q/$^fh=pE!ܜXQH P"NBArŸivXO6tnZ BD)nI* )8=sB 8'H@bvv\Y+>cԶߚ2&(DP(e@ YbXpN`(Ph@D$Aߝ{KsCsaֵGf^lz3q; ( )8ۀT cpN$ 8'PbFJgcW%;_}IaE[NQC% )8A  8'pNBA^N"aB$; wk\8qFLvD((HšB N`(Ph@ $(*;*G.*wbէywx " Rq((e@BjNB N`(ǡU (D E퓨W,K>zQy>=^|L&ZD$ E  8'"шbBCwMj(Xi](Q((p:`+W]$ӏelB;PADA[1P9Ѐ  8'H@!]@!&q=S~PA}zs Lذ#-gg~g&ek7[ڛhQ^iDس*(Hq " pN`((e@ P[S=.m=y`A4*LO " )8!]@!& !QH?PLLB8QVlEAP9A pN(1ֶY Q\wBE큂fuߣP H  "Q4*{usZhzNg)=1Iż3|BB N`(Ph@ P(('D1&qVK#WLk6abP\@\ *hQPVWZ]6Z6p3)5fT EKqD?qXD!'pNB>;pN"2Q b- ԙ37d^C]9%&( 8'NNbG'wWVPTZW7,)+^ΞǓ{>,(mg6>y;,P (E^:-˅}v쥺u.uf.}dէn&( Lv^HГg327مhZìI8!PAg}b (E5b" )8=sB 8'pNBꀢWbP}Zێ-  aш/' XkuQ\EqBŮNݿQ[qezQo,nBDg(nI_^$eF Ű (P9=1 FGnegN1.v9i;0(D| AQ,^}wW.^˹RwRuju}3uu!E]q6 rm`F!u$ E  8'd%8!&36w\g)6_oeԓ8{1;,O@!(ww.jG^v[%;?Z)nC]ϩ A8sIQQ.9Qm0]P9Ѐ  8'H@!N@D1i;ul.aqEBPٍ;}w/jj5$}BBBRRڵk8= E쥕~ӜAw.xB j Rb%8{])(6B N`( |w`( E(g/n47 Wf"$ 8'egȘbZ-At'VO8QZZj^g(ffi\  (P(.sQ (D1yλ־M‡=D1uRvX9k׮MNNN (6`JLpH1R/(P9A  8'"Dg/k66;{75Ev@/ъX.WE!'pNB>;pNB"bD_Jw E""F[\Q/'d%aP9=s{@!5'@YO4* ((Hš" (w@ (P9!+QDɉhx"8+ )8=sB 8'pNB>L(D(D  " Rq(IE!'pNB>;pN`((8Re+rT (P(.sQ(# DPs{@ (s{@ ((U@L6ĉAي"  KRp{@ (s{@ ((s"(*ڑ(^NQOaŰ (LpNBA 9OQFpN (EX/zYE $PP@焬DCNGx EAQpE P| Pȇ1o[E )8!Q@p8YR}Hۧ  8'd% 'E!'(HIQRQUQJ9ADTV@ADA*EDA*PRp{@ (("'\Q9!+ lh>WbWD*(H@ 9!(Z-DLE)Vg*h"ٝ]ݎ(mI i%6:бBY 8'H@A B>W'n:Nu]ډ=;-]1vTo;Hõѱěe[;?{7zGޤ7~V+7_}`4PDʪD!'pNB>7KEq(Ea9mv&]u{*9c\+L1mvꌔr$h@ɭZR-P-hR%,tuvvPD*V$ E& d! )8Z]nO&ɟ-kѳ>Yul (W;0øDwߚ4̭%'?ry?"6CQ(" (rRBO6`{VDm sG4Y-kazAƐm1e[w޹Vm[^^XxSo֭_l"PV1 8'H@!u@EPQ{* 8'dPEpQ]T5O5f͝3y凓vZxhl7P>7dNP Udu #FѱĝbZ>Xpf_sݝݏͿ?oS~4}CNNulEa6kԜ#J^1&幯QfQFo[ *D!'pN`(Ph@P]eH12`=5W>3^כ#}ktZܦmzftZ(F]%h#bnDѬ-y/s^:ѫZШZبJUMgoNHLQ~,w!s+Ԡx6)B PH͉8DaEBA ':4vJ!W^Dޮ'Gnө_ެ W6u9[.1Z'z~U"k6K:+tK)FקB7[_RWGߡvW5rұcN 8CD4L'7+ў˪$^Nb"vk"g@E|ڭ۷\mמ87X^{*Cٳ6o)]n0ym:[uf͞r(J&Q5*uIɅ/_-.A5Qcg75Q=ZCwgT( ;+\0kfʋ.X))N:ejzVp ) }2*GC`4xG{JMhGW-p6΢nG7XLCBA^okkCnh͛7#K,_<%%ei3fU2ym8;([]qՉS7-D_Bf@QlH+yhiiYz5ӧ[[[֬Y6mڴ  }=pMʼk2͊(r$p"(* (6W}n7vP3^jg*k:Kܑ֙ 2qQW!-6(✕^QM&z ڽ{ʕ+322b3RD^;aP9=sBqEjmBEq+Q91EVcwmu]}82;!GIb_' TMMMla4^ G^/'-JOUİ/aP9=sBV'yƊPDԢLSoqgDAz85:бS*(r$Q} BE4PJ@EyCwi M-6wn;MVbK1(Ubs{@ pN (B}K|D72[T:O܌AguMV\K1(UыbXpN`( E(Q8 *XQKRpBnaGFh>G4zsMGLPȇ& )8ADAJGth{`HKYF5zc@n$ E"&( EnBYZ_4ήnG6bo \ϸx 8'pN(4s"ޢ0:(D+AQlؑz͖g~gu#g>%3ED(N`Z3M e nH#sq ԜP9!+QHP0I- )8[Q bEOw{DMDa9?G?i×zϹGgZu.Ȁv;uF24"  ("DX(-- .EĀ"AWEMb x/.zĥ|*˿NU_/7ّm9u24 8'pN(4s{@QP0I' ) ټ~{7@F9Q.(lNcoI_}ɋ?gO=u_Oۺaeym9; TO[limZ2s{@ (C@!&OoOuuy+?Yh:Z1QWl-$}{ygˡwϤ,\' r0mR_l+yTy2~Uiƌ7&+;f@95;$hbƪMuCI=nT^w^ŤIdPZ1P]<\6zE!'H@B>4&N"(>:myCQi}֚zӃf͚(GeRSpNy顷g(&`OFܷN0w gf!O&cG>)UT?~gMK>צ3yMu9.S *f;ٟv ZMܔgv1B*B N`( |w@D(PŠ #]vֲ݌()P$9+dE!W͜Q`zl(N4yEWOl<',<~ U[c,FyGkSUO{%{g[%ܬRvj&T \QlW%zk(e@ PDP@NtZ \-6 .)Ϫ[{g+ O:_fBV3 ZnȽb޵'oW]Hƪ߸'~\W8G_ܱuMFk٪.̞)IGVҷ5Qi7 ;*KW˽KP3oSգU_8tdJQl )f2KBQ5ouo]W꽑E (P9!+QHPE5QHKҲ7xp'-?o`]III7 w3g|Ćq'} gu*A&`*X15o'<kwSz+[~Jo) `>ڽFH/j*CӴg;4CM C Ѡ/wHx3[QH P"NDP@DQ 1Q,^}WյQg+y1\6̥;' j% | f2@U`WY "XDaDS"AUu/|_/fNA/ɲ-:fp`wZ-:ff\8 SM/7x~4/ެZ˹Vئ |/ X1~C؎K$e% )8=sBҀ -ޒ/'E̻VwZ݃&mokx%UӺƒ0E-. aA諁 ÷#^\QX.MI?V LVX֫[:j'Oz+UK_V͌ll=nvLsZ;w>#,;o\3^ʻ֑BB+Tx:`ŀw5K$-bXpN`( E,DAws"()]}xIl(Nzϴ\w7lFӜ{{ ~'įXcG~$`##Cc]Mo]vLhң)3uVjk-}ͪGo}Sz:bSkAu%:*{jj4-IEicƭ\waCNlUEEN6EɨS0QA ,( ,(‰ENQ\MFqBMddN< )((\myd]_p~kCxϚc XPZH{[N(0LQU_ g['WFg{!)uEe{` `AmAv(F' 8'( (˽T;u+7~sɐ“'S&?kc D ,(LTP &W`XP(0GQ ,(Y^ۣ[ cxpDaDa XPP*(ˆ{[Z^DA( ^XPeC(0EA)vxEA,WWGa]{wZсE=;)|g( `^P9 (.iXpNPPE.{d^}\hy OpQQ.o=&(s%f  ڜ`^P9V$ ŀW/y衢|ڹ7_qɏ8v*//_MAA^466FJ Q\XPe+Q'~QP\0QA(뵩W?־oRŠmԘOp̑>e˖WWW]#\  8' QE>jठɓ')s\>9M=&5㡭9A!ؠ [4x0*;tN#y~s***5jԮ]f͚UVm߾=//խ$h~F&~GU|F(hpyAwD${jQԂV=hpvA- ^w=5ƍWXXh2SΪ=&v,9MrsGsCE!Q6("##C+uzjE?USS7YaF {+L<c(` ,(h{‡KDA@Q\]J=濽W O.'=5ӧO'?fQ٩E+GQG鬬$ ?~#|v={ƍ'xEAN9O<1kР;XaNwΝ + nW8 HJ+!\j?%Ϩ,x"dP>irȑ>0 'pN`AAsjA% 'řDo(rrr (//9r#wǛܿ{s K&&&SKpuKnW%kA RI !WHtlw˘ѱPx+e?&Wcc#6D5Vnu3z睵fu:ΝK6.ۏ"0r$U{iCQ-kUQ mN0/(b`Q& PEff&y^x ?[ٱ&NԻwo/I|:U?I mF.Z.v[#yﶒ7e/5 o163|/ȸ=ztzj]]ȳZ'Y￟ 3f Uq#,mH2Fo]ro[@6B}>U!wLfYJf,("UQsBME~d"_&yϛ7Xbܸq:t(|b(:6:7Qj{'/Uv_]58ڟL&LX{=E^NLZG<\=Fyf=~E)+B~㢣 œtDs8syApyA78jyDFP29(  5Qٳ-[F|d?~رcܫW3g7|(,8ƠtGra_f/UPs8NO&R%̂ 7{yo߾'O޲eKuu_BDa@H#[s]j%,"Q \'hT48˂BMd'?%KL8q3fLbbo/6lҥb8h|opw7K}Xuy1AEw99d#;sCW=B^«2ێQr\)),,3gΔ)SVXA jy(N )đf@L!}S *'IB6;i1E\pN`AB[}:{왐пYf U}zZx'r-U>SH!G580U#<}[r)aT_/Аҥ[IEEEFڵkWUU׬Yjժ۷7(c\GrNBG͸*%EzG{ yް/\9/Y.ߙK(?}7nܸQه(~c^t6}B7vIP!{XQpYݒ+يjJ#V-Q0IU:҂\rl~WGF)E ڜׂ"({DQՋ +mEA QB?pHy'ݯIIIőAv麃w rU4sM9 ~$𛃎S*>/JȞw{ QhllLIIM/dA{q䧆L}'ΝK6@G9#UHF]ȅ\JICh4fHG~R# N`AN+(EQNDQu# dJ 5Q]Mo}^HJ>Bbg]5 ӧONNNmmZUْ*vJK~v }mQ(=d%yÿTu(> o!ڢp{QA61GNL-;s>x'Jїo޽{Ϙ1#/o??>|zqƕGZוÉM_48s¤ 8'Š}' OAI 5Q̝tN˕s=staؚ\qK֛j (Q.q^n(Զ ?YL' wlnn& J̈لwC?ݣGQFm޼n(:EڹBIu@Px{q3I@qYP9s+Q+riGQODqUCpN0/(dQԉ-__+_KSA-=_k5_E/=[PP"Uw&ANQȺh5;۠Reϫ,H& 8N߷oɓ'oٲZ/I#*t÷aUn"EOz(τn< QpN`A p@Q Qutgoؽ|y~tCR_|g@_z>32+'a?=[`:?rrȃ5Cza!yލA`ю[B7KՐY[$---dSXX8gΜ)SXL ;N l gwKKI~$n7V>}q?MKkS~1cDDn>']P9sB_A-=ߕW慎(L]Pvkפ"wn4iԻIo78ᓹs#% JJJl6|pؙAQtDtQP=HqYP9͉PP% eA& 2755"oG;yf%znE'G3cQ@ࢀs ,(tp"6E8Q\A=3^P"ʠ(:spDah'pNsyAD[CDq! Q' )(PÃ#  8'pNp% SaEANRQ4' C8QEE|pNYPh#E1<4F\'pNsyAD(.AVFqE1<( +Q ,(wDq ((E( L)NXPzGg+(Š2p˅a.](^& 0iA XP((x+(E1sɶ-Y۫wT>j?p |=_y.((W܂ED7E6' XPa('EA1+(E15eC-kKjYfCi]gNaE^%uޯ_+V)+fHD-$.\( ,(LTP9OpN`AQ QJN EApQL3;k7n][vyXm\Ϯz5w\.P\ 1E%UoIduk𮩖|G7|oZIIId?5~E'' XPPD,EsA(i Ը?;\pѓ+dl=yɠ}obff&5 j{f>gfN`d(/Q ,(hpyAwPwՃB0DpN0)(EA6矗KlC?H^8hРQF͞=l4 ?3SQ`AAXPsB(BZhc# ' -[?bԩ/-))!#Ldomm؂OLQQ48a҂  8']P9sB( \࿠P"2(%oU2fAH5(UnȽ0& =QW˂  ڜ`^P97Q*(DeHaiÂ*'0QAWB(- 0@Q`bJৠsyA ,(D,(L* 9 pQw0/(EXNY &a+ 3r pN`AzDlQ DDNp" @Q`x DpN`Az ,(hpN0/(`. s( L b(hp+QeA mN0/(`[P  & + ,(tp pNp% ,(؊'E/8 QSP9syApyA,ә N`Az \'pNP \ 9 8' ᢀsyAq:8( h `^P9 ,("-('P& 8'gyA 8'pN((y &^48OpN`Aa mN0/(`^PIDl90( ,(LTP9(`+ YA Q `^P9?`^P9sQĬpl޼y7yyydvmiiQ1#\48? 8'pNp% `^P9AIf/(ظqE'RSS222TܬxcF؈ŒDXPtgQĒ@QlKWlذak׮%\kk( 4!*'pN`AAsyAEEAO/^d 23##ihhEF* 8'gyA pN0/(Q (\.yG-[̙6b…[n%Ӿ.rQ\eiC&?RG(hpB(D ڜ"JNRl9C---d4_>33sŊK.MMMMOO߲e `[[[(>M6UK#M@XP ,(EDBQiii ,X|*oșB,[DQl̷ܸ-#Q`AA 8' 8'b\Pp( &(!+!$ſ gɦa˖-Qv3ӆzC. Cצ4pa VfVc\DQXP DA 8''-(EAg\RҥKӗ,YBɹ^6| (|!Z^Dsy@~BOf&*(3ŪUĎBŋEQ_(:Bvg߽ȥ_`f` 6XPP ,(hpN0/(༠(LQPD$ ؼy3ɵ J ¯D%wpJ0#'pN0/(`^P9a҂ &Pʕ+  J(BW=Dzg(hpB(D ڜ_mQD&Xzu@6iiiD!ݝ2@ mQ%{f ]4Q3{kc8 [QSP9s ,(tpIApaE<\syA!!?$7mڔIJ#''gݺuv]{ ( L Pf  8'LZP9s"(`pNp" [Id#[mذ}̯74( 4Q9(0z D74pN0 N+(Jp{QPWW'd.#0#'pN`AE\D䄹DAڢ2( 4aEN0/(vA DaЏ0#' &-(`^P9Aؽ{ᢀsЏ(hpB(D ڜ''n~b/ ~ 8'pN`ANqAa(LTPg{÷ ( 40#'pN0/(`^P9a҂  WE5Q9(0z DEA)(hiq[qOU_*3{d=qAIQi9s ,(tp ݒp. mV{}WKgɷHNU^=:oѧzKqq1A( 4 DA 8'pNsyAI Ea­$ ͵sg %ۅ C}Ssƌd?&#MD' XP(Q9gAV'EN=+dfV\Y|yŧV$n{}ѕ%iEf 1a叉H#? 8'0QAAXPsQD[I5;jjJOAWs=Ev5Sn=z4ySQ/ 9c$wX%`yPQa̘؈ XP`AQD (6m&_ȉ+-.kЉ I'}ofoPYyeƌ!Cq(L(\!A'(l =9lЗQXP pN0/(`^P9cQp[PDfͷUU©S#_=. []0)v1cɘ?(|bmqXQ0ߠ3&TpNp% ,(̲s+QeA焉DD (֮w‰cDŽK+_R0(fc𲲳 5C~71D] cͼŅo$ۙݱ|GQHPWI+OrㄜGDomn-%'(tD( XP`AXP(rOQQ>||}DG |#ԭغ[oIUUW#Fݻwjj*)[Wظ$x W=׊h\埞'"†<x7~( Np% `^P9s¤ 8'pN0[I\@87̛qrUƍ>|R>}ON~MMMT%̀YPEЍ|w\5c/}-9G3lS?9gζk I>|Ysssϋ̟j)+'ٿ/D`i!tϊD_ngDHv̔}! ?* </N`AA 8'gyA͉[أ99yƥgDdӆD ګ-'0QAW˂  [SN۶m#X|9H9s ,(tp G48a(*8q566E( 8'E\pN0/(0iA EaA[Hc(48s ~;yA Q.(`^P9 ~8=QEA? 8'pN`Az DAn&V + ~8 N0/(DaEAL$ DD RE% C;ڢ0#'pN0/(vAlEA4D᪷7}<_DcxڸcG#LLg(JqYP9s ~;pNDZP. 8SAB4˜C:C]}pV@Q`1Df&*(E?Dn(^S[(|2 w^}?c7pۜYdt:OH&  8'0QA'ZP+ MA, .B~ʅQݏU֋{ˏWBkJ?sjkk?PiT9s ~;pN.(El EQOsqFpWo,v#@ꫯ"t%_oW<\A >*lc(N`AA 8'gyA%QPE ' C<8KB|>*cdɲw[D*+2e_7'<\^KJJ" 7O@"Œ`^P9s  8'x.(b# 5Qfdd|#!g?Ʌ*BSS[[ 'Pq#FDaFN`Aa D^QQ# mQ9syApyAD<EۂEA*'pN0/(J48sUA(ۂEAXPs ,(tp(hpRA  N0/(vA((L' 'P" ~8syA 8'pN' s( L BIpN`Aa mN0/(`^P9A$ 8'8)(P$()(D\ Sw p'G-'r3ŗHCC&*(`^P9?`^P9Ů]  5Q-,szpEF[XPP \'pN0/(vyPNSMӔf( $XPs ,(tp(hp"(Ȥ1H3>PNS'pN`AAsyA_[7'4DAB@abb\upA(sr9<_\v}aڎ9vIT%NbҕT9dIHE\:ˢIĽ^"q_ ^ A$3;;;׽|JZs4fyz@Z40' qAㄥ qAㄍXWP D>|# g[D )(pHP8!.(t-( $ ' QuٳyKH I2ޥLEk 'F8N 0Q#(I# Eq9^{C.l PwRE|8pd)98AAaq"NXD8N찠 J)++<}{cy|vf,Sɋ;Elˌ`% 8!.(p-(p8NPPqX҅DQ\TGGK?>tX[o o $)`֣Ю6QT"S*M( qAㄸqB\P8aqB\P8!.(p' EQKօ  'p3PI8NPPX$(pqBN줠0(KtQ8F˜9 qAEؾ1ЁD͐(`<Ѝ qAㄸqRAㄸq^D1`6Q$ f3DAAa|q(hIAㄸD1PQ#(pD@3'Zq"qBPP(QD' l0(+s8(&|DAAa|qRAㄸqB\P8!N A8NPPX$(pqBNH D_uG ;& '9pXA(tD>h|:k*+p.Ùo&e8spf4i8SphZ  qAㄥ qAㄸqpAaQhZq)ЁBNh" 8aQPP2!.(p0(ZRP8!.(@GZqB\P8AAaN '((((r4Q8AAa|qB\P8aQ qAㄸqRAㄸq (ʺFHP8AAAA'w '"‰"N '((t ' 8AA'E(8!.(p8NPP8N '((((r>AQl@:p"Q8AAaqB\P 8!.(pTP8!.(p8NhV9 qAF- % MDAA'q"NPP#( $ '((((rq(Ё qAㄥ qAㄸq(A!B6E 8!.(p0gC\P8[PE9pB\P8AA[P8!.(pHP Xv(l qAㄸqB\P8aqB\P8!.(p0gbg B7NPP qA9lj9 qAEHP8aQqB\P8(J廥"8N '(( qAE0SP D?YBEk- % K qAㄱ"~(M6ℸq 8!.(p0gC\P8Qh@e(" 8!.(p-(p8NPPX$( EN D7W˹FЁ K qA9lj;7AEq"Q8AAaqB\P 8!.(p0gC\P8!"(^vvS+Q#(p8NPPPP  E3}M98!.(p8N ',8N ' (&WTl\^(((l8NE-)(p8NPP3!.(pBPdR(&V&W{F8NPPPP w ' QtQP}/mDQD' 98AAaq!Sw:'\Z_,( 8!.(p0gC\P8AAa|q%F5nAㄸq qA'((tqœqAㄸ8qDC]SPqsb^,Q#(p8NPPPP  I(S4& spBN ',8N ' nQ9–qAQDђ qA9 B#TxbM6ℸq"NPPX$(pȁZDnzP1q"AN)fVЁ s; `DMB'((p8NE-)(p8N 8!.(p8N 'ĉ8NPPPP F-;&(%V!8N ',8N 'qbIXQ:pB\P8AAa|qœqA=%(TQ)qB\P8AAa0'((,8NPPPP qAQ;DqF+AㄸqB\P8AAa|qlj|DE B7NPP qA9 ݂ qAEN4$R(nofH8AAaq"Q8AAaqB\P qAㄸqB\P8QQx( qAEHP8aQPP2!"()hIAㄸqœqA98!.(p(PP@D1rӇfFqB\P8AAa|qB\P8aQ qAㄸqXAa Q8!.(pHP '((((r@p#[>T4pSPh qA9 ݂ qA@C% 8AA'w '((t ' NK8AAaq"Q8AAaqB\P 8!.(pBnDaN ' '" [;8i-QqB\P8AAa|q8NPPh:FHP8AAAA'F8N ' (D8N '((,E 8!.(pDZqB\P8AAa|qBqB\P8AAa(( 'w ' ' sEHP8(pHP8!.(t8N98!.(p8NPP8N '((((rEx8G-)(p8N 8!.(p8NPP E8AAaq(eC\P8aQqB\P83B(p8N '(( qA9pB\P8a)QqB\P8AAa|qBqB\P8AAabxЁ '((((rqRAㄸqB\P8ab)BNPPX$(pG8NPPX$(pqBN '/(D% ݂ qAEHPDDTD qA' qAㄥ qAㄸq5E6Q NHP8aQPP2!.(p0(ZRP8!.(pyAѐ(TH 'q"NPPX$(pM Dqcmg% qAQD' E6Qn*(tE 8!.(p0gC\P8a(tqBqB\P8AAㄸЍ:pB\P8Q1hIAㄸqBqB\P8AAAA'((,NdE& '((,8N 8AA' 'ljDQ^\ljbX,+(G;1vc,(aaT҈g.QN# bX,b]S.Qt$1 0 cn"D=֭bΩG(aa2R')(RP1G`aN"Q"Q0 0 L?+](D1^% Raǣb!.Ecrt 0 @yJjoVߒn0 0v!dljK~,/nA'xG9R'z>Ep+@%iGUk$n6o#џEU_+9uߑ˟ڷe4= 4DzPP-@4@4E[Ž y2ޟT_߷'>d}w -j}#EtkRH}DӬ mVe0LQ1<~mYJŇeE#w}Z{^QP%Z_'oVpCPma'" n+[[OY[ƻVm>EU?l2-:NZ-?ܵf-xd) 08vui}I?Uuˮz g,GP9ݾB 'P DTI)F}p 28=Π-Ƃ2 Wv^*P=/wUw{M~sm2YvE^Q]>kf;@\~nUڇxKjy[okiXJ<`c AhA.jh&} M$fLRNAaӇti֓JRxq|3 .O! ҟPqhW e%wo?FsilR%vWJ%GBNHnє?7TQ?_IhMEYóWC}{bzo=g5}" 1w`&EQ?| i=zRjwqJuރ 6-k)H9ɫ'uiM`cIyZQup'9sYƿy"SՎ&% i鎍ôN] ØsSܻ7V܈(ŽE^қf摥^_ O@7 ܈(ZUIƝHny:Q&R1Rۋ#BDѨ38³WIm9lx&Q_a1 cl>3?>>xԯ32ɷU11_$=W/3)~޿Ām?z}FpQ=V;bf=Rw؟Qz<^MhX&ui}_%[*2Co1ff@v=/iC%p)f:{Tsѱ$(2~Q$z$wI"o(xTW?L;Z} ̨z1cX1N=Ey#モN~k.?5:/fECkUd?m_wKjadh`-Oxü73#=аKFH}}A{Z®>*r&~b/Q$C&9g?|+;zO`f ta#oWuw֯ta#s?!_ {aa07.b_<~q,z5ʃ;1 0 cG+G?ܭc춪c'G'?\~1ھ7|G__7}[]C_RWꏟnu>o%nu՞_:?˗{UuMx9~\yuja}֍5Vg2j%f"aJuWqYoe\Y//;qyIfnYW ufr}XZ:Y)ˬ5*}<ח'8Hl͆[2jѩ\ecfamÕk.ߺ8x~zaxؕӣGTͻ|V_9=veȩǛk@%U# 42ʃ׀SsN]lJ\lyUꈆT]rf⪪׼:7iSk^gz9W3xyzs1wxfo{߭Z~T?hUW:.>j׺'WUhFNNenIN]JvU:b_Rlc֩eSB枩ٍfi_e]5fJfzf>wz~f/XN:VV{ܑR+Ș̨sj2䫥_KxO#O68g&֙:*^ych^sJ5#^=J_gp'B-ٺijY|o@㇜zpjS>jJϼ>pϷ{sy/{NWxu9UoQGGy7>u O]iqJp*tFjEUzG$P:Rzکi#Y5WS]ƽ_kU7]Ndp)+:Rn:˨k{(ԕO]5ܹ~n|5ӕܛ6}YzOtWIc-cf:5RsbXcw"aﳻAo^cfCuaKNxwpED[ZAKwDzQ<E)D‰t<8V&ֳ⢅+qb%Zu,)cD*vw~#9+?Y%8Q۱OzT劷\ SL#\> stream xX_o67Gh!;N.Z,>hkQ#[bɖ6֦#~wѓUKoJrr29->%דc6.yZ.b @X;qj؆ up6#*$ͧ0ra! #dǛmt2fTt'Myz!cM`4qט 9LaxOaXPyh#J|c*V`(ͨCm3F"F7:Hm[=^qY6!¨;6_X֔zYF ur4 +;В (u*145ẗAH/ p_jE0('#mt_ ="T@oX_ _.-h8Naʹll]oScJ e?مԴC2@o.-P&E!eRH$CNdĸ~DQ-2YZ2qn@qSќA_* pH۰Rcb˝7iwњd_97&<@zDk5tA;LSTcur5Vkfw'Ks|]}؜ksm׋TkWGW^cvK J6<.H/w51EY)_uyuo<E3YA>ד|a4_ ˣiX=Xo9ۊ0ArM;|"OoWrRuv] ו}sV:*,Rk8 Bz0z%b)H c} /a؁-q+~ZGGJщ +qaTe``օ`[V7AXKŢry# w<\P;qI$)PX D+>˚':O"n, dv=? :!>;,b z0M8\b܆׎`#hml&'Ȳeo ڊ3E#=s쏃>c CW^u;R2j޶;Z=ߣ'5دGJ5͘Z jT3Kjn4kBW$ sd+}zqWmn]+^5KжrwOUg_HEմ&Yv]v^kȟW7 AԜ ^נ9Ig">$@\Pt(99ӼZ8 y* nYp^blp끃W5JR4( Eᥲ52SQ endstream endobj 109 0 obj <> stream x׳$ugE)WJbu:`Pz#E@,A@Y,A X;~zjSfwNfU׽sg4t㋎ꬬy~y2뺮_<}HazK_y7/]򍷯ko|&z |_t5Y7zd޹NVE s.[ꍷ._{._;wkrk#|7.]{7!$.]'|.!5. s+OW_E^e.p\Tx)/k^ʍq'{+_|]Tj~N^W.y_`!GpexKtd޸h|f o|__K߾x BWO[  R79eZy۾SW4ZrDum ^Fr+ni̡kOXޫ!tL7d'4x-'d*5)i 5]C9K޼|-q9ٰg_KWn.I=Ҳ A_$˯'Ր}.O=gӟ<۰H3~zf'=k}Zirڿq'rN:@˧p#/, '?I,F̏Ӵ}v{ҵnv}so鏼7d>i &2gg.̏up~_g_GEE%Xn+ۄ"MNlE[~7R=_K yu߰G gtF-w@c띱љ v-g$alm4wӥgN ӛZ՟ك38pGAwtyQo/4{|pQoFy_{S5}hBNcwt䌎ٟ޴ݝ4MuWm9*Li/QZNeףxi'U*т,fsJ4SOwSxq3VϭeVw7w7bw"ZYHJNI=@ _ _9|O{i伿ػ뱻PV OB釨yfhy)k5Rj UsPzvb#&^>ڈ^zɃݏ|to(O\DmI^n#^N+B+UnΤٙsw4oUwV5kR5uhȟ$O5;ӆ;x IT'}q$t|͟D2cphBC{xd!?#tWG+cp&T3#Tf:+7\,#N} k7!}F,&+{)N/I%[NɩYFc ѡ5Wgth &m\7rVۉB=&˛zyq/uU/[ˉkyc)Yu԰2VD2F$G=a'u"ɝ(Nڈ?^Zݿ`-YL{m'D z[԰"Zi?HکSB-IV.դz5@fnT ΐI;ս[=:厡cq39}0ʹE,J9ٛ-y ջ3`iP+K>)z_~LMof` n;#̏GD83G^`x|wmg|Y<p.Υ3> +D6;>33j^]w J3YR0bVPf|/o^_|WɭBnDnjm7C_4{J,zc ` I]„"lТװz^8!l!"yB݉vof wHA:#40?Ciw= A_[ޜR*pJaLx.Khۆ5P^Msu-SV~o` J1boDNFsD`9Ty7a,i9mb#1z1vf 6˹FOb̬6ŭi38B̾E M)HH&듡 ?yayfT#)0o>fиDݧ#D)7|.fDsxx[CE,AM3rhs/Q܉)lE>#!~}pEC/@DɰRA=|:)2X"_ =E~+^M"Y5^lfT8L2p?Ǡ6NA &1 [QXs8&Cu+@F3o:F՜QQڃ|k*Em"1EE\J(1q?NxܲI[y7u.뙪^Vht%1'(s(C_;[n%VNa&6ukЄkSL$iP4 Ð.B+#L=FS+#*х <hI0 Ih8t޸I·Cah?_ i`CHE2I$ ?9w3>&|`v|{u{vS(0(cg:T.F1#]fH_+Jh+.Yn?HwpecJlM/6lX{e8`yD1-} i6ڲ+MҴFi1ם@sPf9RtYa3i8;6<{awxC''"M{RG=@H0~FkukuO\눹h1aW"H=='#I*-2 wVZ(ԅt))IW,c9!9. +OE%r"F!/Ӱp!_ T;nZj/)G|oƐr%PiŜQ5Hx%ghR3RU'tj7["-c%U(Ҟ[6#:\kB ~G'NH3N 894-Z۩4b݀ȧZ0cvCM.^c|M1~$;Բ8%B+%h؆͙YwbB %"* b "EcP(eymi".zmk=AMԥƬCk(B"ı"!5},%!(lt a, `N#,? ) pJoK-  %袩4U#Ȭ6jzQ1Ju:P]cƫpfd+*ZֆDO*#!O;5jR_8ŧET-jS<ݜf4) ƱAτH["mgI 3("FX(eRRJKUtR`0/ I]ٙ16 )wv VHkxz \M6#R2+Y5VV112gHOݢ ѯ} M!=8v/8ȾIoC9P|h=&MV,5 d45\2ۘR=9Ga3Zax.|X2}Z(Xid+zNIx)tH3'^l ,J7-UW>9}K2Ƒ0p3 5ȥx35= KZ)W+Fmp>Ցea^ xD@0-UK/*71>eh7Ecy5FfLBHrdg҄j{THȾ<:m{+aU[N_|k Q{0y• WnGS JZNB}feT.hDsdBv cXumŌa1z0Mm.\ggnPC@avVwDbpB)PF[Dc1P-eQnO͈n]uU k'HQ'?]KFaNIyDK}\jS族|{s'XoPx@?ޕ!@|^A53 S3[ht+R ;!c٫)~}7ڸWSd[v֮r?%[nNϷcG Mx8XYLU H0d BSV1(2 zɱ+T />93<[m"&`iBfn=K<Ԗ DN\Fg*HcKu4iP7sh 0pdnHn),J$̢NՔ0F<>(6c|FnG0ƤжY\#bhY ȃ.5sؠ1KeסpE8Ц;"k5Q8KKZ(+NӢECR&tz !yX,`Fh<:J UltJ"Ȧ=/z`x ݋ݘ>cTN!ꚣ 0;-+A6X~wSc:Am ̘4o 5#t܎ڝ(^ۑV, }H74ū'w@h#Iݼn ^)$^%%*X>1cE.D"V ™hLՐ2o?gI Ƴ o\}%ɤ0d- -WEmgoӉbUmY}9&.37/3ܝ?^YQu@G_Zy'y@Bi'&b6TK++_(2*T\o_\vUUAQmJ"=?{anSmz++AʠJ¢mSeNeb3~}ek- GWiMM:)@%\ɐpEA @%D+hЅ55&S_ƌ%c[d0fm4AðA,zV`7\I" yrVij@DDڲ ،hӿZ[?,+m{(60DϦ)ÌpCϿJ?++/<ΘY&~j[ǿRjs/|JPXk"#|1PG]}ҏ$5 L)G~^V^x?KA N+`!q 8}&O˜nOQ^ĵ5Ǵ)=䧵 ;'_X~\1SlzZoJe1bDIHBDssygk{s3ՖsvOwOx>0E_]0c =yV㎧/%Lh|B_ PȬx*_Y[JLc?V$n-z/G/?”T ۛ9gr_VFg0Vͮ]^ys@B![-`˂d+9K.hy;Blw&NMtȦ J4zpACpBL×Jj`扬nÜMfW~6qB{gH#qrgSҙ`,jq(gTDR sK4gF34i XF€ "ל%pRE) ?N٨MsR6dgz<*iir42f/VXE qAwI +Q6j]A sfG &*XιlU'g~]w63Rɢl8Xн*I7V8O"yo,O  QV1 :2 Lq*-Bq}@؄ -3Du{H= [>u*<⟙jLm,֬?h>˿wi@"PM.}>L%7.^oyWj:$ƒ1CC"vqǣczoU_?-uprnycθWN1Pu{ d~#jÏ~cHY\ӄ8m;@\e)ScI7qWS)ej?9<C:_1$ŇC{B(sa"ȿcc]74磗]Sx#?|Ҟ_\oW1f:Ta*˯8߿췒ן~c{^y%}/m1wp}Emy~ pєlF|f+>-\YM:S~輹V,loޘ߼>A1yca{j}`c3L⁄.kkf֯ά_N 4{Mm0S$O`- lJLFTԢ N0tYqd2X1iĊh5ElNI |1irB#28Ѽ#*BYT?"֡trs+&I=pLp()gdi%"}<5.!ĥ/pϬ`r z{\0cl:s1\rF|֙XtWl厮K*]2-ka89Paz41J6w!`D0fc\%Ƙ!>!hqw:1&p2r1b9 [@uHy@%.r*Y$֖Fw3B!)XP/y 50ͨYMаG–rP&]'79Q:DC:a0Fְ%b]aF1fPӛpWUDu?0c`+/200C[*A)E 81 ` \0u8|sB F" ?.c(ٳ>]*hT9Y|w[gU ϯO1JF%Qp1}{ƒ|b;k[B=S9*lńHPBT)[n֩JG۰bNo'㞁b'JN|ڗh>W}V<̗jP3Jya1b`VkFOW[j+yT\}1na4L\D*ńCu3OՌq \ )p \zf(7l1%%%EV/N<_3jREϟaèHȧy@ytPF2WO:~x"~?yC2 p6[,0hƀW-t$8%4CĞظ_á00;1!oa ec膬oŒ #Qog0 Tg#Xnoe$>_\ |XqйB hTN_ˑ[Lu51*|Q ާ#^ tg+Xg]//N.|>}+υoy/\Om? i;&V:1^%5J D6\H W sgxi EcBk"p!+F@٧vT k42֩qk޲S[tn/2\Yav0#zShuq# FՏY3iƒOL!X%&bDLa{2fSE%?G0\¿؊"Ky:ń zЄ.7㶩 wF"+uG xٟls$e p1C11b V.KWc/qʞ?]TY;cHjOVcD50F(K8#xy行5("?kE'R1ehW) ,m9]ntSG?@LU-Õ\P!*ζCJ޻~Ni !,]Q[U:zRӕQ>Qrf[UYCo6cms0K# ԔmL:QFi7O߅+i]; {g9Hg _U©"̜0ʟ`D;v4lD2X.Ͼu1JyVgO=Wq%WR̻{ྜྷq=ۙtJ[.ΎW"1]pW,_ 1,fnjhǾ7%jJs b}lI:^I QxgK<ٝJ) ( @\fKumՄWFhVU4mp|bۜoxnZ΁%~MҀO!/ET_WYʍ" `jt aA ˮcxj >5\pz+fSY'z{Wr-ldOBP޶VΧ/'ЃfLnOԄsB{l jդXS, _ԺjXi)oC1xe7\2xs=XYomnƾ\ >8]^] \Y \8SF y\ݒ~<9eDaǨ1Ƞr2Ud&ȧke LltX{8C㉘~pm,w ) `9. ,dUlDdf]^^XM=tgJtA+;f *qr,ovjw|BsnQPlbO[P)*a\U;lmMŖF{lZ(\2L3cLƨQlrUf qqR@rtU g*sKWn(`&!hu16Èc4tCϬ:ù5LEZB5ξo{pQ;.$IbT|,iߦ{~rt8&TNCzz4gӌT!bI+aԢa͵*s&]CeTRS̓He1A)EYUjTiNzȞ J-:'37|Èp59 ѹx&cPOђ~e`K1\UAQIÝULMٯ1߅k@u=z>eao ywF0ޭPKzT >BkK $ukvͷG5BN0yvo? ]UY;`͵ӍO.OX6{{Qjl-42^\UGT eڭsRؤB_mv۰٬ZǗm8NYbxDb8TVu@OEiϱfhwYSփxRB7~Z*j[/x(GȵqdOf帪4wt亏1׸nT𚥼FJ}AVՍE-8|ZbR0?სb9C0lc˃HvhQ bNBUT=, SJ2Pړ Zlc ^ZD=4Xm^frb&Gt/] ٓ#IY+]{&Ux ኏(?V8GRFhλ-Y" ZYx1J:Jű Crll{i)2HeD+Ogyѽ0٪2.c:@mWʐ*R[qp_-JQwgV>wϰ>NΈz[{s{;w?p Hg?ysHYt1Jo?]:}^C֙ E%NOԩ3y4Ûo[^~.]BoC^|ka=[nsUaF?  (WZkO#f' O*Տpl9`.m K )sTjvT=rwڿ7e$paot3 xpO}ZiAi_)]|Vs1w bSމJW^h\Y+tA`k9FsQ{ !aƮQgV:!3w:jm02QIcX_ߜG$W5q1!Q 5D3b~ |XCDۡ|ӵq0 $j`{&`Z0!vCȨˑn, k"'lO 0XnnӢ#Ǵ(Ƹ zҦIg,8⃓z]=-jR4O;V2\O萁)T+G&y{X(X=0s%vqXgIǯİD0FF#{LjT,216٭<U@Zta &\ׄ/ ˚1&c~k=$asC=bb1{0I~5T!vQgϳB=b3TTE.m% =w߽R*դQY+*ū;FwDc& QDp6V ix$^a&>BamYkJ{(ax '!A۾IEð% aʴş{C:I5;=00P[N֣j=@ 8G52 c%ec|F,aQݲG8)֑ x$&`l眽4L uUm7>Q *3ɤVC$tFae%"Nv0* Ɛ F{?o cL=*e}GK?]ʑΚ.P]&loL**GB]=in f $^V d#g)Yj0 180qq NRp 3ud`VWI$aV ˈ`Y;ZӢb Z*"R=<P,jX+810BGE4Jk(-l_&K34fTq23{_O2P1SԘKV2쒿G[04%S34QGώeMX/nyTbvݢТ̡CУ;1f >vul ѽH:tƣl 5v U>7"!4W@mmxjF' jNxh90ېKR5k0B-SFW't>m=J:qcf0XTB%\9aacGub0Ǟ? avdb}K FmO!=x#&_ź*>0W}`]jo(Y8%K0d[}19 x1BpU9(״ -)GOgmPoC9ٟ t=BA0 R 1ф Wq;T7a&@D7{8.tP hGN:g92{4C1,q%\S:NES'٬n VI`{{sa"Ҝf)zAT  -z5P٨dU1#]U!#^[C4Kԙ,O`[hF3#`wf,O0Ns] WƗvOJŒN"[|Ը315yLo qVe-0iɿk8֍pc~3q ;wtK(; btU!-9'Y(ې5\o Mp'*Z@ԓȴe} XնiYKgm6KImfsرc0ƀccfj ;c;&! $vwfF Fv󼏞Ιs{)77w/S]3e&˔^3bʬLJ"PtIŐ UP>a9#T@Hj1àF |'Q@I^Qfz 7)W jCf= ^@A$=~r0ŐmX? C m0x%6AܥuЅ`#pY sF,)1DNܨ^%_=A9J1Lh1RAB?À՜B3Va6(NWj{t~!3<5F`V͒p4fIV`gHƪ˪bƄ|%*4 `#= (%T |?f,i;a嘆&(71HqFT38.A "A]>JhSN*gLfPBV5 |OQ`3m: h3 <4h_=iPڛy "f`g/@`2T/>ʉL ld(:A ( .GbLYjU`|3˃~~':v5ޣA^n? ^W/E+l=0D3oW 5r[nD&)L u* `% yj w5hfcM=4ʹ~qʬB2P+# ҋ.e^r)^A!TDByX~`@Ѝ5qـFX3:F91L*7نjj SB؁a8 4UX3c5+qIlN"ӚobŦg$?| T.$@<=!UNx@<=)au p83M2k ㋠%yT>uW%QVC:D(,PZYXi^{XI fb0Hɺ'5ݲqb}X\.E2o&\|RP zeȻ [eOZƚ{u@x@UWRXD фhN iH~.eb#(3?|$ɕ^ O+rTX[ :)m<i@;V O 5eB'X@0Ӭ9-A J5ʯU*{Y6-̙̘f{Y-Y6p2~°s% :DO}{̭̭[؀`< c޶u؋ݮ9}b'VUT7e"|Ly_i %Kuߏ_w\#oڇDиE\[&)5 huϯF#on5= Z]ꮸ{@Br:&Y-8\ ,/#4hРA 0"s1hРA 4c\-a8]A 4hР %c^s!T1ϴu_ӠA 4hPcs; y1p W˥,E 4hРA0m9^Ʒۍy/%~Z>?.P a2Tr4+(Xj U Ck~ŕbP&ئS~Z^%zOaR4hXa 7!kCQUhРA- @chW֝WSb٬)Ȅ0CJcO>jeHE-0R>n7>u][.4hРAD?89 |C<=a=Vv|#$.cT =DjYڪ]a!훎ux'a+uׅ 4h\0m.O, {mq!"µ{4jpXpW^ 5wT~ >rJ1nL˸1È^ T^U, BԺSo=qK\nex-4<Ԡ,Ν(!.+)$5_m5i݉oNm: 6OZC0Ψ֠QRU:m<4hРA]6bYOB | T}'KqtsB8gzԊQoBPf`Yx-(2{Eڕ)SR),$O@5*2Dw45{]'RØhվҺի7:Rx[$<ҠA[@6ESMÍ=JL`|շiuk_u,'D3]}J,(ԉQoe2s2Тw,ע|MyݚIӦmuXa0pWi tʝ+,قixg^8yyU]VBV޴HmA 800HkԵS@0>rؤY vILO@w_e#Nv k,C W=U L-WM,  vv@P!UXexl޹"ϨQw_ gɬ }u[WouԮGOg 9 4hиh褤Kb\ Cb\ eH Waѡ^vO=Ynd*ZG9Ϋ᪯YkaUTB«gJ435Ofo2!<*G&TaJ`ɪcLϑ#kmcU 8ApUiРA- F&1U-\Oq^%Zq $B\/o`u #qG 4h80m.Q%QO0Iiи򪃘MS?%4hРA{ӽ%:Iĺ.q، hи bKh-A 7 fV|tS0I|]WcvY؈F4hРA €C"kI%r b$Rt ]8RV25?8*A 4hР %CB n^"IIM -B -bXX.ϟ"'[ϴu@B -B -By [w.HL,X9IhZhZ }Nمq ";MsKӋ$K~l{iZh@>%Zn[14)SC>dkc/\c[]nenWՆ%Zh²wR!Pb~yAc/$_JIs&?2*";$+:p1|``@(^ag\`\: f'''tL}s{luWWGs['jaIAA۷K\@ Xa]XCvݠ1eܬR'Lm䤖"& 6* |&^5ػn%zؽ"5;n1z{ZؘN)?jjxlŋ eTͬwUCjNX4opp_oY/+ (oe|cRL(r.TP(Ofz%sxtxdwuuzULJΕO0^~ǧ"Wo p]p[ ˡaaZh[K"2 @0v`C@$fVq U/_t E!/PC<"rOk;BBa #<<mUx6Td!iljnjnihlohmk '/K6f?Z SeY=aV%爪~eGEE@T2E2ĶԔ4] BHt!dtpH I{{zzPǘظ8 {[[[)ꫫS 4r_<1<c j'6߻hE4xvc/33 7o:?dttfy-, I$CܾO7D?\aa!u =gG9IE腤˝+XTҍy)fc|:-:t4ft }JfEӊ|X(?*|ĦTBu % /Q==ݳ lJ?:?29%F233KJJxEPraasL?pb;ң{>NZ jPP3/AIB;Mlq%ŁAAAp%88X擒jhŅ}=peM#Ǩ-q68"FGG &iQ_%t2AWΞΘY!}ձ/y_5ô3UVS~y?HE> CGFҭqKťD2pPg"3zy"}||ۺ{s! 1X=Y7l!Ɓ۷^ eٺ"Րэy)rjqa8:'["4(Qbnn%ۛlT>w7}"y"heN앦}W~hreh\|3 ity +d.O.vHO 'RS3224Z4 1W3D!!f@ѷ# 800׌^j7/."$E>8077zL*o9{ N/ cޑwlX]JN\[/-$^"z>nmm}yQ&emw0A"$00u 8UDDtρﭫ([o]!|38{e7Esp Оدy핟'v!V;p8-t r9JL7fb5alIxՆVvI6#M*1ܴ,_ 3}=|>88R᥁ͯ_/߬xýT* &T{>K$7( p`%lhhЪD T.ψ8cҋmShqS]656X9*(*!5jK@3S+fmz CWglz5 GeKw'GGCy<=iB -\7\u4</e KEln`\bvA)X})BS 3ұ#U{+wsJG ={wbs,"yT Ԡ-"8pχqN鼯ٽc/m@&,S1I]ϓ1mphajph pgϞmjjZ{@z9x/*XCPkKzTٲ+ Um5xJJ999jANS{yhS̓a캟*mO|iucǎwo/m2!IכMqgg8D}} Ʃ?C?{=WZ1ҢUEpiK< S3SN9Áft0;SQQ111VŽy#l߿so^ (bwN0IIIYXV<]JY*l#?L<#r=Jl X+ۖnbTUU n~Y$ izG6%*եDk_OP-2;e\մ\y9,LLLpozyyuuui-44F.y*=@NDzz6"ll%{ll|zؖXXZp;;Fn}"%,,,p(Qx] ϟGeyfna#o1cznCA?~ٹgI63|2;j 7n 0,p2A0bbϟHO2{z죾YY}}K>>/2N~33?C2ya?Ȱb0[&/ou8c`^2};uyw ?B"|2MM L"|8F9O$1n' )d1E¤XM%9OV vxpU 1Ng( Frz%^"c񂩁əaniĉ>y $… B\7LN&Eƣ %~jA13-K[, CijWw߼!U/BG g\9ǐܥz1,쥅i\4*p_hoOx\h÷9qePby:11e훚 8/400s΅"+W6ZmKNN},W_<+y3)Ј///:z,kYqA߆P8*9uI^)IIIAAAKt>>2nEX>{baq{nݺ.޹aǞbLoMOk}'`n DzYʍ[qFu]-D7岡!B{;A3 Oѳg&zyca10G48a<0x ي`6rJKKK:'d>JcOq/Y!!'?xUJ6*kk(yyS.VOr 8ZK=KZTS]e]9gMZTkلW_KGÇA- _B\>XꛁfgDyt~a  xfQ _ثcF:ћHq-h{#Q$sFvHBq(1̫)m3]ƻvY;dsV޿ůc|Wwxkܑ{mwUo?Fl.K@ɽ~׿;<%iiK@0zzPTTƘM`I.UY)CVVG߯k !faBƑq;>" F;ip F0=I y~:>ĕ5K: ^:=oXS[UJ[[[e{inpSRO+{p}LZQ_+8kFI.!VvIJJJ)}Y"V3nxsH|H;'kl鰷߯wvZF87(4'9F0p!T,L`r8Ѥj*& !eZ,F2G$e!%BBi ǸkOF~k{߶+wlɿ˨^_x75O;5>w۽ŭc5/BKQD:3݃G. ,uoyήP zJgB׺6AmgllMsrr: V~PsYzp>4Zm#ނrN^)'QIp~FG]sMz9?J%>>(|\ǸtREEEmmmqq)T6&:6( ݜBl̲!x2ۍh#ܸqch?o?uO,!<TCNvTT-pnֆb}?J)X8/mQhhhooV%/=gbXNe7âaRk;::c`^ŎES~ Ȟ-ͪ䓎%pEH>\܎Ryvn);憚Lζt8J?mys/jAKKXqvI ;a(0K8}n&Is Zh9b pLgY6]LB"qރa8_-ss0L&^6#4MVTJy|וLmr,(*IL<r!*!-~OIx 7tףz^ҒtYѥ\`û~eH)qSXsbc$sF8/_]cӐ>AƐ1]I"];q)H+11>TabVn~{=XߚB iGkw!ӻ߾r]Jzjkzj!RK2zV>}Fs3, .ŵ>bرn VKva8p%${?EseUF0g|JH/%Ls=ZбA'};_j&3W3# @S ӼxfSK:pnۦiWx鰀kJO^:jw|FNPR|Bb`Zъ 9\^g}bW֩g{RO􆇑+M1cq xʤ8`BX/[t1>K+IQw[hU{EԼD#W|uO_}Ȭ/g硋O2vx^j, ymhgf߹ΜρBF_AhKY;iuRDD////==NJc@ #2_ CO[A\ol{7~; ~~~bVqs.p8i8l67 5vm 14dǀ_cbbc!p鍍SSSoV!17gփ'%bAd}E.O}wwwRKwp?A 􈩓c["J ~ʕ+Q EII;ގӻ=}mlN;;; cdVof׃wv|ʆ@ Wpp1]ϲ(hR"uZKV{cl]w:YqreGv`cV+ILtuqoO)?P^GB3s)%vmתSI&AӺM:X:8 Jrtv#OvB\a䰫Ә%^78c^\|?hC߮2_be cSxy5333 t'-h!Ccظ,T,X1v1![^IRs PX~ $CFDuޗ:qݻwc^,1f^τܒ ?,+י/$:}yhb'ML&1cL}%.Dp7AŸ.q(\}}TWwuuҷnΣMuݪ{ϯέNM骟mqvݚ~6]\ׁoλ3paǏHIIu:6H/R ~G.Tk֬( 3au\j큋8q"\6wRPbgo9s Pr}:ʕ+kUmuꭋ!u. zgHގ8HLxl9`۔չY<+Z ;H5ط C9)%嶿kttRh}]pΝ;UBw>GvF@wg*uthGS~+m%:f}5] ;Gjz8s yus߃~0S/7u72"=y)Ц߇uDEEѷɓ[$%+Rߜ}qܝtcnƍ9Be1k#3ײ[VSV tYR{OSRT=;@13OC{\XGvMo֫aO8(+.zɶ1~[}=gmammm~zWX}WR}hPno|`ck(=Jǀ@q,ߏ,q.y͞5IsF1e#^0_@@43iY=S-LS&o,ud9JaK=qgźubcc9++]`h@uZ &NѤ)(q|t /ʨH55 O3/?Hв_=q)5zc>`Ud*+_f/|\ݔw_pKm>Kny?`Æ ? 6/RSg @Gj6,Yx׶ /F_|Iys\]]GlBg"i8sٛ'dYfn;c=wL`vt4 p_x>ܫk>}`B4_lYxx8)]M in۞GNGt޽{wo[[0Spzfdq.PL; @ߧ(''\ `\tIW*hb.cvn=bé8h@C&bQW 1222ϟgPP Ξ6(Uʉ/h>/͖[bNP-3| II-\s[|1׿|}i䧟~k}/GY͘ *FQ#ڽwUx-wC>+9tpMh%phn|'.]3>T.颍Q^KGN[pc~Ĕa>{^uBSNAH,&;v0~mw驏׼eI3?/6G&Zy)0>s9 |*zT+AlBCCaiA&N0n877aÆy{{Q(z`;FBV/Y ?rk׮ Zv{Ku6|8iҤ &7 ?L_!R l`BKKK!QJ= `Aζ7&8?Z/22RwXɸs/BC)~XX~ 2S:`?WhkVj^6#~}]YYY111P&%'V ~ݲvP_ƍm<<79v|MCA ˲f*'첂_NPu?a;_gR4ՃF8lG8bRe>X ,8, koe݉˶; /l+4P&_ /I|(hRU<3V "˴y&;ׁ{B' fքf^Z[iPS 2ӈ"G[?FJ(T Cس#׭AqMM#l%BP(J !cP( RCJ# BP(B@P( 1P( B!d  BPjBP(1-]Ӝ͎.CP(I>kB@P(ʪld  BP2BưA( BY2 B@P(ʪƨu0HY޹#!WCon ?WjU( BY1*1B poɼ>\or%宮˗wf^YPfgJ eD R-1BP(21FCCpoJ9l33:{Kd`<Qq( BYc#YrWJZa`Ї>-)f{j"I a-dދ/85\#4* ڛ,BP(aZÀXou-j{´ŸIQG2cBN<:!œ dGBP(U31R,*cSGqLvPq)JJC@P(694cHݰ!2Ʊ%,L _Ie% D@P(ʪ1\3 چcpfm1[1[h۠qjQ۬{OeM#ӊ_;u2BP(UqV]?-S"pO*ͥߙem[uS-BR ,Y5BP(jxhZ+ln+BP(e g z!cP( eU2Q1F21P( *y/d  B cT4!cP( eU6BP(<͇S14ώfalT@P( %/ᾣ|P( MQ{wW1P( BYU(}4cGCCCCCCC`M1lOO&WB:ЭN)t |*ޕ5!{%63ݻmf*rX[RVT1hC˱w)l;/anuJ[RVS0W^Πv}^>޻wK=wA/|= eA$7ig=/ ~'! +C6B:ЭN)tq޻/%kG/ kY_OƼ?+YqνqQʳ}j沠v}Д}~d g)nuJ[Oɚ[KbλO O]xcJlVl. ǐ4ewYȭ:-hy҆:JJ0Z5!.D/c#'aX8hã뎧oq4GV{Xz_ FvLNj/\+f\A׺{ #.11ReA 9o2i-;GQJ~pnзm^J _4g@ dŭ(FG s+jWI9pd$D؀m|^` :-r׆|'a7.9>b U'C 7wjAGnƕzɵ`v^x2TYЛҜcV\\:&*J0jP/ c4dܪ$pihk)I#b>Y3`e:[Xv92IvF_tr21LI9IL gpZy?lhR.c0t i ә_M&v)2bX:KL,MZ61x̕Եa [}-5v10r|7c>- coyL1RNgKX$Ӵ>aYIK$̟' _RAH~tâ3C#4êc _9wK2/O" h1xe#21[c0δ8o+s1Mʅ.ml֎f{idmmDb"c8JD䇰V9c(fÞ"JL,MZhk OLQsIa z9ldtV⮛g=IdAgnڄ(XKJa/j+kX(g,,b1qk%L,T̺D.bbiRy҅%4%': tmc\1*1YB1*2ؓvVN@~˥dAT!!Hs>ekwW#Hec)J ˶g1̲a ! 6f֓;Y?j wc{Llfks8hg-c}r|d 5dV^JV>qÍ8{ߐ"=w2bK$la?O䠋s r Zןm-61^(`xEU~UZdeY]K֑:! Sj|ZnY0FwQt3PLr55&'vkU(e":x}RNv >o[:Eo:Uo;tN1l-04eIP1馬&'Kc8b3ɉ=c8nmaIF(`"je_ʛymZKbkqg|kZ{]oO#nfsY#oyŴ}+e=>fڵ6x% 3ol>*c(tS B:(HEJÆ*տRavJ[RVd1jUXmnִʢVV)nu>0FyM]QC32' BP-QƘ0ƃB1 1Ȝhhhhhhh$cQwFv+_|ۈks '#}d1>6ظ_~[z킥],n2ifDCCCCCC0QƘ]Q⡞4CYnݪQMEV< +uįL!id2ПFf=6n5sOd:A<90F13FuܫȦ5EGtdvx7ÿx2&v)L>oa|?O+V\ϡSMdQR.Y[Ħgd/$45Q2F.EGw]{G_mNXɷ#/ ۱c?cǎ^&^sh֛|vzwN85L O9W,[դ~Ay]3*QI-'O=Pr2%֒~ nqdrbNs7ms't1i{w5m"|KX%vnҪa3 zOHjxR>:?12j<ٌfg0RbMp{鋆/DgG66 ALxFkhϚܔ*]pt:ndezeJZxfVWt.zo-G<2:8V Jmnzw//XZҡ7f6 !㷵ydn& ۅk>sYpҁҺ w;|w ×o@kZƿZa~ 3857ꙝ"x 8/"0[97oypg]X F:^45 ;wjxlM'esn0JJF8w&X,_}t)LGYothM1v k@ 3 } K2g_ЀrS[Śn?߭wb?J2Fڂ2fŤ1j1f[: ֝=2cQ x^N=s%fM.GuwZyퟥ_H.!K[/ݮ,1o&ft ̄gO{v;nK?I #wviNhN v$ <2o[d* :4xoo^Îfq IpMw8NjVd?],sc/jN0d>O21.Ʉ{Ag3Qh0ҿ%ZKu[Rr6򤯤ȨVn[Og1m?0F&IeUO_}ҥSO~]l sի[uؠy~;L-*VyN{A"Iy)8LB1"#ktQ:ЛLƗß'c&c +2vΒu:t9yZv\f` ["susFxz#udw;e9i:ʶ#N%Y44P2|I_Qc>jtnLJ/vr4chkrKj>cW8G(..ؽ{_>עUk޺u chw[OwpB{uN!e5Rq䆓$ad2|d؃f>~?שǕ{3ot|>QnÌO&V1>G,*"0)O,"SEY n I"ҢH8EqMbg:ʵV2"mF+ǔ2QZEr|uch+jY/1<}=|G~C/YRutwjO/22E c:. '!$dS_0|E{GG'~gڵϫ|=LOE!V1xry މ,"ʥq] %twBHZ} S=iOp־̖Ztx',*^1x_+Y9cH4kZDy70a!bT= |Ph-)PHnfjt05{.RD2 &1N7- ׬͇oGRvn*rge`I]xwW-_=ž(2j[U>Y_ `b;na,MUIeTH01r]u}җ|3"[c}+`kAdfa N}]$u6Œ0yMXbr[$]1}"gp53_5UAqF4t$cWgUdWfkjƠ6=Ƿ?@D8SfIbIύ<ںˇtgocy2"SΠGyG0; |8Zs3;!-LGk4C:I^:<]1)01}/d19YA3|?ӰQXgs!$g2H ]C<}|W)=U !q",W;oHG@cȓf 0'17Wph)X@v*]c+vڊkv[JC+ԺL-~),P%!ot5S"=cXe I1F3Lbj-(T\vXl`MkXh6Q[QDԺD畋= |om=E>ȀacT8kLư/`3`ptc/𹐭(t:eT#aëJ>h:TܴFTUrFs*(Z~YjQ(gd;L1vua_hЖW斀)\YEC h$0¢, 1V6ëu=r#_6VEU(V R=DQ:EԊTG'b_YIY`aO0$i0~.rH~^b MYݜR;`%Z)ƨq8h$p 6}tf-S_^qlէԑ胚"Pq>)>Վ'u\Q(P::D[*އ($ ̰/`R$c#nj11  ځM_feetqm@ Ƈf=†6.9lRʆRآY6 jJQUj5}W8R~j^% ^@A8 T Z i߭a`tYg z{0X`o̼wޝ;w(A;; sacJ*ͥӣmj擪yUK% VA{DUoEhSk:Zz>zNY؀)&a,fob} 1E>c1?a))) лhA;CI8jpmY6ڠSk: ZuZU*jVR_P*h- ^@e{)t a@} kI6-Nİtg xXP0(---..fH2220'\x8.+ :3t%K,Zh@O*h>橣*h:f)L4Ce#o4]yQk:T.(A `H#444,,,""رc,f&hZ+1$1#e =fJ"y1$07**j޽/^LRSVm)5{S|U{{ǹ孝 +elРAnnn0fΝ;ٳo߾GFFF2bΰ1 {0F]#fw?1#a" {FJJ ?ۿަJYU-kcՈZ]=Zj &(by%R4fyPʫYc >X)XJ*kͬBijfśPjfNvEV.j&9jx==/C@}m l&T...^^^0Zf2Ξ= qҥKW\3S&12F1*vIbTNOO}vbb"'6nܸpg_xi]ʺtM jvv>X\*֒s+X˩0Yv9k7,3,,` v=`i%Ҵ3X|FڴWa{0f4 pD}}n2uW&1 >`u2X%Uqv3GnXX6cU U&d:gX|FkW Yciŀ+IeJje.-t❒ ni~O.>Ttf~TBީSsO]9q[\b;ͷ#z;k#`q9f;bbMvd9fC963I(iL؜dJAA1 6y)c["]Ɍ0Cv8&kLǏ3=!' !E%惝QBβFN.N2ع&\t!EoLv‹Evv1gWƽrbvX:K]%FqYƤM 8XƂ .:9e,@PفrY3ع@E a,$tp!yW糢ҪĴzhYYٹs窪&K0 F^ǘC1s j-8MYĐ%h4 y<~_^x/]1_@ cqƼ Y } 17̌hL#aSǔSz8џ{ C>dPG*OG cNvK!ki~Tph1G@ӌG=p.aDXd77&:2THmxu(qGm"@9" t$􇘄G[ݫ}9o*/+vҼ$\O^L>gh}*'#od:U/R\{B6a ^ԛ cw"]D3H'Ta!4.vT AftjH3jzfDT&4ЛjFCPLjN FBŠ Nƨ0i?.7)k8Kǎq?9~G'ѓc''NNN!ft)Ixa?w"DS-[+l߾w>Ǐ={… ,tvvvf̒,Ȥ[h KǘSb0` WСCsᣟSc ĕ`Rq ^3>I0܉9W1;&3cQ4ጚ05b ML8Cgd 8C5pPvWkAb_)1F5h4D{>!d@?&{6D'J[RIs oe VG:%"- {yӢ NF%Mz#&i ; =q&%9[b6wpm0zu?+,R2!€~l8ob~,.ah0 1- h jjA3ڑ\]@͸f3 i\!Cb0 Ѐ_TaE3i5Qiܼc puKkl:|h#Gt9)=#C#cȇڦugqL=7-`DwA_c 9Fiƀ'=}]nڴi׮]<JKK*++[[[Bk(1& 1#gL w;!_a9 bduttt```O߮&f8p3_{@6"xСw#ލ!ÿ O|{f8˰XWQ4"0xc8f$2yW_}uo'8qҥK l18F#*#wpiWwB0n1XY $ > Qǘ[.H0|$H!AF0伟3  /2SӞ TNLjD&$a`1]Q0'n n~ΛGJq3:T-qsq @b,TP2Lu#! &1v`ٳ̃ݮ$:hsĀx 9,~ &Eð:7o2:nd ? ڷS|e(֌Q4xLgOT ȡDsDnЉfp@jgSt 9?Y/wHm/w PgON0(hh1iaH ;Ià:%j\añ{.}wv|gcwڿ=Lۗ RëpeZI=C0 裗/aqFf1~_|q˖-w7}ѣGkjjt,Qc ͘(q#^1ĘOYz+p8GV]]gڵ9B`P-nRxE(o)#Yo2Y<1Lr1>Q%̈O2bR)3&=Qĝv̚`|Y%?ˍk$dɁ1DB2}nHIŜ[aٳtȕE7 dž\ ƀqxeg雃m}6>" OM.iM-IXY $!E6{`aBD@C V1d !c0 j"Ze;/{QxR(4,ЕB"zӸ:(ڀh8h:5`fie$+Ԩ ]D3]_fc_ll.Sw]6< "{6`oVU )p> .}کFqat1P3c61Dno,K>\\\ۅ"4q!`;<b9F!5Caƀ?aʴa)N "O.lL{& 2! ㈏3g@*Gu21c$VuDy .eNݟi œqmN}ړmt-KlI%ϴzܩnw˅3M|J `&p]!h4Ιat Yvq1<1ikOļ fPM4 ӈ2f2f%I i(Ѫ:1>ƥDrF*aQ0F!$&fWʳ6YmnԽmmzvn`;7,8Fx7z _B>P0~#C?9c#to{ݺu˶|} ܉s 6 7nܾ}޽{?|l˵,%C.wOpX11<12cfdnLNǸq,CQ’1XY 655]p?.t2D0(|?Hx vIχ 29#IƬŒ^6\(N&z0bt}xQ [vUzЫ3)0!y%b8F>~k|rl=wG9hRi)6{iH}a/ Jdfs庨FU?#.Au:?=U9<ѽʄRpњ-Yk'Abfˍ8f侞}[X3 OO y44hF/uey!clr3ciP4゘1 -6B@"h=כaD7u!54]F2_f^c ySo1g+nfOVڊ%.iY}%֕Kl+y+|F,]]vOWF90yw:oݻYI.ŋ,%ލ ĸǘķ̍( FtB4c4M#̙ƒ:ǘ?dǛ;wг~Z#a?XbpʟPiZT1-Dbyˬ'/zKsYt zfyodMD֊ IpCS*Nzfj"*<Ugt4?@Hη$~~okEgtg\'x W0^3E;Ϭ$ i͛|p*6iCJ[ٌe[eefd ň4`pLJk<,i ]i iլI/iF^W5a94͈VE3NVg h$TkF.ȥ|').oz3W}<ﹺ잦i}gF)a\Ú֭{^}-[[<;v,%:#; c;Mʸ bYe 3SYYGmݺL0p9ƙΒLc܈¿ F2Qa\؀^6BYF]IQQ1P܁aJ81TZhg1>'H@IAC|&=r[UTi ɔ9jz0:hcli ܸl̸Tf#IȰZN1dFɦE%guuV'U&%O<P'42f;ctPO̸Z1O*p eDY3P1:8i0h7 ?:e* QʠXlL2B1 4|AK\YX!A41ƀF#ٚfyaЌ.rҶK\Rle?5WнWix^#v=ro#?b]:1&> *\E-@ogCBqŃK>_r%m{1c<>/y撒w}СC}ӧ%W^mnnfKK8:1,/:sߦPFjǸq1T`=Jw~`MKD{ gT9` ?ToÕlf|c%b5ZS;URz۸DR/Z\(Njjͺ ;iȿ!Ԛi\37 VMT)kk+qMgiN9L8fXG  4_O\zvKϯZzq˫^Y~҆KV/m]}RڟuY NR~ \C+h =4Qo3X4.w:/~ p7xc,--=uԹscJ\1BX1ĚTf;8w7dǸq A<~a~8cjq>Ϭ/Z{beQx{\e/<;)\M'ͨ@4TrrfisCbM3r4IC?h(ͪK`(ӢJ5LYT3F qB$cNXCCsZ>11[=t,'JI-4DJq -aMqcTRAPb%m</e{hn7w 1Ws>҂'[!,| r Du -퓽MfU+)ZURr>g,14m\]b!ĵN 7QM-h@CzFmφ(b~9!\Yԡ["AUvRJg'?֪]rs2.0/>g{.Bxq;IEZ§3his ,1`_zc" 8AnF~+YY h*ж e6!cSp åC^.4˔c.'z⎁MoJNQiAUR*ڜ9[r Pb!'GR c(#i4S zL5KsӐa0(1GanlӈfDf`.I4\8pӚ1rA#[ޏhk yS~.kNh*Z hU,?(Մv>#WhK֬֏(yLRu 13" 4A"5g5gb7OڲN7G`DF{p1fTkz9F=nc|}y51jpьIFl"|N(5h^WkAe(P'f$e?%@\SDW%嘕^맨 (,/rj+]$%/ eϳԤn 9TK\(c8B?SClkP+E9u j{)ўg!,$Tq=wW.dPM唉I㲡 S3j9G5 fy*yh+lA+Au3BL3jlaDʑ!Lc7|i`[*JhhYr5)1D3-\i10\/{sUw5k=o|i7';i: 7PR4J+B)Qh4׸fDӰ&v'f ڑe&)jL0ri3NL^]qR]#x_cQc jw;!_01GihFh%l8##$`h#Sf_쌆O "Z1 iv@sEfUa gFc7+n CLc8nϊ:njfɻQ>l#f{NDhA]Yڕ՗<^OǍi#D˫VS*wT*k/3r]v`u |a(G̐ÐA/+*c 0  / `hdsAϳK?E)9egeцd A0 DtG$>C Y8C`(A9DlIǗMzЗC nɅ)gxz8 @cNFdva 34Ϙ).$1u+JZY ( Ъ*^+t!MNhD1 טf D;l ȥk3) ivfMYǸ :Bq1 [w h19Ɲ/9q1[H3dLÍ,</#A+T˼[+AY47 󽺦X"34EHK妢u>o$rCp6|``r?9Aq2[\t^@ (ؼ&t 10&\LX2FS#d3_oW7ҟ h` HOp6J X[w 'e Z9M5Q>[F0M;څŦH.۴^C'YkIX4]4DE30 TTϠFЌ JfMNgaM3_FӰ*S'4bDC5C N3 sȥ7nIF v fcӦM:M}|-jm ͘087~w9Ɲñhh!QΏuGcsjRA#,XXŒ̀b[Vi-29nmQ@4CDζ#J€R=T7 &z}}O;j4лT+~UU(:mǧ>pXzg'e˩X'hw/S*uJ0\$8qNW%yU&^I+Ut|*njN'>i~D׊ΞU4hf =bCxx.,T'\G1C`/ ~CN&0![ PBQ ZP3ބ|n C)31 `XL+łLJtrDZ0UyU6ȆU8S_1ǖb-]EVhUcYo1%gVKI-H+Vo*_* j"2%T,IdԧٯIO J}LT̃Ej3.sa&1hfk 71xcDQƈ.'y3%J1zzz0a&FcP_UcN1H&cd2` 0k a 41TQ`0#)EAD1ƀ@ JՌaG`#[UsQ{M t:` z6T2F22όRcp1>0LobC1Ƌȃ1 6"1>1JA3Xc!c,--#a bwr1ng |`hmb1?#.ohycjC1*@ V1\%i1prQ10Z/~!0F1Zq1??4uAV12j  ӛK\4#ƀ@ F!|c;v̎`[ "M ckx@ vJaG`h0F 1 ƨ&@T-B|qc8Q6 eNc&>04ü1ƀ@ ۥư#04#[1r0P7ƹsRKQ3%!T*x1 }F%M ,cX䌑)cl*41k1Byb`w0uR`3UDa.0*ib1 dMEWư0##YX̭H0!VcLla_%k?v4F1]QcXAb(#_T1 !5SAlbh5++ƀ@   ucSA0 `h2訢1` q6EORPcX4F 41ƘR1;wc@ hD:~cnbè&1r1f(#ecT|Ŗb(#Xu1P-cX c Tӫ43(i`c %ƘW7' cT7uuuV@lecdg| ca"18f,VM1azC[^ /ƀ@ EC3Qb1a 0l 71e1Yk #ֻ~Oo,fF"΃o*tʎ\y@+MX,iZ*HNd12ڍטư0 3]c0D1Hì&VcDBH,5F}0Ԧ6ҝQ q|err2I@?.yQaW y13R&GM81HfFfc|i5ƕ+Wh `5(in d tXՙ2_L e1 G;SD[.~=Tg/GQ4Ur8 7转,3 cdT]=}*_ 0MGcn&dH23:+'e xcj2F51c$ Lcx|h ލ>b}mae\t0K AYGɧ܊D`w~_ya(Fw+1J(.KCJ j9Nz*\Lv8*إLo>wwoyR;CD3)XN,H]%uɺUZ] R(#ʎd&c&1a&VcƖJVb:AJAZnq} z<}S,}lL18r_[YGgh姭C{ojv>Fxs+Z"ⳋ$]"5FO(]-A=c0Op]+}JƑ hbK׭»+G8_Y2ưN M T*i|au.W2kf7RfzLgBJQzN_cޘ1$]Xټo_2}>~w}݅F/f&\"z])1 %&K%h>?2821鞚~Z@/J.d])=K֭@,Ec ڊi dR5<1lVc L 슱`.#kr)g㶺*߾ގ/dSRd$c8% ?jbGV=WD/Z4t1?sut==3tc_%C=#ޠD'n{Etֽ+ᶧ151f 515×(+e1#c,KbWaAۥe#Գ#8wd𥛶|םB_c?޴qAwDG!X'ј. O&|^ KC.1tѨ/qc^)lK^}aԯ>nFtOi 4uQ1p^ `X 1 v;WA0W_NoϙO~AF{w%!@-g΄Ñ77Í pptB#ǗcH٧/?D^!.^!/~o a BJ_9*gRNiKʮK-b(#7H[^)kSNZfuAZ\X' |+0FXa[_H"7Dc8CÛ։!5 ;;K] F1/>b(# 2)P\IM61h0j0U$٪Uc506̗Pc4˅~iHW{V2KZ%c$s4_e^cÎM  |-c2펎i^T@?$%cEҨ:M |``1Ht1 U` cT,ҕ3zLcFe, ưQ#.ƀ@ EL~!W`cT*@x'3Vn9cشng QXY.b(#ė1{a: g8 9"՚Z_*ƀ@ FP"/1dW_}Վƨ*H.-b2QRn\cF%M cLU0P1Fb1?r 3L6J@+_+L%+` ]H&MeQB:M |`3l$C23&YYcAlbh5F:昑 λ@ 1SƈtI /`40P3F: /1̈j1HXc0ƀ@ Er<ƨ20TVLhfuDdXƨ&@ }xg1a`T`1c6fa |`P&c sY@%cD8_%ݎ0 *ƈ!cR3AΔ)  BƘS1Fvyu"G5ȡb(]L]a d"cS$ d CQ3M M,Sj̟1 nQ2Btx 2>0jbONSR^yrưxCh@ k ?@lƠK11jb1BbH+o 0#c#7ρ1 ĎQ1F1ݭhbý@`ΘX$Ac` gF趪1L13&JQcM hq̍1 ĶQ5Fg&c0 `TTKH f$s710082æ rƈs̨1H1d\1xf1 vQ2/*|c\tI1&c\rE1~cdC1f1 vQ1FX ӛWgF<#f stZ_cbèg1n15O1H&F&c&ttv cpC1F104Xc9f6̆qQt8G_qсLxm}w[E)>OrT[|4wc::;Q[ |6Ǻ쪿{Ǘo? ]hI-m־tR{[NH5/εvvt w9_j]|>Ffg*ܓr#&,_U\Q$VK1U>ɧߔUTŔ2 Nmi|ԍAQ<3d3$AQRc+SԆ.n'}>s-c+QI9Ĥw̦.eKutV~:7ong/ _+^$ aڭu\s<ӃCCpf}{R9Es/ftڪ51dVK17~^\RqLb%/[ -f@(1:CwC1QM r(Fn lZL*nK6(l3Ҿ}hn{qx~K_?w^u{>B#Hst-0W!h>?2821鞚G@?p@/A}h-ye%4J.?iU/+p/wLj7?bg{IJ5 :70qEƠ<3*7P7ƙ3gJ1JÂƠJk}ŷm_FY "Y3[G'3c_%]|E` L]L oq2E}49 c/hJO¹(c^`Q3a&1Ϯna+稊0 6Jd=Qb 3gQ|5cH§wd𥛶|םB_c?޴qAwJ&/]) 0Xrͧ`=si WGƘ] z+g4WK Gz3Rk>E_VբUг)1F\ՇS'Q1!cF՚8ߏ+Aزdh,21P1zH1ύ{=~/HZk 72!ik>˞+vkBygGG˙3ppcu7~769}".4hΛ'(mt+SUn ׋b"Bޕ\6,9TU/ً1bB])~N\*}3|e ͋)=50%92͌04㉝F_1?qr)?Zbj:X?g 50Ĩabez' ?'GkYה7J)}v"\|,u:>FckdFVYLFa,3 5ݛJx]Ҹ7jFM.mv!l Aي>U]n d Z0FaMNN2B?*} Qe/RjY#in705lC?r&7lrܳaS 282rndrC'ܵa?aYc)M b @ 61c۶m:QKM %co:Ϩo#^6<?'4$~,@l%cR1hEC4l|# '^aDot~t]= ՍQKM P0b˨Ґnj0 ob( O^Ӿwju}[㛷Mx^G_ QdEC1hcPGƀ@ E>%ưQLTC^^w-f;\ OݰcM X <0bè"2 c _a&1ϕ|pT928ۿ{N\8UcnM a&&0c@ 11xf30d{6nsy3To|ቩsǺ3=<9:=~kizg{G;~j  MHRڌ1G.0.Ƙ]]]$a&1dع:;o&33FfĒ]&F@NTq2܅Ib  M %clzg|wޭ%s@-*=TqwYb |`خ0fc@ n qesAemO|#NMNn͎SH?{P1HhC1x`\c@  bsXf3JƸױcbjt'3u5{l -yR“;'FM |`7 01o/b71ő5&ǎi_Ss'FT;\ޅ۾-H eˈOy~B}ưcC1 $b(c&<{ma9Ac3 Gt9uUK_[۱['QJYcڌ[q ƀ@ EWgyf`&0a&1\3 G^9zՑner(UMc&.cPcT?݋Sf& 2͌x8y$ cXltyqgh@ʍa&FJ`ƨ0/z;r9` bxhcF՚J|eO; .6!} 61T3Rc\}e:>&:z>Ɂ=#c#ǛΡitM͡@ 1ɖ> L5Ƒ#G5 `7 Ϝ 51^h1JQkCt]/zX_o1z36&z{5_` bx@Ơ6Fb1g1(k sJՌAF+MBQ{ztñg3`큟cL{}GO_νx‚Ε@ Q4?m昡nb71QzYc7F%} 71d1<>0Lob(C10jNlcm 8{H4ri5<<ƀ@ $n *xw1QM ck  d ˥n f QH] Њᙞy?m+W:]_Foƀ@ $bicP4+BBcP̠6ZùV!Rɹޫ-޾5O@HDN\+rc)M Mcx^uc8i]8ׂ1]%`+pocwnXs?>@HD3<3d\ca%d]A41XXX`B aq9119 ͖9L-#P(DTq8cRC.qc5Z1H1zPMg1*{>k@ 1<=3<3*1>0Lobƨ&o`0c `c0:  STM `h6 01X1v4F51T?.kϚobyHeWiRǀ@ F,3pq sA15_9c#c̘1*K#o '>b`#G0 7'.mbМWl 7ό0mb11•obh422y359vFm>>-M/*q h8qeu} q*` #WB![~ Vq@?m#=>=BݢnG,Pgfe Rc4840mb887AE1c$0\Iqw@Q~I= e` 7F#_PP 3dGAG[`tB~܊n!7֭r?R3?(eF1yưEC#c0e1l6c,-3j8 gj S nt6!42ŗU+13u70ƀ@L 1ЦۍϺ\3g+R]n5݆w4 6&-nda8Asn1ܕ0mb5SU6-1"1(fPe c27$F& Q3040M)xcd#!@N.ÍAib5 c7:s*$z+B4sCO5@o0Rԍ$4ƿ15 `3`~Vls<1n =$?VcFu0?M 6͇|. <?Ae0 ƀ@ F<0\eԄi |`Đ19ckl0y9}9Դ?'j2J@/4@j/pe 1n]a?: *B'7>0;qnLVSuιfL&sIf֙[3dB؍1@HK$!$ @daKXn0x.o,[ [&mek{O_xz+$if"3d Bc:ȀC1feBƂZӵ:~3x[cKLl cP(F1=|Nc*qcsWV#0 P%IcSh Hc 6hdd|”C%F1F#0> $0ƹCH k KZ%mNg4 1`ӌ188cP(ΒH12Hl"0FlyvXY])|cK?^VIJ( Ek `s)2KPb xvRGNeGoewg&5FƔp8hc?BP(ZN,cq.`4C 1;^y;{)7FVP(F2˓C#JDpn1K4FMG.Ou[Vv#1( L3ƹt/0# #6;aUNotK|fX cP(J$` %ExvmVbyqWa%d ߏ4FAP(Xn_c-1s۽#eMM[}>Yo J1PBƠP(I F%\4ExfN.7o+prONcCctc 1I`|11XC1s!wFM.ːo4FFpaAP(4C_%Zcݨ^]Pac'2K <0TC2 1nݺJ k%uqfTwV'1X]㭷z)(y% B]i PQb(5Ƴs;Me zcq X+p121( OڌvDy.HMeR? %Fxư1( %#AchPj u{mۭv;bU` %FEƠP(<1 `Pj9 GC^grF_}>31(,޻mNpwZtF1nܸ,1Ccƚzn0]&121(2 W3|/ l-l3lyKם;,?'Ͱi)JC1H=0tcC1`f2߿wyy= l-l3lyKyf?(*<ͷ>E_Qg+W K k%K<Ѻ.A֊AwxEDƀ}AI~/=m]clܸdFm-OOY,?c K uFj:m͖~;,s>3+4&d &15CoLƠ$N1q91tTbו]l(m/j0_5CKcvUPdVLc "2ޑH8-揞zP2%i4b mJ܂\uFmK1^b۵FG꣞=weׯ"Z`NlUVvV͉B'xneZvDSO} OBƠ$h 'OD0\b1R,1±ёW#cPG23|'8 Ԅ0GƏMl~!K'g~3&=|Ѩ`đqv1զ1X#ƘPx[ČF_|B1X#%FAax>K:C;! YYmY=gE@щoIYq<0*{By☿#K#5hM;a6e ߕ#3>g&Mf$fH!cP'4a SJ%Fbcܼm'1 Cו(~Χ^VIe J#@6ItgU`T<ж_om! QsEl!U:k|CV<+6ۜ>D۟?=|ф:Ot;~p:9:d JH8S0%6Ƨ~4/1cޢ<_Nlqv]%Fx1ƠcP?b'Ki_"- ӎy|7+llscܽ{s;OD>P2!ICƠ$ ;wDCG%FR`(5nkgwV|¤ cv2%G oҩ/ۿL99Y>y~휬9_ |ΓY9M;K͈C'Nw$;kKhE}}Ft4 cڌC1sF!@-X/  %f"cPnPI:K>xlʊ5+ݯqSO("|goIE{=1o>> !…?fa==8-<<ˬ'AAI0,PjEK!C#n&2K1\.ưݿerdjO:xۜz 404믿,9y1]fa0/oD08^WBIxvϙ,Ƿu lscAom&cPgƙ#J s',cs l Pd ϧUJHƨkCo!cP;c2Pe~S|[ [[3ƬYdclݺu1._*1C|Χo( O*#_W2n _QBP2$1c mc^qV>  =Ql_ZBƠP(LdS̘n7xc۶m(,,k 1,1Jc#1:;;o޼e$cP(J$3x嗧ԩSիWo1c %}@p81Rb(ڗٳ}ٻy%&Ͼ:̈7R>kP?9?K/KW^L^gUYh^lE䪟 ѬDMΔYi^y5R>+^Of^hkʄ(zV|G`|bcAoU0܃G1#Zi t:M&SWWWss3\%%%/^etK)1ftĞsnF|H7Aiu aZjS&FF!ql.cb3p6-5S1 Sm>Wm>;>&a`g+'rH/Ρ -j.Y4خ6]k_ov8ann;0R>NҴĞksךPS &Ն+M je+\LQN}'uO4#DD{5X? 6[|={<_`7o1+g J17{?|`t@Ǒc07 `̤Ĉi hiikK.}WvcwfǬidF{lf FICbF83.1]|pmẌ0R`1Ɍ c# 0hƍQ*0ƕF6i 1$`$7F03mqiL2tt|Ȍz[3(6PfC6Fq$f \y=+0ONDf|[. 1g?{kXb=O HcLO9h`LkD1t`LcwOLTe_?cosrrVZk;;vػwd… `"3fn H1f/ZM0#=CG%F40dc~6 7MyyիWO<u=G9eƌiHb(`Lт4H2F Cn30`*0T+1b2D`F`;mI`tF3 ۼhuL013#63n`g9U(K#}qaJ窍W36n$3mFJ)1F!UW֑!^*Nx3᝗(1i!1$1&PÇ;v/^ i.1y9h}j6{|U/y]K 0u\` +Ϝ9s!ʕ+;0[g4F<`L.3E,2M"1k(FE#IDQ 0IӤqWbDcbJj30VR?Uʼni 1 9ib#~!#0E8*fb"3~-G011 p)`dfL+&g**[\g8qHjhfDƈARcHUFl`L.ͤ(100xqWcQdZgC^^ /av킿7'N={ҥKQ\\ ƨX%Rci"oZnWu;k܎؊50YbDCzih4 MMMۀQ/\j]k֭G}g w~Ǚaiv̏Zt]0̝L!xT<&g$DY<JD1N?O~ؿ>sŋ֭۴iӻ fٳ>/O<)ƍ%%%h㝹3kfs3M?k)ϰ 3\ϰdnn.-z 6[lJ=zTZ(|r̅u` ՟Y{ntO{[[7K4N\d_z3g_?{*@f͚b^JU "&+yY8dR6%l8$GI%[~~uݺup۷޽{_Q ҫV+**2Pj_<=aJǖ+[vnjX0Rk 1<|u tҥӧO3:;Gm۶ ~7r9E aU6 d= /:Y&kd5$kHuXO* gW8r{ wpeƮ]wAJ %,j-:`6Se.{TbƐ%#rDzSf `G*,,qر#GسgΝ;;vx?V1{lA(ɻ  o1Λl:IZB<.\p p wwOѣǏ())@oMjU6 `p,1V<1f1 ƸعI\c6cdXol6K/bmllkLb (_}駰ݻFgd*G !`J4 0Vj:a̝+n KH[RuwɟQ" %LPjゆw ߹ծ[c [bL3f\K+& ؑ`WΟ?=qHÇ矉90Od?C6:{d|#1w*B˴큋 W;Q;wGp|С/0._|5=#KHc#1:呌3mC=%}.uq0UƐT\|4`^23 qN:~7_Wl%:G䈒| 9&sq>S3X0sWQXpW܅g~6Dɓ'#!?Sz&Fd4X%Qau?Zm>RmaZ.12Ĉd `~\Vb3ۛථ)//QPPظx `<+g :;%AN)ItN0q%97z"1#*R.;.| 'ܦ }3_20JJJUĀKOYlorrZ|{.v#a2zzz:::BnGeee~0U%e$ѹ {tbsU`!VMYK KE;kQaIN[%`o}[5)ܽ]}ii)Cz-z J|#7[o 6[7C/,hfH&.FKKKSS$6U)od)EM)B&:7ؤD3AXpTMT86YTMդ,3&?.\p+>;- 0^=0x`(-1vKEkYdsh$K Ljf锞188/ vFsssccwE]H;REMЩDT,$r7w ⍧{(].&AIODRǸ +2Ƭy9.Tbl-o챹+=S/11r3V$ 'cCLDZŴ)IӌN:JҀ.xǂp,{]n|ǂm"\H?.D YFfʍj{{* 6oq0VbȉfJBc``bf$y35tc@SI:iGGXx/y 1u0cqnݽ_j=ƷOX`5fn-|np餫NTav~MC/_1eƘkz+ 1V}.1QƌhiHOҐ3:&tJ҇N/:=J'_)v0F{uEƉ[_ tik%ZH݅1X`)1F5PQۙU͌HixH'26 Cbl* :XWNZS"DPw8騛?T)}Ҿ$NHAlFB[1ܼl/\wW_2Z K#f!/ȝDqcGgHIl#"B=H8TՑg+vcƘ nw׵jیNOpŋkgb nHi̐WOxƭ$.t"/aF.ҋpUCt$ΒYyZI1eBC=ks~auxKK'Eŋh!-[Xq-xv֡Ta&`dC1]0fW ZA1#ƈNbr "5u"3T0tZb{Y%^bA% *1tQb$6Fa1.j,J p/1u IQcA%S`P uJ x`p/1X{ %bc4:-1^bJ %TbCSƠC$HcF?,)cdd *1J½J {F L41P *1tTbA%vVIx`p/1Д1X{Z qaI1SbJ :*1J `g k1cHHj C;$K <0*  *1Xx`p/1z" g}&^%0x`PU%K <0tZbC%F\c,Q!)cC=hJh *1J x`3Tb{Tb#1rcO_=fg84x`{ *1Xx`p/1J *1c&Ƙuf L04e,1^bA%vVIx`P`p/1xJ Ƙ i79:-d3*A%J <0ĠC0x`h,{QEƘ=?iw>=nfN %TbhTbJ *1TCJ p/1C;$K <0`]bJh`[+i3څk J2TbJ p/1^b %K <0Tzs>BfW@|RTbC1CG%K 0Yb(5ƼEK1À2{K <0x`PA% `P1#1X40r&hê2FFx`p/1^b %K <0tZba+1C s!1lv{χJ x`hTbe{%KHfvi kEc^<4z69FLk44@JSb{ *1Ġ)0l{`1*Mp"cA%vVIx`PU%Tb.1^bA%Fb`3Fc(s1 *1tTbA%*C%K <0x` sG aF`JA% `p/1 uJ x`p/1XJ Ub$2{z1,^olݶaF` LG`p/1^bA% %TbPTbPjy}@2؆#l>0 *1tTb` %K <0x`{ɍ!̈́1,ǚ-&o[} z=OchJ x`hTbe{%K $0]:PCi{^J ^bA%vJ *1TJ %xv"7\6X+0lzBw_zeSRcA%vVIx`p/1Д1X{ x`p/1 xfNlar6 XRcTbJ *1T{Y%^bUUUQJ ^bA% %Tb` *1X{Q%F1<7n=&$l`p/1^bA% %TbPTb+1c\Vm6<$` uJ x`p/1XJ ^b %K <0J܂%XC[0vJ <0x`PA%^VIx`hYbC1dyBwfj ƈ| *1{ *1P *1Sb(5R %TbPTbCS %Ja{UML`1JkEfWk { *1 %TbPTbh@M2VT* gVcPU%2FFx`p/1i %-1 ִִj\z *1J ^bA%vVIx`Pj9 NKCg_ \Cb ^bA% %Tb0QJ1/;i6X[zë*~ =J ^b %K <0* )1c%HK&w\v"cx`P %k`PK <0*  .%c'0=mm1ai x`p/1J CG%ꌁ:*1H1.uuk~q{ %:-1^bJ %TbhHh O1f^Wsv_|e=J p/1Д12{Y%^bC1f]hwk;+ ]M=OyK <0ĠC0QY%^b#1Z呌6wmg?۪M6[K,:(Q%VI*R&[ލkwݤr-Qo'Hq_$CX̅g_Q$8鞡n |4,]b =ĀJ %0K 8`00`0F}xT1ݣy-2#`0K 8`0, s ƙ%a.1q(%FCxbtA k`ʱn\̕-1\b%0K %\b%qfIK 8`0!cKǰ,i;o^ӌ%0Pbh0PbHb5ƀJ I 8`ۺҹ2yJ a@`0p0Ās (1p`.1USq;/yW>~%M(12K\bPq(%0K 8`0, s IVPsW2ĀJ -J I 8`@`*1Zc9/! [8`1 %0L*1\bĀJ J I 8`'ڻ+\qUF5f zs ƙ%a.18$%0hag*1iLV1)Ժϧ%0PbHb0PbHb%qfIK 8`0e5d8:xFfܱdb8%0Pbh0PbHb5ƀJ I 8` ct$2Дs|jqDsT3q%\b%qfIK 8`[bĀJ KU5i0Nأ-`Ās C1ơp`.1\b %0K 8`0p;cJiblū-3qĀJ -J I 8`1Pbe$F+k>s50>k>MRbĀI%0K 8`0p@a`.1cc̺C3ihE׮ 0Pb%0PbgĀJ ̒0pFIz`=Ip:_ҼϧN (1L$1(1L$1%F \baQ3FG{)ZZw.HŭwZ` H 8`0p`.18$%0Pb5ƀJ I 8`0a3狥]Jʻ$J (cXds%[0Y0#`Ās ƙ%a.1\bP`0p`.1c>I'=bbOn=F 1%0PbHb0PbHb%JĀF}0ړ`FӌCW`.18$%0Pb-1\b%CQ1.k2FsҎw0F:4zJ =ĀJ ̒0p@Ās @h1ں7wo50[@a"(1L$1\b (1 1ƩN۞w %c0K 8`0p@Ās p0c0, s199cޕ0cJ (13K\b%qĀJ $Fky 1@aF@a" (1Z b =Ās $F#pI쓾$Y+`0p@a"a@a" (1Z 2ƻu%+)ƌCW`.18$%0Pb-1\b%A$F}PfL`-6` J 8`0p@aY%0L*1\bĀq$FAF%C@a"(1L$1\b (1 IfLO 8\bĀJ %0K 8`@`0ĘTVSAwufaC)1\b0K 8`0p@a`.1$ƞ0#`0Ā%YfIK 8`1Ās1F`-Gx]a 8`0p`.18\b%0Pbh0K 8`10}] zgC)1\b%qfIK 8`[bĀJ J^W[]MV1 &p@`.1aR %0)1e;PJ/2(c(1L$1c%$0K %\bcYh:v,Ɯ4뮥8ڭRbĀJ %0K 8`@`0Ĩ#}8R1Ɏ3b؂k#޿ƀJ 8`0p`.1 %0K 8`TbĀs!10Ƅ`OJU/lSҠqC@a" C1J ̒0p0cJ /13Ƅ1NKs5{a I 8`0p@a`.1%F D-3F8}0ᬨ 1$aG쁽zoĀs b =ĀJ %0K 8`0h"fD+s%bk`ԱnC@a" (1Z (13K\bcT\Ӆcqɽ_WbY(1p`.1%ހC`.11cT0#*vuUr"}%8%0Pb-1\b%J%$033I1Jha(1L$1\b (1 &p`.1\bI:T3ƩNz {.1|b0 d1@0c̹1Lql76xp@ ˸%B7:fqx[<vMHMclϥ2{$Ơ*c3&/^e^,,,,,,,sT1l"f%sǘr<"D 1L&0F2ѓlqtG22r=eXaJ $}!-\r5aaaaaaaA1#1hs9T~SU,,,,,,,:1FJ0`ư- e,d +7nn/94$V1NX:b.-Kr{caaaaaaa)+=18̈)cs%c2{9W'VR3Ɛۺ2Ҽ7l 9b86#J_cWxzm_GnOM?W3=.}Yb>zzd{npzOP:z3ahUCvgV[O=1bT!T'uT]IB€ R1=9c|߾6߼ng߻3u> "}/&sTa+/(nb߷_~ uv")?rse<[Nd7Xj9XUp|9 ES$*zKv5^3ὅIr 9芔(M,GAHacP4ɝw$.GH|rkȁvDv+(\8Uve]BV) Iǂ1֒9.\x0d޳2a N&)+4YElA柾p"`$\S$@CIk$L㳪oE&Ln]Xcr^\,Ƀ U=to:!/MAϲf0x8|8bq? 3ǸL8H`?v2F:Zg[?Ly_q!O~<3=>CMe~M2GG9ZpŌ;4^COxh",aUJ<-U4i?O Q3"/ t``%Iyk Xn1_'0!ĝC -ƨƀf mpTFZQ0djXfJⴓnjI|D̰0C|(ixD̠+`Ƭ{D 0\`T00($iHG|c Q9cPd# 36c4Hf Rư?M{f})wx.@#]+0f*2Vi4=R< ?Sh#C ^ 2NTYg #HmQ 5cC!M1b 0c2-1/1xư8yXlM aqc)`~ /1a11 0C+ϕPWK m1/ Ĩ 1TGi33M؞L:N@^ x3㙂1ʀ֌1*A1@uUƠƌ=ٌɀ4ccƤ9W1ڌ̘ gLI1ڌ&%qHHtC7|_g?k:ug#tc_C_H ɪ5WHeEic(ͦVRrS&:ب[t,HU5RRPƪM)y!unPy5d$FiMt&䣩|!}#kTMvY4`U4JF#~ZIeS4So9I_~ɯ?4 9~i[׻9Eg=tjL$ {NiWtӦJWS9&)y:k娘t4wĜP]3GT9J[y1UN[$GU9l~ ;bN9Aoo\gOvk<{K=^߻sRy13=NygHIֱ|yoG.~y䟾?8ݷo}`u%e endstream endobj 110 0 obj <> stream xX[o6~7Gih^E( ڮ`{ $c 3GY۟sHʖl˱kcmH|ܨy5ͯ+MUw \.<dZtVdt2&{FR91Ln9Д̋~_H2.'m p#Dfd_RA&O#yw+|O0j "h&7@݅ {i ˀdZ:4iMw~,'N8Qq+vN)w{؈^oTSCۨRu)-NLT{FOqj6&#R1M'g(ͨ],sIIeUu[,;:S؅rY'FunA@jʶLmaM 6bTقAGEͪjrQ)YF4Մ%FbQ֐aU4A$Yy]y`U׿]|8QW1ZF0li٬'cj |A3L$RԘdTq 8@Eq(iќA_M2ixISR#d͜`mI-/^C(&zDk5tBw{LQi63Nߚkf¢_f6gkuziptk$Mx+YsX bh.nA92F酂w^]\!0sȧ0)Gޏ/N 29a(؀(3/]+qmv#[94$ IȆ@,w<#qy$=-4ր@ ZG*3҄_s̛wVY7ަ+T]@1; 1[Pgss%e!}lcæWȖ.TzN5ٗr"pHqAb֒؝h2ԉ̇PXdsg= &a}#Hmȯ>"C/5bYmhqyA5QkDҴ [%"҉ցn> stream x Xgsfι̜ӹwν.3vsmulnUZ"Uw[oUQP} [!  @ 7e5(O͛wKǯŢlΘߟI7!K//63"ߍA;vlBBBee% jKj 6nү_hbQ6Q#Gt:ORA"5wBF# Ȑ aBBBhL>  ܮm{ +++OAdfmK/Dlq&N  C0jRu.AA`.U|B  "A9kRC"t49SW)_L(AA"%~6dL2Ikۼ!q_f\)OX8 22щϴE}2&ݤL^N.vh7Y= <]>5_XvoC$#PE *%/ OͧĢ{c_y^WlK aYg!IcCIAg5fT_>ѓ+˧nrb:9UO1& .4\MݣEiWRV<*eȏ=wW9q{3ύ㌜ǎ} #qz/l?&|O &Ow)[ZKEg)O7Cv)_R&51&]axfDeOLKs e/ׯa.i ,չc/sʻi_8ɣ:B$#tdžwZωNk&X%)2sQqi<ǎG TD~NWʤ`mgN]%֌zm nc.Z8tq$9WLtʲZ-VC/}k y.z|UA'Y+?e̛>SH<R7{CM|s]sG2&ݤ {ls;\EwkNt5Vy&掊z$"n~A?*LZA7`{ZuUytu9;zŋ8wa.Iss5&%w3͙giR{!~2d~Z3ʼlӤbEs\s1^a^UA~qV9f,i ?BR&N53]f,C$#tÆr\.8n;/E|2/Ix#1{΀/AC%ް.1&^`0JT2qYTW2 .mP#׹1Ew| ,}Jlg,0@3@h*Xs*ʔ@k9[/[IFv7FULܬɮ0]Pϋ-Lz7]Gc_ H?x;CVZ߆IFv7dY c5 29s!fʫdL2I'o'# Di0^Z  C0%=6LȯCA!fr86lξ{_lZ "llnED!\dZ6 ;v^rx6buuu]]]F+!'9Ha! l!FvܵoUj2o) io*ۨ 6( k& & }.tLYtr=|LssS{͡#=m m(ۧ՞O-J[A6΋ _l_&EZ+&y5lhlMBQ$K 7>Hj04yjVTm/<2c~ʑ_K/JꕴE\w|',xVKzCЁo7omdfC)MU]ăȎp(?i5W_'9m_%QĔ7-Fҿ|kғ;la>.>8~Ig'r8[ʼ"S~ԦH%N^Y!@ VRT>Eez?.'mLZّd*:u` ?i[ZC_6$*l~`aQl; i 3d?aL6It ߿\Va,YYK[̅{FpfW*gX+M FlKJ:c5b[ZTbW= 3=hn< \:ԌKµ>;{v}˶%s yՊjC;)dTvM8{/GfQ$2Qa},S 5 w [p˼sa9 Kw*l9c8.ᕃۦ-e@̴>+Kü6$*ِPXea 6ۆ쁶a]~MU;2nWN " Pm^X)_'FļPT'ݷQLm?KS}_ZW ˅<ҩ͆w"HjZ)3DZ(ذwbmmmV*m*Te,&6L6iC oJa!ilH7E$}lʤW_&Rso2% Rl@& LAlH8fæ\8*3&ˍJIH2Eq)i 1S;yF3{*d]MO76O\*gFr3YQ11zL/WNmh`6D1zZWU**%LTa&==[D!r[PP s l;)iCn$۰,:9-,7T*j$"aHS][[[__AfGX1 fRSS[[[vm. xcCw\kmhmHdw+.,.їUʕbCV[.JKKssse2YIIƌR$Yx>_K`C`'^ڐƆif|lÄnTX^mRayUN_+)R+K OP( 333FR$+DR ϕH$dW}"l:(ΆEf|lԴ;eăU)]!6Lss%L&';?zvR_kxHQ]UuYdgg ]K`C`'^^y61uZ4t˷vxB,===###+G( ﷷohxEMMM}6N!^yLԆqII\YJT 3$"ef~ M-m"BG]5T{Q:vrcg{+kii۵6v6+ IY" BqVllBT444tkɚʄezJAŖw;Ɔc 2ɮ0S**2MRեh0%% |/E!Řѷ slmh`߾OJMI&f"R[kohik7&&&ߧ(//'9b׾{B&**؉76tP  cҲf~EW]# rssbcA6A/kiiy[Z:͛}0N6(n`f@~!.>>*+u'x=ҽF޸  -rR(IIsD܊ўD0g`C`'AyLf*+:)xg3GrC_ ~<Ò+΂Çt:RѨϞ=GdyF_ 6v goFfjSʩ**$Kܦ(=K%YEE"ϯ $eBVZmuuu]YaC`'NyLf)p+ ]J,eSGTz%3Rjk6u e2YnnP(\~}OKK-..,//'>_l:(ilU#3nC?߱)t\Kj:Tm۷o?zhhhsf׭^uGh4z676tPmiǯV (=E(*>LIک.eҥAAAĆk֬9㫛a?W*cX|…"?V ;yF J(666DݴvERr7z_#Jwۨr(i'UQCS͛ VڣG^zڵׯȐuuu}N؉76tPӆ9%M؆a„]veeei(R&[fAAAA\6v ǴPČmyfXbUĆR~[uSo6uOpW_p)""޽{Ǐ?rȁ۷{'O&''K$|AyLjқ7JT'#,LsKSۭ-L-}F%5-6v iZӆ)cHj}-{j~p؃4!ol< VSZ)uv.曒}D؉76(;V23 i`Ck=NјO}|53 xeC{1mX\ʌa|̼roh:jkDM) 6v Ǵ|?iӯSNMytކm<6dl 3L`C`'NyLjT=ymK`C`'d:ml؉W6Wӆ%5m xcC zϜ†Nцj}3g`C`'AyS;a /0p 6H]ϨoӋY8mnN][?cw Xm̟'5˛Y8z"l;3OѸ5 X8ԘU/I}gn>l?EӯWt^µ\ӝ =zŞ 3^)KhKΔ_`q>LkNgA-<^r ^l:(iDYOS4p}S4N7x_, ^ 6A76tP/mhE.0ߏxv`C`',S\`6[XnAl6%!ЗN`C_;6??C;6x: ?&c \属_{6v2hl|EሀQ\fTTOLj8R9̓s~>W^s>ECچ"l +ږ=;89!{K?۩yocժ+U~+K^(V=z-e( H;~O!UrD'gmwb]* l乶P1v;愨f+|7תR м ome{AUTO?@ShSӜ./.&SօE†0xm#~%i3w ګrOGK^d KG+❭1;t}⇆'g6=2˭~n+*1ܺڷK <6Ε,?}oVɆӃc6G*rSґTm>]=ao'k?;Tף/lqqϵ,hJk҆(ϵ rH?;(gn灊6FqKKk5Ӥ+Ӥc-I?7&D4y[ӤĆꊦhϵ ӳV%ܙE`EoVD 4#֖XӤ{,I'ONOmrn.6v\0-37`w9neOK_|;qMÑT64iՄ53NN?MZے51⹶ajzSo-{QXbիdoL=l4Ӥo:?~2VPB$@e0[ @flg񶆷l{O mZmIڲ'qFy#yXJG1s9Lʁec/~cUkͼT 0tӾ彺u.v w}qzˤϻ'Ij'II{mˤN.~cy#]ôܒ7)[ΏK(~9LzߩeҭSˤ/zyCտq2i2XhJ)5Lnw}c%w~\kzmˤneR_ٽ22ium܀weߡڠdr&?Rno]xϟn[|}/v+V;ZW?G_kkKWv~?=~/{6<<OGi1Rf UkjBEr2-95\5FӦSiEo CXLj08t OƥG'Ĥ&TV*Z;T::L_*drSs1qIYqY,䯜df c-I!^a08t j@&ԐM!PC6dB ل 5dj@&ԐM!y ͒}+Ws)g]"Lp8i.8=z+!Gt \Y5 cԐ219<_ɉf/'Ϝ\\VrYZΚNR[6jJs tf: ;˹M΅6jfuIssQC5q/g?8s?E cԐTB]՜y5>0s7ur*j4˞ϊx9,@8~scN_ÙjujjSB Ȅ 5 j&L!PC2lB Ȅ 5 j&L!PC2lB Ȅ 5 j&L!PC2lB Ȅ 5 j&L!PC2lB Ȅ 5 j&L!PC29C Mzl(֛srv jhl tek3{umE7bsl!Vu&mMIdv֞4R==)~mYaRif}d1w`. 5 3PIgw[s}>w7sR9fԏXæcUlV6ib< jدjH=!y:z:&v' G5c-cmcͦv׹drvfL0ʧ4fY]_bg+"1PnڱRΆ.~;y'kl@:LNPCKGNfv ^VBթt(IBh]_9dr Ψ@2M0;";|`dTlv^^XGjug+LE `ܞzN Gݞ!~|CRZpiUF]KҞU}.s!3kD1;9?d 8ui"K"?Y&rX@KKGNFdL6C:LPk8!L*+.*(4*Q3[Gxiuuz!1!h4Ũf jגxv Gj~;R8EyR\hRi "qmeC[U%Hs1Ydr6']jfg蜬rIL)oִ[g5!=M3jhMbvFn <ċbfe%5jYgZ[ڌ ]b`B  5TNpǭym)q!)²u)R6'{[;P2gF  jhlLP7čb,mq!I)%*ymmJm iA2bTB 5Vcjqs)rXyָP$^tfzF^NaUSw_~Y!Q@;E 1X_XOhw1%:3;QÜRZHjh6b`B 5G:v}u^S9ayʲriL&57TnXgd4A 5卶1<5G:[E!ǿONK)˫7Է75i{MfTQ%mXFbcٲ8wAD 5EcGZhwRnΌw>nx ]TZ,}̔PSw KefhTTVL{zzA$5 P[>ji?uhHwc7c0PD'3-3;XTZ&ת-mfnLaddWWF5gĹ*j@&'F6 n36`fOyaޜx~fFv0X$)$խUʒҺNyaDDJRLu:Df+PÚar`73{ye$pr%*yIV,mmPZ[ ;:::;;mA4}}}s!j@&'aCyPӎ-Y6vBrC8ŹrDTW'oiRj;T"eiyC\ݩdj~dkkk{{;SCpI-!q,a&rܿJJU%UueX jcZXkɰf*Jbn09A -4]d 3ZU*ʙ65+umZShEP( vvv25|7? gkJfC}l=oA|DEYCe2wǙj)ʎFc{Ei>HLNSCS^%75lІ)9Yi$7֗Qh2Y{zG4/N-b`^q2jZz۶Jߐ[3C [Aݣ[:J9):'뛚~j@&g!CZ9X g~dCէ sRx!BL zx!nUVc433=}TLRҙ)! r 5 j&L!PC29M ͒}+1NP}bf}<܍PC29U WLoz΂ɹj79LN ]M\ \O_bTVdrJپᩕR䂪-Dz;yD t5Hmg>_ #!O!jjx. 5D ijxQ?g\!I ^_!/5 Fl(JMǸY:KS{51qv5 t,1arHRS\=y$ԕ }@XDۗtK2s>T j@*Ga_`vr' aUEyފ.Ե'/~ c{|(z8hX9mJAyy݇jA H5 &$$$%%ɤ[zCOxeG+k#&K_ ='rlܣ޴W~ƭ{1"ggqEb݇jA H5 4S###%|xkϢ}9F]I]H]9^zFfkO7ئ15b>T j@*a``}msTd4/Ң(YGyuƃ௮O]uڋ:>MOe*X֗/Cj$&:/rWW+"#<'P'7\_6Q6zP ٍ_}굢'^-/ߐ>vj\SWGEEvww}T^CʪаH>͉NM*FEel_~窫'?҂3Nny).&g>_|KlE}6!>~E'x\NxxرcǏs?%[5c#ʎ6InnqPp?L~8!lF]~-q7ޛH]/aN]|$j08z Of䆇s8\.Ɗ⺺:??[uӷC^L[e}XƉRCq3 zѭgEJ\)5qL?V?WxH ?Jo](}sIr@]!͊54z?(Ol'Ycm r߲:kHk% /lNZ}\jVȯad۞̹횧B㴴LSoRu*7kLkCW>Kk]D+}9B7xzdŨfΏ * V<ga5Mcː@o teWSca'1VU>:حz|գ9vج^Qn*e7ݝyۊǣ/Iʁ8aݮ;bY\W;nŏ-hն8X+;?2;ko>Y(gZu:Ne# :A7drENnQl\_Ёv9aӁwH7S Ҕ:Kh)HarlA;=_}sy^Prqe hxܫ5!."JT-4,Аu`d2kuEcKIiEJ0"*?088$:&&)%U&wߏ$'w&8/]5ܸCIL|"(Tw5 }\w,+,\br[˨;.S[}H'ZSɉ XVD;Z jM† ݷ9w|CM Qۘ;>^ρ>-_te[3Wx篈X{]b|L^^.&ߟ]K-̤n)n߲B׻'Qtbu }z!4F;Z j8Yһ.8S;ZLY=!ۘ;>^ρmw.}b&+y,Ħ?fu.l .1ZTML-^o]CKtu-k+GYE}[$5D \ɝ QCn̽{k!ϛqn딇Ҟ8Q葐U鵷RnHnʧnQw(}`V%t.eutY=]mG\^nZPj m86j=3:;G ܺ㖧tݧ|ttE+*y]Gfl\BbJ-wPC]C(n.ɨ-?ݓ^L KZXA +,1#s YMmvv}GkkSb[UOtPCcZӀ]6x#+Yu jݶv-{wݯEe󗼕p)nON,Z|_U |+뢩KXRee Fl:>̠oJeEE5\AQ\b|è6ūD5,Whw^TŒ#?vC~K=c_=z|},==%_M]A]ǥyԂo]8}f(_̠HhQO߆*fh-l4㏻+ocةag'ln+)㰞~Ű>{H؜*#SåD-y8ow_{!Zr5upԿ&.uGL|OG+lL}vW;猛޹GEqq|iƘjQOrLj$I'$MbMjlDaQ# *>I#p5*"P."5SYJGٙe߁;ޝ;{~6@qԱ۝ KF-ɷ9. >}YD!aƶ)Gt~O# VIǗlhĢsH϶?l'<\ȗ2, 7MSw<2$n~<<gB3{9_Y`ͭi!7~[r(puug겴qtCZ/$u&-=qPj:W&8vWpQ678 {8esp<& vQ_.5lTš*&V`|cRrHy;w:H8la=#NA6<_a16홗y{k굴V},?=7wŧǎys{ǿ>170ofO<`x'' |' zΕy?x%{d겴6d].hաl)hZ"ڐ*Jfff|mXѩJ`CUT%JSgtdŰ+/7Jӌ:Y uʥwOD'zt*u!72aǨwx!콇;#|"tCz[WHw xV} 'ԳoW:ny\pqg=g0X,Ҏ ]|{چ$=۶aw|))Pf7NXe8ϩ [ihlRӒwqRw^hy.R%Kac[ Y#E+6ll{j߿{qj԰q7>aZtA6^&aV2j71}acf{ao=bnbaWmm겴eCp;6w=]Yj)mGv]a@`䚖 ]ž$U)٬Rì  [SRsRS&,gTm/~$kņkN~ۗ_O=gfsYERp붜Yc = ޏ<~g/d 3hh時wٺ,~a7luzijڰMNu.Ni[@`ä;ǪI{6SGJXKmvCJ<$I9zQg#L cgXsG36$:qUc zi>h'E~c'ee.\0=eq{~;ߥ2&1RZ\|СfOR؟ؔ?>cnaJ`CU԰;JVZ%F~94pT1ۦÐ ,5w鬰"WmڜpĘ]RRLr0ϟ),M5]p|̫SXX|d'NO_8*kwoh5ע iAgXvV1&[\>mƬ?YpqDE>[dY욵mߞ{…UU/TVLOB}Ӌ Pulx|VC67!!!ӧO8qóF#JOO߲eձ}:wܹa$U'$%%'†6@qTk;P~]AӞ 7oԐ}III7n:x#77̙3yyy999vJHHtVYER#+l7\C+%?j/]:jclHCb|ryy9ĉ[n%!hXYYYXXh2Hn0i9u9O>.H*5(-_GLs6Nvɠohpo86&> stream x{pUսNOsN^!Fu*bXim+-ɡ(wt(^.VL>Zy D J! ! !@INx$<`{̩,F >vwT*P~w˿>G4*zvw(&EVzY~^ZwOfAY-x{d6selybF3O5(yd;lxou&h$"Qo <Ԅ"PLUGZi2wOVf`*6J5ӕO\&߽$?5َÇEa}}:־)w/ )+6*؛bbRdUwjMw*oyMcA dKv&Cd;%1 5ip,6}Mf,'&V %fKB>٬N5&7b泡텝U0w/яBЯ*]3=fa-Sn*nG0;e)g k>GϑӮ-[DmΊ o׋J+$ZC~j r+Qە^e@cQf,Aca9djqLr+9C`J):VZYuaPIl9C1^6Fo=e+ۇeӐETAy¢irz3Nul9;`nV̹-.,7_m''12yPL2YZ/YηKѷL*,&w-{fq֩iVJg:R6s"`hhoT~N,F7N&GIL&l~b9RXhϑM Dm/yzҩҫ`^*,ry򐟯@ ME]&U?-?wsl‘ߏ_Fwr%VfkUrF347-9qTumhhoT#k~N,F7N2;wD|5*HbҢ=G/'̱7o? f?񀌮LGF1)s|MkӕUߣڐ|P+sLh8BGN/$7b{ik~>ղ2sn+G*bks9:l`#XUxZ mYYOSO$)ŤJ/2Qpʯ)Osw)<98bbRdgmJ1wG f~)Osw{zٟN/әe:/Hl.=#T./Li(&EVzU^m8V0Z?8qldz+(&EVzvZ'`0XBm潿cb~;ŤJ/S:a0 rJ];`0:Uۋa0 {XvDmp9$N~mommmQwݐzǠVF#~ !@{@{@{@{@{@{@{@{@{@{@{@{@{@{@{@ۍjs|P(^**+ؑf -9_G}"I~T$hjco'lu{*q{_re-%%---TCV9v |ppD=|HTȯ9n$ڞ;]NS`ɡn&/$'-_dʞn/,+j";^}9Oᣃ]jXVgC'I"|ٻ}2*Yx#-aZ93 ?&i/|&lQ?FYwN?6%ߓs~ӫoCTo5pɣvMbAaJ~a*Q6O8px骓gʏJG҇,.ҧ0ǭknکl:1[1n'c'KmlnxT=$pK qش|/\'BہH+A;-{gvKt7R7k3)Ӭ6M_k{l{2[mkmm=\^uoOj??0&=8Of~Lc51/vDSg沦]>rvug}! P083gJ0QݳTc4in$g k]nqw]l6SlgWh~Yrh{EEEIiiooߺ`ƸSh!Z!w,UVIa#f"i1ZמFWX_w6WTLάOYm5$GXcmhz5V;I 8.!A_?iݳlK'ࡧWKte:mgߊìUnLkOW'I{2E|7!PCZdO>ҩQ2gKL]l^PP3QQsgnQUSKy_잌Fɵ+XL&۹Ɔ/Ϝm<`>;| T^tXoz]X&mN̴#irG ׹Nh6D󁏂FW=QջCY\ɳZ*OBnV11~]]k/ykdzV7\yz6nCTJܱ,X*.k@m3[Z/tt\:U8|S KI4Q3SxfӤR"%q壹)̯s0մ哘[rdm(va=߷ҧ0ǭknexyKi$&>p8҃G[/^j:$pK `DkweM1jo#M=iX_v zobOvcnzG2Ŷ'u۶UO^^OV3mMt* P5D4e=KeA883 o`0i:1>MEZʳ9q&~ҿ$hZ]j{,Ԟ>hLI@ +L؄Ѱu`=Ԉ{2*WYjEEIiiooߺ`ƸSh!Z!ɼH2B-Mg eGj= dݥ6}՞ cun/?^ ceu.>KG=LEs&$X8|qŻ\hH/nCcdVi#@Jiii7<cdZ0G'I늊;v#+((cg2Ƈo12Q=GdDKumO(ۃfܸq㫯v3)BPm!|ٻ}AI9Pl=ѧŬU՜ڴ!h; -mU:D˩iuW{/x>_]z ʙ2w2@h{ܡK E8߸ ʙ2#w'>~A9S1B㎍ HN}޼yNNeNG#=@H!믿N(sh{js|Ph$Aj{_9YY$$gsmmB\>ّ4*6t/Φ:5k]AArIo5vr,˲SiVtV\ !Kpb9T¹$M`"0UBqXZkYG]IݓQˆgsQ-(Q*oԒCAp}~mת{{uB{@C"|Km_nZZG(֬%:/,ȃ11NZu;P {Fa%h;VJ _@]etB7 LSWW ~-|`]aq: M&Ak{zNz~/2w2鲤7=[颕 K|AVP;IFĭ12K-1zeWʞp{25|@3mVt.izQ^nqoܓlJl~uwfBq k{OTbnѓ?ڽ3S.n*zIP<?.;33wtȔUN!ܪf["wWGB=v^adw휰d4`FcvZDm7ߴ16PwaQڵk_x K/y2^ ^z/#=C|%U%2wemٵ^u{9ƽ SeC6mMr.$ݱi}\[\JJ/7o26,T=Q*s36nRR4>lh N+g^ƥ=E_鞌N۵kTaWUUݞ-y,uَ0jn \MHb۝k^vl5(&^45 ӹŬwq7erSIl2="8|m* &!KjhqkkTv5&̮81JY*U}F(ʧnXǐT<Ryly9J(ѩ}jN5,[(>444A3Z{&P?{=5TlGfF2wG$.?PԘd<1g0Vp =UD7>㾵sc>88x֝P )Ĺv'T @ q2h;)ookks3eߞR`c"ޤyyynrs.ٴMiH(g===========bv=A@Vh;xh;xh;xh;xh;xh;xh;xh;xh;xh;xh;Y{zZ[mFz s-圬 8緹en(+il)gtD+rs;;;q-L'wmyOJ/6 vQ3en:wwwʖr̓|ײONvQΔ͛G+TuPΔyrO>pvQۻe__u3mˁe=Ө#TԆBΛ@AD957;hus,?]VwIa}].TM$m9&X)yC>_vu0 D#j{կ"ڥ pRٹ^ۇQD]]Yjy$R܉UGr{97/nD ռ ^W=Ofp\zY(wE+}gU![8K}gȕ8r^%D|XLɕGhKvڄuDC yfkFD Tn^.8g|klCT[(72͞Zyi8r{9 J(-gsk(^rsn"m!<7/}??r6ʎjYA9Cہ=vRý{2^O h;8PM}C>00P6(gh;_>>ys=n1ʖrMG4:@Rh;pNϮ-}ꡞb-L(777//c=Ps.%` Dos?zp?R:7?Φ5pBg@RI;@{@{@{@{@{@{`:Dm > stream xXmo6nbNjNR] A?hk,Q'_ɖҤ66L#ywtS-oyENN&Ur=*ן'W2_,Wy,WYFg3xd%,MS)ƣ?ސxT1j<\p(X^ݎG0 J|9܃ߌ v+VH3g > stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?4M.[. CY {wvÙb0 JzpIՏFӋ :w־rEk,N"/cz:IB7rд94*ShNX­[r1gxO Ŭ\iv~V>M ߔqta0};# rh1>e5{ǹ2 QbB8T6ٵw[Mm08I0Cx=@a=/W:/=#NX”hz/4+Eݶekkiyx: Ŷ"S g''珈E#UͻrHb+0')Y>c]D?ӿ?30m;S+ռg)1AvTC"nO9VB rMr;-t}V"$磢 G$sEq~410m;S)?i X is^Mg!@79PI0:ֺ2E?JTvmx#cwQ@m;S*u֣}{ L/E;H$c*0X]^g{@m;S)?t?i W1EҵWH(a'r0ی295z㾼tF.ѦY 4m ,>\:G? R7_i W5"Ե/4˟*;{cP3~A V/Z$fP6NCB6|`M0ib84+.]O:~??&cDԼF4H]<(l$4 eخd\mnYpNFkj7ӟf-eb&Gv@cOp2YG^{ko0ȵc'OHl:i:G-6oKX+5- UK}9^{׼3R;K:;EY6Y :qBi[~ M;"M9t;iV UMvw%?*ખ b *]FѬlm.nm.\FxbKx];$0I\8?.9,btҴ3z=ԑvQV:+I!9Fr5iXȋ}K;<'B:#Hml/w4;?iOM ooiD!XrJ`E kbh4-+oͤiH¢4.$[@0hȾdOVq4Yi]_W94]<0ݤZz9^t};# "QڕCJ,TFt;c i$L%u'.\s޴PDs3}4 i TG4+:9d)zS>4gfҹiؚ'4(?,YgQޕo>X.jbӿ?.,Y/(+IESdh:(,YntX.EЇ)CЏ+&Kj{{wsEt ,MmFƏ$Vr3Oi6h\.t-8Iӿ?&[5ڣ=Xw2iBy?ӿ?&?J<`B|>[D)ܩQ%BB@4};# m'%:wѿF5~;hqaHӿ?&4bv$PҬ&!$4`>chjHӿ?&8Ҽ E+#b ?&hYVq5 T0';T6#M XJ?&n%Gj,T:.@ݤ TE?$Z@Qd"N:FJFzwVbdw-4- NX—D>6R :@};c iдQ0};c ֕\a_i RFF;ji?4oi U{GX`ȵAAV|.cՠ Tˠg`wquv@ q~qUu= 64?i TP:!:>@T_j\J^dRij .dؤm_,:r[̸@Z,Z_ Eww[[**eh[-%nmVhso-)`EnH뫸n!ro[i]E :^:i4nm!GIkcgG. m4 TlojC62Yͷ@jLXC?? ,XqIMlVTm'in~MֹkЗ:&pмe\m -E"L ~]"-|#JH->)'0OF{0k;IVNAkjlM m?Sӭ}:k)@SRC؂z }}hޏpI%\mO"pK^jFIs18 eUd915m5'LPG }}i<pzn+jfkWxK,P`J:go Maj3ȍ,&2+dFSf#'kl}@{;L2=k;FyuK:pwom#y ~]\[ wk$1Mj0&!uoV_nA }}hu_p4EP5ȏr A<_%jPj۸.y+\xJh}A >qR0Gcگ }i>@[;JɆ?xr|5u{j*-B:LYU p*0:sit [ɲxrP9ư57]le>{pɶP#0%RT*TʜokXn`+̛aFPBP90k;B Jv}$ڭy_7Ы9$I8ߌN)z \:}g+2ۡhO}@k;Jn/O?Ag1x9N>k/b+92 7,\p02814ZM s|Dۑ0OLǚ2ޟpn_pJ ~U,Mvke#ݘ2HPbWJTZ,2F1єu5v}/?=?n݅ K,HJ\ ?J͸_.5[]LiVp[6hդr2nO-w{V_p<p.S2Ց '0w]Řy|?SڶC7DD䷘$Q` qhyyCEq3"23: `)jv?B,Tj=? }}h 2F9o? }}h5_pwB!ji8l֞_pp{5.VGY,Te?e?.d;2i[LO^^C k=[}㴛}}h 1d /G?8Mz? }}h 1`OJz٢}?}?VdB lz }h^t;2%4հ"yןyן]DH4_? }}h? }}h 1օ:v:v({@k;E5216v#oy?r7}vbmӊ_6]37}v [;ʯ rv]R==̒I]Frp2O8W|O+1d2JٮV{+iDLd0Rc7Mk>)c[O_=RW??EhZܖ.X O崷 Q~`F2zc'ZZ㶞o*c!l#s/g;\xH` bDBm,1zz=z[n#>YHt$zYo~pET!ns ,5>ϓl<ѻ<47V6c=pY22{=5"Q$*-2@ P{^T+B J>Y\ L%lȒq)˸6s۶1뫨Et"= VR0}#޳ceG5ҼNb8f'VYcjM/ly(Q]A֯%Š A >W<M)C@ݻ8:P-ywdfc`A ˞W] ^EMmP= 0`6UEjI*8DxvGҟor#01<}|;o[ZDI=-l.%WȔIʮ+_hOٝ#?zHˌ}T,=ld 69Hr}%i0 !8+svCT>PH/3ˇ֒C)|2҇hXՇM{y%4T8`Mf vλR;Kf:Wm-ɷFr,$u=*ijK3+;>MFH3'ӧ"Q$*-2@/0M*U7B` w%+{ ݗtmwCor4,?ukmC]k`Oڃ*?>ᑓӌaj٬2z c&}7s5m/jf1x<·h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂk&h#߆⌠\FI^vjCj$y%ђTOJ "2idߒ?1:oqUp&YY 82gXW髾ƴc JvC|$O.Q.>1б{>o cG,[;Y n2Js b< ǹ^%ۙ,gvo 'MfYՔO1I;^yb8=} Eqs$yBFv.b`KLRvU} x䞵3(ӗ/oYd0UJF+y%gve (۹q[g^-,t\y57:ͪ3ng;$ |W8=qS׀Eދ"~Gʖ`eG&^; O6J$=\o Ѽ]{?fc8+8ፈ̨ `Vub;EYM$A1/$l~OSgvo &w5^~S]/;I'3[esBYԖn7ƈLa_ҤkDR檁MԠ}S"{AKY w&8\]V(dYH"R=N϶/^mP[5=|;T{89oop+.c"Lruϡ'NpIZB'~WV+ 4W\jw$I VnȒ\9dCҠ >m.)py#˩2:={W%i.FT.QO8Xdƚhv=>LUUm&pᕗBߐlly%A?yέwqk Mϑ3I.8ǩn-Wu!H.dӛM^ݕm}OmrQp[K("yd2 s/Iխm7WYY^R#j@_xW6D+}k d:= 5oeJWvȭ}A],qc5g[3I)qĜS|ci=ݬ hITdAגeErڣ$y]x ㎢5 άmo1%uKm7S2EYcIc1b0]Po U%+!As2o]8)c=ߥheJE̼WW {)8G$̘;B|T}t=&R, $d1BqIX_* ']ޙhzct}DXKQ>7/cidF\*ǹcQWLKUI$# TdZWy.9[r{%͵"Fv s&H<|)i&_*[X6pփOJz?wr7 ~`V2ds/?y:wq49XHS9GJ<mi enl#%˖/w.1͋ҥu+YՐ ]A8ub8c[,\uiVSAlmK7 nem)\-뜜gVDX5DжU@'NQIEFUYn",AIIN+@id _2Uk o>K"xQQ789n"y/$\<1I !I]H(5r)Trm3Zxlm*; dI@fҖx$&kcb*{ۗk;as"" d {C/j`]dnE稩nTuޓLUEomgsX/Pj?%χ&H+3.o_79+ v?q)MI/Sq(# W7{HZI ]Tcס ȱהjQg(bw62Ͻt%Ou]9z7Qmٿ&_*\: ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUYHB;g8N+>)DmF?7Nom?_3ZגoV%wQ8OVuXE ([4%vb `_NSD-\%ƨ9 #Ƨ#|a{g=HIhث@#ɧvd%F+ T6hjTH7wS^C{̏wmgWppZ~D5aA_Gs<%S8'#Ok;rBVv[bB\u˛c 7cݻFsں Cb ?l?5+'N18GxS_&4h<Urs]_oS?MѰ?/FPؿ”)$A1mu/]@V[ɝ#cЌW0 [ϴj]ے1(lhjQaA_Bz[E,`LP!oj{xc*#''K'G'K'PQOP-5E+.1x??JKWX1V|?_?H@@t 8p3һ&OO&&OO&JqY-RjG[ gjVpF:DCHzۈLr29jǓ'K'G'K'V.Z;6&K>&OO&&OO&ڮvZwF#>::~o.GNOnwL/ML/MoϛC/aMOڕ P٤MX]žO66Mr1G'K'G'K'X&Ӻ8&{+'?߱:Zu44@6Awkɓ~ɓ~(EƳR{vZ*f*TR W.6tM~VdރV'*`8q]w'K'G'K'Zz&g}wwJ$LXgIYGh۪Hy~ukɓ~ɓ~t<ǩ EƜ#XȰ8`tY2}*hg3?Zd$hd$h.g&yzuXE ([4%vb `럓I$ehqY }xEuL/ML/M)%(aŸ˙nT,4{{[XoTWy|?_? +FXϑ# =O=O溿&OO&&OO&NL/ML/MIDT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/M@0פ5f%޽#'mwJI|^qOFk__ Ľ/')`qkbCW-dE$??MkjХ E.lo\1W.~bDJw7K: pA5K-j=b{& >nExLEBmg<|ϧ/d;JAR§lZYi]Y;5ԏ,BSp_ZVG- BfD$ =-/?[:޳:3ƥFtRK7I8xJ[x4,P:1uql0 䲌^ LɉcC"*JcEDP@Җ׸H>"hqjl[ٱQm"?:[өx:ngwe rMvW+}4dܛpwl=+ ]7]v:MMiгEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQERom?_3Zגo^0פ5f%ޭlKr&ծ乸0@p' #=軚LRh)e 5ɿOyutTVRf?-E;sӿTOb $#cWDpRB;lw_ۚO,!?Ə'_\zޗ>h?:ti&B|ҹ8NuûSLxywݷݍgiRԪ?_'_GAK/O3~&-ލqv#FxȈV~r::/Kuyyoc(i##U;sӌ5?WѭU⤶gQRh)e 5],u:gHSʤ$lcpkJR:{t44 YBA{76ID >NŖWGΜEI <қ8 kBRK(Kv#ȑ)ۜUXn-}?ǝ'Jkv5^M>,@OR( Z?ht1hmH9Mi+^soʬy{?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J Z?kcΓߥt(ţGC|U%]:B"r@n-}?խc4 ,'XViw:,nR2Jt1hmţI4Y$/h(]\zu/:O~c?bLɦO}2/#I昕T)%>qҰeᠸfhn+;u(CţGC|ڻu K+y7U#?>SV?P?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J)k^Kzd2׭ y?7[;' #=軚85V}ɨ[3D` d|sQrj+vK\9+mK䛖uI%v8 p*Iysj*1f֖wB/46A)w䌒G#>Rƒr ?MxC%anQ'Mӻ[W<E:WR_;mIOhꠓ뎟I)_"{Eؼ?{>_:;{d,9" ,['v{H%5w̵w}r҄J4ׅzj[:OGM/D.?j햟{#;D`iQ}&w(9qx+kXџD Fe*xқ7nyӴesw>7 :/5 /х(RU5u#DiWVpL%vnbD IɯF6xeOU㳍H>-OmWaH,@ۜbǯ)bWr譫_PRE/M솇}_#9S}!֭ EvZ ,SEX_]02К?dkއF #goۻiCtجFYsVف ՓAO جk5Ȼ,>? dkއF >FΥ}Y&x[GmO5̋sҶ{׷CL$-m&Y",̥l2A8Yc(z?…/no4?ȹun,u,Y4dZW4x1FVLp_ƼF ?dkއ[_4^#(z?Yc(#aWG,w߱}C0? +dkއF >_ja?{5C~Q #]?P/?0?=Yc(z?b?_ژO}3V]/DK)!ʌBFebc686z?Yc("W? +dkއF >_0?=Yc(z?b?_ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#azoZsOTQ|I&mO[ڤ3q#!pr x js:,"[G3 F >_ja6w^oXu[ Ȏ -^ɖB(hUdFJcܚ7#Sٺ;bg.`(_.@ba'vpG,w߱/?0?ڃSZ]6l[᳞/~@g|=r؟ r ԯ)!b_2 1LYc(z?›W0?4?9N++Hn,٤`( Jn3Am"PUԬꙆl2[`y,8_J?dkއF \L&9,,.U Ape@@^94_EZ[k v9:  #]?5C~P[ek&m[Dv#Gl'$7##"<12kziI%CA?q5C~Q #]??nGQ^? #]?5C~R#c? +dkއF >_ja?{5C~Q #]?P/?0?=j? /Yc)|D֥s GR6AWGi_j6| 㦲UXbIgU0$hW% "m^J K ׿Yc)g?UژO`mI*%ٶxð+&c•㍫OkV,vWsn 1ӚdkއF ?_ژOwLwYf07,ѠR9Ǜ!9#p좩'n>icGi *h-fdYc(z?—1L'K?\e%l)4[rb@*ςoB}>V=7EO$pZ22G,w߱L'0]}+f'Ij32.xYc(z?—1/_xKߟ{5C~Q #]?P/ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #+q5C~TG5ioxs RoZ`sJ:/4T3 5I(FZ'GM#-zpיSCzTq^iOFk__ ;' z[8OY^5Ӯh͸&ǞO$֋J[3 BnIuxׇhti$Kp-t~\2 tn<+㫰E]/29a bxKL&]:ޠ`{ qW^ӣ9N+8/K >UI}*uW> }=͜zInf?RZ UI}jQ]/ 'gG3#S_z'꘏s9+ Tx>Gރ꘏s9+ Tox>Gރ꘏s9+ Tox>Gރ꘏s9|9 vm: UFp9q֓/7#ST"h؆dLx$gj2ލ)\-Ű{HE6^C$c4G"oEmƄޫ sn"wiƦ#WQ~a`q.YQ(]n v"gdV,!T }|)9텴IS!]ĒN7<}R7:ȅ*+.իYM ٥#$P oMs>#(uOr!Dv]oZ4moo<-,;]0d*)⫉iY\cfcInh:qDh*¬ʩ4ns4WG'ğ U(:LG? OxOA}4$2k2VBawaCo|7dbkR9#Emr[;z j/g5o_O;]Sw ^}>YbKl&gmDK3#img&" ɆCс28qg߭]:79̪PHo৒3m78.`I,W74)_m}% *Nsn&%`-V&a!ld#=A \H-wKUIt=Zw}As1r]*qn8~0ͬK|n#}Wv*;|k~nfr٭FܴsX_Zgr">Z2?n涀YkIlɌw8-sM A#;ӏ ٴ3TmM}By?C>_yjӓ? {iY$3]GQQT*RNO\g)Ssʁks4n GD- c_xyyԓ*YK9['zkxkdMS]?wv)Ӳ\^`ro~Emf%V6-ܧ<6Q/ȣ9n}V^,G]6%j7Z#1rq q17GގO?Ȳ2 0,"d灷Һ24ot|wv"J,)(pb1^ xd GT9WKVSn*kR哄3]eVޮkNxE\Pգaú0de@B0O"oЛm!@n+nlgwukh.&ْ #ܹYQ!g9f-9=>=Ɛ4=K6 4Tގ 7'>kM[{7_i)lWFԾZQ]K=I]8,| M̖uRٮA|sSPţxY7V;ɻT ǹ{jkSi|yӮ Fdd'{UwVtgӴ_>[Ff N9#3c,lf.$_{+IlgϽL4_?qTSK_or|0 ۤ,dr83'=1VCOo8{t"_)Y2IMߊ.S8Kt9-}7LZ dx=W})ZvKm܏cZKV0l5-_HcO%V݂E` }mb;O^)+ Z89A~;[׭ y#גo^vq+cN5|Gi^Kx c꺝_NSD՗]VI蚲3:EC@RPA JSI@%)(4Q@h@ E (E% RZJ))M%(4Q@@ EJ(E% JSI@%)(IE(QE! %R(4RPA JSI@%)(IE(4QHhJ(4RPIJi(BjS'3M{# {\pיMF=z]q^i3FO_Kb^{85ifz/sU"?nDշ]t4* J(QE! %R(4RPA JSI@%)(4Q@h@ EP(QE!)(I@!PIAIEJ(4QAJ(4RPHii(4RZJ))M%( %PQE)(I@!PIA J(QE! %Q@j~?U.Iݽ?8k>&i^kze6q^g7F+__ Ľ#??M\ދE('#5軚$h4RT JSI@%)(IE(4QHhI@J))M% JSI@%)(4Q@h@ E (E% JSI@% %P(QE!(4QAJ(4RPHii(4RPh(4Q@ EJ(E% JSI@%))M%R?ji?41[׭ y7Ln?8k'k^kRؗG$??M]ދE('o_.:IE(@ EPhPIJi(@%Pi(E) QATo0^%l_ZAl_ZO/[l_ZO/[}i>ؾn}i>ؾlU_/'ր-*֐/Z}i>ؾjb Ub}}h%Vb}}h%V7I TT/k_ZIU־k_ZIU~־}}hѤk_Z>־dU~־OzEFOhJ(4RPHii(4RPhQE %Ph( (QE%R?U.Inc[?2Zךo^q#zpיQCz/sI 蚹'Ek6+#?DV3[@T(4Q@@ EJ(E% JSI@%)( J A<\%# #m( 9'ҷ vWQuk2YF|}iv&솙S*O\ 5͸?2qMϋ?^uڶoVvK!!u1hc$7Wee9 B_*#|YBo(ϋ?^zG(Cgş/vr>,~o Xj}_[Ey8&wVIIzQʃV|YBo(ϋ?_z)YU$\3o9A>,~o Ϯh[qEfXKQ*Ic"fpW@ .RoWeo;]B*3ȃ6_ 㴛U@?.W_{qr8DkV0 #'LYQt (9#p*|9nOdo9I?v"FQFYj(70G=,2(t2AuDKR]IvrLTyWDFr{S@)?.R_uӁ 3vv'3K^32]+ m+g_ cv{4ќVq^eBeoZx6KlKܷ"s 5wo_.#?Db]QIPPPhPIJi(@ %J(QE%)(J)C@!r]k rU-^-493_j /cNO߅6O] Hu8Ik-*NIO;sX╜|1gpʇav39lԞ|^ٙ-<$P]lt#](2+4w?oo_J%Rż/BҶtXɬiEܑ6- k^HbXm}B'waLiE 6?W3Ӵ\]Cm1gqtb3P3p uq},Wƣ^;K=>XO.TL)ܼ.>]ioߏ:-B3M?.`P2)eqֹ6>,; ;.Â;ݛQ=~n3UٹyQoh PDӁS2Ph0p4 ~hKHZtgwrO\ywY-m!0Aq9d\Z~wa1JHvk4OiA@=/j焜)Q̡FˑbuQ՘5 š^yPyFR=?CO]DF &,㵩&2{u?/ &Bt*0yUgCtPIJi( %P(QE!)(I@RPA CKI@T'fsO4̝~q &s+ ɲ6Jm^nueaٮ?d5R=z@Y/|$=FI 蚹'EjOSD?ez/sDIEh@ E (E% JSI@% %Pi(IEiii MW5s^?ݵsKƮscv-Qܙltށ=A*ƩDA$rIdcV?'R#ZV JgLcRe\fu{off|3p1QɬyݥQv;"o컟 ߻5GUoݿmu[[TVhaIWia;7ᚻKqA*7Vs03?n?3}~7vj裙?/ݿ"s1oƫR9r(貞T9ů?տz(aʌ'T-A[oƫb|9QVjUEϸr+y~/Z[עg9Q'տē׿Vr'_ ߫5G,Vj*2eTcMAoƫV9r+o ^߫5G4Vjh7/տo ^߫5ZQƛQ7/տZ(adecMAoƪ'drF\ 8Q ݬM!rۏ( $xׄӴϸ+|'V^}YlAPhI@J))M% J(QE!(4Q@h@ E sOZ?_@om^5N|Ci^kz]q^g/FO_ Ľ/'`jܿ2r+ U5;%"C! zpAShYNz_SK&rHhN $~͚%fkoExI=(PfBI ѷUe;CL ~^)utW5%c 6uxVXߘ ?zdcCcsn,8V&̇Sti@bDj +. O &;J+n[/XRbH")V6 z[Y b &bƙ1;98ips}"ѵןTY⽚(aHcrv;}L %uWD{;J϶e,bIVʎ@]g{yvWs=uou[o|ގ) vp.2 C| mowgkm:\FT(NI9^KI?:+7)}z-m!-L*ĠB7+ ۳zjYiIKXĊ`2 y+;Aʀ2!-]Q\5oapI,ߗ6 J)*bF=2NޭPNAԖhF1,Il`/9;ukВK4"HQ6~f+#' ;Q[b W3Gqmq2yP+sT:]4vW#/.IFpfXMv 9a#:Q 6]_[tG @O9Wjb]#ˤ}뎗U\@oJ}zhUumW\g4>x-mi& k|ƪC*G嫎rY{8(|e!8Xa IqĒ=t+,~9ZIZ(4}CUѬaf" D47B+ѲG^~͌֗(w6II@~vbþFpw6sYe[B_c,X7+*  QEcAMHiGW>[ov,Xd.qW`ҭ-;F.n@bg;w`j\ 5ͩ6a9eiD7Rt2F0>`xtSGyopz$ H95Ee^xsK市Bjl,"$ 2pE= 1+q4S<=^1N9MiQ@&Idh&zD/a`cssQ'td!ɸ[4eUv ߗN+r62u.lM+"]J!fnb'nsZn3REb iIX (1}q>"kNL}+[ D&.$Pyg!d$qPEtG)9qu,ϼ!@K;@V`8u_OjR[QHaEPEPEPEPErVe`$L83ǔ\|xN`cm˟3Gs3ye}'~ v6[|1zo\g?9I|+ʼnHcim阏MRg9}=9o\+Kb[hCfK7H[ mgy&sm?ru 22Ys_%z~3[׭B]%ђUGkB[o_.d(_'o-ދE1ݤ4aIJi(@%Pi((4QI@Ph( RZJ)4. s~ ߈ݵsI\7mPaΫ_I"J?UV)n8QE!Q@Q@Q@Q@!Tq :qW.c_qYIGCj-klhQEuQ@Q@Q@Q@sYۏ(*4ۏ( ǕWpWxS<ʽ7L,(tIEJ(4QAJ(@ EPhPIJi(@U+uf\_:h WCq!/!?_%zaN2Zr_%Z~ {HO]T2[ߛFKw4OCE,( RZJ))M%(4Q@%)(IEQAn>s'~ v]&>Fk ^А Hl~upvZ?|"*Ԭk.oOgIY 0C:OoJ'oQwEdqo?uym.WخdkX@oho;G+آ?? vW9Ec@ym;G+٢ ]᮹;G+ע?$MnI@oh}VG v?{ms#^;G&9_`F vMr̍z+?ym! vW9EbCPohw26_Hym.9_`F B?;G+ڢ"]CPoh`F U㴿^;G+ٮkM?_҉*$ @oj1Fo0#y/lK>E87Ek+a?q+bo-ދE F%T( Ph(EPh)(I@!PIAHzQEenC^C}jircew$H%X2+fx5sr` <8 ]CaSb U_BP`W%܎HO9g?~ OBJOJ=${?io?`Q]DZK\oOOeqcj4`Gpb'и14KBi?٣KrGHxQ2 2կhfi.Xжch? g?fhA  U',I[?15?4`GpbXж14şj٣=${şj7 mS`G4{IwH+s?|)qcj4 =${=4y' V٣ =${?<4{' V٣ =${=i?\'4{IwH+{' hO?aG4{IwH+' K .? MO_%9#؀|A̸15GU^ڽi!I3Hz;T(#<MQE%UpJbڂYiȾEtSGҭJDVSGҭQ@ QETPCh}}**}}("UC@~Ⱦ}*%U"Re%FҚJ))M%Q@CEPi(E) QI@J))i(4UiJX_:h |mBo_zӳ+ۼIͬ[+t--&bCFI]0._3):GB>Acz/sXv{c[s軚GR6Pj ) )(I@%)E% JSI@%Pi(E) QI@J) -% J J(QA(4Ph(@ EPhPIJi(@%Pi(E)(I@!PA JSI@%)(IE(4QHhJ*ҿ/V*ҿ/MRkb?FA^I rڽ[!dXlM.l6 O:j z!dvZyoؔ½CPq*1_.s??E^F8?ދEt* J(QE! %Q@h@ E PhPIJi( %P(QE!)(I@!PHii(4RPhQE %Ph( RZJ))M%( %PQE(4QAJ(4RPHii(4RPh(4Q@jҿ/V*ҿ/M$׭[ yWȂc,FI^ψmCFIT!zOSDUc]g[>_Z3軚$8T)* CKI@%)E J RQE( Ph(A RRJ))M%Q@CEJ(4QE) QI@J) -% J J(QAC@RPA CKI@%)E J RQE((@ EPhPIJi(CJNj !_Κn?8k(i^K$Tn?8kʾ(i^K$[=8zz/sTz"#Eh#hQA(J(QE%QAJ(4RPHii(4RPh(4Q@h@ E PhPIJi())M%Q@CEJ(4QE%)(PIEJ(4QAC@RPE (E% JSI@% %Pi(QE)(%_:! +t6q^U@Gi^K$Un?8k~(i^K$[=/'`q*Pn8q#Eh#fT(4Q@% %Pi(QE)(I@!PIA J(QE! %RPA (4PhE% JSI@%Pi(E) QI@J))M% J(QEQ@CEJ(4QE%)(4RRJ)(4Pi(U_:BW:;mCv2JMDq!+s+?_%R؇lG?Em軚8zF(?ދE!b)* QE%)(4RRJ)(4Pi(IE(4QI@J) -% J RQE( %P(QE%)(4RRJ)(4PIEJ(4QAC@J(4RPEPhPIJi( %P(QE!)(I@!B:WsPI! +tq!,# y/WPzk'+O_%ZH{ (8q#Ek*Z1A_.攆IEh %P(QE!)(I@!PIAIEJ(4QHhJ(4RPHii(I@!PIA J(QE%Ph( RZJ))M%( %P(IE(4QHhI@J))M% J(QE! %R*?#_Φ$_:hFo*?⣴%ђW.ϭ|EfA%ђU-{ű??El\軚̉qD@s#EhѱIJi* RRJ))M%Q@CEJ(4QE%)(PIEJ(4QA(4Ph(EPhPIJi(@ %J(QE%)(4RRJ) -% J RQE( Ph(A RRJ))M%Q@$_:B:WE/xuKg^eѰW|@yu[9ɲ6J.5ke?q &h#,?t=N#+z/sYp ??Ej\44kEh@ E PhPIJi( %P(QE!)(I@%-% JZJ))M%Q@CEJ(4QE%)(4RRJ)(4Pi(IE(4QA %RPA CKI@%)EQ@CEJ(4PhE% ҿ/S#_Κk^ݷz+ʾ#rFI^nn?d_9e^CFIT%z% ?Ej^Mq%F@p3#T顂ϥIlqhD_Mhc@H?Th)Oc@H?T}߈rϽM{  QA~"@'MnO)>c@H?T}߈jϽMoS} o&6?EGl oS} o&M;6?EGl o} _&>/O  QA~"@{bϽKԟa$*>c@H?Thl_9OMKA~"6?EFE>׿/G^MKA~"6?EFC>׿/Gڇ^MMA~"6?EFA>׿/Gڇ^MOA~"6?EFWPkC}_&}߈  QN׿/Iv9A~"6?EFVO;^M'jl W{r4}_&}߈  Q>N׿/Gjl O?{r4y}o_&}߈  Q>/I9A~"6?EFRM'{r5{6?EGl 7Msϭa$*4{r4y>/Wc@H?T}߈ 5h_}o_&>c@H?T}߈ 1h}/_&~c@H?T}߈ 1i<K/a$*479M>/Za$*>c@H?ThfK'^$Mj}߈  Q{Kt{5A~"6?EFen}/_&ϥK֯l OI3'^$Mk}߈  Q9|_&2ϝKֿl %i3/$Ml}߈  Q;{5A~"6?EFc~|_&M>w /[?a$*>c@H?Th.&;ϝIl $i6>w '[a$*>c@H?Th&ٿ$i6>w '[a$*>c@H?Th$i6O>W '[a$*>c@H?Th$h?^$Mn߈  Q;'+/a,nݎIu"/9--"dGHee A9 :FA^UCZխD~?#CMyw_ YאђU-{wZG}GYH7:9-mw؋$x<M]ᄾu(|֊bx˜##!n5?Ϲ1D̿yVBTFnuz/GEi$ͨI_ qHW<5(yg>>ئL>q#o[ifoym{#g9;])xEyn$#1ìd w~ڬHDC/̎WvOo~h\FKGy&`ʊdʐ"NwP:]^\#ƒ+=V64 Q![]nG1u)wki6R*~Ɩ(u^I.N65 \:o'_PL坷 'KjG?oV[8}BG_EylUضV<@$#mt$YhыHU9];fa6&p-O"59mХ2S=E?X՛IŜ =Vʫ rG=r)imᶛKE3O xBv.9w bxKլѣvi`0Lry&_#v*1I'j?dAN㎆4KpjvH$@:U2'I:ƧgiI6\9BHT+zrwnoy翂G?/* /=^ֿȋK񾙨pwp]Ku@?):An|u ѱ6ߵI< 1~f݁n8,A_ii.XTJ_ psۃTSSauy$oݍ<ŭ7HeSQjpA4oS9r9-?T_K]FHMm*7&4sӅJ/i -ѻ Q,weL*98ڮysmiZÛskI'ZWg= {l'mT6#\hfāa2G6@5t[_h-X4$aeTۺ@d^.17_}>nMב|Icn0q9<'÷H#\HJ$QF_%d-|Ʃv^WGgQ?#?3Sv Od?\ΣO4GgQ4ɋ _0L_ZWGgQ?#?3Sv Oc?\ΣO4GgQ4-Oc?'?x$zu =s:?ѧ`/ _0?-|ƫ#?3S)ƍ;ZQ _0H j?G$zu ND`T _0H ?G$zu N ڇ?&Gj=s:? AGhӰjzVRu P/H ?G$zu NvA[5GRWGgQ?"?3Svo(?~A[5^G ACh\ΡO4iz_Th)Aƫ"?3Sk?)ƍ; S[UUk?)ƚ#?3Sv OnnN#Cn֣O5hx\ Nsn?1|͸\֣O4GkQ4=Oo͸6nC=sZ? AGhӰj{k l_0ԮU?jG`Q˼ j?ON׹u[Ϥj.A:#z j?Z=sh֣O4=:n _0H j?G$z N _0C\_0H j?G$zu N^K_0H ?PK=s:?ѧajz ~Pxk ~Pa=s?)Ɲ AGhӰkr_Teo(?x$zu \ΡO4iz]VRyU_k?)ƏH FGbߔjZWEgQ?#?3Sve?x$z MwZ?ѧ``Tm]֣O4z N[n-|ƨwAk5^- AGi j?FSڱwAk5I _0oI5 j?K AGhӰj{17bjdUzu -s:?ѧ`6ߔj6ߔj{-o:? AChӰ=;;[ΡO4EgP4=O`o+}Aƨo)}Aƫ"?3Sk?)ƍ; S| _~PO6j-s:? AChӰj{}AK5GAK5^? ACh\ΡO4i5=̿Ϳ>"?3S)ƍ;S< PO6j=s:? AGhӰjzAK5GAK5^A AGh\ΣO4i5={?)Aƨ _PH ?G$zu NyMqsq Cv|'z^^}IaZCkg!31v>:kԉƩ{,20WKeaȯA&(V8^W? endstream endobj 115 0 obj <> stream xY$Ǚoa X0@JۀHVvmJakw0!e^ΈDΐZ-i=3}Wu}WVU^UYw]=?"{TC 2222*/g3F7Z8E11wVzmE-&vR7JR?Sg)e$(= -wP:)nJFP+CHS7 BuG\k3y.'[w | lu KgԳ:JFq8*"b?$|'ejJA/l{NfՖYud֜ waS@ "~X MAJL~~ozuw*8%kfђZ0'&bs{QHGGǖck5`.N`.Z'73-X R8jޜ;}h99{̩ %Ț}dele'7v-+ӵVcjl˜lEխ3yxK|ގ[alGw_ؗ~b0=ka9%W"D(ӱ]ܱ; m5׷0lϜ$PrB+6w@;hހ{ .n5y~ßxx+|St = g@P>& $ K& E$@G_k[Rj I>a.r V1cĖ[%gaɭU7xuΚ_dºw"^nN73b>qNo! G≏ǾYXy7$m^~glɞK6Ȓ=H0ٰfp:x/%us "L(Yۏw҆WXuz _Kf(=O +Avc ىΘb3qd/Է现!>={D>,9U闷%SXݏU 5sfNա{GiسMGNsnz~aIXEQt+gyB=K$_>FD CNQB9b@LtaG~D b/*]إ;cbOraXцU}\CNj1::óWFZ>'ouՄLudM#tLk=de`ZV);gY jg{E^in-׷+[KrisY&Hr5F8]lVog>UNnB%LI z+x3*HE$h"pq@eK  MHIԆ4%#0t2nJP?FqNTƈo @\VFQ{r@errk!Oʦu\e+u*|>|/B;jBÝQmqɗ6ugvÝ쎏 aT>H A nB Wnݙ[gVleKj(`N,ͱǘ&-%kzɖYed{X&`ޖYP PPs99Io#$ =s|lN-X2(6fQXvqH5m +RQߍ7579p?9D"lHEs4NQ̀Q'P\O 9ݶ2=NHEn`eFq$tdAz6z$WW X>!t +@逎cCuFAw{:䐱QR>C\Roc5Y*. 0.;0u+<ģ{*bՃTӒm; }28 gJEz}F;J`q/: *XD+؅1vD'%_BȗߍBMhp Ȃ߲UuTP@*0:[W%Eբ^t;^`JA"jq+&).T^q2&KDA*Љ8B^V?;)5zf9meuO(uKRoߝK,6 ͍mn.1ςTI;돚|ee2'Jťya?itAgT.7$"aHETQ8;]e+|=µb1ΐ&RFErb0%![ҥ"#3h:b;eJ]8$WқjF^ _![rcvGB8gp^Υ6|,ԮR/b5 yKD.xLij__K`胠]q HR50ǫ{ae;P+7ɐc#dHaKF )V(oT xz|TQ\^dH%]?M/" p5a xTB٤Tx!Xy'$Ra=NϙQPH >%"tBx"ERC@؍ak+fѡTŪRfHlb1+tÞm9͝x ]Q4 ˣr%v+_҄ZF j*FEL>DK QE-"BD"t# LЦcPt;@W!kK!I͸DgxGGOv}ϖ hwLZX9yqR鳕Tv׏ƉMTjpNxt(mC-΍`gHl,rIP*2Iy.4Ϯqn'\E8WG(d v;6']r%d;Q s7h-Qm ő(9%GH @%Kha#B &oěME1^?g250] eAZmϘ<"`8~~/^Hޏb*m3u;6FT1u'${]]2bΜa8@@8Ed@!G  Nv/{5D*T*8QYQ:&;qm;܊66#Id'܍a el~ϞQp aIF`D tad6,;aYQx,pA yd! 0a a^K]RXe7T^bW 0( :1C@-` C]ztHDe7r%yh-si9<"@XGg #MJBfL@(OΚ8xP9hX Ȧp)H$A$P'̉aN27' *+ e45ǁ~C6Zh.P|˂Z ,@-"tBU*NDDjJ=3 8:& I;aBüD0vP7{Oa.V:RP\)4}bzRy6Z_ OIpW_Gk '?cهy`~q4{__&私63;}z}8O+sϫWf}P@-|7SQɝRIEpb@7Se+\kŎna- BSr/_-0J;'(cYJ;_jV"Ws\Th b<:U4'.oW+OpKhd&"d9@Țe;.ι[;-FF=ΪL1Vr*oUAwNT٪/W1UM՝)CH{PI#5jTБ.#(~lH]B:2`)X/[kjOi7s=g).m$ Jnf@0<ҙ GpP-,{ -$0P5tAUPEwNlǴHs-\_ Ve`%PY U7#hkśaiNaj24  bFa&:pct2(#= >9JG$} 1!T!0lz BCk F9L1  Ư^Pr_D|2>qWPdAY3-6(ɚ3%.BT݅iY +m%2ч ҥm2Aqt1ɚs50tvpT N⚛]vbTD P0.2 ?YQdUqZe۲.ı砝UN/n0ݨJD&zn¥Wj^ B Q(Qtӑ  Z\A!!FeHiT: 4} i/D C7d!Chq^ Z q4'Z`)&WnPUն8Zuz8O d ?;)%q}TP] 6KUA 4RT4iyOӟ?Ѧi_`:yFJIk'O?~~{ !=rs;(׈ GU?SgUGfpN Rr,bt(4.AʰPVlx͗۹sP/i(:\ "WzBST\:QFTإj_ 4r,55RQAHi@B<lIAH$Tj=i ̟"M."xuFC$yO:.L-N :̖q5lJB35l= +f uJmznyL<h*[lyOYu |Hxu VTaꄆ7[|[x.Bzٮ+R 3KAe_[T`#L "P+%݄ʡ$vXݎhu?8LilWОZQ짺x{3Z 5o呧t,ۂZX{7L׊LH=΀H s$H%y; {utJ%t!]~iAGQzG]?Uްk$mBhhi;.Tk?FTw!Q)Q8(k'W~* 6wC AD5ǫZE"9A`H1"A:)C C"0 = w ) =7CF&螼?QZPl)p4_jVd*Sj9DjA(H_7%;ѝGwR;ٻwonW^U'by ujnUɁ pt=[Ƿ }t+ѭ/K/ߋ=at%턨-Ʒ"\"lAQA$JkE-ku(*t*p:>),hmtrW;|+TXk}HJN@*zTGZ@(Nm(d$54h 4E@\eD dLF&Oc~,ԇ:! '@1:s.J#*>jpj)udJNA0Z yQԠmm jƅ&%& DJ?-QW>jUw"6a lp/ǫu 4 jLL`(?@lFPcWsʌM__u—G[q)/ZVz@A `56`8k>04*dQ#@? :Sfuvh,z e;ap6ҤB}J$aX%}}Kb8dciG p'K\  +\Nk»$D}I|a.!GTqJ1@C1]JZtSjʀU]3*4vNB/j #SJh }%WPpP=W(~Hk .\= T 3!j6d =Ħ'|󸢵u,c!TK31Cy"ړ$ƥ]Y|toReTV I݄܋K]={s ^! ۵V{IL4u^f ͵=Rrz˜8(t僱J578vj.j`_Y/ovkڔTl>g✣U\p?Y9n. ¢[v +^q' =6H С^ܥYt|+TFAA0.׀C6 I ҦB}]?"Bks+#:#p! 4! D͖iYH3Ă7f:_@{2çƴh8{xC*(͉>:b.\q7Fg@ (L^5$~!Lx:z2\KC-pR7fr\c,)^臞tE..#Gץ<^ R1 \lG>`.nQXWUƖOK8!R`Oa{%t7ٮMoM5w5uL=τg0ߠ!en=dӛ#@E\ 6iZGAPjK(?\0Ň82fD #;%P{&%iCyAf^(_Hvk׃~oou޺{fὛʝ;7;)Y؋8P$5h3{믡ĭw_zסgN nBG 0#ӸDQ!RA:(8뾟MMB0/nL.$f?TiP(Z z۴Iڐ3X!L.VN: T҃Tw'ވyweƦ?,~j;f̽]t+Cn"ڄy;.: #+3gɒO2G9 3odZǒs`&P[rB6^xlѕ$$fJǸ𐭠1opŠ,y-Ae ` "s jZM`.]*ja`( dL .I5 5ߩTX 1t0^q"x`ʏB …WLJŅ`lzEN$yB.9KT-9!!E IvɎu:uPưWtAԋX?oQ#cX*⨗py> bٞ_-E+,YsPd=\o<{?,P%7x>|Ѝ׫AWuʷw_K/lKx|΅TQ0CKqϰP"K3̘ޙz ^䟃eY4d꧀ HLM+Z^a?mgWyy}9sf>$N:!d }$ 66`,m: &!H0`TTR*VUid;gy[d}=n{$z,t`ƋDY rM'*c%7D%* (pU׺nQ/UeŬZ>ɝ<,gwba?/Y+[^HVZxg:ԡ<-ůPuSAnS;_fśYv]\1\BxV 䊰ɿ60`ھΫŝ(gCh{(Lq>}z0{L7y/}wwQwo |/r\;G'gSlzVΔS:lNP >҈P,> xO{N : H,fKjV 4ĀޘXT}s,낏hP&(\UWp Q 0iM T?_Ka:3 [bET*^DbMDH{psD. h' HJAh5 ZxmbXӂ(UmYuEo`.Æ 2,3 "­U/F .n&>:lVsmЇd:_.`i4 F-:ɞp7pQ{Phv08;B R`C$:m)6 _Ӷ`o˛|5 rRY' [ȗLܠ/V~z3ʶYǃǚ4G7 h֞l~>kSߪ ?BtReO|o*]o='^  m֮6߱A㦛wlnvQ;+_p+›Gpӝ76 wߴ zͷtۭW@KUĆ 0FnI{ܮxomgʺ9ZüRʄ*RPqщE%QMyL/@"BEn.1AE1:IPqytX$V#]Tl?:>źYPj`s]2L#!2(qe>!8xͺG>DV3E<b? &gCS&< c*, 0'9XAPWs(8 ^zդ]|QfIkl[YQճт8iBEQ~࡫x!+J$m{g+^PfM7"XZIUlI\pi0*,ì2UDԊ/;D1Ah+]N2Gy-Dn緍nۍ> DOjt30h6cMd}O<&g ~՜ZJ!!ATGziV-69ԇ^F^B_K @JS>T-#4>_[oy8J2OqY H!tKH8$^#@ Pqώ-b2R%t8l~# H|jG]#cyh,V[/Nb+JskoƟЕw?AD ZpNPVV|./_Y`jF5MʼD ^%;>[;T6r)W$bq#2N :}'0È|#JU%uE%$<9%C؅~u*+ZQs<@эK%\AZ-@DZ%A#+\^@E5|P<8#Յ"^Fi^4jẔF`N<89:ߞ}‡-+ͦH5=278ZOA6H0NBWo-V-Sp-0N9zO^ FВ`hqôJS sJLc:`o1 8;B]{cZ -ı&xLPqb't9cx14+!Q8l"A Kr@P9p+-E*)0h1Tׁ iaIpŒ$ݥݴ@ZmkxhH$5!W+:70c͎^B9b<,t:j\^k֌@O>B0ZXڱ^oWdw^5kvtݿ-}o޿ٰ.Cwc?;?#upσa#i;@=wX1ÃwSSWo];7on<3tBPaxx,O&X">60p@0̄3PbBD*TūN(,tob 5['/~bW:`bl_H8KY q T/zS|2 \L_PBd!;-ve歧w]P)h625~#fČA5B'uƥ>8$H @ѰEv T!E*V"Rc$` ,yԣ@U cۮ#tp4Ժ(g@Dc5ޡ*jk5N2K(5 X,U*ahs3ǽ;C'm6~]'})C)~a0ވA ,T@<8)٠c 'B:D#GP<@y$8}pvzD. l9!.ARd h}p:bYdh)GՉiQbW/6'CX%OEȿ: S!AMTJ.OQD]$sF>A}\V&Y J3680cH$"9:mLj*Re^D8 EHh3w\l=cUq!Gt uB `WP*j0"e*W)s>;Z@Vy ccC>˹ƐA*8QY*DNV)ɑ-g rMqhך >j9q*V*= N}4R]yMI5՘^e}vͶ;JMÅsI}H[6it~~}4$&/SM h-&sa(9C,Ln1_U.>!&}3Z\03aq?1}B'/BD9ɵWT'vYupCJ=) ĮUtd{]X\4F *ħi\kY$!\/d.0-.Ld|Sjg$2ƒn3hD/#4Q*\(r~ӅTgk/g$IM}["$HWst*kMeR\q$HD᜿sV3Fj'?%lA%ހ)7>^)) 8 {pIT8Aȥ{ ΚH1J8Wlk0hKAEʉ(zmD@#˵:WBGi8n Xx*9Ģ0WѓϚGv7;5qx`t]~PPd*`gϽ~BY,/g(M_vk~/>2{|[~<6cs=^G/=xHp#? ?jGF{#} byQgF.^v×K ˀ<("L&o/v1aXz6_ GӋQj5ƕ~R ZF9R? HbS@H8J TئK ~n~쎺{EEod"o*ijC/TMpC4bIUnǁo:F'52@ol)-MeaɯdLQN syV:/B=Ze<ȟ◍hU1UU Z iĬ4P` \yO|nD4W`HOeOMYI NMWqzrh~HLB: ;pW}\``dE=7`]u>BM$ /wNV(LAD!r+c&jU"X\nz>*Eo=,.X2ǴO"u?y~v?vGNgS-M֑LXDN#iXak$z3#: l1>>oĶSlx%Y'5q %"Q &PSd{)U?iT=Qћb$K2]1C0u.W"AUK[p-T4@ZhoF*0U U &#TPB_ 'xsh5K.UxP+&*3 ( <9%jrMi*C2}uCT TeD1+f[Hg:E1X)fyym>DEE $;!q"t047$U{E#5fi&.ԻszVޚC [BL~܁EЇ^{w t~ XB} [Xc Ǵ$H\?Џ Ͼ܂a, 2D[,*! a6~s gyu}ï{}o}o=9l3*ӤbA? zS7v8ꙑW>gArϙx= !@h);O'5 gCp22> VH=]d hT@dv;` Ta=.ᾈ خjIVh,E=Q%o.~МN c+a9/+i-h!A!xLV*Ơ{um'|ԭVrZ){T^Af.G61#ɡf\HUdlM1-_{S4@g)Vs r̢kL|TS'M$Kmplcؒl&]4FІP+ε4j$b hHXNguh^L62&Oǵq] 0p)u&wb be-ZI i` [01kKw1,l ͘i* Iqht:)XϼWk~Џv<{ ڵ{꾇A{YFAW|_B;7|q _//W_===ƇXCoqMՇu7PvWw}+;{7嶯zRrI ?6z/t^0ȡc@0:ȑȸgCb9ǽѯ[--ZSX맽QՇe)ieI\!FЛYc>VyqܱY)y?!bhvXE @mYor6QBA#q$KKǂ,­U*9*?WϩP%*'*0Q$Q{ih("ksgf-~\{Yl+[[y$6Vf)/,, `u3$ve1"Q N) h|pRKPL qf`1]>" 5+: b NH!e YY{ 5trh+[RtgdzG]NO!^{"^9_<Z*욤7enP'K6=gկNݯiq9S\%;:7SuX ʾ*dcE}HjP<+ʀT&T T+T\Bs-1EM1}IrfYX'S_I%F \VˎS0# %iP@1cv2]h;d͡;ިvmqa85Z\XKfXKˠ j~'ZjQu^CZ%rnor4%kUH/͑;9C=h(8!`)AhpBj9~lsigA**s@j+<*$Zi(&0H(%!9eK%$>LVqW+RlPGs*L NJF+RP)QJ*;4=1sEy!*^3q" QC]K%ʯ?Sgʬk%T^GϖQE, KLUܓeP8'Fe L-!j hZP\+z3Rt6o`Fq,iM&uNwJpf}pQ}`w  s1 q pPA`^% kI+/עcsgrRE9ZyWkYK=CҗV|Ug&~B#G{AVZ)3:-ԯƭbN+N!a Zh%~6՟/g(5 /L+o[Lfhz ԫ,I 9SC=pvHT Qp%-I>D<HMF011`< *i41bmdفcpf4 P "+Q0B+AZ FFq`DqH5! ,d n}vBp_=:FFǦDgi)@O.]K˛^RKgn5 ]+`܊"Wv\fL\8#^rPށLbѰQE"i=QT&E%d3Uv&KK ''0@1х! >y¼Jt`r.J0BK Wh|Y`W Y$>qyf8·tk^"tt!4@@BHpwb2R:QsĈ~`e,PR*tbQ s)&/zp^>%~}jצjY+Nvptq\~rH J\k WvZ \!qGz1ѕPE$HI|$>TKCEY]?sId=' 5+ v9D5o'vh6"EL 8Z56Y40R`X)."95jbEY] WD+f! ) (;6jX% d$rA E+((gFSK?},XYV+<% ImimS@p?|Q4KB(-"dAl-ǤTk^%.rZ-apv"鵰a5Y\MV20A0uQjwpqw_^'S$NN;vl~N\qXސBՑd ёPCI^8wp{{{3f;XuhclQ;uDݖr3?rmCFZf$35WfF롄Am_ݩSEF=Ru; UcWH}"$'SGݤ[RnΡC4]h"-n4Cue.9hѱr+ W`'C5b`N* <~( 6#' `dq3;+;=v 3;I/$ Op `p˃ZM7?O**^)aZю#|""D{6# C/Ua!BFTȊ~"a<뇝 "fS^>gT ;+nwķuo%q.*ʬ ?"a0ru7TҢx-DZVZX^@}"`tA!2etEGT@*`]ctE#DGiqtSa^H VZ@$ƺ$$>X= ]!v`9AL^k /9mE҂Z31r!t ;^L! &ԷɆgBG/ i4}[5q"J ZA, qWC@ AU]"Ou Zn 6DS?`t5 I Z]H| .h ]^~+Zymj !< `*sDbINТBld=m{Ct7Dϸ,tCV]ft U S]Qj粰Z[]a蟜WI {ai1Ϊ [a)lB+x*H73Ԍts'u\0jڄҠ7[=:HsIʡ#u[$[wC j`hׁ j~m m f;d4M#)s]VjtO\W!p}Mr $֖ (FZ)&aK byI#CY!!QL-i9A;sPaPxM NOt]l"*.NՂ\ ]$Yi VW8 'ANظ)!P:qw2yv^3NRv%N7z_e=:@xt>Y!d#*]T0"8SC| L0\Ϻ,8r^82ciiA^Ar[T8`UO: 5R̫4_L rP!XT&XDwt¾{Sa ĺWe诨auЃfauE=+\vخaPsĞ rǢbtu !zq= {lFc'k !mCEvi%VꬨN BPTb P :/V`,C[@6Ҁ0AbF]Qϡw#H5Rs5\2UB:NUݦ*lHp d} h 6-۷:U{h6<{7G n-'@[BA B娺րiZQ^?z+nؐÀj' `_^ ܉ QCMpKh`]E+$fGeQ6!VQQH3Q,xG 0ڙ#.+Qa T̔ !Z!"yb; _^"ȕ@b*[ɮU5ITHME3y+iDuh?=>A8}FBIT1N絠_ O֓%"FN>S:Z+V] 3]!dA!D"<6 )(ma01EjC4(BW9T=Tct[cQPXqN}n[{.UL"{@𫝆9n \BPP]&h@1Xuij;5uMCY-VVAD6T *j VUUetkPߍ@.Z[\M™muؑ{4t95*f3̓k ی³gc:rXt>Vմc+^6@/B!(G2`0S7aSZO{3ҘY ̇&2b$!ƈc}akZ35%$4Tw0M)pWAEq29}o >ծ۸N3L V_qdņ,[ phX pr[?w.N6lq P6@QF #4XT2鍣<<<<<<<eʍzh߀ЫHC'7W/{tԜs]]aRW? ( Q2bB9,R)QPk rˣ4< Jdv:wַmä=~.<<<<< P6 6W, yβXT MTpjyO[sƎ8&=7ƈn B}3l&Q3q{bMNJNm@dC > nлӇ_ y ɵ YҶ?n<{ܗ6Ͻ  s Fwm UK,Z% pXMhZuN%Wo:Y@',x!D(e+n]&/94 8579!NwdSk~oᜮ ̡8cAr "|"8[2%`#k.JiX<<<<<&P0 ٠3עj!*DJBP)SO_n@ejZiӨA7Վk u،4vcG$w'[v.Sө Bo&AgL :n)/_gPӎ &u zq$`jܯRkMid<^Y{(lט+;1>qϚM%vG@qu!w OLu78I>eUwr RǝCzp' orLJ^iSǛS7<ԘI4Wڜʀ#((}trTutӟؒp<<<<< P0|+S BQK?K/JYإ#wq [SXwƎཬ6ek-Z| uLk*ezgP֦ XOJ;"uDfPSC _yNxxxxx(OML5j݈g!0P焇΁aµ8BI#XnkHz.Τ^R4焇΁4C͠Ey*4ZӬhW P0@٠Тy*0C,9n P0@`QgofP oo慡 YZe&M>2X|Vx7x7/ ?B3`A(jآ5Zx7x7/lo8&(28x:oA٠PĪ Ēu!_u%{nU¹y+K7-axBqNοvc '.Ew]]]*sҜԕؙBpppA%(uR]P^Y]TRv# 77wsDs vtt(J&Uh8vgy;̞koY \?T^dlb7rsƣ[M>dݢ쌾0^ȭvh%i}^|Yݼ.˽/XK.u\ܙёztZUw7jXU\HԯEkW7  }KwXJJԑ##y9lŗ\ޗڱ7}.LzLoP{x7ʼn74h{YD:Bʩ Ԣ𔦦&ηS<97tL}p+Ts?H*ܕHC99}2ibX,hZ-JAdBp y://n9#{lsFv <2h5.I%tsKwVJg+-j-;KKK r@Y=4BQ4g>*'H * ^rSJpvy`k;e}zJ!(((Jj}xfj1M, ][p`^ kw&r/GG,.5oIMkR rjϽS|៲~~~NwjJ쁄[pK()j@?/ ~J@@|pLzQ6~<03$(7;fggGDDv[dd$y%11޶:i^ܢ>Yw7]PWGϟOLLr` ϤVWkf-Txd}_S^[K-i?(yʹߘ5:(uTDHG: .9r8ޤNpo689A :lyjq8Oۂ7~l_8Jm6vQ~Bji3ݻcޛ8}?R稚_R?羕ܓk-z*sS@I (SO>r1e8"Hg)8A9c!#uD2$nʿm8SQJi)w2$9J86o%D)9*X(&oM_#rdnRp9uD/˺[_~ qD8N+Tn"1iWS=KNK nVew /}9{8%?}7YxB98.,&e|xt|hdLkS n#^Wq?m?q3lDuKsQn :\uYv=c oZpٳgB!d5Pc8ѣGnܸ[6DTOS#j c6Ϟ9}UKq;iYYYغw||26 BRBQqHucgQO WEEff"cjEYyޙyÎ3ݱy%;w{-u>CnNNN&"#[Vbb}bߎh9vo G`4o/nsE9"R椷 ]>-ң>&66sؒPTdddLJT\r2?֒%KɞJL8rdۃ- [+W#fy ?e3NC;ۯn_  @m~Q EF\>wɜUܗҁ(hQmNDBC&8`e7?-ojoڲ.A![c8ks/*Hdꐓ{x Y3KRU>'?ܞ{9$~@/$"//*xkvB(*CS0CXNE1h,7ǸbASP·B?{= ωk܍ʊ_-袛>ȽU|>aN8wW3?DŽ{or}m?ٟ( *P]t\GxR5/c .rRIIK㨨( y7BQ^^j*]WwmU9Ko#FInfH[T&+"u_l>yg'QA-lX&PN@ "Hd=TPh%''ëOH?X/MD){M/hi&5Ҥ,(]Q@P El`)E!2;;;eg.9sosf6uGG}v>`U׻L54x2}ro^x.P_T糉|C`''%Ҏ8}2nq0`Cǎ)s]]cM8҉'X,v_I-sX^bKԈ^^^-i=%`k3,[zŤVdF^{*bRxm9N-yƞ{)Sfy MdoBuFN';.m_ro&oJ5*{^Ґ \T{n.ϏY ?P((cBSa=3t%K(8Quᖒ(޸]o*JJJR?NwBՄBP?P//Nt%$t*̌~+]^G\e\%Qw1{9Eϟ?(&%Q-' q)))qqqpRS> v Hn ڨ bYYYsR;n<ۄ ˴g 옱б}Gw߹??v_~Ğ<Ogg*>th@PʑT6mjT@Fɓ'@U_ΩZ쫆;>Ū{ZxX y4C-ZqPg6_ t zyw 示MU]%] L/)"70cٳ!M/(dr_rO!`,2*  'c+jn)XN;z ˗xOit>hNy?""l졧,_PKzRVH8-і}~ly)AG=c/Np2r9}!G_-7~FM9|+ǏI㒞 W^ݲysQ)  *BOYorQň׎gffd5Q(XO*Ė?fo[yAioݡqa7jjg8ÕPTTU]sWjذaӦM[l0DwoZmKܳX=zڥSS7unj#nZt :zw`Xg6zD a3[u^k1p/ ;w8fSӺ9fZ{muX___Qtֱ=إz7^~E/WN;F0a-.]b Ѕ$??˃?+ <00-<$uz̼h’e^8jlo/^d~@,uT\aBûufXä PZǩ;LLL!cP@ny$Vw ŎUx…~̙q kΟE՛n۹( Md Nȵ;76VXǁ<(DN-Z&2tPoGWNL\]W;;oy'WrFMnx=2a$'''L[C"PJ);=<|V889%y . 9K@yR=Sl&uv;u%{&@l>bUkzY7+=d6Λ~DNRXt1?KW̵:[+VJ7 X`ogbee9sLss':::kQ(X(0@v2!F{cZ Yv`yy S::܌3 g϶P ;z8/2af ]aPn$3L47nh5رcP^^^?JH؊{PPDFpGxn1@tt4?̧PgΜ YBfFTׯgffBt큎@YAݗw—~A4'!!]l tNؤ۷&M6y͸_((HOO GT-[z$&5(%C{zzWHѣ@Z&bj1'> 6[J7wwwDj(K(1 FP[m޼n4'CBE>oor1Y)0a|2D0SSjAO8;nEA!0S̟*>9ǞkMh數@,H[kLE_Ȋ~%|͉ASd}HYts9il`sf"E u}Z)yӷog(%-s.%J b]pqb)t!f) gg{zs"g\ȉJGڧtc|0VQ[[/ZPf *c*T0Җ,2 l;¢#,%%( BPb2eS 5( Bdk"PqBP(JL?$~BP(JBbP{*P( B$A( B /BP( 4=:O,YٞBPB7jʀ BP(zM7B*P( +* )Ʈr B BPzP!G( Bwf"ϷW/߼WYVr_pBP(yZC\/1_I|T$3WIf53E>$SȇĴb20]@@P(JTJ7EBC-#y42AH1oץMw(ݛ~~9CT&\ PBP(^>T\RkF) T?kGG: HV(u#x <mioYx&䐑3F]D@P(JtBB#Pb wՃEUQ2A =Z^$g\2:?.@0B BPz%qTzPz8aCiN۴=JξIf|buL*J>PPBP(T$Ub.ɡPpYg//!u%3o_D@P(Jt?̴}rT+h-vĮ(6+T:]s՝ށr-رzlJ!"^ dBP(T\!="$3m#T={I=*Wy}VU|JE$\cl#~YPBP(jxjj]opL_PBP(^bFPBP(^1PQjhSZS5j!TP( W,T0\YAO+  BT *XPz*X!TP( WZ !TP( WX(^t%uFQXPBP(J~c1Ҋ*P( BɐBj(B@P( %.P2qX叆&(QZzT4i잺6+VVQ u*S9PA[_Q۬PvZqQmVXF)VVSar@EIYQS!q6ڛv^TVQ (j| SQ19 8{"?}x{F;,?"oo :4* OE#wOza'/UoN-g{g/]>qdK^൫&u%'nב;*UXF)VVIQ ''#w!T LϞ==3͕JLOVǘLb   .KȇFE[d|J)UXO5V]{X] Ab~̹qd׮ظcs.YDI2=S,.1riTT pE~~d!FӢdJzfAYM6C\'=ժ_oj5H'$*儔94!e l` S@79UTGF8 TAdBcwMY}Hf{k+OkǦ(x튍;;[6,>YgYsN  )PĤjTB34k- T<1ITrꀛHUǘh>IdQ:ijq= 2VBK%5m}PmvţV^?)PGrɜ 6_&;Nګ+dF6b鸠w0qOMʸ:d `xwB՜;s檿5` KZ1%9gʰ< 9KUwڧeEZw# gkYysJY׼6 ^&HP'NgѪ>^ŝx:>qO-Bu D`R]VgvpfYTK SZG;78FB0w0T}\a?z<l5Z z*Mi[28(7 *`ZwB k1qrLD_zB<. w1qOpfsNS40vfW;t#vfAA2 8 ~P5oNoMWLPQͭN%2CܴT8,BmF֚&ު{#v2כ XuTͻ/N>Wk0QIn-jjɳT 8*s7%v3D`>ncpG;z6N0Sޤ9q7]+%bsY ΅>YTN|j;N;+n\`|=qALh>8dv Ux17;04o=hcV0m? t!Eyaڀ&ˠهArB;nBH)7*.SJ߅nZ qRC*j=Ṁ{qXpdxEf%*n(M.TLIQ7krJU&ɂRxU$~Ǚ >Tppv8ǥb&.㩠Ƹ蜷і gܼ#UiʑwFl'!EP6$! ݅C3A qG qS<e 6KV7vuB N\*FmA;P1}Wʸ,N6TH4fҞ@"1D~#v3;⻶3YkT?A5yEhҪ8;S繎)*gcZR[3<2*x dZHq#"qqC=7dBŌ)68O<B$ :Z Q0=|ook$>QAdwl ?ˆ|=^-[Z.N0Js:m^nU# v_ cM|ʫyW{51aU e4ZD!*,O*;{M{?VόOc撰]יdNf= 6nGOf=c܊4ʏwfܛ|seQI bԂĠ דL;xBu_E 5ngUʧiv^&h])埽0T78Ξ]ΟHN2Ӊ@S+˵8]tgTljN2}~Ez{*h(UBEB;+_PehubW@ȴ3dPʇ~>ц\߮.DC*QŤ>jjM\C֭7"ߌ!ϕ?9Y~GNJƟ#֟Iў.ޏ}Gsn}t !.Of08=hp 8wNq?6)x[ԼƫgK{":Uty @5g:kWN*0NΧl̉&y^|m)VL6KJ xEV B 㩨yXVBcw>2am X]Jrɘä_ֲç: :9ɻ< ;s#yp+j ugO+d kBY̶&Fcӆ GD1d+:{`?aKdl27Z48GWߔqoU8 &x=M(~9`O-qnܼ;v#gߠM Shnt}-g[:MN$N"DZl /A=ntU^y(1.TP=F [oU*1PvͺFB_\xg_I86dy> GZ{.p~ᛡF,uo}~߻9_{sr%H~A##@y*5[(//|?4>`7%g" l:N!ٚJлŎӽ:_1G$2 84oz[ ^T4žT{-^;x]kM/Lty @'??554X+8(? f@*׺ج)3)kD.UڛZ§Bz* ,TQٝz=P'O8|Ma3O gc|2x*"trrI5~ՠ ;@n&/ aKFΧ n\kDNɗ~p1'ABW2#)Ǒ秠tMQ'qg{42#̂#ӛH@دkWS"3.=ij0U G˘Ҫz6=X dBtotkCwJ MV=HvJ*==Jgŭ;X5͹8""ߏ0hNUc2`XQ +QqM5rȝC,\&14T#V[b~E Z/0l!=я;~>ɏ+6Z-D CZ^04:`$,8DZ\'Od"Wd.U/XzvRDժI}+q]OZ% Ty6444668j w2nՀLfq Sȼ]:9yEUB34T&k1$f۱4TRD2{u)ou NF@L\.QSAP!aTpV<q | ՒjM#'Cjo?t.IwL-ORsf+ YIems6\qwGoc*jcWi_@Ej>rB&TLu򠩱&Y##Nn~<1]I>8E=(KT.,}I*D J&~z^&_W=~GwUEl4*/Slum&u"jEyROw5Yg9qOS<}| -H?R95?}z7n*ǯV~ P!vEvʂ`wh /', Xw#608ã Zoߏ%3 *-3J)P7 u4 Tr~coӛ3%vD)x^yGA]H"\ q}|uV T6DBPDaT4(   ubl%TnTQB>Q4B*6Gܤ޺潝w6eW[mgk{7oJO"|1!==3?oLϞaY4Sшa騳LAu]x AQ)Q)rS'6⦐;Pkd @7E+ T\Zcx^ 5=Zs+򠥅Err>T00ܹJD\Pb!e&j+?.*Z(Mv>ZM!(MѢn =PQXPn'C}3nU{r[^G+r->}zjjjyy"78ǑpO!Rf(C]- -Ah; O JPDn Dn A/`ɺwQ)rS'VwS4(@EFZ*Z(ZM!( :>T$/\0hC *"#1HM!ڋ5(zO|@7EK))"7|h]{@ZM!(Mn,Z%N6+T.QB>T0 \imm?QՓ tSVwS'VwS''馐 P= VwS'60*JXTZZL 0ޝ7qWn/}m?ݮmަq6ym4{rCB `$`bMq , pXU6Ż[5#K]Frtf?FFB3o~I"&c xQ xQBA1(BA66dRAb""T]s@Q % xQuL/ 1(HL!ۘB2 îv]92*A)~ S^c xQ""@{A1 &'&FQC^Q(: Db xQ $Pʁ1( cw_UkOU hNWAw:=a(ZLAPA* &*HLT$PPL/ h19[+NV١"&c xQTU@! S^$@SB ]KhoRÕ@^QT*:@! S^c xQ) 7*nѕ@(ST1S"4T )E=( NW3*b2A) 1^c xQB1E TIÉpPB$A(Th@! 1jQ`)E=^J)if]:FN6@!)P"LT?*SBV 1R|`)EuTzPap9*b25*H $@* 1(HL1E`T}qe)E_2)% S(D=)PE+چܮ>+QSTBC Q!{L/ 9hf]hsA^c xQ`)`DAPA* 1S )S{LNҨȯ hiԸPQ 1S *HLTc xQBq1*( rY QB$A(<*P{LZc xQ`)E=c iTZذu!B)> %‹ *HLc xQe--nW@"&c xQ`)V+ *hj! /HT( 1EҨpRϺB:>/ S )`PuGD*H SBV@! 1(PhL/ TXTZJT\iT) LFvC"  1)B^r)$PPQǡНP^c xQ`-\p޽`3TW@T"Q`)EAb E %MqvoN)! jEAE%: .裂$Ɂ1(䃊 *zXTaqTdL/ 1ջQ,a2u k?Έ_wsqJV=>ɓ`W?=I jYjOr6Kuv#/):LEeQ2jbX1vlȫC$@* 1(HL1b T6ިD(HLB=uG-\䭤3N3JƏ^?=iIN*P$Ac xQ9FEQr D Q`)E  F4LMX˩?q œg'lܸws**"[Af3Kg *HL( 1bBE~h7 SD'R?&gh< .\{n@ _% UT"yCD9bAV+ S{L/ SD v,-A(HLfLWߗreѱ~߄III.]n2 w 'pYYɉ!̽/^-d(EAb S"b@]uT^0(rGyāĴ46DMR*HLT$PPL/ 9_ ι"dT((BL0t%%%7nLJJZnŋ;;;BPA_>+ S6 # SD4MW75ؖ{# *H xQ`)E!+TdL/ 1(S"tTh+8Q0C@ Q`)E!A)~ SB&>PJL!@ @ B>@! 1(*Ha/$Ac xQBA1^Q"я)*HEB@^Q(4^c xQ"r*E=c RQ((D=@- S^SH\(lLAPA* $@* S((EhE*HLKP`+ S{L/ S)PT"ʨX1+d''tځœ.{T$v/ RŽ *b2^$AEYspE) G@! 1(b.Hsx,sA)~HEAb PbL  S"LTߞ z+s@/[«m *+vm=$ RD(S{L/ S((($PB>*Axc " wT\ LwD*H+@! S^$ ,og]m8T{L/ eH*jZl*=|+%u 'Xt)Pѫ/z& y0W *S)P{L/SFG;xE=B+Tpmlky}߷'$$h4AD츤ΦoS *"_`P,*HLT$PPL/P/`cp .(Fb @UqE[\ޘWxr#_46̉+?[*n\oKxuٳ!Q&@\bsȨȊ PhL/ 1( 1꘢SRh`Pт xE1*cCýC!kߠ>8?y'@gVTU $06uvrt鮸kh󌄄(%:^OKzj&~Ȣp^wXq(D!+TdL/ 1(EqTh\((D=|b ATΠ"庳u'/Xw\]m`^snۤ˶ !嚉ٛD0MuB$_g7ؗ|cK*QߤQAb 1b xQ !LEEL-D;iY`e}QBEC *v=z}F͕sE/>Y-t S \^!N*EИ^c xQ`)EAb "(T0h(C)drC IUPRwrݙ\ϭ}'r^6kp:!W { 1b xQ*" S":1 *f- Viuךzg駟={6Ś5k 9ܙ^#LB83 Rb%:O)_ᣂHEAb  'FE E^"&c xQ@b^)bzŮ+v)gjѣkt: 'jJtM% *P9=)P D^QBf͚~ťD_"~E (D!+TdL/ 1(ECmCĆ *؎*b2"T_b xQ(4^c xQB> bސQB$A(TȨ@! S^c xQ b E QFLAPA* Gb  )E1c"&c xQD?  $@* 1(HL:Eb )TX(YW1SPB$ρ1(HL:4*t xE1:c RQ(@!P/ S((( +B(SA( S )SBV(P1TdL/ R+9=)#H4W!(HL# ԨjON**4T)s{L/ 1(d Q ( *H*( S(()BEE1(R S$@SELbmo)P"^((RʪQBc xQ(4E\S,@! SџTd *S{LZPh Q6$*S{L/ TPTtVE"(Ҋkm)a*LTB>@S`GEL@SQQgs8~ghH+VlK+ e?*PE1E(R 1E1'`,{ b/l`[ EP*P{L/ Y"XQH\PBc xQSQq}zfG44:}bǧ-=tt6ؖ|Ei/~~ꖲҊ]?K5FQb"PV"&c xQ" ɘ^cn^l5,g{Ʃ s& &yǡ3R}΀sAa3^|!&j]jifմҤM^Kl"PVQ/ S)E:DŠA^$@SbG79&owNx`~W7Mg6:to)=nߤ"i3wGίp9Fg{@yᅪ]ȑ#bA*4T^ )EN`EsJ@! 1(S-vg>_N}ⓟ`vVSk'mf@8%!mF1q3;=Iˮ9U~5}3є%?-[֊ R* )E=@-(Rp0PPL/ 1(GY\S5ab-Ϧ7X_f/(*49}:: cM1uīF*>&qw {w %(yM`q3zn{Uo~9Ϝ]v-,hQAjcDXcS+iԱ܋YOT!AED!MȢQ)Qas}qîsZ?i^xژ?Y#.?3)]Oܔ.3@Ck%FXҡboESo<=گzIIXyMצOM][\\,v*"? .?b=pP$E Q`)EИ^PQϺ")‰)|Qa#;/L{v5;~g޻}Q&MO9gkKhhC{=nm?wSt^۪;U&I'N8gNBffVd AfEeUPBc xQ Br L@! 1(Œ)|Pa0_y_^uǮ}I֛_{NqMnv`fiSMG#+mo֌UIbngOSM+13dq쏘Vm5EJc#w3!;WoT -35bǦ,뽍HL}o̙3VZV F A* *hϑ'TO6s==;h.J{w@R> oQ,Jd{,"~{J`ث!/WD  )E=*PRRotGWT^ap_^^^BB‡mY\DPմC5`3M+H0a'-= o#ISN]1cƢE ]YQe-Ν @p tN3򺦀W=;Ds\ݖhR{憗-#?e?|,XPAb fL!6^ĸ" 1EQa#~03⒏6o=فbKe&O0+_tWUG9)7!{?ϐfHLˤ'\,i\͊탊 6Pښ Dm۶:EM>=--mՂv nj0hM'f{EO<0 4v ^vp'VX8c欹 K+}hvtR^'7EOF?>˅, zjXf^à xD9KWQpިزeܹsN P6-7|L Rabᠢ9c .kg EP!c ԢrL!Vr}OQ# ٢(>=i[ oظg^@ ݒ%KRRRճ̟0iʺ?f=;O̎N訜UؼL;js}*G?&e^bIˤeVTVVi&0W\ \q…&$8HBs 3 RK @(B)䃊(BuVF{ 1Ec T(0R[:钊ܳr՚"y睄Yk.NTWW޽;uŋ1>S1f1DMvfOtu:ﰅ0$'{ ɪXsCF*E=Bc xQD-ނZ pEQ/T{L/ bfܬkͽXv?>`ㄉ&OSO`"Al@GEi*Z[[WZDp6Vz괴Yf[qYE Q`)E!+TDJRrtW\`5*P{L/>}`|tIiUg9⽵3isvh;()1Owr&PrnEUWWgeeeffad2B]Ν;W\{nv Tp'GDAeXQAbETmv*HLE0}S۬]bӝ΀srŠbrnThnnnjj X__^nP9c(SWLOƿ~ք'n]8)Ǥ;-JQ&*B1( PW1SQ*w;R]]ُ*"3% m8۞N; sFwrJlQ*T^$*P{L/ fT   TԴ؀+v͒pFsbgگo>tW;w\כ~2S._%I(eUtP1|D4BE vTdL/b ~g\ ?r̦&] Fs¾  'wvGQ;n.I c(HL!0h $ÁC?GEPO פ3/^ҥK[@p"6x]Q6HؤY9rl)eYb0%9ۋ~VQsTM|h[5"sqs3iMЬc*䇖g8G( 1E1E TPA^c xQ(40c`}U\j*jM-5]G}pA2s kRQ᳿V3u-ɂ_;5%{ o4{qkyH%C{_Eǩ*V~_{7ס_,5̙3:Nl",X$Eў'ROL`NM:WB 1SBV@S@Mi@! 1(S%Q1쪡ᢓiͯoxcb3'dQ!Y q:T^&N4\ҴAq.:??#Ѵ0eWP0zx;e={r6(zP? SSorT Ƥg~]WKOOIK_Uo|yjǫ/ *D>?\n5Do҂+(JG Q"1*-Hj2Wρfȫ\tw$nN@!)"l'X_A:%ך&=nڜ|36o}"XTp;.lvz#YD,5wZ==Pg yW}ث:Kc~uϽ1sF?1m۶ܐ7N~ӶOzS>B5f1n\f{I ;~+KSV$6K︠b Q)E*E!ۘB S-꬧t>uWFWwMF۔9K9Q1(SEy;^+7j_DAMc`?()۷oٲж/СCZPg\gΜokk\f[ 0$*EAb 1("Sbʜ;sʚ.m8hMQL7'^TdL/Pnk֬l-RG`02 *Fs nQ`Ƒ;Ng4pΎ^McE(DAb \>$P1qV*3Ϋ_xE1 c v'=%E4m0(bozL .eT(`P^$ 7O|3v49ܜ0^c w)E*ɘB>Sb9_ul9RGJؾZk39#)EAPAJE(RQB$ρQZ ?Uj}zTn΀@! S@#G!C.E‚  1B όZv]fЫwI{O͉(Dc1 "]E+ڞSUW#Y=ǿȢHGZ뚢GS"4TB1*z9݌)ۏN赟]ٲM7S1ScLa& ⶨJm>sOn[,=CCEE 5X6(HL:Ec 1T<ɠ!e+^}.\R/ SⶨU0XmK= 1tQCEE5=ۀ<|`)P{L) ѤuiU'Aq"`lWV=4nΈ(FyLa 6=qWJp' $mQG:ln=8FF`]5mJ)E!+T(%CųN+єTG֜rw+ 39P^cІ2QM9G5##&2 *FslM[loH :C;(tdQAb Sⅉ3+[泽܍=rW7QS*h@Ō?_3aOLLL>EP1{I03jz#Mwt:toԽHG(HL!ALs*̩jm\-tL7.lm>m!7 *PAQuVv<)k՟^ا.QAh.>*>bߐG{RHYn)LN;tۊ(DAb 1EQpklt%Ӎ:kk(^ҨoW&pZ{LWMA4uWtk TdL/P/ blm.7xbue+uҘ)E==% |Oh}f=g~-Z"77]IVl,(N_w]iѬ<-DP S]u>cv茋+q/<ҩ7ŶMYzt1w]Bk'j=1Ϝ?!j̺O#)P@Sbʜ%:Ɋm z.Q}S'qs^$@SHN?e\3sgMKKۛh[LPfb9cJ҂}^uu tO +RV.Y䫸θ[qq0b~Qd4]|dq)[b4Lq3ӂO q!VΉEu>*P{LZc xQD˚sUKŞn7L_67gȨ@! 1(Pbuޚh|[;z;;N>؟J}#}D vp1X's`cU<Igs`+Tىk+4|G ~i[s2yŻN*@ɧ{3i\ܺ J+ػhQ>'7HJ۪5cUcRTcʨc ic\kJPSmܢRxldC|,6^2]x2QNG麗CϴCAS Λ?~D0 m=}gwnڴ[r8I@loIMBns @ $Ü ```c|[,Y-K214xIz$ChI>P. EB1/T4KgG=.YK ~cBO1*TSE<)-..6mڔSZ J K[[ĉ'֭[㥁Pi2xtp{,9у"^ITp+Kι}mNΛ}Bv]l}n=AEcLLaLҗ_YԿ@Ľ/r `T8;\'YX] u-Sn.iݭb t/ՈQx?@مQu(%%1}v5=~^AiuҌ7MH*0SBErrruuN~zqQkǮʪy͜9sKeW8,vO^kbA ?Ixԃ7FqT*6へgb n-K 5&&&fs#+&f~L:E+zg{eȤɢ(pQ( 4DvT<[ozɪҦnAqSdPACSu̇"))f`0>k֬!3gĸq&MDȮ"\9 Tx}C tk"~H"ye/ۈuvE -ť|<ԇ>Ţ){ޟ>+#V5 inqsni9ʼn.fͥT춺=9ѣbM> u^s}lO/>Wm6uJgiw7r5cy1e.jYxqWGDtI&%],dm p,g:b}$36ҫ/|Ե5zoayP1UQ: tPQLB* _0dݸqy k7{츸wy7ߜ@ŧ]ae6Enί8rO#oV_kS@_.nݚ`X=J] S 1\AzQ"+B@lEKfq/X_q#iqvV|L~QV+Wſ(u G' YC| H(+]ptS_ByXˡȑ#3f믵Z-9ݻwΝǏ"G!߃ݣ[k/ro{ `+ pQ0)N:W WlE1Tl4M4~1 ssOU{?9+8춰,%Vk{''j_gptK=8",߹VI,J{oހZW]Etn$j<+|- 9̙3gF% Ҟ5!8yG|wN}{ɿ%OȞ?c&_ {{ԩz^v{S#QDUUեKZ/G`)^UT`LAU)q)7*Pc*= ǒ}EEŞ={,Ynݺ}dddTVVAsss[[ *r+BZ>aQV*)`SE,*JPqר! ) ZZZȽߏ_Dz^#&#*v)ϣ>:EunT9Ţ"*cދQ= *hc &0T8\qց `+S *^4(,u*)hQp^. 1\J)Xa/DVQ1UQD>*TDeL6,@T``aPAC*)`SET6Ê^(0@T`1/58KRՃ\T U`\u\tB!1\BEA)4DM1+ţB9 lE*h*0* Qt ;CETpQ)h?( 4DR: *hyLAI T! 1\S`L(S@3[B3w" =eQ1\ >RJ@ETpQ0)PiL. z1&E\SEh֟\.*f~DBj`SE1r> (78 Ǐ]~s̤A Q`Ltu&+^ d>?s1m6rn0K\pTE<c Et0T:p↫ګg =P. 5,}']tlWX.cݖܢ &ҥ1ѣW^MmFT`*hyL. )3<(U`TniwVm]}gȨʘ"2UQȢ/ڎ}zv]cr\`MX=7f{655IQ%. *0`+ 1\S(g# ͻdmɚ&f=Ũ! )BCE[[wgwr#e-Sޟem;2dmbX- [jUd+h$«_~Î BE1\. )=*4&xUG^eҎU7Z. `S/T,xPi '* nusMܯz{/77Yv˥pa vB*Z" !! 1\c (0SEޘڏ\&킭{iBOQSE(T9KEO^oL;٘ucfASsgnO6o35jqf *RcZ"BETpQ0)B9)@h}зփoӶ\<}'UT`L(dQ`;'u tمJ5mU}wpOzj֖K )g .|&FL3b)J<= *؊c pQ`LPAځsem3w=f3XT"3KT[cBDq))ێs߿g.,,z p>"bc*xo=z&v,%WhI\c (0PQLQ*̎k*82kMo,T*hB1,*6=Si_ؔ]?Xj,ؚff5/ Csyd{dSCtK5}" r[{ު ?`SEQ*hc pQ (0\''r{P!+ `SmQ1\c (0SE<* "aL@FETpQ0)`S. 1t}AŁk*`R1CQ *"P*؊c pQ( Sg,Y夵/k3>ACc /pQ0)`SE1rD~AFMOX(pQ`LQ0)࢈pLDEzIsJ~7AE~c:*0(dQA&ؑ#G222o߾yĤCiZ/";;[QB!* SeyLPACc (zR%{aEtG^*);*ׯ_vm۶tElݺ4ZZZxT߿CxXE\S(cSQGZ1唡t+9"jb YT9E۝E$}yyyMMMJNNeRẑ~$ζ닄SK__u"PD Q0)vL. @T~c9p5L {*Ҩ)# 8*$ٳk׮;vؼysRRƍ휜f@nHup1yi{yK8Otݒ,1]rJ pQ0)`SEҘ. 1\a)8rm[rh[ 7jbL?*v'<*6l,6GJ$|(!hs15s0Oi`)z )2<- )( *]h%Ek{X4g@TE)BT8pCnNU" 4D<c )BE@Tl?Qi?^h#&LzG\cA/QȢbǎaGI^ Tx5_PV*! 1\c (TSE|8+++33䘠.K\!(pQ`LA;yLb * k;DETEh;]a4Z-occ`hmmFXQ1[Q0)PiL. J1Eaa! TE1*zY ,q )2<- )h`?؊c DVdc4D<c )BEPTt`BMA?"1+E 4DHIS?⣏>"WQ1\c (TSE'K;w^3'uʔ#FXd i[ZZO,*\ϛ(p P5gx-1 !$ @لg VyL. )3c *m.o)nZl)BO! MMM))GsrZ.\*͘LQMqFF0LOT3g{^߳dw ݍDn* *"PDETpQ0)B9c bʣ Wo:T`LAUpTvժs99SLY|yRRRzz: I–.Bc"T= w!nu!! )TSE(TDeLEQ1'vNvssEZ/ (Eɘ*9Rl١Gf^H}e9TG1W;x8':PS4Qt@:MwbEfDX^ZE4D1!c">U&:`DgQACBE$c ?;~D5gNG" mV_+/TDeL. pQ0)`SEFT]9lW]CvVT= BO"Q% =ZѣD۶m#GcೄWP1\c (0PØ7W/oȼh+qBpc?*k2l>K ,qQVS(P(0{LD+۪^R*.X~4D1EPZ!*%. 1\c (0P. 1۫n~~sճIf GHXP1\c (0P. *^YʎjRvۗ_S1UQ *P<*hc pQ (0`S@P1dO[o{ugK~\c ڢ`S *"PPACc (0SE1EP1Ǥ5Ħ6 OVx=TP*@T`E>1\c (0P.`c *fOn:^wѷ}&!"1+E Sec |0) AEqyyLt6ET]I(lhY9_W~U{9 Ud.[ߨ՗ BE1rD1՘u,_;EsFR"jܞʉWI}e]t:_OK\lQACc (0P. 1Iu*W_;]T('yL"䲾侘|}cǸokpqtrr /!*DETpQ0)B9c (B@EŎ,w\{;nS )" 0^嬻6c`ew=̍]6GK=:&7pQ`L.P)8VuׇM@). 1mQ(!EEחq_N~Ǝ_H^oTZ~pGR璧]gIT]E Q0)vL. @T|]-4wg =C@ Q( J)dQm''̓^3:V}گ=ݭd^V+}|BoDzC*)`SE<- 1\c (zSQQTn  aP9SȢBo%cpcj;ݸqOsb.Mʝ{Qpw57\\OcGcޙug\})>@-E_ۢ@P9-ZMItb'V "@6OEDvN"9$d%j&)J]9.Q{2s;ܙ3sF߇hxxo~g8Жo?m1܌P vx":2Ʀ~A' j ݚ' qMɚiPAM(@P~ؖ?2-G[vC(yݻwְ~NE/8"9c?59atR"MB\S& qMQFB~3()B-:?GvC~>m6EjU~L7Ne(0vT,DQ2 *)BE-:6v;n _ue~% :B\SDAMaQk (ZIS7N 8QPS4PS@M|R5~99P(5N' BQk (4E-PV0GSD!)"* P j [>))  P(,8Q*[ (5N5NVh *|0*3n0YS*&T qM5nMM*)O*)dB\S& qMB@bfRM T0MHe(bA%BDS*&ă D!)p0(5N)zzzt@5Eh T0M>A' qMQP(5N⚢MP1P0GSD!)Ȃ7^fժR7, Gc |PSPS BQPS4 *0_ۖP *dBB\SDAMSPt-"*x1uP BQk (5Nj (5N6jZTPSh%@:~%7#8TDs,TB\S& j D[Sՠ' K5Nbyy9 *T9_~?7~42RG peB()))E1m(T IP!)P7>oFSTn3BB\SDAMaQk (MQ*B5EЧ)x~ӟMȚ?vDM=<;imXl*?BPђ' qMQP(5N⚢'*z1V/T)p8QPڡ"iNCb2?Yf!9t0MU% j jDD{^M~o޼~]K66,LLlm>]TGLQTH"mȳD$L@% j ݚ' qM5E(L fQ)rBj_Knz{o7<:yTuB0%9ĽCG=LI>T qMRMB\SDP/TPS b"*J% !nݺčw_wnlFMo"<6>Yer0H̙L%5NB7QPS fjZF3?Cb9,XYqzo'owt :94T*JqB`mm(V8!% j jDAMQh&T IPaȁ R?9:꼛BE??8Qk (5Nj (5Nȇ*|0 *l$h,1 LPђ' qMQPђ' qMCU Q s4N' * '*t555V *ph T0MHӠBQPS8Qk ()&B~63( IBEKj (5Nj (5N' Qԯ)LhIMM:BJS@RT YD *&T55Eh :$T0$ 8Qk (5Nj (5N'kH\Paƒ jZB\SDaTB\SD*)EUg "Z2gl-3 g dLPK~E>QPSj *ա' j Qh DQTQP(5N' K5N' j (@8@CDAMaQk ()8QB\SDAM[SD!)pHS& j D!) B\SD!)pЭ)p8QPSPS j }F@(8QPSX)pBQk (,8Qk (5NZ5E-Pőq0GSD!)p(eC\SDaTB\SDQ+T.EUJ' j sB\SDAMAMQ()8T8QPSPS qMQP(5N' K5N' qMQB *l$ j 4NB\SDAMa@b:TPS qM5nM"MaQPSX)%CWmAD!)p8Qk (,8Qk (5N |PS4GSPqQPE1"MM:B\SDAMaid0GSD!)p(@i (8Qk (ꁊ<>WTC' qM59D!)p(@fj *]uk |k (8Qk (,8Qk (5Nj *9PpE=Pa#Qk ()p(@' j s>5N UbWz]=⼂T qM5nM"MaQPSX)r+rj()tRMB\SDAMae4EupzW+ @NŠ' j 4NB7QPS qM59' MBA+Th (5N"ME1"MEcba5]g׻gk sB\SD!)p8QX)p8Qk ()tk ()(TY=pZe[–qMQPђ' qM59' +4ET\ b\>0zp6(5N"M59'k *přՃ#k8TDaT qM5nM"MaQPSX)@/?}ՙ758QPS3!)p0gC\SDђ?/\BB\SDAMM:B\SDAMaB\Stww#P+N]RáMQPSX)p(8QPSX)p *?Ȋ7B9DAM(5Nj (5N' j ݚ' qM5E*N.{Bq]PAMa(hIMœqMuΓKW8b|(5N"M55EЪ)@Z*sT.TDaT qMRMB\SDAMaQPSX)p*V58QPS3!)p0gC\SDE+PPq- *tk (5Ni s"M59' qM T,zbPaB\SDAMAMQ(),8Q (),8Q4*2A' j s>5N5N' jD@pBbt% j (5NFAEKj (5NB7Qk (5N':= sB\SDAMAMQ(),8Q |4MSo[抖8Qk (,8Qk (5NNMQT]\LA0()tœqM59'JSC@*+PTB\SDAMa0(),8QPSPS qME T-9Dw`a(T)p8Qk ()8QPSDQ *pHSDaT& j D!)p0gC\SDAM[SD!)p!PՅ ՅvSB(),8Q (),8Qk D!)p8Qk (_ sB\SDAMAMQ(),8Q |hPQ@EKj (5N |k ()! qM5E5 ϩ*l$ j (5N |k (5NFA8Qk ()Pl*TD!)pHSCi ()) @PAM(5N |k ()tk (5NB7QPS qM59' j ݚ' qM5HŠq3B(),8Q (),8Qk DAM(5Nz)B\SDAM[SD!)p(eC\Stuu AEKj (5N |k ()! qM5&MQ3T APa#QPSX)p(@' BQk (5N4EP h% qM5EHSDAMAMQ(5N j D!)p0gC\SDAM[SD!)p0DS4*! j (5N |k (5Nj (5N' s4AHSDQ *pHSD!)t58QCEޟC' qM5nMQPSX)&hIMB\S& qM8QPS4ASyi#QPSX)p0 *)l8Q-)p8Q4GSU>[+Qk (5N' j jD!)p*e%5N' j s>5N5N' j 5E P1`Ai ()) RMB\SDa@R P(),8Q (),8Qk DAM(5Nk OJ -)p8QPS8Qk ()) 5E"(j2W8QPSD!)pB\SD!)p8QX)p8Qk (ZCSCEW7*t5E' –qMQPђ' qME5EU_}z' qM59D!)p(@i ( CjB\SDaT qM5nMpM}sTW4 *t5E' j jD!)p0gC\SDa*o)AP(5N5N' j (5nA'j *T+DQTB\SDAM[SD!)p(@i ( T8QPSX)pBQk (,8Qk (5N)rba}# *eYeY6*Sqbօѯ>O@0 0JTeEl`YeY4 *6Tx\@wBa17186}ٻV>; 0 09 bڑ *:O>P0 0 0T B0 0x| Sw("P*0 0xT;Pq++Pᔦaa<T"*aAEN#PB`aSTL%T0 0 SGPqIB0 0cP]e[ؾu5e[v^`ajM*nU# e.2S^*wt9 OM-*׶$ڥ_뿼s o4 'vw2akw?!GrEr/sԅ/xU{H G&oq‡Tp")f_uQPKДӾYP}/&w{y O1®]mzА20SV)w_,j_@ Yk-B\V^RykC`F[|KfBEQWmmm[vȫv%.uz_}Sg9K=&^++ ?r6 /| 4UCRfZvlUw,/^Ė8îUvxq9[5 0H]V$C0=blP*B?=K;_Y f9MYX|kC`F[PҙrbR>IΩ{iCKo2X[#D:F3/H.ISoN}r'+*oU =#:[݅jITM5ѫjJ"ѭQYԇAEG^N48I.0LCRTZe> 7{g c^L{5^|* HvKXhkK"_ #U6lدتmXuvh)js~%gnROQ2x܃<_oSr n{ IT?rُ/KȻ{7cu9.Kl̜bS^qwui΅&ʾ'WxbB]t;gb1[lu˓"[ ᏴyzWpbK/7TDaYdnT=+ C=[ǞҎЛoMv˖3 ԓT,eV_|fnU<9o1{a&?O=ii0fB/̭{R1s/3 'naa,J *BRJ`aP1@ aaj aaK*Tx=x';~"_ />]_v"JJ #OE}x?)o7>>هu3}h~ל>j~ӡw)jsVO|a|O;>Ǟ^۳۞x_|O=7>jIxvc_Rܧ?<տ{'m?ԍܓj4wMMV[ E,]{ϏLP9r||MqH']+.V>B+/tԟ~qݙҕ W'[ u2,*]7F^9 SZΩU:ҳN/z)JU/;3)]93iC?];N^n{?>֝#jک+WGq7/ݚ]=vG+w[z5ue)+Nޛ_;zG-u3&VFgǪ?3n_pFƩYf𪆺KU= ӻlas)=٠2{Lfo:Qdjj>sN+ƢӻKP[jS -{'jy;͞<*gW5H|zvӻfw#˨ [@ECK.,w`!hsU:Ήpg>>V鷎E)oNDox9zǦ ՜SO}p]¥ΡN.{_NO ޡx#?i_y:m:>ޠs{S잾w)};SvǦ}ң^fx_݇w[~7NǼZk}E:rw?SiNr~A)~3W:w}+\}?ߛҗwlπӽ?+O}Վv^wf灳wMυ]Gwlw;/;S:8v Ǧ7pfC ?o|^FϔO^T W˃_;o]Os7{zkx_;v;tJzJ:=tp4ѵ#];贤u=gڑ 7N<6u:$f6fSƀ`40 Ms?wO:کu<:uGj\sͽǜ:=/=4h@|z-xSuc~{Tro?R0 endstream endobj 116 0 obj <> stream xX_o67Gh  ؎S[t ^snH#)G%שMxw(XW>74/|6u3>E}m6M^l'xvjW;eWСݙc8_75wzZ<7eOy9[>{ t5.>'ܦj:~Zceéʐmd\l2tbn@MXDJOU!&)qi>lM.LNppMNeKɁ1Riflfux\/rULiía`Z 1 VbSw6aQl\IȄvG qͰx۫_^8kz x6RUMF-ǁh.u@ENp[+TK:WKsJOhmj SG8K'ە\7TYl[{K2v'm"ub1*e6nǜgZ7PGwYxX(Rg<: qʟRqНuGpO x>:Us "qZeu;"uɮU_Х$Z.œtQEPēTKnav7Ǟ|ަN .Gx3yuD[J.YoZ@*R"k Vh$9j|4ao :B hBgQ@_ ]W.ʍGahLL%>Say:Di%МEbɢRDB a~%Bkejb nQA H4h1XPha%ZfP "IGT= We1ф $$8 E"8)ݝz?ՖNN+ ;DMj4sH/9[c?,%=]hoG]ms[r(-$gdシ]m+$iL zTa뫴1)d> X'"]*0)3Vp#6bYװDBJZ""fhyjKq*p-h4щr uD5t;$񔆭Xe1VTmGpOiJ>2Mp=dc|*t%uyi6\4ݹbXs VI}"Ձ &m=CBp(<}ƏƂ[DIKin}Q@);nxMlU OwrYČ$P5f 21;3FuخW5]2 N]޵VN*mXxlSغlDz]奡^?k? endstream endobj 117 0 obj <> stream x׳$ugE)WJbu:`Pz#E@,A@Y,A X;~zjSfwNfU׽sg4t㋎ꬬy~y2뺮_<}HazK_y7/]򍷯ko|&z |_t5Y7zd޹NVE s.[ꍷ._{._;wkrk#|7.]{7!$.]'|.!5. s+OW_E^e.p\Tx)/k^ʍq'{+_|]Tj~N^W.y_`!GpexKtd޸h|f o|__K߾x BWO[  R79eZy۾SW4ZrDum ^Fr+ni̡kOXޫ!tL7d'4x-'d*5)i 5]C9K޼|-q9ٰg_KWn.I=Ҳ A_$˯'Ր}.O=gӟ<۰H3~zf'=k}Zirڿq'rN:@˧p#/, '?I,F̏Ӵ}v{ҵnv}so鏼7d>i &2gg.̏up~_g_GEE%Xn+ۄ"MNlE[~7R=_K yu߰G gtF-w@c띱љ v-g$alm4wӥgN ӛZ՟ك38pGAwtyQo/4{|pQoFy_{S5}hBNcwt䌎ٟ޴ݝ4MuWm9*Li/QZNeףxi'U*т,fsJ4SOwSxq3VϭeVw7w7bw"ZYHJNI=@ _ _9|O{i伿ػ뱻PV OB釨yfhy)k5Rj UsPzvb#&^>ڈ^zɃݏ|to(O\DmI^n#^N+B+UnΤٙsw4oUwV5kR5uhȟ$O5;ӆ;x IT'}q$t|͟D2cphBC{xd!?#tWG+cp&T3#Tf:+7\,#N} k7!}F,&+{)N/I%[NɩYFc ѡ5Wgth &m\7rVۉB=&˛zyq/uU/[ˉkyc)Yu԰2VD2F$G=a'u"ɝ(Nڈ?^Zݿ`-YL{m'D z[԰"Zi?HکSB-IV.դz5@fnT ΐI;ս[=:厡cq39}0ʹE,J9ٛ-y ջ3`iP+K>)z_~LMof` n;#̏GD83G^`x|wmg|Y<p.Υ3> +D6;>33j^]w J3YR0bVPf|/o^_|WɭBnDnjm7C_4{J,zc ` I]„"lТװz^8!l!"yB݉vof wHA:#40?Ciw= A_[ޜR*pJaLx.Khۆ5P^Msu-SV~o` J1boDNFsD`9Ty7a,i9mb#1z1vf 6˹FOb̬6ŭi38B̾E M)HH&듡 ?yayfT#)0o>fиDݧ#D)7|.fDsxx[CE,AM3rhs/Q܉)lE>#!~}pEC/@DɰRA=|:)2X"_ =E~+^M"Y5^lfT8L2p?Ǡ6NA &1 [QXs8&Cu+@F3o:F՜QQڃ|k*Em"1EE\J(1q?NxܲI[y7u.뙪^Vht%1'(s(C_;[n%VNa&6ukЄkSL$iP4 Ð.B+#L=FS+#*х <hI0 Ih8t޸I·Cah?_ i`CHE2I$ ?9w3>&|`v|{u{vS(0(cg:T.F1#]fH_+Jh+.Yn?HwpecJlM/6lX{e8`yD1-} i6ڲ+MҴFi1ם@sPf9RtYa3i8;6<{awxC''"M{RG=@H0~FkukuO\눹h1aW"H=='#I*-2 wVZ(ԅt))IW,c9!9. +OE%r"F!/Ӱp!_ T;nZj/)G|oƐr%PiŜQ5Hx%ghR3RU'tj7["-c%U(Ҟ[6#:\kB ~G'NH3N 894-Z۩4b݀ȧZ0cvCM.^c|M1~$;Բ8%B+%h؆͙YwbB %"* b "EcP(eymi".zmk=AMԥƬCk(B"ı"!5},%!(lt a, `N#,? ) pJoK-  %袩4U#Ȭ6jzQ1Ju:P]cƫpfd+*ZֆDO*#!O;5jR_8ŧET-jS<ݜf4) ƱAτH["mgI 3("FX(eRRJKUtR`0/ I]ٙ16 )wv VHkxz \M6#R2+Y5VV112gHOݢ ѯ} M!=8v/8ȾIoC9P|h=&MV,5 d45\2ۘR=9Ga3Zax.|X2}Z(Xid+zNIx)tH3'^l ,J7-UW>9}K2Ƒ0p3 5ȥx35= KZ)W+Fmp>Ցea^ xD@0-UK/*71>eh7Ecy5FfLBHrdg҄j{THȾ<:m{+aU[N_|k Q{0y• WnGS JZNB}feT.hDsdBv cXumŌa1z0Mm.\ggnPC@avVwDbpB)PF[Dc1P-eQnO͈n]uU k'HQ'?]KFaNIyDK}\jS族|{s'XoPx@?ޕ!@|^A53 S3[ht+R ;!c٫)~}7ڸWSd[v֮r?%[nNϷcG Mx8XYLU H0d BSV1(2 zɱ+T />93<[m"&`iBfn=K<Ԗ DN\Fg*HcKu4iP7sh 0pdnHn),J$̢NՔ0F<>(6c|FnG0ƤжY\#bhY ȃ.5sؠ1KeסpE8Ц;"k5Q8KKZ(+NӢECR&tz !yX,`Fh<:J UltJ"Ȧ=/z`x ݋ݘ>cTN!ꚣ 0;-+A6X~wSc:Am ̘4o 5#t܎ڝ(^ۑV, }H74ū'w@h#Iݼn ^)$^%%*X>1cE.D"V ™hLՐ2o?gI Ƴ o\}%ɤ0d- -WEmgoӉbUmY}9&.37/3ܝ?^YQu@G_Zy'y@Bi'&b6TK++_(2*T\o_\vUUAQmJ"=?{anSmz++AʠJ¢mSeNeb3~}ek- GWiMM:)@%\ɐpEA @%D+hЅ55&S_ƌ%c[d0fm4AðA,zV`7\I" yrVij@DDڲ ،hӿZ[?,+m{(60DϦ)ÌpCϿJ?++/<ΘY&~j[ǿRjs/|JPXk"#|1PG]}ҏ$5 L)G~^V^x?KA N+`!q 8}&O˜nOQ^ĵ5Ǵ)=䧵 ;'_X~\1SlzZoJe1bDIHBDssygk{s3ՖsvOwOx>0E_]0c =yV㎧/%Lh|B_ PȬx*_Y[JLc?V$n-z/G/?”T ۛ9gr_VFg0Vͮ]^ys@B![-`˂d+9K.hy;Blw&NMtȦ J4zpACpBL×Jj`扬nÜMfW~6qB{gH#qrgSҙ`,jq(gTDR sK4gF34i XF€ "ל%pRE) ?N٨MsR6dgz<*iir42f/VXE qAwI +Q6j]A sfG &*XιlU'g~]w63Rɢl8Xн*I7V8O"yo,O  QV1 :2 Lq*-Bq}@؄ -3Du{H= [>u*<⟙jLm,֬?h>˿wi@"PM.}>L%7.^oyWj:$ƒ1CC"vqǣczoU_?-uprnycθWN1Pu{ d~#jÏ~cHY\ӄ8m;@\e)ScI7qWS)ej?9<C:_1$ŇC{B(sa"ȿcc]74磗]Sx#?|Ҟ_\oW1f:Ta*˯8߿췒ן~c{^y%}/m1wp}Emy~ pєlF|f+>-\YM:S~輹V,loޘ߼>A1yca{j}`c3L⁄.kkf֯ά_N 4{Mm0S$O`- lJLFTԢ N0tYqd2X1iĊh5ElNI |1irB#28Ѽ#*BYT?"֡trs+&I=pLp()gdi%"}<5.!ĥ/pϬ`r z{\0cl:s1\rF|֙XtWl厮K*]2-ka89Paz41J6w!`D0fc\%Ƙ!>!hqw:1&p2r1b9 [@uHy@%.r*Y$֖Fw3B!)XP/y 50ͨYMаG–rP&]'79Q:DC:a0Fְ%b]aF1fPӛpWUDu?0c`+/200C[*A)E 81 ` \0u8|sB F" ?.c(ٳ>]*hT9Y|w[gU ϯO1JF%Qp1}{ƒ|b;k[B=S9*lńHPBT)[n֩JG۰bNo'㞁b'JN|ڗh>W}V<̗jP3Jya1b`VkFOW[j+yT\}1na4L\D*ńCu3OՌq \ )p \zf(7l1%%%EV/N<_3jREϟaèHȧy@ytPF2WO:~x"~?yC2 p6[,0hƀW-t$8%4CĞظ_á00;1!oa ec膬oŒ #Qog0 Tg#Xnoe$>_\ |XqйB hTN_ˑ[Lu51*|Q ާ#^ tg+Xg]//N.|>}+υoy/\Om? i;&V:1^%5J D6\H W sgxi EcBk"p!+F@٧vT k42֩qk޲S[tn/2\Yav0#zShuq# FՏY3iƒOL!X%&bDLa{2fSE%?G0\¿؊"Ky:ń zЄ.7㶩 wF"+uG xٟls$e p1C11b V.KWc/qʞ?]TY;cHjOVcD50F(K8#xy行5("?kE'R1ehW) ,m9]ntSG?@LU-Õ\P!*ζCJ޻~Ni !,]Q[U:zRӕQ>Qrf[UYCo6cms0K# ԔmL:QFi7O߅+i]; {g9Hg _U©"̜0ʟ`D;v4lD2X.Ͼu1JyVgO=Wq%WR̻{ྜྷq=ۙtJ[.ΎW"1]pW,_ 1,fnjhǾ7%jJs b}lI:^I QxgK<ٝJ) ( @\fKumՄWFhVU4mp|bۜoxnZ΁%~MҀO!/ET_WYʍ" `jt aA ˮcxj >5\pz+fSY'z{Wr-ldOBP޶VΧ/'ЃfLnOԄsB{l jդXS, _ԺjXi)oC1xe7\2xs=XYomnƾ\ >8]^] \Y \8SF y\ݒ~<9eDaǨ1Ƞr2Ud&ȧke LltX{8C㉘~pm,w ) `9. ,dUlDdf]^^XM=tgJtA+;f *qr,ovjw|BsnQPlbO[P)*a\U;lmMŖF{lZ(\2L3cLƨQlrUf qqR@rtU g*sKWn(`&!hu16Èc4tCϬ:ù5LEZB5ξo{pQ;.$IbT|,iߦ{~rt8&TNCzz4gӌT!bI+aԢa͵*s&]CeTRS̓He1A)EYUjTiNzȞ J-:'37|Èp59 ѹx&cPOђ~e`K1\UAQIÝULMٯ1߅k@u=z>eao ywF0ޭPKzT >BkK $ukvͷG5BN0yvo? ]UY;`͵ӍO.OX6{{Qjl-42^\UGT eڭsRؤB_mv۰٬ZǗm8NYbxDb8TVu@OEiϱfhwYSփxRB7~Z*j[/x(GȵqdOf帪4wt亏1׸nT𚥼FJ}AVՍE-8|ZbR0?სb9C0lc˃HvhQ bNBUT=, SJ2Pړ Zlc ^ZD=4Xm^frb&Gt/] ٓ#IY+]{&Ux ኏(?V8GRFhλ-Y" ZYx1J:Jű Crll{i)2HeD+Ogyѽ0٪2.c:@mWʐ*R[qp_-JQwgV>wϰ>NΈz[{s{;w?p Hg?ysHYt1Jo?]:}^C֙ E%NOԩ3y4Ûo[^~.]BoC^|ka=[nsUaF?  (WZkO#f' O*Տpl9`.m K )sTjvT=rwڿ7e$paot3 xpO}ZiAi_)]|Vs1w bSމJW^h\Y+tA`k9FsQ{ !aƮQgV:!3w:jm02QIcX_ߜG$W5q1!Q 5D3b~ |XCDۡ|ӵq0 $j`{&`Z0!vCȨˑn, k"'lO 0XnnӢ#Ǵ(Ƹ zҦIg,8⃓z]=-jR4O;V2\O萁)T+G&y{X(X=0s%vqXgIǯİD0FF#{LjT,216٭<U@Zta &\ׄ/ ˚1&c~k=$asC=bb1{0I~5T!vQgϳB=b3TTE.m% =w߽R*դQY+*ū;FwDc& QDp6V ix$^a&>BamYkJ{(ax '!A۾IEð% aʴş{C:I5;=00P[N֣j=@ 8G52 c%ec|F,aQݲG8)֑ x$&`l眽4L uUm7>Q *3ɤVC$tFae%"Nv0* Ɛ F{?o cL=*e}GK?]ʑΚ.P]&loL**GB]=in f $^V d#g)Yj0 180qq NRp 3ud`VWI$aV ˈ`Y;ZӢb Z*"R=<P,jX+810BGE4Jk(-l_&K34fTq23{_O2P1SԘKV2쒿G[04%S34QGώeMX/nyTbvݢТ̡CУ;1f >vul ѽH:tƣl 5v U>7"!4W@mmxjF' jNxh90ېKR5k0B-SFW't>m=J:qcf0XTB%\9aacGub0Ǟ? avdb}K FmO!=x#&_ź*>0W}`]jo(Y8%K0d[}19 x1BpU9(״ -)GOgmPoC9ٟ t=BA0 R 1ф Wq;T7a&@D7{8.tP hGN:g92{4C1,q%\S:NES'٬n VI`{{sa"Ҝf)zAT  -z5P٨dU1#]U!#^[C4Kԙ,O`[hF3#`wf,O0Ns] WƗvOJŒN"[|Ը315yLo qVe-0iɿk8֍pc~3q ;wtK(; btU!-9'Y(ې5\o Mp'*Z@ԓȴe} XնiYKgm6KImfsرc0ƀccfj ;c;&! $vwfF Fv󼏞Ιs{)77w/S]3e&˔^3bʬLJ"PtIŐ UP>a9#T@Hj1àF |'Q@I^Qfz 7)W jCf= ^@A$=~r0ŐmX? C m0x%6AܥuЅ`#pY sF,)1DNܨ^%_=A9J1Lh1RAB?À՜B3Va6(NWj{t~!3<5F`V͒p4fIV`gHƪ˪bƄ|%*4 `#= (%T |?f,i;a嘆&(71HqFT38.A "A]>JhSN*gLfPBV5 |OQ`3m: h3 <4h_=iPڛy "f`g/@`2T/>ʉL ld(:A ( .GbLYjU`|3˃~~':v5ޣA^n? ^W/E+l=0D3oW 5r[nD&)L u* `% yj w5hfcM=4ʹ~qʬB2P+# ҋ.e^r)^A!TDByX~`@Ѝ5qـFX3:F91L*7نjj SB؁a8 4UX3c5+qIlN"ӚobŦg$?| T.$@<=!UNx@<=)au p83M2k ㋠%yT>uW%QVC:D(,PZYXi^{XI fb0Hɺ'5ݲqb}X\.E2o&\|RP zeȻ [eOZƚ{u@x@UWRXD фhN iH~.eb#(3?|$ɕ^ O+rTX[ :)m<i@;V O 5eB'X@0Ӭ9-A J5ʯU*{Y6-̙̘f{Y-Y6p2~°s% :DO}{̭̭[؀`< c޶u؋ݮ9}b'VUT7e"|Ly_i %Kuߏ_w\#oڇDиE\[&)5 huϯF#on5= Z]ꮸ{@Br:&Y-8\ ,/#4hРA 0"s1hРA 4c\-a8]A 4hР %c^s!T1ϴu_ӠA 4hPcs; y1p W˥,E 4hРA0m9^Ʒۍy/%~Z>?.P a2Tr4+(Xj U Ck~ŕbP&ئS~Z^%zOaR4hXa 7!kCQUhРA- @chW֝WSb٬)Ȅ0CJcO>jeHE-0R>n7>u][.4hРAD?89 |C<=a=Vv|#$.cT =DjYڪ]a!훎ux'a+uׅ 4h\0m.O, {mq!"µ{4jpXpW^ 5wT~ >rJ1nL˸1È^ T^U, BԺSo=qK\nex-4<Ԡ,Ν(!.+)$5_m5i݉oNm: 6OZC0Ψ֠QRU:m<4hРA]6bYOB | T}'KqtsB8gzԊQoBPf`Yx-(2{Eڕ)SR),$O@5*2Dw45{]'RØhվҺի7:Rx[$<ҠA[@6ESMÍ=JL`|շiuk_u,'D3]}J,(ԉQoe2s2Тw,ע|MyݚIӦmuXa0pWi tʝ+,قixg^8yyU]VBV޴HmA 800HkԵS@0>rؤY vILO@w_e#Nv k,C W=U L-WM,  vv@P!UXexl޹"ϨQw_ gɬ }u[WouԮGOg 9 4hиh褤Kb\ Cb\ eH Waѡ^vO=Ynd*ZG9Ϋ᪯YkaUTB«gJ435Ofo2!<*G&TaJ`ɪcLϑ#kmcU 8ApUiРA- F&1U-\Oq^%Zq $B\/o`u #qG 4h80m.Q%QO0Iiи򪃘MS?%4hРA{ӽ%:Iĺ.q، hи bKh-A 7 fV|tS0I|]WcvY؈F4hРA €C"kI%r b$Rt ]8RV25?8*A 4hР %CB n^"IIM -B -bXX.ϟ"'[ϴu@B -B -By [w.HL,X9IhZhZ }Nمq ";MsKӋ$K~l{iZh@>%Zn[14)SC>dkc/\c[]nenWՆ%Zh²wR!Pb~yAc/$_JIs&?2*";$+:p1|``@(^ag\`\: f'''tL}s{luWWGs['jaIAA۷K\@ Xa]XCvݠ1eܬR'Lm䤖"& 6* |&^5ػn%zؽ"5;n1z{ZؘN)?jjxlŋ eTͬwUCjNX4opp_oY/+ (oe|cRL(r.TP(Ofz%sxtxdwuuzULJΕO0^~ǧ"Wo p]p[ ˡaaZh[K"2 @0v`C@$fVq U/_t E!/PC<"rOk;BBa #<<mUx6Td!iljnjnihlohmk '/K6f?Z SeY=aV%爪~eGEE@T2E2ĶԔ4] BHt!dtpH I{{zzPǘظ8 {[[[)ꫫS 4r_<1<c j'6߻hE4xvc/33 7o:?dttfy-, I$CܾO7D?\aa!u =gG9IE腤˝+XTҍy)fc|:-:t4ft }JfEӊ|X(?*|ĦTBu % /Q==ݳ lJ?:?29%F233KJJxEPraasL?pb;ң{>NZ jPP3/AIB;Mlq%ŁAAAp%88X擒jhŅ}=peM#Ǩ-q68"FGG &iQ_%t2AWΞΘY!}ձ/y_5ô3UVS~y?HE> CGFҭqKťD2pPg"3zy"}||ۺ{s! 1X=Y7l!Ɓ۷^ eٺ"Րэy)rjqa8:'["4(Qbnn%ۛlT>w7}"y"heN앦}W~hreh\|3 ity +d.O.vHO 'RS3224Z4 1W3D!!f@ѷ# 800׌^j7/."$E>8077zL*o9{ N/ cޑwlX]JN\[/-$^"z>nmm}yQ&emw0A"$00u 8UDDtρﭫ([o]!|38{e7Esp Оدy핟'v!V;p8-t r9JL7fb5alIxՆVvI6#M*1ܴ,_ 3}=|>88R᥁ͯ_/߬xýT* &T{>K$7( p`%lhhЪD T.ψ8cҋmShqS]656X9*(*!5jK@3S+fmz CWglz5 GeKw'GGCy<=iB -\7\u4</e KEln`\bvA)X})BS 3ұ#U{+wsJG ={wbs,"yT Ԡ-"8pχqN鼯ٽc/m@&,S1I]ϓ1mphajph pgϞmjjZ{@z9x/*XCPkKzTٲ+ Um5xJJ999jANS{yhS̓a캟*mO|iucǎwo/m2!IכMqgg8D}} Ʃ?C?{=WZ1ҢUEpiK< S3SN9Áft0;SQQ111VŽy#l߿so^ (bwN0IIIYXV<]JY*l#?L<#r=Jl X+ۖnbTUU n~Y$ izG6%*եDk_OP-2;e\մ\y9,LLLpozyyuuui-44F.y*=@NDzz6"ll%{ll|zؖXXZp;;Fn}"%,,,p(Qx] ϟGeyfna#o1cznCA?~ٹgI63|2;j 7n 0,p2A0bbϟHO2{z죾YY}}K>>/2N~33?C2ya?Ȱb0[&/ou8c`^2};uyw ?B"|2MM L"|8F9O$1n' )d1E¤XM%9OV vxpU 1Ng( Frz%^"c񂩁əaniĉ>y $… B\7LN&Eƣ %~jA13-K[, CijWw߼!U/BG g\9ǐܥz1,쥅i\4*p_hoOx\h÷9qePby:11e훚 8/400s΅"+W6ZmKNN},W_<+y3)Ј///:z,kYqA߆P8*9uI^)IIIAAAKt>>2nEX>{baq{nݺ.޹aǞbLoMOk}'`n DzYʍ[qFu]-D7岡!B{;A3 Oѳg&zyca10G48a<0x ي`6rJKKK:'d>JcOq/Y!!'?xUJ6*kk(yyS.VOr 8ZK=KZTS]e]9gMZTkلW_KGÇA- _B\>XꛁfgDyt~a  xfQ _ثcF:ћHq-h{#Q$sFvHBq(1̫)m3]ƻvY;dsV޿ůc|Wwxkܑ{mwUo?Fl.K@ɽ~׿;<%iiK@0zzPTTƘM`I.UY)CVVG߯k !faBƑq;>" F;ip F0=I y~:>ĕ5K: ^:=oXS[UJ[[[e{inpSRO+{p}LZQ_+8kFI.!VvIJJJ)}Y"V3nxsH|H;'kl鰷߯wvZF87(4'9F0p!T,L`r8Ѥj*& !eZ,F2G$e!%BBi ǸkOF~k{߶+wlɿ˨^_x75O;5>w۽ŭc5/BKQD:3݃G. ,uoyήP zJgB׺6AmgllMsrr: V~PsYzp>4Zm#ނrN^)'QIp~FG]sMz9?J%>>(|\ǸtREEEmmmqq)T6&:6( ݜBl̲!x2ۍh#ܸqch?o?uO,!<TCNvTT-pnֆb}?J)X8/mQhhhooV%/=gbXNe7âaRk;::c`^ŎES~ Ȟ-ͪ䓎%pEH>\܎Ryvn);憚Lζt8J?mys/jAKKXqvI ;a(0K8}n&Is Zh9b pLgY6]LB"qރa8_-ss0L&^6#4MVTJy|וLmr,(*IL<r!*!-~OIx 7tףz^ҒtYѥ\`û~eH)qSXsbc$sF8/_]cӐ>AƐ1]I"];q)H+11>TabVn~{=XߚB iGkw!ӻ߾r]Jzjkzj!RK2zV>}Fs3, .ŵ>bرn VKva8p%${?EseUF0g|JH/%Ls=ZбA'};_j&3W3# @S ӼxfSK:pnۦiWx鰀kJO^:jw|FNPR|Bb`Zъ 9\^g}bW֩g{RO􆇑+M1cq xʤ8`BX/[t1>K+IQw[hU{EԼD#W|uO_}Ȭ/g硋O2vx^j, ymhgf߹ΜρBF_AhKY;iuRDD////==NJc@ #2_ CO[A\ol{7~; ~~~bVqs.p8i8l67 5vm 14dǀ_cbbc!p鍍SSSoV!17gփ'%bAd}E.O}wwwRKwp?A 􈩓c["J ~ʕ+Q EII;ގӻ=}mlN;;; cdVof׃wv|ʆ@ Wpp1]ϲ(hR"uZKV{cl]w:YqreGv`cV+ILtuqoO)?P^GB3s)%vmתSI&AӺM:X:8 Jrtv#OvB\a䰫Ә%^78c^\|?hC߮2_be cSxy5333 t'-h!Ccظ,T,X1v1![^IRs PX~ $CFDuޗ:qݻwc^,1f^τܒ ?.3w'DOK_M墉%3gI+` "* Q v +"*Etf .ev)O}癙MUYYW0t;AGEgk]z=S߆9B'>T$%%IKHa_z@ }F.T###a !!!0 C p2Lc㊀)_#ng;\6pr/Pb'n;~{;Qr0i$M9a?.+0ʕ+lWpppxp4iŋOu讏'e.5y/+zη_&_W]`}6oߜzŃnQ~;mAH> !Ȁ6Ŕt'8Е+{ﹹy{xx̟?(::̙3wU xo豟_#/WX^JB#w>!Ϡ}}}akV=ϥaM̞/zOW3Ss{+|Pa S?|B]uqG{&_-烽>~6RQs. R5j 9z(}.AŅ&%^RŶ";0zԨC೫(_@1\W3}oi5%Y%@TU%TY:BK*nuimrwC:trceZko'=|szc{ۥwub&vw~͏|w4p@///jnݺv#pH / ߾}?3 tDO>l.CchSo'N1[af {ϧcE`p@p:o }Ur>ㅢmWeV ڶ>ܻʪ/_w-W=%NjbG|FmRVPI<;oC |}X"!!.322h~V ZyH' >Iz!.{Wv\er\VsiePOϘ|"<}O ^G+% v>u:^ ld ÑY{v.^C&_=׮|62+xU$@g_*ܷvF{v#@#EEE͛;wˆgNK8yq\]] lBRfy臭.añcǎ3$h `r/1U`H:4l ,w233m NO :|jR(>h~aH wڵS] ]:ԁH(5^!/_:dnW/gAsȈ,A=lvfA(|&ddV(K`VlkBN+X޹sCoOXۗT次Ipx0HAkkGSpaKQtR Bafnp̈́9MXK`;  * /osd/ɜd)%UxgB.ѲY! ͛7''4(X*aAϰwx$4‘X [ |i VpQ&ck9 ڏ0iB51tݫ5G4\BP( B2 BP(5d-cEP( ( B2 BP(5BP(J !cP( RC63Ɯ!M94,2 BBa }S2 BPe cP( R2 B@P(ʢ1l2 BP0F1F&rMLz̩'3$^BP(22Fy1Я@W ^WW{] ip…OW?m?.K'RȏW 1BP(crCCp_l9D{=G$ߝ&}/!+#cP( eQfag[V # >a-I2[˴Ѻ% | ָϾ4!\!a-7b-( BYcTF0HT̪'ꖘYHC~ Pԑ$їkR%WC@P(ʢC>>F,2߲0R֪ۭmtbDY);dlߟF&Z2M@@P(ʢX(*sQY?Ɛ-Sj~xxS{wwuUzRZoN,P}xL dKTY'^V#cP( e1V˶s$d+Ck"cP( eQQA/d  B,J1*9(C02 BPE&@ BP(e"d 1P( (d BP(E۩Es;JZcP( RcxrϨ=( Bl$cރ!*2 BP(KgA2o3piQv+,VS e*^>U!{%63FxxL(S )|bT1h| K!pլ>im [a:XRXΧa^n6="^1=^!CK]m/tjfsZm|= WE _ҏQwDpVa:XRXΧa׻Ux15c{񌩛o^~83<9ܓnx_osNTlN ǀ4iYeUjnV|QQ=wPAɩZkQ 1% ˱d-W tʌ`Ny?KVTRS B2ؼWNT͸t> A##҂Ec'/҈snRؖE)^+CV \*9H4 #ŭI 'ꢤY3a!N`6y&4Enօ6TSp jxy{ Yq⢚\_'y:Q5~;J[}dU7o,0E=1ڹ3v2XUAKѤP.1RYN2m,CY[dVU ,n]c1FC;]kwR~I<;$ :Q5< #/]+M T U.]'Oڎo%<[#T&6,,3p5ޅG.4nnU)e 5 ZT\)q.ZTL ed[ Y BadNw.` TN;iIbt«49\]Ƴ r( #]1hmqvdvZzݠ-n KcFdF_| *@*0Kȧv˦e} HR7Ko l13r>97Rī+hٺmpxm:Rb w.uFg"E>?6˪HtYh|}6Sm:B`L\вFA)Dd)n~Xgh[5c ?fgnioKK@21{Ie$)"T6uR'f ^Z@>c0v|Z1`Ӳ>>P}~[>cXS.FȺvծn7K#KהlF&2=>$?W"1q܄u3@(qaس1t2Ci?)Y0A1:qv,Qa cSqM[O'037m(?WGrQČKk(e<;B>-#iϕ0mvaCn%6bb5mF\'ʼn{sl՜$J2HQc NyDp@sYV fRKt,-+COf6${Y_"3WbixWf2` sdr12nN]|~.>j$%UdCo!O~ZH* c:¦Z}me-,& K ,%+d#_҉5-͘4i[LݧYtC3_POXX,2F"c1cOιPu]5oE%Y' 'ؤۤ+:akZ1ƝI5UÙnr8V<y&IN<3u,N\MV 12Q@D'uM&ƿ<1yϋY`u,ac$9VZ )bu>)0FiUmA#3e / BPM[0|1a-c8 QYPݡ{eW_=KFJƐۈg4rhz`/[/]6k~pNÚg# $cO 0FGҐg wsaکK0~ Y,֓*21x!gH`ⱕL9HysXzԙN s'3BlpP`:x$cmn}kBvAOɨֿ^~C72&~>0L9Կ<sX'Ozs^J"i]6mqgK7mm͇xLr/aq~飧7?I%" 牐6_e39Jj!ŕ5y&(3F9c_sg]d|K?,#?6fE!_""0 fٹf#aMܱyaɗC-ℏ[Gͯ}̽o'vqSOandBM.'{-J颐I]K< 7_ FRv%[W7X`˜rnu7Jl2%>Ż]G}epL<b#A6@w}qAk^QQWb I(eƄ}F9owTTJ<ˤ `2jϧǎ-)si~k%}{C[}7mh6y5kGq'%c6O!_t]P98Oni쇄^' 7rԯ `8VVdhL45F̵zf\)̉Z4x6 $w ,N狡- +DQKgvW2hA3׸ {rOźcoO﫟|{|̧Id|R):3qb5žq5qR[H^t nR_Dwo)\ci쥍0$`p镺-vQwq$` 4f A׵&I׸ڦ(Vٲ$W``8<~rc:n}=/@JJe]=Uzwb+W.,c<-+afL*:ݔ.O}7h\Au9-0Y8]>gaYշ;_go?B#G뒈Gx3S'R>Ɵ<{zg7?~z540oV҂JhN\A34vL' ނi [%  4l{wg/c8ǿ㚤 yݝNQ+E,c,/jNd>wL2}&1N) VG02-hr-pFXbޝeƐ*hU1uU9+#Vx-ɓΝ;zӟx>_8tzՑۤ,)=J~%iہ1!s;5I.y=o~0>޿~+2@%ư<`qwB&wį6iS <6vm\f` W}}Ճ.x]?DD'1$9D1џo"h桒R/'{]v].|;W_ɿ;Js%vfN# blRnM)#Z?Q8p 4$IJKF)*L{k2+KOQΕHYHl_2-lS7bUzZy5n1*ŌZ+pammG{wl9::<՛ L#8ZOȊ!)Q$j3_0>"s>drߧB$'xb!= H-Pf*Ɛ+1xJ>oGl{'xy(.ٕJw܉Ep0S"ybO p7D j `rsx!'Rb65 Qd!́V#ݕ5bU:z+KѪX#"112L]ϡ=%՞|BwC˼^1xk+9cdȄ(1UxL}"=Wd(j 00߂d%}5t 9ލD< "woEˡD;n*_~~~iFA9;cR*b c@6q̜ͤpdBʼ/r(7s'H#1pbO(h Wz?>cXÄn ίry#H~q0W4ìc6d!%v q/ Ì 1{'F 9c0`FiEUHFUkjUM*jUZ jSZ֨Zz@-5*I*V>Q.rM,kI jݧV5G4jZlRnS+ݢV"nR5NkԺjP2.Q뢕d^S a1)-iƠ C[1 C P10Tb 5C%P0Tb 5*ư0b 5C%P0Tb 5*01t%F`gLJ1 M z@Cm0471M 210p 0Đc /fÌ3&=`8A􀡹Ahb,&=`iFhL@QfI471 41 M z@~fI471M 1&(.c&6dbmAhb8AFBBe0`Fq1A&=`hnb&=`Ahb8Av,fԇ1pYM z+pJ0471M %Ġ 41l JHc&=`& &&̒hnb&=`8 c􀡹Ajb&=`@&dbj3&=`a?$&̒hnbj <e db hb&̒hnb&=`4*c&6dbmAhb8A #e0S􀡹Ajb&=`hnbj􀡹Ahbح,2!M G%Ġ b 41Cs0471 M zĠ 410l` R=hbhb8Avhb8,&=`4cJ+S@$Cd=#TEYC Ġ M zpP0471Cs0İ@ÁL zsC1J*.Bd>1F1S􀡹Ahb,&=`a?$&&$`(1F)1#C[@ÁL  41Ġ 41gDs0471C+Cyl4W($hba`@&=`c($c$01xc)M zĠ 51Cs0471M  M z@)M "b G%F7N)M zĠ 41gDs0471îC Ġ 4161,)0AsJra-ch hb8a?&&6&=`؃U c1Č1̰1Cs0471M %Ġ 4161M 21CsC=PfԜTf1Fl1Jb 41Cs0İYM z@Cm0471M 31(T,cgLC @ÁL z1M 21CsCmĠ M zĠ G410F1rAmvq34f 5Cs0Đc eNPGȁlS`aΘ6A3JR2S􀡹Ajb([Z4hL[HF 41ĈW`4` 6rJaŒU-2=`@&=`jb M UC|5&aOn |Vknba1ʀ1LQg ]3kK+1 41İ.XЂ'pcJ*]k{9L?ToАcTjjao&5Q1FŌÁL zĠ g51-8ǀn$DZX i[;zܟ؃dy# >o(c}UT6WEjL%ưf #f1FQuh@pJ0471CsC`gX{O&m;@k{Ip>0471ÞM KQaŒr 0`}2ANlbރ443bÆ 0hB;9s͚5k̙35ZTjMVA~*W @Am;w.4`Wh@{>tбcX̀q Uo4aM 310:3AM G%$, K@z5USƫ 3-Zj*عsgll=zɳgrV 60Ahb5,c ]n563=`@&=`쓪}#Ans֭pjX *񰢺 ei(5xlT>Gg aql~^$DM޼UUp$p<+׮oCMC?+֯_bʸ&=􀡹Adb1|C Ġ 418(((`M Nd軠CMߠ 1cs/n梲9svH2l*eĬ̲73Jo/~zz{W\I}p9r R.&0QDm<wp7" Oc-,9Ɲ|6αq8 ęl$柾eSys!N'f>3|e3L6YS~ qpy¿´JrA] //(/r.쌺+*}7;`wd"&"(Q"?٦c"hOTޝGU{?3z>yfL/Ooz[A[v"D֨-@ߦFPPwAEL! *U}߫}[!I9J}sNllyc;S`.*6ֿ4WE&2 >}W\~͛7Yʠ4VbLQi {`s"cPĠ%FያnUIﲼ-[g`x"!z1H =LQ#G 0q rtnG؈uأ[nZ,3 !GSoP.|$ٯ6(@}*n 1]p$=!OQ1 yfȧ6QSsN )F}0127Ē̚V(qx r9œ`aNM$ sçPBrr}r\ga0VpZp܌㮭ghƿH6ߗIyf2hrQK)**xbYY2Zqߖ#NJ4nch%D%I1'$%\g>|xҥ?Ŕp-+*L$^ *F>FoJxP wէrĺ.{鰅qmp%$ F0+X,A^6P3+>{#94d{v?F!aCʌ f :d\$ %c$ul5cѯwUVrLYY,,,,׉##G'P( |yYn׉llۉllc=DzUL8c@|3fXfΝ;?쳯:''\~T$Ux%QĠ-11zc13茑`^bC+1Rm0$=b1 >%%%MحscPĠD)1keBb |#PĠ%=0Fm n ^YYyҥ\x6+  d؆2d t2F%IL̈8}&xq (gv Dd`ntiwt۠0Ă`5-h| i`l@VJ)4@4]Z#qGEfH2cD`H3ƼG^8Gp>}Y8uϞC|J7vW܃rr/[or=_7߅yh`lg˖-[vΝ;W_}K0XC+1Q4ƨ{ Ę($ 1Zxʬ,xc ]iaSԆ ӑbg2zh2hC`;>3F1a8W$#AHbl f i7}ꐠXbC %5xT$rC'"CHd4ع̐ 2ښ1z ό5~oox{m{ufػ͸w[,n?ػչw ?iUxVtct[ϧnڻhdG';>ax`%K[nݻw%//ٳ׮]?%JcJ13FhaFp0A K z`h%FZKDcX,o5d!Ϝ9_'1a FZ~îȰ+<348$Ag2ﷰ 4{x ^7IĄ_H0.M,!&(,43xfx+:,3ءBRiDH@Q 53d1+ݱ~wlla;w}ؽCdχ8=pl>}OBZp샭 8{6tж{C -;75԰sSM=35+rʍ7~G9;v.f~Nc%FcĈ1*H0T/1聡cOI&c9TVV[C6mDAaElw!Ѕ;rˍ>(C(# dЉ1J\0nI<1$ =lmB~ #Sz]VCd ֜y:~Y19dRJGQ G+=WB ,~{ņ`#FŒyZ|*!$*G%IG^[hGͨ%"3i@ 1BC0TIRfHᗝ I!\E7Mmg 7m$SkgO=bM:둒Y陏|`{w3$0 /bŊum߾}޽.cT3>1聡zA H_Ae ̌5VbLQow^WWw x|1!0FFe0"0 aFN@K%gN7惽1q`if >jY2J6lF[m\ç|]xQe,g~glxFAv}Pa/pOЀת[JaçRԔ|r͏v3!h#33w{キuVrtIVVɓ'Ϟ=%=0a2#Nj `^bC+11ٷȄO$>/]矿c0!b +W!iCb 71 3pN#Hǁ(1| aAnc󡪙U|vC 3j 'L" _4jE[Jy/<3)E9#O?rG?;Yc,Zf͚-[|G_9rĉ3g_z%#1C]`L#1ncfn :N`^bCch rPI{*?׋c.11cn1 e:|[w)Cm Q|/-زsxHaA/7dFQ lvnQsw݂AWh٤mxb>Ǎvlr\}"u`cڿ;lQg3=̙ř3K^Q닧W,^xz+( Lod3nm{^aVہ6a˰ {:9(sfD .\l;SiӦ={1>|1JcJ~GƸ1Cj 4Ơ%=0#%FP$_ڵk#C0EHA\q3bʍ| vH- r C1"c hD 7o!= lu+Kaz^\ o&xd0&rE[s5f4iQņ| nE <nQ*ɯS}tk."cA0Pc'!]\ogKBft1#bj4c(Œ ?c ǀ1V/{c7/]ty٢eʖ/,_bª]X -+*ExYS [_^Y4< _?=1${cJ2f#PĠ%=0q.\+ yƈ!zJwOhdG-rr l-FbFL0*n0F.6 6dQ <,`8!MJA?F56Y5{c.nw$1%Ubc\F/4>G(?Ìąfby쁫ĸ! ul !34ҨH(4svIF"!5gƐc?:Wwt˫AV/^Zovoqu} ina-z=l\ Wם{Kb~{edtƠF%ƈB ɟl Pc I>%ƀ}]Vh |h :٦Oٱx j \G L |[ldǕy` 5cc4~Xנ]@?=Fc f{ Q~OD5$Gsd2=g &&nʬ>=_NH=X wnA*aO-!S=}hpCHG/*4TFqewlk9Rkcw7ڰfӪͫ@jVڷ!tua Fe>|^+wmjɂi&W2F+>'g z`^bC+1]bԱKc1Vb#1^*k Čg!0Ʒs%3@ ǥ谑-x`m0 쒑oAZѳGtz;v1\H2A{u%|d*A8%wr y[b0TɆJp 4 U39g%rF7Jg==dU0Փ"(<0\gqB[!<yόЏ̌q H^6?<3z??e\=Zғ`㒤gܒT!Qad0gdž0y;TcN9P!gd@I:<{v3JBa+=298:HO0PqqshꆏW̸&j3:`JCr)3jzɥQc#93Zz}fW`k/.d?-?-]@< %`X օ-v`kM2l v}-y[!HcڵZ.0ƕ1FTqdIYbC*_c2'<쾁3'dIp1^` {jqv!Bbt3RP]+! {A4rWbh7tkÝ6&¬̹=9I-"bQގ B t@W5N1xftrǞfg2C :f( 1GS$ :*LbLh)T2ƍa u)#3C`۔J2J2K Yc4 2Cf0mƸBs3+6EZ#00Ziri¬fh)7cdCQ*i!ty_62W#==t _cp1 K z`h%ݗIq#:JcCZC c;!' K]=gP&i#]G1Ce{}&;;Tr^Ͱ$]l:7tB$Vi,05={*L9:jAwqdha1DFu\Pd|! a\P~Df=})H#P$ <3G0D_Ƙ%=0#19Uʉy>6.79$0F|,8uOOBp.ʅk ̐ɘ!䁌186Ԓ7Ri*I1Ä1`wc HwVc Ę(%F11=O}`C W6)_L ͧr8❠ {mE[y'-0)?Hg'Av@|Pn&H & GgvJW`*@.C]Mb,F&F&3+!(4' ǷXhpcDfH!11Ch fp-2UIw#PĠ%F^cXcDo I0]PĠ*1ưZ#nvi(e@1n&6z&"]2NH|XQ8:t8xk]"H9܄LVu=ܾɋV pܮ"TB:Q*:eO$LA\+.w8DͲv67 '.59.5GFǥF& KFhEDf iBZ4ćpK0KD'#PP7Ir+; #q2 RU`d)4U7%0Ƃ ({Cu1)K z`+c%0h#5nj{cIYbCv}w c <ؐ>>Nt&C)vI6[kZ,h9hLY @xBTt$:=7:ݐuv]Co&R6Lpqq >MF& ȅzFz v3q ` ~"f\cN'qG <UzJP.4ϰẗO( )3H7x+MPZ1~1zcH4ɨ`h%d-1R6ųpbq $&gUNdx!Aʀ'}3w8K#m͇̍"\ Dsn{'LfrONaž^Ÿp,n]_exQ& U\#*>`[1(=!)AƠ%=0T/11e1!`h%FK `jGӉ g/6uS7|޹y˿f~&yj-e#g]e%f 1&eAPĠ%=0IAxhaw81a DJRm 0cO1jkk)`h%FK z`UC137Ƙ%=0T/1 Ԍ1tUiЖhASg)ƨPVbH$Tx@Au7PZ1K X|>11QC[7ˌ17Ƥ,1聡zn`Sch7=0T/1聡zA Zbf*3C3WT]cLclIYbC#fVkc_3OK.0cč#0^h`h%PbnH0cC8-2)ƀ JcCWƠhA.1 K z`L3F%U1M[e/ɌrRĠVbladWX-8&sO%Fh69f$1m`N4F:.1聑#11|0^}}Y?`E量[`nE%cC+1&Pn`sՂFL|1e.IQ4V1 K z`LJxu۞(;, z$&O<Z:nŻ7F:V)1-P5f1eR.Ic0F11)K z`^bi2Fcka.@Ky#;B$P0:q+cPĠ-1%cj bf[a_D3L%X 5%c|WƠVbh%1\&2{D_Zn.P|wĠ%FJoϟcK4chd]|\I:`h%F%1~.[M(6 /_[1Vbo%FcI1tl6 -ЖI$1F=sO_}1Ġ%=0ƕ1R1XDz/`̙isTr8}KV7H0T/11AK z`ܵ1n7[̐P%C[&뒬PĠVb`w$No1c<]X\UX\Ib0;[QbIYbCP2͛7e{sc@3LEzrA4P#JtHwdKlsW]?cqxOΘme^a,Z[Qh z`h%*1TFƸj Z-u5~iJO"1Ɔ 5F:zA Zb^^eډsNwz x⩙/rte­8:cJ7%؆2$h4FoIYbC#%1J[w9yH>J xϴtS|v}Ƃ9cLd%F]YCVԖI(o6 zjJcVbh%]C/\ŷEs={(l xWϴtlں[qJ2JOƀ %c ]B6G_#TcʔP+i;c$_4~d(h ru%=0&hAt#cKM톿d5ԁEv}/_h2}vMAc!cbnTA ĸK 1zzzÝp]],.>3սjZ!$ t<Cc)1"h̄3ҥK)cu`^bc\nc,z_|{ccƿ<= n\ZL_x[1}H0T/11AK z`1owL)բ|4Ւm\3FڞCcBtC+1c6v>qpޅoN^:_e07sNrf:bJƘ@%=0T/11J 1,Krc vD؄1zcHwf ?̴Z ëVvv+mʬl?}ʔ%KPmJ%bO[mp︣>?.QmI ~蹰?_tuу_G'x@H:<{d^hR2?:Ё ;qR5 )A HwA{Yb(x-*=vCǕ0fΙkp鱺^~}9b((apFD$uJw^I8a}f6 !O!"7EݶⷓlBwƏ'_-pO{ ?LYO:EW-͔{0)s ?3:G@"od៘f@t"鶇?U%=0&hATlT)>[Z]:K`d ִs/[%=0ctp84qEq"P<9̿G`^~%$)2o3_쎉D_lWؔ H-=a~?IK+ g%GW-zr%wmFpI/F";IXktc%j#e0c>Ġ%FqK %cfkiu[YMպN7+`,[܊#PĠ$.1R4;frGI)#ǕPG!Cy"2;$c[B q]J1ɗ{WfFcHPylTKdPlۉ&Jc{ %c,J7Tb[nz1FK6寻H򮕸)vc7nH"!JcLFIL)?# ۔]QvT c%m*2,I|&,7BK|kWyU˾"?Y4?"ɸ()A"k M?JՌ]c:`^bcH1V|]Mh68[n7oo/؀cZ"1聡zA Hk75'Babׇ}" L\ٛHpܼU(Z/f=)cgs6)|բ_Q#d|#'_UH4v"31"}Co b"f_1nܸ1 K z`+c0Uk|xiwz{hxeh1o[ql`^bC+1Fg[w>.:8Ym"|թxo_νvJƈq&C+1&wAQck~-hza+0`-[`@֪ws+h P)g`2!xC2ۓ~?aI01JJJ(A K z`LjJxu茘Q'`m{h`t5s+1C%1nݾL6chE; 1 U1F:zA HbU1yf/6mGhKwmg}vlfkgd& JlWd%Y%JaY-K8XT#[-J-^A8I At7It^S4B}`61px b1/sf?,5-u1|$߷r>AƠ!F)`!bH|1Oi  bcR;9{*Kӳd v,1.\4P1c^`F|j:_cTDtg0]9qQ5{&5-u1ա e  bDC t`̾wesHFlf>@4b3J1\GT[Bƀ|&!dӧO5`1Ё(cF.cD(1px bv::}sv:K7oE|4Pw Iƀw1ƈAC PA!s|ݦƠ3 l.2|h t`1ЁQ!:0lg`71$c\r%﮲u1hV3·0`1ЁAC p7`1ЁAC"hnn^d[ V$5-U1<;1s+cCb>,3&j UX!TcXaj Z,!cC.x뭷p,0h$ưaf 71hQ*{IJ=SZVz Z"}B0!F!F.c1:0!#+0dkij Z* 1Ё(c1rgFVc d  bx:!c<ٳǎph+ch0 1bCv!Ơ!Y`(C1z,̑162O- aװpy_յe&e n.Ⱥ0ǪN=,skZj*ƀX(C%l/2-,0h`>}%2 hoo].}_(0jQX{!R`i p.|:=3DuIyϥaUR1px b%H1#Ocx b<Đi ,chںz?pZSSwP7aLe4_}3F02m3 #!3j912r+|ƀcPe`-(!c2@21C2FR1`  ]7 V}hxt`Q0W2㻞ccg`,H)"[/0#xz}%˷f  b(g/cxr#:o !mV`04nG1>?c;~^uM#C#fm|r^ߍA,x%3Erx~_xRC6i,:#ʲ$}̇NhD6|"C t`!1_*ᤑL+8AC !FN`H51^D8ggQ>]DRAng1B?C" bM"KeLJ<3` Ug t`(6e)cx3*C t`1p1&''aIC1N:e #F~.X ,x=z̧Py:tD2QqT\9$cw1pC t`$@5g1⌡2Fa!Ƙa FS z'^@ +F ^OacD*`FI,^SKƈsWil9Dct: bKf ,0h`H2n=0`w HY]"v2M 1Ё!(#1cif,0F,bH1TbxB vPcRq0FƀO1pC t`<Đe;1$ bCQbH7s'c1h1c-nϓ5`1pxŁtӜ1Xf`2`C9b1X`t1hDю 1Ё(cJ>acH9B t`1$mc l sPgf4}%T[0mt c t`C9 baF1И4Đg TfCa cRk0!E6`C9{I$QƸi2#1bHJpEXQC1Ơ3!1}DcP b1tl6 R !:0J4@FƠ1FM 1Ё!(#1<3q;1Tbx 14Ǡ6Fm͵1h !XC'xf1ЁAC bC1Ơ230o 8|0Yc70@1FlLg51Ɲ0(hZ1`5Z홳g? 7n^ -e1Z3o UP1J1j 1ЁA<Đ R1e $Qh.1c yf8A<@1wr0h!iE16Vda dCKךڴ]ή@0`Dܰ(f$wV*1^@4|J%@ 1b0F`2SE5`1ЁQ!:0 i OF1YTQj  0 &Xg#5`H9)0hDq=m c0 1CH3#To 1ЁA< aXrCj8v8uM#C#fm|rn (`ky<@ƥЀq hʧDJ1c1ЁAC !:0bcH 9 1JTccphhn5NxH Q #$ 12aE+2#otP1pxC t`7ˌdፁC t`h LG3 8yf29`3 x^,xy? 'jEkigƔDc 1J(@Q!FNc03FUsW_K!:06;1F!0d! O80.`I`(`.d,DžRfʫrc$cc+0B?L2i;ocsEAӅn b;@$c8NIkPh4p:1p8k9빫hDь8A<@X1ɉ`jw KTs;>s{tcx 1ЁA0v1:Cc 6F4} x:`ZnkpѢU41 tctuu5``!b=0=ε:۴u[,׎l,y_g,1px b6#OcDkk4gΞ}hxK Z )acL5f b`$nc͗NTcÖ-{ iO?e~FcA6ĀzФCAKM3ֆh t`1ЁQ!:0Bx/‰o 퉛q dž-۟ڼ-6=gơ)g*ݳ ?caAC M)l TZBƘcP1pxj 1g+ّ8go޾nHb'cFgd ƒ߀4`1ЁQ!:00K2Fg:hƠ1F## c466"4@1v{ab3k7TngG=44GwH8A<ĐQ10gcK>1IXA<@1v>'2m,aC [<%KVh7ر~FqcC!:0x饗1F:K 18f8A<@E3FރPj7Gm#~w8r}u*4k=&'ٽQ bDC t`1d m[bwP1p 1uAG`y84o5 y'ݲr&_83F]L&]]38A<@ 1ȑ#1x`TZBưs`P8c+0[vh$u޺~ϵ~ßx|k6xSCLNt LL;g2 1 !1gmLhScRk5#&lSN!C t`h !>>ϕ^^tu*ۮl޾1c 1D1`Si .`PcRqYfFC Pk!dMyz=zݗKq_M> 7vFIojgj  bƸ|Rcph5eeeZV%l50Fyb_!dۼz]'ǼS?Ȋ5o^;R5ڠ36t&!"Pe!ic!Đc hCzAVK^0eߑya (C t`0N//u`8kJ,0Mf6ϸ4Pw|B c455 #1~D=sǡ ^ $˰Due1px EB\92z걕kHcic<C t`h !R`H6H-yպzx:nm +򻫽U~W:]3{EC"< .qcP1hLB 1|K}^ f #xb+ko1ooc+UmZ;UǾhwv 6:]O/ %*8&ۨ>>ka!wN jq#G><`fI0o;P}qh  Y8)jdHBs Zư_c̐g B t`'2Fen Z-ܵ7ZI|{E3*C IPr!ўFs~qϾuD?|OM 'o~}%KH#Z&2cY1c\yfD1,0J4@@En;4-1o ! 1l6c*mfh8yfީu`F~?7Y`Lh %|.W3ZKd>ChK6c _܈@2FIBƨsP 'W^}L3d0cruOv,4Đgj"sW؀a̗u]n; tjGc\ҧ!%h (C t`bC:c3Ɗ5ʐd "k !$97Mn#ӾLcFO010vg;F  1D11S!Z^5͙g=rpW((F%d k 3c2 b1!hY7ζf4bpp\h7 h)Č癁n VK4 "zSHod1j1%t_ -1\1xf!r 1/b3&g ̺իn3cLj@l+<Đ R 1P9p5-14c<3o !ro=ϿLF͓a3ϬTr/`[6/egsWqC t`1e40Z"ƸH3#2ɓ'QB!:0e U4F|B[\h|5ohX}lDU*{IA<@Fƀ6CdVcТ0Fq1hb#pG9fX OavcY.kLPe EDC qc\tI 7Blha!d{8Q!:0bH5cͽc:e4P0%%lŽ`cТq3e he0h$9+qGvEXcc ;7=cu:7YZdAC %dlƈ4AAkYU6`yC9Pw!f+{$w'w<*U݈K3lhwc/4(~!M#0CAkBcزСC@ 1x(sW0畸fI漒uWN;Ϙi ! 1>tƠ3Fm|"cD4F g t`CDs ~_I8rTr0c@tzC bhfb+Ơ1$c m`1ۇ4 1c-6:BP(~F 1Ё(c Xj X;Ð:谅e>b 18!1\11mMsg߀c5 1x! |}%Un=4H7ƶm0h$Ƙ>FcT 7hHbv> ! ra2ј2Ɓk-U49H3C1%b('5Ƭ-1ӳ6oo0}` !C1ٞT=MAkg9ccժUƀo@Ơ!V`1Cc-ݼ1b7ǼS|G0 1x Iưl(hƠ,5F8 b(g/I1!B (#2cl;~G7.yEѣ/)XZXbbTAd bCxt. bB h7j2Fr ːuzcǎyۥS̰E^*4 1x Ƙc6wgoO(2B jV1~W{N`V!7ׯ_G4 1dcyxv(d.^:Ya34OSY*{I0C9(C1Uk _]9Re" *{po$> 51hC2{cӣh{,Qfhaf%Jh!TXA<@$cx^i0;Ω9n{t qߵn2k 7]V圌F*/?gQ1gm̅5`C9{Ic]{_Dqa7v0:f}#=F'Ќ1E5:0V&Q`1lI3F *5}j[k݄KOgeѸ7;P϶ΧS/`gO[-Q  y@ 1P!d<'Ag Dk72*4Vc70Tb 1m䝱\ζE//C~wO{ ± .n 7U7C 3?tqoOO:gNq_ن(ư Ẳ{^m0/={^=̀CݬCr-b'N 2A<@QYQmh 5u 6j:?XY!I |La"j !2C R1;͎>Ή$n򉲲PS;e6M =s/3Ѹ62 eek?0]>_ԳC.c]gdl\&k՛LfZӟd(c"ذeޫ=W\n'}?rŚ|x}8BX\c+0b㫯4FLߩH"GHx/0ww>_>VV?ਨ1SlDk==^eݕw_ ¨Q=1[{ -`Un|4X!1UX//47twYޟ{_޺6Vh=Ӎ3C IvCE0MYQRcW_:b=Zc ːuw8.'R̰E^J1>sƠ! `1ЁQCTִ?ק3V~ / pap߅ψ4 ņY&qcԫbmPt ːu~#GjB/XZXfX"G|Rcc P1px Dcܷz{ѻL߭f?U*rtSWG}k~F4 !:0 b,5l1*߹7"v!X J`iaP2|  b,CVUt'Mo>+L'>r+3b5Y`^|mW1h)%C9!:0P`!d+v^=qzco3?QO?~  !n`,c1FGGa{u<5eX _܈ 1ЁA<@F!1Wʈ  :sp_dn}0c+0Ys BPcZy% H 1phКCOBיZ` >=c >@?y<Y`h !:0$j.5ƩS9K/QcZ~-qDC4 1h!z5c3CO3`oOG֜1<5|q$𝕻э !r7nƠEK[ƀ (E`1ЁQC啻́χ}6fK[?Z[1y Z5s5YACRFIYNJmj Z˪QQQx2q˗/ե,0e  bC1~6Kp~c,ޣOSnkcE= 1ЁA<@FC N31G}WMߏ?fWBM{X޷qGސo?g 5z}ڿ_^7XzuMM_Ç_d @!4X!1~ix\Օ7.=<㝓G;&mw,W4P^Lcd^3FSSl!Ϟ=?^Qn0ȿNơm :6,mlW4[G6$aSf;suzJfԳDalǼSŹ)Kz<ۻҝZAza^s;bqp⇇M7167;v[o;v>?ʕ+`VC9!:0Px!dǫv;BǛtQE%0}www;MܾO1?{wWyy<E?ttIrNҹ9\M"aaO`1$B!!&c-ydM<J5fK%ڵ]UUֻ$䚤wK(#>(ʈA-c uwwq>>{۷?ַ{u#.fsQNv{$v頝-m.m>6uuPħʹqڃMMo@;j'#=qg?vvo;޿Unj7$m5{jb{k>Wwvуc6nNNMO1vڲ;eی-$]W= njA3vx7sz`<2KsE.c{v{Vxk.zpUпUgY#M#o|7߼vڭ[d۶m;>?qq2=.1T#{Qח?3>nu߻UN,|7c ={wKn J1Rqi:Gxeeeii={|gyn~{tr:`]0=O i00^lf0>s?vK͌ڡk(跍F:c6aoOUG3Nh0<~%N/ܥ1f f n37 ѫYׇČSęT`#i&/$$A_w;cƍ?Oz{^۹s]GJ'cTUU1C`H( 05&5﫷whjko-pq| g'+n ^`H,INƘ$c1bġOs~^XnƷw``EkN谍aՌCqlC~c$'1TnjlH,-451rqӦC㇝FTa10z3S^1jFY3'JcW!MSKR;wo?XfͦM{챧~߾};~' A/G/!C)0,b3l?3hs:|m7m|iv鳵1p`heLLL3gϞ%c9sK,>v}',))3F.XLF 3ڎԚAH1,c:c2>~pm$3bFILҨˆÌ}uC>0rbFK^K['LfL&/0\@%b 1Lf4Ϙ;)#y 1N$6ncFi ưNӤ;b뢬yo|GO ֭[/|饗?{9p^_^;,q80# ƈw޻qlzd[Uk/^KՍ=ZpcHP E 1'ޜC޽{ǎ ?NGƷ~ ,=/?(m۶_W?38:nذq}!{г{R<%jNYfV);@weN$G}_w/믿;w8?FD# CQĨdN1~2ƨc cY12;XϜ9CzUUU=z>)F[g}c=FGZlȱe˖ =*jfy@ܯf6* jf=6͠w}X<}?O?4㥗^ھ}Ν;׿ݻG!WWW GS;JVC" `aK19KRc8KAe`(++ۿ?1۱cN_yƶm~qO>$o_s5yLLG#jfKLC3#+--oGƋ/>o9ϘlyFF< ϯS WaȽgϞO>Ɖ'$M"1BC"Fkr0.c̺cD,D }Βd0t23&3HtC(H>|čA7H5Eϻ;mxfv³Lf3ݤQj邞\gc%)=bhj@cB(ʈ0l#5e1FFFfX5J̵Eˏ=je1vܾ( xxv2³K|dh>4U!X t{H8taǏWTTTUU9p% 1p`H, DlưQߑ?D }ΒG1JnfX_A1:zA_]]]YYIؠݎ;f̜#)S3P.9x|\BK=ޱ}ӳ EV`G 619K3Μ9H#555TsҜ*\8<9dx[t]tN#Zg zs:K"ce%13_#C0D 38&f 9AÒu†Ɵz"PSTNr lGn*hнGM&< F CѡiŎKٍё7D `80W3188hIӄ `;;~P&afKuIYH7=[ﯦDp>S~D+cePd,1F6 %!b8KpKj =I3ea?+QX9M믬p> E"co4`m\ƸP эI" KVٰ&L_. O<䓏rRxRj% kZ]§N?9O3F.sW0r5]1:#BC`HĘwRU6JAx2I7*,E9 DP+l_XۼiӅa Pd E=m%#FXcXcHP #124 g,op.sTɤ9R'؈؅( ![^Bԉ1 1r1Ƃc19K#7ƽ3~FI|܂E[TWEnQ"@c l5 `| #l~ጁC"F"F'NH Mv ^Y-E =bdfS11=bP1 NJi64(:F54C+ce82ƭnc̄1 {1T#Z'_CrG|)∁C"FV`6ƌrcVƐ1p`G Z(# #{1p`0D`80$b!#0# %aYq*3nc|1=b:b`80$bD(b ٌaT{:c,P 1B=bh1p`G 19K1p`qJ{cF8c=bD `80$bs=bўð1$b({!C"F`HĈP80$bG܌*e1 {1p`D4b`80# # 9Eh_QcVƐ$V(ʈ=bY#׈a1D`80$bH 80$bs=b$&1X.1x1T=b:b`80$bD(b J#Fhc cP 1B=bYC">gI# 7Ƥ0O1p`H1TC" `G 19K1p`0F]w%11=b!#0$bD(bg 11180#j`HP #{1p`HP1p`G E ƈ`G1 `he Q9K1p`he80# {OHk{m(=b!#0$bD(b1:K.ӎ1a ^`he `80#F {!C`HX0F[Zc,a 1$b{!C$D }ΒG +1Z1.2C=b0$bD(bY#1+1T#{!C"F`HĈP80$bh1 c3Y͌0$b{!C$D {sntX1C" C+ce1p`G `80#BEXo-1l`he(=b!#0$bD(b1=K1~d3 Q{ш=b`80$b "F8c80$bH C">gI# C+c{15ƔBc1p`G 1"1DE 1$bFQh80# C">gI# # q.a^af1T=bYC"ꈁ=bJ@Qkck!C)0$bD(bg 1"1p`G `80# 0Fi^ b 80# C"ꈁC"F" !#gIc&14ƔBcV(ʈ=bYC">`805bTWWg4FoA!#0$bD(bY=b*1p`Gjs2Fmk:c\(180# C"F" 1BC1Z]Ƹ#gcD }ΒG 19K1p`HP1p`G 1qC" `G 19K1p`G 80#(F,h` C1Lk J!#BF8c=bD P1r4ƍ cl 80# C"ꈁ=b!C"R`C5 `he80# %a80$b 1$ƘLk !!#BD !1p`he `80#Fu`qFAO1p`G 1DE 1$b F1p`H, {!C$D {!#1z\(2F!#BD }ΒG FD# =bm@cL1BC"F"p!#B{P *#1qѣ1 =b:b`80$bH Gƨ 4dZ(# =b{1p`G 80#/[l c,k(C"F" !#*gI# Q{LƘr'b`80# =b!C"R`1Z l 19K1p`H, {!Cu1p`H h4F!#BD !1p`D4b`80# !#0# 80DE C50$bW`s-c0#`80# # C"DQ؈1j g 1"1p`G `80# #{1p``80$bH 4FU1c,A!C${1T=b`80"1p`G 1p`d4Ɯ1cƈ"0$bD(b!#0# %a80r2FUUUVcTm !1p`HP1p`G 1"1TC" `G*s2W`Q{1p`HP1p`G 1$bD u#1`Ƹ.1T#1p`HĈP1TC" `G 80# CiaE'b`80$b1r=bE1p`G 6tƐD }1p`HĐ1!1D !1p`he `80#F {U(16m(C"F" 1B=bY#t@ќ1$b{!Cu1p`HĈP1"1R&1#`80# #{1p`H,Dٍ`14p!#B{P *1p`H, {b#1-` 180# 1BC"F" Q{Qc`#NXp91{1p`HD !!CψRq6ҕX|a 08!#*gI# Q{ш=b`80Yќ4FgI#G14Ča#e;VP C"ꈁ=b0$bD(bdIqi3f7>D }ΒG 19K1p`eĀ1)s1TG D C50$b{!C${8y$dF1'&O-180# 1BC"F"p!#BFјd)mVc *1p`D4b`80# # C"Isc`kpA;%cHĈYC+ce1p`H, {3#`80$bH 80$bH #1#b ZC0# #{1p`H1"1p`nn1:,cČQ(c *1p`H, {!C$FGƘ 2ƝKq1 K錡:b`80$bD(b 80$bs=b`'2~0>{!C"F`HĈP80$bD(bPi ~c1]x8C" `G 19K1p`HP1p`G 1NLFcc6Ō z1p`G Z(# =b{1p`G yc*1.c }1p`HĐ1"1p`he Q9Kb#1`T6hQ{ш=b`80$b C"F2Fˎ1Ǧ0>D }ΒG 19K1p`|"Fc%11p`HĈP1"1p`HĐ#02c41:O1p`G 19K1p`H80$bD(bX!c43x>P *1p`H, {!Cu1p`HƨcQ80$bD(bg 1"1p`G `80# #/c4tW#5}a0# 1BC"F" !#*gIX"FzcMoFE1p`G 19K1p`HDFtX2Ɍ1%nlx?#=bY=b*1p`G 1*ѷB1p`HĈP1"1p`HĐ`1&w51$b({!C$D {!1b4}%C50$b{!C$D {!F6ctE#1p`HĈP1TC" `G 7F 1We{!Cu1p`H1$bD, {Ĩc80# %a80$b C" `3s> 80$bH C+c{1p`Yaϕ(2 C"F">C"D`80cb? 6ƦLƐD }ΒG 1TG D M"jc 80# %a80#F {Ob.gS1(C0$bD(bg 1"1p`G F1{1p`HP1p`G 1$bDEJn&(ʈ=b`1p`G 1{!c"lce2F!#BVƐ$V(ʈ=bX0\X80# C">`80$b!#0#P0۽E1p`G 19K1p`HP1p`G 141o>1o C"D`80"1p`G #1Jj #1p`HĈP1TC" `G GưqT:cQ{!Cu1p`HĐ1"1#1:նBD {P =b`80"1p`G FqDXvq-ICcDE ZC"FTΒG Z(# c#Ffc?qbF17F" C">`80$bH 80#NhO#+g80# C+c{!Cu1p`H(;^cL1T1::4FGXC>cd1Lf0C!######1˪[LfN!Ɛq,cU5Kƨrc!i1eҪRi?>Cx@: 4^cdq1LNccldSieS沓)_a22222229eÕ1LfƸ>a b 1͌M1%Ɛ}ht1v#n3O!rZg[WJf{B]#6I2222_a8aY}~c {K@\yж.`~0K^rf_]of^~f7@*1\omq=q?nYԹ_H*|~a|܏'-A3EFFFF&ĸq0FJ20\O'?[>5~pn@s M|6yf]Ϟ=725IS{lPUΕXy{S]W:t12߅_>柸#ƐQ9.c4lN1F|gX: \3+!si%{_t;m^uʧfxqyxt97Ko[tTVH._iJ Hôٌ/:Fֻ7F]>҈1dddd 21&h]M1s|eKU,c`c:{sxrQ9sf'Wc1,UOFc @LI6Fy\Ifc1y=g8Br \{%YkR{uVJX kHRTo=}@͜ϕHW㶘}IDUd=:w'bpeddddB5kώNJ5ƭ cdI]5_WԄxį=oa]u{ /L = \So>x;oKS_0zݯ*ko Oq~9_ߗTR*# ? uάLY澤1#7>Qz?3]"####8Icg0F%KUW扑~ {E0cQ'1&:'.Ɛe ce9WҞǹ/#\߻jczº⾽2222222јUwQiyen]5GW'fwu?k}0nL}nβM]=>iyncϴk]cFcC.c7d{}>uK|{O{=댽w;k]e}.h0L[ۍ'ޙw6Չ~k%]q֮2w޻׬=eハܿMlz-q}q%?M[yM֬e߲o~[[nwӝizRo-?}^ߑG~ ݑGc͏{6>|-k?x׺߽~tD[oڲa7o tdz7vK}Z4cuƣ@]c렝Áެc=Y:c5tw=J':up[}C*?h cܲjnb[x[X[XkX 1c܅)c;.Nwvλ7t{ok]}-Iܰs3kh4Է;};ex;7F;Nw&N[;lY{v̷wԳN">8{6f︱gkW[ʼA7{|f8>;B乱izw_]4teg/}t˟}q?Vh?ﲵWp ˟;yf~9>Hpg`G@ӱΞl|f˹_j܋+_rYF~a_ŕ/ꌽL9I7ff_^4qny|vil'hO8nvO{65lY#7;ZXcttU-Gۏv?umTHkDٹ3ˣ.N/}1s]NK垑d]Խ7>8'x?w詮ڎ־xًt/&.dz3K{a쒱Ӊ+<W W󟍛;6ܕC3'G[{';F*ZN4N4WԴӐgF{Z質q;c }k=m}<4<:G GFcÈyni;㝱΁ɮɮnkNJCہv&w¸X{=q>Ϻ+sҶ&y)1|#6б<(Yǟ3t5vW6&"{u^dok+!+]-lgb\ߞHt;{I_=_ۣrʳe6nirJOzpb{Mc4j߷뮻7޸Ճo B"^ x 萫%t]xɀ۠ mCE`}hʋLo9qh

      +ϳg=9Y~)>7ςS8:b<Rr.LTpn,vWUYg]WUu{ʋ}qvuymZykyWs?[p%'kWs r?Ϳn-=;jw=r"rdҊ7]mUeVG.Nt 4]lRw &ʄb&?KVd^j=]޻ Cs)ij{*??z endstream endobj 118 0 obj <> stream xsUչѹәOwJ%bδ3jkk[ZIDmrZ_zKțN@@m}#&-Z_x $E$$$! $!71x^{s>9ok|?LX{'$&(,]vdu޽ӟ(}ىszݍ_Z&' lz=@>O|yJLdrW Xd[n'-R[^@ ōM\veO>~Q@$/[nrRf9g瀟],~0|ϖm I,򓻏!"Yvȡs [s2Y~dk7,HF;O,{DP۷y#rUZ~^glθ^OƗ-1r}ݭ]վ/beܺjWί'ՠ]u-fV4K0!پ\Cu$OA=ڏ/^9M(YrRf9}sƶ덫kgi 6-ק7j4KLƕlHݓjg|a3+~:%hw%u$oz<6=b5׍{զ|ѦYβr?_&ˬo#:F*ԫ&:s W^XW)n*^o+q\/$Y)_{,o:1uNHqތv]ל|l }=}SyP:i%,g͉1'7Ԙ졆j r},v Y ޲ҊN\f r|cSeI)#lLjFQ`GХ0OJ[+EdU6&,-08{\W&ub)䥕^;_z ʽf~ OPN?%%$-v]weK>gAmI}r=> v ~m--m]#=bSߤ׏RGd({}J=>ft^{j~リcOT브2_C>޺/ gzŧ*Jv_n4/cy%ٛ⍓tdW$Bh;s8F+ks 5V4{mS&zg}a}O[U{ܓWR=7Կ'eL7`:oy8. ylkf2pM{dA9).[/wƟ^}Ulw˕o{:e*o Jξ[En7f?9:*2 >q\3xsFO>SA Iha%etfuZ=s6)pf7u2 U)=y%{ !kVe 2 ӷ'$W$̦7jn ro6s@RÃ62Yj:l-2gnPrŽ5]{m07˃Wͽ/2l\N}*QomqLaדjRv;)l$S:^rbj߫#=y]71Y]XoneڲuOA}^I^o>N2MhWcT-jŭVTYUߥLmT)TC9)vEk(7kGG2qÆ<%/X ["$ρWݢA9)ب+mg~۸_yhKe,-Ry }Wѕ:5X] ,VXfȣdrRf9ˏZ~ L W}W_ky=RE%X*"[y+A9)e_@$^eI,7-<|@ ō޳W˻;@ m->2@ Ƶ\ˆa-'sT|c8 EZ@+eЊZ oxlhZ@+e hZ@+e hZ@+e hZ/Dd^H~\xO?6 @耖}*xΧFXgZ+hi{o o-m=9011-:e_fr"|gK^novLNN}-Fe_k{n>ܲ2!F#|x??ͳ?egv-;>3?shma8WCÉ77X~G7-2aZrU"|sl޳~۾ѱ燆ϝ#rE;ZLLL"ŋP @耖 ~&3hZ@+e hZ@+e hZ@+e hZE_^A1aZ߰aٳg?a/hd. >888555 )_2h9\`Ŗ _2h9\ҥK@x-]סת -6gjt"yͬ2Ȕj9bw`궐oixbW-S֘rykGF=C'kFxiƨRQ7sISKXF;,EK 2%ZZ({ h[#˄[Wnf|CJ߫d̯N g/euT)2'kjdBϰak])3힋5aZP@ ZQH- SF5Hk0Gcր(chvĸ?ͅ._>t L"&mOjRg6]mYG4s'ȶkBhd9}rhh-Ѡq!w*ZfZ⚅ guICSdstU--bw߬6';uvUstr;y~EZUn3,e){A`4E=ئ7aI٤1&P]nQNFVvZ)&uM!vyu Ϥh:epԤe=fgpp;39RMPzD>LIh;RHb|.>쎄*ɪOha-L)jY}rqSh.-+ ul΄<3>peA'''O8ӼLlYsO soٲ={/[ؾUU[ipՙ֛͛CyY|"wV[Ndd%OVLC%!Eb-Yi|hY}Pa%XcheS7==jOww}Q3FvVWf[&6|'Nmζ=U>S[)w"6D,< PWUvgXj\Nv텖AYއC S߄8"n>PH#|`q|0Z!ǻv-3gɮjO cΒ;ƨ9l?IV0*6wu9z&6]rz2xf$'FUlJ "a\Ctw/hdD!Af1߄h >1F|d#?-<3T>L7D:dǮbSG`;6UX=VCMK}U#{$4kN6rM2;mكE:^{͕Ӊ"y.@~hdDX@~?/hdZEZVʼ- 2Es-;/hd. ?<<|Ster7x]]t~A #pQ_~^ Z-V@2h Z-V@2h Z-V@dwr ?|  .-B- h(@ˠ@Z. 2($ro' I1T}rY7Gjm~c痨BaZ$ZowaƛFo  I,T Ѥј5 8JkYeL$Feuwlv LcjM++hsyof[kLOZ\eiyOP8ܳ"=k~ePH CHLژN& &7l.u'b4F )%e+"m{RFS4NAdә2h20kYu=vePH Z6W¢j; `텬cqk-^U-+ Q]=KVo|lmd5X=x/>suaLZD[-'ȀeorA_\f7Her@1}I&Jᖕ퇺)bdec |Tv86 HDTHMՔ ϖ5Z` ?sR}h >sxHlb#ZXh~{&u3t:EHek h;[t6݀ ZEZ@EZDg-/rQA!\ePHp-hh9\w'l΃Z@+e hZ@+e hZ@+pQ\Q;Jh9\4Ghh9\@EZZrQA!\ePH®e[o rQA!DҮ°A;sC)[-B m16EJuFU(><-h,TVL`QKYaϾ+X[kmdh4"-T,6K{UӵDEeU_k\/-HrZwh] γ eq+*̓r%:j(KSUr]5oaG.b,(>C1թ3h, e YYzq˙kXlв c:h_shXFk./ñ)5G#aO2L~O`W\rA!A 59O}Zh?=sjp:V}v݀bk hM -hh9\@EZZrQA!\ePHp-hh9\w'l΃Z@+e hZ@+e hZ@+e hZ@+r0]& 3 .OLL@h9WD I)*=D$#;!MQmǧ7W]]]h-犈%86R8DFyB# 777OreB+l-3/G\ľ'R9Z[+𥵩xLN>y$9w߽ȁree3 ~f>nnoV8Rā700)Z t@˹"4j/О1A9sĉdoAKeZ t@˹"=|ml},ŷ[ݻwhho&yZ t@˹"=~199'P78wyG<)rQrerŋi!%% @耖 ),ǎ#9_r-:BʕN\-:Z@+e hZ@+e hZ@+e hZ@+e h9\4bGw/^0lPTyn?`Dk֮ݰaٳg? T3UN=Gh9\@`Dˋ- T3UN=Gh9\H-[L".\H+b+vPTs f0|ҥ *"^Զ$ &yhKPa>W1Q5FcWhdr<#Sއ5#A+в_~a @jjyjj|[WnvU-p3愹čvЂ66/uą]k|<*<䢖e%bYC`\:T|hhѳ=16w~ZaA@^lCl-*z&6F-?cD1XBwXh3P[VoU-z ;jnjmVԢUiνPmmmd͡xfZf>Db##KhHGi\k8tj c=;(4͜4 ڒ<hāvg']NV)[տs\z!Ywטξ?WsC{6uI6uP)<99޽ʖ-o޻L=mARZOOv}6}`Nr?9k-טcŘiwI6uPͩ|"==[e=eeV'k-۳girӷ'-r-Si"8<-'׹=9mQ=˸eym\iW2 RZ 0*뻻f}eܥ{x[tۻ=t8Ұ7==KhHHnGz>HY~e͆qs}[ac̭Yo|lUK)C՜BkԳܚSQ1gΒ;]]]FvrXfǦ<$ T3\@@´9]˯\%LTsj-w hāV1y"H\^_9vtL8Shy||XؠRZCG+j-82ܪOTs - T3\@@_e7GϿ{3,AR)~r@Ry˥ $?}?PѰUK5Sgvں@RkIJh|vWT> stream xX[o"7~G?qf1SE#rQ*QQM@JH/{a!n6axznANNzq|On{w=Ʒ )\:*1-83Ez2#$a c ͩq,b-_[8XSf4gWFF{"7T+Q)j uj@wW:>!{MtMgzD4tBp\Q鎉6Vڃk²_e6gker=I48M *ٕ,y,u14~w896D:t^]h2lFn@z8#|\^QN! Xet(> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}\XhfO._Gh?+̊ßPSi4};M#N>5mNm#NH³]It}fK1mh32N1i1BqAm5$ p>nr {Z_ssGF#h:8ӿ?[][jwui9B ;b/09;s?4}6^HUe"$΀G@x\ar.qu莉@wGb-F=t};# 11ݼ_m40#ܟ1r 8莧q ȟltWRrG?LPݕJӿ?WұhpH¬x^Qf{q({(y NсװQqt1GǚJU;}[x1`'N>q5k(t}ilwd pJ\QsWfQ05;1S asҪfֶ:c$wGhI:6c?4MbMhb&UO7"6fG]H3{yḧ]Go̒>i`"xa t94+7LxtHxQHi˱\ȸܲ8Ũ7?fOT[ky+2;rBepֶ9ڵ:v:wGjzum3O[^1+6kڠܖˌy3 tdY6YuA\5sVi]-,!w?(m9iZy88ʹ,XXGip]mSʜ- P:2KHmn.-nTFhbKx];Upx5[j%8zx8c<>MV]ԧ8(EtHnqqin{'U%l(G!IH+IsZSC4}# t<ۜMh|?7pwpb!O*T4[{;KE:D±8^ io09-L+KkbIӳ}#jUdݎb+y2f/&cPLӈE[y8"W.YCƥ;8H¬6?(ӿ?pEi 9˝#KLJӿ?&;i0&I 6Eolt;# 4= U`=%wGBIP|N??ϸ3M=e+N?&4&Dv?t$V!1U'%\=Gn>6]F_ V rW3ƍgAwG(b?$H&sEO:6Xq m;c  vh\mE> hӿ?iT`Px{D64 Ti V3Z@>ofjӔa̋N?'ӿ?vnt};# JM;!\&ӿ?@m;S+Axs7wR>iaFQ}/L_i WO$ay-R\ǥQ$H-tq$[)h)NO9I?*h EV]Gi Tɡh,S|,;?NT si t};# GR:`9t>C (#NHº7VUNh I'wG)4;# (\σG\i SM!mԮ`EiGJ=CDkh,SNX£ԥJX/8|OFfwFӿ?)!ΏHD}CD;I϶ .d؄vJ? Hq,t7x;)÷zsY4 y;{Uh[0->FcOnSV/uwm,um:[gX \괚U[KX`!k;Gn:S@rZ>|hxccW-MC΍$W$Q%@jA:SLx{DO8*xQJ\lo9QrH} nkQXjp󛄶*htW?wѳi/KhI $ewA}ƃ(tm;# OTK_v0Z!"0 9W@n4M%*! !@ A5'wO;yI0đ0Ϧ;עKNL%У+nĖd2WE&znjqsuihOn)`g%o1i:v向Z|R>N@V@[kU'dihtM->WӦ b 8e 0= *6@k;J&? }i$l6۽?ozR\cW,T ?w'<%<9k%ܿi{O6"9BAkο5M@{;OMɶ)IV9R97*$;!F*FҤ80A,SXj#K0e;Yy5yi0dx>mKRcO2!˻+5y wsZ; ]~՗ېz2v6v-a/}uw &D"( cֵ7V`{@k;M:SE^eA> I8ĩ#Nu~{@k;Gگ }jyb:/.=bKH!mʨiglsW.'oqǨإM0ە BscK7㴟i5uw[ɊM *T`Tm%i s^^]^EsFх!T(Ppys_p>{@k;IY+i]y~SB䓂S$oOfo_YG !)"3w}E\7㴆{0k;NZr׃L]I}{YɑbcQ aNsKu{yrC)6L**'q浌`v}/?O,oqko8$}[;vvneHP@h, a5YEcã)32q֞_p](_qۻ 6 ۔Y%$U8An<ˍVSU7͆5i ۓۺpioE̾= L˟ ҟVF@0k!w/bA4OCR[VHcFh2X 892v2vpԱ 7uPYrS-UѾvY2(Ȫ}}i=,˻Q_pwӺkU<_pp}}hAfZ{@{;G{@{;JveH{@{;G{@{;EY* 㴛}}h 2jw ֩/G?8Mz? }}h 2 tenf{_pO:v,*{@k;J&5,~a5Sμ5μ5o4o5Sμ5μ5,{au?u?Af[ au?u?Af[ au?u?AfZ.iW? }}i ]9sL,j#%5/{@{;EY4M?77vdd'EG_P6"̰̂VREg"̂̽K^^tdC=,KeDѱ 7u9{M{@{;Ip.o`\G[)C^yvv?+'V?o)ȗ.ێmU@ڈ?(P]̱?6]m"ݿ[;EYh]csom?;~m\^_p.̓;~m?ӿy@k;K_p.w3tb~mgo? }hMo?AfKnI&ݣ Tg''W|Rom7Om泸O4C*63tܽqּ1{:X(d98z5nK, '[ʨ?y{޹ѿC=tW?i&2c {uk+M!2\[IO Cɴ;3;inM3gi# Бgj_;ncfq)zpfeggɶhfzdt⚈f*ҼLg7ww+ֻ<ʳvg:̖Z*E~vM|Mi$2g,M(vXtYCJ`eChfOAdkhOY-l펕+軣_?tK6m}>Up4c׭6\3坤7BG>`Xzpfeggɶhfzdt yQ˧_S)8#L%YD/# AUp#l+0dM^n-*k_.b9*'l20x?nytԱcGWC,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣ "MnюF-n: yA/vϭyH,>K$h:6??E_:eu$ɿ$~cuE$??MO}m-Ƴk pd;ư) W}hH(]ys\ |cb*}/YƏm$Yw)O13w4J %Jive2?2s gF~뗟K{D.txoJqϡ9.ږxnWt u,C]>%^Hۣ%܌~ƠerI:|1*Iv_2G'% Ui_>-0}HEb s1SS8ZVNsL B:켐je΢gYbU&U}΍&NGDMMU,Ms$O\Ɍ1`?R1U,Pds'rxnd詏K%js䍦u+q\h:V"B=Nŧ6-4Z4z;fi̜~Lct asD.ntDV8fK3pOE$V.̲,wxqk!hML9ϓ?exGmw4pDr-P@Ǖ2$PӨs#iM&_*O}dKpêB ٮn=7Ō9a[ĭq$y)v-nTr9ifi1m܇e+\՘(/S^wceK G??f <}s#aTQM̼Ց'1"KY?b^i~(xƎr?叵q^ZTf}Ȫc3aWJ*J {uӳ=756C #4gvQFI72\-SSjZo,et>JI6!gMo]^}+3gy|O:~`4bwCNIkR+.u=e⩎I|O@ \e~%KuDfPJ>դ)rϐ8,u1)c^INx}M(e2y\W43jK}LqoX ,lKP-ΐ4  ԨͷH8mBFBf#ǽ7O4MSpy~eaPusyh@I9 Ozc֨bPkb618pk侷m=?Y__Memm,'+!ndgŠ/\3[xXVGđ'w5eN2L>?o3\n[J/fn\öwE뤙 ~yiu Rds/?y DŽ5 {)'!q[5"[&afpq~k*jtVK7~Avw' I'Cw߁?ָ?WZBeX.g*Gh؊M;Fq!9  zҶQ}S9sС7ym1(pʬȩ*c(P2IzNzKy161y^*`]hs?F 6i#m_FAFXIgU$N:>t 22< /е3iBVYBz=RzVe[{E[&`+5?tȅKZ;, uFE9gsQPiiBxᑮL<ǡb3W4t$8у,l7f/:'Uw\J6FpzT>滞Om2U\F]DtNOzPnaMI"('.3><>h:{$ԑa)!RW7>pwWg_<=xV 7_^HDVNps>ߍiujOm2TbLUr1xQG?7?Y=t |_4{V-?QOm2Uez7g*o3G,4{N-?QOm2Uexz7+ſG.Yvh:Zo e⫖o*_3GO箏R9du8/F-?W/Tf'ſGhN-?QOm2Uexz/+ſGdu8/F-?W-Tf/şGduX/F-?W+Tf]4ZCGUOm2TbLUrJi.Rp\妏R- :|Zo e⫘*_3UUf+8Ĥ\˅!uzgP[i#ŧ61iM&_*֍3>oѿ&o3Q̻{)+eŧ6>oѿ&o3Go >LUX)h7Qmٿ&_*E$QOҳ?'Ķק76? y?7[;':Z֔-tG;JSGq~uZ/')`qjTXS^E x0K}$$ѴlU k;IH2C*? Cb ?l?5*[li$Utt։/!ܿRMeί40[65 'Pؿ¹ov:pm$ڃ g0in>EG*}r&V&㴑O7l;"ZڑEtX6u9h̃M˖-.YpG#2FJnK-#3 Ntu"(3nxdQ$`yQ'#LG< _ j66y6+J'zf5L~-tRf%Us 3ҫZV:ATHRӮmc[FxY2q_"ʇ ރڇOO6yw3)]|KC6{SWpPI#ftn0|%qĐx55ZmWQX\I,,w`hp0 jE+-߉4 L3ʓ}S8@ع< ZF()\F\L'h;GNsw:X[}*uC[1y䐒nz~V<<{[T8}]\^i6jMWNv;pSת_[oٿ鍂*lAI)+\&:iWx5ltvyL7@D<6ćPFMgv7um̖G!Kțd>[4eM˓pHvbZY`cj:mOCA$q:Lͽ@'#k p'Y3j|դI}ÕI X\ӎwc{a;8^8 3(hL(̼9c>Uvvۅ^JuC7i}j%4Ievaɼl`UUy܁Yh$0+UZIXҋw*[[PjrSm-d4Zi5-DkWe*yQnmHՙ-Kl;)K$ ~9ihߖn_yY6ˈK/1~~bA^2/Z]ϩX[Xr-ẒsU'K?W=BI,R'U٘J$Rm8cjYckB6ID ?t E%~קRA;SulחlgQ#+]z9=;T `<#g]nZռ5X%VO5M̏$^RƾX|bA޺ß JG'?-iO{{K/$,?=AV b.T1A2yiF(,TpUKO Il쁮;|?dd?cqҍzK ԅ3PrQ5/QbZ[Oi=oa?QΊdu*QbZ[Oi=oa?G:FZKO[_ ?m 'e6ͪضtb[Oλ#X3SL-]@ZR1V :}ar>勀6A!p)V1FR>L HmE8~&A i7G4OI~vGܶfo5Og0~PAG4OIOt{HGsOIOt}Gi/G]پQOh? %?_.]p3i3RGi/Gشt{U=W'4gZ?I>ţ4a{ܯKSGi/Gشt{e=AKS}Gi/GOI=!A i/GOI~vbS}G4z?']vbS}G4z?']vbS}G4z?']/l}(?_.h? %˰{bx4}G4z?']vbE'OI>ǤBM`O Ot}H4._qS~ǤBM=#o.l}QMA i7GOI=F)c?!? &A i7G]>ťiho$Pqf#??z|]vdԿؖĴ?G]>tTؖtbZ[O˰GIRbZ[Oi=o>.j}h-?i=o>.jd4?%?-?~͐P Oi=o>.KOt{D͍Fջ%]ضtFX?ضtbkOa2C#}:C$oΣŵ0{_.u9,oΣbXO;z.G.I%K3C3J yڼ{SSMŤyƵ%WoZ5(z'}ZOsE>C ()76? y?7Jom?_3ZגoV%wQ9OZQ]r\E PҸPNxVt_NDՆ]&)e 4ni?^'M*+)D3I c"',ӵ6X;%؟1+8YD_S)b!6;'_L\vYBs1Wz_tx당Ѥ JI;q׾kǞ&ͮ4׀'+ ~|q֕,,u1:u F?2\A%q+GaqtY.fB#UA'κOWZxJeT i+F<8s}$C Ӭ^`)QET y_GdbHTLUJsӫ/S?Ė:uBBHU#>c)[CZVVV+P0F~y5\x_Wic]McAWEIm-p_OGT[Kχ?d2>BTso2&FڻP@Ž:zu4I^l44qʦd|m@ۍڟ'bK=)lfk)) eIXQ~9ml.eUl`#I<V(M(K!jʳjnKmw`cڧ,$a\+fƮ]o7݌9-*r/,ni/;!8~g>Oj\Mkwe$sh|8'tW^l2Q[#`r2y8^1Z4 B5au+VWz55(5o#jYTXG`HTAHKPbF Չ"%c;3&;gDx*;o[}(%;"\:ѭ*pGmtTZu.XE[b 6GV*è#qi@PZ[S̸PD$d1̃w+A,KbIrkx^͆n>aQ7?s>ag Ԋu_FIjy6%Tzzc³r8EpqkduҤm(ZO ݸ<ϓs޴m<(m|]soWSzt5R`AžöJE-Z=5J7RΊ(s((((+׭=mV<:zSUrg>"jٻ8g]hW[^ E斿/loYb5|ICk~/q(?Ot1hmX`J'Jc?[Q tyʉ>f N?xzONյIҸ#AVrT:;dCQĖCֿצM#-zpיSCz/sI蚰38OY.g C4FG.?5&dE[#İ^IaTW`3 O1|t6#`Ain|G}$"Ld{XH$z9U-i,7!ا2ZFv^t-;5sQJjSeu/KԑF ?n<=i??b cn~0?O?EYыx^M1  ay'"<Vb7G_hgI3$UM)A( ? gF/{S4h?O?EYыx^M1  ay'"<Vb7G_hgI3$UM)A( ? gF/{S4h?O?EYыx^M1  ay'"<Vb7G_hgI3$UM)A( ? gF/{S4h?O?EYыx^M1  ay'"<Vb7G_hgI3$UM)[ge3{MFIpUSF/{S4h$<F,Gj[VեԵ1=ĈXI puFP\{#ʯ9զ$[+kG[ݙEFI135hcTE|B1ZZ_|yi)Jy"e`=~oUo xZobC1($׉TcZe4ӛӃt)*R~_]>w{9R,LWx-?JeGRO`~ OxGDheaE̹[P U"o)hZ^M},`୅^[=셢(QHHPI8타3H d'ҀEEos bH\0 K@Q@Q@.iѬ77!XH[9~X:}uhoK!pDJPǭ'hЁ}yzy[czV 2S,=@$$Ϋt[[Ď@qm **8NIcR(Q!jF  bx.5HvE:z !y3)ϯȍkZ.K+,#xAUͧ.'m ™]" ON=jkZ5vPGc'9Rʎj [MsI"bD0xݯw|롶RC|>-|KqlS 5 ǚh6Nk^wVc 6H5˝JFRr&g$@{py8t _jn&ZZ=n&X̍#'^͵[q @uUpG'k-7K DfbНX*~' kv o[]ɪ܏-Wm1 *X3/#$ !pH8###+X~g(Ʃ01KM*jQE!Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z?,??W?o^g}-;4X״MN'1>mAf3Ro7yʀB$ZCy=彼i$Itpyɪ6>"F2Vgp?gֆct97W ;p?*([Y/<~ԴĐjvS$6$O.nE'hR::̎@'j?8^)+`գWS8%zpך|R9-y/7g"?q^kE$??MYދEh䜧/#=軚#4QA(Jdp9~K?'<oؒ?IO{4|?6Dpܙljh:E ^Ȼפ_5PBEm#L*IU{$YLs޺ t|up5 7ȊK'Gm3iiN<ϔΣ\̚"nhwBrs5C$eN10{qYQ &'N$T߽Rm/N͂6 ZHQ>ҜzKqBv;Z*8gIԔ9*}ΤB(.QiEr _`BN1zVfA t,튐vjUnN6Hٜ ʹ=!;#WE!!:Y3bA#n$o_IqiQDn%tr5 rџQ׽rQ9J\۵7$lgWQ5-vd1A`:QM7S5I-FW,퐪 DD)ByQd$4YQٷ/c;71n5Ng~(B8 ċ*rZF,$'8WķS^kgb#g#^gv2\uWbI~\`8ױEo )uKY,RqrBLFN8;k/L|AڄWR271cV.$NF:Ӯ;XԵ-2k=Q4hniW.'|7@+1l@cK((((((((((((((((((((((((( a^"HC{竺?,??UF-9꣹2|FǼOtGZ&i^klKbt&?EjG- 蚶3[@EAAQ >/4x=_(/sS|C Ie]JL-E3"iJ?]?/V(Z*Đ[I;`Ƭzzv/;4̅*T*@*A@ 2)fRN כֵ}xqn]I+1>U^ZkX.Xu4ӳ29m2\eh^ _7)\W;gI; M%ov@ &۟hjQ3MF,( TfX4l΅ i(E߷kt88bc@ƉrIu@9R,(izu懦Isgo3H4+62GYC^#Ú=^Zi8|nlvZo4ٴSg4&rJcqYI+!Q8aT:)}am[}/2/1$۸:ٔ¬EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEahUF+z?,??U`3;窎住(/}c}-s>&}`KŤGIlpS]auR?h -Cg6צ^o^5b5ީlK?oSD]RI 蚺3[@E%AAQ IQ r^!y~y"Uw҉*/ǼCGPs5IU&Nƶ"^ץfh.+MzTaxJ.t]Oh`i$FZ5\"9,C׷Z5? ꗖ:}wq-ڵj0 r k!b+(#HNfdKbj@C/Ek";L חF[w4mz+2rOK r~ y~'E;\Lo/?ȳk)t4@+/@sKHZҳfEx5GUm-OWg8`LM\!1;+T6Jhٌ͓e.d}cJ İmh (2ġRy}kNɷ[ıFR\*Q?NֽE{6h,TQEGF 7bh/P( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0X״mWC_mO[:?,??V6!ۯЧ)DO<]S[A²GZc㫋k[ґ4khng7Ḧ@X ,'rJ5mШ6lR1T}\OoW=aKt& S-yvyo gO,$(3u9ֹ;m%)vw<@F<HU>gdU@'&\,UtRq'a--:tܥ)iE:ª_:U?J4Is#zpיPCzˏC-{G-蚱7EjN^?E_FKw4HEK >k^<1jwwJR*]r$xՂ x &mHB6eVhb < kQ@? ,w5 ?m8Mkm?. 2Z79,4rOgf>آzbK=IRU T-ofs!8,73@3W#Ѵ[~-xv8wݸy_ E XvNaNT!I@(׬_@oz EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP KAv)gG%{G;u^?'?jK'#-rڟI㮣HQ-[tS6?)i *_5Zҿ/Mm^5e%޽"q^cAy/z/s+?&#%軚/')`qjydz/sDQPP_i~O'_ȱk)x=q2֔#:&"^e.i+QzVfEQE!`$=h B)h((:4?i(C^/EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEEcjko z a^"_׵=iO" :ڟI㮣H\#x>KrDtSN4%W?Պ?4@t>$pיRPKrE-5>RUiJX_:hmCֿץ#-zpך|RCz=N/')`qjycz/sU?nSD軚$4QA(Jdp9~S_y>?vҙj}=+iJe)|Fu6:-E/"j/J?\/V(i%,k!n > _-v@Z@øn?Mzh/Q GH2ޏ9l!q-_z̫4 zWIi_\eQǧ@I´V?Mz; *>Zٔ @ sj*j-f0(:4?i(C^/EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEEbko z a^"uo׵=iO" :ڟOuGZ?m:4ܨtQNE-!WBWVBW:ye[O_3Zגo^?q^iKFk__ :8с@q+Fz/sYzџF8?ދEt* _i~O'>[OS-MǼCQxE]?\L/ΦCȹפ_EYz_zE ^|5paw ۷9(iٞ{6}:υu/K85b)mc`s{T׼C|"/hֱ-D\D&9^6gzm|SC/D68̳ORrżG3[6'촣"wn FcWoB 6PMvgw^,x9'RF:q:u'軚/')`qjic]mPh(*9~IQ r{5UR=*Je)ngSc?\/VE/"j/JZ( ( ( ( (#C^4?i(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z?,??V&!ۯЧ@+X{[S֔"'coQ}Ů_^RvI㮣HQ-[tRS u!WBWsPK! +t"o)["P:Y/ZmCֿ-{_NSD軚/')`qjib]mJ(5 L}G/4k'ң7vҙjM=T^[OS-iKs:"^e.i+QzVfEV$ 7mm5!Ok'DĒyG^A'U_I ǹiSYVmO 5FpP|Ǵ?u:f6vT^UE%uO"3N2eOz<-au4DnȥX}W[ (эE_TgUIDu#upвǸ)lāprVp֌ (+uK->voıS y~vڧ[>ݪύ~ݪύڧ[񺚊ڧ[>ݪύ~ݪύڧ[񺚊ڧ[>ݪύM/䲨UI$n Ojgmv>6nuO}GQ|'>ݪύڧ[]??Fv>6njgmw\τU?*ڧ[>ݪύs>QTn Ojgmv>6nuO}GQ|'>ݪύڧ[]??Fv>6njgmw\τU?*ڧ[>ݪύs>QTn Ojgmv>6nuO}GQ|'>ݪύڧ[]??Fv>6njgmw\τU?*ڧ[>ݪύs>QTn Ojgmv>6nuO}GQ|'>ݪύڧ[]??Fv>6njgmw\τU?*ڧ[>ݪύs>QTn Ojgmv>6nuO}GQ|'>ݪύڧ[XfxdCaʜt'Դ۵Ot}T? o7SQ@T? o7G۵OuNQMDYY٬M媂H~Sڏk_ ENVf;~S|l-n??k_ F@O ?ng//|EϷjgmv>6nZ]7G5it{9y}\v>6njgm5it}Z]7G޿=|EϷjgmv>6nZ]7Pj]ip1Cf ܀PǸIà[hX@ֺu^(QB@絏׵=u5kko z)ETO2׿}Կݷx>/oWOŨGcөKHaPK! +u=WBW:e[O_3Zגo^?q^iKFk__ ;䜧?b]C855P@JSIPPTrO4~S_y>URk$*Je)ngSc?\/VE/"j/JZ(9:4׃. [:ƫԕqﴵxލ+A-+6B}%^}o;zRv[}J#G]QɊ$xwnRO_RO$W{I 3霏WԱj^^\yʑ=<zj׀4]ش4qֽyTcFi+yғ|h׹r> WQ\M,(&=fcOM+*qzVI0+"tc]]Q .RoZGAGj=iq/ANsSN?AԋX.yx+hnnsy1l%S:ggZ5y}ͽwWזv1|]BpH=E\ºM7\ۼKhz+r, x:Eټ3퐈'oAnG<6#~ >!-ʹI7<JC(X#`v㛫mOFXyb.*\dCq>j՗I$>#ymw1KU7\lzɴ .iO2Vñ*G Stjz|d>'5K{<=2Ofx$㨬h-Efm 9\_O0V&v@`s٦(7_r/Zȼ&K㴎KRˌCr($Fuk}ȿ_1kxoaV'KaC9),B>b FTƧ.L"XUV1\I'wIpkEPEPEPEPEPEPEPEPEPEPEPEPEPEPlG=>/fOO( %3g-h}?~{*fR3Y@ɟ)wt]'r*2-kZz5T~꭬e\[1i!T0Lnf~sedFG GckHd19Xʘ{"Ef*^8nq^[rQ=I{kgi|EF$; ]nK/p<ʥvǴ%rW< F+"rJa Si;kDۄI]b%F&0v1 (T_{XĉK.DHi^hoư#;S<#FZZ: ֲJ TGFUldGsk}`1y7 ʕ&ic۝$/HSZgl<3ߋ9,MSV=Vo.;nM#PGYF{OrJ:嵟׵=u5kg{[S4#y#]F}wGK'#-D)lt):CU_:BW:e[O_3Zגo^?q^iKFk__ ;䜧?b]At&w4HEG/5%G/4k'~WOS-IǼCQEm;\L-ltZ_zE ^@+3Ah˃zMdY0+1`qzw*S]>xP#('f𾨖īpږ̊32ez9;:}j|Hb5>piFFNy4-_We]t8?UagОW*3\xwQ᮴ X%嵦m6baZ%}o:_qX#?g4Ux`vJ3$p lw1_iBQ06BrWv*iBr{&aR6rK'HgϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcogϤNDUcoEo a=v(Jo}p,:[o,U(#TYc/[=߅gP?Z"m \ʴ|RkfK^A(|09P{{]3R9D"0%U<${A(4Ikz|f`CpszFNjj-ibɻA7?(lG<${A(Rnem_]^5YB$ G8+hLHqގiwH9j[assy[v9nyxԕ`-eapBG<${N5˟Ч-{Cw?mOUKOMsGG''-rZOuOZnTv:(4HaPK!+u9$_:hmCֿץ#-zpך|RCz=N#BW1A_.ߧ1A_.6 %T!K >/4k'^[NS-KǼCQxEm;\L/ΦG@+/-+L u----2û5ad?|2;}xzܢ3{[t/4pѢbxِC`V<56.DאȨoxYc.ʬ\ghnK[Y&H4&[]O>r$l" k׮4 u Kpɵ OD?Rf֟uEwZ@+1b|99ی`索1"LK(cYm,DsNK[QEEč]kzlrǥFy]dm|4wREzSMjnPJY nC>S3c\"9 {bImefC.7e?͏ͺ4m(Dp#WPAnj5}>?O?E ~kv5.ou ! V)au"hX%!aq{:dyD~kű bm]ggI3$Skz-moE}>?O?E Z>ދL ? }[hkz-33$QA(moEϰ<GgI>?O?Eay'"Z>ދL ? }[hkz-33$QA(moEϰ<GgI>?O?Eay'"Z>ދL ? }[hkz-33$QA(moEϰ<GgI>?O?Eay'"Z>ދL ? }&@$H 8%A[[ylt=>ъyG!kA?.%gݷ ? }m!F=O JTio,)UX9$ M]( ǭ^HGԿhoΥfGsPScT2GJMPI!+tL2׭ y/7KF[o4#5y/KbzD7|+^F(?ދEkO]P@JSIPPTrRS$Z5'^[OS-]`/Q\~%ӵ(6M3IH_r9X *鴞M6;Zҭ-:;84ty2P hn3'\H;uh? /a)5dK7G,fOtrGsQ A{ O \,fOtdK7G${<O$/?%?ƏH4_ Jr<9AK7G,e.S A{ O \,jOtsO?nHyv:H4_ Jh;A?O;A[7G${<o$/?%?ƏH4_ Jr'Ǿ-trGs˱A^ShE 6 strGs˱A^ShE|w?ON 9#9 /a)4A^Sk>;?8 s?:?8 spcE)4A_O?;?8 sǞu[7G${<$/ O  <} _O;A[7G${<w$/ O # 6 sÿtrGs˱A_O?!1Jr?xwo?nO;A[7G${<o$:/4 O"|{ i8 spcEƟ)4CcO<nx?nHyv;Ht_ iG$:/4 O;q 8 spcEƟ)4CcO<n''-=Þ] A?Sk>:Mu9: spcDƟ)4CcO4/\ON4/?\9#9?!?1J%?ƸM/7\OM?7\9#9!?1J%?Ƹ_M?7OMO79#9!?1J%?ƸAmyԋu[v%?ƏHtO i\`: strGs˱CcO?!?1Jqx?nO6?>s?6?>spcDΟI4EgO6?>sD==Þ]-:' A?kD=m?nHyv;HO G$Z't O m?nM?9#9"?3Rh)?Ƹ/M??6>spcDΟI4EgO6`otm}.{ A?hCΟI5m} C==Þ]-:' A?kCospcCΝI5wڭ֗E[: 1### C=7O| 6???F1ɓV+G'}'-qswk7!*~iqE[5[-5>:GJ违MP!+tL2׭ y/7KF[o4#5y/Kbzl6<+z/sU#~&4HET!=)h4yo)=KFpګ0'c(`~UGzPaQLJ/gRa?ҽ=Gzv<p~TaʻO_a~a~gh:zv<sp~UC`aGgi>aʏ1һ/i>ݠ r s O/h`~TaWzl}@~ޛ`_I??*~}}(؃w`_J>bQPlҀ8?Aҟw?`_JҀ9/aWIk/jW҃E% ҿ/S#_ΚF[o4#5y/sm^5e%ީlOSI 蚳xY5ĔG+~K?9mԏΫG$??Mj .}-&p0HcLD )OMa$*>c@H?U:I)?#7Q߈  QЏx^Mox^M36?EGl q} o&G>7M  QA~"@ϽMi>c@H?T}߈ϽMh  QA~"@ϽM{  QA~"@>7HoS} o&A~"6?EF7>7I{߈  Q bϽK{߈  QhZϵKԟa$*>c@H?Th_k_9>ֿ{r5/l ڗ}_&K>׿/S}߈  Qi>Կ{r5?l G^Mi{r5?l _#}_&9A~"6?EFV@k}_&߈  Q~N/G?jl W{r4:M[  QA~"@*y{r4:M\  QA~"@){r4q[a$*>c@H?Th/8ϭ9A~"6?EFQMi[a$*>c@H?Th4ϭ9A~"6?EFP[}/_&o9  QA~"@3K}/_&~c@H?T}߈ 1i<K/a$*47{ϥѽkK6?EGl {r4n9  QA~"@37?^M&KOa$*4/sϥKn}/_&~c@H?T}߈ ϝKfOI  QA~"@2s'$M|_&c@H?T}߈ >w /G?%k_6?EGl $M;a$*4ϝKщ%kg6?EGl Ŀ{4|_&c@H?T}߈ ]ϝKm|O&c@H?T}߈ MϕIm|O&>c@H?T}߈ =ϕIѲoI?  QA~"@0M>W 'II?  QA~"@0O>W 'F$kw6?EGl ?^$MFo6H{ f{w@rH}߈ii$z<(C+,1A>FKo3#-y/#I bѺOК?2ZגoT%w>OKk3iFP0%"Mn8;v[ G$??M;Q_jw:w>EE L93d m3/Uac^Qik*<3j.*W8oq:UCxMJ(GYď)$e{w[^nU:cDӾЫcEp ^4:m<:]6KHO^F:u@3ų.$vv_aӞXw>tL%V*pAbAo[[_Ke!AM*w60=2jA;%ݎ܃;ީyp]\^NbU‹g$G=zmӭ#V lQh]nG8jMRXo!͒;Elrۺv=vP#+qj-{?Dgszb[ClM$7i+}g2 x_`m9A?iGorZK1W m ~]}@`Icn0q9I[Eˍ:RMvmC3fۨ`[=QR+- eøbNylZt>I4^5K& UFYV9Z _QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEPC֟? y7IC֟? y7[4&PXIW̥Wadr=a>47vN, НWÜW AGh  0>sA{7^) AGh\ΣO4i5=w?`t}nS-s:? AChӰj{W.-}|^׉EgP?"?3Sv Oo}͸\ΣO4GkQ4qA7Gm/?x$z =sZ?ѧ`ۏ _0?n?1|?#?5S)ƍ;fbqA7^! AGh\֣O4i5=6nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Oo͸6nC=sZ? AGhӰj{u/?`u)ƏH j?FSۿ?1}|ϸ\ΣO4GgQ4 0>qA{7^% AGh\ΣO4i5=7`t}nO=s:? AGhӰj{gn?/}| ?x$zu =s:?ѧ`^+ 0OH ?G$zu N^ӆp1|#?3S)ƍ;g\bqA7^! AGh\֣O4i5=6nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Ooθ:nC=sZ? AGhӰj{u/?`u)ƏH j?FS?1|θ\֣O4GkQ4qA7Ht17^# AGh\ΣO4i5=܏0O\^׊GgQ?#?3Sv Oj?c\ΡO4EgP4K _0>sAk7^+ ACh\ΡO4i5=?at}?n[-o:? AChӰj{Z\0icnC-s:?GgQ4qA7Gm/?x$z =sZ?ѧ`ۏ _0?n?1|?#?5S)ƍ;fbqA7^! AGh\֣O4i5=6nۏ _0H j?G$z NO`tgr?/}|#?3Sk)ƍ;n\^׊EgP?"?3Sv Ok?c\ΡO4EgP4; 0>sA{7^) ACh\ΡO4i5=W`t}nS=s:? AGhӰj{_n?/}|~qA{7^' AGh\ΣO4i5=7`t}nO=s:? AGhӰj{o.?/}|?x$zu =s:?ѧ`߰\^ 0/H ?G$zu N``u_)ƏH ?FS1] ..dThTmU^y GF-fǰݏ5ŭSƩ{42:%òB G*/T`I endstream endobj 121 0 obj <> stream x흋sםJuVݪ"cdo]ۉ7!J241nmv݋y9.HFc@vDba $€yHB3腐Lq~~LuZԯӧ3z@v۾I'Ӯx`Ν.\ [|g_erruuuOOφO "q,z9af2?9@ \eZ*_pacmmFZ~zͧ+xw~꿧7('e6gyҰ֭[w@ Dٴ]j7('e6gEK˯<@ XA+ۡզ7('e6g{;+H_xWsI4e[lҏzwuѠٜsi4:]\z5ٟf_}W9vSUbscs<#fÿt"}:i+)C/|u$hob[cbn2Lo1y CEE!zJ5ٛceͣ,;ܞ78xFڧ<'mg4ۧ֯͜iuq/8Ш6uH>FJ&uRywkSJKQ׽U 8^H"^d.+d=_IMyBg_ysfϽP^:k%l劉L-8khJ9Kjƀ,ޢw9mgFZK/z%G0G8jlc"gy #c$1Ǜu4t)2]"[(iyg]}:Y`[1_8'Ҋq/fqA|XIxxyHob]gǦ;+NOBb@m,:--7|qc-ǀyݲ۵ǖ~aﴍJ1<b?׏Tcꑘ_R=f_kj~8crUk2b_C>޸/  '{S'*vu_n$/cysXW8/Bh3w͚8KCMC=ЁG{Zv=`ykYc?^iwZWϼ}~f@{=Ic;g4cj}tė1Ր~W絍3Ο,>aU~usy^qJuPߗ1рɼz:ٹy_+~@_+~I2piׁ,('e6gys=/ӿM?gV.uir))4]dqmWǁFOէgI<3*ZJLB5f,1/=ը^a|>w:qpr7u2 x?U%q=yz Xa,O1g@o1O71p^[sO(͢vj?G2ٜM=xa+w<֓ڵ63L1uƁZq~'d2=w-\N}*MaoRv;)lS{8^r%bjϫ!#=~]71)]Xwne²qOAy^1^o>N2IIjWc \M)iͣF%k̟R6uzJCJIC9)9㒖?j&7kkG2V %ϣ˘ "2$ϞOZd)ѠٜĠ[.&ovS[=*?lTپZ*"cAg۱=Ǘ2c?7vnX`Ҏѯ__ߓo2AZr3;[mٴl6U+?gȯ7|/Bh9Ch:~C-v_yau _J/ @3x,ղ`ddcccԐ @ O $2( J-R@2( J-R@2( J-R@2( J-?}b, ~˗/ )_2H h9Xw|||Ster78r-ter75~A )euB HF3+ %Zi2 ̷HQ]$:YWȨ)@sty=C'Y< ;p75P_f'>{w愓5]-C}.->2Hj9k3!F W7*,\ueZCWI3<'Pbx(¬L's]Lo̡\Ruxڽuњ;M ~A )eaʰ 7p F c@1Ƅ*VpZ ]Nf15'5 9\Vw-fy^bSϥ eeɡ>+J4zXG<Ɓ5Pғ46 ̟O=JM'ljfi>ȳSS$y3*rPa-dC  ."ɽQN& 7 ]i@}*RK9Ť.w_=b8N14-C{?W6R,=xpeu&Gna&CJ jQH‡E$&r1N>Umc}v[B(JxOha-djY~_#?M9,%ױ[:Ñ!=}tgS'K;;Yo{ ڵqS[ՖN=;;D%zw{Ndd$ULCŬ!Esy!-PYnLhY~P%S_)eS]rOGGMV5FvzLnxNژm7< TDl^xƫxǰ8 -dɱ1܇hΧQqDD!F -=C@rR1FFFN:վcьv2{7i3}B_465 6HZv[ZפSنXNQF٨BJhA1lckhb:ٽ "? ?oPS#>2=XEJEϝQO4Z>ydvmm' XUqц6{Ʒm(2zf+/7{ܓ$4cN6 1;mYE<8gms$=iy\sI@~h$D.WQ ><<|_2H ŵ,+v,-yZ> Eq-: /h$, Ster7xuuuOOt~A )`_~\ J-R@2( J-R@2( J-R@"8o#wr ?YZZrNA6eM`-hdh9LB9Z$sZi2>鬛cjm~cX旨BAZ$ZoNwaFZg >s Iִ,T Q c@~ֲҘPVխ-|߬eckR]l 6^ZA{7[+It(Qc M˝kIʷ+|eMCH̴1_HOMnJ!ҝe>ldM)t,e-%i[7zv &Ny`5aTulfc!!acͨݱ8e#Y&e-eMT$NgTZ 2&*kY<-hd,VL`aKZaOPEKs1&\pH s:lZfXJidrsSL*jQwzZqشܹ~|ҝZD-WB¢%uTZܚj Is!:hHKSYXii5Nkxzysޔy8ֿSP?vҩOZ˦Ts*-l]-eꍥia3iپduw XɞeGTbl/$թShdv-e YZqx˙kXYoв cH*h_s,hX+[.bmSڻtӧd{R<΁r%aw_ eMMMw;x}H2ZNCׯSr_~)_@h9]x(r29yllmmmB$  @ )l.O8Ar-8B5,p-8) J-R@2( J-R@2( J-R@2( J-R@r?u-\p~Рr?'- z`GUU_ *#,e0  *#,hY,-ϟ?VV$ʩ- hLa|jybbZ0ʡeVBH*I|jsL{f{xIoOsbAFj¿SyhMHaL=[6QƴҲ0nKRmL= H˕3Y:jNWZk9zIò?GehMVteһZ钲?İdžH^}n,I.O/)O-_AUvʡeNF|՗ oHԶke/}"O4ղP_mZ|kY4C\k I[;XgknY0zloy^<}pܝ1}[k}v]VZ'zVҭ>$M>b k5SZvc{`dkT#w6>lkD2NJҲcU1r8C {#m{{:鈽fX+i%uk0 <)ަ۰peS)n)5ڬZApn+l(OZv AHZ3cZZz#b?1ryf('5|49~Ô[5V,'9%ԲSzٹpն'g|qxC]g!V An3>ڽ`.ݸ{jk%uuVº^+)yzC|a-cZvȗ0;-kVe^ZzJ5-˫S?eQ.Zf-:y+{k9V в2it64vvvgmVRk#略VR,-azzl,$Ye7nrzXaJx>phپMe)m$-?-!:b2ЬtVA֐٧OH=JG6 qj;}xWGkkw=K+amꦖ8 M-3.i,вUXԟ$۞0HOur{rɏ'[Q~g<_e}&?u~15S\,7Cٵ'ee呑S>h߱h2(zf,EzwP30!T9,i ⏜mJZ>LI0Uu@O-&T9<0|,@SǞ` SCCCG U-O=e0-wwwT3Uoy@d4{zzLWᷓ$T3UeP hZ@)eP hZ@)eP hZdIh9CAZMeP hZ@)eP hZ@)eP hZ2s_/0(ARqhݺu .Z9[7 Lޟ[KC JPT3UyFUU_jʳ|:@?l2|;UK5Sg`@RTy>Ph|߼22CϧgE4T3UݛZ&Lˣ7/O+8Z4fh9 ͋ Z UF"hܾyahwF8՚5c~ɥh^UH.ueV;)odRQr>-ۙћ_Go$3k BkDƬGjZA }vߒ4f!}hØK0Șȳ467Xj y|ƙDZA_!fC}CWZUwcgcB)C-920!u<0:MrBkxځKB-i%\DJYOc}ZG"T~j0+|۴P+sR c=+^9(ԇz4 ;h9ρ ϿK5\w^z!ݵcﭶzh6wWybTs-AKwwuy} 6^b=~|Z&$o?빞0Ng~¨͹Lˏ;#ڽyW꡽ܪmybTs|-AggmVٸd%v-.`=fٓh9ρ cc7Ϗ:ϓ{V?*Chțejs>pa,èHN_5Clob]wJ=C::j5k7r-ۉowI;W{?Kf1=ro4Ug9sk|Usؾ;wO"N)X4*h#l,ҷf͘OFvtXFۦf?'T3@iħ_%喙P 9O h9ρ O %>]uGAƮt%jyxxDР|Z&$cщN+Z>4<Z&$щׂGjyhhhР|Z&?Xkn4GT-L{т j@[K7~{Hd<(ARTUUUUWW jo'ce S_GRqΨV{vǁ@2( J-R@2([mqGhP!4m endstream endobj 122 0 obj <> stream xWYO@~J}H^5jU>%~Regئ"|޲_ӂ"^e|'ni:/b/vw:8Ŝyǂ$ fC@Wɣ0n*t T$GВdSȯ^e*aa:K2(Ns7l J \Iqydbya]XN'#My-oqq":h$sT54 ͌ l ZKݠCbvVv$s#)kWI͓az߀2)IZFnEqtD\diŃ{]kW-8UdJ]*uZ+e)^ZV-V _r-{P 73Hm:UoxLm {n#ljpܫ7 q}؜9s72ѩ)Rë:V+|K$D _ 9`4 Ֆ)\ fÜUjhf;0SkFV14jF>,7&h77^]нYοCOig4lmCpz*f}"bMn] 2x& 0Ef1..1zx`}<lj7a?BP0Y9=9V_9a"Va6 endstream endobj 123 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?4M.[. CY {wvÙb0 JzpIՏFӋ :w־rEk,N"/cz:IB7rд94*ShNX­[r1gxO Ŭ\iv~V>M ߔqta0};# rh1>e5{ǹ2 QbB8T6ٵw[Mm08I0Cx=@a=/W:/=#NX”hz/4+Eݶekkiyx: Ŷ"S g''珈E#UͻrHb+0')Y>c]D?ӿ?30m;S+ռg)1AvTC"nO9VB rMr;-t}V"$磢 G$sEq~410m;S)?i X is^Mg!@79PI0:ֺ2E?JTvmx#cwQ@m;S*u֣}{ L/E;H$c*0X]^g{@m;S)?t?i W1EҵWH(a'r0ی295z㾼tF.ѦY 4m ,>\:G? R7_i W5"Ե/4˟*;{cP3~A V/Z$fP6NCB6|`M0ib84+.]O:~??&cDԼF4H]<(l$4 eخd\mnYpNFkj7ӟf-eb&Gv@cOp2YG^{ko0ȵc'OHl:i:G-6oKX+5- UK}9^{׼3R;K:;EY6Y :qBi[~ M;"M9t;iV UMvw%?*ખ b *]FѬlm.nm.\FxbKx];$0I\8?.9,btҴ3z=ԑvQV:+I!9Fr5iXȋ}K;<'B:#Hml/w4;?iOM ooiD!XrJ`E kbh4-+oͤiH¢4.$[@0hȾdOVq4Yi]_W94]<0ݤZz9^t};# "QڕCJ,TFt;c i$L%u'.\s޴PDs3}4 i TG4+:9d)zS>4gfҹiؚ'4(?,YgQޕo>X.jbӿ?.,Y/(+IESdh:(,YntX.EЇ)CЏ+&Kj{{wsEt ,MmFƏ$Vr3Oi6h\.t-8Iӿ?&[5ڣ=Xw2iBy?ӿ?&?J<`B|>[D)ܩQ%BB@4};# m'%:wѿF5~;hqaHӿ?&4bv$PҬ&!$4`>chjHӿ?&8Ҽ E+#b ?&hYVq5 T0';T6#M XJ?&n%Gj,T:.@ݤ TE?$Z@Qd"N:FJFzwVbdw-4- NX—D>6R :@};c iдQ0};c ֕\a_i RFF;ji?4oi U{GX`ȵAAV|.cՠ Tˠg`wquv@ q~qUu= 64?i TP:!:>@T_j\J^dRij .dؤm_,:r[̸@Z,Z_ Eww[[**eh[-%nmVhso-)`EnH뫸n!ro[i]E :^:i4nm!GIkcgG. m4 TlojC62Yͷ@jLXC?? ,XqIMlVTm'in~MֹkЗ:&pмe\m -E"L ~]"-|#JH->)'0OF{0k;IVNAkjlM m?Sӭ}:k)@SRC؂z }}hޏpI%\mO"pK^jFIs18 eUd915m5'LPG }}i<pzn+jfkWxK,P`J:go Maj3ȍ,&2+dFSf#'kl}@{;L2=k;FyuK:pwom#y ~]\[ wk$1Mj0&!uoV_nA }}hu_p4EP5ȏr A<_%jPj۸.y+\xJh}A >qR0Gcگ }i>@[;JɆ?xr|5u{j*-B:LYU p*0:sit [ɲxrP9ư57]le>{pɶP#0%RT*TʜokXn`+̛aFPBP90k;B Jv}$ڭy_7Ы9$I8ߌN)z \:}g+2ۡhO}@k;Jn/O?Ag1x9N>k/b+92 7,\p02814ZM s|Dۑ0OLǚ2ޟpn_pJ ~U,Mvke#ݘ2HPbWJTZ,2F1єu5v}/?=?n݅ K,HJ\ ?J͸_.5[]LiVp[6hդr2nO-w{V_p<p.S2Ց '0w]Řy|?SڶC7DD䷘$Q` qhyyCEq3"23: `)jv?B,Tj=? }}h 2F9o? }}h5_pwB!ji8l֞_pp{5.VGY,Te?e?.d;2i[LO^^C k=[}㴛}}h 1d /G?8Mz? }}h 1`OJz٢}?}?VdB lz }h^t;2%4հ"yןyן]DH4_? }}h? }}h 1օ:v:v({@k;E5216v#oy?r7}vbmӊ_6]37}v [;ʯ rv]R==̒I]Frp2O8W|O+1d2JٮV{+iDLd0Rc7Mk>)c[O_=RW??EhZܖ.X O崷 Q~`F2zc'ZZ㶞o*c!l#s/g;\xH` bDBm,1zz=z[n#>YHt$zYo~pET!ns ,5>ϓl<ѻ<47V6c=pY22{=5"Q$*-2@ P{^T+B J>Y\ L%lȒq)˸6s۶1뫨Et"= VR0}#޳ceG5ҼNb8f'VYcjM/ly(Q]A֯%Š A >W<M)C@ݻ8:P-ywdfc`A ˞W] ^EMmP= 0`6UEjI*8DxvGҟor#01<}|;o[ZDI=-l.%WȔIʮ+_hOٝ#?zHˌ}T,=ld 69Hr}%i0 !8+svCT>PH/3ˇ֒C)|2҇hXՇM{y%4T8`Mf vλR;Kf:Wm-ɷFr,$u=*ijK3+;>MFH3'ӧ"Q$*-2@/0M*U7B` w%+{ ݗtmwCor4,?ukmC]k`Oڃ*?>ᑓӌaj٬2z c&}7s5m/jf1x<·h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂk&h#߆⌠\FI^vjCj$y%ђTOJ "2idߒ?1:oqUp&YY 82gXW髾ƴc JvC|$O.Q.>1б{>o cG,[;Y n2Js b< ǹ^%ۙ,gvo 'MfYՔO1I;^yb8=} Eqs$yBFv.b`KLRvU} x䞵3(ӗ/oYd0UJF+y%gve (۹q[g^-,t\y57:ͪ3ng;$ |W8=qS׀Eދ"~Gʖ`eG&^; O6J$=\o Ѽ]{?fc8+8ፈ̨ `Vub;EYM$A1/$l~OSgvo &w5^~S]/;I'3[esBYԖn7ƈLa_ҤkDR檁MԠ}S"{AKY w&8\]V(dYH"R=N϶/^mP[5=|;T{89oop+.c"Lruϡ'NpIZB'~WV+ 4W\jw$I VnȒ\9dCҠ >m.)py#˩2:={W%i.FT.QO8Xdƚhv=>LUUm&pᕗBߐlly%A?yέwqk Mϑ3I.8ǩn-Wu!H.dӛM^ݕm}OmrQp[K("yd2 s/Iխm7WYY^R#j@_xW6D+}k d:= 5oeJWvȭ}A],qc5g[3I)qĜS|ci=ݬ hITdAגeErڣ$y]x ㎢5 άmo1%uKm7S2EYcIc1b0]Po U%+!As2o]8)c=ߥheJE̼WW {)8G$̘;B|T}t=&R, $d1BqIX_* ']ޙhzct}DXKQ>7/cidF\*ǹcQWLKUI$# TdZWy.9[r{%͵"Fv s&H<|)i&_*[X6pփOJz?wr7 ~`V2ds/?y:wq49XHS9GJ<mi enl#%˖/w.1͋ҥu+YՐ ]A8ub8c[,\uiVSAlmK7 nem)\-뜜gVDX5DжU@'NQIEFUYn",AIIN+@id _2Uk o>K"xQQ789n"y/$\<1I !I]H(5r)Trm3Zxlm*; dI@fҖx$&kcb*{ۗk;as"" d {C/j`]dnE稩nTuޓLUEomgsX/Pj?%χ&H+3.o_79+ v?q)MI/Sq(# W7{HZI ]Tcס ȱהjQg(bw62Ͻt%Ou]9z7Qmٿ&_*\: ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUYHB;g8N+>)DmF?7Nom?_3ZגoV%wQ8OVuXE ([4%vb `_NSD-\%ƨ9 #Ƨ#|a{g=HIhث@#ɧvd%F+ T6hjTH7wS^C{̏wmgWppZ~D5aA_Gs<%S8'#Ok;rBVv[bB\u˛c 7cݻFsں Cb ?l?5+'N18GxS_&4h<Urs]_oS?MѰ?/FPؿ”)$A1mu/]@V[ɝ#cЌW0 [ϴj]ے1(lhjQaA_Bz[E,`LP!oj{xc*#''K'G'K'PQOP-5E+.1x??JKWX1V|?_?H@@t 8p3һ&OO&&OO&JqY-RjG[ gjVpF:DCHzۈLr29jǓ'K'G'K'V.Z;6&K>&OO&&OO&ڮvZwF#>::~o.GNOnwL/ML/MoϛC/aMOڕ P٤MX]žO66Mr1G'K'G'K'X&Ӻ8&{+'?߱:Zu44@6Awkɓ~ɓ~(EƳR{vZ*f*TR W.6tM~VdރV'*`8q]w'K'G'K'Zz&g}wwJ$LXgIYGh۪Hy~ukɓ~ɓ~t<ǩ EƜ#XȰ8`tY2}*hg3?Zd$hd$h.g&yzuXE ([4%vb `럓I$ehqY }xEuL/ML/M)%(aŸ˙nT,4{{[XoTWy|?_? +FXϑ# =O=O溿&OO&&OO&NL/ML/MIDT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/M@0פ5f%޽#'mwJI|^qOFk__ Ľ/')`qkbCW-dE$??MkjХ E.lo\1W.~bDJw7K: pA5K-j=b{& >nExLEBmg<|ϧ/d;JAR§lZYi]Y;5ԏ,BSp_ZVG- BfD$ =-/?[:޳:3ƥFtRK7I8xJ[x4,P:1uql0 䲌^ LɉcC"*JcEDP@Җ׸H>"hqjl[ٱQm"?:[өx:ngwe rMvW+}4dܛpwl=+ ]7]v:MMiгEWQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQERom?_3Zגo^0פ5f%ޭlKr&ծ乸0@p' #=軚LRh)e 5ɿOyutTVRf?-E;sӿTOb $#cWDpRB;lw_ۚO,!?Ə'_\zޗ>h?:ti&B|ҹ8NuûSLxywݷݍgiRԪ?_'_GAK/O3~&-ލqv#FxȈV~r::/Kuyyoc(i##U;sӌ5?WѭU⤶gQRh)e 5],u:gHSʤ$lcpkJR:{t44 YBA{76ID >NŖWGΜEI <қ8 kBRK(Kv#ȑ)ۜUXn-}?ǝ'Jkv5^M>,@OR( Z?ht1hmH9Mi+^soʬy{?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J Z?kcΓߥt(ţGC|U%]:B"r@n-}?խc4 ,'XViw:,nR2Jt1hmţI4Y$/h(]\zu/:O~c?bLɦO}2/#I昕T)%>qҰeᠸfhn+;u(CţGC|ڻu K+y7U#?>SV?P?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J)k^Kzd2׭ y?7[;' #=軚85V}ɨ[3D` d|sQrj+vK\9+mK䛖uI%v8 p*Iysj*1f֖wB/46A)w䌒G#>Rƒr ?MxC%anQ'Mӻ[W<E:WR_;mIOhꠓ뎟I)_"{Eؼ?{>_:;{d,9" ,['v{H%5w̵w}r҄J4ׅzj[:OGM/D.?j햟{#;D`iQ}&w(9qx+kXџD Fe*xқ7nyӴesw>7 :/5 /х(RU5u#DiWVpL%vnbD IɯF6xeOU㳍H>-OmWaH,@ۜbǯ)bWr譫_PRE/M솇}_#9S}!֭ EvZ ,SEX_]02К?dkއF #goۻiCtجFYsVف ՓAO جk5Ȼ,>? dkއF >FΥ}Y&x[GmO5̋sҶ{׷CL$-m&Y",̥l2A8Yc(z?…/no4?ȹun,u,Y4dZW4x1FVLp_ƼF ?dkއ[_4^#(z?Yc(#aWG,w߱}C0? +dkއF >_ja?{5C~Q #]?P/?0?=Yc(z?b?_ژO}3V]/DK)!ʌBFebc686z?Yc("W? +dkއF >_0?=Yc(z?b?_ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #(z?Yc(#azoZsOTQ|I&mO[ڤ3q#!pr x js:,"[G3 F >_ja6w^oXu[ Ȏ -^ɖB(hUdFJcܚ7#Sٺ;bg.`(_.@ba'vpG,w߱/?0?ڃSZ]6l[᳞/~@g|=r؟ r ԯ)!b_2 1LYc(z?›W0?4?9N++Hn,٤`( Jn3Am"PUԬꙆl2[`y,8_J?dkއF \L&9,,.U Ape@@^94_EZ[k v9:  #]?5C~P[ek&m[Dv#Gl'$7##"<12kziI%CA?q5C~Q #]??nGQ^? #]?5C~R#c? +dkއF >_ja?{5C~Q #]?P/?0?=j? /Yc)|D֥s GR6AWGi_j6| 㦲UXbIgU0$hW% "m^J K ׿Yc)g?UژO`mI*%ٶxð+&c•㍫OkV,vWsn 1ӚdkއF ?_ژOwLwYf07,ѠR9Ǜ!9#p좩'n>icGi *h-fdYc(z?—1L'K?\e%l)4[rb@*ςoB}>V=7EO$pZ22G,w߱L'0]}+f'Ij32.xYc(z?—1/_xKߟ{5C~Q #]?P/ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #+q5C~TG5ioxs RoZ`sJ:/4T3 5I(FZ'GM#-zpיSCzTq^iOFk__ ;' z[8OY^5Ӯh͸&ǞO$֋J[3 BnIuxׇhti$Kp-t~\2 tn<+㫰E]/29a bxKL&]:ޠ`{ qW^ӣ9N+8/K >UI}*uW> }=͜zInf?RZ UI}jQ]/ 'gG3#S_z'꘏s9+ Tx>Gރ꘏s9+ Tox>Gރ꘏s9+ Tox>Gރ꘏s9|9 vm: UFp9q֓/7#ST"h؆dLx$gj2ލ)\-Ű{HE6^C$c4G"oEmƄޫ sn"wiƦ#WQ~a`q.YQ(]n v"gdV,!T }|)9텴IS!]ĒN7<}R7:ȅ*+.իYM ٥#$P oMs>#(uOr!Dv]oZ4moo<-,;]0d*)⫉iY\cfcInh:qDh*¬ʩ4ns4WG'ğ U(:LG? OxOA}4$2k2VBawaCo|7dbkR9#Emr[;z j/g5o_O;]Sw ^}>YbKl&gmDK3#img&" ɆCс28qg߭]:79̪PHo৒3m78.`I,W74)_m}% *Nsn&%`-V&a!ld#=A \H-wKUIt=Zw}As1r]*qn8~0ͬK|n#}Wv*;|k~nfr٭FܴsX_Zgr">Z2?n涀YkIlɌw8-sM A#;ӏ ٴ3TmM}By?C>_yjӓ? {iY$3]GQQT*RNO\g)Ssʁks4n GD- c_xyyԓ*YK9['zkxkdMS]?wv)Ӳ\^`ro~Emf%V6-ܧ<6Q/ȣ9n}V^,G]6%j7Z#1rq q17GގO?Ȳ2 0,"d灷Һ24ot|wv"J,)(pb1^ xd GT9WKVSn*kR哄3]eVޮkNxE\Pգaú0de@B0O"oЛm!@n+nlgwukh.&ْ #ܹYQ!g9f-9=>=Ɛ4=K6 4Tގ 7'>kM[{7_i)lWFԾZQ]K=I]8,| M̖uRٮA|sSPţxY7V;ɻT ǹ{jkSi|yӮ Fdd'{UwVtgӴ_>[Ff N9#3c,lf.$_{+IlgϽL4_?qTSK_or|0 ۤ,dr83'=1VCOo8{t"_)Y2IMߊ.S8Kt9-}7LZ dx=W})ZvKm܏cZKV0l5-_HcO%V݂E` }mb;O^)+ Z89A~;[׭ y#גo^vq+cN5|Gi^Kx c꺝_NSD՗]VI蚲3:EC@RPA JSI@%)(4Q@h@ E (E% RZJ))M%(4Q@@ EJ(E% JSI@%)(IE(QE! %R(4RPA JSI@%)(IE(4QHhJ(4RPIJi(BjS'3M{# {\pיMF=z]q^i3FO_Kb^{85ifz/sU"?nDշ]t4* J(QE! %R(4RPA JSI@%)(4Q@h@ EP(QE!)(I@!PIAIEJ(4QAJ(4RPHii(4RZJ))M%( %PQE)(I@!PIA J(QE! %Q@j~?U.Iݽ?8k>&i^kze6q^g7F+__ Ľ#??M\ދE('#5軚$h4RT JSI@%)(IE(4QHhI@J))M% JSI@%)(4Q@h@ E (E% JSI@% %P(QE!(4QAJ(4RPHii(4RPh(4Q@ EJ(E% JSI@%))M%R?ji?41[׭ y7Ln?8k'k^kRؗG$??M]ދE('o_.:IE(@ EPhPIJi(@%Pi(E) QLgE@*3xjU>ؾl_ZAl_ZO/[l_ZO/[}i>ؾn}i>ؾlU_/'ր-*֐/Z}i>ؾjb Ub}}h%Vb}}h%V7I TT/k_ZIU־k_ZIU~־}}hѤk_Z>־dU~־ 4U_=nSCK@J) -% J J(QA %RPEJ(]_3Vi?4 vq^gCFK__ .?c[??2ZגoT%w=OW$]fpdg ғFkw4HRRJE(4Ph(@ EPhPIJi(@%P\V]6r@dք5K} b"r]R%t.8VJGA1'G0 .akZclmEU~5jX2Gop2s@$kNDG39m,?/Vr*WxO(A>,~o gş/Vr,U{-2ശLyh8$s9gş/vr>,~o Y]Y6wcuմ4FAi!ZTy O nOdo9]U^ N8)FA 5e;82]>* m+

      ')o;S. 2ǩn]Cx\$.<{dangdt*pWω 6g?mjkJ =R[X).R}`Fv(#'=dk[}%[ jein|I įJZV(VI FURi!Lm)T*ykMIQڟ`zأ}+53E)FP=+h>hu)]Ϙ5"]亯5BAL̐E) QI@J) -% J J(E(5R?UnI?d[??2גo^w vŏe22-<%яT%[oF9??ez/sXBM1[o_.M(((4RPHii(4RPhQE %Ph( QE%W$wGǿO['ƼC2T-)|fRTs^#y??΁-k˭̮yK15.r]ΒFHw0MxkE=&5|6~Y(Ы PIςKuPFҮđ1tL(qm+i?B<[YtOuCd8L $cwŒCN57 Hg?h YU\s]: ;ͦWm [/KEYUĠ*4`%fV"]Ua ~fpyynxϩ(.Wz[ğ]:ĺǎ!p\=Z<5[!b%r݃.xk~"'}0v(@s\hSkxBmm庵 : ,g~oaiZ~<"Ũ=DcJYy|I |_7oO*=o[M&V-Iu1e :Qo,i(A) yr38XGڤ4#1ݐ)助%q8N'c<-]PgWv,1Ur  'iˋk&!iqrHU~dVn2*9)7"KS ҿ,f@#4eA:TyB|‘ $ke2Sg/[Qu#*#6+#.y1IowHAJ#xrZ7BW9]r\ͪ;ھ- O+ q1jƏ&qJKSn}lsFޣi'PB`ҳnj-"oZM&{yw{}`L#EI$u!y\g⺂;i ' =AHnA|դ)'aieJND $-0p4 vh斐5$֯o k廙m ]$A0'<^Tfti:Y\夒6f>ɮz=&1eˡ,$M^]6;E%iMV~cCQ4`h /&#jǖq8CMԵK $RJ)(IE(4QHhJ(4RPEPhPU.If\_3Mo3<:'_+ɾ!\6rlW[vXqk yī^P8K$_ sѢz&I#-軚@5rOmދE!|QEAB(QE!)(I@!PIAIEJ(QEWǿO.7?*I$$19Gk%CʨH1 K?/j-:ح$F_Dp?'UNOJ͛\>Z8&}7 s2Lc5KqAoƪ(Cm#hf\uR\S`V3Eq $me9(e\fO쫏 ߻5ZtQʸTdfӢfFgLvj" ^߻5ZQȟQ1UE9QtI]Z[O'UE>fo ߫5G V[آfo ߫5G V[آg9QVjUEϸr -y~/Z[עg9Q'տēVr'_ ߫5G,Vj*2TcMAoƫV9r+o ^߫5G4Vjh*2TcMAoƫV9Y_b[?UE,i oIh% ; "Z$hסk7ZHy%ѫMEqZ&I@J))M% J(QE!(4Q@h@ E sOZ?_@om^5N|Ci^kz]q^g/FO_ Ľ/'`jܿ2c|U-s.gC\mxHcd! ev޴=n{Eq>4E{oeTWbNBy!3֯t{H4 3[ܬҒLP Џ9׸@p2C֊Lm;->S1B3}#|(8a[@, Fsq )Es7-kOGxZFho`<0;pjׇٵ>k3mI$g*!>4í+7xoMG욍Զ,mrȪap s;o]Mzvi5Pg2F\ӳ1oM<CK_ZdZطdc*Ãg{{v@le]6Gg߲񘃯6#9ˡ)gO[Xj\|AAΎR )9v4Mw_j*t{]+O5yĒMIUotĺZm;C}PQ9CEJ(4PhE% RRJ))M%Q@?_άk/M}#{\pיLCz-Cg61Ľ?'i`jԿ2qxDչez/sDQHj PhPIJi( %P(QE(4QHh5=%r^u y y\ooQmV.J#"xr{^KT-(c4j.{7-^YC=5qIwwcp5żWP]y 5k?l9SNr\1C ?R5߃*0t殟eV3[y.KIf}7QGdèo12>7|5quzUGnHFDzNWca`oӴ~#ȮN1B @aU\tVam݄h,F aN΃  uyݳh\yN\2IsU/iy x[a'%1B rkŹv YH!$J"~Vɩ|?]},eu,+*FtZӢ%mg^j4A$ 1*Jdr zzӥ #q1_ʬ@pxwJm5 dmR65GDY&%$d )́P y;@p]mKoGN2g!]Æp@'>isyЇ(p#;U(|#lcʉྞ&!epYA t ~kj{|mܺ"QO$:d@&MXmj<܋ 6l6x݌i=Q9i4\\;/#3`v֯@x_HPlbfHy9ˬE+(9'MR%o]}t[ƽ4;Dd $WKE0oݝ\[ɌHUċ2S €;t⧺vq&K{avp̌@tj@-̿fbTTneXX)69, 55t:[_:ٚ"r.PI<-j@o6MUu)#WįnZ:%ɞ+Gf,J]+n_ +g{p"o&^7.Z:nݍA3qL/Wf& 䮒I1vm>f1MRg9}/7) r ϙ1r,;v_}/šݎi-![WH[ahu#?3M[K[X;rʄ 9T_y;/\ ~7n sc޸&sI1vm>f1MRg9},;sGEr, .!dHtm]hukj(E% JSI@%))M%( %P(Uk/Vj_՜nGk˾$Nfdιm^2߉ vFIV7r??Eo#%軚PqM#%軚&8,))M%( %PQE)( %RPA CKI@\^o^'U_pלx@wz(kWoiSr!QEaEPEPEPEPEP'9X\F>g#~θ~7lzolgrkoA\io+H>oH.8w5Af#cv8rqGvR3[z txrdZhD5Hȸ9@wwj~"Fq8=q5Af#cv8rqGvj1~?nLJNtq]\ơuXdRhSC2|7:RãD&vy$@i},>k*&?Ӣ+(((((?iO5yohסt''}xukE"ƇV o+-v6pVeJ(QA %RPEJ(E% JSI@%*_5Z?@m[ yįג+Ե%ݯuѐחLLxӒ*Hk:DAr'o-ދEpto[o_.u7(eRPA CKI@%)E(@%Pi((4^7HNJNyhՏ-:۬-Dv q #aw26h_Hym.9_`F B?/;G+ڢ!]CPoh}TV/$_ vHymڢ!]Bymڢ!? v@oh} jg7^/oQS@J3K$Dbtv9ˎ޵@`ך 73WkCR/y>]cZ଍ -% J J(E(4Ph(@ EPh\_:U+t6q^a8Ei^K$On?8k>'i^K$[:ȧޛFKw5DV2[@J(( %P(QE!)(I@RPA CKI@%)EE: rZцC dVu娑O:5-QH "(`Ճ[w0r~ZmV%ԞHOk2jqBj_`GqrGPB̶ci?`OBJOJ=${?io?`Q]DZK\oOOeqcj4`Gpb'и14KBi?٣KrGHxQ2 2կhfi.Xжch? g?fhA  U',I[?15?4`GpbXж14şj٣=${şj7 mS`G4{IwH+s?|)qcj4 =${=4y' V٣ =${?<4{' V٣ =${=i?\'4{IwH+{' hO?aG4{IwH+}' G'и15c ?٣K{8+ qciG ˏSaG4{IwH!?g*Bxt }ǔ+gU:PTFHdPI8'NIt>~_rorRؗH*tЮNF| R( QE%)(4RRJ)(4Pi(EWVBW77ٯuѐח|M7,d~&8EѐW|C߬Xz%ZOnKǫ?ާo_.$??E^F;w4R64RT JSI@%Pi(EJ(4QAC@RPA k(ju%@ݪ#f*}})>ƾl@ƾ}}[)E}}*)}("U S"QEtSA_JI@>Ⱦ}*%T"PmҭPO/}*%T"QDf*}=("UET"QETPCh}}*P/d_JA d_J>Ⱦj_/!_JI@~Ⱦ}*%U"GjPBKJi( %P(IE(4QHhJ(4RPIKI@%)OWW?@;E^eѶ:bڲW.ːѲVЩhrN{.ћF;w5nd"w5QhPPQHhI@J))M%)(4RRJ)(IE(4QHhJ(4RPHii(4RPhQE %Q@@ EJ(E% JSI@%)(IE(4QI@J) -% RRJ)(4PIEJ(4QAC@RPU_:U_:h _F$-[xU Xs6JmkCP׭oG,*Cq0q*1_.s??E^F8?ދEҐѷIA %P(QE(4QHhI@J))M% J(QE! %R( RZJ))M% JSI@% %Pi(QE)(I@!PIA J(QE%Ph(CEJ(E% JSI@%)(IE! +ub! +tz[ xďטѲWk?n?d5;g^cFT$??E_F8?ދEu8?pCA4RRJ)(4PIJi(@%Pi(E) )(I@%)PIEJ(4QAC@Ph(EPhPIJi(@ %J(4QE%)(4RRJ)(4PIJi(@%Pi((4QI@J) -% 74栗BW6jѐ׍H?=1dc3zkƾ#r|$?WDUc]RI芻?P!hQA(J(QE%QAJ(4RPHii(4RPh(4Q@h@ E PhPIJi())M%Q@CEJ(4QE%)(PIEJ(4QAC@RPE (E% JSI@% %Pi(QE)(%_:! +tz`[ xYטѲWn?d5_7e^cFVz_OSDUۏz/sYΧ(;z/sJCF%)()(4Pi( J J(QA %RPA CKI@%)EQ@CEJ(E%QHhI@J))M% J(QE! %R( RRJ))M%Q@)(IE(4QHhJ(4RPHii(4RPhQE! +u=A/4@mkn?d5?7e^cF^ͮbѐ׌|Fݗy%\~7 #".?b]QDUz/sJE#b)* QE%)(4RRJ)(4Pi(IE(4QI@J) -% J RQE( %P(QE%)(4RRJ)(4PIEJ(4QAC@J(4RPEPhPIJi( %P(QE!)(I@!B:WsPI! +tZ [ xo טѲWn?d57e^cFVz (@q#Ek* ոw44lJ((CEPi(E) QI@J) -% J J(QAC@RPA CKI@J) -% J RQE((@ EPhPIJi(@%Pi(EJ(4QAC@J(4RPIJi(4RQE( Ph(P!+u5A't@mn?d55e^cF^ͮbѐ׌|E՗y%ZLz'`+bF(?ދEdJ ӹw4R6))M%AAA JSI@%)(4Q@h@ E (E%RRJ)(IE(4QE %R( RZJ))M%(4Q@@ EJ(E% JSI@!PIA J(QE! %R(4RPA JSI@%)(5ҿ/ST2GJ违4޻!?FC^/CV_?l!G@Ok>!mfُ%h7i`+JF(?ދE\>OZ?0_LFQPP(4QHhI@J))M% J(QE! %R( RRPIJi(PIEJ(4QAC@RPA CKI@%)E(4Ph(@ EJ(QE%)(4RRJ)(4PIEJ(4QAC@J(4RPP!+u1B:WE-xѝum~q`!?b6JD%-[yOHUu;Y%RH{n_Z\IDrQ6 A=H6ǀDVrg684HqF/{S41 c@H?T}߈t(B/{S4hG)gl )Oa$*4~ܟ{S4}?i>c@H?T}߈>7Gۓ} o&a$*4>ڟ{S4{  QA~"@{>/N  QA~"@{bϽKc@H?T}߈}i>ؿ{R5'l }_&k>/R߈  Q}ϵ>׿/R߈  Qϵ>׿/S}߈  Q}ϵ>׿/S߈  Q?hPka$*>c@H?Thӵ}_&߈  QN׿/Iv9A~"6?EFUG;^Mhk_a$*>c@H?ThOӵ9A~"6?EFSMy[a$*>c@H?Th?<ϭy}o_&߈  Q>/I7M^  QA~"@(>/G{r5{6?EGl Mkϭa$*4?o9<[a$*4;9<Ka$*4;9O1kK6?EGl }/_&{ϥ֟l i7> /Za$*>c@H?Th^?%h'^$Mj}߈  Q[Kt{5A~"6?EFd}/_&> /Za$*>c@H?ThNe;̿{5A~"6?EFdf_IL>w /[a$*>c@H?Th?%h$Ml}߈  Q߽;ϝKl %h{5A~"6?EFboI?MϝIl oI?MϝIl I?MϕIl I?6O>W '[a$*>c@H?Th$j6sEKK3ۺ7c@H6?ENKKHY#GRYaGBh!oѐW|G?;!$P֤i5kb:^]CV_?dKb^}+WQ9f-ΠaKxD|,pv"?x )]I|0ڝΥϑzB,@s20ddg '_i{gQ4af@KIk|K|*k0o4Ә5dQ](!$5[HZiZj!tiwK$StX eIOZ4Zves-˻GuP@H!YxT Ѻ'0QjO BWkIfY#40`2dR mͷd zChVO\&ef*\b2*:V t[(o%c”w=jşƵq\ 5DU]s+19灁OOӇ:mƧҙ26*Wc0ʂHxαE(ȴ5dVѕI+78yg!ҼC&zC,GɒG2}=rM;-/7My{zdl=tzK>;hO-$f8urU4SoN6,giШDzNJ/%ׅuK$X'Ԡ{U(Uhe๑㞀- iwz1Q@XRIYUk^ݛ[kQw8Ppc|`qjESs8cEn T޼FkgSZxc* B|@ivMHmgZ]/HByz-ǂHm'/*V@^=r2:ֹ|7g.e1YhUq"@N8i}p{.{u}u'M:ѠS;;/,s:&@J8 --K 30_a̠$@f's2"NΖgHZO3 7@I^.S}X_j6S|ч4b6 1i c+gs=/_$F6-FPv~`8Ǩi1ڸgݙUbw6NH<E-#:M6ivh&itoPҥ;N Uwڵ4w=Lc@'N~G+~%Q)$u-G6Aݜq־0ҦinNdhGPʾv]95='T ?Q qqf+(IJyOS֢_No<^QwGB$g9Ki~75 g(6s$XTsֵa{%v{H`vl|195xn}7W7o~@i &d;q Q5 u Hlcn]Մ`@ AM]oT 8./'1*paE3X#cT}iW@dw+yg6G(ʉ.pͷ#5o뉦ǩ,7K "|NT9m;VG (a=lg ΢39ڽ1GP-ώZ6&3dfPpFk77ZBf,wHLӥF&k﷧Mɺ<9#~m692$vAܖp 8I X<䬇WmּoX\I$F%ЫA߷ñCupR\% EP7?2+7Bk[+:;OGklCDg9-j$ѭeƝmck]&׻6bJmKgo-cqg1u'<6cYsv}W/m%*,s+J}(C ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (9{B?'l+5 Zפ2 !$[;-e'ʷ2M"s{Ak5\/.&+Ia&(px9r)ƋX]`T`U)Ɠ=s:?ѧaj{}Ak5Hd\ΣO4zu N6ߔjI|-}Aƫ?#?3S;-s:?ѧ`Poů?./-|ƫƇ ?K AGhӰj{/-|ƨ?x$zu =s:?ѧaj{/-|ƨ?x$zu =s:?ѧa{/-|Ʃ1Ak5^; AGh\ΣO4iZŋ _0?-|ƫ#?3S)ƍ;j&`U)ƏH ?FSaAk5I _0H j?G$zu N9?-|Ʃ3ZWGgQ?#?3Sv-|Ʃ7?`U?)ƏH ?FfA[5I_U)ƏH ?FvA[5Ij_U)ƏH ?F^~A[5GVWEgP?"?3Sv O[/ _P>ѨRWEgP?"3Sv O\'bjYo]VWEgPkx\ΣO4i5=+j: _0h|GgCZ?ա=s)ƍ;o͸6nC=sZ? AGhӰ=6nۏ _0H j?G$z N*|R8MVGk.z5S=; ^ioo>cuO뛿5Sk'ͣ'Z?Ӱk _0??1|?#?5S)ƍ;S?1|p?1}|#?5S)ƍ;1{7U'.\ΣO5#?3Sv/ #3!Gi)ƍ;g/uA[5I]VWGgQOH Feo(?'wA[5^5 ACh\ΡO4iZίt+}Aƪ@.ů?x$Zu =s:?ѧa{^˯ _06]ZWGkQ?$5Sv OjwAk5Fۿ _0_H j?H|GkQ4նj`U)Ɛ]֣O4i5=`T]֣O4)ƍ;z?+|ƩK1K5^:> stream xXYoF~d> C%۩sNԴ 6]Y ٙݥDJHhS7|AzvA`~68^M7pHFcwg%,pǩvA ?^~/18h 8q('' ~8VP-dz~,#2y$ da<s*gs\Xu0/\.gsM҉  OD(`@aK>[)3R riQETMpcåfXTyA ;?D dʽ+VFƖ5|G6&-R(ys$z/9DDG6я+q3$Ԏ{j#4(*:U!G}REӤT znт.v5] 2P6_L ZHӫt?/o~"\e%y"XUҬ/o6ècQ+됤|C%$3&f @R^WWzEWL*H '^\kO0DN`+ jjژF+U endstream endobj 125 0 obj <> stream JFIF``ZExifMM*JQQQC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222*" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}:R5MN1u%bo8<x ''$5atm?kgB>҇?-j s'RP1NNZiZ<˓ Thz:#GӺϤRY`p}\XhfO._Gh?+̊ßPSi4};M#N>5mNm#NH³]It}fK1mh32N1i1BqAm5$ p>nr {Z_ssGF5-G+Vڽ]jrNd؋L20Nh45yʬDV$;<.0c;'Oi;$VavwGk)c6om`{ #|>c[ @'q B mt]_OmBۉDCgx#9bMr܈X]F?ӿ?𪷞ҶF??&x^Qn{q({(y NсװLkWi(o~` V#yopxhtZ҈iqHio6i{6{i@85xk:ޥ}m?E c],A#X1`7=*hmkc>?M$O:i V>D$ ʬ&&"h%Tr#fhpeیj]_C;# ^ZOpvP 44;#jӺϜMnnƛj䐓dVNgHӿ?C>[*lqQaѰQ$T/4%ˤ# aZJjs?dP?g|knKd@Ng# OEjZcRqkbU#v Se4e>j!Jsjb"*w3FX#NH“KAwG աQCT9fӿ? ?$]jVlE/id#OH¥K (#OHµ;J( ֺ`l.$MMoct+Q'8-J,Q:;#OX­G?,Jm1,+ӿ?›&$hwbrJ1Ə$Q$NHº lɪϧs.=?Hi T:K74+B; *ۅ4X.U]G ģNX¡4J6-PpdP{zVZ) T!6GKqy%-t9_i~qYBGMWğ,@͇+(:B8`GȾqq ٞK#Y%>T"S? H},gtЁr)BmG9/)'X=ި7Vf"&rXv?SGkm>Y ŧ#dD h jvOA,։DJ) m?R}:k)@SRC؂3j㴢mCvIF̓mأ{^yE%5qʪ@crsb]CÖ]'x$b)#*HV_pܛkri#.;|BCam*Hx#<#5N"4ʯ!kfl2yַ}@{;IѦ_I_ywKƙ-J8^;ǵD{rbl,G,aBJ!U$99[o ZCsחW\&)FaHU +{vVCv{$y_7Ы9$'Gyë[rQ,pJH}W ?!Ӻm+S:|R_^Vrd@n!ad.qb~_\n'1M A$yc%=}@;SZc[6 "nݝlt1[R1f3p13xZ$KeMgl-Vksi#pqu5v}/? 1_mM%Io$I%.GUEN08P~ۏrUƕg aZG*.vZ[}}h/}}jS2Ց '0w]Řy|?SԬյRѺ%'%"mVckC̾=̾=u5,B(#yT)@d=KUmo=Ve2*pa}C}}h 23TC#`vjfZUO2v$p9YF^^Һg4A^^td@}?&p.̶ubK0{;N^_p.̳})y]ouvξ5,,sPIo{@k;K^җ,$Ђ6:v:v4ʼcQ? }}h? }}h0 65:v:vccRyli|_p<_p=0ƅjp ^^֑Q%ݖisU_pC-?UY42^_pBs $.i0poo?,Ǘ4yTxEm/?, 1ae$Vx[0;R+ޯ?Af^iV }}h? }}h 2r\>m?!{p.̔Q4Mw^G4׿㴙=,$z5o9Go?!wmҺ 2ukvKgauom6mDpڔOp.fXNoo.vq@[ҋ-,Ǵwѱ6ބޟ?6]F./ }hE?AfI?6]mh5M?Af?;~m?ӿ}vtdF1iDm0UFrp2zߵyg&Czk;iDLd0Rc7Mk)i^K#C'Zyr-\s럍[dO[Z2ͫmky ŴqO֭/ccʲ`~^Pe^K{@1K!A+}F?7y8dR%vp=zt#ҡ[36<*@9"8{o-`~lڋ Շ60Uip$3р> rFarbysV*wkn̶!7 zZ\J)Wn6 ͉\Wпs{pП:G&~ΨXxQy3(@ŏҧg K9'c*kN嵚ȩI\*~Us؞ V%a!!U"fn:@|*/Ico kG"2)fb *ѧ [7ù[y9sM:TeXR 'xX=,z0 O"֖]Z[cGdKǠzՋKVt\lIɪ?F$ $%c7pm|AjJ\*30:}){H'7mQ;Nmr=1XiwW&9AJG#aBpW#z햇7|/ʑl_g1Sa$S eб]4K5i[ qm  3muiUk%w7c=ҥ}tw Ζ)sͼuʮ#F=z[n#>YHt$zV Ug fVv|aܑgON+JE+9 HU[dˠ_S1h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣcƏʂcGWAvXƫtytr,}cU<9P]>h]].o4}..Te>jGG* o5_ˣˣ "MnюF-n: yA/H1>_CAg_%KA"oaI2oz7.4By"/m|A C |8TƔ%+I LUT:m2yRI"$j+'5 w+0X0ܧjfڗ,E\ d$/F~F}d!̸#V:5ܷq[,i/>?9O>??pZ7=k6y#ϩ< G8aRu#&V8TPOfvW7Dn$-43zg8rkYEHvɒ5y_Amw12Id|:7'N1ov)mdô/P]GYExH?RfymeO-à/v Y/.mQCs9%S¹퓌P.f_y>Tg{+,<7*jyU,P&^?|)ލI +60 y]įG l@eGpO .4'(J̷ Zm" uy#cz>LUq7vC̼g؊|?jI9o.0=++ͮ q4G'2c Xd#X"o5T n Zl#1FV6bW$t TC'FARw}foezٮ&+m~Q{{^isW1cC} i:sNJ"!;򽊷QXYT$'RO@j֏swD.6%lG Fziiw1Moh.'k]I=1ڹ-t5;Iwh"0̌ʡryǚ$4E&ݛe⪭i6 Wrfŭc* u>ukH>{X\goZm|Luw!=Kqmgo "F1s'V`H7FjX;l#gǬ_oYA!QXxbI? BHP;H20:֐pq&^-ۧTHd{Ud*N6zЌe6;+zuO-|xN m4ӮٞѬ]eYn K+8i$2(1?Eˠ$2"v'8(e_ ;>CF KAt7IάiKڷn 뛌!eooI&_*U dO]i%\3\LL'͹՘a{*REk::Ic~:\v߱NL$I`[GnPLڥ['*Ƽ -B+Y%P$eOuO٨Nuekmk}t(5-W뮺XooI&_*q,z*36jKń*}Xo1.w`t9^ ߿* G{}M0+Nx+ElmC/T.e?"kH)9%d[ڤs 2`P8'5k'M??PGiPQLUY[>LUݛe\ ݛe϶/VhV϶/G}fE}f?7U(7Qmٿ&_*Emٿ&_*o2Uf.oo2Tgvo 4Qp+gvo >LUY[>LUݛe\ [x-voOҳ?'Eg^K$G֥CN2 W%#K$I؆͵U('o0j]V-QgJ:#qX#?:JCtc'us[ڸKQbr2GN=yi Gx0K}$$ѴlU k;IH2C*? Cb ?l?5+:H7wS^C{̏wmgWppZ~D5aA_Gs<%S8'#Ok;rBVv[bB\u˛c 7cݻFsں Cb ?l?5+'N18GxS_&4h<Urs]_oS?MѰ?/FPؿ”)$A1mu/]@V[ɝ#cЌW0 [ϴj]ے1(lhjQaA_Bz[E,`LP!oj{xc*#''K'G'K'PQOP-5E+.1x??JKWX1V|?_?H@@t 8p3һ&OO&&OO&JqY-RjG[ gjVpF:DCHzۈLr29jǓ'K'G'K'V.Z;6&K>&OO&&OO&ڮvZwF#>::~o.GNOnwL/ML/MoϛC/aMOڕ P٤MX]žO66Mr1G'K'G'K'X&Ӻ8&{+'?߱:Zu44@6Awkɓ~ɓ~(EƳR{vZ*f*TR W.6tM~VdރV'*`8q]w'K'G'K'Zz&g}wwJ$LXgIYGh۪Hy~ukɓ~ɓ~t<ǩ EƜ#XȰ8`tY2}*hg3?Zd$hd$h.g&yzuXE ([4%vb `럓I$ehqY }xEuL/ML/M)%(aŸ˙nT,4{{[XoTWy|?_? +FXϑ# =O=O溿&OO&&OO&NL/ML/MIDT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/MMEC?RI?RIT>L/ML/Ms)b?F[א|Ev:6JmbɬZ+Hz^W*&bd2Jٜ!'Rk8c!Bc#ޱ{KX3"йe p\smcY*jvFCi,&;66g9,ﴘ4Ki1ia7ݟ0oS3,<>Kl;)K$ ~9ihߖn_yY6ˈK/1~~bA^2m=[{KO[u%&5|Oݬg~3HkG7*7 dc\u{m JQIWs!iprrOUaigoŧugtR<DJbO Eó }k[t75 p [*~> nhz:UI,@Fz'S|?A)ohбB;IѰøl'1{ )3&%9 p>}*dEBJ[^#Ũ}MosfEh8ҵn/No-ʔa(x55^(a8S?WWrobRy3ݰD(Ft޽uOS55BQ\GHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEn'-# y/GQݧzO^[;F?_%Zؗ-5"xk.n" (i\('td+Dt8z[F{ow4H"jni??4 YBro/]]&xyddAiޛgXCOIHypRB;lw_ۚO,!?Ə'_\zޗ>h?:ti&B|ҹ8NuûSLxywݷݍgiRԪ?_'_GAK/O3~&-ލqv#FxȈV~r::/Kuyyoc(i##U;sӌ5?WѭU⤶gQRh)e 5],u:gHSʤ$lcpkJR:{t44 YBA{76ID >NŖWGΜEI <қ8 kBRK(Kv#ȑ)ۜUXn-}?ǝ'Jkv5^M>,@OR( Z?ht1hmH9Mi+^soʬy{?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'J Z?kcΓߥt(ţGC|U%]:B"r@n-}?խc4 ,'XViw:,nR2Jt1hmţI4Y$/h(]\zu/:O~c?bLɦO}2/#I昕T)%>qҰeᠸfhn+;u(CţGC|ڻu K+y7U#?>SV?P?ۣG?mn-Iҏ:O~bGۣG?mly{Γߥc?b[t(@n-}?ǝ'JSjEy~7m?^}6tv mhYrDXN4]Gw3Ήң~LQsӊ4Vֱ5?@T1?6o]LOi,e}Zn%Ruev^k_Y PkFӿ1Ү.K{x"Ĉד^m5 ʹ5*g}Zgi‘FX9,ŏ_sRү[VK5_/Λ \]ɼe"FrFCg9[ռYY㕌+`e5G,w߱ G+L%? -wORcKY炭8@&pXkwY%n}~G,w߱}C_/L'KM}h4}b7kUa,m?oHZ8LDY![Kمe( qY5C~Q #]? ^WOirWqX2YIJ%iȵ'?whc 6zy,w߱G1/iGQ^? #]?5C~Q G+S #(z?Yc(#aWG,w߱}C0? +dkއF >_ja?{5C~Q #]?P/?0?=+^g1Rx MJ ֲDipB=giVZ~qqqxf4x^]iIjtUf)!ʗvO85C~Q #]??b?U_xN :^nt-9)H8rLJ䵛PLEb,fئ߼ >l9Yc(z?b/~_ja?jiW3Qx.]JΫʾK(#Z|^RB!M7 m+q^m #]?5C~Q E/~WG,w߱}C1ja?{5C~Q #]?P/?0?=Yc(z?b?_ژOEx,w߱G1L'`F ?dkއWGQ^? #]?5C~Q G+S #m&MRLRH;ycY!dg GU*Cq|@tXDg?/,w߱}C0m?67x귶#,Z-P37Ȍ`ǹ53:+n?Gu{v\P\6NF3+z?Yc)g-n_jao~Vm"oc2#Dg<(^)z5>"A^,6SK{C+ľeP@c5C~Q #]?7?a?iٚr,5VW3AYIpP#` fEaY3 $e9( XpG,w߱<!w_ژM=s.<55XX]$Aʀsh,: ٚ@ "ör$u WGF ?dkއ1 _}?75MbMn;G(+NIoFF3EjxcNd%NKKa$%#dkއF Q{1i-`F ?dkއ G+WG,w߱}C0? +dkއF >_ja?{Vw\_A55C~S$KXlG1L'TT4Ql"Me/OѮ<7vlt-"aH2K8EY x$@~)5C~R/n?0?4,<+s4lUKm$6 `Wk+ M +V!ҭtXncE*g(A<) c5G,w߱_Q/?0?:=S7&r4afo,YA(s6BrFERO |ShA~U$ &[|0'9?5C~Q #]?/b?_ژO~ K{mͳjShs;3āU{}Y歬zo؋ZHʴd4d7˂Sz?Yc)G_ژO%aMܺLWO4Nfd]6w5C~Q #]?/b-n_? +dkއF >_0?=Yc(z?b?_ژOEx,w߱G1L'`F ?dkއWGW/F dkއt^k,!x@F8޵2ׂt^hfjP~ODտ?m^2ω0Yג+Եs~n?d5Od{? % `q7tZ)ln%k}.q tҫM-#olޕ4 eoiZiΎ GP3׮3>3]MDG0E|Kڴf' !N`tnjK 2sЃ9eڤU+r3Vho,mFҀHX_U}S_5/$0c/A.MxL5V^Kn־gN Ч*R~_[_k˂Viw=q]Wmnc!~_$p14W)_LETr74 | G*%ku}%u%M3V_:[^d6IakFҬ{ܜfkKpDzN3?h'_xsUсTxukrC*]\}S[ʐ\P69$r*χt2\=JNbNCzK@3_yv ?p^T';69vُǍݏ<ךFCe4z|}ׇt{=&7Ҽ1RDPNb S矧<2 evKcrbfX`NÓÃN4w,69`8K `1\36cjmvaRU"ɿྜྷ gJӭaڃ]v3H$? q=lgkhoze@d( ;ԏ$YHW&ry'gG}>G3O@|M@G >&gG}>G3O@|M@G ^&oG}>G3Ðl&Ӡ}n%\Qlgi?7<U8xB&X0fOǂFpH:֣(۝}Ҟ%^b[ ;k(.'t_Y #e912F3Dz*&4VlhM꿛; 1R/|vjoB:uJ<L-%]&ی1Xs~.{s]O悬*O_3Etx?*Akh}̘{j>>D{ jM3=8Pk٭C9Fܰا.g9S5[9? aŒC5{,-J$y E?<!3M0yJr1g]I2ES@%rx\KdE9swb=;%ξW&Vn?Ucoq ~#kE"3kIuȴum \Fu3.7'lc3xC<7W{be4/Go5#H9 ⦻..Y8C5ڹ_[uiI}}W_~ɬ,- Z9Z\<;рXF\m$ X$)*&m d Ϳ"&wp>N_Fm 9˕;sb)#Ѽi M$`zIN)}pzsVѴշu{8"̮ܶݠnqdk]KizEԳۤ%K_`\m[[ye-@w85 Z7Kcunӹy<@{7?i̟e8Ɯo1[: Kx A$fLLnlaqǵWuo7F};Nlbp]89n;RmiRKpR$yAqJ45XNV-3XMPBʨ!6G#0Qsk:140Xۤ3IR%򕙱 n$۟ \]E<$J1Ӓ٩'(^/MWcIΖkE(VwOLI!,q2e,N}֚YGX{vyVp,g;$8=I=);⫆!d+||ܷ^>`63pRO sg~qNUiFXjrJؘ5`KW6qa?#mQ*~,W";ypۄp ;+J./Čp ')jUʅ:˯GC Ϳzkʾ"jW_ͷz+ʾ"jlKHP`+efz/sXȌ"d]t& ABQE)(I@!PIA J(QE! %y{USv!_ZETboր-Pj֓@5SI tWI tT/'ր-U_/'ր-JbEUb TU_'ր-QU~ؾl_ZAl_ZOZl_ZOZ}i>־jk@*֓k@*֏Z4WkGր,*փvfݯY}iEҞbQ JSI@% %Pi(QE)( %RPU.IuR?h -{CVq *!/2J]{CVq!*!/2J/s??El#5軚ŏDT@'Eh`T(4Q@@ EJ(E% JSI@!7+\KO5j$kkk`Bq'g[ڤ#n{VaIֵqFdczSJMo1]+m+Դ>P*4 aA9c:zU"9*m(,~o ˩jQijL7El(<8=cW()o;R&n_ؤ۷q "Fy@$ddC\XWg;_QG?)o;Z[C5,'-#Ɠ BWkr\ "`Ks H`qɫG eG 侞D9?Oڨd.[[x ܤ =W^b Xܖw=Hq(8>t8wA&QԄʤ0 2nw}%.O^c.g1E!)(I@!PIAIERPhQE]_3Vi?4ZFA^UC_?dFA^SC_2J=OBDT@'Ek?DVԟ2@(((4RPHii(4RPhQE %Ph( kN?4ko߇ڷDZ:V_na70CrexE֚n{t].|цmn`r!\&.rUu5ŨH^h BeDAw( 0yЄkN_Ԟc/[v-\Cc4Ė(o9om%JO|ûo6nlY]Q`88P2: I抙A-wM>ǚj,XC,s6YDvԍN$-~E]vzş$|亯83@ă=3]ל*Zͤ/m o#fFF䃁i~_ [CQhzpK[W[%$j'y@UD@cP#FAR9zf&fs[8V[˹VuǶ?3epI w(+K[4pַto%ٯgYXbl J Y_k-ܵ=XPs9>C(z]rco1Gn"L+uܗg< dp=YsNi3PUC}i4I&ZASQ81ɦ8DM1&ni KfiAN(4(jPi(4jԀp5jp4I\k%澻G2Y#ܤbg]j+k{L7v\DN|Y> έ?iS|=gF ˯'joG.ÜHelcb+Cҿ/&_E]l7g1+kM2ZKClU OAsỰ$Nz4OiK_MT#*Y(<9r2Z'P:)z?#1h6Yʇ2Uƞу. (kBsq=wZ+ ^5Mlx,ʽ;L? 0y[ʽ;L`tҊ %P(QE!)(I@RPA CKI@T'fsO4q׭9y/O'ͱkyWSjӐђU-{`+jOmދE,"?ez/sD撊* E) QI@J) -% J J(u5wYTJu_ o.3Vj3޳YΥsF#8v2QՏ1{~Tψ;kz)Njg}zi$}#?eL%Q+\՛ބqvQ\m[حGK[m2Bce'_Z::+AGoo[šݪus73*6_Uy Emh6:ڰ+ X b3z_nm\Ğ(;M3Kyvvbb vT{ 뤰|Z+ly@$0>GK&ݿUEdj:Z\vSE{fN!X}qXxnM:dL%h5Ȅ&sB5;katQ\&/QX[Yom!*ddP̬^iz AJa0;ԉ63s7y;tWx]д8O䗻1Fc@0uB歩DCZJ6n` r*I3M#v/lO춴KdD$psd3o%\Mdws-I&Z ほq۷89GOSՅZB9ȒdF&5\ؙm2+4㉸8;UC-k\^(K,/{峐EsFiUՊ)n*eo5KKm26i绍KUrHl9j Y]vW ^Aƒ%kv 3H& $I\9xGH]o^&!67] c?{[۬Z_5fZYBlcv$cXt'W{; {+m>EBZPBd^NVcE.9P*A p{\+7msW񚏴kS-<]N-mnY :WkL]7LUPBPݍAxNJh 2%s +UU5KkVfXkv.VkuuK{mIj}+N52n5Z۵CLe;NFpp3ҍ[MO>[Z,REmD"6qj(z ǛUōLe\IFpp3ҙQ8u;ฒhʌ(qڶ+&RK;q-::$`y=r}u?k;vB `89Ӣ1υy%gw4(E p8`V1ē6wPT=*y~8-Vf0gG0pVUbiʲjk;QW VƮ@M 6!cUP!pCr9'4M4\jH w,%P@ 8PnY.#U._`t~i]QPnmp0## cm$q'2o<ۼN*[iZc;c+k(  ٖtmY`W9o\:Ab_]IvJ7^s1R9(X ҉+{Kn?JnDyUg^(?ʽ7L`tPIEJ(4QA( Ph(A U[/VU't܆=j؏ѐזFd+58Dѐט|JTdK!z$NDՙez/sUt&K#-軚$4oRQEA@i(E)(I@!PIA JSI@549gS+3? &&?Ҳ Woa=DGhvzѩ{lQE!Q@@,w yH\H$8~ f 8u?־1٫oaRIkr?鉳tvt|F:l_l? hpsuEsEo#F?־1عaGS=xOG8r@sc|c 7LMw۷;Ǘ1cgZa;/\~ f 8u?־1G16nn^s]ckM,;sGEr,m,7eDAh䄑¹8~@tY] OGgff9$$ҔRWLpdm?Mw'Hp'OT RGGN ՇmJH $Ɗ2p2H$f۶,+2F`31F~*^b ?]:P*.@O˳O1b$I¬2} +" +GRK<DQ=9f~T2AHn7Q q5MPߤHۻjNq3܌2cvMgTܛG:O}s>2;}Nd&?vX jf"ERs~g3zn;3!ԧk7R@ʓ($n2v'Mdm-VIkR5 P,-b0˅n[qVRZ'߀!YNF57 R}P_I v WW'<+BuҮ.2dg([x67KNTDs83&:gjv ~`ǧ}koA\jٿHsvԜgdL^5MPߤHۻjNq3܌2cvMaa{Tj4hC6n*csgrczh_/i+ԯ-V9ty8x!cV7Lʤ-촘$m]o8pBiMZ*~E->vє7?>JX&g[i$VVȤtoҝ4ނʷheDxYXd0Dy?u7nmu4Umyg}I?*;橩iVQ7fzlія8 #۟}vkۈƷdFj)$<ƪ3Ri6WIq:giu SUqZiO y[=ikoAYiO )ۯti_w?=0\y[{XV.X&ieyC8aWc槌sv?D5cm+>vkmBe, cxE`cE<8 gS_q.Ǧ\]6eK(@sW=*ҟݺ7JXg|M+&KՍ1j D~;)!N0};xkKowg4/]KY~B1Jvn?iO _3 &ҝKS.]G1A r=ϫ}f}?u7nnӾStw7舫;)ۯuGW"vHiF$RUcDSC֐tQEQEi_Q%tu_Q%iOr&y?4ϸ+̼)vM>6;Q@A %RPEJ(E% JSI@%*_5Z?@t?1׭ y-7Ln?8k(k^KRؗE$??MO7Ej䜧]nQE!(( RZJ))M%(4Q@%)(Li9g[}+'%DZm0dn3pCUvzѬ+;"\M4Hi#8FEXڗ7qwjJƭ'o?nO;G,VOܟ v?ym֢?\*OUr̍+yym@oh}V?]㴟w26hoH?@oh}4V0? v5=4oh}VG v?{ms#^ܓ7'odkYۏ@oh;G+ע?7 vW9Ecyo?> #aw26h_Hym.9_`F B?/;G+ڢ!]CPoh}TV/$_ vHymڢ!]CPoh`F B?;G+ڢ!? vHO?dmW3߯~DwUB)k^KR؞u85<1"r&F;w4HA4RRJ)(IE(QE! %R(on-%UkE=c_JI@>ƾc_Ji(ғkVOkGU(_AGҭhҏ/[?/d_JI@>ȾEtSHmҮRPO/}*%T"PmҭPO/dOJi(ҏ/Z4PO/d_JET6GҭQ@ QETEV U"REtWHmҭP_/'ҭJE[(V%F(QE!(4Q@h@ E (E%RRJ*_άUyJ4M?q^iKFk__ n?8k>)k^KR؞u85<1"r&F8?ދE F٢ ABQE!E%)(4PhPIJi( %P(QE!)(I@!PIAIEJ(4QE %Ph( RZJ))M%( %P(QE%)(4RRJ(4RPIJi(@%Pi(E) QI@WBWVBW:ye[O_3Zגo^?q^iKFk__ ;䜧w5 _NSD軚$ۤPPRQE( Ph(CEJ(4PhE% JSI@%Pi(E) QI@J) -% CKI@%)E(4Ph(@ EPhPIJi(@%Pi((4QE! %RPA CKI@%)EQ@CU_:U_:hmCֿץ#-zpך|RCz=N/')`qjic]C8541_.64RT JSI@%))M%( %P(QE!E%)(4RRJ)(IE(4QHh %R( RZJ))M%(4Q@@ E (E% JSI@%))M%( %PQE)(I@!PU_:CJ4O?q^iKFk__ n?8k>)k^KR؞u8541_.桋I蚚z/sDF ABQE)( %RPA CKI@%)EQ@CEJ(4PhE% JSI@%PIJi( %P(QE!)(I@%-% J(QE! %R( (4QE%)(4RRJ)(4Pi(IE(4QI@A/4^_i_'n?8k>)k^Kz\2׭ y/7[r&w5 _NSD1A_.6i)M%AAIAIERPhQE %Ph( RZJ))M%( %P(QE%)(C@J(4RPIJi(4RQE( Ph(EPhPIJi( %PIEJ(4QAC@RPA CKI@%)E(5^_i_ !_ΚF[o4#5y/sm^5f%ީlOSI蚚F(?ދEI`qj{z/sDQIPPPh)(I@!PIAIEJ(4QAJ(4RPHii(4RPh(4Q@%Pi(E)(I@!PIA J(QE! %R(4RPA (E% JSI@%Pi(E) QI@J) -%ҿ/SOi_'n?8k>)k^Kz\2׭ y/7[?oP 蚵q#EjG- 蚹q#Eh#`QEAB(IE(4QHhJ(4RPHii(4RPhQE %R( RZJ(4RPHii(4RPh(4Q@ EJ(E% JSI@%)(IE(QE! %R(4RPA JSI@%)(4Q@h@ E O_ ?#_ΚF[o4#5y/sm^5f%ީlOSD@5rF(?ދEH@OVb]lRRJE% JSI@%Pi(E) QI@J))i(4RQE( Ph( %J(4QE%)(4RRJ)(4Pi(IE(4QI@J) -% CKI@%)EQ@CEJ(4PhE% JSI@%Pj ?#_Φd_:hmCֿץ#-zpך|RCz=N?'`jP?OVa $ע* E) )(I@%)PIEJ(4QAC@RPA JZJ))M%RRJ)(IE(4QHhJ(4RPHii(4RPhQE %Ph(@ EJ(E% JSI@%)(IE(4QHhI@J*?#_Φ5GJ违4U?q^iKFk__ n?8k>)k^KR؞k@5fk(WX*6rہ('VI ՚.\)gl )Oa$*4~ܟ{S4}?i>c@H?T}߈>7Gۓ} o&a$*4>ڟ{S4{  QA~"@{>/N  QA~"@{bϽKc@H?T}߈}i>ؿ{R5'l }_&k>/R߈  Q}ϵ>׿/R߈  Qϵ>׿/S}߈  Q}ϵ>׿/S߈  Q?hPka$*>c@H?Thӵ}_&߈  QN׿/Iv9A~"6?EFUG;^Mhk_a$*>c@H?ThOӵ9A~"6?EFSMy[a$*>c@H?Th?<ϭy}o_&߈  Q>/I7M^  QA~"@(>/G{r5{6?EGl Mkϭa$*4?o9<[a$*4;9<Ka$*4;9O1kK6?EGl }/_&{ϥ֟l i7> /Za$*>c@H?Th^?%h'^$Mj}߈  Q[Kt{5A~"6?EFd}/_&> /Za$*>c@H?ThNe;̿{5A~"6?EFdf_IL>w /[a$*>c@H?Th?%h$Ml}߈  Q߽;ϝKl %h{5A~"6?EFboI?MϝIl oI?MϝIl I?MϕIl I?6O>W '[a$*>c@H?Th$j6sEKK3ۺ7c@H6?ENKKHY#GRYaGBh2[׭ y/m7FyO[G?<>ל|QCz/sI ]GYH7:9-mw؋$R?'`iڏSԣ/Z(Ve.sSW—Aǩ:LK<2]M]R[u1uI Ng;2 $!;o'QNgatԎެqEB,/Mثlx$IFI-yda##=kzvrZ:%X'.@ j i,᷷WZG\rz1ӭ-Yu9#;d ̑,dS ;}/"[)亊xйc8,RI$n rw7"$laxĊ˵0t *9e7Յe_{㔼}3Qxxຖybg9.M8I=< kZV[o9w|j0VGC0psCYWusv4 B iVC R P?.,XFNt@.K= s\#9%9;KoضouyGxݢxcdrLB r9cVlzy l@,dOӵdx벁[QmSyfp|#<~Su5bm!kI[9y@cͻhqB nYL;{]$ԕAi Oh 6bH߻qyZnuZi$ާvr6凾s([+Z z$LbdTnLh"0? 8=j^8d[ǖ w"A$4Y^0ʘU&2rpsW].Po`77x#ht wl> Rߖ}BȒO'\z)B$O>ybmGh2͉ek7mAj>:Ssq [D-fiI<ʩt*=:\boz}ܛ#Ø<7`nsy"Oo=]jGӄȞJyyJw -ku5͔Otmh[In  ny ;t7Wme%[pțQ q"I|t,fӬ#-vf 4I~M/\i6m{j/0Dv躍^o67pO.Rsf8O^՛:Ni]ErѬBX10>R<JB(0((((((((((((((((((((((((((I8k~(k^KzLI8k;'k^kZ؞y4RO b@~e*#E] ?p>vffrqA{7Gn?/}|#?3S)ƍ;n\^׊GgQ?#?3Sv Ol7bn417^# AGh\ΣO4i5=:nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Oo͸6nC=sZ? AGhӰj{k l_0ԮU?jG`Q˼ j?ON׹u[Ϥj.A:#z j?Z=sh֣O4=:n _0H j?G$z N _0C\_0H j?G$zu N^}nS=s:? AGhӰj{W/}|?x$Zu -s:?ѧ`\ZK _0_H G$Zu N?e?auk?)ƏH FS^ԃO?`uk?)Ɨ=s:?ѧ`ۏ _0?n?1|?#?5S)ƍ;fbqA7^! AGh\֣O4i5=6nۏ _0H j?G$z Nٷ`tfb׈GkQ?#?5Sv Om:};1{7^+ AGh\ΣO4i5=?`t}nW-s:? AChӰj{_/}|?x$Zu -s:?ѧ`^; 0OH G$Zu NbW`u)ƏH ?FSqA{7K 0?H ?G$zu Na7`u)ƏH ?FS~qA{7G.?/}|Ŀ#?3S)ƍ;n\^׉GgQ?#?3Sv Om?`\ΣO4GgQ4\Iwqs"FnjG_JXM=u1l\0%=}AV-oV(.5K١^9.zNN8Tx M endstream endobj 126 0 obj <> stream xXn6}7ࣴhIv ڇ` GvlѶO_vlɖxm4N"F\|\%9;lߓmet9]ϖYX/&Jj9'Y ·?>pP1v8}Q] 0p­'|Y."ri8 TeaRœi)yMX.qXEzt'iWlV8Q~;8G' ;cl̳ i4u8fsiF9{]':*upp56_=W8bOO) 4N{:Ge10ʸh6zb;zSBIfX FV~fgZSia- 6a`*μL?OȨ',NPD*M&\w&bR"Me OXCwѤX IHz( $}~2NTD__>4eMd8\"[ݏKSD'Qcz;3ڦKzAB1~BR (3" :ʌ58B6[ dP{R0)Z$): 7-S**)Ѧr[{rD~чř>WvH2غ t{"MxUeW籴AŽ "N,ʠC9xfzT]cyruAX֊ QRm0d&Ks%€I)2K$'%%(-,ס׭`9\dqh_&tP @gXU%J΃*iAܛo漉4oC~Wη[ ZoU٨x[ +JÖ- smB2vl7س SGPRGlFJ*Ϊ/rx5.i5)`:N ;]v6N&@ļ f\W<0T8Z06* ]-]@HlAiG5罸-v_ n;gP&*l%2֌Iv,n08!Ӹ`IvK2_#TB{+uUý0UHATۻXAM94 )+I[Ek Y!|T"tVq{= endstream endobj 127 0 obj <> stream xĚ؝Tn%R$wǞVu37ήq:({Kht4V}A HC8hR[( <~j SSSwЁ#C9-G}bSo?SD#Ǟ5BZ8gC 3rdpѽ GhaτgjC<>pخv;}[vо.exi|1h_O#Nw#{ܱ}`֝lnO[׿8k۶|-;vo5m`h]Cס}5;~zPY{A:BƊt4|F`8uSڿm{ ` fonl8<]Cۆ6{ۿyK_O?y? 8׾g[^o/wl׻Þ]xyhw ܻc`[|/カ+[+om׷l߽wKa >{Coܳeۮ׶ @S/:ij˶عu.۽w3[3mwfᄎfXKӞfFL{vA 9L=rtБ탇xYؽom\b`ڻ& Z?r9f?g0m{ȣ_5mݽ< 3 j_oZ p蓽M[Kf$3A_(1r?}/7du٣yaxᡑCoiwϖ[x{;g}2uxCV!wh/Ql|h߫'v){}=2}dh>2kddsshddhˑs9}P{=zX?J嫛Bb%:O!38o~=;k9?~=?6VMz;Gf^4:: @D"J0̭[B_\6kz{UkuFW ]Z-U/1:ZN^1wkFZ+jTЫ TkM4ީ]+Z_a>蒭Y#5;kj{^SZk5cjUzZkuy>W+OZ+--> c\rSJXkau4ubUS//%}ZQFW*j)Y)DB ysY7vd(;ZN'mT҆mZRvvYW,XL+LCJ+\SrU,9D OeR. ^*KZ dĺffR\RT*AT'Mq) d½V V6*p1$ Pʴ'{ BY)ךhw$kf{7VeuTN֖*Tѥ&ɪ$ס\%eYi5B]&>m~8CZd5;r]RBMW4܄IJ&8Vީ]E[m7/x VlTx5f^u֞kswf[kzZbF UjZfCl6$U-jYUjj 6Hj"1Р6koYb^+훮錾М C34MWu]5JV [b5]_ XbhojKo7kC* f >齂oy%ѯhL]gkjez*y䚕OVp*hcF@bMRz?MX&Y>^9=[zOF]ǸM-ǂK^o,8֭v-ڐ(fWhlA91LNqFJq%Z:/kR((b]j/UL[y9"\07Jiw$sHI!gВ\M#Z rsCbyDԪ.T j*lJF$=7tW@,t"nRҵ*yRhtLS;%[nv&鲬d$8(3&F_|[p_]]^j~{16Y9l=Jy\(Opt^eK:_1JvK <RgAjU_5~R5"RVvBh=.ۢpq>T J˱ƹ]2'+-0%5[PR3[jp% -0| 6PKx7\>&o^>ǿ鏏?q׿|_OO=3X >ܠSR$}`tstk3n8/FO~ 7&ޟ7?ԥ[gG^=yw6c:t 8[j4[pp{l|ssbG/~p.{'.~tfś箍]3ymjPt>y)6WB-:hn!UR;!!N7-*/~qM2S=2eAӎЌ#)w PB$Sd`JMt\Q޳8ɛ +dW9Ŗ Ќ@Fv% aqƟpeww2wmen%xCl3.hΔ D2qTTՕbsNх=|SҲE%zN&sдh^x WI 0$kzSlqFu\P dzv%Fe\.e,5M>|*aKcP)rۭz2Zx_r2)p2˦ $Lc\$","ƙ'8g_UfHH2Re%/r>Oz&AٚR6!KR9tCki>q!HbR8CO%`:$jWdT BГėښ#ZOSuOo/\Y5+ TZdJ:#10"lNd`M;5}j@?࿥TPIDHHPAi!skV!>a)+ebvuxRo=6:׍jwsjt/\Di#-Ѻ71S\AaXe WJ*z0Ol&mbvUWp^+7'JAIri4I~\[*S|k+ BU+ߺ<:Gj.o9WV3"ܯN;LEwHx@B-mrW3$3w+_^I$Y)'PL|%OO9C^Οt1O Oc- ЅTEzDQH_|՝9+R;T]Jfk9eU ~k}("jb *sEc+w'l[3{3yi1O墬U3k`(pHs hl+Ń*p c]i=KjEvgt)-y~+L{`ޓ(`0-G0@=(*|5KT2-^8dl`XNB˧=s.3qn^ ~pN}}ѓ7޺x^;WF;8dim쯃# -:>o|v}l{/:qOΌ~p".8w;>>wę+w>?wN_U˹nL?Z‘16@<ps}z~?:ӿxo>9'.jlv|MR|$oD1ds7pj.I'p9:_/x'!fs)O IsB ^# mFG /2Fc278j*OǧRxl1wRXg)$""R-%H·Ȳ? $%#~F&hOH0XqYI-{3}gĬvHBh$L#iڟ\fQ`D.p!.f3,ь.Ɣ 4BJ)O/y7nf=ь(+BPVvI}'q#p"X村Y3 ]&l~ ҈#p YF0,g 8{ +lZ`ƓڄJckmK3"siX( -azZb @)줭ÿ;Iv9eW:Y0ZPD/rf4MT2SĴ;4f^_Z_࿜Ng}{s/|'bK=:9J.b`4 E9ͱ\}ϾElO_yջSm3G0NQU)Be-!2 #6.#\&/zc8K ]<\07$²U'"?_ٮܞ|tfWO?w~ąO];s9' 1f`mJ2ȪHȶHq!(x [dlw=62|um+%rAJD&ڨfd*G g)+qZJcVtd3U/UZIsL_K^N^J^L^xcL&c3B4&Q*s,TH98dXׄ(HX[ks]RJ 3feE͔dea@ ~EfI<B?FP< )MYzA 2o2Fg$ o: czN.0-C3l` AKJ@*Ynkf5/["ՌČ'3~/i0 _ȡTKs8Dg7FXC79 l4ycY9 (E>AF$8H=1,XfW;FZѫE-|{5a1j:<\Z-Tԛw'$b BP=Y '"$CHj݇rgƨ:F12|b R{p~oNKU,C\Eg:JPpyorkf9÷ |ZN֐:FJaR=͗b4TǖEwhg0鋱J$|vi HlWѸBJcP1\9` Nw:# NT,aYnIh NUk״dU)$ah:glԔ/z~?rYwQ&K bV*RPb]/7Z*bA,W2)nt͕*Zڅ.U%r(*\%;=o " ʖ|-eѮb!h\!ȪYQ _<'岮Lr6u_ ,}<Խ_ݻ?wg?ӟ܉tG.O|{/3 >&_Q,/eohjrkrԅ1wܚ16;>ks]4?+0eHaJ`-/ɟ`lԒΣk&/|uKK˯],"!; '2{WLݟq,SLU$P+o`) 3,h=6tݙcP~N:{:, mXl^)^ɂ M06qeђlœ*"Y?]"1:(~~"qn<~qa2f[LP0$F:ODKu|w3Pb1 MRa*%@5$caU͐O0WcK1{з31"V4`1Fy134BGј3 & kIR_&9L~%pbv}xeLI;A27C  d䇒l~ҔI2f `0׵Ȝ+2³T™y7I[pQq˾;4kO|8} 0cރJ;Y3fT(JIf N0k+r T3c~36FxL>4W8b%ŐH@ wv($z!0e$ޯM9R?]Xh~&tKB\$-l)W2k-"I1Vnf 3z'gQRZȗ7>ȗxFR|( w{'_3P_$E4π1U?1N|qmqo%&c(+?zi]#_>h|(h$~Ke+Ǧ-fa`7ƁS9,E<$)e9̬*ʤK eCPKdt)T-J Z}Ҹ!Ԭ:NxA `o8`#M, u 0VJGŪ *5e.*ZuNبˍbӹB(+(v!FOF5Jͅ R\iBAj+Zuhvul1p^VP֔V,yхt\ـ9Sn{i//\˩/stJd2E^RE/U(iS* ]/'V+uQ /f\<j=g\O7q7}OGåsO._]ko?دlSz'Lr3/Rp" FcWTǘu.co0FacTcucܟuޟuL#"Ŗ\0-F8Wƃ3W31Rv3&or@J⬏pf.&F.Lύ.>JXȎ9r~i)ZP0ЅJ>v@8`& h~(aJ)_0RB-Wt6ED`[7/&3:-5 76~g g =ƨ%0cIOgcPDOT$AӉ`4ű>c0Iċȳ&-<9lJE0+ۼD$_MR+;z|A>qA D faƚQx4-ay1\JA(?.yb6OƓ*j@ s,3c¤!I)\Bʼ-_ϟf&c\Z }1!AO/0C݄=0Q6F40/! ZBZ<džC[x0'ZP3c|M:1Fz/*(B"#`#吤fb & t`{0<1,[%f35W" 1ZXbjV,'1d<;wvo $1:FtȈUT*Z*[2I=D0J}sQ1a~+E-,6ͩ\ӝӜ9R_4vNL|+\T2fI__+JU۝4"]ӅjL,8ɞ\O1 fH\)0E%/rMo(V7ZVBq( ۣ ś.Ϯܹt{mqmo#~!M R1pؕOx^ǀѯݏ.~O޽zwN:lMXg q%)rF'^uKn^#\%0\:9Hl&n삕GD03$g>ˢmX Jdq^VE0bQ[vNQV,S&lzc36ÀLz@uE#]U{lGIp+cz"2]ӳ $wlf1̙ lp*[dz=N72u\]' @7(5lUH:xQA{)cs9(lMlO1ct! q TXΕJZ;d1 c%VՒDPXCS /;Ot 4'a#F<CҀ)9`8B<_@X6s9N#ZA8\>\ɬe7B8 3x^,QR*0q>QD‰? 3`zcpX 7 peaeď1nJ{V"id(|*!cW crqǠDd c)c<S?F֘x3+$ LCČYd<Ō4Vҟ8ݛ4] qx? M OBc-cΝU+-K:^?cher&p)Q,<{w7b۱TP]VƹY"tfv|P\|-3E:U) !ȤZ \o؜3B\1pZ怵^^^x3R1(61K#Hm|6ྷه6<0 v^nfR]Qh(vJsfiv`z7a ;c^glbp%WWR+\c;MoZn$%%fn5!0`S?^ "MOwۺmiiuM.BBo1]:xyj7;o//}[wZ[~w{7M}+?k.rԂH\TҲT*#04'h6U@nlǗ7Eo^r7g+9XluM_6/F.{Eh7n۾r{o\^X|{;d)Ybs4敠BrK,ۇeh$o۽pkK t I*_>\{qa~ư042|dH> 6效~~-[Ym#%%+JO4+4O%,zZ11[%$eT>sCLukJ,8نh^J viSMi\ۤnVoK1n=-dγMJzf6&}AI9ՀjtUf.ڬ YL ĢN1I6|0z's1uXa.Z(VOYл^&X5t8 Xt^P$tzbI8xR]PJ U˵<]Ó**U9eh(/j BRTܤ%lԲ2Z&g*|S|o!GHBTkG"!TbRP#*$0VR=,mrςmaIB]!8J 9hխY;q0~MaJ%A w n?`_UXH#UB5)fKs:~7|Ā1'1ofww0ڒ}P*bXVe7Ԡڠd 62ʘ|t]t=N1F0^oxnnZmۚeQ}tSn/NJodnl>荰4cz4f{tXUa,e'~F>Tc꾰ߋQ~5&*]jvj.x~ ,D2=nǰmݔ5)eYJI.W(ߠssw?ZoW~~t?䒟3%&wev`S$ycDB8S;Xj=X9Az/?Ȕz! ?ae`| %(),)h2w+ +;WvoFm@caHU $ՅMl\[?\Z.,|zm坥>EȠGI_gz e3baE^ލQhΛmYVci*&_cp?&c4M\*0CDuWW;UYlHTԽ{hu1 ڝ(c݂l)-Zr~OJGVJ2J&5o0-h1,%1c|z煠DLYӄ_A`hwFxhi=O^0A C_.Z& &[Wrgu@6]$o 1ß`z?pxGXt/kt&th(D55뒕Й28D:y&U'saE,ԍ R0𪸘a$>|)6&?y6:!h 'r֓Dܭͼuǰ%ᒐ1~ j_+j~AߋЯ! =6zvHśoWǢCǁt6ǎ?R n?-nzNwlț7-8>nbA'0SI̹TPk%ͽ{;ҖPlhv9'Wm׮4{v DO끍"Wb>2Fc8n)BHI5v^Q]ΧXy_E,;;8;w4{Y!y%w.]ץ- ۚеdIP4FT(F,TTNL UH|ݬqpEHݰT-Č;M%!Z [1Tmze֬`bJMJS 3tB%7)Vke^߫+Tu95N1t'J$Rl6esg/UE6\jvw>}GmČQ+ߊDފF0FK"lnUş G|T׬mw(cyW&OnI`e0~p6uoc%*GTon? v:Vj0. G"kG1r ˷_D^C ~x\u$Gꮻ.mw֭;-g}MvjWy%[m, :ިc2v٥#?@0 c8&5M+m%0 xuOg3}!M]ȧ/sZrn wWtiOWRVf`MɰlHZSuP-7ҥ:L7g⮠s pIzqBoGMaJgǧ8*`*`OhjVJ@K m%K{٥䝍nj ,`=TbI2#1g,0ٯ%g`meYa/rACCevR㱺[31 3a2E1ʼo隚Eq ilgXbn1QVҴ^`Ь6 <c`f_ -0|\ g>FNDDW֙0FgDc% |1)cpU带u[u 4: a˶):p*2H,5$& hؐa!|i*i:ل _7Og;T{ 1WykD$+YUNhrTw 5a9ì6g8t7i4<Ѭ3a<𤆘 gMrP! ~R1T%v%'p[5ѪF qbh0UJ̤XeRì4) eV;bjdDFfesŒ21ژ"lj8d655o(N# d zyYB;Xä69"c#@FbƩ7yƘqe |7݇?+{g} W'&Ǔ2[>azG7c_"5޷ ׿ԕup痯™!i '?+0CK<>_05FKʻaojCm* .1Vtz$Ч͞t |k , tYFՈ0)ck&kH514+hy'`auӧ./ r\ep3# GF!cqу.i`TGit{``$K.ٿD~9Q78GGщ?~@Ktϐz~{#y=ڃ`G^%cxgcݾֺռZkoN"WɦguqT䖁15"[.kؚa AjQqWWEfoaj MW^-_kԍzCDQe]\mC4&,I K7ET!uA1[rH~2< ++[(1P]3txD oIē6LGHYZ*ԊuZhW̒-hEa%`,vGE~2 -7Lx&Lb%$bZj_2zRJdi51!*<c0 !c̻2X 0v5s 0㐒4e$oe9E)ٺ^Dpj24]ԗ;GFwN c`/+qDnB?=NǹVv"l>ԪB[!]'+ct^uc%))2Jz`)ʛNrϔfЌ(-˖$)hh1%+Ȗ ++t+y Y_yӦF >a{$+A1YŤURk(;0iLG0p Mc߃?N}Bז/ZXY@88{] L?5Q.\M`d$acT< v.΄v'X洅jհȰ*#}2h"ybF)3HOLJG쎰k6GκzI+-0L`\LJ[0FG.G ϿYNckZs$f@G} V@<ֶzn4/ Vp8 Wa`ʼn f|z3_|sp aa+0ö ˎUdq}&~~k7L\iFno&Ӿ˼`tN;;"?۝ ꛯNƪo``Cz-9ڇnL cz~A- cPꊗ_}r 䵳%?:gU." I3n`5c,X@rG1rF"*Kg#gVpdGJp!fK8(Q҇q]/~`L665=șeWVD~r[0ʙr=VU^ى3g޼ųg">K^ߴ{-^Oޣ?j`a1 _t6 sK/K=ފK~'g~dp>3|ZV6_,,[Zj rm=].5SNY|ںQ`mFnb.Snn{@o=y||Ur4a Łؒ`%=Fo*LEbDJ F1a\̏r%Tũc!d q֐%r^$LdIl.Vʼ]lJ^HP9u_t6O 'VᅉDi#W׳u-CkFkYo% tI3p{L4y:H-GjKsv Qmo.8<ݜOVƘa ;a I&!l0ƶFܲR]n1vۼ-bf3\NGc&4&S|hL,9 ׷)OY>'mrFU5.V04}C6mSOf޲iawvo:>tN^ m  v^|mb1,`ha]ew6 -\Hl:2FF' Rdf^=ʌ7$h2T]X88 YW(LQ]:&,U r X{C $D&)$a:I; L|ƸrJ8 bZ}o|c4+U3z/wtz(DgIh>\#3tbt3q:7|MJr<|2F`0AJ-Rp5sJ=X{=22]T7: }Ę0D@&F.&`3׉7#=kaOCm1THO|3 2a/> A{39{H*vtgJ{tHn>DA:#&#3 Ƶ`L2VCGx lr_G!qwdq7 %g$ZFu-.m$򽅕b/UV~wߨvL lJ74^oA?VX51+=9ԕa_S+ ^ANkvIhWvUnӓBU,Tetg z<"<ifP2f SgwjGUInR,+D}1p sDZs(+1H^ +J^=.M1[5@ w HWA꼤V$Pv$M :h=j1>feMbo6Xj[Bs0 L`>4͸aڮn!f0Jv˲6_:C7b?4Rn=gйZgf-nazjHj34H5RI2IM| A`ԑ‘P ܂cHĘM6f.fAN!!= rSЀIMk:n#B=bЃq^Lf3z^\ Pafv# B *E=h ߼CXa՜!><ۇ*n%ɂ)cT?c lb/ F"ݐY+H|Ik(KB|Osűks-S2 Qx1>] ƨz_E}:ߔ (KQt_%0QƘba Q0Gŗg~7sb0xHؽK;;Q?7;7{@CO6'(~'H™h馯+뾲^fUeUhi/:|{MWK;\3ѱpu^m{ӟLZiQ 떮qvM\I/ed'@eVOo'B`dHp M}9^5ФS'y0aB0Лc 䀂N1Hm@ϫHFcIKTct`fЗf2םq%2jSe{jf9AMF(Ci 70w'JSc:0;#(YhdžH=LFn4ڈX |̀sAOP5GW>ڥu+`@S Qĵpr{fw9ZmFu~54k$C`Ԗ1&s7J)x"/{2IZ w$) oE[%IV { ȴ)s`!'j4F*AHpJ_ED>q@䆠f>1HS@$jA0 b{Zu=y~W_n1Z;NuNPj۶9QKq"Ǿ;̮ ˯Kđae4 .c|G @mӹ eI@B gpRTƨij2K@2hD-Lܱs K&ڗUs*E{LjvQjNg XU0߯:/ԼT| S`b?S dʈ 1yAѭ;~%N*JҹrRdg/j&өldbQ}GiW;vS9F{H7}p'Pc F6-).}%:bXd xJRxH0zJb-8 M]hͺ-~H䐏5)vX[f8Mm#ڑQfb|Frk9D@;H;6$ K5\X0KAflh܌0apFI;iU\&ƗІߢh(sħF 1x ٽ^ⰹ{mjm:Lfܞ=5 dU[裣p:CnOv5FRcq CA1TeX*2#ͫipiAJ<,N6íAnͰsߊhЙ5,܈ȢMݯ7h('0'ԫ%Wm̠m(P)h ;™iLHMl 9\;p"-Mis% ((B@`/5S(v" אX?n޾;5|Q1@ccXf̨oih3tb߹w8}xKc'OvPL)z2}GEۤk|0x;Z.pcc[,55wn8 H I S\fdǒQp2Of$aH2K$r*GbWjFiƌ߶eYyC /j[>zͲf&3y/zj1cj 1<|%xܾ7e;۷ d@;Fde=bn{=X~U{`MTL,w{=۹r-}-;}}^Md|/ETC$4F_jԄZ"FCk)\Ãx F+Qc tXb( ͛_F2ߙ)m.|zӴe7F +̂ !H\'FDT 'J @ߩTtPIeCZn>$24E#E&f*8 5v(xYFIsxi ؽ{ ٚl#v{qXsS44&hӠtaxKR &.K@ќW'yD3p%]玵N^Ln^cȔFxo,{D-pɯ^ m?~P:DPqL@ȣ);ܹe0\chjkk͚#Bt{$ZW-KRsǦ>#*HlOHR a$搬HʟV>Qtmj۲Sj,n `r[-^?x+Fe_,Vk}n2ܹuM,9ܷ.$w:+M[6.+zP=[& ovoxs-wVKqsmU :e}gJtS -P|o%NcH1|So6b1Pg1ʷ1U%W%$ed cR`p[]L.Ԕe!Ql! IYtÅ "Q-q1Cez2۽^b 9Nۭds;.1ؖGh,3pqjB2e(RFN_x" 7 6UϩŖ ;ptMuK;9DXSs(9DLtNrI6alJJ2ąH bz[:V5 &8s$ahߣZH":!)xS0e30 )@a !@ۤIO/ S!ҖcX,k FWL#Z. 2#h*V}ՇyVIlm'eqp' ):cs+8l \;=IEΈp3V%mɯ;e# rtOv0uX| 8%cR?saF/I$=ΐ.@Vq{;+w( Z3Vj)^p܂jJ*MMI[ *{@jm5q21B(+7߼>& u+>d_Y~Oc|~mX5:{;Ԝ؉)EdnO講3aw]9G- Ԑ2՞ 4t14'V^NXi4(p]F&A)QiT@ym9RK@`Sy78 6cD=C22qA8(4LxB* &1 J<%(0 C:pLa"z 1%naHry2çs%IR`8 F2cG ƜAH҆6KV0\Y3Eǝk""QH#TN5{W 3⬝O O CXJǞ`Tz2yNYM1K<' P!b ӹ6ô.\Z :D pSiG ѕj1 + ಮB15#FܡqP'ܦqsc荂k Jټ~+S^Uq[Uq oy6{ AS`ftZ(\'|g \hg0. Zxp hpE\dA A6 ؂Vm.bP;E y4Z 2crBt>0 D"%:z\Wߍ(2EJd\|jWLGBbW%{`2unߔ|g4qgsh":0ĕ`?HP ^NDL.SȎ! N`uiS5JÀU7`DOJ@f i|f%E{B`\#P;T!FB0%xPhȜ{bT~U-.Dj i0MkOj(P5]hb (\[ܔ\T8E M ~ G J@`l>;QG0 J/oP '?VŸ>"tH#!"!z'A. 98r=p;P넲j0Iv!aKw]@J}{(΄.9Q1n[00$G@`I`YG7w:PiDYMiĢX _2KB*Eb11&HguG(;_TaJҒCfrޠ*:|:r#)8 TD{F=fCprs d3 bk9Db deQHF:Q5Ɠ)Z-PAû ǏIqH < [1bf2<$i6}p; (I=wJ#L4|fT A"Qp)*ѹ("W#^HGm)p"r\$+ 89l_s1SVdU׆TT!-`c[o^g 5FE!dށ"RyHIk.D*E- ]|@ɱi"}ŹSr%om=&i¿B D-xĥ8DŽ;MB:R8M)zP[<&ţtP|xLN;x9oKD,EQ.!@i8C8gJ%cy"O4 N(iBkU*o߄|%Lfr$C)|!.$nD&kJc48)G@sy` \1ЃV9txN@_0Ĭs>5Oh@SbJL[9}A<h@D>WN*/FcWN/EH !d*,*{ j?C=x^71@ 04.a,T&2׈d90Ao~>HkIم (WDr0~|~ pPj fZ) :*4v]`.6C/&s0 I0@kNc 4F̠QfF(4J4^f)vF|2^J+W$3:Q4Pc9A9[#gRHi>B˨Λ]Ll"2qbZ(GccK,IIX h;Ŧڽ* 1ӈcބ0yX9>[6D(86/N%`Ra@*%Ik paP-%4=̹u#;p18I]T}@d+ͥSLLPȜFBH ^U{Ir- w)cd>Q4K`97#&Ձj<D&Aad =+Dn 27 b\4,H]C)Z)Em^x -M7p0&Htsx%~)+5LzbY%.BqRKGѲ&j.y@ K([;EFo,\֌J?,w+Cǥ#|S5d-1(dM惽nVn+[ug=h$ *kι6&Po(닰QZ|z9 /4ĆSl@ѢҤ_8GKѬ\9ʍ4t9n5,#YAӽPuc9-BLCg@0HCw`T2ETDPE&TUVe{>BC9PẀ cuz (<0ˊ0ؠd44Fe$2Md p^.yN47].5jf8$$UI2l% ihH'n iukR@ k#|oIf+PUP*)D"6O:odIAQHX J3T~PcqCfe25 DSkL611}֓q)G3f?U c3>ss͜;}[f ,sgMV9TKϘ5s:|iXXbD 7^]fzgٳExV.A{+=a~a>K<٠΋*6obbbbbbbR&,rc0O 㗷$N@=ʎT 1 zeWS#&&&&&&&&`aƬ>B*7zÏ}%g$1ytv4HLJ˳YPtgK>ŃTyأ-ڴزr2)-,3Vwq1+ʸRz;n  gc҈Lc㿺`,"GHeF}, dös*PyO<'忇W[>{ 4 jm㫗-kصm*`p@⯎/پ@$ -+`cv2#y5ŧ+ wttYn]+vkW|a_5}~&Y /ihm=qMv ?߰aW͏-YRfϞ]ްҕ*wR]~}ƳWM]Ɠwح[j#GNzu5?w/[mo?WO=mRǿv'/ܲcV~~y⭽6w/=''_uqog9:~27.۶и7HeexƓsW1[}+]uu;-[Ћy!,O>====LrHkyɦGDp1i E L`<hx$_1Bo_zKM4K/`cuj2*[l4-YfP OW=qjU/w|UW~7|糿K,ٳgbX+t}Qٵ=>7w{ߛ}555u^} K˗/߶mkݱk{o޽{}i*,r.[r:=vX ~mVo[Xx1[lٲ۷Wr7铺}'/wfAwsjky@X/ݷ}?~/ݽ˚?usjkr%W7:t_mmǏwwU`N~GpW;S?~w?u—UYZzccˎƫP>7kkk>\PuMw4?cm͇V|m|͕o|`xO+/y#]^lߎpƆw}wUb)LT㺺Hl6f1! 2 * %$L`1nKS.y/.6~9:<:2viAOɌ?V`7h\pz/N|}4ƬYXMR`:tݿо,i6:;[`$ks ai/.W5{KԩSt,hZ=Y_M⡺yMnago.~_ca+Vر '-\ysOv51<2ƔK:_Ei/q߾fGo[< 6޽qx^|Evu]p!kYR|Mwm{?͟~|Wͤڟ3^cjm۬vO?o}O~??'5W_}5~M]l߾g]L>t@Ӯ]M۶5m;߼_?}gXm;y@U 04'10@P!@`@@I%q{,Y,[.[eUejn lǩ0̷=}^ソw Ң=W9K9!۰Z_|X!/_s$~qX;[E:sɩ8eTN9SQéb]ry*XNͨh."o<[yWH%bQE?{)sϑT0 9 䶹yW\"tZ WVֱj]V-')Rpt*9> ߧS~L?8fBB]D2 LǃN`[͸+mNqgBc8<|/ ;_|)'sTVVj, ))I'wuNO~!G:c/8݂Vdn2s굌KSRa*.ܱc[Rý 6]?Is)rwҏ]?s~A|X_EEE|#Gg/Ν˻ϙAx;=mz֝=s!5''oqsO%xE rܿEvoCvǕ[_}w&fZ_ =CP+)AA#Kr5h^_V?x0丸}7yqc8cw^[oA83kEnx18|g'J,•J y#;k!]b)JYτ'lLW,BT I`{|B)~))%̹ ;wl8~ƍ)))nԧ Jl|Ա }rɾ yo`D~.fӱ__K$g'G5 A0 ** l%rLѮq`_;z髒-xa_VA^|r᜜ӏ' F7A`DP_ N J%Lwk"prX7.;?w}ۂf GBP`}[.ީ L0u_tixZw]~k"ٳg8lbF1(Вm'}CEOW w%NvϞ[ОS$?%Oݞm;v8}Bڵk֭[lo߾HҡC4p7p;=vGz`bz^~#G<乴O3fSzFFZzsrt7vng;w>?_|_ qԩ{~<7x*۝;I?y#1[CS{c oj^ؼ>cCgg#?uq噧…OOC#f?qtɓ'NdqgϬؚ\7mڳ~53[ܕ`gFz<-BJbŽ!/yxȟTb i?.Q/‹_g+m" ox1dsW6~啝;wBhef O>q>#?<~W#/|@y^ys\`-ɆW^R'<{{ǓwO;?)5C o޼_oڴe1Δ񙞞57i* rBT*f|bVv Gz??MяQnN;87+wu՟e=mL sT']I5"dYٍ* q cX,E_l'{e(ՉII_|o,Y0|z|*EG^,zM+F"#!6|el؊K.]nak<\hq䚥Qk-_bl>k#VpˢVF+FZ΁3"E/K X4jUK"Hp+yol _8mYШ5K.1KVviȘeQPΚ:^+/Ae+CV}wW"k"c"W\baK$7` B-_y.[$:5WGGZ$4rᢈ'_D؂<'B/^lYXDXdtx嫃9e, $>[%Q.zdIK~,zAE+iWÇ9S[ 2 -hk-ӖD\bqőы"YDŲB:|%e]%cF.},"؇b˂u(ИGBcC"s͢`LF#1 U"ooh`Ś嫣VFF. [,4 ]D- X<&rVFn6 Җ .  лX83P@, t:ːʮ[|赋"c;/XdQ@xer[l;ہքFC" %YWAjlnȘ[|ݒukF"#.8$mI wEEEt:VP(`rqcCI?1v;W|{5/}#B~1힘vO?]tըʿG7DYhr?2v=KUN744400лMK N/C: tz'^d;tnGoxnxo&nNL!L";1rOƦFƦ7oIg`7op4~#>6ᜱ 7/o1̔.\=p!˛"!uDp Ĵo|M=l@VcPo ^݇\N9cx] gt%q8at;cQgvxMvv1;9'lG'qg#neLNa4 jmNvx|#1\#ФВ8}P3lukn5d\v1;M !|"TDFBz,5&46x,.c7 lޛϔ=sMiGԎ)&=6`P& s42auO=kkHA&q{xN]6G|Mg*U U"} zgrNNt@LƧldt1:eM|7Ho '̀k"yd @ :i4lHљnkL eN0>uA t @S3e4f MV|0lI|H滹d^G>`ocLPcݼQ&ĝ|{(+j*G&=.^LZ`s~آky(9Cf5Ij,iPa+8jCS+5tZM~@i ؄6р(~rt:HRGȆX*x&,׀ۆ+ڴmBܡ "]Lߢ0z-B]5vy]:np\کAk`uFрU:k\awۣF](=X(m^KĖa`*&uMh`Jr+Ѯ%B7ڥ|xS;*Ռ|B^WiXBK`d<} 66KMr+.pJncnV$ZOIt$8vPQ`kERbsd4l0[ f@륺:-vimU L8zEk)l.\.b#QZs.$qL>YF@آQ4$gYTZAub*ygO\={J+Wӯ]h%&GL*iRMTǔXR#C's^,S^HfV],m<G\ )T2yYСM,Q}A_zah܁v\x9w!t&0!Ӎ#ǥnNGe3Hj2`ܑj`3f7  1r 5 H[ 1D)FdN[>Q {nKcƱ>xydRy;3̞`Fܾ{tF2Is Ɋ@t5DW ]C |0J'^zUnjz^WN4ӈZ*&@I@L^}(Fc,ZԌfp8%J0EDh/e21NLb io@0S61 >8F{Š?ڄtߵowqU B ⭒G_S<s5^8j ؅(Wq5c`Uww; Uf'Kl$ 0y*F(Z`jDȍ3*K磲JT,T}F~׭oҵw ;^PilCNխs}F_q4蛥[k]ЕD*;ekD:@G Tp S:. `+׍v°IA@)]^٬7vZfX׳Ibl4q,v Fxաs,.cTP8URKe5c A1Z!NBhRPj!H Q'#v!6Iul0H`֦j2%d~6 9 UPL*2K)|\ PRD69 6Ht`m}MڎZB E ]/'g` _?p"-|ZNz:*7sN)/kV !d!1JM >o/yS|M4(b*>+*@R9P?F 1RYMM( T)8PJ\=YS\a)2Tj[%ؔXݘ@OnD^ ҺnL$o(%ْ^o9˰|M4ƙ676jyƫ27_oipYŪLZ~`1DH@[1l4^5F3Jk qQWHNbs/B"_bfѮ X=$"ɦHS$ȒdQYCQEE5RKlVCd4&s$JóZrәCɴ$J'ZP%KKRJA&AKD{+Z!ԡRLNR0Y TMvCieAɫ*U([߅eb l4^`t:b;o+m4[.Lc@0C' }ɤK\Y] Е!@ǸiW3qlaw1g35C:<6ciF1!v19@# h םq zF3LC2gw.p4cdF3ݦ4Nǘg43>K/XŢaГH0+ ;ApR*ܔ ,^2gqq2NH8 g" $X#VjXDw#ѩ)@+Fa.]*..4U(קVa40=.G)w9d<8Fp Ϭ`Ǧ,Sq-9L1k.'(~N ma_%}t&"xZ{{/}lYfhԚ^aA] dcݤ!*8Xih6cVPcW9;m^'252;MjdXϖdzȧYn]imA|1j{Ҁl~O/ zG8K;ңw`0&hbGrn^ek[FNoZFԦ0Aɠ/CmBdZChU%X@CtkW'%4*Hm5*f1Xb1n!3Ve܁r*ȯfW4]Ų/22KiД\ K@)8 Ck״jy=l^շ5H&d2QɩIi%^KH*K!c.3ɹ u6A$QS%q 8EY^UD_'T6A+|]RWd/w\}AOon"0c0a·1Jꔹ̮+4qBTTsR-ĶTA.CZ*kǵ$E`D[9K<|d܃3WR}=O9GX|Lśeۯvt%V\ b8*zc N-%Q 8 ),ePPQгP5XvʫdImJ*_Ð@3#:a1b,,%HkDjj~#'wD( [lnS!ǰaڭsN>IbO 4HϖvYǠIDՒd2$)$* |٪ދ$b%Jw.:MzԑAl .xIYP58UZ@XHbky͒dIeNQ *unxzW{\Ul"{lӸtroS ]ު%&:F0k0RYܪz\Ss Y"Jv 5EW5QFC5b#8 q ;\2ETi>IKfW ,7Kh'r|4CeuV6j@8Xy)QY;JH$&x0#q3+ڲ |vWGET+#1R+wEb% C9WhKX] Ya!F1N1F 2o9e1f)[ d1Jj362Yé5B骾SU] ՊT Uô;k$&l :Ƭc^q/a!zicHo=:31-Sj1`h'hsLc1APr '&yŝq_<1ϭhFw@3f2y6UYj0ØB=-b B'B [ g==A`GF0)0c tmYPY .@Zc5&RLllc q8L>1 r>=O&{xER9W4٦>3)tĮ"8SUı Iu|X-^85/nhU'ycc %,6i+T3[kS%9oooxn?;'gY(ХY>Y`cl;!,TyB+kA3;% FăÂÂQhpB2<#ck1j/v%Hڎ148>5%oq,[?2dX;è:AP3 8)!W["*Љ˒N=잱^Ιo,q9 pMqe 1Uq:\4řcvBFawXB1 |9i1!r>l;cG2tCVͥ!]"sED  ^u}y^sZCiC clo;Ʀi|i5N+`8AD xT(tf0PF3GFf ǠSK+04c#P֌Oʘc彻 zmdFQTW/_o __k _]hO& kC}YmZeZyZa:s= ߹iÓYeWg>_̙3L(bI$V 7QBw &3I6K2>1?\G ]V?,ߏ5;<7}no$gw{o\rET1I-L&7ស|>~֘59CrސCgq-iuTF)OH%k wI=:C̊;J.Kx_TlMD ^a(K Z $mxQ\X<@-` 앬kffq|)W d[EDkLnzq+ PUX$ HB eO*r-W$pHQ4*q P<NٓZvX]tFk(R*!(0G%LKq- *kAe Z=%$I~@pH,hWZ] [PITtVI喨T*hgc[cSF{sg.Y^0n0ʕ2b7v g9!6 ~@:'NwSR9Fq`Pӎ NyDx*2"@y˔ѥ&TaY43 ޑFqUpZ]0%)Fލ#LZy BgS#;m遲:zk}zET@gMSHQ*v 2G82R[0F*/OByrbJ>2A Mґ)Ȍll^53̈ r'cq$ÚeSsؤ"8 g$q(qmɲb [?3lSR/K"3hJF56c-󷕩^q2?tȢ//Z{7XeDh7*ķ$%$TU1-@,1=K;J  9S2笂^P{xƐȖ9rr Ε6@3̻[& Au,+^.p9+|_CS:T* 8T-bkĆ!c7G?0{l#:f3Ag:M*h6:#ۤV:*?q@#Qfe0U ΘF3:_q/d2/";;Nu}yL];S\ٛHEg^-)-a2gSggcWFvvtt{t{.wmu9kvĉY@lv:]b1:e%8F& aX ;Ǽp*Rq{=֧7~[`bo8f"A|[cÚ9F3Py쓰$D _,ycf'4syK;"Yd$ n[LzR!YSz^VǤa#͸ͱ p\io3r׼G֔WE|F,{eTdnők@˦؎~cR|cTd/RA.+5cjBgk/,9\W1k\JO\3 7h0[؞8 bp 8F2>bWKgq}:1 K}5$pGQ'5 )=/s!btf4&I;KC7$wB6qv@hZlҭN6,3WBm\JgV[QH.+Iu}2RQYW< ԕjL'Nv!X3"hôs%I>}iӁ'OF/_:.b O1'KO/j X_t_:$'bOD.\8pssss*Ap??~ҥI7:%\={,G`}aa߇Kt-Nv Z0 ̨U.nBۯ_n~$rp_#qd%đc4dXeg:v ޢXU2Zs%nnß] CWC /!H4b5`0ֳM6:9inq3_,4@*K;(tP\WVfr f-"[w]F0rA,Jk>A8R0i5Bp^]13ojF3cT֘ǴЖb,}KqU[a*|IԉBHգdTL)oOI1!,Jp̉LSBH;$Q"7媛*-0dMX]s(QY+/qnp Y%`BZﰊP:n)-וJMZsCkm V׌#v&D oY歂cpDD"ךc2s&˔X3|G^,]{޺@E+&'\%cّN/ف @04 ks,ǖ;pF3SռLÞbBmp4ŎYmF`6 y9Ry8]$\ehKbhw԰9FqcJFϩ РQzp_גּic~LReI; tc{REXSI2WI᭢: >Y ̬>1NkS;Ϊ} ?[Bk rwI*}@G$ЄPheasܴEHFձ!EdHSE&1Y  p>l2C3:eQ> ;Nd Ni0Ad6W;FXo^k,Pv#d fÙXb[zo uS*j3uWޑ4Y ҌV#R~c0c&gy}}<}<}<~xx;w<)v㟂T扒2JL×YLlܙB7Qt5G=+ *C[*63"Qej B~߽FQZ4#%Ոֻ9e`a+]Cde#YցT]]0!(e  @B`Di-V\P~\T8ʶl$ʛfޅPqӟ_dGnAQz*TVړؖ[b{p JMhJ :?X:ZR:aKMN#dTN&tF*(hhDpӭr5>5rNI}TmFuQ9fvNZ= 4 bKRwpX lH3X12L輣:CF=a8B,*ΧO FE-S"J<ٔFjaphJ5 OMeMΠ5d:F6-꼭@~S<p   8qO?2@/E6zW􄍁b0_b^zuIv8\ _d#A`Z+&绺༆‡4@F P!5R׋ bcKQщ{) Ѭmhy;[F R = aW&Cf9@r(v2/H-]0ffk*8 "Y^sڊ+Iu.҂KFwQ(,lnF3b Kf T[Ts38y wAK" ](Q׃f@'"kBKL`a9(1%f&- e8J<}2K@ohK -q9 7}e3Fߌ7cX# s&, !ezd "s|{kK-ys|5 ⟶gyGM%xNAcUUA, "|[.IHTQ,I]8cqQhFkH0eM3Ԑ*969K * ڎf@?(ud2mi%)4'8C/#|q)R"GFLA/:& ,|{eHs،EաDpV׆X(ǔ[8Y8JsM) T QXQcuY0&ئ$ג}OR`` ,fK(*⩡;Х.y5˳y ʊk9rOGV%8;i(}2O9<Ӗ8Ьw貸qR% Cd]5ucH<?Owl=6 &TO7aL#@'돢Z%P{J=R*Z^$ _0 @l4:! - 1$, <7W3L+=e_?e_&}JSv{pI'>I|sI/^z<= R@q(Ox| sOh]gwIf78fncm63oo~wfOZ %ML81ٷ: >fJp8nzsqWhUkb JOMKQA_H? {vOE02Kr0*\u-" Y˶m>+(Աc`-p/uQݜ$9#1ClFTx땙}}lqdcgF=-;c#m@uil0^r_:/4mkw- Q?Xֽ9x+H3uSfV[R{K*Y*(Z(\EmpiH0@K*dFH! ea$!la),1#.#@8 -I᯽@gDz+/ -ζXc;l2Υ|gJHg8KwRr ‰$fi3[mK{lg;2ťR|g,Y)|Fp/1p_oL.g`C.Ac @YD,tUDP28f}OMAc9 mxEZAǁo( (,H4kh*`P F1M@3 ^}-g 8Hڏ0te CtCL1?',I!m&X:n$Z6-V$Z& R+Q Y$ZE| &$ ÈDHƀ:,n)I7i0y.eqmQ9Ԟ!c#p^s{E%ۣ8G})݆݁C-v;M?ۃ2T@^>yhyh.]R=[S?%:p3{1~~ l8Ʒ7xW^e,Ѝc}؇.<1N:uʕ)P(L&t~==|Ӄv ,?Wpw1ζ:bG:hMe>l;|+V ##VbF2DGPzB3pe㼢DsIRhzc"=h1+(-#c1hEfhvO8*X 1aDx?\0x"-PPX@6p| ?uցG:>P(nv7Qn:ͣ]uy*%d4!\7u_ӨJ p(HK'Z^2od 4Bӹ`[?J͎??tT;on%qbS\01ƛd+cz14a*XW-c1thf4#MTM۽s4;03%:-Pk+ tEIGJ+2JH 7uM8܂Y"7zt+?˼ON'L7\ cL8Π i %] BY 3M| %Oe'?-CWc8eia)o(C8BN0:4<$TƏEPE 0( ԨjD9"-R]T^(aĨf`:'Z`d!m? *Y &CR|@Hp 1΀754|=zE]p<hu!E.JN!@"R~F*nb&Y-8C ICI֩yOyO{|Uౚ/|i#CIIFiyt-θ/Z4iԆSL?G*+t92)fPA3F3f<&tzDѝ'?*]eͭZ55֮ӰfN9syd랑ٲn2Zς I7KY fկUjօ+Wήxn/?U6lPXXgϞC[|G['([*|41p1 3ڏ}vRpr_W4D**ZdMI!Oم&Y$$j2t0%2 2w. 6jƀ)c7b Ȑ 0 *ؼ1fO(.4 /i0#6waÌWHR2hyP~ͰnmWzJd Ï@CP$ rWF_!ixk՞8R8*erQ]ț(.4(FYwfθ'u_3E y32PCFWr*3SDB)oWR4|n n D %[WHٕS!dQ\0HhңG1f cҀ{(G ~0BGO1?#fX؛OC >Kq1} +4A6ftӌ1}ܯ_yiͫjjز`em+%V W W(PX޺c:Z6eP++\5Rƕ@ol>V<}/ccѢEׯ߹sÇ}]ڏQWW yOCֆݛ7^,.,hM7jl_oܿ@кorƖ2W6ll޽iz=v)^Y8+nI\L mưk`/U:cV{De(;" kDfEc`ߞp3BG#x_. fk|jJwU)wV@r+%!cµR1%4`TjC %$oD.O :_%`pF0BU; B\'[2L'00yHHChR56HIP):TD%"dL0A3P\֚&A Y ct)|2۟p{/KNW(; TqQyY::EM+qU~@W|QmGo@5Wm>}&׶Y_XjcxYazaJݦdji{VB= f(>؃ k2?qb݂o%Mv[! Y\]ήH s vG>ﱳe(DZՁMo͞x;ft Θ#UvF[:1pF"TJ/47p9jqe o)o WUz3v@eR[[[X P|!` ZTД*-UY(krU]8E3~컠0t }t5dFL.\4U#wc!!0d+l%B'D1U'0!,9!̪f״ Q5+ jXc4'O܌V =UoHJ\SmsuctZ`|j@_μW}o}Ϙ9νwܼOk &_0j>z7!͝8vνcgO3;W3wr۞icoZy7γ8v9c8?u7KoQe ߼lYs'cD}R4ˌ4`(6|fCtE&W[OJP)>eOe+-VkaF2:VD4ûrw6 يK\[2[ieT+, #ta7W\QAX-Z:p4$“L1@5nC]\W7y vVt ,8Q"IS2g>"wYf烧<'3dQW2ѠL?AI8el MỨՅRTgU2 ṊA,t@Bs e CA{cMҹ"k BW6ʕ] `u5%Z׮d.0 Г1? + A:q/\H/- c0KW7V)oBPNLƸdĈإKz{{h(ooFJ %%%}+2I1K'y6P tnH^l_緋Ρf,1-%j xH eApjPBFU#T,2 NfzlKUH.DE)L&7 W\"T#P٠CaȑCJlAl 7SW!p_a$j_ fA(nEc!rP`vJs\ )1|"e G~~#UuTڏwv\6$/^ LJ} }B BafP!ehb4H.!lB % #ve js1VTnaJseZ2j6fs1]2_:B@VԗM-P;)( a2< K6chJ6{7d %hE4-_x6 2z[+?{^_.S@a "aCe 80րaHplI/~eDJq\&4vZQ4=fưo!3*z,򦪝!sWX&ORmXn +sI0Q-E +l!s ԵreafZWV SD JB'(\" ' Ӏw;A-LA ݎU;>G~ ߴ PF@ ؎ (L{lJP1  CHh`)Hre`.|(^ +NIH҂  )n6@ LZ:+b:mIH;V`y10#HH ČvHFcd G3CHۼt.X͊>T0S) i IM`'R!*KtBi;H~<4 T=#ST؇!ns&71 =L)hx@2b!~(=Z8qd${Le)#*ʬQ5*D`@ L z_apk^pSFfk`;#Ũ BM2(aH ii5855EJUVU|DY~LӠb%R5%8V 8p؏IԖAM9EGI<"x5nAQC Ax#=tIόP8594p$!$ 0ųAR\}FLcFd~߰" > 4m 3 ŒA h0f@)(b Jȧ!3 vJ3Ƙa\nIM~CT ިA!lS~r2w+ZPp;ug@TKjG5ٻuށF Q;"^6OVݩ20w%K ,IVAhaC靀.L& >0c@hWB8N>8$S =IȚ)c#Z,cҸ.jhQs* f$`1Ҹ R4$ =E(7RF `gfPkd)J3;I5AqeHI:fD2T$66cPc c(،fCo.7coG1 +i [@̀+C `U@&P 4jR w#vfPV qip #ukla=uDth3 ra)gL.Ԋ$0KQĔ@l3@ R, afreCV]# (8q̔N#7]00cH1hvWƨ!,/fwWg*fs`ƀŌa#Ō+FҠH֤P`k T ؃N%7C2% *5[-=/43Xɟ31#CN0C`1Ȃ1h\ac &Bfȱ cqp~QQ I@aפ.p@>jAsQVRD?'Ju@VZI(ni8#Ѧ<!6t0Xc>{0~g C~ҢN{8qHEΘ!9PG Bh@IPE;E_0`4 ?F63{/HĤ:@RY=QaFِH#G`1#;c*jĄ: ]']`13F7Da#O#c 6Aodc1HXC<i0fI 4fhwכ43kOUc :b?4y3lL̈1#Peqed s*fƈ|O:wթ0G$53p (mZJUwL=V;#Qժ:4(~>]#Nfm# LzS$6ё((7jAyT, ,U2ԂE{$0BNU0} Ռ”̻邟FMIɠ\0+ZDY0g0FWEԞ>c Q6dW`a02Ff 5b3ʸz#&Ìag+M4d}+i0|c0 Hueh`:4hGqEf`V0#&CWa 1"&,oFҕfa51Ihb ag -z|m~l>TXIۣcu1htJ6c>2JN wvE>('| ;a7l/G7fa)-`tF5(X1#frEю :|Q'zM",9iUĘ+s#yqO;@r($Ik=RJk`ҵw+jDW7!&Z5(eɨA ;8|0,՛# DdTzƓCԕvqj?xRƐzd+Uxh72d9 |7 tarƁ {pZq(rbIX?Œ=W1Z$V $h=oxǸ}XosۛⅫ6-Zi1Xͅ6.5[_uᚭVmr[-+xtq?5Gm38㌳+m1fc\J13^"oW y938J[2Vbfc\ўK6Xwq12ogOĉU cKcUXWE1i42Ff(`qNZǫV[Yy=7|}qUcOarqڒ.ᒡ(f W?cp;uu.c!\ gqvc\-1piKj z5j#*л^wŋ#6^{.bK}ev/A@ہOϫ-wT/9[wYʿ /g]?0/1~vʁ)60^.81[fC.1D1F1<}4fx8x~_ȩKnב.~x[OROV\gqv a1J%q?x/Loupb *ۯ܏q٢՛ ºccvۙ1|1?F/ˏC4&dh P"dn^j~Vtvq66dhbǭ??6N5~?IwMIHtj ot qt?uhVo!ƒ>ѬOw5ɿ}S}|s]疯\vݦm)عmGK.:TzįAr>=xWw/9dÌᣌf  #fkbxTEg]y2ct#o}񮕢[xUi1O {s[t MJ~"!AƸse ;|'Ǐ/--H$j4v;(^uNרO\q .M>P-~O< ^"EYd>ge6[/{9?nЕfW'O~I38?A1 o~6yoͿle;1N$$ vA&r/AMjv WP<%: 1e؏!(Vr]W5cD}02Ԯƀ=z.)5 $]EkFM.륐,|d,g ]V̗T.t|oy$[Cv?g <#}q/\E?Y_SL}. >}K] 7\r}iͭR_f#GD@x-@`Kc F;cx3JkϾw}mgѡ,ܹ`GѦ^ܴ} ϭYhɪsR8~IbKbj)!X5vlC~D!/qRr8<>80c) Z`8gW]xztXD/ZUM\$p=`'\<޳G;Rϻ92F& .$DeϹL9%+æDWCS =={)I97cc8-Z鋊p^<pxp0'>Y .XxV-v`gmtgapK7+q1 <9,cŊ)~$l !!dvzcWy%_/% | I2I $80@ƈD"FW1`t{>O7[ָЅK]hd=ohx6CՎQe0\܏Y4vs{)qvM/1cؗ[~cfꓯ?k:T.W;E}q["L$CoHy$Z0."\18\pZL2Fʯ<_zk8a i{pk7􌌱!0cdW2d8zNg_נ ^4uX:0j `fh-ТQ:.#c6`5p^R[&wţq肠24(<@T@ FlSѿDCPR3ꅀ.%M nmJ@+u&n3ҡs?D;?ˣTT9Z7nԠCR{x"aO$Dm{~Z;d;SꅠuNEɬ ZÉ;j[:c3F]{jܶ$/]mɡWüa7>Y|g}x̣,mƱۦcN/Ōc<}_Hiܧoy[}qOM:c<覻bH_EL?' lƷf䚍Tp.] OPH(sjрѡ-:Ưif076? >%:i!!Vh`Ck9@>\S#97p͸ѧ,4O$x`-6n[$ƪ9x2-gQPgץaЖdm9tLJ\>li^;oq@WՑa3 [0lu;-I+^L|Y:qw䃺Ɵ}I|{_H>ץ1X[$o>#ymK )1v<%#k(+Ѐaŏj*tV; hQQSX6uٶII#jdcٓ&m+mw=h869(pji<16q|°iEnso%M8 = 6^Wz0'x˦azu3y䌳kn>M76&_8x.W`>7$L8V8Wc \Oh8y =y0,;TcpF#1j cs3Ɩac s_iQk=ޓkY#;yy2FMsJiA W%-x[!V xK~4h:ciK6ߌ,pR8.{?oƸ)pVR.YG*_骚u˶f^Yﵴ\ r5fsp!ؚ-a۪xO[*dĠ>߬8:A_"}77W0 3F 8DҘ8OW%jcpF1F7c9ġ30P z.6!-lhnZPOc ')&9=dYY'\Bqi$qĦ9WaPP?Zzqk_>,Y jZ*8㌳+le /~ .ka5׿nmٺO0V%Ҹ1-Ub a @[fV>M.qn=Oex Bog<8ƽw\M.ݗBڅ.!%$PB !TZBǘ@ C {r޻լbi՛?f%K8>Ǐ]i=ffg~L{}^$pV,A~Ncyuޝ4WH1LQ@ !%;Ca ?>Mp3D:f(A3pA}+J$ϕ{LEdDs]~(clT\oP\WXhk_%jbGA ܒƄw fK4cܡ?A|"Ⱦ~98ĩ Hf,c@0C{f8'lrN cb0`Hp0:-ofLϮq ݠXY1r֦=w}N6C+ 9DoM1l5 ?vC!1r wy.ci[jt WFKcL@ QcO' y>#*cػc(=:ƪϲɗϟp?-0=jI[O0ϧ`S]1)8rFvo8<ʢ1Jz|$K5&-, Fp#7*]tA)bQ$VS!')=rCccy̧}5I9cu1Ϸ˿ ̚5kɯ[LWW{HaO K@ ^#X4GS(سǏ'M;{ӦM={6"-ZKPiT)RAʚ1aa oٙؑ|lD!MIHEdȂhdZ%{pQǡ h,ѳӗS@ yaFX}Td1T1rG}2u[e1bh\w-Ď/G9!4\$,@~u-ٳw۾sw||'Xv pPD1OqP徢}E{j@TxOL_ n@ 1N 21 \TC1C1HJώX湓D04^ WE [i-dz7o-l=YWgb:cȔ(^JҊ 6{91@1 ݢjs+B Ȩãc<:ee%S?i&p_?l:F1kSz%^9ƅ)c_Lxs=bјi/'̟yddLrsO2DLل2w̪ .Lt2ek>+@azLH; zE3Ύ$W`_9U#~ ( $$ ;;v95𧼻v=ֹ?XLZ ?]ⴳc}p#s誒Ԣhj~jn%>v4n :Y3@P(RhpnHExvT@;}U '1nD{t.##562LRtɞq;*;lctQ3CI1{`| -IGdE=2%)^\ ?<R֥aGrKڦ'ҟ;xuYsmiNbU82a섳cjw? CvVx]]It 7qՆ#L8Ty&Rr JHrGWEIcWC1cz11q8}%J-WI5[+1k<9ہ&X+WnGwMpN` V~yxݡ`0^` "=בD1F%W Ύ;8G&[^<oY^JV鰯d#--MT:h^3@[MjoIa-Ilz'pml siS}Ls˫؟8KaJ%, lb[|C2Զ'~wvo=*Ux!1$1Wf{7\ Wbk;M#V4*5z#j^j]s*8m x)qȖ ccDL`}V;7MDy}>n3%_˖.)]R83e*t 7qBR*5Cc qU:lli7VVN/mҒJ@mJbS!ڽ LCbK (awOJ2QÖ5c{1';.l36˶[|_'@YsaNEFnI 'qIؑP0N8 1lf+9'R_<U.]XlW!BpHNNVVPPiVq~;׭6iy-vSww)v:>յ8+@!3nj%&px߹v6Z0 cwoPp 1 ;=oAnB6]n~\8yMZ KU)SXfOG1@12 Y3TӁ4N*4üsn/K=]|ܗ߇z8Qc@ @1k#Ǘk31Bj.\)b%g1Q Գ[R-F"'_a}cޙ7":Ɵ.|¹2~ݖ򳊄_pŪȿ!S6>=9Ư<͕(n=PԲ%xlBn r U3Ԧ3@С'l;5:|s %bvo?s\V/.]Nuw/^ˑ8a ^h;ȭruP)M=&r' ;?(yߏܑg? 3#@f}a\\3!Y:GțCȺm7/)=B--?im`WAcPN3~;iofyS*[- jMcNaa$1Nֹ-åp+tDmwS #;67m\\%/x^wuFx=G~L% o \3Tr1 (X+Fn Y.&up.>[HGc *ηU3> \+ &"(-0-0-'/'/=pG2qQT*C͐k>uH@Fc&</T~h:ƺm1[n$ޱJݕzm "F1jkRreR/VVeQhy"(2J$V͐iH@F_WWjMq_鱐v p !r+t4zt:VVM@ nnn*..NNNowKTv)m $=">lFskͼ酙%Ugpy j[:ct2Y-ݽ|>_ T*ptpv -Bad-!1 $t+K; (Ɛu=[pVc+xb?T~5 ǫ7cUQBas\^/ 8FSN744tvvvioob*** |:"2QN@ чGǘio@Y-AC֍yc3XA Y3F1 c^Tzk (FlI+H)t.t6ǯmiQY^Q] Bh4-m%''352C5H:xt೚-˂s7B £cZ(z栋v Õcl8R3`xOQ KnI/[vb Ii1+k j*i |>_T*W,_0V`㳻 B2QPP`A3@S'hPGMxt9K"Re]70'pǞyyy$7F@!*ʣc<;Ɣ@0@ *òu#Yy7rKz}Uͭ%.]}"hSQi@3JJJJKK*5TR!U( N1Byo!ٙFܐ2-Y !jfx40ipÿc$.)QX^\Bgp< *Q{NHjm.j&ը^F!o\A1?&t idff-թy'-pCA@F1$!2 @+ta@ *6Ҏc1?.6Pͭ]w4Zctp ,_<RKq-)-o\A1?UJiUf;=CcŝnY2Ժ%`1+@~m`-,c8hD#'1XcUJ.5Z:ڙlf+I T.6=J.p w%Ǚ{/->v6qSRR^0B8FZZqp;kHxPmO,),սe56ua.̕Mm`W Z=I lҧ9/NO*BZ$ WҎchW\ cc(4r X4#.^%_(pԊԒ⊊r@c}T*Hk׮`q bEрN*N1KVM qW\HFh:yܬ1K۶9BBǀ@HHc43- 1ܵccH=:1\9F1|p 8,aBTVt,b[ӱn`j֮aʰڸ8Nfرnmmb25(j dc$&&V3VPigCϕ8tj8u4eKܰ`_]<ENA0N&"gpWH vf"71N8 H:΂GW1L P(QEX[ƺUX6;VJKƶc7;5 y7 X,N(xd#>>^mxf47m^eKŘPmZ{Uwn Qza#ąw_H 1!jc\c:t(tC"W z@p@9!cP 1| _5#4y۩_n20,+b|c-2r7!/= NT˖.^6lԔjH!p</X &JeԢ2{isC:F{B $#V`qJ\9&1i`1Y;Zgc0JIZ֦ŀօڵ Ȇ ͝}>VZ툈5˗/h #%ѨDb 9f4!G.Ɓ@ ? <;c0qhgcϞ=u Bpr9F71xg cŢ[7Ff⣏?oڻfcY>OEct cXD-[3b=~7FFF666s{98Vr=:>a@ ?iH:F+܎;wc#cA^0cbC_UJ>7}MOU/[K^\Փ_>{ WjbpVPX޽L&355޵k׎;0RQQX8@F2!*6co|$ÿccpdC+uc _f\3ҎzU%jpښ]tO_ϓ1wwǽƷw-MNj1y b۷9>SN悷 d)h7:FG<c Ԙ1;1׮]h;u"vڰšo3"NgNٗw%>\uxjwEr2|pu/_><8\PP d-!dA1F1W0;F1!k@8FWW+ɷn4J2TY[]YUYV[Cm.˄ *:jVgff&%%@0bbbLnnnEEEzZ!qX ~jvvL. @ 2!%dA!hƐc،/|pa o1Ԏ1 x풒.HQX&zOG?\֖ :{ÇSRRxqdB(ʜEsCB (c(:c5Cch4ý`xt^'R ̭!,c;)ҎQWCde`tttTVVPJZPT:88a7(K{췹 Dٜ!ٙFܐ2 d]}.K;ÃceV͐*aj0k1|1rFP1 5Uu7իWΟ?E/_>}}G"55x]2Je3\ 4C61l 2:6=fDꏃϬ @Ba a[1*++G14c5Cf(>8yc ;-R 7#= hps8zhTTxURR `Y3Ip8lJB8a9}ύd288r@1PU0u c Ar 5>˄1dr 7bأcE3B1l մ￿i,ZZZ4[{8J 4C1j {pih`Yrn-:?c@r  ;1!79j1! Cdt S(C1B 2f3N3t8*n6սe56ua.z)̵Mm>/ p.Wy [zҌnwZ޺ P6.u4GlҧaG@ cHd*Ơsp Pc$ÍcHc[oR=5#Ȏr 10Kgwx\nvOR\ @[U;Wg/^ݻlwb7JLlpJWi1?*^lΚ =!H R )gg)b>֒2s@@1KVM qW\HFh:yܬ1N Mjr_2m!JxDǏ >C FH;֤1K)R81 ,`7-!_#>>^viHC|6`iU[ ƜW 3톫 u,H rr cU H0 B?͛>8$ìv1X2$hs Āߎ$\ƄZa97%ʇt; ¼ݜR.dѣ2TJ-! | &87$ўH@1LaԌ;F׎e  vҳ4@3 `9p FcA-O0duբIK,-%킼cDGGU3D熄 8 H:[ {Ǹ|`xr %â2b o[3j;i'رc1S;` ⱚ:"C4cl%GpnHȰ0u@À@B2!Crwc0 Skc茎a kP#/2͐1>}G7u Ϭ5Z3i~SHM!H qBq(!!4ӂmp[^$wU%Y]dIe3HB>*ֱ|Gz铽!wR\q}󀀳Swi':~* aq]8Gԍ0C5 F c$ecLp xԌaqntm^C|v0Zӂ1 fJ(ưX I1_k t`DR]b1#y SGAA4` |cq1FOAas13f12Dc`sSn}}p8 l1 hvfQ֌5ƈah1c3Ōa1Fk%&;B(ƨ /9Քa; E4 Q'01栻1Lq) ̐0cm t`P2؞Ƙoƌ`d> @B͢P3\c_}Uƈh<c̻ p81`Pc3Ʀ0C.$>"9Zcvws{Wy,3Ld(At*Esa Npp$Ucx^5y1O_fQRR?;~&a3CB<2APB1y-qR+ #116ukc\.IAql0FPnb*{n`G{#GDAo(tQ!"GMl:; Tc7 0:6)u61Bb"^f?*AG.MhVR_2}_{&97,z8h۬L.Ɍa :1@%cb0FB1Fvv6qKw ~U6ofcY FHOc8ﳹcw!wY\ \ɔE AiqǾ :E~+o~Ǔyk%~e|") At \736"4i Q1FT&10` Pb6x1{Yz?kߧb JOĉgr S:nP<_&GٹXm!#f1wTF@c؂#lf0A y;0FZl0B9a1F AD(`:2QVVh t`P03<@4F&11 ADcS5Fw11Ё$1.\k&0B`  HE6FQQ1žn =6h01 ADĘ9990FOA0ce !Í1Jgc`B5F-0A}B7{g 0B15Fxn _c41c@'3RF c]09FF'|11Ё1Tc@'=iL83eb bL5cQf0"0A}d |*l?իWb11"F >!#f4#0CmT1#ICctvp;mnvح-Mڦfn{'KjFU:DryUS%c@'==,Jl~q9DcDe#^ƈaC2F냭wW$ڞvg݅}t^-_2*yW/'~?u+_7zRzΛ]= Yj^tNItO AD(|$1X#0ci a1x<^0cC1h€oo=:ͭ%KU:\Hڣ5Xqzފ7=ɽ'Phbc T'n)y!}^y+\t-QS%c@'ϕT Fƈ0C2I05"1F5P0cUǧm]6-SpÚ ǛqVewaV>Ě&֜$V<Ϫ_YսEüÍ ruS͵߳A< ƨip1::qOc3cvpȟ۟>8^s5΄'|{_KۛfΣg-h}aw+_/u/8ѳ_cdٌ* >!CŌALetGh()P*(cw&*x9xɾڕGZמJ8շ yӟuƝOyvw_9{h?K:/_{AH˅=A]}C?Ixdd'>>w//l׊y~g+V_'?nxqg@ϊ1 ~ <4&۸\?96lZ~b<_ՙmɻ4:0(Coc44%,YqjQ+/ <|6ݢg xPʗ׏:XjяNkӮMa]quGFڬ0A,1181Ё;GFV0Y֬߸b͇H9aeQ4 0HcHp#.ƨgl>\P:^ޓncx|_(?D.qܹPX(W-Prٰ\(g1 fyƸ]ٗ^GCGc4555>ΐGTCoXa銵J+t |ؐe{pcD}cfe2~gwcۧxt=@a Pr¹PX(YN.\1~x͹PIHj.1 1pfҠlDcPd;:s= +/]!Qj1$hXV2CQY״XC+ds6~ǖ1\쾡['=JVx/|fDa)y Y1t1 jk%5550F_c$&mu|dy9z|qcT1X5]_V^za-OmGR_x3d|΅WHł_/|z*Wsa hb~NU~r$FƠ @HHLԥ:+4 ,{cޢ~fN{t -_aag1*Xq=u/&7=I_6%>X(ycr|{PrFZ(1 %w*HN1c@1}40$e42!+.x7wRܣw I01JXZv5O|ƶ?m'mJs/|\(bE?==BI*P%:Z AЬ83pi@7FdV7(N˯H˯L/ǀHۋ^~ξ3ײܣdj@I Dc>|(*=SݬT>HR6`GJ^[/}W5Mۙm/m;|!ˋG.~vv]/~9ye7){O;۔]FlYpUY12cdggy׳׳%]%<4.=zk6:0(}[%OSojw?,z?_XK+}yc|UsV='Xk~s3so.s.uy6nPk7hV@1l՘cfcƀ O1#1oH3H`0WfF> 7ll>y`  m ^ c={QF c~,FvYcn9[ Uhi†M&Hm F#B`P6A!0A}d r`ko&X!'`4䔳29Bj?6%ZDkÇf%c1eơQ9#T`  DF@c$~p`f i1FH`4ODlF#n &4?1c1 1F Z~N:20A}B2LUrMeL1ƾ}ISƌA,xׯ1ƈ00Ɍ2_cE`  DYe `(kt{>iPƘhD!7L1\6 0A4%c K۶mC4F#1mLNn9Gcy$ƈ"0(ce |[ {<}M|x6U >!#b0ؒ3C d ^#Q/̰a؈1p4$f @ y$'11]` ㄊ 0A}B6Ơf#As͘6c4b }^`A`17iWbw3#rca"aFc@'Tc ЍEoc81Ё1*TF̀20A}lZ~ 0f1l1onf1Bƀ Op2#z@ec )!a37Fc ADf1#1;t3FCCCpcHtv0FA)Ƹr 1"ĈȌ 0f#d`  yi6F ` `c`Pig@p320A}`#*@19V!0A .`tc(\ %W uc#Z`A2CcADЌ1t18#066`P1 14Ƒ#GkH|F@ ADBcC|[)Pt0\.i f#d`  4ƈ$F(cs4NcT10A&f <0A}[n1P1&Ơ`ƀ Of FHcc#1f!6NC7 >Ebb0ѝc40A}c466"!~`\oc(l( a2Ѝc ƀ O`Xf2_丙F1 ` AVƠHA2#^ эuC >bc`1#1b `1ƀ O1U`54 D4҄j t`P2jP4`Ё1 M Tck %n0C 0b`  4(vƈ$1:i i ͚:l䏈R`  ;c #<`7Ff 3Roc#JƠ ֶq[3{6sDUnYTUyY[o6&U,0c@ѧ#???`6an96y%ncL4F,Aϟ1,nVtv=n`E6MƈY~$lTeZ0h1kcq2c@ѧ#l`|ٔpt%1ig YƤҤ¦5l>n^Q޴iG KajlYIu7$0A}jlcdffy,4#IhYiѶQm}omU}[vLڼ1}Ѹa횰 'CvI|"$0A}1"UcKDgL'1dz Cp#h q |a?TxYڟjU6qD,'H`  DƸu1Ё1f{>qc|0 ݱs#l`DcX$3v,|OgS)*Q[y tMYqc(:&80A} ]f3i 1d10;1a+;X]}jS,V˥" 1pƈ!Q4i5n2YLJ61640ZǶ~nH1ۻfq1]tZΔSo-(uBYd3|ƀ Oԍd3gbeJ՘1VhTZU6#]Q1FE͌x4TmF`VQֽƚ^wvɲͷP(`ur8@1 1j-X6;~'5dQgo۹7v bCT8v0ᲂtv-Sa7~+ȹ]^ʨmiIe6op1%c@a6c`$.0CYc ޓUe-̚.V]XYі#$0j3Is1uBáХco;pljvc;kphHRRZKl6|c@ѧ19HT- 9b)e2*;ʪ"𺍛C#3}'M351y3nV79-lnkk_L&)cJոzxl2&"3Q,N ADf t`4664ΌJ<1J˚J-H:.1@i =wF#}<8>7&Iz}YJꪪ:ă* 4\IKbaGb#vc@ѧxbDcU$3Hc,XXfTUupzdQUcϧxHs2}Nk7+{N!cD?.˻1Z-2CJ`  6Ŝ18ƨ;c,syK΁ȱbDcn1lB_‡1:6֣FFI>PT]VP7x>)z༼l?chcj5c@cP{cd#iF C^[cUch TWs P ¿䕐kbՔ4#a[Z;eaO9GR)bFoo/2p"V8 Ҏ!ck .lc0 /QI0A{1(ã1̐ic[kSIPN~>Nc>~m#?O9PR_T]n4 ,FvB<\J .k |`2FW@v9 4J9õ5j1}}JW߱{:H)88!$-iGky]2V ޲ƴ촘fX9zH$H$*yc@bpo. 1fYү5W *._;`XǬ2Faa!+4g57tck06zTF$; bb/!tA쉂1tnqqLcxNf81{Rk{yeMƮ\@ -!8Ɋ!OS9y*31 Yc$5Fhh(p I`3F924cn5[_CjJ́1 ؓ=0&3(1dx` c@'~+.5ًU1zKeTclc AĞb Z9Qc(xcՠZW-pyCs>az WR]ɯueF3un910A{"eɍsNLc149%jEYW-FVj$w1G?}{ 0A4c1 1ޚd@gnFۯ5K10Fgg'1NR5Ʈl[eg }ف;wc7wtx;;~ⅇv]c}-.9 a#i.W_aE O^dYCIwW0-Ch }m7kی~o'FЉRW?ưyxfFrᖣpx46ۧ8>c@<cHa ` 6chFO[5'>0HC-^ñࠁ}m?<(21&jaTc/טO 0A11P،ּ1zBEOޫ1`A0CVՀ"%`c}ip\1 F^c4>Fj +4uwtou*dQ2 1vc6x>V2 AI1氋c(6C1 ؟όH@/0<>cjXaFg~,Z*Z\4i Ve Yckvu9KLfE1,w3ɀƀ bUcҥ@{OCh7s(ˋ:rk۳ں%z6b> dAmFuu[ca ōyji:@?V`9c@'+ƨ`yU:S//ḽ)Te^Kv`6F90% =Aoٮ]m M]=n_Ka4 ƀ bOL1Fn( ,$J4Zbh?Hhc@hHc΂a/S5IU mj5&3Cf01 @{LLcP1l̰ce:H\ܥw ;4ac0 =1gC0>Ƙ!ɶA4$݃݃UL1 0A Ơ ȫV9o5oͧCg: >3s?cP AĞiii3ƒ~c(CSkֺ0f01 Ic'qi6e`x4#&vc,@>ա282Ƈk7c=0A쉌11FBB1A 1 ç;UF{g j01 AĞ1&4FAAÛA쉄1X8v11c%ac0 =aGa1F48O*)cTVVN4F)L`  k .jv9Іqu*I?0A{34>0(C4i kpI{uΡ3\bt `20A{0j;N119_>tFׯ"ٕ1ZZZ6X1 ؓgcM1Z`jNc]h}B+v kxFah +3c@'|c$Nc Zwf:hXсc10A{"eDA#0cmﻊ5c 3cFQ AĞ7ƍi ȫ_0f :d]eTOgcem6#c`ƀ bOd1;ci4K -;0z]WB0cR<Cb(mc%1 ؓόH?cXǘ5oV?ܥnUh1F]z} 1|bƀ bO,4&00?j7. jqu)ch4Xư-bX2 =` O1 ؓo~79 :STɗE]-݃Zc 3Ic\v^#0A{b1QUUEΚZzj۔ NZ?އ+aCCC8ư^j]01`c`  cc7u ybawisW7h^j{c 3cXOcƀ bOSUH㟯͕%R;䙼a{1>0H`0`zz>c@'QRRi ds{u%2i=B7F'h2Höa;%=@?Hiԭ*Vӭ5:mh& %1j dU2#$4mٙZ'|qɌ"YcI Wu]ZQɧ{''&r&Ww{-^WR)TzH eA%Ơ xYU))u)µ)v͓s{@1N^n 6+K b;A2>K~_[lD4'eRE5uuB~XP'kku*{d Zbbb`  Ĝ1Ye9 " v o h^NoLL0:_%@?",<׿O\L!BL\CCa[xm糫,gͩe GIʞڪ \A,105`5*h=ƛuFTkib}3WHöQWcFVԘy܏G8l2bQIL?m-`tk-~KsVf(8۫6 E" ƀ bO(wƸYym7F^hz11I5`t1ی1cvuu"ZH$sΡg?{qAD\CܐARB^OLo%ԇYFNYں,vEi-Ѣ3Y$>uJR v&f ƀ bIH(1&DΓjg%w0^P}a2FVf [O GPetQ7 m4qoqf馳CKk:,.PaiǒYgF>[0A{"o GccÛE J9}p cW$~11ʷTWJ$\.Wxqy M bzbnSXŖ JlnH,mv Wb/?Zz$=AĞܳ1=ʄ1&1z~nqnqB낸91oF[4rJΌ_>j; IQT߂>X[mM8|&sseハ@nϞÿxF1&3Fccu #HxqVrs y{_x9浹J&8q]"q}qs1qE鿖 ;~5>'cgpBo5>U3 My4Ɯ ưcFc<7kif8iRhRoToXK;b 1ŽD46 BC3JKK233E?;ŕ<S5lqe(q L7RmخܸSu[?kzwY l..JniAĦXn 7po*s؍e=C'ȓ J]#Vg1GcDE6;HMMʊ ?n]qu8qm)7|͖w6!wSϊP/ۤYVeK$ڧjc@)lc811v؁i 1㍅SurCukJw>@;ɀAv`ᒖؘ.i}3%/noW@\qu$q} +oϞ` wZ\!c*VWǏ;M pAl e_2a k9g&4h4+?wcd2ưr? 'cRSZE/kb+Al ?? "/:W7&?R?^|պhzfy^lRQ >U3 Ma6c Ƙz}tg֬ {:7xư.eGGŤ&lpppRl\Nvl466Yo{W]h{o b}L~}䶇Sg z|?լ0:v,yc@c,\q\3#35=ư1c>RYQwxlJrRt9pO_d5uge= ~iiUDd/ .zDQQ8F\}m7>A\e` K?_^`5ƢeFvkOvkGCc5/2{`5Fgc՝1 ./>Z[[Cmo麨즚lNeBRu࡚*om*A'm {ܴLiAĞ4ƪU0HchO؍1T8/ LINh! :p%ڐ~<8mzy'/lMo*))+(}A쉅ect;7/5_1Fgpryhh+ Cp~!G6nO7H洷j F1*df'3i C!lm|>m#ڮ&)4h4+ MAĞf䌑:chp_w0B!!hRiKK ڴ#Dz =a#acP'c_.u>ki-[\0}uc6mCrHS91 Ic]Bvc E ƨ WL\U 1 11vcPPLn R;51Ɓ1zc@'ccP%c1 %c1*'D #!!a2c1<ƀ bOda8Lcx /1L11` AR4>0>0H=cz'0Ry(׏]jc@)?K`P5>3qB0Fu5L@J A_)cنc>| :"c0/Mu VO?w|1_'o+ 1 1dɀ1%1ư/޹lNWU6X3͎.7]n2 ;c@'w^Lcв1(K`5Fό1(kcpxcoictƸXH0  =a#Op X82X,lF#>4xQu =CQ۷o4]nԍs>.x4ƅ'Gs`q{Ă1 .h1֭[ RhoowkaČJ+1;1UW|Nbt~Ng@cǟIM`  cc k  0.2B`a+3|b TA쉄1c16l؀i R1o 3)cеA` A쉴1J}a `x0F9xwpP*f1 =l2YN41lcx AĞȬ10]}Js8ԕ1j㌱60A{11uct ccAĞ1*** Lc1Lƀ bO>0Fii)1H-bP51t!Lc$c@'QTTĄ1*lQ3L,b5FL`  c5c8!Wi |` jƨc`ƀ bO!7F^^pj`ԌQAĞHC1(1~3+a.0A{"c +0Jpi |`0`."Yc9c@'lc8_cT!c"1c@'(!aLcP^Ġh &d3`1 AĞ0KLbB^CJcǃ1(ƀ bO(2` oAt0=ccI60A{3 1a s0a |`P6ƽ` 1 1V9atK`xg SaA 1H11L^`1 AĞ<c10 }`  D11A"%cv1A쉬1blƘ+c5ct"AK`  {c ob 1RAW`  _j cAƠa1"cr28 p =yoO?b**Ơ ^  =8po c,paS5F__1̕2C9"K?[V_of.c@'/`41hT7l@d?>\WיnD颰 g27ƀ 8ƈ"f1/^̄103c1T* co!>N3=FI6U *'U&[V̞EusCk_Y:o퐎A*ZQ^^i |`Fڍ 1Z-cn Ns*ekL`Ln5}S#|!('j/ϓ׿-ڭV24%1gA1k䌱1h_ĘJ.5lm]845d_V^)Э,y;yYϚߧ 21+1gA1())4)``Fڍ N#c 0hF_xyg"G #XU󩢾pYfqr+K6¾|i}жB&f2  ~7bcXi7Zw`!1݊Mx #}>QșSUy|E7~,7 Snp ͏!eu_I? |f j 0e 􃦖1w3Joy'cG՞͍;o9Ă­oe|xؒՑ*WسxWЏUk%}b.c b"oc,B 8ctE 2JuCWixOUXjϞ;10h EYZRZr$b?}}Y>͕uvh4hjz錡 f112&ߝ1AvCg?7FVw0}aϔ}Rndę_ ݖ!vE!1Şjcc |`L]cL};}ݢ֯>~dGSm[T+Ѽ1UՂk!.?NܐMRND%%nT>dD(T -"KMR+4H-eGPWs$77ٚ` D1o1h4_J1'[Ѡc 㢧ԍ13*c83A>Z}U>q_6?]c͋ 3o?axFqk1MDu3CyUjKnR`)YJfw"qKqq154P84D^,|` DQKLcDFFb311E 2Ʀ+f,b1cq=stktVVAp8tbƚ+i9kJ?9w>bKZ%&߲6@TYYEl͓qbl#]4yFor 4zl?s{ Eƈ.j %0cL|J'3zf=ȱ;9rs{[o߽5A+۽螿__L\{.CTFT$C SHȑSgcع!m h;[cĥX.K$'>׏|(689ɋ1.|c ћ%-!$/Aхi 1cQcx 2Fo㾿h sŢgLD{y/o2$OeN $6OLƓc31`@1`0cY%0ͬbX,!֖֭]HBqrN_uoU풚;۷ު[#2Կ<;”%Dʝ$E=\ç2]Hw߽V!{Ql:۫o!pw|f0֓8QO|HjeA[2Ry~L!1*1*1f1#c.?xgU?Q__}޿'#>dS\z`}olw}i뫇]s W~kmΪ],'?)?yބN DA#\*QI'jTzSm(C{]#r6m*_$[lA\BZ-*` sKy2.u(>Un:F hskw;?0'%AC }Ғ.4b%Q=?>EԎEDa`rRgrJyx.R0cT{;˄G5oC_\Xwv>#F})m~w=Vחwsx'}{IϪ09͓NYWΕ> 4DcoTz/HT1Ԙ@{$ +'7yk I5R!Ѻ&=}I=m KBD/°Z+B{B>+oaK\;8;}=>rtʔ6U][xMQc®6[6ZD屆f͚:`r!@|~wgc '|}_//Vo%%?_?7]|hN3rO==cc\o&T<3̔ϔ]x-))MsWc 0v 'n9C>Rg|Ap 4Y% _&h]SLl)vaD5Ts%"t'$ii}]ᮋ}5a#\jd1jũw]Qv@T\nI@h08Ff-a`7X:A q뻵fէ?/<}ko}~ӆ¢~tW/nvwֺ\\_?\o=̑=s~Ǟ)Cw4)DWW훪-FMj"*C\B=tCPΕLQ)N$ uOMۅb<aOcQݧ`cc}G81jZ֓Ks8vˆ9\]cZ\,v pktRJǠ Ǝqӂcؒtv\?#>@C?X>jڕO[]YQ_r3~=\ѮKߊSu{eo>V\Tv',V[tTc͕p]y j3EscW#RJs A.5J-UmJE)Fc=!pu4 sGEf6 ;Q%{=!X|*" >qCeD3b3C1Z:S/8'u,øK0,>X|_nxsVL{c7V}$ҕk55^S^~-7Ox"ۯwcŸ~Xi鵳glȀs#"5eM:נ;n K'tri!֫Q37f ӻӫnt'QsN-23ˎaoêca1aϒuuE?c>ae.^6s Wz{.dgr@x<%ǒs<_tII+y,6/` .SF1xoU5"S!2zn2w $Nre9@ggg©OfFqOx ׂԕ0sK,[t;{+6~HllnŚ:hoMm-4Cv1{oVԅŞw΃cyǂc+:F ǰQ0c6lܸq'N|}مeeeeggKڰaҥ=wܹ A9֯ :zދtЃ1sk)E&#`1.a1nܸ1f $Qޱc￿z͚lܢ⼼<'NسgOddCdmvTT#掱j#-"hW2,8ƅ (^0,9g`p k:4 tˇJIInU[[[RRIII7n\z͵kX9 `/M Jy#-"hW8p2R:ƹsX8!p ۓV#g8 9vqqss+@}bݺ)RͰ.4CGAk׭ۺuk{{_h c 4WG p;F(ce1LBA8:?sZ?-u<TYy +;H^w +Y"]Ԓ`j%TFXӏ :;;?sͿ9@].9>Q3<ö8F01.91C}28Fs_:B RA,$X8U;%\a]!q֎1gX^`3"hWb~ ]Ljt z0-)b6s֠Sb1jqA>0e~NK&J9#xb]rnEUg]$FH a]!8Ɵgh8`P;մcV rCQR62'ȷQ! i+Q:w!]*u+m@cH'+,!L^H1_^ޱ}AdB^>Pq %{=t/>K2%ܫ˖x+6.g.SX㵊 Ǩ؟RsΥt {c f4wq !t P"q w d"/s!'% A)*PǸ}vUmhX=Fx6r̘#9M4J1ъ.[- 1M1h#cH!wЌ*^3zn:AL)vW7uNdENp *8 C:H'D(\ɝzȫci, C|By4cU%W0=ǨLƂ@HCXZQA>A2] SR*^RHŸ E) YsyhN_ȼccC1>sܿtaPqf:5vVX';Y!*4Q^ 1)^0`D$d1xFyݍk7*;@9up `Hc``4Q9Dcu!x(k  ǨGǰ0NV b ,hnn. -"hW1L EǨm+k#7l:F@W'0;Y!c[n0" h+`9hC1Jk[@3jۮv #R0TquSpNavB!c%k"##Nm4ϱ62^=jx{Ĝ S-uQ#1רEv(fk{Ly>^v:#bs1cd%{cnmM1^}7xcٲe6mΧc"タc c  wc@πc$$$ڵǸ_Qr43q]=vŧ ѭwhmhTE`<:h7:.ni ݨՈQ?n_(T~˷ ht(}Я,F"njvrw =?^. <-$z}q]SlUhRGeS:DSWz:dU*;+PE/ޥrEd *J{8@0\WjI;?ĉg̘1w}8 ㏥T9`ZsCrֆ[^^^XXJv={ZjĈ{7ݖkƥ[\xi7/zhi#;@eWiy^Ȫ,ĵ.L)ʸ(J/EGziGZi{3긑Zr#X6u}Rت! ZqJ$U.N(Yy' N^m8]XlCl$4oo)ۑNT#2O۹Wf|Wwmb.-[+Da¶Sh=U8N*E\B'o 4%6\SSwk]G\GR?AT~%EGg8"X.Ÿ!2.ҵy،#>:[͈MTs<6r]rn+ '&݀WP-]$E}R8.Mrj. h/LJ+=q}yĐH-oQD{zܾP>ȯ@PK|ɲ$){nbSQT! F]{}̙`X0ゎcxcԀc]|+999&&fݺu?'cP 1~=Pi*z8B3ue\kFfBIFQ+fI$4C-DB A3H fF4 f(FiI@ij(i1Z;Z:/j8I#)JcRn %ǨVp 4:h`d]8Ώ䩨GUeWI4.r}r.?11NwdYf%rQ{h\CfsbF%j͐9Fi莛>L#M[H QJ#$bhF ŠcĘtl|?z'njk͞={ѢE˗/1q֭чs qApſAc"1c455cTTTfeeAƂ=}cYp!Ib),遠gCcpc;c0lv `-6T71JT!Wi54y8/!F0 \ȑCiZ0D8 Y4_0x#SٌCc g3<*A3.$d;C!yc -R9\64#"j>*Iew vG!1<`p c ӎqi{𑧟~z„ SN3gΒ%KV\~m۶ݻIII0V={֚c =7yj%R4vZr OH_0QWWWUUvRRR@v޽zjЌ־?4ߦwI^0$8W'w A31lF~!$}cHf4C4NA5JH!<Ӑ2$IR)Tؑ;iP S׌>0+ڎc(ɿf3&ss2hë HHq14jcQ*L ЌxN3|3&ID3iF(W91F3&5Ό1Ib2ijFy %4~a215ԼcX Hr+;A0/^y啈О?e֬Yl߾}G9v؉'`LOO8< 1(͕u * _-!}J_-C;x-[}]ЌG=;_ħgݸTۊ7D}v6Z C m>Eo4ὃF-O팛w:܂}rdZl [*F~J 0ѽ]|x嗧L2mڴ9s搉kn޼y׮]111OK%N8뺎WǰQ0$ǐ(%L۷ 4z^jqs̹s.^xQQQ/c9r$!!d9F+%a`2 SN8p:>XfͲe.\8gΜYfoL>}ԠyiȀ˜LvIlȀWf3f^qlx/Zۡ38`#0mذa۶mR0> cPq tI{{4]B]BRiiijПw޺u###A@6,YhѢ< ,?%0s6-6f,Ɇ 70 #S*)E Y|Zc qD0`A)')}kjQ"9B0cZWWW]]}ڵ˗/CץBg=zm޽۷o߲e ݺu뢢V^jժ+WXcU=K26,e;lX˜lXDB,`p}F?4ϣPl$plçN0QoΝ틍=`P:)R4v1 9F@%CJeTUUE4#>>w;vۼyƍ7ϳ^}6cZ3D1 kUYɆ\M3raΊ)7  G,|$'g`%6\hK_'III!I 2QBcP:$R*xEE&q9L6ۣG>| v}m۶m [̆Mld@z /e!Ǝ.SݵEwYlxH,Tk.}!|j'RM`۷o i܉!%1X8F%ht v!+!dAn$7ff\| L#..zȑ#刱~3c^j!lENf;cSnLĘ^wY㊋4kJwmB=h8t> pNJpⅡF:I0N>JN$F@ǰİ&>C8%$!͘pW\sNH倞?&# q 8j5Gˀ2AƲ,t,t;;LuwewYKRBht)V8_8F `H$&JeXw O`-$!25VVV\z577ҥKХзiii)))X45p'I6C!j1RS Kͪ) e, :ΦaM 'm⥤l!: vY8P&sv"0X$1tIC15ƍD3ȤIMM ....(( A\y9ˀL3dPNMPJM 5lq5ea`᥌lRS0&D(,(#dȦBwAQA>tpC`HWeİC g=OeeeyyyYYFQQQaaa~~U<+&ɥrĀ-ad`aZkfH/xfӏڠ#kcE(bvZð@>#AYފc칶8`CO3@3kkk4%(qQl"j )& Wgg^# =l2zp|Ôc '_0H#c~B0Ob &1X'1Ra!Ġ Ǔ,$`؛f($12A/'1x^00I IaĠ c8q@Ҍ?Xw z$0Jb I ւI x^0i^0Ob I z$c40r OuI3|? ȧc  ڎt#9+ c ;~1#)3?l~2hFVa>BΉ  CIq#3?lh1Jn.4;  #|2s   bW%ͨoP9F)\,t AA#Er " r9FČ<^34yNc  B18ͨS8  w<ЌDЌu]E@A|y1>hCq2NbaqDbڤ 1_k6JtL! A=[w hQ;@j݂cX[^y+ B8WsZ1O o& 2F&D(/{T=㊑DEȞ_+>U'!%F(+8_L@0UƎ!Fy O{ -Jv4:Pu~v&{,):fIj{AA,rc9h`P$\#AB_a~ @"ÁlS/ozlRZ>$&hl0cVo&b VhlԍbAYoTJ^jZbL9qw&D&9 ,Q::Ѫv a)]Ϫo5E1 I+%w2hD"7?h/ozlRқlVB6)(zb~jV1EkZAoW _g oanC,#ä|h /軡B=ۢȷ4L=Rߴۢ5)"`Cw5AD*qCWA z h!i7 C|ejpGˆu[AaF;?12\/UlXAq1ZM#@AD1&vIB>mAAၞc~Į.i)\Mt AAлL(rQ\EG:  ;ƫ! [;hڛs)Tu3uU1Ttc:^Sě1-p?Τ)aicf6&&)bZ5bnLWuoN<8eih 1 1&v҄⤤o2L_ttm!F>dKnْmْ%Y%}Ls`00FzgݵPQ]K.\*GǪj.Q%hh;HWCoTW?RQgϗ^ڕO?/{ r5(ՇkkΜtsU'^(#9rKgjX۷.e2CE~a=Gq?eمH.* `F%G͋Rrm$3`NTvEΌ% 2}I2[O67k|4Hb+=]etD19c1 Hfy`IC#Z <\1ps 1ZScX○0qpLwI.]@!Kfe+d/mb%)LbM*Iq01inDNdOE yF1t^EBs~!ﱏL.? 1ЅCio$ c"J/eP ]d~ƨ3Oe 'h"IbQ U ƶ1'u(3Sf[abө 50"77S4f1ێk11CWe )ib2ƛ3T% mJJ/3BorZ\aC>L†74(袉n)D% a tg-0Zq"Hx=CiO1/hrb&"B A"!yPw,жf|׸CfWHgZ$&FJ8{UA8'CQ.aQ[bءҠC31F_ӝ1TFz*C_୘30I,ihᬘܗ4J+&bM4fl07%+&K\1;LoHƨ{~;,6$_8Xs &|>[ߕ poFfn ͪ,^QL#o$gdkMhy}sd瓵ͭͧ{lZx1eN3H"MS&.`4I(q"ݚUܑص2tK!Evr]J1Nvߏd> EdP2E()z{Ab;ҶHhT 5t9 ugQlskl>Zf8TR on~{{fXo߾} H⑎U89$A>taN^5}ŕ 6ypl*Cų]+_-n^؅Rʫ'N)5w{xP wޱ'۷OrMEwa endstream endobj 128 0 obj <> stream xXmo6nN 4/&Ef+[q5V/wGJdKiS{CY!w5׋bv;doo(FlBWçշlx1b!s9!󎥒/,YdWdd\?Ovp P^{pD8;@vJ2}8߻$D{2|@4ɴ,mRG*g%.kzt <}hzFI2H@lkzD,gJt@k(k6ʵ ̤]%G34Dx -E2`jr87.= g|-vOkpZ?Cμvkai6adt4_>X|F,w!ARgqfƕagm0nm8I 6L`Ty-9>?$Î<|E~Tl,SiJ6"Lk""JZ.x",⾦9ĊNS# I2Д1#.6%h$; XWu36_Т*4?Ƿ5K%#L]ZB ÷-eFH҂Om%Y!n2-2YmZqvobmтC]LFR5xl n"t ٖ ;W"~wcH]*UgݎyD:&d[*|!3>rI4غ$uxeeת4AP_>pbz*2]M:2Ɖ~4͠8e)燧G}@ Ƭ &8pM5)y( \C5 }J?$+)<}OKA0aɦװ{+S{Ja|h4֔"|Œ^wDF" ;`JY3ל (I Ӛx \jV=1v If<Ӊz'LI0E%`kOh%,dd4@Y`03eP, > #}ķ"3Sl@9rȱDfXp '8-Dۉ+tAQq`Nʗ+m bi0p)أvVڎcݭXTnGp+7GRZVQj%/ >!?B7+ֆq ",CaLG*<+֧Ɯ\@I9C-`f³cjRCH z]58KGS` +2_Lҭ5o lg endstream endobj 129 0 obj <> endobj 136 0 obj <> stream x]]&m/0M)QHicĆm^p؋spwvw>gHQ<$ؤyu*24g.N27$r4:x]rum:ueJU}L:5^YRF!w*Xʔ+ %Yŋ@ziBb*n*j2x156tj}:GR8Xy1:aeDUςShD6 PN2Lh_@By v xpN:tI& S"cJ k0k9 >2^`cN`ZI&`µ BύڅކmJoIh4Rh`0۔"+g!F!uE2Ƌ!-ys^k)UOT݌xC t*suX N 8r@dxKvfRq1QL98*tv^ K?lhh*9)p&G 8`+)LTH3r1UgzVADm^!Y1~kT,NUab/S 5bj tJ*EU[jB*g [(pZ**M 6@yNN D04 xDa@0Fo6< lã-[VA)42vL֙Z&+LVLUF ZGeg2"5O B0y3W#WL{fTaBIˣBfi ʨ²ۨXE͍-VXCgrd^cv#71Ln5zW&Z+K2de[8[nla- sdP'&nTwԀ|(Xµ3dr3s3Yy5|vԑɲ;2ՙni[f2ȊL!jwBr,Df573cd3Cfj+̾P|byd0'=Y~esc4S*2JamP*2 ϱKKTeUkc1Zf XӨ3=lA=Q ?1ld5(m\ǞQߠ%qYgJTAHcVr(OaL3R 5aE[X2j\{wˆFdSh:%"Q0slJƱDFi-ꬣz~ȫ2Ka_YZ-hQ + ,ER@+uFfiͨPX)ڢe,)˨T/HJ)B2zE ’- gd:vE+%r|2KQf)cOVݙ<Um.e82’$Ư,@3+#.xYB/WP@hP:" .N `!Ccy%?Wa.BWƺ/zZ$;\ȐJ'!KBI y>ZX!5H!Qds3hq#``19mdFO22ވcG+"6)XSQFLZ3r 4V1Kyh l22ri> \3]YA]Y9<:yܸabc^7A⪋l\cIDXU\]rft#K%btKԏX3zU|Yz*k(.Ig ZAcqY/׿Cm$,,Qmm:ڶ-iԥ܎mcؖPӋÖڎL¶qL8R4w)d>7&$^۽ʉ7 &ZAbŃs?}~wןo>nX;Aζ‘bKZ/lQC%]7S}B$} ˻IM߼??Oݛ7??o2Q8z4b~'UoAiH/e#eÿ~7 N6$<̮+9~v~W#vU@Kg/ۢ#o o~4vL;(G@%F@-PCBIeG>G͏Eƣ KyZ%`h<qt=8BBGP2P)JCB},sIr%'8 &'8a +NXd?ju>C:TP=9J!PBPM*TQ:UtqS%;|P|Pj^iZPI{*=*\B*!T $*P%j0↻T]q]q]q)NZz%ũ;ޱSv_P)/5*=*|YA9J!PBPBj0T29U̩b39S|詧0^Pٲ#*my BJB( rUB( j"E]wIQ;}u՝5'Qs5'Q;vxjq-2T'n./-BJB( rUB( j"C; h͝wwN;`wu'Q?(B"CskEc`CApQ6P)JCBBB%}l|GccA"M{{Qk-uCxd rsB( 4!T ,!T R(9US%9U|V}Y}Y}Y}Y}Y}Yez"Z{{*o)Lcb`{*gU g:kY;Ъ{Z HwX%D*2|-`9+1`5k1XVwwoVA.^ci?!!!!!eojͅAyȭ3^LĪ\uJCr Vb0j bނlDohqZ577777?[iu"|o[V]^[Y Vclu,`-OhuTgMuư涶-Wm. Csn+*`zMܷ``=[voY=gjWhY{7 0```+~w.\߹P^q~}lЎ<ɏ}vk'oyq X:ycMrwg^^f[V[YXn.w eWoYQ-+[b_wwxihczF\{50Drʉ+Kr//T5R{n #6m 6:z`Wխdn#G]-^'L&'BsuI'ʦ=q5jP=6[gӵm=ctxyeWԅJ|$Yam~ >S.M8u@~"us֧>^wXڌiy>ε 7-sr|p~2㯘d;3;َ0ہvx:X#jt~}-k|rWzrvY6k>xQi%xT=(݉ҧ<=|}~}Y\5>ֹIKc߉am>{;]أksՎ=j'FJ[px&KwbW;RzT.%xT?N%y٭ϯc9/jjrJ^,,Ie >.lɱg5koySP*_i^?C~=_Eӂn9o\2=(-젋B̟W[zsQbQCHg^G{;Ї_}TU"|(Cu7Ϟ:o %']96ג.c41@r:%{ PJdP]c=Wnξy8ӷ@9*E@5jPMSzDѺ{ CK|z>yd]qܻ/rV/9lh?8s(~:1;ZP`9xvi~ľ.߾NiZO|UUs:ÉO#n[,\Qd[M{e|͛^ endstream endobj 662 0 obj <> stream x͙o7?qFH@mE Ha&Fu_jS<ǿ,ЃM<GrOi*1 j1"a̛'xy6ͺ!i8tۄC-Pt>9ޔֹ3Ӹ71Eۜ_Ou3Xg bL9C+U-O9\Ss)j-բ9Q-Z=B)N .éALlFZmbڥ|{zh~ow?wJ/ݓCҷ~}dDIGJSZ3ZCJ#J2#J1=LIFtD)(و(>OidnRsiVFZ#J6#JeDiQCx AՕdě>HS:GlD/vLd x(ս?ۂtfoeAJ>TF:]` 6dDIG򈒍(unRznkAivQ%Q#JuR%CkJsW:.! r٤<)HEґ~䒐-WѫSyґ^N32!IDD}B}[b_YR?S?S?NF/^F =^EWѫ32! rAR$H%7?&iHGb?23f2? 3g? aϰg3 {=Ǟcϱs9{ĕW#`83⬝%m{ěwFق=ψ?[Gqhġ-#x=ⲝ=m{{ĩååςTdFґ : {z {ppppppp?c 8,pXa 8,pXa 8,pXa zێ7y1\I_Ocrz^nxO1.><<=ۿ=ڟ_l>?;=?{sz^|wN.O<_\z?~9~}xmtj}Ǜrx~>yyq7'gW^<;;}Rwk'8y.c}wi|h%YoZIVú+ :MD+-D+b<kH$nl(omvo=$l]oo VLRa/n8,K&e4.x LDddd2d" yFY^E_RbY/Sަź^0)k1Eӓoz^YW.y3I)}!/$'$w=^ľ>HX>\>x15ޜlY[ۓQDuL~0ߧ_6=#}k9qriw"q|I܍ޕ/kCVW|rorhȠA>/~{PS}%ZՙvW( endstream endobj 730 0 obj <> stream xeRn CdGHI$P~&i"h}Duk4z5#o^*a`φ=I*R*$|4' CdL[1D/FDup{ PƤ,zs7mw.t&3,&q0:)bJZ* (qwBױ矝 ԩ8ˀjDDDu@!#B_>#JBKk[ildl ;$d0KW-Xyd ڳ=J0 d1s̾6%۪$_}}VP] mlvx`a~R Q{=< endstream endobj 731 0 obj <> stream x |eǟ}'M&i4m )mZJi n@P-xU뺨*قŠ"}P]]דI`d麼{gy3L@ mc|U|Le뾽q,бgLX{ٴG71ک7M8g֍^/r{MWW[֪Ɖy!ߊ}a4MWw䲒 (O_?_n0:{a]5=N uW  םd—/iX ohnsHw9Wվ;.7gT)ki a9.rK/^4Ď}y_;Edё#@yg7{Szw.lxy֏5/lh@KK.NjK.hYm@5sikCM |7k*_SEI00XI i +q l,;pRp5+eT# ~a;\\!_){&|E {ɞ)興[p6X.Z<r[uVm=\7V,_D6M8"kd9hwc>~?X~݆OR}?c]>ƴbΫ7Bɣm[<$LG6-]KUy>l_+֣Uj'+KU8Ve.x7`N}c.42g`0QaRqx$BU *P G@ jT hPEՁU/F0P3P-`FM HTXQPdaɘw)i 8PS)|.IݐjQB:xP3 Շ du_, `j9Gͅ,:kȃ|E 0IG-aE0 u0u@!j)(B-PZT(*(A aj(C gHZu<I'IP: _Ik :T:M3aj=L: 13lIgTPLYЀ:Y@9̕t@g hͨ a/٨%]sO|hA梶J 2z!,@cE^ P/t9,F^ JI۠u,E,Up!Ւ}p \z-\ .E.>vXz=\57~77aͨK-pja/*a%6X;:Ե.|ww n uFnF~z?܂ p><ރ` z aIQ;P;Q u5wv u#܃ ށ'~m,.-xuOzԧa-=<I1?;`&< A?A<'Љl u'<lF}~ P_-%}F} ~/{o67agxKҷw`,{BC^vËnvPKz^Fv~~ g~F &삿_Hz~ o /!x _ۨwPCү}%'| |-N~ݨ?G?Jz /B@cT69טϣۜY9?aN?/8nNeN/mN'Is>iNw̜ѿҜ-?9~9?9~ӣ9?=?0θk$*(/DŽ9U۔ RRAe T%BPw$_^.TF*VT-24"3먌X`0Qa$a1 ^olQt:^5jƠK:E{IQk4rUZVQV\䥁/wBiDglQ@-`0Qa$a! b"WE7`8e5zIo z^gCZ r x5oj)0Ԛb+CL^Z[1s8cˆ>`0 FTXl8IIRo'&*JeQV͚lSf-ٚC&dR Q0L&Qe6>U4}V(]Ge J|`DS,VEEI*SّdO'%ZӎVf\l֘BVl؊qʉc:*#xOy`0؊q8 j&(jZm]rÑlKq,V#%9Kd_-KbM*%5&)zqeob+Fɵb}F,2!0 ~΍>=ZVkbTݓ:mTӃT bYm6͆a:]\O$ZϿ+&/e"Fc   <$(įG :=B>.r{6=ÓJǒǕJ bvݮV>q=Mgy0Ȋk0i1y١q؊>rS7yNc`0qz`9>덡Lz^@c8O8gz2x½8tjzd3ٛ`2brJ<1ݟq>e8!0 >`` mڌ!l0F_ JOpʟipfgXL{IMuojNezf!őiẁRq(1yv   $Qt߫2ZFwc+3f )\vf6W̢ _;}n.U7D\ϒbt tFY1y؊8&خ2bAQ`0 FTt= a#Zb"WKFp=xp-ifp/i蛑a0F%Y2<ȇccHL^8OL|'dFqb}F,(+!0 _yIfM;_&[ S4^W4?cXzF|/}2# ]1j J_g0bْCwDs:lN-'B>e6ANUqYAYq^rr99I99fKyo8ҟ7zW4 qLN(N;Ե  $Uv== #E1jTyr{ΨQF:7w O&Նre?(T/İ_}eDei`0 FT{PN3]*_rz D&T;* k'TL(]^00011/W+9 2$oPrFL^׸د2El9/ J_g0b T K#mRkRZ -A}`A:AYf Pc[ CąP @ˤF `0̖k-)p5=×9`?kPvN!yC /(Q48Ge1cϨ7~IMvf}gķˁ6n곯7ZW(-UouuX6cE1MA7V>'n{ <ObtCq wUuw1c<(KJW&wUpګ*[Ѣj f5 ڼK:Hj*ꠠ᠂voeU0[) eT5 N\_UxIl x˃,*A|Ao2¬, nÔۭ .=t+=W%wk{&uiѸp'ԺqkteC}MG">kV5M A;}A>5 Li`r{=RّS.٘p'ߒ=h !ʹDڤ.jD,GD=ۍ#c*g@p|FUM"^\?(0z_ރ__g1+'C {/" |Nq%RyX ׻wL}P0 f9:!MbT%zMT"cj^Q$%^S뭙<]޷5uǕB텑p.h4NjŃ1,A>A=KģR!AcSuHO+u ŵja/<|њP mpl8#= LWfu Ekp*D\>[稥hжF;&ݸC!V6m6Ch /OR4JG5ajb].΂y[LVn8glpƜE_n Q>|zK:3.;uO`h pMBkB[&ܛ{nF-GMw& F MBSW;q3]twUH_σ .Lҗ蟤ELS1ILuA1bj4e.Ds梕MDMNѴ9.3vTzvR ܧWW[_(̡sрoXw-w w ̉;B̉⛳sĜ(uCw.=U0\.3Ћp/]{"KO/vgߏ{lm kն=MڦH[ i mŤlҖEڜ-HSwE l:8"DvI[+i ҖNܤ E=cJJ6/:LGcܣ<=8'lCݍ&H:Bɩb_*-.;p4쀽h<>A;0ځ h3ѶB蝆_-5m&ڕhpQXi`AOKt.ix'btj'1B*-7lRn7oсLEo!R\]NS2+ Ry< L U*RL>i^sf rm%zqͮ\;(f?s>zœNXfusX󴯋`-nq)+dr׹N%pv+tW5W b]γ]!a:]qY;)mԛ*u8 RQ+&*+Kp(fQWjjR)WJeB#QL伨7RQ Wp5φY?k]Dg+2o9 k%>HJC0O) 5_7rr JLp%oUSzLMB?67J>6>;3'#CIl6'X"8\%iG]r.E\đ>ΐG׍>YRE6l(]MުK r;f71_ӬĴ%m V;F6Ds<[UuΑUʆc& -8n[E5tOt6Il1?\ 6U n@֘i[ ;PހRjx69< %%;ғtc+ TEb%EźbN ;,V6FH%K Q !V<Z,GxYY*{mp./КJk. [l+$eA2?C.|>Ŕ'|x30M U]nkmm:\Spa$Yp/ LB"I>+a%:te0 Íd a/8XKHP/$"<- ЀfKR>d;`/E$p+mr3x"x"aN$\rE/'̀yad .Hm\.=KaHA0&xlz)=&ý4F`b</#],d٥H!0G ^˕sh_~)m|D$L$@]J\|߷cajn~QyJOgwoDMZ/țd?3tw+0ٰnGb&d29#ɵJ>eKqUkd?y=y508_ȶnxȈqqJ. r#'MW>9%}M~NKԁ'?)^gһn\^_8eqøb['x;p?=#;,*~/x{gUϚΞMG`=0*75xm׉I {f&Y@'㞼%y[YGҘs0ZN'r6m-t}~)8 gଜZ%.Ƚ}y,~ ?_*k$X/_#g5%IɊՊ͊=&<:wcGL\$Dd a^y&SVX=a5'+{.%JqtlM;9ŽA/<SοP* GaYxz嗸jn;Lhn >޽0YxHp5΃4V!fE>A>ˠNr-=q?ƽ lXde1e3淋׈8.#\!IAE74bZUˋ=pZ}JAּĩd|1WLZYv<`njƃPZ:x<(b,674 lL&o`w8yoznݵKFz4V ,ۂonL* ո0v/UJ%QP(UL!`>$_LI@gJ?$1xb%QULt3ɤ'L#$!a . 8"0r)J"KԨ+7,HȲfuoCYεbS/3% GnM_Nf G.%.U Iִv\يpʰt Ո8㸗6ڙT.L~D-.D%jXX'җat}aN ?RKIFlv #F[`ðoCOpW;{Ni\.V9p,N&N|ȶ:2?h;8T>FWX^T|Ձuo/طy?7iZB|;vtn;E[q!lǵN88@PiA۷(V'.AKWwJGJktOHVswL^|t\Dq+cEpC_tĉv \CދIn߽ʸuz[Bo[x3SWQǘv$ Е.O|b&pKЩ\ ٹ/ ^η.'j a*D‹+1֒Ğy]8x_&T-{( ɞV MG*=| JϡA N(:?G [\$>$U"Gj T\#?M4Zr1G> \=ǭkyqYwl crON^^ -Pfo. /#?*]ć1+&U0i-z$ᄳ&ȑ;3]fT#8lE5Օ>c%q櫬ֵxP'.8e%?wݻoۭnvۭcS(E/hM|N?_K),ΎvX&G9kCxlC@8Uߴi#a c0`KjG[V?3Gov6wntWۧp L9) ܐ XtyS&T8e1å"v{7G2G̡`LߔT >2#Fuf$É Q ccO֗+|7h=}79y:6z6ucQT0SЩ~pb$^0UQNZBq > A`bвϻS? 6w/ʅrxvvtynܴ!s 8NFu(U`5ˤgh7j+{4^% 0% `$S@iC ?˹R 强G ::a:y`B)"F|p#x[ ;r/OVm4yS鶻{' unܬmS0GRz?wqՁye.30åˁ0Ua0q#kԈ1N5*A?: Hϖk3C-.nҘ !F@KRDkoѿ}G_o'E+,1>f%FՇ] Z(Qr3"]T=}Dʝm `%{cqẅ́/[S,9'_4kfuo^zǩhk|ȁY/ypryhЕf9rMD@37v7<Y teȀZ爛̘j+`DĉR0jvoJwvV~FlWȣ4wp% 0*'(6#)GF&hD#P1JF=,Hh|Ia9N.\.rwq劼*˞e. EElD5D5D4L\9Ͼ92:󲞞_e.<(ۀF5fO_ rKFezcNoʫ5Z]?诹BД]yfLs 0T}"e"B3 }FyhrY& #"v|@N&ooH㵼279 :Cy]پXܗFkD 8Rur3nOm:xNr ݕ>3^vuwl;o1-Wں}pC|閹?@=⫮[sY֜k\bY⯲V `0RK)@CR*рDHGJif6&89Ӄ1fnCSKSHh:* F"l`@~eяIiyicSg(_z~A}_dU Yiɱ yM;#4Ϙ|aeERBn YAl}%>Z6ڈD 0~YmOyҴދ%҉ޒ8ۤPk;sR8Ր?!CJ( q eXZw5W9e?zgܼkۭ+Wj6~{X~S=7ӭzÏng-gСGHlDZ,vR ~ "4b~R)B4Ms~:;=ىHO7BBry{ӥ1Gl;DB#rm|mk^j4E$R]ԾUu|*b <х,J uYT%̀XdoJ.g>e9,lHV&+pe&#qWo\ v-^=(}r-*VޒJY"cfF+`BA PQqfh~*ӺT1v>N-v*W|6R; 17p%qQ%đ?)'xxta^h| =Lś;5 K<*>ăL.y(kׇnٚۅg%"|mD++CyHDGr .ԄWXTE(ґetZPW< NS)..5??bٜa<*|mLșY&>=ЛIA]l&Y aJrN8ҌM9I G+2|<AGE ]ZL[4wLn~uS~|ѪcǍ^xC%S]vaߜ,9<噃+tܺ17"Cb`T8 R9{OpY`šAk&pBВf&="=ǵ98F'םFK~yfIIwp;ۊ![8ȃBG 44@iRs!̇ GxwEq:*M*m̚5HQ ʬǩ3)!gs1|(Rz Jt|ۡҿ+/wK}c“k+!~U?'|TOǁ{]0vY|AE\H&pKlv 3 zBڏ?s.Cnp%ˬj.,ɢ,ȼ̋@(@Dz`Ds81pBgףF11*>p 8Z57}SokXt{;H>;xT݃7\=Û?[O]Sz/;~tS teIBOn(H(:5JkMC]2ZSTr7ݞ=%[#tlOx)N# e%Xpo7 T )?ݖg0/ͷާ}"vPöo>>]O=l{\hB}mž,WnlpEE(jI1&mƢ?a/).29U2iN0|$o~,n.%qӎ㳦r:4F-;͒4@cP^0ոVb>+8rGf۔P(<ѡآQTѿ|‚Щ])DRxH~{@Ag=Rs{ooy/D[+ ^;<:t&v'dK}ᦶy(_\w 8<F)dRBnoEl-.Ƞ$4,7M@%DA3;'qвC,0/=zL"?!1dD2rLԲthD609$l1(9D?t[:#SMZ렍BQvS!t2uElR*Pٗe>?BI~Z`{񃐅ѧ N Nd(|3<kCLܹTCTnHhJb!Akz>a6KCKMzz]1}kS㐥B2%T2*MX,EL76ݖ=ͻq{ ,3zҥ3=#`WRT[Kć3Pë_[[o6s7By> h"\aMR +'skw9i}}0B%i,6d!18nٌhgV5iгp,gHPn@Hd%J+eTy>"R26%`մU.V*\2|3q4VaO&!jz/bncM%N3PL L_@=`eCr@VdVXne"ql I2ϙ(M' 18LJ2SY4+"7͜ǹ5nucH%'xOƠ dr$#Z^Wل12N%ȠMF'NVEZ]i'ՊLeV")ǧCK߽K+1t9W6Ӹux ' 7 {4'y^=_ {99?&fOpO[)dm>=?#0)49|a#gD7nBC *)5I4O^~})!XzB82PG0/gT.X [C gPeҫh^Gؖ[鎭w?e_M?v(G~OMpbgXt;Px8mg6+jXψ,$kYF?r a _#`_38529 0sC(Fu쾺k:Fz=פ7NcΞ/qx{9SzxQ)z`F8 jD h4)~">\Sؔ-raIx==^ },0\S}b_x/7`Tl\|S8ʉ*⛸%<_\2K]*Y4JA?t&:EJqUJrEL8W*%4Mkx)J]UţM5'&ߠw,p ,S;Vh756*]wiw^|ck7DF8 Ge!Gs@7I))łOĒ E">ٹpD*[?6+9ˏeI9"B8' Eaw؞.z̳ҰL`㝖{}%}5x-p5N'XF栟+ U@pܠ.d@nNWQ]&Ru'Xn͌Okݩ Z=):+@sQ \讉ʊlƹMqټ~Rʗ{3^_q WO/BkO&4/_{#oj?kOF_yz΍ξw޽jڄw/魦%;ty C p4ٻ 8R=Yn&5GrMF;ZI4%t>1۷-mѼo) QoˣRs.IEDo'D'Nr>9ɉMXH2}L"_9X7ҿ sHҡφ:ҡ=.y:Lh8xIԳOT<4;}?_t+:νqwcǗ܄s^}!΍+!O #ytv$daǝǝze%'l p?TLu֢TO֫'LK%lX9bOm6S<, <6x՗92Cd,M˸YncA !OBRhpP8%oUfnDt8Z `W 0D&w!Hl;-,IAg)V͂Ns(Đ\׺A$no˾M<C+^z$Q4cХ4YbLhiUj8Lx*u0RJJ-VxK[.K FG`R3xA o$NK ] t:[Sr"~ y0FA#ހ P5t25ݣiaSWp4Ie26 CבC6|92 6 =& /gT(X tw݁Fy'ȥ?TnoBh:v0s)& ;]A@1w$?ƾ>s}Ζ$6&FsQمk(*l jxUpR[ֶR\j ּJi]xbQZAq39Nsl |u `ȯP _,voz)Voo [m~/GH JbHyibG#NZ (*74CPQ|ð޹? r3/eXTrVn aF(a &̐kSl]'f[K[,0I0.k/'gqUÑDpe{;xz.+To$qqG#2FˣmHEV4Zh|0Td4gPi'ɀ3O|%"'PU Wy$Чj 38 T5:Gnнt;m'9R ` l[XDۉ64 jvޮeSQE?IjVغm|HZC(,l(0 'S Y45bqⱬ4ZnYA"eM4F2eTJQE**i%őP\ij,>ZLx2a9: 0{OQt)B#' HA G[8:<'@^{+P2a%Wrz\~ĪU7ݞOgbT%/pjDU*: 4DGWmST4D95PY߫ Ux)|K{+8\)\8B7qeYnطMţk3Y&[3U3MhM榗)k7oofCFQ؃KkVX֬=z5vYZ5ūWPz :10=53A5-FGO'EHp;Bkk)9Uı}ƚI=$޸%% Qs^hI,\f1"s⽿ e d\\ YwNJkr99i$'ȅHO8` گ(%8i[6ǎhPTx~J(ē*#E[q@g*܂!?hAʼnD7z}#oU? n=wR%tӁ{y~!ڥ/,1x*/s_=~xF) .ju?ֹv̀'}Pp2fT5󪖋#^4yd,xi.vIlQ|]k5"/ mz[H0_Q)xS'r>+'EGpkfa/'sCEdRR ɡ#ϔ;ee]DG吷vB,씻2. pցZ,Oy 0(/ IX\ UVZAtgons+/σ?\/.{ݝC-ys??yu:wZU&O ӽ(ݡ]<)Ɗ|(@ z\=O8׼'^76p4RT@AThl(\],R;MqCQHk ;tZ8 $k6PG(@u:c'5(U`-C3$Bd2:HAo! ?'rcﲗ{BIOO,.0lv'[+ aC2覭E_P_?o17 ޵Wo~2:o5f.Lu6JQSjFLe+ir8-^dm>F,/#\F`RlX8\Bޠ> 4hM6td2oR$i9Tz00si":ia1ɢM`M875\П1DёvMG o c_+0Ll_1t;[~Ι?ݞKt/]5x}aP;3Zo{l,Hf;N(jcĩlzP- 7$<*j0td5ņY"bIkkc+tȠ@Wm{B#5t0360hLyoփͻA_t7bEuf HpR|ve6:#;LAR~I#2"\3,>-=.wtс>\GW3 `b/!(!Uh}yk{@}Cp2tڽ짻@9{T?c$6<7!/C"dߥl:~^~B*DJuK'̄|TF"A=&L} Qz?N1 d[{3(v,W@U6d!Dp _4BL]0]qDZz/ɉ<'(erz4zjFv,4`5jvȝ.:xe?}c^fϥ3{9".O@:3e)p?'jrMYV#O㯔oH hj*..u5j!%CkF#JWM)R555* rn2Jb$dz [m`6ӥ1E RuR*:`vvԠ)Sk[[ܚM.$~5,\B5cHUxU}ޫ3qYoA =e2>:mz8]7vsoNpqQ` vEo@VuB_z9.힐mM[7pox|m+2215x-Ïc߶{_{_Z1} "ROSOw yglTL?J_ GAB$G? Il'FDo.)~,/0; Uj<̖̐ \ 2AO4}Li!{^R{Ʊ2zm?27 1KHB>!I⬗Xi|J(PdVSȨ] R,3e۵tބ4mYڕ-{/9WC GX<)z#b(Ec EP1ǧXYl`0=aN2btaXNe!HS٘gc {% 6" !3^-&L*ն#MЬ|S~rO'Fr3aSLemey 룀*Cگ0&+ e:mYu2rLcӀȣDA&9\L2_,ض]2U+<F:qP`y[kn&z`HQ j|r57V 7Uk77 hwf臙g77 +ߘ uӸ"˞hPnKXN LK>HnU`d:[,y'#ð D.KC'e\9PYmQ[VJU}\y;}FX41#XQR.f 2xa&,S tGd ^IdKcZ 9E)L A)BN4 ER*-9iiw>@ᩝŻ8L9<D%cER1M nG GkPTԄۊ09m-^`a\o϶BgħNBN[ß Ai~9`bŶ~W[A[~M_:L RY(x|;xw}l/͂[Wa~%4 u2y qRh8eZ$KEl'2țKv<~'(YOf}Q?oڍ/+l6|=Eg]ya-$3sg))pPLey=UggfRQWX}=(CфHe1.C pe!Hu )B~LK3ɐФLӑO*Iw(|&$yqc&,pn(Ժ(]]MvQJFIŶD稂8Z@+KShbE߳?q[O9~\L.>;;9ѱe7Fl4++fXjP{ 2C6'5/OԾoe3.^+g])d5]{\k٘{n[bOs}%ns|,F $}16!BGB!&!5B1j 8+Db.D[2hK&F g&іL-tWqeLJEp:BB[B=!&Dú@.1p.Ƴn7&}? O GӤXP9Sh(79- t򄌋:&RP~"^3`H]F S -w3\sӂa#Ug*U* ҬZO.x>_qċ֮ٶ۠T<,ܾ/ ~wo\IТu΃qq1`[0Rʊ]R(.!4ڍ1hp2Þm)shO]ȻGG$z2&mL1cL7_ ` C\0ɔN!9LSbD #|IiU0ux_RPnʍFr(lP]%f侂S EIڍxρsӲzf[sW8ǞΟYz=o֛V8*?>dhP10yPiX(\s9<6xC1eŗ.NM^>: )EȨJ:h8BC?Qk? ZU;uDz:"> B'@N,J]3>x%$dAnuE[͝j``z8n8U~t+{:ʕM-}:? !\Jz߾n$H*&sa (c2̥dfDSQJIPXNBi|g}޿BGt^D&\ 5rF۩ŸOM2X2ŸU_QBqSm/«LY^#=P WTx;E/H/=ap0Tȍw%YFH_K$:q:zzgRЃK?.A8Pրn:-m}ݝ4nAq.WoѓSqAq)7 4W&XG{:,JP%EAe(qi&Jō"gu@8իWSVW ! ߣ~ {WZQ[ ^nnQn=mؼų/,ٳlnzmECSu\q0JRӅW9oWRy{W?b]yĉ^Q Zo`ȉfB҉`IG_x|(IGN t&5!RgUjf%U3+43#Dn;:,a(C,.P@N4rn+UTX.ezi5RVJq sr"KkZGO9C)jUztzOD:KjH!*(URRB9:V0"Uic8 R:!Sćp y"cB4tۗޗj /)QD\2+I҉9^i PJqܿ;,9b:TXND¹\[$thjW4!cVG: Wo{4z1S놅S{0rw!B-#S}\IhTKP_tiZZt}ɤhp: U! @FbLC\Gg↑IY 'W1DA5S%1U&m&v^U00%#Vήx2pbbdQˠ| Qe)ZHko..Gr?N+_4XW铬y,V~"[i;+Vf%UVhzUJ5X˅5c3YIAvk`>3ϬS1&z5 Υ%-Om3e 8UT}$WSIY.)$i9\egJ ]p]}mT[c:~yV$(aȿRYF;s$]KnB7-+~5$甪UUP?z9{BA[g!?Maӱt\+O*m:UZ8RE ;0oNu,40qTG6X042gvӾsHHw-Y[?=3kF1|eP#(=BizB:EudҽVDL#[uvP7V;n'yl:v)$^ Wfxpj,RwKHP?٤XKkf{q}E;7^zO>!q:%c/WFѿWj?3_j5Z])k9vGB+.u:Zm]X8f:=tm^nL'=xoK e ^.*vF7|[I c,(-ɊNL+M&xiCt]XMj?>ԘV7#^Rw6iͷ*Ot$Hiu9c QkӑÑоH'e#]_ĂX?M,ю $*f | !BP*!^{ܔ+Jߨ`k ̵nᖩo ܭg>`=j+.hT'Ǣ~~NᾯV_S+(r}%]A0%K( |2.s Wc0 wh.7͖ckW-huKvꠔl9 eҢ^R-rZ l&V!Lj&/;"%OBƩaLNDB 2B8q(hKW2vMy(8%} Y!!+Ț^!s+qC"> @J;4rV/xp4+?Xri <=tep?lu2r*9JoBqD4ל1hP+Z# h0F- 0Nzx.Kn^p FB9bV'cke2W>(C4l%(HR @Ak4DZr YӚޅC{ ^EQa+֗4@i6SNj,'%t;)B-z)"n,)nu a8Rc\酚kmF1$U\;{Kt]xT-:ZI^>ڦINwE^mv]R0  s,u+%RWo2B[+'p?[q]ĩFP$~l8DMZF>,~QWgdo^ wȂ!;h)"M11لl6l"RH}H1E"4"*PBJEQ*"*jܻjO>}~2{̙s̽w;q>k7o(u,3Yy Ŵ$;qV*KHK]^-ucnT:iе;DY6BmWmc%t/#+ 31wp'"uƻ.tkկ$~qJ=)?pKu`|/[Z@=CƦȺ$$֧?4fШ6.mB %%g}5dW8{ޢG{[o}E}[fl^ԮcԤ/F{Ygٿ޶A6ذ~x/8U>rt]<~2ϰO@_~A66/Soԡ۞.]Y-s/usvVQ6VZ6̝V!lv;'sq:|'^IEI I#I~I|}u_l_?s|k5$sa$$$-xSǙGYfgH/kv4!9+>mv^c>eijx֏߷0P?<}K~̻[o?PG%}}=+/z0K~5dްc46lrYSϻRjgLqPYXLeɜ9X2ZRgߗķ۷'MMI|}M_j_}v_/w'󹎹 FɿJ1`x9~e X|B{]}aIs9ײ&V}P)KT'E/NUQ'S6nv4l@W_?n7D*sYH}zc\n1RzY\ţS(g~o"|PmY_x?`3&[69z;իq, d[CTԏ1,lK{Wv Ffn#z__waMm)mD}&hHIQo 4wq;01}l 8MHٔ=fʾyp).Qό/T=<+Po]%_/X0.eF؝O,K'~ն\|z"*ng͵y _qê>+<ø}'.?첱˛IYgV}}{N^k{~ƗSJUҀ> ?ʹtC >a_;_g<'92}{i_#7q8/r[iJ|9]NӾxr.r.r.r t9]NW?:ffii^||,ɔR*iOEUމ_嫜_SjTIA`O&).8ATE8[RNY3kہr^E. J<;\RRTg50V3UNs_fi&΍AK5 *Kz-;W(]y\jJ'Yj)$}lUd,oXlS.ƥJoiy,yK[PYLEW-![(4Q(+zٵwJ/_̓/#u#z]#9s,_dHXPӨF^f?/y\yQ8#]Jۅlʑ5G1kT W5.+w}j]ԸTUz 9 ek\U bW_\V?UWR"f9bf^]c3ƹͨ*5U+re/ntͪ*-w wͩ+uͬ*7 s.J]se9q(w]еl(wй6 Թʪ|58Q\[PY3(\r@U҄fY+EW>]Y4^(ʪҚ`(QW[T5UkaL_ G)فl!j5AU%P@_^kk˾lbs~FT`UVP<ߗ-N;"U8>V3sQݫ===G{8JVZ"'/U%iJmkmDpc&9f^ l;n̗W Z ސW?]Pba:f'4?=8v ㏾nf9ಞd@q}iqӷ_!9|??>S h]iIkO/іך i5l#yWh A[pN5v:1-Ɛ&ƊYz1;:է3gssyz>[\zxH!q}#W[i%iǀw9!츙4-αıs9.^b1,rn#<؉'5[ow> s?3??#q NS;:E9?v~ w~xwhg3>и@(.X\޶Y>_Y޴im(9(.v"p/t4!"_X8~|c?^ M81xO g߀q YKq1q={qY㉥uD\MT/O3%~*)baN O焹a lCj6gccIs[XD2_K^ת< QʗSV_0.]LWyʻ59JU ݅|R-u$ ;zR/M}/\q_* .zXUfVZZO-0Vڏg?q:E٘zAlaY.+`~6lÞbH&[FY 舲tY?e΅vYNL7L3.صr )E6.˭_f@ 2?(7eͲ<,+)>[Uz䪼jh;TlUR}}~Wh~o5,6fYuFM+ ԭXKީAYկ4O9BS,2,gMBPo'SLFlV|l){s>|_ [?@4P{N;kD/[o[nd{X!ݥW>}~\d@O eSLÎbČɎYs1vLtgssss1+q79wo\K܎?]wďį(h  !ޜ] cWOAWs 㱠gj0F=<'w{ro5#'wtlUm.,%ޕM#2M0=8)WSjOɽ='w䮞;zrNɽ8gJQx.&2'wl-[J= %ܳ'w:qFMU-}|esX"srdro_Q}X=9#'nWqhj..Wpʝ7Q1WJ#8tVn|HM Z9~[UOP{ {#~ So8r@CÆ_f!M_Fty! ^ H}Q2xWwO)<o6^腎^YxWNe/QS0>8<8Fo(FS[rZ\?pQjD4,pz$pV8{R@.Ph0hh/SO@>_lLQ~F̥ R1hy Z Hh_1X4Ohϓ3ajj_.plXg5` 6i"m_ >_i7k򫌿H;XUpwk,W]!Fxb+$6BF>1A!5{[Wwu4+$[DhuO$O0<"ZDҋhuR ZDhuhy-A8U 2w~cH4z9p#ma.Ry#v(_>ÿCp(*6#Jv=Pw^rxji8LH SU3hق sk!$nP9ht-[$pd+ ;JJ+BJ#gAS*HhK]@M3qFԈ^*>ME]H=B*.U*A^U\2r!h u>FÞ^/mo>,fZg޹ iӛO^e3䰬epFz`Whk}Ӵ䙧zN1V3|iy:u'](g&f_mG,[܂ +KònXU4YТz0fވ&\-:Q 3T${T<4"w@7C͖elpR EŕK <72P9*nE |Uf «( 9ﰎE 8cYŲPjNv=iE8_je(Q_$c e5h>pJj-tXVmU=OdWzEf+"SܗD\ASV8jk@oWE:ЂS~AG= ̨kWK<ڰ<يՖ9ʒ-1\QkF%[UzOu%a잯U){VȜVq5ִ5p&s48GVXkagӘ3fKiF+>[L#vĖmWJ7YG j0լT֎ߺuhDY׹a)RW_=%pH{"'4dH\cqO<N)7YH]߀dcQ?kJ <pQO 4wi0{ޛϦoOy9@dP/ 6PMP:PN倦f5fàĂQgžMLaoNEwSaÿC% F;A}[پm v >?ŷ??u٨6WQ//QGyeg7GByzvܿ]J/Y?>E+:v}x0렷 PEnsWc=7A] Tڐ%mA; PecC$R~KFdS*nou_=eG' -hd;;h-Z{U}z~&37*w[ ]'I$W7ܦF) +tI!^6Yq Cyf{UzUy =Pގkьؐ1P<꯮_ RǕ7 :}\͗郆R1!kc/21w*pe _\' ۭW<9  ͔QsR||U5,VbR̓H?Y:(#kCtZ1(>ɘS1e'R9%C}Z>ӌWf&1'gէWO }4zh)ĵZҴdӆjCɮ ׆Cmh#FS#CU!k?~BI*m5O3gݣC.>>\h/i ~i~MõGG(]{T{Fh~Ccc4R[N~hkX ==IgghvP;L6e*}G;_tޤYi4h{ڇ'a4Od*SS4tZ fT+fT'9"E# ׇ=]O =.qgWg$^0M/ M/ҋK㮱*9z 3t1|Թu1pz6zކp>Fcx#F"s]l$F7a`F/h14bWT6H3pc1C!l12t#42,6ʘddol1ǘî7r\63\#gF!(2XQb0Qf1Qax<ڨfFQn2jZVDO;q?Z^B'.ބ2 -ZZiA(m ˷vZAOϠ@oAm(?}αʝ<}{y;bAn}|E P OzŠۨ7M)4OFEV:ڈg՝#tޢtX<1l Mg׼y'S 3c\%{&{r?dL:>:>>ۓG6 4pG(dؐOClz }}nw^o& 7wzb40=+Kdl_ÈJG%Q qT8*y"R;!J%RO)S )E"vKALP6h h:h(?T@ A7U♲ϓxsd)NeVƻjw^.tߌ|{9{Q0n*gWI$"1B~D _ؔ/t _LGHxzυ_(=R t~r!{bMtrc?apCWɿB.D$理sM_;MN z. `{ kzAɠ^ěk^( '&riͶx@ļڈc]ƪ%h꺁$f{E,Jǀ0[AS:;ua jcK^\uU_ \?wG!e^LeDޭf]{M駎w}#[eqߒВyv/y803dG i݁Mqփ"M -yI^ZJ`Q+KG򿎶{X |NIE/o_mz,Ьn 7k`Eӹ%w4]hXA/MPsMS[kX6 lh؃<+OXN!yjH@Q=P晁~NRsBC= γy |64&h(LȧBحyQ%_mq) B3ojV4B~GpBBs|Zh=7-I/[m[棁=-'+ojcjc}Y0& x BZa lB8x ! 8z=be\%xX/Eye80.R.9Wݢ_2:u=}s9s5{X)ee ,<6J횂Q4TC3cѸL<:Sݭw꘱]hau.Y{O߁VK^s{6-#1om2I f0o,mٌx-9窗uYk-ZS[ Ϸu wvo5cMu u۟w_{a̿kIߺi=o:i_)7Q=6]?waw,D>뎇Qy̦t']SH]ɰa,̟.5D"DS؛F̎ǶlWx㷭J:m W7qR-qz.3ye ZRۋ{\.Oʖ ڥޫDhy9ٲu̔Ԟ;]kTQ1޴qW=(sʞ+ڞc]H xoA$/Ba9彍wF׃7zZWwר5}>9dqd Ȅ)v^Ou\tg3##\㪻_.;nZB-7gݜsL+i O7:=u}`[@_wcX]hKXO<3[`=yӻlp{WE02JB$Ax;\ z_qa̻px_ HyJh_3z%D{m)/]KcaKYC8ew32_rLX{}j_&-iGK#տ1i0"Ϲ;&gLJ~Kn{d˓v8-Xz4nkԠ6h4XNaEÚjW޴{|f3{McOIޞoxU) e{猽 Vzmll`髳 8o0=hÙ=kA9)pUҲx}ZsR:70:O_Wk|.e~ Zd}ƶ.|o}7^냲wR~ DuȐ>3{Ħqu8b}CX6ߐ#avhT} mupv;Lti1;Ц x :s,󭛝iSzAxoe]N k)auk~t(ud q$/ JW!k]j9qk*_qBZ سا et?]m=wECJ7YgaO_x]L3Fd 8.tA9ȱtG##s4ۥ7>FOSy\\4|qsNDS >5\ 4Ǘ@*1' ts>kHu{w5\Xڣ;_fNaxW;7`=܂Elo: @khwzr;g)kܰK&?si YIwq}ˣu|֡*h1w/1c{j@lUo&nMvOwȭmxwGGpUå]莕Wwy{hk{ɿZ^/w[5j +Z zQ9umObkCGߦ]4;sW$jҥhҕ"!N+v;Hט/4 ]jA2ӕk+ؕKztDv:|Ӊ *oԑܥEл־u׉+]fT޿vjZ Y:ؑ:ԑyu[}됈:d[Ro&7 蛆rEޓwз-ʨE吪Q$}a\NHaH'^Gj2H#1!2LnZS2A> W4Y"KKY%vA>"FE[rܒK~E%h6?&ELF\'b6C"b%$#6|fo޷%I)%f/JK)ˤoR$eiɐCq٫E/ s@Ga']ŇˊVl0_QCd9syUc>, >)Mo$vD;N5iOϴϵ/n +gcx6Me3?:Dk #}GRa0D2ag'{RFK"﹤1ST9cbj0I,=6m2VigH=w:IRK|Oj ߈6zmIۢi]ZO{E;kG;{Ccvu&KX)ͪD6MgVlTl[ֲ3Y`b^ Kv*[}a;Z]b}^MLYidR++ʊdE˲25We':Y ^V4fvp ppiUvоb#Y%&jfyl![gP4ulĶXc/>(7ʎ.{G>Џ|wߕ[ۦ!j# O~ U @RVIʪeդP k Lj$z=7EdT%I@onɭQ5>teUq2L 1ɫrM' t)>(e 4bSE<5#5B?q<`<Ǯ:b.o7ĺu}m=iʠ~i4 .腺yWn1ňD[tCa? c !m,4^T 6^=bZ7A 06| # mB.l^Seedb[u I"P/1+m7MƩ+9)l>n96F~]KTۥ!}o,1ijkPZ,sLB~dZ0]L^2] ڈM׫V͚fp}#LՑTPW+MQFuA0^uՙd#,1|Ǩ13g0K)Xa^ 'b c1aWOи#8Oц{ak;a٬{:sMfuu9vh3 K⽧Ϭ~+3qP=d6as]77U}R}l1}Տ͗WW_C՛>aO.O>V/~.(\DXrQ,a;~.ީ ڐXº [G(R{DupI! gx2|_ EN\ s"#6a5ׁ_#5vDybO 1x.d~55㈯'\i}8P\ȇuO,x&}ko^FMV: QB.2\9̉c5*yMQUlMqGj*2jkjS51bkp8[|hCk^Sk65.^='$ ?W}+{ss)/$} e}2G }kEGd+\os"{ȞL|.s\dO>Nn<=0LSa5RcԜk5 m@3梦WsY#j™뚛X okRyyi4Keͪ&`MJ{$ !Jģ$6Wpkam0#jGBK2w(oR0CRϫIT5ȅ lΛUfO7 DO|&#$G/\'D:$%e$z|4}rC̙I/IpH?$JbIu{{r,TPT|||5W司5.S9e3.K.n,kҋmq\^ WF!z;?XT4!|^wA\D*A~CΆRАpuU%,/pk(nz5AB| SޠM+_没nQ1qCp&|˗ nkEhEH~7MsJF! P"ԫ l )Wx t n4A!cu*.ւ@ ZQ~\ A5 ݈n,hw#O7yM,u1?*zeR]PCTԅG]NSܢ+*_֕t34N|[W Nq>Y:s:zR!v rauݺ+1lg`d3\1 J8Wa&`6" C\a3WGc'̀績99" `ݭclQ3-E/[h^Z&=%J!v >G??/4eO~Um=b)"e" J}!LGhѤ԰:2!a C9`dCPbsѬpܠ6 'ʷ f%Ct{L7˸+|A]ѽmKE[WLr}>^HٛTD}F[D[J# "]:, y܆H׽s9n}HciC;ם7JzMџ2^ L}/dW"f weUeb5f\Q (< cf< oS X< ~+ԯ7APXӛ^ hpOsvX.1ӸuIzıx4d6ZD~b"`Z ˼.W暉\Wx z>v  Q׏ aQ~l̡̉`C8:Ml .R`n(YU5W qw,#ǔ GCdV~. Xv^X`!߯$_ǎO.@ߧIyƛP ku{jqnZ7ܻnjQ.ڵMG,5{Vω$ǁupl)W^ 1_YGC'\1>ql}GO,ݯyEh: QB.* & T% _MM-s)O%a)iY9y'/72<mލaM*`\`1g +EhC@jH2^!To|~$~$~DCR@r~ xJyw -Ku&M&Vf!2!2Sydx#;h[̂R~97|2 _r7c_rG_ro$$/߆I߀Qӯd/dү|~%\ !c;:G o/Gx{W^{{š񌈌Hx P( 1#$r; IsL%DB!ȇ!>2 WfڥvIبFM//$oG@ {ID$CZ8M$',kFZ$U\ur0`s,=XFe\_2?f~ c) 0(gmMZ DE9规wAr>;AC${1;wJkĠ֫SaVz4Ml!qR1QP/"OmV?E~ m^Tש_`m uڪԛD@7p)"ʤh>, "& Nu\W_:kԅ`{t>*'kHTvZ9IYSԃC+҃ja Ét`~AKU|0TѠh rſ& 7$Q(C(l ;cX"$&6n!i n8 xGji.Vw蔅c:҆ԂԂ )i:Py2eΡx6T4}bgϤ$ P6ʦ֧]33)3Zm&& =n'&'&$&IܕĄT6i@cԓA2S/"l" RٴA,؁)/:VBAӆR3p69Us C@:F}Sσ@;a~hט֗ZAߔt8wU12?$ G̏HFQPMf$~,>j=jڈ foF9 X LcRKPg>5mFq !Er:OBD3t:~OWN#H..I#= "Fb$PRަzӱSj-!S"^oq G2;/1_ʵkzY-kY~ܯaqHbC7k~P:{-}7|#g4y+A$!"̅ D4o0Bɔ CA |Dt4{ \&*ƺJDfbY52KRr6&\9#PPWy½I,xX$"pHb/heX]~^gG܏6"X?fב2Z." l< 9,Xtoh Jr_fFb3 bj;EUIi'IkKhH4슅MA/3`],Z!(60.sX/V&jl+Xk.PgUuz{Er/@[ rOZXY)[n ĺzM{KyxUqV!/F6s;rYsbYg``$\AZHւ;:f$ПT}y|\0V@ЎJQu$6$" "ggy8=8WE g <CzĎ2{vq{Cg;qYMQJ <+hRIuHҺl|xDN. 96rVXTokuKfb)%/3ceM&:h R>1&9x䎣*[~Zݭ tJЯ;A;eƬsլoٳKl[.&G9݌ReCֽ l@Y OLYcq^9 z nǹ`6{0>쐳}`GV `7ѷ i+*z{ _qֆK0VT7S \$^lG~  Թ 4E||,u/ #ŒwuKb^|]W+F(׻XumX{̉0&E)noƬ +(U,^.QD,YkZM$JU_NJ5ֺZ^w+\x.H%m{-(#t:M3} w |  T*O_`!}`5,߇>:ɏf!IRxqK@C6G1D(ħDyW?&4@gpKO C!H: 㕝eigMw:5Uƾ{{nG?,d!AE4 /:ONG#YH@r^(|p`:. dv\?խiMJP&o2rM#y&v)%i`1f<\= >rmK_/>p20wϱi} kh]&γn L"'p=E6΋:pW]Zxc` =; =z`Wpp,x;<Ho7E2>DBk9$±f` |oZ]*@wi`_$m$X3Fh |k@7|J:ZK_ s7[ W#`KFtFq4$:\.YظN\ ._Qԝx7)Vn\K~ꑯqdŮ,A2UH! V;d㬗 G0GI=Z:,A/ eqtƭ˻V{5yla[Y zdTz{nI_/>.zײ'nϘ6#_,e"A0~j y Ϧ߅bs OqMh;M\`ip8 &#,8 b85_|ѓ‰BfG}'0v]']/"ah./D'GDӿ_|1Fwf0KkQx)Xx.o`Y x`Ik˽ĎIF5M(D>0gnmI_ݮ<.~&%G6A+<;sz+=d!uI.> +h]bò|b> ǹjt]Q=[ԩ"ޫf:Gp$`bj4f i%NG w`7/eP08+z,ke4e9+ZΆh=JBa+6kȎ`;GkI6~H2L䋱\༁`=uWֹM5y9'w˓%buCވK>I[1d-k}e[1I&ڙ^V [ZPkb<率ss5=d$ D{ħx &^ț008m1{-FY4?Շ`Er]3mrQuHB|SЯ h.# I:IE!_#9^@<qxFo4-ƹ;Q~VGx|; V\>uz!9{i3AЯgtEC!{?d8qY&u-6?#UTr\O(jLx7ZQohҺ_DaGE~;}䪥yRz| ?1k_S_z?;هuz $y`]f&(rC xL֫e}܈ Vc< Bo8+>z|.x:K`Wqos8'a:sqUͧS;By Mm6wWm6^{FS#wɠ 5<}`ogѾ㸳nh6&㦂yQ0;׏{{Fx"UD,o +",t"V+DA0EŴ]7m!;߁vzi(:iwE\l tQMAZF=> RTp#q1/_#xF.IR|pTP_Ck}xFs|pC$W>h֍< YE<1x=ί]Tss]9 ta)G.Ὁ鬁Ovq9>fK9+-hRgG~ލH2KptiJM4xĉ5ۚTRy\P&a)!iesuLPs y!x܍V,*x.%^6yzqWͷ%=v<#‰7ُݫT@[RS]z +_ ʻ5Jޓ*CUw"7T1ReTqJ~k-T%UiUV?˗ҢR,&qOJ]fbݏڌ*aj8烋 V8~|}#[ඁÇ]>x:~7w:}ooc YSapJF_YL}a/0 , N/0*USelLRT]Qyj_U %)ṉb kFYJ~3Q0iko,mGt<莥c<{,pvo}YwE?B' "gG}|oO UuT{U F s3@-VZzGPg: O*___qE|=Ǖq\=.7p\qeuo(7ٟVX79.o"[W߶+؟VZw9.o"ǕmW߷+Owp\qe|UV{ԸG>ʗ?<'3"|lY$ϧ_G~9`CG>H2H<0 G#4SLJM蠺PcՔ@z,TOGR=M=-=Dlf56cOԈLԈNFt25SK|jDR#XV,.`*xzW{]f0B_ iG߮<;XkbSokŚy.qFߠDwў!2K]o}u ^}h{9aXF^,;<6&;雭ga[R쭟es`;RlgJ0Yއ½cgQJkOi3d$Oz2?/tdLOR>M)v ء,Xܮ˫ ;{YF̳k9{zγ+oyV+MOZ>jۙZ9UW_T=uT} *43uiLQכm*ij`#jhښ)U\u&96zz&6zn6쎦b[LWH3R0hckF8u ɪ)vyT[}U;3T{Ϩ;l$Rl4Vwڈ:ڨ9Ou9_m#tʵQl#ubuF*Fk֬U$zol1EuqU;տؘޭzG~X}@1~Xq~L5_T?sڜV9sN 0%5|gSl"Slhͅb!] 9QR yqzFo\\F!+H)5h-lQclS7R JqAàdjͦ걠iTM դ 'Qۂ6ú)6z?}>jj'_IEMK5Udk鯩6<@ͰYXB=ci35feǰJXE՟lRslQLlTaR l\8lmVꅰmV- ;"ѝԋ6lfwS/b3Zlkgs}3j֗i'g^_?Tzޣ?}LeSW_2uM}`:.nz>f33ʌ1 fYaVXo^7;f١>2G9k.oeSxAWCpT Mzha ˆJaFX3 oo o[-;»ܰkxo# kͧ)jZjQ4̧jU@STbT4*U:)"""""]EE*ME*CE*KEt <Z*R*REjQ%jQejQjQULuu:uu&uWԙZԙԙ:ԙԙzԙԙLuT,*T$!*@6&*@c*@*@S*TfT[ͩ-9T[QZRZQZSPnA@ Б pnr9,Lw!s!s&s![%[#[%[{B$['[{>f_rٟ@n$7Hn"77ީ?qnb/RWR={]^W[~}gQvֆ@>~k{ RX)f=SٸKvvQ)vP bò'EWv7Lx QM/^߼1ɻ*z7'z^>{}q뇰/R˟Yh{cF.Muw^WћREY\rMn;ⱸ`B;v/k,%WAZ &w'3!ʸJݥzjS}_/es>}+>Yt͉;|lVJ7HN{&' 󼴬WT7|ve;a '?LC=?uzhФMw?t~#2ZՠJS[?b! %J.S_sqC# 8drœ7%7A7hhld&WHPƻs2ɫD_?|!GnJ%K0^&۷Cy`ij$Ue{bftjykrBzxjc1XIeiބXL{~j&5ï{xӏUsۜ3m Ik6Ǝۮ{C7.yDU₯ר֚{=/l_^׍Un֤TCXâm_~-/~`IW]\?k/wT%U-_u^de&ke{==߼9ËO^yKak;u.ݏ,Y֮͟iJ7Wscn[L==WސM_^4rrw2֝ɴ aCט EMӸRvn`w-E￐?oJ7͚Mjwo{9,)c,&!YY%k+ݷ:νU֢V'ӥ4[blZwl8ba#=+K;k2964~)+k\9|rbOOXxT#wc~(U:˜;{mj;l!^DMh HABhJ A#"RT6t5o޸?wݽ9sWRȁ;7+ 90&ZvF4(,X;'+3Ťhće}ԹUک56FV _ayN5q/54?L+23kuǘRgbN4XEӖ+g"hgz٪7:gr?gٝ=_yʿ j@8v+9vq{xle=9i·#~ =m5J*S!S Q^ޟPt0X_@xd )( ʀ"l`Ӏ 1Rw MqʈBV{}5 5ׅeKbbE:N犘#~m}ONc'C_.ZgY3FB0I:h*{? ) sjj<̔O> F܋A[%ov0f~85sH_.m8`Y60Y + FzBW)Y/j]lff˱}nJ>js(8K˵ 0-cW@sLa`H1!D hYfϠuzPdh3wog{o̿u+ժiڥ&UC5LF̫ +.8FV7~jU`ݹ}b.v,x/RPP}tldta>#%ə`KoHnC ة Hfx>*8x A<Ë p'd|N|R "'1X$ix",Q !vsT%K֑Q|JziZgDy'݈CvX>,)$ h(}ՒK ҁ aA]H[%' .7%fP0a_ժQImVAGqϣ.T3U(qf~[#\=)uʽtE.謹9+0{vFBOG(4Q/6V苾$;@}Иҕ2.t}fqiWEQjau>W(BѤb x38­ 9;RC`:1՛!5aʀeT>Wۇ-O+sGߤzތV;6,QlvD{Th 2>#l`[8y'l1 IVCrd4r[h·LWO#1@qsBkkrdd9-)9M- qNI 5)~36o"UHĹu(c5I8gY&Ra&ir!3d{D׼RyD^Zi9OF8 run/&H[R2*RڕR 8Wv7Ԃm/(]3_|B+T#/ \KY+bq.:-<#755mNW(T]6 U0+8iNUUbõJn *[tHYu[/A<{'sxs y=u1.ZvMg@퀅y^O:$cx5[R+CmVoOr˜B}Q úЛuO QA)wRY:bp<$L$0[o6_2q[ӲQwb3;#N>PڕvQ@gಣ #0τK@ G} ˡ/كپړ=;,pῌԀ_0X{/ߑ Q%fv%If3h-XFYzMt ҺM S D΅6&}6o.XXl6:又nHU |ׅLutL> stream x|@\U93f30$!@ LBB&Tf DcbnlQWc h5ֵkYꮮ5ݵwN$Y-ϙy{{9E3Ɯؔƚ1:bSgٌ3*&/|xc'݇>)|Ęqɍlc,,ՍcS&Xɍyÿypזe{ c,;[ ^y9ƚ:H^йpW_[U0uu'Kf^,.ݸ`!Wu)wxE0Xoӿg,Zf<͘RX:V-E1v L];T/b,jYδ܌kѾ=[udkuEuXNxEy窎Pz+lL6Og%K42pN|w9;#]F2QB;=eiw~+#~I),t"4,u0ժ|#vFTbYvŒLE(S[L[ 7z<`Z0~(1Sh3Kk I}g3N=]!θcs%sa;/]L?;V~/cUXCoL=? kXz,i 4r%7d{v?sj?Cv}Ϻvi 4@Hi 4@Hi 4ҿ9a$Rf:tFz6c-fKY'[ֳlW_ފCjc l9[uRqJ̠ص? I}mxpRbC~Z^6K'T>sR[Y~GZO7)ῑSO'1;=SЮ?YW݄a`4W6[0拫6c0Y џugR?bΙ=kfsS`ZԆ)'OP]UYQ^6_Z2nEF3(+3ÛNumV)hGTJoU'ey'Lyo+ -ALU zZjckQsq5T&{Ʋ9J'Tg64A[mk^Ӻ,-cE&- -< *)J[wHqIq{E_Jq7I[A른Nk%5R\-/J+BR\.eR\*%R\,).B).|)Γ\)Αl)8K38Cӥ8M pppppppppppppppppUR˰˰˰hhhhhhhhhQs(č9m)Ѡ;PrN$D12!RZOh-jUd\J)u ZNU-%:!\ ZBhB Pډڈ#KPn6,DDMD35M%j B4hQ=D:ڐTC4!UU\uʐk"S;?Q)+!G4j!M͋F$AP/ÉQgyDC].Qh`ADuQ&A%JӈgD}BeD>> DK'ަ)ޤA׉^#z2~GR(~Pt DϓDY d|I_=AU'z=B0!惔{ Tvѯx/=Dw ꡚ)wѝDJAP,P7Qۉn#h-8D7Qnn :kv]C]M** DS(w)%DS" #:y6庈": CVi!|ЩDCmD֐1?9 :h 5LN$r6R D%ZC^EWumrh) DKSED id yQ;l#OJB4h.Mzl6,L꺙nD4;n^5M%jASBCbyO nՇbsAJQm(qj2VbOUbUbObBUD~RP4|Ɔ͠1DC4BjШ 42 AeD!Gh89Ćbo t"u6h0u6(((3^ Rgu^D.(ED%sA!bkw- lk+K ?>C٧8 G(w?E-t6G[ =:_^^~g=5"R,ocFS=i]5ЏC?f]~ԺuaB!}=<z?p+JU{,w[ָ=~D>-tAFM̛ݷOr hum2j_WA_@_;]\ \\ .B IM5>t45}Z΋[89%pҞ-nR-{7ml gS`c`}`Þ4=kk׬UXk\akk=kU˚=lՔU[WWWJaU**je`EsϊK0E , ,(jti 3'0hf`֞梦 ԟ^4-3-X!0hR`Eu{E5{&Ժqʬ ?3(AA9󚻹R>-+~cO;\VRLil Ji n RXYo굫}5sqzO"׊OwggLT 4o5i\ӭw?u3GSYlNNMF`X@'X,'K"`!ځ6`> `60 4M `:TL&Dj @5PT@9P@)Pc@1PF#BÀ<`( >`0dY@&xt n H$ @<8X QfDF@7WP0a{;[/Wg'G{w?~  x xxx-Yi)Ic#!!A p?p+^n{ ;ہۀ[=-/ u.jUNr2Rb`pp!pp>pp.pp6 ocsϱ9?csϱ9?ppgqpgqpgqpgqpgqpgqpgqpg9?{cs}ϱ9>{}S¼fw1>-aV|Ng~*϶CdnKdKgl~lYLbpn'"er1:>{>gG3֪<H߷x"7R3mZO W{q>h`3,6a-ogbx-c˵r-ur bkZN([ײl`&v"̶5flx2mLTvLvO:<S{L|.da=\.a˱.dWgL_f`͈K`FS^`wil#/ 4v1FL[['abn]n}[~5&BA8O\9aFD^)U(+xqGCClb0CY# (# Qf+9D-Rftb:fBeB yaCzo{6R>Z;5K3C\WΝi9;848\(=6tVֈz-[0B8.iK ,ظ#GdW;j̅ իrKܼxs\q5%RgpM_Pz洬έh/s7Ob\łgYZY`̪)#\)=іM 4P|nƲ ԙG}`gu'3 Bo O1!,; f] @4Q~k^J|7Y'3z/V0}Nzk7!Z^؆~I7*UK;=J!ql]S^#ƯkW챁ON[1&E*ĦYxwfWXk)(K.y䵼 zVe.v领_$bFGL+4|χ7^q# jV-$(*#9V;g3cΛou'$z#wo(m,>>m*;Q~\_?~{5Z]Y VM#31.zHyxk'CF\1R1 &&-o7hk;+|7t'j uŧ 1-o֘N/--ѭ tAVuײj>hR"?H؜N]Jnh+߲rgH͡ugvPjUg&b0UE5GN__qӪcWj[rIKnuqKEN0}3iJ,ĄM=8bM1.:c#zwgDس~gtnX_Fc J{"\R^Y7Eɐ~-OنK [`p :b_7[4yh4$ogچԢW,9-Ec' \T;edFG_v~QR+xJl<$)>yo VoV;9.>>Uu eFD#ӆ¬bSsY1Sl4?~S{岝si٧L\vcΰY5y꺺Θ7iCcNJ\TPŤkS7$&Nג9~ӴHcZ麟zj5/ppdRŘ;xs|yʰow⍽+b%6+-Cbm=DŽ1wwL?>,+fkچ12!*,ݟ[Q8Q;876S>pho߻;#G'1ahͰj!N3.uJ:ᦻLn?Z?lؗha_cExňUKw@LΘ>.PO5Є |!7Kґ|p>Gz Ն>Ӣvߣdtf ^t-ZbHeb(jrADcAŊS|Sij,N?kk<.NlIOrylSfNLOHLwFZmwVsX?9dTqFZwf:aK'ǯWYx,<}>OaWi3?},zhG,g~[]Vq oOʌ v]x8Th6Q?6rk$fȝ,N٣;Yb/3glgaeg;xRfdE<ò|P4YVeYFeCT>Xp(5O SK<7ŊRbbEZgw+&~cJ cO,JwDrB,v *J'~Άp.%ѫo[#Wߺ1a_(ig"4rD.bŻj]5Ő቗˸jZ(#kG .;b?bu '71vgtbŦQIunz{KNҽ5X={Uu3g&3Lgp4$1RdLB$a2S-Z*YK^j B+"D )0>g ~اe/kk@k 4{U^=MS4i *La3U8ɏ`g 2 SâQlc*z"aꄯ`QN4IRyohu *F'M&5c_mS0$LfSh)x:ٓo.T4莢 N,0Y1kYViHaI`'L;\؁N^+3 |6PLI,:K֧cva}=zr!0+յ`Skp[`;e,#EJ8q~%{Np̜Db1$cܡ#Ϲ1HzʒiyQF,L_2gv:2("fL“ N6()c3-Q6KXg3FEG$ 2:MN:&崮F{Gnc:'l>L[aZ NaWcNh;/Xc 鉃A/E1%n>(.vPXGL؁v12“!BͺLJaFSQIǛL&+\c%df땄 BJDp± 4=ƲKSCDŽꆘhfjvɠ_ f@Ĩ.?V魑zQ@oH¡7&fFZ U(J^"Fz^`'6 pf>,'&'%ɰO &CC`Rڦb6]TSń#鈉uDh]}rRrl_x̫'ݲ+ =>>\f$KzI@02hy)=I ) +eeUAOt Gfm&EGDBn:Mُ4^94QjnT"D,HwTHnRN!ݮA[9Dmvjh=t҉tOZCHmY[ ]!bL\|.>EjS"WBtg_^tﻌ]F nnpv"ݤGw#ڔ6HHy~] Mt0O5R&m#&Hhi'VڑnR>5Rj<-jb;4&GHHt;b>p M94^ i"4V03R&a7nHhH7)H+#ݭA`^D+ ,ݨ|}j.[9Oi:*IZ^c µZ^ 7Z^"CZDdMZެBZBV݃Z>T7.-OQuhZ[$c-1!-/jﴼDLGIZL{CHy(-o3-JƄZޤYͫvVռjg5QŠzj^WU;yj^WU;?Id2rԑzxQwp Zɤ$Uh%.p/CZЯ<Gs5UykQG]-oSWa2kM(-G ]2]WWcn@r*:M5N!cu\6|qYdzy%K5\6RZj [̭55\*4]ձ3MuA%BExy۳T-2{6:nR;15~꬗!x5pi5\BCf+毮{{Zː:Jt/fвUrrqϼ\82MJV=wɬzvh2W*FC^]qjx\˹Q-ks֊{E]9(U10{c6ig<5e$q:xʹ|Tj_/ +fs{ȳx[l|nHhB-[ >sJ W߸#>fkz[s`{=P-T7Q jQs9I]WЫo۰y{lSLk5OWexvf ^;k0/WϞtTHzJҲvΪS缻tw\,fE=^ g3UcSfUy g9?l\=rg5? Ea{@DY|ܤIyDNN|CU+_Wqyު,yru\RU[/]eU*^v5u.O\שּׂ^U!W8kUr}C%{j˫j+:z]5Y[.yj],yWp9 Wq9*/tg5NFuiV!gnO͆ u\UvyZ恑\]U ]uriU%*\ĕ%kR/8kL^w1'´Y#7HDM} {0elJNySbf.[``.OVY<4D<:k̈ ӻ`_qB~e 8]5N+.,͜*/:!+(y=U eit%Oԡueg/_<& <&䮫8݋˼uz+InwakXITć7eΌhֹA]勫ų٢N.wWCS2pjYr@w]-"*]vՔNj̗gg. 3mu`S) ߳u ^wf_VUb<]&t5kW"U&rֻ{_OZ-$i]DCy?@BCZ~ _-ث9WW%1~Vx[ԑxj#i<ɡdd]@J)b#2r7]MwG H^țt;CwτB.LQ= /|]覙A; Aw.t_7BB讆& ݛi~w@Cw;t+LݱНDխ+ ݃{8tO=+{t_B~_{?t;ڡ[L So[x9HwtA(·n]֭нWBt? /Av ݇+ntBwtq}tφ[6N ΅)=ˠA/q~ ߄3novʾà{"tAw t{ t{Y= VWBϠQ~w@tw@w7D-=GBw1tBCϠ>IyǎCJbGsss T4vH͍7|nbX-g,.ظq"3|ϿŸ$J%GCϷqse=40uD:$Qʍn_KQO||rDM;f@bYG|"cG|!b2H&3^D/ 7oLT Ĵy^^j/`Xâ!{ ƹ|IOMf2]=r$=hbhLj&35YZy,8mDj֭[Ť ԈD.fy݌fYfI{7s(RԸnoUl>4rNyu:Qg6P3m3f3^ T_@:UVUƦF͌#F ӧTU$!^lR#6v,nB֖E-`Ϳ!ZV`V̪FN517kHُ_ޮFװV]d a X6Ґ [eldC i޶66JCZb[b7mN8m4~"DZ+ikڵkUJ"T†`-`#t]qf\ȑzMvVmT gE :\,fIh Uui-L^E6 { DϕBda>U_wb l̀=% >t6-b;:耎{3V~k{ܰ{E];vu#-V5vYJ R1*QYg\g=b׮Vc>Z֠} >CXuԪoi!%2;qvi3zhFrIkt;ȗ|;C)$ߎ4ko 9l|;=ޖw}+Fmg8 ͌| Ԛ5T5?a:Q86v/jzּܼO9m& L|F'\@1I7I7I>9k<Б'lTPOd|g&N,VʩvNEFX3|3=0sgY6}w|zӑYYYho/_|F/|[gu-%+fu|Q͜⹻[`J}ʃ3A/j܍wݹTt҂KKW,m^gt}>6ϙzR^?QR sh8L\e,;`wo\i|ƃMIM6t+rW\|W]YrW>UVz}:gw&~5[״ߑwGpV|y-%v6z\a^/{N {vv;| =+~Ç&vg0⼵|}0tޞ3rr能gj%UBjYyvίYr_~| zbtySot8yQT(` %Sf̿r;'!c^8G=ߴuęZyXQq6֣wK|m6Hc\gVז\rOl :Q/sɽ{z\G 㶡$x̨{jOĬ«'UD{#,qn=@7Y a\>|uoSc ,H£7"g8$\'j120zjg`<}Ϭl ڱ;YSrػ&Dlq&꼸g1@mUc}vL.ar}pVjKRF7M15.6C`WM= t+WMqtu%.{u]*Ցjgvw 2A,Lpzz8m5"$v@A[Z~coG͊ݡ:&vnGȽ9a#zn1<ў Y!ˁ޿x^x*c ƛ'|ZK!||(.ۈ9CHH!y$ʕ /W9Kerh"BGVN_X4w?6"ג׀.SP7%l&̢ ̸JK I &$Q1;IQe~3?Zc pOI|h83X ȟ:}x$</el#6"l#`92N|x8OA 6n\Kq# Q1ri'p>5:kf`W,$AA2ȟc=Wk$d?ٿ!o. ӐrRl2Rj!%R!%R`G ) O1@6>ӷ{B_!㯐FoS^lȹ rFAlșD +><=-* 3#~*)g1w[&ÄڎCPHԱ:RS 1 >BϏn,' ;Y"w*d`=p tw=^C` * 9|mʻ 8pFby ۷ho=Ѝ(J;%|xحia!}J#>?pJ o@ O,EykWSB|i 9|,nSڍR` ږ/&WzƟ_D~W!QoAqF9 `X##Ȉ52xFF(ko< siN){gQ;<2H*KG%>1Ё@s 9+g`3ݫ+0 1 XiXߡu}7V[OJ}\1U֠T#} ѷ~DDm lg!_1yKr}Ah}w )GxI4 jRx{Xe-7Bn&X6=pDxp2|Dhs=qLb1tD[ta!}M'YF%`d YF%`d YFYY{ZӊV=iEO+zZӊ9=Ss8iAO zZӂ=-iAOssfr Pn?;yX~ (f73nf̸qw3ؿa)n;#4MiP Y@6 F#Qh` 0qx`0k` p=0L "`p0l~< << l< <l~< <<#nk-xnW7No.Vӷww}`nP٫n[;{~e"( b8M9('ĭi `$GMoU Jq  d6&@ 0HUi!c:_0XwGmr8崤S$@3X+ 60o 0o 0o)HKK HR@*4B9!QKy8SWg*nжX)'Q~ 8sJ)BoJ?c8ynPzg{|.'Iy/y|)~V~ojv[~t00w;s<u?5f}v_+8z+s U_%U_%ȿE-o8Z"qE-hG^ y7w9*͹f5[ĝͺ*3cVX҉ 31 1ǸfclL 1a6&Ƅ٘0fclL s1a.&ń0b\<`ʐ0 =={VxJVO?ɻnJnJnJYgŞ{VYgŞ{VYgŞ{VYgŞ{VYgŞ{VYgŞ{VYgŞ{VYgŞ{V셙uyD7({3QGtj#xpv8Թ R&tJlOП9ޑe,keY+ZYʲVe,keY+ZYʲVe,keY+ZYʲVe,keY+ZYʲVemtLy7c1Y-=: 'dr_f/2#G fn5Vn5VneU-jYU˪ZVղUeU-jYU˪ZVղUeU-jYU˪ZVղUeU-jYU˪ZVղU} Y9]$D,JȷA rmar:;ɧA> iO|TĦc{B/^-1wOt3rU--4nJcwݡ'p bþm6q,>AL9Wj|C%&\)>~C\p#&L͸þ|+V#`s]^߀^Y`Vh܊ۢbλ7tx{> o$(X2$D9xp08 p88 G~Ӱ4a? i؟8?4&.i|p!>/E\)p5q |?u! Sqf܂Hl*n=maHD_B y@¶YqrV3rTS9oYarV&gYarS?OAL9Wj|߃$Gh=BZz#Gh=BZz#GѺ="Έ8 Һ Һ =_;S l﫽=G?zÏ~=G?zÏ~=G?zÏ~𣇂 f(` f(`F7uCZ7uCZ7uCZ7uCZ7uCZ7uCZ7uCZ7uCJs(͡4Js(͡4Js(͡4Js(͡4Js(͡4Js(=WsyUƴɘ6)gh_8C 348C 348C 348C 348C 348C 34иcF9f䘑cF9f䘑cF9f䘑cF9fIja*n479f䘉43*NϙSػdT%u[nۦieѤ&Tqf/͵ *{y9`u(vM{@u=?M7T߀P}o@ ?Vz(l91s==CvJ6?tӵtk7]Mzӵtk=]ZOzӵtk=]ZOzӵtk=]ZOz5էTSS}jOM>wӽt{7ݻMnwӽt{7ݻMnwӽt{7ݻMD!ϩ p3n=-&^|E]f^507'4M^OKg{ZG'9"߻W*^wՎk:w]ٱ=ѸXNF7 ƣ/A)tz芟vY8'ɊI^H9C U3a3yterٗ|yX;=ɧ|R.N˼VrJ6z y6{  准0ɡܞ\\w{0OΧCTmj+UwSQsC%Y*f`)JV Sml`;Nv Q}l`;)G> Rz}R/K>e)XRYJe)G!J QjRC(5D!JWR}R*K,cOwS(km UgSc1}YlN{O:s<Vŋ}?4L]PQ?-|jOܣτ 7鬎㗇ʰdUUrŷS[|v߸K/]>i|/oHO^k|rRbKpv/5>O=6_wգ=|>=VX{TkXb:U.ٱ%P;TCelST6U[UVUD^EUD^ElS yW ;8sV=)"{u(:z7C(9_|jXB ?m,˫ѫcMHAí!M&{[]ug멮jcr*^J ]WÔ%V%52 q8 P?ϧT=Y_8gz{]pp{]Tt\J̥\EKKuQ}/RJ.6pCrh:lB;^6߱=P? KʋQ&Ԝ0Wvqsoa{#caX%TjLwMwMw~NWFeb3jЌ4>,a{@\̗Ael4[͖A=h uXfŠY1hV )s9*aܿ?ux9[eU| 'UzoT[majlSSoak#]sc 樖XȨ>~ 70vJn3tefԺ>cwÊ_Ux b(̯"6bs,̎'#~ɞx1`Fɲks6ksT=ss>n|\f?i|&|SW\ueb2-~EtD[ oMVd\}:~OQ%sTɜߊNwGg0|G=caJ y+ 7DMMߏ̯篙:~^k5ܬ}Iv&X W uַtRsyMt뒇t]PWT8Wſ7)֊>*Lמ+ֹW*-VfVk5OVV"fN|YJmvfȻ"efo47'D,Xl,>QKacZO \o>+zӟOϧSV|Ǹ wSToћ}VV&| ߢ7-כO~:_{''m5eZU"uH].RjmZۮֶ^իjhZe[­rEW}l\ᏔauhR 7ͷ[ZvRj9{+eW[(Ni4`oP#S##l)ۮV6`6 j4dL&;;L&l2L&0L&Dk3MvSk0L6l ɴdZNSn:5N STj7OӨ4j36pgɲd¥Zml5] [M-aɰd©FN5rTjlT#uNM:I7&ߤt|no]ޮ۷pQo[t]=qqa_}vx':GQt< g=|5_kZ[|.y^llWTUy^UO5:-Q{hV]R{եЧ>OjޣШFYzw#Z9Q#2Xngjsktv{Yze6 s -5nD ݢknQzE+ݢ-^A{8Wʺ&WJRʕzhXGmtaWktFW˺Z5Zi1D!Wbȕr+h1YWϺzSÔ{taWb=o⶚F'nCGg*-}V7,[|p=m{YFcIQawluٛ"|k#| xMdeY}U6ߡq+ [7$^kq':DxB?=9GoPLb)%^q.q.1rAtA;]wtu]cgtoQMٍt^JѩZ6'E~M,Nv]EW}9y f S$XܿFW{[kMW=S[%*-}) mZº6Rk|^w%\lwkB .d6+U[帕 `-`-[-79ڸ&DqbX(何 ho_#Ȟ(Y}".G,>Qy37Sy37Sy37Sx+Qx3u7Sw3u7Swʚ{~GeKQ*NiOyݳAϺ۟۟[)G#VʑYV.mҍدvi{}E=y6buwV+ۈ}G-moҌX]Fq="Y`fuoj?Se~8~IrjȠY9x=OtEEg)/d /8T?^/* Y!a~x4+ߗ̇GntlzlNf2pAW[G,}[;sθJYWHB꽻ehm+msy诀wmum[y6:1^ѡ1~~~1=+gcc*GvFxp,®׮W\Y;^~1=kGkGkGk7ZW[mt&1nrfnoás.PaQ^}ϥe^y^w|kNo TZ':)INqwM"F'5:INjtRB':I(y%Ƿwq7q7ةn|6U*ryβPA.$ xKoa6aߢc8t|gLqy>q>O3,> y|E'\/q K1 _Fet1/ƼW bjA=ֆEh|ބ\{`?0o]Xvc8ᾱa W| ŵa~|?xM{XV)9)(0Nϕ3qa^7po#XNϷa;xV/Ic=υ{Kc4"E1KKǡ $Q0 Cɰ||g;Ʊ&UOVd5>YOn u>EOQS:݆v܁Nwn<} z]a:Gst:Gh Gk8ZDAzOjWZժ1?cq<_I,¯k5x OK;P?ǣ3 ?Ì KU+Üpm\g$p}%o;SCS1oomvWŻBM|H*:9cwr\tctPT܄i`:fGLcay1żR>_ь Ў؂@O^ګ̚c ͪ~3eΨ|a0_T*> M0Sa1a~0?S͏bT<jx~h.ߠo.9q PӦ:1spcODMU%xm5s9SS+.{_頪h|顡0L8G(c RTq'_}[E^i ` 0l}6>f φՇCaPX}(>Oh$>Oh$>Oh$>Oh$>Oh$>Oh$>Oh$>Oh$>Oh$>Ohd{F{gp <d(A&Jd(A&Jd(A&Jd(A&Jd(A&Jd(A&Jd^b~xxxx/%%%%_ ,+KbY3[*Oz4٬-٬m:'Mv;!}u 62[+2mx.WH",1o~~%>}EK\?"dwL)E(:GgL3}to%V8#((g<<܋̜ 3%I_%I\B %q )2xAdq )BLދL+œ"̉^@Fp Hc}[@ L(R8"H=2H,Rv]M(kqs2R(gybuPבB!$rP Gő@q$‹‹Q b|{ ||/>`#*e6.Q7z(W}Rw;A?П> |qQ8.Cj,Dž*z\>~G E %4%-|>[((((j}o;\zTTTTTlTlPRlPԒOx$^?Ox$^?Ox$^?Ox$^?O+J+J+J+J+Ü~.󝖠}'^ z:BK(sm&R2u_ыW ɨ9(Dk5^ׂ@Ge]wJ^ <P|Cy(><P|Cy(><P|Cy(><P|~j Bhct7!R)7$:uDv lD[hl 1Y?;EoeY*Uoz_Tm~:_le팂Õu- "X)wq'z\'0|XnEޒ'2dT8r%fN8yJZXN?enRrrjOp* Ծ<-w;lG둽0ې{B4sy-3Krgro2gQ)W5zpE 2L-+=ʊN*M.۸^Xz((pA x @HT-{p'` xx05\Wza ((pA AUP T5@6 r@- jhƠ h Z5Z0=^p<0I7 $Yzy.#:e)w8 q'JvX,C<G2YmY)tPum+)l}!+`ڶb"V, A`0 C00#(07X3, ^Wk`xoyMu,bX>'`)XYAk:A lA) l _;y7z}>u=L_b뱹뱹 恷|X@B,frz;Ź" ~ptU@UP 6u@]pޠ<5 z!=i ׼{[Ўz{[#O)4r>*ta<_Qh7=tʽ w~` ywy]wywyG0Lם O'0LOt x\?g}>?g}>?g}>?g}>?g}o2>e#MMǧLǓLCLCx(tJ~g ?)tv mB )ѿ>G_}ѿ>G_}ѫ%F-q=|kћ>z$QOCcNCSFSFboxM^goIVy rQ~(Ε\= Jjh!u[|}p޾LsXoP9[(*NC/E/42c=cmE"/8Z|/叿K-O}l 5 pl!J/![."[(%u9(Lu1v3kV|0s[:@ђbB|?MnBrTQ(G"l18b pMЁ3?+"0 0E>^>Ϟgǣ|w>~;?8#r;L>nwqYjq\{\T7M,V+GىZEg5β8V"9XoSyr8q|t3\qRjuiQqn iw0~8RwM>]h}#~z4r H?kC+)PCjFST䈭(JlG7 `֫%*0ʰwp 3Pđ_#W+x ocvD񤨰51YA_m J|Jiqc{gǍ1Y:F =zʫ9@i}]P ie6-hYA8sFrr lG죠TcCKG}[({_3Xϔ#)wÅ׌27h g.s2Fα-ZDU't-T0 l[0OUJ˘[|uafqy\wrErFbZ|Bmȣ6ZwԮʜwJ3ôJKЉ:]y Xqh 1.Xf-Q')jIJJ>Ȼw;w1#~oiv.;lr&%jzļADfP{+Q.bN;izEl%jE꽑[p'oVo%9E)yW5}Jm .fv/C/^3rW^ygʛersJ/%C/7;m{D̯3rWʙ_9+g b8FQ0+ΊᬗYXψ+52D!o)FM\ Z-V:i=' RUl潄`(O>fUV7feܘ Vp. ?˼gWʩü}j~S&2dw6v6[dk}2>ZOf,ci]7˭>/`f%ZAdoYf\b9"F*D]|!aK)dECq8- Z:CkM9SfsB&@2y'6}q|ˠ>\[z@oeVT'«q=QcA&=f2#LZfB+)QP#ETER>t?sº}xsas?ᙓȲEԪrk[E3c>p1r܌s9ׂ|`Y9P yo=lV-c:U7)(BP;Ne`v+Z Wg~թ>3?n5|#ИiFYs[JN/5BӪ\Du!дp)玷6lPaιǵezuqr1R֌9߂*757Z WeVgU{YkOiF1uP)uS-O^"y+vyd3µmqp3l U'>ޢr֦OS\)nl,~*>8Lo֧jX + w}b& 7nBV?Eev¤aZy4S ]*+2iا'VkiE2;aQ]X͔jZLf 5ZZٙ2V VTVT+WH:UiΪ4Sހz 4 RSQŹyx|RQmZajJB Fwqqg{{/r^x&SEea7օ/1>½W|%4^g5lqr[xq ^wb GzL]Esw(W:Fʨo!V6bθVl7:].MMFOQj1A4Qf<+xWcƫkF=#c<<8<<8li43/2?ee?Wm6f{ufGlv6.7݌?=[+^f/*y`6l16715z)Fs1Мei 6ˌ̵T3in5^6wfxg27SKa|,M)RɸLVՍ/e692X)ZT63k[Ŗ6ߎ2EaoOEvZNrʔ/+Tsu@bTTJVnRU{U]u:]uRC%-}u"K05JS{-S=,5Vl5QMzڪQX5 fYVYRuZZg j[u@ڨ kNsssukLssչiius.tZY79;[=?9WZ=Nkig\tnsnpn:=^ΝN.g3tFZw;8YCG8g5ʙLq&;{)t>ek3Ǚcu:sq>g59&8(gMZQ˚UQzn}~~nmw׸-n#<+ki{!2!nlIdFlEl_eOyx{F ޭ^?; U7fFx9oЛM[x'S)ދދy,u| mb=o}}n}魲;x /awzIF/}cw{Qe7}_܊q'W\x^D~=5<ܞm?7||LQc9'SO7_ߊόlefeًgղȪU^u(먽J.]jWSDC_ VCp=]Tjݙ6+<_l<*QlZId#΋zu9ssjN2zW-9?^TMez{Ѿ oj}X_)i 3?7>Ƚ;@;srK%? }l0j..bAxoz^K;~Q} ׿փ@NXﮞOu>VgBS &TwybTT~~.|?ޡ]QgnŃOF'yWK>e}wvX2:ȇNxگW'Z;bGg\~({g}/hOCܷO髬_C^/GIZW2^n_/\ˉ޿<9廌W'is*N,gW8>i%JNjn>SATO%:dh_q8Q^ ʲBrâsmO؟D"ٟ[Y[YÈ~Qg@%o7dV\}-ڈ@ W}_rm'/p~u[S܏։Mq_go?3u"wxuH,焟*'|^lW"Fwqb`ŋ̾b(~<)F̭bYlʹK kx,o.&\<7e@L])]$[Zj1#R=R]|ic#?{ֶO'VN$ժ( <Owx:%t8t"x:+tHDO7 [=UOgT uܥ1`5I 5j$Gg>OU8;QMdDcy\MdLi| 7x>gAsT3gE9j%}C:So2sZȚ,RR~ϕTk1֩mP߈jʚlSŌSEcK/RUʈ{>|@AueC39QuU9=W QCS=2JDDM&la [؄-l6a MOT XFȀeDmXfmlo]ĽyE-E)zio7S+ou{?y^WFCarܫ1/iuZqm$n갘#jţqWԌ1jz ՠ$;#v9[:ԩo Q1MM4ޔ}rg3z!=όϢϗ/  cYɆxɐ #4Ã2A|} ~'pA 1¯2 yPK^͐rBsC֫^nzC YS~Zܗr_n}yWɐ

      ~e}W5r;8P>XLѫ^ mgt[W0eJx7kŌ?&#s‹c 'B/h= `|-hot飥z8KObwtQۧ|*,Et}K̷{hEJ'V~]\zK_KHU_EMY <?sѫ>A?Cqȟ CiC-d6>a&!;'9N\6+ jU1\<m-H}Z_DZ[@S?iz~~hUmjAi7|k AV,.g8'a)G*!̳Nox_- ζrΝO8!LKW=Տ=jRqO^ӕ{Z.v/zťQźyDѵ/K5ipfb$#n5.`3-`=ٞq\Wq%G#xOmf͎"[>Ö_ ]~Jށ uj=RWt[~)>kѬM_[^a;~|v!.-b<1T/]o~|ɻk x7?Drgc<}W}?;Hw,,E+Օתbٽ8~1wx DOt'7ާ} :W/QzˉA"[/6@]ͺ]?ٝɸ=cuck]0*VVg~Jv}H_UX0A|x5FI!}ݕTNoʗ}2/n%V|&'_@kq<%(a彯yWv%ӁuU_y#__QZ~T8X+nH/=wD]H>t˚_11|?UQKŹ҅ zf$I]=~ 6~8SLةߧw 9m{Q{Mѝz^ QG_/8怭KЗgm~uK{1d <8y{p] ҿ{I}Vs-[hKSߩ@k{rc;V˕ܧ/kpա^!r?scY:b6T_`٤37|z`^Ʃ8;1U տ1MW{г\ K!Gz`ШDM߭l7{i ~Ŝt vbI4svR|uzQ_|~}=Y1( d,tbіr~r[)WkxMR[h`]/.]:hy=֍YEkl^d/c74c7!uAtHn M )ҥ{ZxPf ӄgNVqu:6Wc:?‡1U̶bvӱ;~-znqX3'>qՊK--Z\Îw??-씸Uq}gP Vvn`IaœdH0$&RSHU.Đa*Jr*Azr C Ђ+'Dq7! )7k\M(Jo&¥fR-<ބRit@ބ \Mzo?{&KH p7a:xo \M5ބ\Mxk kƛxɓO(pu7D&&*,)fsE7Wt|&sE7'jOWBq+JXD)dZUGG&NkJg]gr5I&>Tzp5Y&k\wM|뮉&Y)Wŗ2W_s5QQq2M&<r5qW__k[\}M|[y]Y#V*ōNqO٫(_(qU6[&Qt ~Us\Ms9`zlxs!ɜbheN37w5w51w3w75{͹\C9p!;4=!fmficI0dsu7C/fr6*Z Rdxgx0ffXWe8u Nuڌ&fp6ci3^uڌ\ؚp6c'u1ӹN1o:mƞ\؋:m|f=i3Rơ\e8*kBfU֌ʚ$T UP54`hDhqWV36[B-^("0 yȢ0wK?kYPafL? 1CccF{ ~>8 > _oVƱXZ0/г6 VeтUe1p+!>F$ I,U t dhŝ#Fz}i/w_{KSԭg iMݙvgڝkkbTw1l6{,[ oC\7OvOɧOɧO$~+ȧgOO]/.+_Y[q ||}no~87﫬 H?{x(mf 1g1  P Kje ݱ5ǐa2`ZNZo;y'|o| -f0Yf3٬Y\e|"kio+6.1b0Ҹ(K S Y/Ԍu K첃YiIH0KIuW >i3ILjvt@:BĬ|NB#LBE`f 1+x\7k.N|BH߰(tHJblg3wwȟ"=! "k.d#!Kp&BVU6&! ʢdle9r2un|F(#br-q+hOPQ{'3r2 oSMM*rgIP܅|E_ngY(]L{ɷdLwd;z/ K</f=1r)%r<= ZYw~S%WD0 'ɓK\2 o7Jn?DɭV#ylc;1Nv &w.8 j~:,FkG(%-2blgs,<Ɗ|K7EVHSKa2Ųn֦63XN{mJ2u`w::dS2,7nb9TS*Zlꌒi4bꂭ&ĎF7,Sn٦ll1/) p8g3L@p& 8 b8gb8g39gBesĢV-KQz)P 0's9 ΜX70'D,). eP, v(+~ST!?Q;F+te2XYN;%p:Xj,V~VR'(9IFS?2MALu&I)>1Vgg'Ayy9W//jžNNc[>֙I,iXY2,i&r> OHΧY]OyħEb\ǘ9?%~Pb}%fA̸?1Č[3"f@G"{$HB=Hc%{$H'{$ #{ ~Ӝ{~G=HN'0f`%ͺ 1B 84g`w,w w sHa$ƒyy70),\Q(9#F .> _|CxV`+g Xx.SX6J~¹P3RG=qGũWgLNkkb툑??\MmI|IխxP,@GF Wq乾Qxyr$~/Ck]/uGG "u ABœQ!K 4Zba?pMDb' ]XDݐ4d 7#Hx!@-h) M`H`0y`X(x\A?+b`׳ͬ7Li2&SsdʧH/EHY3b)bbMACaX8$ߗ1(b)s<&Ӌ No"6o"6M=z1hbyMˣ灋#Se,<]NG 99#&&}[%nAܺ?qĭ["nM9Z&O|L~ l,b,y1w%K+\9CM\qy<VĒ"~#/gĒK^o+"I\9G-++gKnE,9Xr\yXr6^Ē3%KI,6b]^l8p~I8]y<*gČs["9qOĽLmMXobƹČ!f|+^ă!K<3ۈn1݂6XiI%F*ba"&TD*bii zZbiX?RkN*b"C*b1"&D*bX*ba"f!0R!1THELj"&XI"֜TbHEL"0Ri"&X哊DaR0ìFa7H?,$ #0$ #0 ~֜~GaH?N'H? aŐ~9BҎ^i IItbJr#%T%5d(iJvE/J 1L]vx [SnQPf2uUD$+!ܣ܃<SV@G8ppB2ōv<Td*)R-xEM+Rn̠'[L86sx s2(Q^P^eh'{Ũc_Q5e)uD>!>sPs;><>>gG|,ZI;O // <2Id2"ΈL^JIgLPduXo |K} vܤF|Q`zD&SL2Pݤ~-Ȥ]ݎ<&IW?Uwb.I}L(2IUk4OnR?WH0H;GcpxzyHzLzx=Ʃ??v`` bH:ד6i &m8L$Md&h ͭa*I2x5\k0Ik0xl劃8O bk1kKX;DbUx>b}D_(Bq@]O#?:R9ra")&dR.L"DR.42X?ȯj3fdG4ɍ4Sp-Ƨ4 i* YHs#i9*H6#mCڅM %ѿi'GN F:X "E" g>mԃ\RX4iX{( H+NS@b$#HHQHqU T" g>HXA9ɏ49J ~יH/ nl;i]w |H!mDڂi7R ҡuO" ~;`y HpH?~߯0)?Ū?V릦Ɖ敏~踊 ~t?+V'R^ö?~Dbl6oVRF(QYq9 +ZaJS}W~dp ޕ{Vߨ'KUW x}mA @ͥCJ]#JT|N(ϗ8+GKOjǹWn3W.Ab*m-įaϖ՘EdMl-i5[| Ɨ"lI%1tAL)-GxOGJO KOGGK.(w)ZB%Pk+ŷЖUXK-!lSvb[ϒZF4W󾥶dJVh3]iٮ\BW_bW>pk0iټojm`:O Wa=vVs؆l؆l18 ]^QCT [qnmk+ 7Tn V1b!p_bm(U}`jURmcKi#8Zxb5!ϟX['&UlbX&+[wC)JȊ`CĊc^z& SJk䊓3 XzmӨ+Tϵ=hZq_o8ɔo{üIBo p7]xNoVbsZmRq66MX`[l(z~omT/ ؃3Ve[Oi!8w`^ĕ$m~LpBG}~8..N.NN^];Wh[L^*^}z$h}#Towkˋwx.s{&gxUmW(.m쩭->=nn֎6zw-=Z^ƶәmq6[xhm΁6mXqSxYmsotxV)emӡ,F8XCCc3A^˷Zh;,֎ڙӥ(V [ƺi'Vˮy0޵jWsIOq]Yc9^˷Q)>0uu8Rf)8t_hpBGYo=/a,a/ҞP,8,8,QpbYOX;:N/|l/ƞꜧm;V\I{s+2a ؃|۹ c[TV |pY {,ٓ>Ε5e')MeӁ[˞,{ll|ᑲWFƗl+[\܄q/[ <ő,5Aέ³ek#%eΝ"l/-C`۝{{._QvUvWv Pv̀nߝ=cqe՟`;—kw;9OzfrtGcw/߮9 p'uwݩXIE#'1#Enwo8w O?Hs&iq|&gMu峒\Y4=R(?hۭǭ|8\Kn =)p?h{/=^=`unp˧*fs|0o|\?^;9?zTsgI&G 1||om5EKm]U~W>Zآ {7WpoO@](sڽ?CtOw(ӕmގHQlC<GO-Ֆi9=dO#͓_LOGV(\&G_O_+xfvGg00`mcпQqkNOwx=~-="|x)ΨƌH/wnq҂{|jGEjڦazaX! CB!K1 aiYCXCׯnGuu+mmKø.a}\c xx!>uYz|rqg<}E&g|Vq֭|RUL,$bȮPS'+CT{1A5=@* rҝ8Qk祥2r1<*c 9.lyc 餚2|bQH{|"OK{g|*da3ss 2̀|w@lbW{|w'Aӻ2'{+)A*sƇz2|NvV_Z\e|aʄ%_^8s+p>sW.RcWxmG3|R掯:\,comW2\W5}9_>k6>6$}C6d}!x _/p BPww8)߱p-[A,ћVF{ޅjߘʴW٭q7^|n8τ[ ;p7vq ˤ, o8ധ]MQS ǩ>@a܆g=n-vFpdF}+9;H.ᓘu'~ߪWOk)g;{~d]w>{X1BDqE,{L1Q*;N(ݥ숒騒z|yvL)R|";vJ99J×WI:LRTSvtW}l(tY ]+ؐAbPW,`Wrţ]D v S]c: gFbs]ⅮXx1RDOꚌmtMS]qZ\,}&C5)ZuܝDܵku3 bdc4\RF03HXP ThK]5T,<rx?4&-A G1%8WMҭj*+GX?V:V,=YYnO.=9iOq˾f?gSlّgshܑ*4߳J rF'?"kΤ"z.Sh5(z3eH$)dqEH.ir6R+#\%eTt\r1U.G6s LkRFp9?IzkQ`ԑVnvgrmCYV(worr?9GɈK[[AQ8ٯuۿ1z>.ϊ p!̙$=ots;NDΨ>;͑ y%gdo&,jft+Vn5ܒ/4z(FnYC ?ޭFnL`w(lE{}TW?)sMF(>?MsWB|2H/_f7yfh!_-e|^7D |{ -j@B ;@^hWf>(p,*V~ PeQ?zK47OX(*s5:.F gDSW1:3XaC ˁc1^`F{X`O G'=;0y贽00s2j{E`>Re,D"X.OVvKa{.]tjC]誵z;nݕ}hgw٥]{vk6l* ܮ{hWL{tW{ڽ] {]M+8[CZj[58J[wQ6Gv0k;OZm m)}o ^mڸC"p> C$⻯rEWbs]^귏ڽWsݳ ~C"-SQȠ۠3t/Ћt+%k,.GzEW{+} P _B9<(wO6@GLFoj2!}^Ui }ߴlZEנ5 jF/ԁ#}P Gs4ڈF~GLFQɈߛ^Z)ʥT*T=5L} ߩR_M^(E/}_ߣS}oRAM꿣*՟?!_cA|yP?-&_R:_ߢoxuë C!ucMo 5TQ_xP3|P :aMg2|@r 7 !' 0 >k4} ]rB0jݗ 3p0nn 7 7uA/ =},]׆{aHחR_};ԢN~!UMzSR*RRz8年j?H=:<>PJQ?ΥlNz;2x&J鷦r4 ᯍ`"ֿwLrJ#jAt^X;.]futۼ\ 7+ҁwat\:)6[ Z_!:DQ~t(IDE꾋(t߃kuG)~67Q ~Kt?]E;iӗt?{/~X~4#J5xCe/DzSRПdd))MUX^JuJ5'߀% |SH(? #S$^BA8%^7[qY'>xO2HiRM'J%T&UHV^HRdXI )@?yB#.A@CJ)E M.5>Sȧ)6S ܗ5T<66"޳ذ|يꨯQV%@Ȼfug#%QPT'N(5Q{0C;=&}ם85lDS!{O5DE`b$K%2~X,5oRcu{Dx6p9{T8'!sMp=!9C|ڕC”{Z]s.Z9!p?n;ŧ^p {yr)'" #KQNcwRz:4Id+=9ς+#uy =Eb yʟB T{j[=b)XF.y6.Nw :/C7@]G' q}v#<_z}oXzsؿ86z|7G#{#{{Q=}cvgwf8?;[Sߎ:<N\' N-G.;=/Ax,a A?shzd\;(9$|m%|J6a8*gLc'~|)9΀R5'`V2Ws @HX,;}lܯHH35ߘ+𑚟q 1}Sq ]P,\B2 8nՎ;VDz\'[H>aK݂a{r9Nq6e:}9 '\+rJr{k,bgC_eWC4jI?&_Cg3ҙk\Y,>ggO@Otvwz0w6bdɷw7ǫwNwSnY\w3عwǀy79Ja?u:㾛'}u-yճt6e bvbu..P`wQfB"\_σ'}NnAA_%},#$ }~зnd7~솾CvCnnh 8 -F ȧnh9 4 @@DE)<BD@DHQy쉾KDȞȞh=}6=mdOLzџ=dOdO+d7,ϩR?DdOdOkdO}}J`D]P zlfaec[g{o :#t$JӃ}>FУD l%i=mnX>z Mo2`/b .3tNjD?>K/4 kC:OX2@ N>a Dyh@рa/?9'09kZA ,89J6O\蓶B&5l!Mgm~b=L%Ĩ:#uMtfB9D?7|(.doӥkd p.'R r_!Ib 1ڧI,nm0r:H'!&"'IqQG63Tݭg0uX3 ff'ޖ24# jMXSf,MD/^b\`;e0~jF0Ae1V {9D똣˃} ;z39Cscd^Za.ۢ5(aan0.lGj+xvf|\X]?ʘv٪Yfl[HlY-V [zVIX6V[bdf()6بm[;Jk&o9pun+t{aG6v f` vF6 34; @rvh %+\4XkUȗهKFT"e/ tpu`QvOrW1'qaoM0;AJJ%]=Yx=c[)>f8͊-&~3_o;y<1Ͷ~]z` ϟxl+.^t-DCQm?ş&j/S9ym2A[7[~m([= &lz T@셶Q[▘m0:{ھ-f{jgt%vtfQ{?-Cc}I4?0VT4ZWT4p|h 4Q޼zlepP/`= ҷ5x/c u([jA 5Ỳu`Uay{}>X`nߓ4x4TXƛpѧaxٰ08+0_u0χpXpa pW+X9Gp\}>lc4#Q&];fr񳒱@{V k*e|PjĶ$N8_j>ٜJ¹u/_YגkM`9 kk_[dI_Xb}]٢|| v[ړ٣r9مfq^ĺ2j=zem^׌\,>Od2W'qdZJu 0Go^6xqLL]iscZb#c0۱nEU>kcK k\sXGoC}7ۡgqcCrTq1:H*_v5a<@&߯B/sA߶iyI_kcA:um\@( kxoƬO_qWreOg>eWYk"2cW(W ^5}2#Jfw`c&֘rDcE1R *+cc6)\cjo;{ |tR'F'@~4o5]c pJqk〓 < 1AiYϫz}aEe6^WuBmu;1 87[X6?mIW1%W3K:x-ڵMZU.@hЂ1 a,OYhu|-cK;*>X @ dax?q<`X娖q)~l'# I_}[.e,Sj~㥋/C+ӗ/ߨC(5P(*5IZ@ htx vz1~08आӀ󀋀ˀUuMmKr Q7ҵ-iG1 (Pb&͏llj=;Z.k €> (v߾/N_H_?N^6oK߭ϑN 0(VUKE}MoqA߸7. aq߸Po\* pU-4}xt% g'n)pNxoVû—d}a=V&W |rJ;Kr~$KYr5$x]7YzMֻnvF`/7k [O;v2O꟢[#OHHHHM5"#NGZG5ɪL+K=WMذ 'NQn}*m lx¿QWT&U;%E __Vu{bOka"AnI7}G} mܕ4oM{R>rN轠 En rI>}~rSLoc}ݭYO+Fd\!";ǐ(UzpF܎ܖ/vzz4ffc)n+C=lJi a"7ubc0o&sEovf >SG&- g4zzuccH,l8{i+39eC4Qk`7v `v!iEd Qb 4=:S3xE^AiGK|nk>-ޟ|S-ZOR$؏sB⭼4eFf6ykȗ_I W > gfY؅MkkN@MX`O+oCxּl L4VbSp @}}o} }Fbٯ/s%OR=Z筒Jz%C~YO!!֑{s(G0Qg0u}]^-4G{ 呷ayru` F?4If3v̲^"{B-W!'I'j2췋ٷW.$'W܋;xϭ=f볲"0/%z@m`Ungl۹^ uu+wY2rת$+ [?A66ҟ[~Mw a S,ưw](~ى5.Udu]zyOFΖV ꌟRG3}2&~gVs ܕ+`G|vgG|vgG|v$JųSW,D`+"A^#Q]H? u iA?oʒ>tZev&rip:VGXR;W ~;PwpOqyBwظ{zӖ?ғTbI>,QXM S2;;ɣQ"C~*%3U֜ϙƲzko{qfA3̅;ъhJe^|. sdht&1i̸>G)_WVsk>Y%<=;)햘-}܏r_ F/grtw.p~tzy٭@0T }%<?Cd\8k$)䎰M9rɍl췐QDžRl b~<:V![R`Ϊa'j]"$b ۸jg1w3-p<g3<9 6:N}׳^ܿ;kăR*'/"e9BӜ8!:l(>r,ֈFS4]E=MV^EgR`ZFɖE){y0jo^9[ș^%],_B^p-̃ٔʸ^X"o^Zn@ggi] `& %s0OaAFoxiHLn$(݁f^@Vk_LԒ{$^$cg}#u5} WǍSq\3a_(^ 9a[Y;x'Sz< xwK+g\QSlSk=r<NNxyRjȉX 'Z+.yb?޻,u^u4$+dB^OSjv6d~7-/w7|)Ke^tc}:*ˎڂxFفu^Zާ|rzupC^+_}•L,7 %g&!M6+"+h >Ywܩ&|"}syNr"s!AG=CBxZۏ:-#Jrm?B''n\X9k_DY٢nC'\_z˕?I愪!WMVl\FnEyN6mwYf߭oΛro3ZXqiɺ(׈P'03~.5kuʞ*N\Yj}ikhϑ?+Ϣ?޾sϕ\/z2"*NK{rֻ\_"|>˾R~yV}!{PGrL#z"KiYʝKX 14 f:ʾEfyʟ[MB7Hdv`x`)>1wᩲcNm8bO~8$2 8MT^Qwy꓅;=vuGPwreOE2W9bEh^S[~>7H)lG9[s/_q?Mg܅"Oz $kzؗf\URkyTa=ӘטLj̚^M{D9SLlkdN(9N:9rҥ$XxSEÈ!"x#ƭ(yqvM8򣜗֒rVҙ!XJ6["O2D3IiOչxPW l36e9{3 |g=FZH %VOW$!܉8Jr~ףʳ/FYA_ޢr^G{dˎyY5;E˙[:s5Vz{n8Iz i.|vReX M_e u!79 )pC>W~RKwc#Cˢז7MV(ԗ,~Bˆ)"ׁ.yP\8d*0y%ޖï|| p*c0KhBU&*3y\dy(uɁr<Zl8|9t=џ dC.h:"R.9"Dc <+w{hD Q[}O"o1{H{hfBd-\Y@N ΁brwh5J\3:&İیM:| C+NGQǚeJ GyMn2r"LgiLMy2&?`Bf;)&'EoDaV ;$4E%nzL;n#57 l'VdU5U2\rUV#ІIa[Ei޲D)S $9Ų >D>YXEn/z Ju=4^Ĉu#]dy 6A{HCD̬xD"@谊dMC)iUGIbhg%082XY&LB>|=H<7"\(S1Aru$f+^z~Ҫ"#WktGB"@;MJOuЛ9|σ0G(lv=mcv½M%Ȼt,i@Z9NdDQQ\GX w@_mL6k`wO+ fECv{6Qj!h 溠kzf _@?JZ <9%{0>s> [1_-7L$+ȃat<ȝau!3W5mI$"zŽ"~޸Xi=FnpeɝX-uv#B6*Q+0ܟ5fvvM|y 2^Mk>ܝd|[Nj-;Ck4^kv:Xv(r)]0N1L/%QnW1 ?'ڲ\tJ >S³:)Gk=yBeÕO|ʉw[Tt+UgUsۮ%"O$ҺG.tl:WeJ/iKuRh V'3 6tC{>x(Rf|>&sdƝ%b6ٞ(bgL޴%M-4ep?TaPKMMx NySWhort$z&^o)"+'uPduRE%^k$Q#߫̕wзLZ`+4LAO8mз (#roK$JmVqlKɷ ۶-k3 i>1+jjOl O]MگJ?ɺٞfO̲m[] fgY4?B+-[װݞo ߉kh}e[]~Vy!vY wBC'ʞiç3r@^e1̒_jˆ<[.sU$D޵odHCv%eC06jo ,X:)Y'qr5>klKIOy<|'=Ox#eG}a*,t.Bb)˺0Ji2r^XCޝ. @- 8A<vE3ZnC&Q## )l̸x6Z-܍n :"XZ髏_̎eXjHdby̔S?f2LL+fְ_Q, @5rjCOMLD"gw lMDR"ioY͆;_ tȨ]i g{a@صȽ۰?m49qKݸ觃MG<|WcԵnPqQ&m[gYw(u;ދii?DYe!eVb {K5j]wdsFLݻJ-wh}؍!ߣF[hkLE&6=1- H0ȼ8Ui9HChk8XYݬ\v4!;CV8xNŮb=u=>4;O:yv"<̈)|4f7 }v3l|^5='Peo!z!^Q.K>`"rf"c<^䱎WИfNw%IZsfA7WGVx\<'!SbG9-#ҺRrqwzTxY\+^9BۅSB(uadȽ<;]|/[`Zq<y"f2+݆ϑ 菏Ṃt;G_GSB]m|> c q9瑷џ#"?m Z`+u/EuQߤ4i!X+3P0>Dzhzx%5u-D]fߛ w`̸W ykabiVqwOxS:taSDơǔ6B=7&W@K2;6qpFwf>F~JsxͱfeK_ӍDҩJAB^qn@f]h*B֔<:xg=`O]w4|7 NSN&8d}Zgrތ(2Gcfv30gƧ~ Y.os^2kgNAv 7`CVf')D63l:'C'!9̂^h/\{#)uwB}\SyԚNg O:SP6Iϧ9syb'X(k znCEͤ<v[^ӌJQp!mP:VX:jYj@^(s;gR^Es y.zކ)ZEȅ1 .B0?r.-^f.J3S[Ҡғh֡CFt4fbl# x'IxA'e6Bu+,>ظbY>{W3Z_&1}_M,cI~#R.SWZ-;vBjyd]Բ8d4BN)aDl!W:ӫf@ĶɐҞubcW|!Yen_s"{)CH+LE5Qɳ z\&XLv XZEj|x<}-4(Aso9hbyEw!2Ӈ2dl>"J;LaCCjEic} e^:6³A<7!=Oe,ĪAŬbr*`,%n5Dֹ}L,4c@[ Xluv oOW3/'-gd#̨RgO(?hHd!x~}`3%~RJfV!b#čOViq|5"0G53rUZ# \]YMoѫj}Uld5KVNn1ZL>3"$nXU42y2;!(Uƹ@5N}#yb(;Lي,mL'ً,XvB_JϏ /G!vf=[z.9Mg\3%KcP7Q>r \;IPA_FJ&|:[> Abe 7An*ӎ5k}&<1d#"_YG r|Pyf$#PJ=/3[nB[nD.96C& CW B66`S,7ҷg/A6."5Wdt ;0~,e񙂦1[>tZMn +#DEOC~ B|O\Oy o;pp? 7An*/ WwQ=}N;J雿 M_QZYQy6ߡ_|PCV);%MI5)w޵檔K$&6&AjI6,[¨K 矑 RJFGs? Xq3॑*# SYFP>=ڽ]'Ru*|~*>R=)zYMRԳ9z5/BTTs!QӺjw*SQNX=ޝP}UQAjz^^SӹkN*#I$5/_轹DV*]V(GU=T 5RUөsJR*J.-**A~j:Gԓw}SMPSկp5Jf=CUɪ=4SmUYuU}T15QMSC5Z22j|#5_hgp%\7ߨAV  X0`L,6kgvQ}熻p  38~~p| .yp5ܬsw<1n</ë& =7^XV5tH& 5l;='~7|ps#,8%S,\r#o5]p/<24 a5jL_20րaʨQa*gp<gٚMp)\WMpf3<S,8ouX, 0G9*`Ô: Li+| ݸ뼚Jߒ,8MOEC*ڿ\edKz"ϕ;O$K2mf^_<%dYb$ze?օ#}L2O?/U͟Ug??W軍?[-U6uHUEk[5fVhXjku:kٮ]Î<;`{EWuϼ̼˲9"%IP($PJ$(H9P,IATrӭ)FdWw{G]OWW=ݓvvt.ꚺ_Ӄ8=ǠwmVNUnNT!;}exʲ7-r5NYN)ϟ..U9O㫧*?JtSKUJg>˗)˹ */wbRVbj]\zUy[;yAG4_r} lEAJe)E<ޔ)*pTgR*wMUuF1KS_2U/T孩Rbo9'F%68Am N#ucX !W|Y< <(@cXT*sA骺TJ{'o/p9=FX?u6Uq^=P^u>58ɭag <)O@nqgZ*O\OAqi'i7YWB m]ŵ\O\"wG#GZ'OJ{-5u5p[i5[f(5 U1*QMǨj8VA۴|5nſo.S:hيyזF%*D|*8:k[g[Anc jw;N4vw;R6i)`rQ.HGy(|s>*@ Q!HE$P"%{TJ@*E +2rG ;U;{E㐛PC-%Q[j #u7;. Q2%CaNݡB@QzހDM!Q?(Fh1} S3Ni1ԠsIKi)Ԣ~R6WPme=ԥl-k)mezU=C?U5%Ec4˨1>#v5&8Pcas0/exo ;B*<Ҩ40FWaʤ28S*T U+TV1x VFS+5@ ujh56jl?7uq]nJ 5t TzJe[b1mn%헱v,mex"bU9o(*A]􊼣Svʮ)'1r4XOuZ*Hu::=%Q@ũTRgTZ'PY*3Qy*3SУJ~PSuRS8ImEMCK/K:un:?JԋzBԇԟ"44DBCt  aA#tqEt CctIGt)@tiDtBStYFt9A3tyE#4 44Gi-Џ'D iLhBKhJ_-eqZA+tuZMu ZKkuMZGt-@6'Fצ-Eס;]u=~'I?E;hn@h~ !ӺY:OucHst烹|lcl»[ck@kTVpp==ޘ-?qo%l c0*Y 3JPCc/t`04RX_6 80^+^JzUdDvQL7D&G-Q}Dze7>"E%{= nQ5Dd,{qD&G'[pݣ#'(ywz"#EFȌ 36@f\ "D&L  2-@dzY"D  @d~ȇ" D> 5I!$@", Y y`+_, Y e"+DV Y UȺ "D6| MǂbU-"| 5@D~ )@d{Ȏ]"D7@f_2? r0@P#"GD6 "b)9 r2@T3"gD r)@rȕ"Dn  r;;wq.2EQwqt1A7A rݷ;~e5mj~Bmt[A_t~]ԃ`~G˯>#>>O}V}Q_[q+IӹJֵAV5Xn!UwN^ѯ{7xH-))! XYlVv+eXy}͸Edu!?78"}Gh,]`|7Jg2XVF+U X+e[!Xa+r,EVc]֋FYX⺒g9zHzި77z 2=S3k(#ޯ佳>ڥzR/+JJk}gwd|4{gn>">@3wѺw5쿩M-aP(FHa 1?&Da Le0fLaėa|'g`_ V*X͞c-|`=l7l٫?OvN>f} {p8 8p Nop9F"\p57&܂p U=U_=3jUsyD5U/fjZVjڪv^TU'7YuQ/)jڥv=jڧgUTauDUquBTNߴΨ:.꒺ꚺnꖺ Ҷi:JS~^7tsI-=@ c^?ӟ/;U'];.[{>_?_rVy֏OvkeX{}~u:dXGcqu:e~XgsyuѺd]XWkuuӺeݶ;3bۯ ,3_fYiVfYk2zl4l1ߚVf~0?v4n5~sl~19l9nN9m~3gYsΜ7W5s07-s CL36s\3\0%s\q^q^u^st^wpz9>N_My}}v}7~[w;quqxw;ѝNvSitw;ӝvsy#cSw]rWkܵW:w~nsptr;_܃a{=qϹ܋%{Ž^s7ܛmzӞ^;{G1w;N{yg9w].{W5wûn{w"##Q'FH$BHL$M$66IId$D2E2GDFdd䉌LLLLLLLL̈̌̊̎̑ϲ"++dT;Or|ߡ`n_=C. z8c8$ĭ#J:&q^ 2VYY7Uc;h1$+B1hoJzWʙTMUULJ[*,!A3 ?($[e˿F!;܍r7q|%!+3wοqq=wi?#H3ʹnYFťup5R#5iRKMFIQkwr(UMUj`:r8K8g|>eQblw|~ q3cM+ƴ3GΪ3hV#ӻ'q/FŞEw;2:e1I8dfjaK}c2nz1^/Ky^/%x^/rz^/x`xKQ?]JnQx]w{xL)0*s\xH TtN[ѹ6*LSqX@NRbk(m-<=ƞ88Mq~-TW uz>0PjP5F5ϱjbo/sIӱ0Y80[EK*?JIfoۭiwpNcx}3W`_cÅCBC0Khh}yCB`hrh }BCJhch+>ڎMCB{оlanה4s󈩈+puP( 'pCd$n M3:hQ&\)\ 7pp 6D . Ƹ-B%nn;xڏNKv^?;ݝxx;].h EvdG ܉p7_ x1<'$eoοbU,%+ c.;G0(7A’aż 8+ 6YY <}>yr9;+$@sZ3- ט̇H`_pJ/Rz~ 8`-|'3#J\E81>g y?J*ﶁܿ{U[M]gBz5Ql}=@pojr>q 3sm+-.mH Z{[˲7';2B_ BK|-0$Ј/ /_/tz I|a ӊ/_N|akXOUKZBc9òX kb}n] ];8W,¯q+cq8E(<UVK`Kb>cQXdcleD6Ų"_r"ay-ȖXQd+|Tdk|Ld"=Vّ/;c "}I7®/aϗa"-V8Fpw±dVdh7fT8|>dKd8o8os˰n%8o%9o8oO2/bU;2gQUuλ` _šw'8Or>ks>ގ|sǰlլ0s1Q69ź1 W<ߑc}O3`>|_W~pN )%ųb[JĒX:F3֪#c1BlE6E D6ÏD`˖VPdkLdp_Y}Z>$ry8"os)N8/Y"+$sSJM.}6Cl,ss  x QO3 q+r-dc6r_>(&<@V0Zxog^'V$a {(t Yl`;GwצU7Fqzn-MwNt&9)Tg3ݙwY|s;tiȦ ;ל s˹qHw;uK/ܥ2Kwu?#1{=s(KŒXrLe4*ʤrnm/rRnK Dũ$T*УTPujJ Nԙ^nԃ^^ԇ@LCh( 48@h M4۞aNK78WKH݅ҹw}:sGTV:=[/p9z Uzz^b_Յu%Zϒ2sݟtLSjUΟEĺ EbSg8~HRTVR[NAN8jLS)S>Gs,ϱ:.⿍e0 Q<s`*X3mKT^ rwc1ʟc\c]z=Y3Bʧ.{eS F^pkkkyTTpXՊ5培܍mm}ixfqv_^o}vB C7-#mJO3'>,hgtv9Ӿ뤜ވw|3|/l\}8jȅ%NvHsf&Or`7p覲G?B<ř;6+xnoTqy<29Kecķ_uskigs?qcUyG5u pb9'.gŌkwm&s['7#˵s͵41rpsBF ' X8n65lHTuq7LSWՆgrFY d]Ȏ)@[~Qr1ؒhjwp(F_8{=Y& @O*J26ٴ~)ܿ W@_d 0@ ɢ | JVB "@ rv90[Tp*S{wad a.N8V>M7ת.@F ֌93ۭ="iS4CWݤT:Itೃ[I&31v ۦuq`r/uK <ԓ ˣfB\tT@n~9w׍":c~]pؚefhDdb|UjNBI$ہhA`ش j /Z* Mq̸U2h1K>$cZ ﭢsa&18ZSG4v \ezQ`\F}0+ցa(=@KIMNh0߁=[6·v@oV#tŸ(d~DK*G#@ս %QԮfaq|g!υ> mS]3f,5ڢWk=>i\jI᪢`t!tg1%$~UV֘X`S/]8-z4BjQ~ڱTj0-=2:zpC97eܸR!;@V|=U0v.jK2KJW2OŕKrU| b5#'QB~ag'W2cL2f ;`d¨ #C[̖#}C&{6QEO= L54"j$6y'1 D NPZtrrX0!G MVQa)m;gd*y6TT9VqҾJ[iaq%!^1cW * m-i|ũ83=ĵ`BP >\ ݬnɮW21\ŇVՍcw"6F@KS:|QCgG_Y .m{=[KB]pdL[(Ѵ nA(;/au/TPЙQ2^QZM}g <ܥ]Zg^ҚXIݝ)C"#( s&M5 5pl^0// ؞씕Fїi_LNҔ˛[q|}iny>6jk ԏ qtYDe=OUμG 8Gzr&TTE.Ђ^VsQ@TMȽg:Xt+u-M{loZrQ2OOVgm)zu_[ k`vc:eņ+Z%}֜)0~0Z40C#u1Z;"k(;lJQyq3^݀ ϏRGW(>u| #PQI55CgGg(0}C]ڱRu(b S/ž<6`WJǺf8K&AT3ZX5+U2<<*JZ35p Alw7:/~",#!cqlM$BO/5yzG&f2ܔ)x{^%x4s%;#^_GwT,V̴͛lkӪP td(㳣mSSv@rU)7 p⁆Jf\.dsSJ'ߢ,o7޼mhaoU֯ޗ@VOFV&ۏDoΞ}\Sw98QI1s3 ̡wꮇ7 SQ8t-+'\6C@ *FWQg['y4/Wp~#T._;xJ̘yY3&nH:ɤl.gی'L/#È^rMۭ)?JdH'"#EJy%t=24G\'EOɛ0 QyW_L4_@RlT])9 Ђ [&HouOjȌh 0fN̲`cfjUi`UG\dR9P|;G{Pd hOUTi?XH\T{zʳ:Ȟ{Ou{]yUQb蠗.*a}nR3G(\Ѹ={S6n[PIAհe'` +r0,8'mq)?b endstream endobj 737 0 obj <<9892D77FE8C329459960386FF89CFEE2>] /Filter/FlateDecode/Length 1676>> stream x5 |u{3lw91m6fHQT5Lf)J(*EQQBrTD(:U<||Oy|Gz<~fkL3*n2!u݈]b52RiHF:WV݀k= ڰhhXn*#7h?ey#?(ftdt]gtyn,3 c`ыf66Y\a j'CCCƃ4&3ƌ5pҘYjGՎ$R7 SX'01ر{)U(il Zlx+~ !Q'[CWtc^X|]6욽~+mqʞK]F~(OdaF6?QvS~bJzezQv؅^4OB{#-E[jO7D?9jO0k4!yqqOV{w$}6~8a88qNI8c>"|_o[.p ~?eUCo;_7\_(1k b1*`&9ˆNTS#@3Ve&9EvUIH[E1ɉ)Z&9?UǨbq@+Ikdddkoj@M̪ AN+ 2Pf5,,",&h(HȮHh(h(h(HHh(ȵ(hHHh(h(h(H/n]n6Yn6w/8i iM111111186ii1iMMMMiMMMMMMMMMMiMMMMMMMMMMiMMMMMMMMMMiMMMMMMMMMMMiMMMMMMMMMMMiMMMMMMMMMMMiUii-ii iMMMMMMiMMMMMMM-?qJrFŊj2 .|xRW\"-\\\Ǫ X̖Ȇ endstream endobj xref 0 738 0000000130 65535 f 0000000017 00000 n 0000000126 00000 n 0000000365 00000 n 0000000635 00000 n 0000001704 00000 n 0000001864 00000 n 0000002088 00000 n 0000002253 00000 n 0000002482 00000 n 0000005774 00000 n 0000006190 00000 n 0000009348 00000 n 0000009472 00000 n 0000009502 00000 n 0000009654 00000 n 0000009728 00000 n 0000009971 00000 n 0000013898 00000 n 0000014029 00000 n 0000014200 00000 n 0000014441 00000 n 0000014572 00000 n 0000014883 00000 n 0000015014 00000 n 0000015145 00000 n 0000015276 00000 n 0000015635 00000 n 0000015766 00000 n 0000015897 00000 n 0000016028 00000 n 0000016159 00000 n 0000016509 00000 n 0000016640 00000 n 0000016992 00000 n 0000017123 00000 n 0000017466 00000 n 0000017821 00000 n 0000018164 00000 n 0000018522 00000 n 0000018850 00000 n 0000019187 00000 n 0000019531 00000 n 0000019857 00000 n 0000019988 00000 n 0000020119 00000 n 0000020451 00000 n 0000020773 00000 n 0000021122 00000 n 0000021451 00000 n 0000021582 00000 n 0000021902 00000 n 0000022260 00000 n 0000022606 00000 n 0000022737 00000 n 0000023074 00000 n 0000023411 00000 n 0000023743 00000 n 0000024072 00000 n 0000024203 00000 n 0000024523 00000 n 0000024835 00000 n 0000029348 00000 n 0000029402 00000 n 0000032414 00000 n 0000032468 00000 n 0000032655 00000 n 0000032835 00000 n 0000071118 00000 n 0000072815 00000 n 0000072994 00000 n 0000074919 00000 n 0000120546 00000 n 0000164641 00000 n 0000166424 00000 n 0000203838 00000 n 0000243082 00000 n 0000243142 00000 n 0000245183 00000 n 0000282924 00000 n 0000327435 00000 n 0000329016 00000 n 0000372362 00000 n 0000463500 00000 n 0000465475 00000 n 0000469402 00000 n 0000480294 00000 n 0000491186 00000 n 0000594643 00000 n 0000596979 00000 n 0000641264 00000 n 0000642787 00000 n 0000689942 00000 n 0000691142 00000 n 0000738438 00000 n 0000780991 00000 n 0000783485 00000 n 0000826038 00000 n 0000827711 00000 n 0000906540 00000 n 0000998841 00000 n 0001000133 00000 n 0001004061 00000 n 0001117791 00000 n 0001119153 00000 n 0001216434 00000 n 0001264761 00000 n 0001266247 00000 n 0001346383 00000 n 0001347991 00000 n 0001441842 00000 n 0001443664 00000 n 0001467782 00000 n 0001476890 00000 n 0001478413 00000 n 0001527419 00000 n 0001608148 00000 n 0001609750 00000 n 0001699697 00000 n 0001709136 00000 n 0001710662 00000 n 0001766207 00000 n 0001776169 00000 n 0001777252 00000 n 0001827067 00000 n 0001828743 00000 n 0001879940 00000 n 0001881345 00000 n 0001993427 00000 n 0001994858 00000 n 0000000131 65535 f 0000000132 65535 f 0000000133 65535 f 0000000134 65535 f 0000000135 65535 f 0000000136 65535 f 0000000137 65535 f 0000000138 65535 f 0000000139 65535 f 0000000140 65535 f 0000000141 65535 f 0000000142 65535 f 0000000143 65535 f 0000000144 65535 f 0000000145 65535 f 0000000146 65535 f 0000000147 65535 f 0000000148 65535 f 0000000149 65535 f 0000000150 65535 f 0000000151 65535 f 0000000152 65535 f 0000000153 65535 f 0000000154 65535 f 0000000155 65535 f 0000000156 65535 f 0000000157 65535 f 0000000158 65535 f 0000000159 65535 f 0000000160 65535 f 0000000161 65535 f 0000000162 65535 f 0000000163 65535 f 0000000164 65535 f 0000000165 65535 f 0000000166 65535 f 0000000167 65535 f 0000000168 65535 f 0000000169 65535 f 0000000170 65535 f 0000000171 65535 f 0000000172 65535 f 0000000173 65535 f 0000000174 65535 f 0000000175 65535 f 0000000176 65535 f 0000000177 65535 f 0000000178 65535 f 0000000179 65535 f 0000000180 65535 f 0000000181 65535 f 0000000182 65535 f 0000000183 65535 f 0000000184 65535 f 0000000185 65535 f 0000000186 65535 f 0000000187 65535 f 0000000188 65535 f 0000000189 65535 f 0000000190 65535 f 0000000191 65535 f 0000000192 65535 f 0000000193 65535 f 0000000194 65535 f 0000000195 65535 f 0000000196 65535 f 0000000197 65535 f 0000000198 65535 f 0000000199 65535 f 0000000200 65535 f 0000000201 65535 f 0000000202 65535 f 0000000203 65535 f 0000000204 65535 f 0000000205 65535 f 0000000206 65535 f 0000000207 65535 f 0000000208 65535 f 0000000209 65535 f 0000000210 65535 f 0000000211 65535 f 0000000212 65535 f 0000000213 65535 f 0000000214 65535 f 0000000215 65535 f 0000000216 65535 f 0000000217 65535 f 0000000218 65535 f 0000000219 65535 f 0000000220 65535 f 0000000221 65535 f 0000000222 65535 f 0000000223 65535 f 0000000224 65535 f 0000000225 65535 f 0000000226 65535 f 0000000227 65535 f 0000000228 65535 f 0000000229 65535 f 0000000230 65535 f 0000000231 65535 f 0000000232 65535 f 0000000233 65535 f 0000000234 65535 f 0000000235 65535 f 0000000236 65535 f 0000000237 65535 f 0000000238 65535 f 0000000239 65535 f 0000000240 65535 f 0000000241 65535 f 0000000242 65535 f 0000000243 65535 f 0000000244 65535 f 0000000245 65535 f 0000000246 65535 f 0000000247 65535 f 0000000248 65535 f 0000000249 65535 f 0000000250 65535 f 0000000251 65535 f 0000000252 65535 f 0000000253 65535 f 0000000254 65535 f 0000000255 65535 f 0000000256 65535 f 0000000257 65535 f 0000000258 65535 f 0000000259 65535 f 0000000260 65535 f 0000000261 65535 f 0000000262 65535 f 0000000263 65535 f 0000000264 65535 f 0000000265 65535 f 0000000266 65535 f 0000000267 65535 f 0000000268 65535 f 0000000269 65535 f 0000000270 65535 f 0000000271 65535 f 0000000272 65535 f 0000000273 65535 f 0000000274 65535 f 0000000275 65535 f 0000000276 65535 f 0000000277 65535 f 0000000278 65535 f 0000000279 65535 f 0000000280 65535 f 0000000281 65535 f 0000000282 65535 f 0000000283 65535 f 0000000284 65535 f 0000000285 65535 f 0000000286 65535 f 0000000287 65535 f 0000000288 65535 f 0000000289 65535 f 0000000290 65535 f 0000000291 65535 f 0000000292 65535 f 0000000293 65535 f 0000000294 65535 f 0000000295 65535 f 0000000296 65535 f 0000000297 65535 f 0000000298 65535 f 0000000299 65535 f 0000000300 65535 f 0000000301 65535 f 0000000302 65535 f 0000000303 65535 f 0000000304 65535 f 0000000305 65535 f 0000000306 65535 f 0000000307 65535 f 0000000308 65535 f 0000000309 65535 f 0000000310 65535 f 0000000311 65535 f 0000000312 65535 f 0000000313 65535 f 0000000314 65535 f 0000000315 65535 f 0000000316 65535 f 0000000317 65535 f 0000000318 65535 f 0000000319 65535 f 0000000320 65535 f 0000000321 65535 f 0000000322 65535 f 0000000323 65535 f 0000000324 65535 f 0000000325 65535 f 0000000326 65535 f 0000000327 65535 f 0000000328 65535 f 0000000329 65535 f 0000000330 65535 f 0000000331 65535 f 0000000332 65535 f 0000000333 65535 f 0000000334 65535 f 0000000335 65535 f 0000000336 65535 f 0000000337 65535 f 0000000338 65535 f 0000000339 65535 f 0000000340 65535 f 0000000341 65535 f 0000000342 65535 f 0000000343 65535 f 0000000344 65535 f 0000000345 65535 f 0000000346 65535 f 0000000347 65535 f 0000000348 65535 f 0000000349 65535 f 0000000350 65535 f 0000000351 65535 f 0000000352 65535 f 0000000353 65535 f 0000000354 65535 f 0000000355 65535 f 0000000356 65535 f 0000000357 65535 f 0000000358 65535 f 0000000359 65535 f 0000000360 65535 f 0000000361 65535 f 0000000362 65535 f 0000000363 65535 f 0000000364 65535 f 0000000365 65535 f 0000000366 65535 f 0000000367 65535 f 0000000368 65535 f 0000000369 65535 f 0000000370 65535 f 0000000371 65535 f 0000000372 65535 f 0000000373 65535 f 0000000374 65535 f 0000000375 65535 f 0000000376 65535 f 0000000377 65535 f 0000000378 65535 f 0000000379 65535 f 0000000380 65535 f 0000000381 65535 f 0000000382 65535 f 0000000383 65535 f 0000000384 65535 f 0000000385 65535 f 0000000386 65535 f 0000000387 65535 f 0000000388 65535 f 0000000389 65535 f 0000000390 65535 f 0000000391 65535 f 0000000392 65535 f 0000000393 65535 f 0000000394 65535 f 0000000395 65535 f 0000000396 65535 f 0000000397 65535 f 0000000398 65535 f 0000000399 65535 f 0000000400 65535 f 0000000401 65535 f 0000000402 65535 f 0000000403 65535 f 0000000404 65535 f 0000000405 65535 f 0000000406 65535 f 0000000407 65535 f 0000000408 65535 f 0000000409 65535 f 0000000410 65535 f 0000000411 65535 f 0000000412 65535 f 0000000413 65535 f 0000000414 65535 f 0000000415 65535 f 0000000416 65535 f 0000000417 65535 f 0000000418 65535 f 0000000419 65535 f 0000000420 65535 f 0000000421 65535 f 0000000422 65535 f 0000000423 65535 f 0000000424 65535 f 0000000425 65535 f 0000000426 65535 f 0000000427 65535 f 0000000428 65535 f 0000000429 65535 f 0000000430 65535 f 0000000431 65535 f 0000000432 65535 f 0000000433 65535 f 0000000434 65535 f 0000000435 65535 f 0000000436 65535 f 0000000437 65535 f 0000000438 65535 f 0000000439 65535 f 0000000440 65535 f 0000000441 65535 f 0000000442 65535 f 0000000443 65535 f 0000000444 65535 f 0000000445 65535 f 0000000446 65535 f 0000000447 65535 f 0000000448 65535 f 0000000449 65535 f 0000000450 65535 f 0000000451 65535 f 0000000452 65535 f 0000000453 65535 f 0000000454 65535 f 0000000455 65535 f 0000000456 65535 f 0000000457 65535 f 0000000458 65535 f 0000000459 65535 f 0000000460 65535 f 0000000461 65535 f 0000000462 65535 f 0000000463 65535 f 0000000464 65535 f 0000000465 65535 f 0000000466 65535 f 0000000467 65535 f 0000000468 65535 f 0000000469 65535 f 0000000470 65535 f 0000000471 65535 f 0000000472 65535 f 0000000473 65535 f 0000000474 65535 f 0000000475 65535 f 0000000476 65535 f 0000000477 65535 f 0000000478 65535 f 0000000479 65535 f 0000000480 65535 f 0000000481 65535 f 0000000482 65535 f 0000000483 65535 f 0000000484 65535 f 0000000485 65535 f 0000000486 65535 f 0000000487 65535 f 0000000488 65535 f 0000000489 65535 f 0000000490 65535 f 0000000491 65535 f 0000000492 65535 f 0000000493 65535 f 0000000494 65535 f 0000000495 65535 f 0000000496 65535 f 0000000497 65535 f 0000000498 65535 f 0000000499 65535 f 0000000500 65535 f 0000000501 65535 f 0000000502 65535 f 0000000503 65535 f 0000000504 65535 f 0000000505 65535 f 0000000506 65535 f 0000000507 65535 f 0000000508 65535 f 0000000509 65535 f 0000000510 65535 f 0000000511 65535 f 0000000512 65535 f 0000000513 65535 f 0000000514 65535 f 0000000515 65535 f 0000000516 65535 f 0000000517 65535 f 0000000518 65535 f 0000000519 65535 f 0000000520 65535 f 0000000521 65535 f 0000000522 65535 f 0000000523 65535 f 0000000524 65535 f 0000000525 65535 f 0000000526 65535 f 0000000527 65535 f 0000000528 65535 f 0000000529 65535 f 0000000530 65535 f 0000000531 65535 f 0000000532 65535 f 0000000533 65535 f 0000000534 65535 f 0000000535 65535 f 0000000536 65535 f 0000000537 65535 f 0000000538 65535 f 0000000539 65535 f 0000000540 65535 f 0000000541 65535 f 0000000542 65535 f 0000000543 65535 f 0000000544 65535 f 0000000545 65535 f 0000000546 65535 f 0000000547 65535 f 0000000548 65535 f 0000000549 65535 f 0000000550 65535 f 0000000551 65535 f 0000000552 65535 f 0000000553 65535 f 0000000554 65535 f 0000000555 65535 f 0000000556 65535 f 0000000557 65535 f 0000000558 65535 f 0000000559 65535 f 0000000560 65535 f 0000000561 65535 f 0000000562 65535 f 0000000563 65535 f 0000000564 65535 f 0000000565 65535 f 0000000566 65535 f 0000000567 65535 f 0000000568 65535 f 0000000569 65535 f 0000000570 65535 f 0000000571 65535 f 0000000572 65535 f 0000000573 65535 f 0000000574 65535 f 0000000575 65535 f 0000000576 65535 f 0000000577 65535 f 0000000578 65535 f 0000000579 65535 f 0000000580 65535 f 0000000581 65535 f 0000000582 65535 f 0000000583 65535 f 0000000584 65535 f 0000000585 65535 f 0000000586 65535 f 0000000587 65535 f 0000000588 65535 f 0000000589 65535 f 0000000590 65535 f 0000000591 65535 f 0000000592 65535 f 0000000593 65535 f 0000000594 65535 f 0000000595 65535 f 0000000596 65535 f 0000000597 65535 f 0000000598 65535 f 0000000599 65535 f 0000000600 65535 f 0000000601 65535 f 0000000602 65535 f 0000000603 65535 f 0000000604 65535 f 0000000605 65535 f 0000000606 65535 f 0000000607 65535 f 0000000608 65535 f 0000000609 65535 f 0000000610 65535 f 0000000611 65535 f 0000000612 65535 f 0000000613 65535 f 0000000614 65535 f 0000000615 65535 f 0000000616 65535 f 0000000617 65535 f 0000000618 65535 f 0000000619 65535 f 0000000620 65535 f 0000000621 65535 f 0000000622 65535 f 0000000623 65535 f 0000000624 65535 f 0000000625 65535 f 0000000626 65535 f 0000000627 65535 f 0000000628 65535 f 0000000629 65535 f 0000000630 65535 f 0000000631 65535 f 0000000632 65535 f 0000000633 65535 f 0000000634 65535 f 0000000635 65535 f 0000000636 65535 f 0000000637 65535 f 0000000638 65535 f 0000000639 65535 f 0000000640 65535 f 0000000641 65535 f 0000000642 65535 f 0000000643 65535 f 0000000644 65535 f 0000000645 65535 f 0000000646 65535 f 0000000647 65535 f 0000000648 65535 f 0000000649 65535 f 0000000650 65535 f 0000000651 65535 f 0000000652 65535 f 0000000653 65535 f 0000000654 65535 f 0000000655 65535 f 0000000656 65535 f 0000000657 65535 f 0000000658 65535 f 0000000659 65535 f 0000000660 65535 f 0000000661 65535 f 0000000662 65535 f 0000000663 65535 f 0000000664 65535 f 0000000665 65535 f 0000000666 65535 f 0000000667 65535 f 0000000668 65535 f 0000000669 65535 f 0000000670 65535 f 0000000671 65535 f 0000000672 65535 f 0000000673 65535 f 0000000674 65535 f 0000000675 65535 f 0000000676 65535 f 0000000677 65535 f 0000000678 65535 f 0000000679 65535 f 0000000680 65535 f 0000000681 65535 f 0000000682 65535 f 0000000683 65535 f 0000000684 65535 f 0000000685 65535 f 0000000686 65535 f 0000000687 65535 f 0000000688 65535 f 0000000689 65535 f 0000000690 65535 f 0000000691 65535 f 0000000692 65535 f 0000000693 65535 f 0000000694 65535 f 0000000695 65535 f 0000000696 65535 f 0000000697 65535 f 0000000698 65535 f 0000000699 65535 f 0000000700 65535 f 0000000701 65535 f 0000000702 65535 f 0000000703 65535 f 0000000704 65535 f 0000000705 65535 f 0000000706 65535 f 0000000707 65535 f 0000000708 65535 f 0000000709 65535 f 0000000710 65535 f 0000000711 65535 f 0000000712 65535 f 0000000713 65535 f 0000000714 65535 f 0000000715 65535 f 0000000716 65535 f 0000000717 65535 f 0000000718 65535 f 0000000719 65535 f 0000000720 65535 f 0000000721 65535 f 0000000722 65535 f 0000000723 65535 f 0000000724 65535 f 0000000725 65535 f 0000000726 65535 f 0000000727 65535 f 0000000728 65535 f 0000000729 65535 f 0000000000 65535 f 0002003386 00000 n 0002003807 00000 n 0002064975 00000 n 0002065359 00000 n 0002065799 00000 n 0002066119 00000 n 0002066369 00000 n 0002148396 00000 n trailer <<9892D77FE8C329459960386FF89CFEE2>] >> startxref 2150277 %%EOF xref 0 0 trailer <<9892D77FE8C329459960386FF89CFEE2>] /Prev 2150277/XRefStm 2148396>> startxref 2165199 %%EOFPK\>qvv default/plugins/payment/dibs.phpnu[ '208', 'EUR' => '978', 'USD' => '840', 'GBP' => '826', 'SEK' => '752', 'AUD' => '036', 'CAD' => '124', 'ISK' => '352', 'JPY' => '392', 'NZD' => '554', 'NOK' => '578', 'CHF' => '756', 'TRY' => '949'); public function supportsCancelPage() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant', array('size' => 20, 'maxlength' => 16)) ->setLabel("Dibs Merchant ID") ->addRule('required'); $form->addText('key1', array('size' => 20, 'maxlength' => 32)) ->setLabel("Dibs Secret Key1") ->addRule('required'); $form->addText('key2', array('size' => 20, 'maxlength' => 32)) ->setLabel("Dibs Secret Key2") ->addRule('required'); $form->addSelect('lang', array(), array('options' => array( 'da' => 'Danish', 'sv' => 'Swedish', 'no' => 'Norwegian', 'en' => 'English', 'nl' => 'Dutch', 'de' => 'German', 'fr' => 'French', 'fi' => 'Finnish', 'es' => 'Spanish', 'it' => 'Italian', 'fo' => 'Faroese', 'pl' => 'Polish' )))->setLabel('The payment window language'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } function getReadme() { return <<DIBS Payment Plugin Configuration 1. Login to DIBS Administration and then go to "integration" -> Return Values. 2. Please check "orderid" parameter. CUT; } public function getSupportedCurrencies() { return array( 'DKK', 'DKK', 'USD', 'GBP', 'SEK', 'AUD', 'CAD', 'ISK', 'JPY', 'NZD', 'NOK', 'CHF', 'TRY'); } public function init() { parent::init(); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $currency = $this->getCurrencyCode($invoice); $a->md5key = md5($s2 = $this->getConfig('key2') . md5($s1 = $this->getConfig('key1') . "merchant=" . $this->getConfig('merchant') . "&orderid=" . $invoice->public_id . "¤cy=" . $currency . "&amount=" . intval($invoice->first_total * 100))); $a->merchant = $this->getConfig('merchant'); $a->amount = intval($invoice->first_total * 100); $a->currency = $currency; $a->orderid = $invoice->public_id; $a->lang = $this->getConfig('lang'); $a->accepturl = $this->getReturnUrl($request); $a->cancelurl = $this->getCancelUrl($request); $a->continueurl = $this->getReturnUrl(); $a->callbackurl = $this->getPluginUrl('ipn'); $a->capturenow = 1; if($this->getConfig('testing')) $a->test = 'yes'; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Dibs($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getCurrencyCode($invoice) { return $this->currency_codes[strtoupper($invoice->currency)]; } } class Am_Paysystem_Transaction_Dibs extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('orderid'); } public function getUniqId() { return $this->request->get("transact"); } public function validateSource() { if (!$this->invoice = $this->loadInvoice($this->request->get('orderid'))) { throw new Am_Exception_Paysystem_TransactionInvalid("Can not find invoice!"); } $amount = $this->invoice->first_total * 100; $currency = $this->plugin->getCurrencyCode($this->invoice); $authkey = md5($this->plugin->getConfig('key2') . md5($s = $this->plugin->getConfig('key1') . "transact=" . $this->request->get('transact') . "&amount=" . $amount . "¤cy=" . $currency)); if ($authkey != $this->request->get('authkey')) { throw new Am_Exception_Paysystem_TransactionInvalid("IPN validation failed!"); } return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } }PK\ZOO#default/plugins/payment/flexpay.phpnu[addAdvRadio('brand') ->setLabel('Brand') ->loadOptions(array( 'Verotel' => 'Verotel', 'CardBilling' => 'CardBilling', 'FreenomPay' => 'FreenomPay' )); $form->addText('shop_id') ->setLabel('Shop Id'); $form->addText('signature_key', array('class' => 'el-wide')) ->setLabel("Signature Key"); } public function isConfigured() { return $this->getConfig('shop_id') && $this->getConfig('signature_key'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $action = new Am_Paysystem_Action_Redirect($this->getEndpoint()); $vars = array( 'backURL' => $this->getReturnUrl(), 'custom1' => $invoice->public_id, 'declineURL' => $this->getCancelUrl(), 'referenceID' => $invoice->public_id, 'shopID' => $this->getConfig('shop_id'), 'priceCurrency' => $invoice->currency, 'version' => '3.4' ); if ((float)$invoice->second_total) { $vars['name'] = $invoice->getLineDescription(); $vars['type'] = 'subscription'; $vars['subscriptionType'] = 'recurring'; if ($invoice->first_total != $invoice->second_total) { $vars['priceAmount'] = $invoice->second_total; $vars['trialAmount'] = $invoice->first_total; $vars['period'] = $this->getPeriod($invoice->second_period); $vars['trialPeriod'] = $this->getPeriod($invoice->first_period); } else { $vars['priceAmount'] = $invoice->first_total; $vars['period'] = $this->getPeriod($invoice->first_period); } } else{ $vars['description'] = $invoice->getLineDescription(); $vars['type'] = 'purchase'; $vars['priceAmount'] = $invoice->first_total; } $action->signature = $this->getHash($vars); $action->email = $invoice->getEmail(); foreach ($vars as $k => $v) { $action->addParam($k, $v); } $result->setAction($action); } function getPeriod($period) { $p = new Am_Period($period); return sprintf("P%d%s", $p->getCount(), strtoupper($p->getUnit())); } function getHash($vars) { ksort($vars); $hashstring = $this->getConfig('signature_key'); foreach ($vars as $name => $value) { $hashstring .= sprintf(':%s=%s', $name, $value); } return sha1($hashstring); } function getEndpoint() { switch ($this->getConfig('brand')) { case 'Verotel': return 'https://secure.verotel.com/startorder'; case 'CardBilling': return 'https://secure.billing.creditcard/startorder'; case 'FreenomPay': return 'https://secure.freenompay.com/startorder'; } } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch ($request->getParam('event', 'initial')) { case 'initial': return new Am_Paysystem_Transaction_FlexpayInitial($this, $request, $response, $invokeArgs); case 'credit': return new Am_Paysystem_Transaction_FlexpayCredit($this, $request, $response, $invokeArgs); case 'rebill': return new Am_Paysystem_Transaction_FlexpayRebill($this, $request, $response, $invokeArgs); case 'cancel': return new Am_Paysystem_Transaction_FlexpayCancel($this, $request, $response, $invokeArgs); default: return new Am_Paysystem_Transaction_FlexpayNull($this, $request, $response, $invokeArgs); } } function getReadme() { $ipn = $this->getPluginUrl('ipn'); return <<request->get('custom1'); } public function getUniqId() { return $this->request->get('transactionID'); } public function validateSource() { $this->_checkIp(<<request->getRequestOnlyParams(); $signature = $params['signature']; unset($params['signature']); return $this->plugin->getHash($params) == $signature; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_FlexpayInitial extends Am_Paysystem_Transaction_Flexpay { public function processValidated() { $this->invoice->addPayment($this); echo "OK"; exit; } } class Am_Paysystem_Transaction_FlexpayCredit extends Am_Paysystem_Transaction_Flexpay { public function processValidated() { $this->invoice->addRefund($this, $this->request->get('parentID')); echo "OK"; exit; } } class Am_Paysystem_Transaction_FlexpayRebill extends Am_Paysystem_Transaction_Flexpay { public function processValidated() { $this->invoice->addPayment($this); echo "OK"; exit; } } class Am_Paysystem_Transaction_FlexpayCancel extends Am_Paysystem_Transaction_Flexpay { public function processValidated() { $this->invoice->setCancelled(true); echo "OK"; exit; } } class Am_Paysystem_Transaction_FlexpayNull extends Am_Paysystem_Transaction_Flexpay { public function processValidated() { echo "OK"; exit; } }PK\t/default/plugins/payment/payssion/lib/cacert.pemnu[## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Wed Sep 2 18:30:34 2015 ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates ## file (certdata.txt). This file can be found in the mozilla source tree: ## http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl version 1.25. ## SHA1: ed3c0bbfb7912bcc00cd2033b0cb85c98d10559c ## Equifax Secure CA ================= -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW 8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 70+sB3c4 -----END CERTIFICATE----- GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- GlobalSign Root CA - R2 ======================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- Verisign Class 4 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM 8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== -----END CERTIFICATE----- Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= -----END CERTIFICATE----- Baltimore CyberTrust Root ========================= -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- AddTrust Low-Value Services Root ================================ -----BEGIN CERTIFICATE----- MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= -----END CERTIFICATE----- AddTrust External Root ====================== -----BEGIN CERTIFICATE----- MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- AddTrust Public Services Root ============================= -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL +YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= -----END CERTIFICATE----- AddTrust Qualified Certificates Root ==================================== -----BEGIN CERTIFICATE----- MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx 64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= -----END CERTIFICATE----- Entrust Root Certification Authority ==================================== -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- RSA Security 2048 v3 ==================== -----BEGIN CERTIFICATE----- MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP +Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj 0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA pKnXwiJPZ9d37CAFYd4= -----END CERTIFICATE----- GeoTrust Global CA ================== -----BEGIN CERTIFICATE----- MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm Mw== -----END CERTIFICATE----- GeoTrust Global CA 2 ==================== -----BEGIN CERTIFICATE----- MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF H4z1Ir+rzoPz4iIprn2DQKi6bA== -----END CERTIFICATE----- GeoTrust Universal CA ===================== -----BEGIN CERTIFICATE----- MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI P/rmMuGNG2+k5o7Y+SlIis5z/iw= -----END CERTIFICATE----- GeoTrust Universal CA 2 ======================= -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- Visa eCommerce Root =================== -----BEGIN CERTIFICATE----- MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt 398znM/jra6O1I7mT1GvFpLgXPYHDw== -----END CERTIFICATE----- Certum Root CA ============== -----BEGIN CERTIFICATE----- MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== -----END CERTIFICATE----- Comodo AAA Services root ======================== -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- Comodo Secure Services root =========================== -----BEGIN CERTIFICATE----- MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP 9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm 4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H RR3B7Hzs/Sk= -----END CERTIFICATE----- Comodo Trusted Services root ============================ -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y /9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O 9y5Xt5hwXsjEeLBi -----END CERTIFICATE----- QuoVadis Root CA ================ -----BEGIN CERTIFICATE----- MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi 5nrQNiOKSnQ2+Q== -----END CERTIFICATE----- QuoVadis Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- QuoVadis Root CA 3 ================== -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- Security Communication Root CA ============================== -----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi FL39vmwLAw== -----END CERTIFICATE----- Sonera Class 2 Root CA ====================== -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH llpwrN9M -----END CERTIFICATE----- Staat der Nederlanden Root CA ============================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== -----END CERTIFICATE----- UTN DATACorp SGC Root CA ======================== -----BEGIN CERTIFICATE----- MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA 9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv 33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI -----END CERTIFICATE----- UTN USERFirst Hardware Root CA ============================== -----BEGIN CERTIFICATE----- MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 nfhmqA== -----END CERTIFICATE----- Camerfirma Chambers of Commerce Root ==================================== -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 erfutGWaIZDgqtCYvDi1czyL+Nw= -----END CERTIFICATE----- Camerfirma Global Chambersign Root ================================== -----BEGIN CERTIFICATE----- MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- NetLock Notary (Class A) Root ============================= -----BEGIN CERTIFICATE----- MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC /tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM 8CgHrTwXZoi1/baI -----END CERTIFICATE----- XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- Go Daddy Class 2 CA =================== -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b vZ8= -----END CERTIFICATE----- Starfield Class 2 CA ==================== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- StartCom Certification Authority ================================ -----BEGIN CERTIFICATE----- MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro g14= -----END CERTIFICATE----- Taiwan GRCA =========== -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS -----END CERTIFICATE----- Swisscom Root CA 1 ================== -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4 MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn 7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5 haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9 MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3 1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW NY6E0F/6MBr1mmz0DlP5OlvRHA== -----END CERTIFICATE----- DigiCert Assured ID Root CA =========================== -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- DigiCert Global Root CA ======================= -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- DigiCert High Assurance EV Root CA ================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K -----END CERTIFICATE----- Certplus Class 2 Primary CA =========================== -----BEGIN CERTIFICATE----- MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 l7+ijrRU -----END CERTIFICATE----- DST Root CA X3 ============== -----BEGIN CERTIFICATE----- MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- DST ACES CA X6 ============== -----BEGIN CERTIFICATE----- MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 oKfN5XozNmr6mis= -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 1 ============================================== -----BEGIN CERTIFICATE----- MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ 8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 2 ============================================== -----BEGIN CERTIFICATE----- MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr 5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P 9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 UrbnBEI= -----END CERTIFICATE----- SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- SwissSign Silver CA - G2 ======================== -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- GeoTrust Primary Certification Authority ======================================== -----BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= -----END CERTIFICATE----- thawte Primary Root CA ====================== -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== -----END CERTIFICATE----- VeriSign Class 3 Public Primary Certification Authority - G5 ============================================================ -----BEGIN CERTIFICATE----- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq -----END CERTIFICATE----- SecureTrust CA ============== -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- Secure Global CA ================ -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- COMODO Certification Authority ============================== -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== -----END CERTIFICATE----- Network Solutions Certificate Authority ======================================= -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- WellsSecure Public Root Certificate Authority ============================================= -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ tylv2G0xffX8oRAHh84vWdw+WNs= -----END CERTIFICATE----- COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- IGC/A ===== -----BEGIN CERTIFICATE----- MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF 0mBWWg== -----END CERTIFICATE----- Security Communication EV RootCA1 ================================= -----BEGIN CERTIFICATE----- MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 -----END CERTIFICATE----- OISTE WISeKey Global Root GA CA =============================== -----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= -----END CERTIFICATE----- Microsec e-Szigno Root CA ========================= -----BEGIN CERTIFICATE----- MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA 4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a 86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= -----END CERTIFICATE----- Certigna ======== -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- TC TrustCenter Class 2 CA II ============================ -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB 7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk vQ== -----END CERTIFICATE----- TC TrustCenter Universal CA I ============================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG 1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a 7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY -----END CERTIFICATE----- Deutsche Telekom Root CA 2 ========================== -----BEGIN CERTIFICATE----- MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- ComSign Secured CA ================== -----BEGIN CERTIFICATE----- MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs 49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH 7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP 51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== -----END CERTIFICATE----- Cybertrust Global Root ====================== -----BEGIN CERTIFICATE----- MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW WL1WMRJOEcgh4LMRkWXbtKaIOM5V -----END CERTIFICATE----- ePKI Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 ============================================================================================================================= -----BEGIN CERTIFICATE----- MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= -----END CERTIFICATE----- Buypass Class 2 CA 1 ==================== -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV 1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt 7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- Buypass Class 3 CA 1 ==================== -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c 1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 -----END CERTIFICATE----- EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 ========================================================================== -----BEGIN CERTIFICATE----- MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK 1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt 2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT -----END CERTIFICATE----- certSIGN ROOT CA ================ -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD -----END CERTIFICATE----- CNNIC ROOT ========== -----BEGIN CERTIFICATE----- MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m mxE= -----END CERTIFICATE----- ApplicationCA - Japanese Government =================================== -----BEGIN CERTIFICATE----- MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g /DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL rosot4LKGAfmt1t06SAZf7IbiVQ= -----END CERTIFICATE----- GeoTrust Primary Certification Authority - G3 ============================================= -----BEGIN CERTIFICATE----- MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt -----END CERTIFICATE----- thawte Primary Root CA - G2 =========================== -----BEGIN CERTIFICATE----- MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== -----END CERTIFICATE----- thawte Primary Root CA - G3 =========================== -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= -----END CERTIFICATE----- GeoTrust Primary Certification Authority - G2 ============================================= -----BEGIN CERTIFICATE----- MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 npaqBA+K -----END CERTIFICATE----- VeriSign Universal Root Certification Authority =============================================== -----BEGIN CERTIFICATE----- MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 mJO37M2CYfE45k+XmCpajQ== -----END CERTIFICATE----- VeriSign Class 3 Public Primary Certification Authority - G4 ============================================================ -----BEGIN CERTIFICATE----- MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== -----END CERTIFICATE----- NetLock Arany (Class Gold) FÅ‘tanúsítvány ============================================ -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- Staat der Nederlanden Root CA - G2 ================================== -----BEGIN CERTIFICATE----- MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm 66+KAQ== -----END CERTIFICATE----- CA Disig ======== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA 4Z7CRneC9VkGjCFMhwnN5ag= -----END CERTIFICATE----- Juur-SK ======= -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC +Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 yyqcjg== -----END CERTIFICATE----- Hongkong Post Root CA 1 ======================= -----BEGIN CERTIFICATE----- MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== -----END CERTIFICATE----- SecureSign RootCA11 =================== -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= -----END CERTIFICATE----- ACEDICOM Root ============= -----BEGIN CERTIFICATE----- MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA== -----END CERTIFICATE----- Microsec e-Szigno Root CA 2009 ============================== -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi LXpUq3DDfSJlgnCW -----END CERTIFICATE----- GlobalSign Root CA - R3 ======================= -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r kpeDMdmztcpHWD9f -----END CERTIFICATE----- Autoridad de Certificacion Firmaprofesional CIF A62634068 ========================================================= -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -----END CERTIFICATE----- Izenpe.com ========== -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- Chambers of Commerce Root - 2008 ================================ -----BEGIN CERTIFICATE----- MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ -----END CERTIFICATE----- Global Chambersign Root - 2008 ============================== -----BEGIN CERTIFICATE----- MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B -----END CERTIFICATE----- Go Daddy Root Certificate Authority - G2 ======================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 -----END CERTIFICATE----- Starfield Root Certificate Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- Starfield Services Root Certificate Authority - G2 ================================================== -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 -----END CERTIFICATE----- AffirmTrust Commercial ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- AffirmTrust Networking ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- AffirmTrust Premium =================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== -----END CERTIFICATE----- AffirmTrust Premium ECC ======================= -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM eQ== -----END CERTIFICATE----- Certum Trusted Network CA ========================= -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- Certinomis - Autorité Racine ============================= -----BEGIN CERTIFICATE----- MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ vgt2Fl43N+bYdJeimUV5 -----END CERTIFICATE----- Root CA Generalitat Valenciana ============================== -----BEGIN CERTIFICATE----- MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt +GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= -----END CERTIFICATE----- A-Trust-nQual-03 ================ -----BEGIN CERTIFICATE----- MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 ahq97BvIxYSazQ== -----END CERTIFICATE----- TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- Security Communication RootCA2 ============================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- EC-ACC ====== -----BEGIN CERTIFICATE----- MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D 5EI= -----END CERTIFICATE----- Hellenic Academic and Research Institutions RootCA 2011 ======================================================= -----BEGIN CERTIFICATE----- MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 -----END CERTIFICATE----- Actalis Authentication Root CA ============================== -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- Trustis FPS Root CA =================== -----BEGIN CERTIFICATE----- MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl iB6XzCGcKQENZetX2fNXlrtIzYE= -----END CERTIFICATE----- StartCom Certification Authority ================================ -----BEGIN CERTIFICATE----- MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= -----END CERTIFICATE----- StartCom Certification Authority G2 =================================== -----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm obp573PYtlNXLfbQ4ddI -----END CERTIFICATE----- Buypass Class 2 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN rJgWVqA= -----END CERTIFICATE----- Buypass Class 3 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi Cp/HuZc= -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 3 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== -----END CERTIFICATE----- EE Certification Centre Root CA =============================== -----BEGIN CERTIFICATE----- MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM dcGWxZ0= -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 2007 ================================================= -----BEGIN CERTIFICATE----- MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK poRq0Tl9 -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 2009 ============================== -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 EV 2009 ================================= -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv w9y4AyHqnxbxLFS1 -----END CERTIFICATE----- PSCProcert ========== -----BEGIN CERTIFICATE----- MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/ AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km -----END CERTIFICATE----- China Internet Network Information Center EV Certificates Root ============================================================== -----BEGIN CERTIFICATE----- MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV 98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23 KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC 7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5 0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM 7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0 5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8= -----END CERTIFICATE----- Swisscom Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2 MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3 qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ 82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o +sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX 5OfNeOI5wSsSnqaeG8XmDtkx2Q== -----END CERTIFICATE----- Swisscom Root EV CA 2 ===================== -----BEGIN CERTIFICATE----- MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/ BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7 XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH 59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/ 23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc= -----END CERTIFICATE----- CA Disig Root R1 ================ -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ a7+h89n07eLw4+1knj0vllJPgFOL -----END CERTIFICATE----- CA Disig Root R2 ================ -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV 7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- ACCVRAIZ1 ========= -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p EfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- TWCA Global Root CA =================== -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= -----END CERTIFICATE----- TeliaSonera Root CA v1 ====================== -----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- E-Tugra Certification Authority =============================== -----BEGIN CERTIFICATE----- MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G C7TbO6Orb1wdtn7os4I07QZcJA== -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 2 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== -----END CERTIFICATE----- Atos TrustedRoot 2011 ===================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- QuoVadis Root CA 1 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV hMJKzRwuJIczYOXD -----END CERTIFICATE----- QuoVadis Root CA 2 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr O3jtZsSOeWmD3n+M -----END CERTIFICATE----- QuoVadis Root CA 3 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- DigiCert Assured ID Root G2 =========================== -----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- DigiCert Assured ID Root G3 =========================== -----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy 1vUhZscv6pZjamVFkpUBtA== -----END CERTIFICATE----- DigiCert Global Root G2 ======================= -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- DigiCert Global Root G3 ======================= -----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 VOKa5Vt8sycX -----END CERTIFICATE----- DigiCert Trusted Root G4 ======================== -----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP 82Z+ -----END CERTIFICATE----- WoSign ====== -----BEGIN CERTIFICATE----- MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/ EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w== -----END CERTIFICATE----- WoSign China ============ -----BEGIN CERTIFICATE----- MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO kI26oQ== -----END CERTIFICATE----- COMODO RSA Certification Authority ================================== -----BEGIN CERTIFICATE----- MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I LaZRfyHBNVOFBkpdn627G190 -----END CERTIFICATE----- USERTrust RSA Certification Authority ===================================== -----BEGIN CERTIFICATE----- MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+ eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- USERTrust ECC Certification Authority ===================================== -----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -----END CERTIFICATE----- GlobalSign ECC Root CA - R4 =========================== -----BEGIN CERTIFICATE----- MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q= -----END CERTIFICATE----- GlobalSign ECC Root CA - R5 =========================== -----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- Staat der Nederlanden Root CA - G3 ================================== -----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk= -----END CERTIFICATE----- Staat der Nederlanden EV Root CA ================================ -----BEGIN CERTIFICATE----- MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg== -----END CERTIFICATE----- IdenTrust Commercial Root CA 1 ============================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R cGzM7vRX+Bi6hG6H -----END CERTIFICATE----- IdenTrust Public Sector Root CA 1 ================================= -----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ 3Wl9af0AVqW3rLatt8o+Ae+c -----END CERTIFICATE----- Entrust Root Certification Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO e4pIb4tF9g== -----END CERTIFICATE----- Entrust Root Certification Authority - EC1 ========================================== -----BEGIN CERTIFICATE----- MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G -----END CERTIFICATE----- CFCA EV ROOT ============ -----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- PK\7default/plugins/payment/payssion/lib/PayssionClient.phpnu[ array( 'api_key', 'pm_id', 'amount', 'currency', 'track_id', 'sub_track_id', 'secret_key' ), 'query' => array( 'api_key', 'transaction_id', 'track_id', 'sub_track_id', 'secret_key' ), 'getDetail' => array( 'api_key', 'transaction_id', 'track_id', 'sub_track_id', 'secret_key' ) ); /** * @var array */ protected $http_errors = array ( 400 => '400 Bad Request', 401 => '401 Unauthorized', 500 => '500 Internal Server Error', 501 => '501 Not Implemented', 502 => '502 Bad Gateway', 503 => '503 Service Unavailable', 504 => '504 Gateway Timeout', ); /** * @var bool */ protected $is_success = false; /** * @var array */ protected $allowed_request_methods = array( 'get', 'put', 'post', 'delete', ); /** * @var boolean */ protected $ssl_verify = true; /** * Constructor * * @param string $username Username * @param string $password Password */ public function __construct($api_key, $secret_key) { $this->api_key = $api_key; $this->secret_key = $secret_key; $validate_params = array ( false === extension_loaded('curl') => 'The curl extension must be loaded for using this class!', false === extension_loaded('json') => 'The json extension must be loaded for using this class!' ); $this->checkForErrors($validate_params); } /** * Set Api URL * * @param string $url Api URL */ public function setUrl($url) { self::$api_url = $url; } /** * Sets SSL verify * * @param bool $ssl_verify SSL verify */ public function setSSLverify($ssl_verify) { $this->ssl_verify = $ssl_verify; } /** * Request state getter * * @return bool */ public function isSuccess() { return $this->is_success; } /** * create payment order * * @param $params create Params * @return array */ public function create(array $params) { return $this->call( 'create', 'post', $params ); } /** * query payment transaction * * @param $params query Params * @return array */ public function query(array $params) { return $this->call( 'query', 'post', $params ); } /** * get payment detail * * @param $params query Params * @return array */ public function getDetail(array $params) { return $this->call( 'getDetail', 'post', $params ); } /** * Method responsible for preparing, setting state and returning answer from rest server * * @param string $method * @param string $request * @param array $params * @return array */ protected function call($method, $request, $params) { $this->is_success = false; $validate_params = array ( false === is_string($method) => 'Method name must be string', false === $this->checkRequestMethod($request) => 'Not allowed request method type', true === empty($params) => 'params is null', ); $this->checkForErrors($validate_params); $params['api_key'] = $this->api_key; $params['secret_key'] = $this->secret_key; $params['api_sig'] = $this->getSig($params, self::$sig_keys[$method]); $response = $this->pushData($method, $request, $params); $response = json_decode($response, true); if (isset($response['result_code']) && 200 == $response['result_code']) { $this->is_success = true; } return $response; } /** * Checking error mechanism * * @param array $validateArray * @throws Exception */ protected function getSig(array &$params, array $sig_keys) { $msg_array = array(); foreach ($sig_keys as $key) { $msg_array[$key] = isset($params[$key]) ? $params[$key] : ''; } $msg_array['secret_key'] = $this->secret_key; $msg = implode('|', $msg_array); $sig = md5($msg); return $sig; } /** * Checking error mechanism * * @param array $validateArray * @throws Exception */ protected function checkForErrors(&$validate_params) { foreach ($validate_params as $key => $error) { if ($key) { throw new Exception($error, -1); } } } /** * Check if method is allowed * * @param string $method_type * @return bool */ protected function checkRequestMethod($method_type) { $request_method = strtolower($method_type); if(in_array($request_method, $this->allowed_request_methods)) { return true; } return false; } /** * Method responsible for pushing data to server * * @param string $method * @param string $method_type * @param array|string $vars * @return array * @throws Exception */ protected function pushData($method, $method_type, $vars) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, self::$api_url. $method); curl_setopt($ch, CURLOPT_POST, true); if (is_array($vars)) $vars = http_build_query($vars, '', '&'); curl_setopt($ch, CURLOPT_POSTFIELDS, $vars); curl_setopt($ch, CURLOPT_HEADER, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $this->getHeaders()); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->ssl_verify); if ($this->ssl_verify) { curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem'); } $response = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if (isset($this->http_errors[$code])) { throw new Exception('Response Http Error - ' . $this->http_errors[$code], $code); } $code = curl_errno($ch); if (0 < $code) { throw new Exception('Unable to connect to ' . self::$api_url . ' Error: ' . "$code :". curl_error($ch), $code); } curl_close($ch); return $response; } protected function &getHeaders() { $langVersion = phpversion(); $uname = php_uname(); $ua = array( 'version' => self::VERSION, 'lang' => 'php', 'lang_version' => $langVersion, 'publisher' => 'payssion', 'uname' => $uname, ); $headers = array( 'X-Payssion-Client-User-Agent: ' . json_encode($ua), "User-Agent: Payssion/php/$langVersion/" . self::VERSION, 'Content-Type: application/x-www-form-urlencoded', ); return $headers; } }PK\ j==7default/plugins/payment/payssion/scripts/payssion.phtmlnu[setLayout('layout.phtml'); ?>

      method; ?> PK\P\++-default/plugins/payment/payssion/payssion.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Payssion extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_REVISION = '5.2.2'; protected $defaultTitle = 'Payssion'; protected $defaultDescription = 'accepts all major credit cards'; protected $methods = array( 'fpx_my' => 'Myclear FPX (Malaysia)', 'hlb_my' => 'Hong Leong (Malaysia)', 'maybank2u_my' => 'Maybank2u (Malaysia)', 'cimb_my' => 'CIMB Clicks (Malaysia)', 'affinepg_my' => 'Affin Bank (Malaysia)', 'amb_my' => 'Am online (Malaysia)', 'rhb_my' => 'RHB Now (Malaysia)', 'molwallet_my' => 'MOLWallet (Malaysia)', 'webcash_my' => 'Webcash (Malaysia)', '7eleven_my' => '7-eleven (Malaysia)', 'esapay_my' => 'Esapay (Malaysia)', 'epay_my' => 'epay (Malaysia)', 'enets_sg' => 'eNets (Singapore)', 'singpost_sg' => 'SAM by SingPost (Singapore)', 'atmva_id' => 'ATMVA (Indonesia)', 'nganluong_vn' => 'Nganluong (Vietnam)', 'dragonpay_ph' => 'Dragonpay (Philippines)', 'molpoints' => 'CherryCredits (Global including South East)', // '' => 'Scratch cards (China) / MangirKart (Turkey)', 'alipay_cn' => 'Alipay (China)', 'cashu' => 'cashU (Middle East & North Africa)', 'onecard' => 'onecard (Middle East & North Africa)', 'paybyme_tr' => 'pabyme visa (Turkey)', 'ttnet_tr' => 'TTNET ÖdemeT (Turkey)', 'dineromail_ar' => 'dineromail (Argentina)', 'bancodobrasil_br' => 'bancodobrasil (Brazil)', 'itau_br' => 'itau (Brazil)', 'boleto_br' => 'Boleto (Brazil)', 'bradesco_br' => 'bradesco (Brazil)', 'hsbc_br' => 'hsbc (Brazil)', 'caixa_br' => 'caixa (Brazil)', 'santander_br' => 'Santander (Brazil)', 'visa_br' => 'visa (Brazil)', 'mastercard_br' => 'mastercard (Brazil)', 'dinersclub_br' => 'dinersclub (Brazil)', 'americanexpress_br' => 'americanexpress (Brazil)', 'elo_br' => 'elo (Brazil)', 'hipercard_br' => 'hipercard (Brazil)', 'bancomer_mx' => 'bancomer (Mexico)', 'banamex_mx' => 'banamex (Mexico)', 'santander_mx' => 'santander (Mexico)', 'oxxo_mx' => 'oxxo (Mexico)', 'debitcard_mx' => 'debit card: visa or mastercard (Mexico)', 'redpagos_uy' => 'redpagos (Uruguay)', 'bancochile_cl' => 'Banco de Chile (Chile)', 'redcompra_cl' => 'RedCompra (Chile)', 'qiwi' => 'QIWI (Global)', 'Yandex.Money' => 'yamoney (Global)', 'yamoneyac' => 'Bank Card: Yandex.Money (Russia)', 'yamoneygp' => 'Cash: Yandex.Money (Russia)', 'moneta_ru' => 'Moneta (Russia)', 'sberbank_ru' => 'Sberbank (Russia)', 'alfaclick_ru' => 'Alfa-Click (Russia)', 'qbank_ru' => 'Qbank (Russia)', 'promsvyazbank_ru' => 'Promsvyazbank (Russia)', 'rsb_ru' => 'Russian Standard (Russia)', 'faktura_ru' => 'Faktura (Russia)', 'russianpost_ru' => 'Russian Post centres (Russia)', 'banktransfer_ru' => 'Russia Bank transfer (Russia)', 'contact_ru' => 'CONTACT (Russia)', 'euroset_ru' => 'Euroset (Russia)', 'beeline_ru' => 'Beeline (Russia)', 'megafon_ru' => 'Megafon (Russia)', 'mtc_ru' => 'MTC (Russia)', 'tele2_ru' => 'Tele2 (Russia)', 'paysafecard' => 'Paysafecard (Global)', 'sofort' => 'Sofort (Europe)', 'trustpay' => 'Trustpay (Europe)', 'giropay_de' => 'Giropay (Germany)', 'eps_at' => 'EPS (Austria)', 'bancontact_be' => 'Bancontact/Mistercash (Belgium)', 'p24_pl' => 'P24 (Poland)', 'ideal_nl' => 'iDeal (Netherlands)', 'teleingreso_es' => 'Teleingreso (Spain)', 'multibanco_pt' => 'Multibanco (Portugal)', 'neosurf' => 'Neosurf (France)', 'polipayment' => 'Polipayment (Australia & New Zealand)', 'openbucks' => 'openbucks (North America)', 'bitcoin' => 'bitcoin, litecoin… (Global)', ); protected static $sig_keys = array('api_key', 'pm_id', 'amount', 'currency', 'track_id', 'sub_track_id', 'secret_key'); public function supportsCancelPage() { return true; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('api_key') ->setLabel("API Key\n" . "your Payssion account -> App -> -> Edit -> API Key") ->addRule('required'); $form->addText('secret_key', array('class' => 'el-wide')) ->setLabel("Secret Key\n" . "your Payssion account -> App -> -> Edit -> Secret Key") ->addRule('required'); } public function isConfigured() { return ($this->getConfig('api_key') && $this->getConfig('secret_key')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $methods = "\r\n"; $action = new Am_Paysystem_Action_HtmlTemplate_Payssion($this->getDir(), 'payssion.phtml'); $action->action = $this->getPluginUrl('method'); $action->invoice_id = $invoice->public_id; $action->method = $methods; $result->setAction($action); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $actionName = $request->getActionName(); switch ($actionName) { case 'method': $this->selectMethod($request); break; default: parent::directAction($request, $response, $invokeArgs); break; } } protected function selectMethod(Am_Mvc_Request $request) { $iId = $request->getParam('invoice'); if(!($this->invoice = $this->getDi()->invoiceTable->findFirstByPublicId($iId))) { throw new Am_Exception_InputError('Invoice not found'); } require_once dirname(__FILE__) .'/lib/PayssionClient.php'; $payssion = new PayssionClient($this->getConfig('api_key'), $this->getConfig('secret_key')); try { $res = $payssion->create(array( 'amount' => $this->invoice->first_total, 'currency' => $this->invoice->currency, 'pm_id' => $request->getParam('pm_id'), 'description' => $this->invoice->getLineDescription(), 'track_id' => $this->invoice->public_id, //optional, your order id or transaction id 'sub_track_id' => $this->invoice->public_id, //optional 'payer_name' => $this->invoice->getUser()->getName(), 'payer_email' => $this->invoice->getUser()->email, 'notify_url' => $this->getPluginUrl('ipn'), //optional, the notify url on your server side 'success_url' => $this->getReturnUrl(),//optional, the redirect url after success payments 'redirect_url' => $this->getCancelUrl() //optional, the redirect url after pending or failed payments )); } catch (Exception $e) { //handle exception $this->getDi()->errorLogTable->log("Payssion Error: {$e->getMessage()}"); $this->getDi()->response->redirectLocation($this->getCancelUrl()); } if ($payssion->isSuccess()) { //handle success $todo = $res['todo']; if ($todo) { $todo_list = explode('|', $todo); if (in_array("instruct", $todo_list)) { //show offline bank account info by showorder param $view = $this->getDi()->view; $view->title = ___('Offline bank account info'); $view->content = ""; foreach ($res['bankaccount'] as $k => $v) $view->content .= "$k: $v
      "; $view->display('member/layout.phtml'); return; } else if (in_array("redirect", $todo_list)) { //redirect the users to the redirect url $this->getDi()->response->redirectLocation($res['redirect_url']); } } } $this->getDi()->errorLogTable->log("Payssion Error: Create payment is failed " . print_r($res, true)); $this->getDi()->response->redirectLocation($this->getCancelUrl()); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function createTransaction(Am_Mvc_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payssion($this, $request, $response, $invokeArgs); } function getReadme() { $url = $this->getPluginUrl('ipn'); return <<result = $this->request->getPost(); parent::process(); } public function validateSource() { $check_array = array( $this->getPlugin()->getConfig('api_key'), $this->result['pm_id'], $this->result['amount'], $this->result['currency'], $this->result['track_id'], $this->result['sub_track_id'], $this->result['state'], $this->getPlugin()->getConfig('secret_key') ); $check_msg = implode('|', $check_array); return md5($check_msg) == $this->result['notify_sig']; } public function findInvoiceId() { return $this->result['track_id']; } public function validateStatus() { return (in_array($this->result['state'], array('completed', 'paid_partial'))); } public function getUniqId() { return (string) $this->result['transaction_id']; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->result['amount']); return true; } }PK\/1,default/plugins/payment/warrior-payments.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add(new Am_CustomFieldText(self::WP_PRODUCT_ID, "Warrior Payments Product ID")); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('ipn_secret') ->setLabel('Warrior Payments IPN Secret'); } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function getConfig($key=null, $default=null) { if($key == 'auto_create') return true; return parent::getConfig($key, $default); } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getParam('WSO_SALE_ACTION') == 'SALE') return new Am_Paysystem_Transaction_WarriorPaymentsSale($this, $request, $response, $invokeArgs); if($request->getParam('WSO_SALE_ACTION') == 'REFUNDED') return new Am_Paysystem_Transaction_WarriorPaymentsRefund($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<$url Don't forget to configure product option 'Warrior Payments Product ID' CUT; } } abstract class Am_Paysystem_Transaction_WarriorPayments extends Am_Paysystem_Transaction_Incoming { public function getAmount() { return moneyRound($this->request->get('AMT')); } public function validateSource() { $data = $this->request->getRequestOnlyParams(); if(!($secret = $this->getPlugin()->getConfig('ipn_secret')) || !($sign = $data['WSO_SIGNATURE'])) return true; unset($data['WSO_SIGNATURE']); ksort($data); $encoded_data = http_build_query($data); $signature = sha1($encoded_data . $secret); return $signature == $sign; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function findInvoiceId() { } } class Am_Paysystem_Transaction_WarriorPaymentsSale extends Am_Paysystem_Transaction_WarriorPayments { protected $_autoCreateMap = array( 'name_f' => 'FIRSTNAME', 'name_l' => 'LASTNAME', 'email' => 'EMAIL', 'user_external_id' => 'EMAIL', ); function autoCreateInvoice() { if (!($item_id = $this->request->get('WSO_PRODUCT_ID'))) return; if(!($billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData(Am_Paysystem_WarriorPayments::WP_PRODUCT_ID, $item_id))) return; if(!($product = $billing_plan->getProduct())) return; $userTable = $this->getPlugin()->getDi()->userTable; $userInfo = $this->fetchUserInfo(); $externalId = $this->generateUserExternalId($userInfo); $user = null; if ($externalId) $user = $userTable->findFirstByData('external_id', $externalId); if (!$user) { $user = $userTable->findFirstByEmail($userInfo['email']); if ($user) $user->data()->set('external_id', $externalId)->update(); } if (!$user) { $user = $userTable->createRecord($userInfo); if(!$user->login) $user->generateLogin(); if(!$user->pass) $user->generatePassword(); else $user->setPass($user->pass); $user->data()->set('external_id', $externalId); $user->insert(); if ($this->getPlugin()->getDi()->config->get('registration_mail')) $user->sendRegistrationEmail(); if ($this->getPlugin()->getDi()->config->get('registration_mail_admin')) $user->sendRegistrationToAdminEmail(); } $invoice = $this->getPlugin()->getDi()->invoiceRecord; $invoice->setUser($user); $item = $invoice->createItem($product); $item->first_price = $this->getAmount(); $item->rebill_times = 0; $item->second_price = 0; $item->add(1); $invoice->addItem($item); $invoice->calculate(); $invoice->paysys_id = $this->plugin->getId(); $invoice->insert(); $invoice->_autoCreated = true; if ($invoice && $this->log) { $this->log->updateQuick(array( 'invoice_id' => $invoice->pk(), 'user_id' => $user->user_id, )); } return $invoice; } public function getUniqId() { return $this->request->get('WSO_TXN_ID'); } } class Am_Paysystem_Transaction_WarriorPaymentsRefund extends Am_Paysystem_Transaction_WarriorPayments { public function findInvoiceId() { if($payment = $this->getPlugin()->getDi()->invoicePaymentTable->findFirstByReceiptId($this->request->get('WSO_TXN_ID'))) return $payment->invoice_public_id; } public function getUniqId() { return $this->request->get('WSO_TXN_ID') . '-RFND'; } public function processValidated() { $this->invoice->addRefund($this, $this->request->get('WSO_TXN_ID')); } }PK\T\$default/plugins/payment/avangate.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'avangate_id', "Avangate product ID", "" , array(/* ,'required' */) )); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("merchant_id") ->setLabel('Your Realex Merchant ID'); $form->addPassword('secret')->setLabel('Secret key'); $form->addAdvcheckbox('testing')->setLabel('Testing mode'); } public function canAutoCreate() { return true; } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Avangate($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array('USD'); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $refund = $this->getPluginUrl('refund'); return << 'FIRSTNAME', 'name_l' => 'LASTNAME', 'email' => 'CUSTOMEREMAIL', 'state' => 'STATE', 'country' => 'COUNTRY', 'zip' => 'ZIPCODE', 'street' => 'ADDRESS1', 'street2' => 'ADDRESS2', 'city' => 'CITY', 'user_external_id' => 'CUSTOMEREMAIL', 'invoice_external_id' => 'REFNO', ); public function autoCreateGetProducts() { $products = array(); foreach ((array)$this->request->get('IPN_PID') as $l) { $pl = Am_Di::getInstance()->billingPlanTable->findFirstByData('avangate_id', $l); if (!$pl) continue; $p = $pl->getProduct(); if ($p) $products[] = $p; } return $products; } public function findInvoiceId() { return $this->request->getFiltered('REFNO'); } public function getUniqId() { return $this->request->getFiltered('REFNO'); } public function validateSource() { $arr = array(); foreach($this->request->getPost() as $k => $v) { if($k == 'HASH') continue; if(@is_array($v)) $arr[] = $v[0]; else $arr[] = $v; } $hash = hash_hmac('md5', $this->getstrforhash($arr), $this->getPlugin()->getConfig('secret')); return $hash == $this->request->get('HASH'); } public function getAmount() { return moneyRound($this->request->get('IPN_TOTALGENERAL')); } public function validateStatus() { return $this->request->getFiltered('ORDERSTATUS') == 'COMPLETE'; } public function validateTerms() { return true; } public function processValidated() { try{ parent::processValidated(); } catch(Am_Exception_Paysystem $e) { Am_Di::getInstance()->errorLogTable->logException($e); $this->answer(); return; } $this->answer(); } public function answer() { $dt = date("YmdGis"); $arr = array(); $IPN_PID = $this->request->get('IPN_PID'); $arr[] = $IPN_PID[0]; $IPN_PNAME = $this->request->get('IPN_PNAME'); $arr[] = $IPN_PNAME[0]; $arr[] = $this->request->get('IPN_DATE'); $arr[] = $dt; $hash = hash_hmac('md5', $this->getstrforhash($arr), $this->getPlugin()->getConfig('secret')); echo "$dt|$hash"; } function getstrforhash($arr) { $res = ''; foreach($arr as $a) if($l = @strlen($a)) $res.=$l.$a; else $res.='0'; return $res; } public function validate() { try{ parent::validate(); } catch(Am_Exception_Paysystem $e) { Am_Di::getInstance()->errorLogTable->logException($e); $this->answer(); } } }PK\!! default/plugins/payment/payu.phpnu[addInteger('pos_id', array('size' => 20)) ->setLabel('Id punktu płatności (pos_id)'); $form->addText('key1', array('size' => 32, 'maxlength' => '32')) ->setLabel('Klucz MD5'); $form->addText('key2', array('size' => 32, 'maxlength' => '32')) ->setLabel('Drugi klucz MD5'); $form->addText('pos_auth_key', array('size' => 20, 'maxlength' => '32')) ->setLabel('Parametr pos_auth_key'); } public function isConfigured() { return $this->getConfig('pos_id') > ''; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $action = new Am_Paysystem_Action_Form(self::ACTION_URL); $vars = array_filter(array( 'pos_id' => $this->getConfig('pos_id'), 'pos_auth_key' => $this->getConfig('pos_auth_key'), 'session_id' => $invoice->public_id, 'amount' => round($invoice->first_total * 100), 'desc' => $invoice->getLineDescription(), 'first_name' => $invoice->getFirstName(), 'last_name' => $invoice->getLastName(), 'country' => $invoice->getCountry(), 'street' => $invoice->getStreet(), 'city' => $invoice->getCity(), 'post_code' => $invoice->getZip(), 'email' => $invoice->getEmail(), 'city' => $this->getConfig('lang'), 'client_ip' => $_SERVER['REMOTE_ADDR'], 'ts' => $this->getDi()->time )); ksort($vars); foreach ($vars as $k => $v) { $action->addParam($k, $v); } $action->sig = hash('sha256', http_build_query($vars) . '&' . $this->getConfig('key2')); $this->logOther('Payment Request', $action); $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payu($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<PayU plugin - configuration (EN) / PayU plugin - konfiguracja (PL) Note! Plugin works only with the Polish version of PayU payments. *EN* 1. Enable PayU payment plugin at aMember CP->Setup->Plugins 2. Configure PayU payment plugin at aMember CP->Setup->PayU Set POS ID (pos_id), Key (MD5), Second key (MD5) and Payment authorisation key (pos_auth_key) in CP->Setup->PayU. The data are available in the PayU account. 3. Inside the PayU account: - go to My Shops->POS and edit selected POS - set "Error return address:" to: %root_url%/cancel - set "Successful return address:" to: %root_url%/thanks - set "Address for reports:" to: %root_url%/payment/payu/ipn 4. Test the plugin using the option "test payment" in PayU account *PL* 1. Włącz plugin: przejdź do panelu aMemeber -> Setup/Configuration -> Plugins i włącz plugin PayU. 2. Konfiguracja: przejdź do panelu aMemeber -> Setup/Configuration -> PayU i wpisz dane punktu płatności podane na Twoim koncie PayU. 3. W panelu PayU - przejdź do edycji punktu płatności - jako "Adres powrotu - błąd:" podaj: %root_url%/cancel - jako "Adres powrotu - poprawnie:" podaj: %root_url%/thanks - jako "Adres raportów:" podaj: %root_url%/payment/payu/ipn 4. Przetestuj prawidłowe działania pluginu, korzystając z opcji płatności testowych w PayU CUT; } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try { return parent::directAction($request, $response, $invokeArgs); } catch (Exception $e) { $this->getDi()->errorLogTable->log($e); print "ERROR"; exit; } } function isRefundable(InvoicePayment $payment) { return false; } } class Am_Paysystem_Transaction_Payu extends Am_Paysystem_Transaction_Incoming { const ACTION_ADD = 'user.add'; const ACTION_REBILL = 'rebill'; const ACTION_DELETE = 'user.delete'; const SERVER = 'www.platnosci.pl'; const SERVER_SCRIPT = '/paygw/UTF/Payment/get'; // @todo: admin-cancel twocheckout public function findInvoiceId() { return $this->transaction->session_id; } public function genereateSignature($pos_id, $session_id, $ts) { return md5($pos_id . $session_id . $ts . $this->plugin->getConfig("key2")); } public function getUniqId() { return $this->transaction->session_id; } public function validateSource() { if (!$this->request->get("pos_id") || !$this->request->get("session_id") || !$this->request->get("ts") || !$this->request->get("sig")) throw new Am_Exception_Paysystem_TransactionInvalid("Empty Parametrs!"); if ($this->request->get("pos_id") != $this->plugin->getConfig("pos_id")) throw new Am_Exception_Paysystem_TransactionInvalid("WRONG POS ID!"); if ($this->genereateSignature($this->request->get("pos_id"), $this->request->get("session_id"), $this->request->get("ts")) != $this->request->get("sig")) throw new Am_Exception_Paysystem_TransactionInvalid("WRONG SIGNATURE!"); $this->getOrder($this->request->get("session_id")); return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ($this->transaction->status) { case 99 : if ($this->invoice->getStatus() == 0) $this->invoice->addPayment($this); break; case 2 : $this->invoice->stopAccess($this); break; } print "OK"; } function xmlToArray(SimpleXMLElement $xml) { $arr = (array) $xml; foreach ($arr as $k => $v) if (is_object($v)) { $arr[$k] = $this->xmlToArray($v); if (empty($arr[$k])) $arr[$k] = null; } return $arr; } function getOrder($session_id) { $ts = time(); $sig = md5($this->plugin->getConfig('pos_id') . $session_id . $ts . $this->plugin->getConfig('key1')); $r = new Am_HttpRequest('https://' . self::SERVER . self::SERVER_SCRIPT, 'POST'); $r->addPostParameter(array( 'pos_id' => $this->plugin->getConfig('pos_id'), 'session_id' => $session_id, 'ts' => $ts, 'sig' => $sig )); $l = $this->plugin->logRequest($r); $response = $r->send()->getBody(); $l->add($response); $res = new SimpleXMLElement($response); if ($res->status != 'OK') throw new Am_Exception_Paysystem_TransactionInvalid("BAD RESPONSE STATUS!"); if ($res->trans->pos_id != $this->plugin->getConfig('pos_id')) throw new Am_Exception_Paysystem_TransactionInvalid("INCORECT POS NUMBER!"); $sig = md5($res->trans->pos_id . $res->trans->session_id . $res->trans->order_id . $res->trans->status . $res->trans->amount . $res->trans->desc . $res->trans->ts . $this->plugin->getConfig('key2')); if ($res->trans->sig != $sig) throw new Am_Exception_Paysystem_TransactionInvalid("INCORECT SIGNATURE!"); $this->transaction = $res->trans; /* Status: * 1: nowa * 2: anulowana * 3: odrzucona * 4: rozpoczęta * 5: oczekuje na odbiór * 6: autoryzacja odmowna * 7: płatność odrzucona * 99: płatność odebrana - zakończona * 888: błędny status */ return true; } }PK\RC"""default/plugins/payment/molpay.phpnu[getConfig('merchant_id')); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant_id', array('size' => 20)) ->setLabel("MOLPay Merchant ID") ->addRule('required'); $form->addText('verify_key', array('size' => 20)) ->setLabel("MOLPay Verify Key") ->addRule('required'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { /* Payment Method - Identity * Credit Payment Visa & Mastercard (default) - index.php Mobile Money - mobilemoney.php Ezeelink - ezeelink.php * Debit Payment Maybank2u Fund Transfer - maybank2u.php MEPS FPX - fpx.php CIMB Clicks - cimb.php RHB Online - rhb.php Hong Leong Bank Online - hlb.php Mepscash Online - mepscash.php Webcash - webcash.php */ $Payment_Method = ''; $url = sprintf($this->url, $this->getConfig('merchant_id'), $Payment_Method); $a = new Am_Paysystem_Action_Redirect($url); $a->amount = $invoice->first_total; $a->orderid = $invoice->public_id; $a->bill_name = utf8_encode($invoice->getName()); //UTF-8 encoding is recommended for Chinese contents $a->bill_email = $invoice->getEmail(); $a->bill_mobile = $invoice->getPhone(); $a->cur = $invoice->getCurrency(); $a->bill_desc = utf8_encode($invoice->getLineDescription()); //UTF-8 encoding is recommended for Chinese contents $a->returnurl = $this->getPluginUrl('thanks'); $a->vcode = md5($invoice->first_total.$this->getConfig('merchant_id').$invoice->public_id.$this->getConfig('verify_key')); $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Molpay($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Molpay_Thanks($this, $request, $response, $invokeArgs); } public function getReadme() { return << Setup/Configuration -> Plugins 2. Configure plugin: aMember CP -> Setup/Configuration -> MOLPay 3. Configure Callback URL in your MOLPay Merchant Profile to this URL: %root_url%/payment/molpay/ipn 4. Run a test transaction to ensure everything is working correctly. Testing account only verifies VISA and MasterCard number validity and NO actual transaction occurs between bank or payment gateway. VISA and MasterCard card number for testing: Positive Test MasterCard: 5105105105105100, 5555555555554444 VISA: 4111111111111111, 4012888888881881 Negative Test MasterCard: 5555555555554440 VISA: 4111111111111110 ------------------------------------------------------------------------------ CUT; } } /* nbcb * Numeric 1 Code that used to notify the incoming to merchant callback URL. amount * Floating point The transaction amount in one bill. orderid * Alpha-numeric The bill / invoice number appcode * Alpha-numeric Bank approval code tranID * Numeric Transaction ID for tracking purpose domain * Alpha-numeric Merchant ID status * Numeric 00, 11. 22 * Status of transaction : 00 is success, 11 is failure, 22 is pending error_code * Alpha-numeric Error code for failure transaction (if any). error_desc * Alpha-numeric Error description for failure transaction (if any). currency * Character It depends on the transacted currency. paydate * Date / Time YYYY-MM-DD HH:mm:ss Date and time of the transaction skey * Alpha-numeric MD5 encryption Encrypted string to verify whether the * transaction is from a valid source. Verify Key is required. */ class Am_Paysystem_Transaction_Molpay extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('tranID'); } public function getReceiptId() { return $this->request->get('tranID'); } public function getAmount() { return moneyRound($this->request->get('amount')); } public function findInvoiceId() { return $this->request->get('orderid'); } public function validateSource() { $key0 = md5( $this->request->get('tranID') . $this->request->get('orderid') . $this->request->get('status') . $this->request->get('domain') . $this->request->get('amount') . $this->request->get('currency') ); $key1 = md5( $this->request->get('paydate') . $this->request->get('domain') . $key0 . $this->request->get('appcode') . $this->getPlugin()->getConfig('verify_key') ); return $key1 == $this->request->get('skey'); } public function validateStatus() { return $this->request->get('status') == '00'; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); } } /* amount * Floating point The transaction amount in one bill. orderid * Alpha-numeric The bill / invoice number appcode * Alpha-numeric Bank approval code tranID * Numeric Transaction ID for tracking purpose domain * Alpha-numeric Merchant ID status * Numeric 00 or 11 Status of transaction, 00 is success and 11 isfailure error_code * * Alpha-numeric Error code for failure transaction (if any). error_desc * * Alpha-numeric Error description for failure transaction (if any). currency * Character Always “RM” paydate * Date / Time 2 channel Character skey Alpha-numeric uppercase characters YYYY-MM-DD HH:mm:ss * Date and time of the transaction channel * Character PM-ASIA skey * Alpha-numeric MD5 encryption * Encrypted string to verify whether the transaction is from a valid source. Verify Key is required. */ class Am_Paysystem_Transaction_Molpay_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { return $this->request->get('orderid'); } public function getUniqId() { return $this->request->get('tranID'); } public function validateStatus() { return $this->request->get('status') == '00'; } public function validateTerms() { return true; } public function validateSource() { $key0 = md5( $this->request->get('tranID') . $this->request->get('orderid') . $this->request->get('status') . $this->request->get('domain') . $this->request->get('amount') . $this->request->get('currency') ); $key1 = md5( $this->request->get('paydate') . $this->request->get('domain') . $key0 . $this->request->get('appcode') . $this->getPlugin()->getConfig('verify_key') ); return $key1 == $this->request->get('skey'); } public function getInvoice() { return $this->invoice; } } PK\otA> > )default/plugins/payment/securetrading.phpnu[addText('sitereference') ->setLabel("Site Refernce\n" . 'The unique Secure Trading site reference that you receive when you sign up'); $form->addText('secret') ->setLabel('Notification password'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect(self::LIVE_URL); $a->sitereference = $this->getConfig('sitereference'); $a->currencyiso3a = $invoice->currency; $a->mainamount = $invoice->first_total; $a->version = 1; $a->billingstreet = $user->street; $a->billingtown = $user->city; $a->billingcounty = $user->country; $a->billingpostcode = $user->zip; $a->billingfirstname = $user->name_f; $a->billinglastname = $user->name_l; $a->billingemail = $user->email; $a->billingtelephone = $user->phone; $a->customerstreet = $user->street; $a->customertown = $user->city; $a->customercounty = $user->country; $a->customerpostcode = $user->zip; $a->customerfirstname = $user->name_f; $a->customerlastname = $user->name_l; $a->customeremail = $user->email; $a->customertelephone = $user->phone; $a->orderreference = $invoice->public_id; $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Securetrading($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array_keys(Am_Currency::getFullList()); } } class Am_Paysystem_Transaction_Securetrading extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('transactionreference'); } public function validateSource() { $ipnFields = $this->request->getPost(); unset($ipnFields['responsesitesecurity']); unset($ipnFields['notificationreference']); ksort($ipnFields); $hash = implode('', $ipnFields).$this->getPlugin()->getConfig('secret'); return $this->request->get('responsesitesecurity') == md5($hash); } public function validateStatus() { return $this->request->get('errorcode') == '0'; } public function validateTerms() { return doubleval($this->request->get('mainamount')) == doubleval($this->invoice->first_total); } public function findInvoiceId() { return $this->request->get('orderreference'); } }PK\J{;2;2"default/plugins/payment/bitpay.phpnu[ 'Low: 6 confirmations, 30 minutes to 1 hour or more', 2 => 'Medium: 3 confirmations, approximately 10-30 minutes', 3 => 'High: Instant, for low priced digital products that require no confirmation' ); private $transactionSpeed = array( 1 => 'low', 2 => 'medium', 3 => 'high' ); public function getSupportedCurrencies() { return array_keys(Am_Currency::getFullList()); } function init() { parent::init(); Am_Di::getInstance()->productTable->customFields()->add( new Am_CustomFieldSelect('bitpay_speed_risk', 'Bitpay speed/risk', null, null, array('options' => array('' => 'Using plugin settings') + $this->transactionSpeedOptions)) ); } public function _initSetupForm(Am_Form_Setup $form) { $pre = 'payment.bitpay'; if (!empty($_GET['reset_bitpay_token'])) { $this->getDi()->config->saveValue($pre, array()); return Am_Mvc_Response::redirectLocation($this->getDi()->url("admin-setup/bitpay")); } if(!($pkey = $this->getConfig('pkeys.public'))) { $private = new \Bitpay\PrivateKey($this->getDi()->data_dir . '/bitpay-private.key'); $public = new \Bitpay\PublicKey($this->getDi()->data_dir . '/bitpay-public.key'); $private->generate(); $public->setPrivateKey($private); $public->generate(); $manager = new \Bitpay\KeyManager(new \Bitpay\Storage\EncryptedFilesystemStorage('password')); $manager->persist($private); $manager->persist($public); $this->getDi()->config->saveValue("$pre.pkeys",array( 'public' => serialize($public), 'private' => serialize($private))); } else { $public = unserialize($pkey); $private = unserialize($this->getConfig('pkeys.private')); } if(!($this->getConfig('token'))) { $client = $this->getClient(serialize($public), serialize($private)); $sin = \Bitpay\SinKey::create()->setPublicKey($public)->generate(); try { $token = $client->createToken(array( 'facade' => 'merchant', 'label' => $this->getDi()->config->get('site_title'), 'id' => (string) $sin)); } catch (\Exception $e) { $this->getDi()->errorLogTable->logException($e); } if($token) { $this->getDi()->config->saveValue("$pre.token", $tk_ = $token->getToken()); $this->getDi()->config->saveValue("$pre.pairing_code", $pc_ = $token->getPairingCode()); } } if ($tk = $this->getConfig('token', @$tk_)) { $_token = $form->addText('token_value')->setLabel(___("Token value"))->toggleFrozen(true); $form->setDefault('token_value', $tk); if($tk != $this->getConfig('token_ok')) { $client = $this->getClient(serialize($public), serialize($private), $tk); try { $res = $client->getTokens(); $this->getDi()->config->saveValue("$pre.token_ok", $tk); } catch (Exception $ex) { $form->addStatic()->setContent('
      Activate Token Code') ->setLabel(___("Follow the link to activate the token")); } } $form->addStatic()->setContent('Reset Token') ->setLabel(___("Follow the link to reset the token")); } $form->addSelect('bitpay_speed_risk') ->setLabel('Default Bitpay speed/risk') ->loadOptions($this->transactionSpeedOptions); } function isConfigured() { return $this->getConfig('token_value') && $this->getConfig('pairing_code'); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times) { if (!(float) $invoice->first_total) { return ___("Can not handle this billing terms: " . "first_total is zero"); } if ($invoice->first_period != $invoice->second_period) { return ___("Can not handle this billing terms: " . "first_period != second_period"); } if (!in_array( $invoice->first_period, array('7d', '1m', '3m', '12m', '1y'))) { return ___("Can not handle this billing terms: " . "not in possible periods"); } if ($invoice->rebill_times != 99999) { return ___("Can not handle this billing terms: " . "rebill time must be forever"); } } return parent::isNotAcceptableForInvoice($invoice); } public function getClient($public, $private, $token_value = null, InvoiceLog $invoiceLog = null) { $adapter = new \Bitpay\Client\Adapter\CurlAdapter(); $network = new \Bitpay\Network\Livenet(); $client = new \Bitpay\Client\Client($invoiceLog); $client->setPrivateKey(unserialize($private)); $client->setPublicKey(unserialize($public)); $client->setNetwork($network); $client->setAdapter($adapter); if($token_value) { $token = new \Bitpay\Token(); $token->setToken($token_value); $client->setToken($token); } return $client; } function generatePeriod($period) { switch ($period) { case '7d': return 'weekly'; case '1m': return 'monthly'; case '3m': return 'quarterly'; case '12m': case '1y': return 'yearly'; default: throw new Am_Exception("Unhandled period: {$period}"); } } function getInvoiceLog(Invoice $invoice) { if (!@$this->log) { $this->log = $this->getDi()->invoiceLogRecord; if ($invoice) { $this->log->invoice_id = $invoice->invoice_id; $this->log->user_id = $invoice->user_id; } $this->log->paysys_id = $this->getId(); $this->log->remote_addr = $_SERVER['REMOTE_ADDR']; foreach ($this->getConfig() as $k => $v) if (is_scalar($v) && (strlen($v) > 4)) $this->log->mask($v); } return $this->log; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $invoiceLog = $this->getInvoiceLog($invoice); $client = $this->getClient($this->getConfig('pkeys.public'), $this->getConfig('pkeys.private'), $this->getConfig('token_value'), $invoiceLog); $bitInvoice = new \Bitpay\Invoice(); $prSpeeds = array(); /* @var $product Product */ foreach ($invoice->getProducts() as $product) { $prSpeeds[] = ($o = $product->data()->get('bitpay_speed_risk')) ? $o : $this->getConfig('bitpay_speed_risk'); } $transactionSpeed = $this->transactionSpeed[min($prSpeeds)]; /* @var $item InvoiceItem */ foreach ($invoice->getItems() as $item) { $bitItem = new \Bitpay\Item(); $bitItem ->setDescription($item->item_description) ->setPrice($item->first_total) ->setQuantity($item->qty); $bitInvoice->setItem($bitItem); } $buyer = new \Bitpay\Buyer(); $buyer->setFirstName($user->name_f) ->setLastName($user->name_l) ->setPhone($user->phone) ->setEmail($user->email) ->setAddress( array( $user->street, $user->street2 ) ) ->setCity($user->city) ->setState($user->state) ->setZip($user->zip) ->setCountry($user->country); $bitInvoice->setBuyer($buyer); $bitInvoice->setCurrency(new \Bitpay\Currency($invoice->currency)); $bitInvoice->setTransactionSpeed($transactionSpeed); $bitInvoice->setPrice($invoice->first_total); $bitInvoice->setNotificationUrl($this->getPluginUrl('ipn')); $bitInvoice->setOrderId($invoice->public_id); $bitInvoice->setRedirectUrl($this->getReturnUrl()); try { $client->createInvoice($bitInvoice); } catch (\Exception $e) { throw new Am_Exception_InputError('Incorrect Gateway response received!'); } if($invoice->rebill_times) { $schedule = new Bitpay\Schedule(); $schedule->currency = $invoice->currency; $schedule->price = $invoice->second_total; $schedule->quantity = 1; $p = new Am_Period($invoice->first_period); $dueDate = $p->addTo($this->getDi()->sqlDate); list($y,$m,$d) = explode('-', $dueDate); if($d>28) $dueDate = "$y-$m-28"; $schedule->dueDate = $dueDate; $schedule->schedule = $this->generatePeriod($invoice->second_period); $schedule->items = array(array( 'price' => $invoice->second_total, 'quantity' => '1' )); try { $client->createSchedule($schedule); } catch (\Exception $e) { throw new Am_Exception_InputError('Incorrect Gateway response received!'); } } if(!($url = $bitInvoice->getUrl())) throw new Am_Exception_InputError('Incorrect Gateway response received!'); $invoice->data()->set(self::BITPAY_INVOICE_ID, $bitInvoice->getId())->update(); $result->setAction(new Am_Paysystem_Action_Redirect($url)); } public function getRecurringType() { return self::REPORTS_REBILL; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Bitpay($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Bitpay($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Bitpay extends Am_Paysystem_Transaction_Incoming { /** * @var Bitpay\Invoice */ private $bitInvoice, $vars; public function process() { $rawBody = $this->request->getRawBody(); $vars = json_decode($rawBody, true); if (!isset($vars['id'])) throw new Am_Exception_InternalError("BitPay API Error. Request[incoming] has no [id]."); /* @var $client Bitpay\Client\Client */ $client = $this->plugin->getClient($this->plugin->getConfig('pkeys.public'), $this->plugin->getConfig('pkeys.private'), $this->plugin->getConfig('token_value')); $this->vars = $vars; $this->bitInvoice = $client->getInvoice($vars['id']); parent::process(); } public function validateSource() { return true; } public function findInvoiceId() { if($invoice = Am_Di::getInstance() ->invoiceTable ->findFirstByData( Am_Paysystem_Bitpay::BITPAY_INVOICE_ID, $this->vars['id'])) return $invoice->public_id; else throw new Am_Exception_InternalError( "BitPay Error. " . "Not found invoice by bitpayInvoiceId " . "#[{$this->vars['id']}]."); } public function validateStatus() { switch ($this->bitInvoice->getStatus()) { case 'paid': case 'confirmed': case 'complete': return true; default: return false; } } public function getUniqId() { return (string) $this->vars['id']; } public function validateTerms() { $this->assertAmount( $this->invoice->first_total, (string)$this->bitInvoice->getPrice()); return true; } } PK\[%default/plugins/payment/limelight.phpnu[removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function canAutoCreate() { return true; } public function __construct(Am_Di $di, array $config) { parent::__construct($di, $config); foreach ($di->paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'limelight_product_id', "Limelight Product Id", "" , array(/* ,'required' */) )); } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Limelight($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { $url = $this->getPluginUrl('api'); return <<Limelight plugin readme Installation 1 - Enable plugin at aMember CP -> Setup/Configuration -> Plugins -> Payment Plugins -> Limelight. 2 - Go at aMember CP -> Manage Products and edit each product: -fill 'Limelight Product Id' -click 'Save' button. 3 - Configure Limelight plugin at aMember CP -> Setup/Comfiguration -> Limelight: 4 - As postback URL use - $url?email={email}&fname={first_name}&lname={last_name}&amount={order_total}&order_id={order_id}&products={product_id_csv} CUT; } public function getConfig($key = null, $default = null) { if($key == 'auto_create') return true; else return parent::getConfig($key, $default); } } class Am_Paysystem_Transaction_Limelight extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name_f' => 'fname', 'name_l' => 'lname', 'email' => 'email', 'user_external_id' => 'email', 'invoice_external_id' => 'order_id', ); public function autoCreateGetProducts() { $item_name = $this->request->get('products'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('limelight_product_id', $item_name); if ($billing_plan) return array($billing_plan->getProduct()); } public function getReceiptId() { return $this->request->get('order_id'); } public function getAmount() { return moneyRound($this->request->get('amount')); } public function getUniqId() { return @$this->request->get('order_id'); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); } public function findInvoiceId() { return $this->request->get('ctransreceipt'); } }PK\ default/plugins/payment/migs.phpnu[addText('merchant_id')->setLabel('Merchant ID'); $form->addText('access_code')->setLabel("Access Code\n" . 'Authenticates the merchant on the Payment Server'); $form->addText('secure_hash', array('class' => 'el-wide')) ->setLabel("Secure Hash\n" . 'A secure hash which allows the Virtual Payment Client to authenticate the merchant and check the integrity of the transaction Request'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $vars = array( 'vpc_Version' => '1', 'vpc_Command' => 'pay', 'vpc_MerchTxnRef' => $invoice->public_id, 'vpc_AccessCode' => $this->getConfig('access_code'), 'vpc_Merchant' => $this->getConfig('merchant_id'), 'vpc_OrderInfo' => $invoice->public_id, 'vpc_Amount' => intval($invoice->first_total * 100), 'vpc_Locale' => 'en', 'vpc_ReturnURL' => $this->getPluginUrl('thanks') ); $vars['vpc_SecureHash'] = $this->getHash($vars); $vars['vpc_SecureHashType'] = 'SHA256'; foreach($vars as $k=>$v){ $a->$k = $v; } $result->setAction($a); } function getHash($data) { ksort($data); $hashstring = array(); foreach ($data as $k=>$v) { $hashstring[] = "$k=$v"; } return strtoupper( hash_hmac('SHA256', implode("&", $hashstring), pack('H*', $this->getConfig('secure_hash'))) ); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Migs($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Migs extends Am_Paysystem_Transaction_Incoming_Thanks { function findInvoiceId() { return $this->request->getFiltered('vpc_OrderInfo'); } public function getUniqId() { return $this->request->getFiltered('vpc_ReceiptNo'); } public function validateSource() { if($this->getPlugin()->getConfig('merchant_id') != $this->request->get('vpc_Merchant')){ throw new Am_Exception_Paysystem_TransactionSource('Incorrect merchant ID received!'); } $vars = $this->request->toArray(); $secureHash = $vars['vpc_SecureHash']; unset($vars['vpc_SecureHash']); unset($vars['vpc_SecureHashType']); $hash = $this->plugin->getHash($vars); if($hash != $secureHash) throw new Am_Exception_Paysystem_TransactionInvalid('Unable to verity transaction. Calculated hash is not valid!'); return true; } public function validateStatus() { if($this->request->get('vpc_TxnResponseCode') != '0'){ throw new Am_Exception_Paysystem_TransactionInvalid('Transaction was not completed. Error code: '.$this->request->get('vpc_TxnResponseCode')); } return true; } public function validateTerms() { return ($this->invoice->first_total == ($this->request->get('vpc_Amount')/100)); } }PK\ ##+default/plugins/payment/sliiing/sliiing.phpnu[getGrid()->getForm() ->addElement(new Am_Form_Element_SliiingBillers('_sliiing_billers', array('class' => 'props'))) ->setLabel(___('Sliiing Billers')) ->setValue(array( 'options' => array(), 'default' => array())); } function onGridProductBeforeSave(Am_Event $event) { $product = $event->getGrid()->getRecord(); $val = $event->getGrid()->getForm()->getValue(); $product->data()->setBlob('sliiing_billers', json_encode($val['_sliiing_billers'])); } function onGridProductValuesToForm(Am_Event $event) { $args = $event->getArgs(); $values = $args[0]; $product = $event->getGrid()->getRecord(); if ($sliiing_billers = json_decode($product->data()->getBlob('sliiing_billers'), true)) { $values['_sliiing_billers'] = $sliiing_billers; $event->setArg(0, $values); } } public function _initSetupForm(Am_Form_Setup $form) { } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $product = $this->getDi()->productTable->load($invoice->getItem(0)->item_id); $billers = json_decode($product->data()->getBlob('sliiing_billers'), true); if (!@count($billers['options'])) { $this->getDi()->errorLogTable->log("SLIING ERROR : please add billers for product #" . $product->pk()); throw new Am_Exception_InputError('An error occurred while payment request'); } elseif (count($billers['options']) == 1) { //redirect $aff = '0'; $lin = '0'; $refe_url = '0'; $ip = '0'; $keyword = '0'; if (isset($_COOKIE['MID'])) { $mid = base64_decode($_COOKIE['MID']); list($aff, $lin, $refe_url, $ip, $keyword) = explode('|', $mid); } $datas = base64_encode("$aff|$lin|$refe_url|$ip|$keyword"); $url = $billers['options'][0]; $url = str_replace('$datas', $datas, $url); $a = new Am_Paysystem_Action_Redirect($url); $a->x_invoice_id = $invoice->public_id; $a->username = $invoice->getUser()->login; $a->email = urlencode($invoice->getUser()->email); $result->setAction($a); } else { //show form $a = new Am_Paysystem_Action_HtmlTemplate_Sliiing($this->getDir(), 'sliiing-confirm.phtml'); $a->action = $this->getPluginUrl('confirm'); $a->billers = $billers; $a->invoice = $invoice; $result->setAction($a); } } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'confirm') { $invoice = $this->getDi()->invoiceTable->findFirstBy(array('public_id' => $request->get('invoice'))); if (!$invoice) throw new Am_Exception_InputError('An error occurred while payment request'); if ($user = $this->getDi()->auth->getUser()) { if ($user->user_id != $invoice->user_id) throw new Am_Exception_InputError('An error occurred while payment request'); } $product = $this->getDi()->productTable->load($invoice->getItem(0)->item_id); $billers = json_decode($product->data()->getBlob('sliiing_billers'), true); if (!@$billers['options'][$request->get('biller')]) throw new Am_Exception_InputError('An error occurred while payment request'); //redirect $aff = '0'; $lin = '0'; $refe_url = '0'; $ip = '0'; $keyword = '0'; if (isset($_COOKIE['MID'])) { $mid = base64_decode($_COOKIE['MID']); list($aff, $lin, $refe_url, $ip, $keyword) = explode('|', $mid); } $datas = base64_encode("$aff|$lin|$refe_url|$ip|$keyword"); $url = $billers['options'][$request->get('biller')]; $url = str_replace('$datas', $datas, $url) . '&x_invoice_id=' . $invoice->public_id. '&username='.$invoice->getUser()->login. '&email='. urlencode($invoice->getUser()->email); header('Location: ' . $url); exit; } else parent::directAction($request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Sliiing($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $ipn = Am_Html::escape($this->getPluginUrl('ipn')); return <<Sliiing payment plugin configuration 1. Enable "Sliiing" payment plugin at aMember CP->Setup->Plugins 2. Manage products in aMember and set up Sliiing biller(s) for desired product(s) 3. Log into your Sliiing account, visit Account -> My websites and set up "Point to our script" to $ipn CUT ; } } class Am_Form_Element_SliiingBillers extends HTML_QuickForm2_Element_Input { protected $attributes = array('type' => 'hidden'); public function __construct($name = null, $attributes = null, $data = null) { if (is_array($attributes) && isset($attributes['class'])) { $attributes['class'] = $attributes['class'] . ' options-editor'; } else { $attributes['class'] = 'options-editor'; } parent::__construct($name, $attributes, $data); } public function setValue($value) { $value = is_array($value) ? json_encode($value) : $value; parent::setValue($value); } public function getRawValue() { $value = parent::getRawValue(); return json_decode($value, true); } public function render(HTML_QuickForm2_Renderer $renderer) { $renderer->getJavascriptBuilder()->addElementJavascript($this->getJs()); return parent::render($renderer); } public function getJs() { return <<_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Transaction_Sliiing extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('transaction_id', $this->request->get('subscription_id')); } public function validateSource() { $this->_checkIp(<<request->get("x_invoice_id"); } function processValidated() { switch ($this->request->get("transaction")) { case 'new' : if (floatval($this->invoice->first_period) == 0) $this->invoice->addAccessPeriod($this); else $this->invoice->addPayment($this); break; case 'rebill' : $this->invoice->addPayment($this); break; case 'expire' : $this->invoice->stopAccess($this); break; case 'chargeback' : case 'refund' : $this->invoice->addRefund($this, $this->request->get('accountingAmount')); break; } } }PK\s1=default/plugins/payment/sliiing/scripts/sliiing-confirm.phtmlnu[setLayout('layout.phtml'); ?>

      PK\RIRr +default/plugins/payment/internet-secure.phpnu[getId(); $form->addText("merchant_id")->setLabel("Your Internetsecure Merhcant Number\n" . 'it must be a numeric value'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->MerchantNumber = $this->getConfig('merchant_id'); $a->Products = sprintf("%s::1::999::%s::", $invoice->first_total,$invoice->getLineDescription()); $a->ReturnCGI = $this->getPluginUrl('thanks'); $a->xxxName = $invoice->getName(); $a->xxxAddress = $invoice->getStreet(); $a->xxxCity = $invoice->getCity(); $a->xxxProvince = $invoice->getState(); $a->xxxCountry = $invoice->getCountry(); $a->xxxPostal = $invoice->getZip(); $a->xxxEmail = $invoice->getEmail(); $a->xxxVar1 = $invoice->public_id; if($this->getConfig('testing')){ $a->Products .= '{TEST}'; } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { ; } function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_InternetSecure($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_InternetSecure extends Am_Paysystem_Transaction_Incoming_Thanks { function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); } function findInvoiceId() { return $this->request->getFiltered('xxxVar1'); } public function getUniqId() { return $this->request->getFiltered('receiptnumber'); } public function validateSource() { return true; } public function validateStatus() { return ($this->request->get('ApprovalCode') && $this->request->get('receiptnumber'))? true : false; } public function validateTerms() { return $this->request->get('amount') == $this->invoice->first_total; } }PK\v@- - (default/plugins/payment/payflow-link.phpnu[addText("login")->setLabel('Your PayFlow username'); $form->addText("partner")->setLabel('Your PayFlow Partner Name'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->LOGIN = $this->getConfig('login'); $a->PARTNER = $this->getConfig('partner'); $a->AMOUNT = sprintf('%.2f', $invoice->first_total); $a->TYPE = 'S'; $a->INVOICE = $invoice->public_id; $a->DESCRIPTION = $invoice->getLineDescription(); $a->NAME = $invoice->getName(); $a->ADDRESS = $invoice->getStreet(); $a->CITY = $invoice->getCity(); $a->STATE = $invoice->getState(); $a->COUNTRY = $invoice->getCountry(); $a->ZIP = $invoice->getZip(); $a->EMAIL = $invoice->getEmail(); $a->PHONE = $invoice->getPhone(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_PayflowLink($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Payfloe link payment plugin configuration Set "IPN URL" for your payflow account to $url CUT; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getFiltered('INVNUM', $request->getFiltered('INVOICE'))=='') $response->setRedirect($this->getRootUrl() . '/thanks'); else parent::directAction($request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_PayflowLink extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->getFiltered('INVNUM', $this->request->getFiltered('INVOICE')); } public function getUniqId() { return $this->request->getFiltered('PNREF'); } public function validateSource() { return true; } public function validateStatus() { return (!(in_array($this->request->getFiltered('RESPMSG'), array('AVSDECLINED','CSCDECLINED')) && ($this->request->getInt('RESULT')==0))); } public function validateTerms() { return (doubleval($this->request->get('AMT',$this->request->get('AMOUNT'))) == doubleval($this->invoice->first_total)); } }PK\ZI+default/plugins/payment/dalpay-checkout.phpnu[ 'monthly', '3m' => 'quarterly', '6m' => 'sixmonthly', '12m' => 'yearly', '1y' => 'yearly' ); public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times) { $first_period = new Am_Period($invoice->first_period); if (!(float) $invoice->first_total) { return ___('Can not handle this billing terms'); } if ($invoice->first_period != $invoice->second_period && $first_period->getUnit() != 'd') { return ___('Can not handle this billing terms'); } if (!in_array($invoice->second_period, array_keys($this->rebill_type_map))) { return ___('Can not handle this billing terms'); } } return parent::isNotAcceptableForInvoice($invoice); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getSupportedCurrencies() { return array('USD', 'GBP', 'EUR', 'JPY', 'CAD', 'AUD', 'ZAR', 'ISK'); } public function _initSetupForm(Am_Form_Setup $form) { $form->setTitle('Dalpay (Checkout)'); $form->addText('mer_id', array('size' => 20)) ->setLabel('Your Merchant ID#'); $form->addText('pageid') ->setLabel('The order page sub-account'); $form->addPassword('password') ->setLabel('Silent Post Password'); $form->addPassword('notify_password') ->setLabel('Server Notification Password'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::GATEWAY); $result->setAction($a); $a->mer_id = $this->getConfig('mer_id'); $a->pageid = $this->getConfig('pageid'); $a->next_phase = 'paydata'; $a->valuta_code = $invoice->currency; $user = $invoice->getUser(); $a->cust_name = $user->getName(); $a->cust_email = $user->email; $a->cust_phone = $user->phone; $a->cust_address1 = $user->street; $a->cust_address2 = $user->street2; $a->cust_city = $user->city; $a->cust_state = $user->state ? $user->state : 'N/A'; $a->cust_zip = $user->zip ? $user->zip : '99999'; $a->cust_country_code = $user->country; $num = 0; foreach ($invoice->getItems() as $item) { $num++; $a->{"item{$num}_desc"} = $item->item_title; $a->{"item{$num}_price"} = $item->first_price; $a->{"item{$num}_qty"} = $item->qty; } $a->num_items = $num; if ((float) $invoice->first_discount) { $a->sales_discount_amout = $invoice->first_discount; } if ((float) $invoice->first_tax) { $a->sales_tax_amout = $invoice->first_tax; } $a->user1 = $invoice->public_id; if ((float) $invoice->second_total) { $a->rebill_type = $this->getRebillType($invoice); $a->rebill_desc = $invoice->getLineDescription(); if ($invoice->rebill_times != IProduct::RECURRING_REBILLS) { $a->rebill_count = $invoice->rebill_times; } } } public function getRebillType(Invoice $invoice) { $res = array(); $first_period = new Am_Period($invoice->first_period); $res[] = $this->rebill_type_map[$invoice->second_period]; $res[] = $invoice->second_total; if ($first_period->getUnit() == 'd') { $res[] = $first_period->getCount(); } return implode('-', $res); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'callback') { return new Am_Paysystem_Transaction_DalpayCheckout_Callback($this, $request, $response, $invokeArgs); } else { return new Am_Paysystem_Transaction_DalpayCheckout_Ipn($this, $request, $response, $invokeArgs); } } public function getReadme() { $callback = $this->getPluginUrl('callback'); $ipn = $this->getPluginUrl('ipn'); $order = $this->getDi()->url('signup',null,true,true); return <<$order You need to enable Silent Post Callback and set PostURL for your Order Page in DalPay account DalPay Account -> Order Page -> Settings $callback You need to add user1 and trans_id to Silent Post Fields Recurring Subscriptiono Notes: ----------------------------- When issued a fresh DalPay account, rebillings may be initially blocked. Contact DalPay Support to unblock rebillings and/or to raise the maximum rebilling amount per transaction. Only monthly, quarterly, six monthly, and yearly rebilling intervals are supported. You need to setup Merchant Server Notification at DalPay Account -> Order Page -> Server Notifications $ipn You need to add user1 to ExtraFields CUT; } } abstract class Am_Paysystem_Transaction_DalpayCheckout extends Am_Paysystem_Transaction_Incoming { function init() { header('X-PHP-Response-Code: 200', true, 200); if ($this->request->isGet() && $this->request->getRawBody()) { $res = array(); parse_str($this->request->getRawBody(), $res); foreach ($res as $k => $v) { $this->request->setParam($k, $v); } } } function getUniqId() { return $this->request->getParam('trans_id'); } function findInvoiceId() { return $this->request->getParam('user1'); } } class Am_Paysystem_Transaction_DalpayCheckout_Callback extends Am_Paysystem_Transaction_DalpayCheckout { function validateSource() { return $this->request->getParam('SilentPostPassword') == $this->getPlugin()->getConfig('password'); } function validateStatus() { return true; } function validateTerms() { return $this->request->getParam('total_amount') == $this->invoice->first_total; } function processValidated() { $thanks = $this->getPlugin()->getRootUrl() . "/thanks?id=" . $this->invoice->getSecureId("THANKS"); $title = $this->getPlugin()->getDi()->config->get('site_title'); parent::processValidated(); echo <<

      CLICK HERE to return to $title website

      CUT; exit; } } class Am_Paysystem_Transaction_DalpayCheckout_Ipn extends Am_Paysystem_Transaction_DalpayCheckout { function validateSource() { return ((int) $this->request->getParam('pageid') == (int) $this->getPlugin()->getConfig('pageid')) && $this->request->getParam('NotificationPassword') == $this->getPlugin()->getConfig('notify_password'); } function validateStatus() { return $this->request->getParam('trans_type') == 'debit' && $this->request->getParam('status') == 'accepted'; } function validateTerms() { return true; } }PK\v##9default/plugins/payment/paypal-plus/scripts/confirm.phtmlnu[setLayout('layout.phtml'); ?>
      _script('_receipt.phtml'); ?>

      PK\ ''3default/plugins/payment/paypal-plus/paypal-plus.phpnu[addText('client_id', array('size' => 60))->setLabel(___("OAuth client_id")); $form->addText('secret', array('size' => 60))->setLabel(___("OAuth Secret")); $form->addAdvCheckbox('testing')->setLabel('Test mode'); $form->addText('secret', array('size' => 60))->setLabel( ___("Paypal interface language\n en_US - english, de_DE - german, default is german") ); } function getReadme() { return <<getApi(); $items = array( ); foreach ($invoice->getItems() as $item) { $item = array( 'name' => $item->item_title, 'quantity' => intval($item->qty), 'price' => floatval($item->first_price), 'currency' => $invoice->currency ); $items['items'][] = $item; } $data = array( 'intent' => 'sale', 'redirect_urls' => array( 'return_url' => $this->getPluginUrl('thanks'), 'cancel_url' => $this->getCancelUrl() ), 'payer' => array( 'payment_method' => 'paypal' ), 'transactions' => array( array( 'amount' => array( 'currency' => $invoice->currency, 'total' => floatval($invoice->first_total), 'details' => array( 'subtotal' => floatval($invoice->first_subtotal), 'tax' => $invoice->first_tax, ) ), 'description' => $invoice->getLineDescription(), 'invoice_number' => $invoice->public_id, 'item_list' => $items, ) ), ); $payment = $api->createPayment($data, $invoice); if (empty($payment['id'])) throw new Am_Exception_InternalError("No transaction id was returned. Create request wasn't successful."); $invoice->data()->set(self::PAYMENT_KEY, $payment['id'])->update(); $a = new Am_Paysystem_Action_HtmlTemplate_PaypalPlus($this->getDir(), 'confirm.phtml'); $a->payment = $payment; $a->approval_url = $this->getApprovalUrl($payment); $a->invoice = $invoice; $a->country = $invoice->getCountry() ? : 'DE'; $a->mode = $this->getConfig('testing') ? 'sandbox' : 'live'; $a->language = $this->getConfig('language', 'de_DE'); $result->setAction($a); } function getApprovalUrl($payment) { foreach (@$payment['links'] as $r) if (@$r['rel'] == 'approval_url') return @$r['href']; } /** * * @return \Am_PaypalRestAPI */ function getApi() { return new Am_PaypalRestAPI( $this->getDi(), ($this->getConfig('testing') ? self::SANDBOX_ENDPOINT : self::LIVE_ENDPOINT), $this->getConfig('client_id'), $this->getConfig('secret') ); } function createThanksTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_PaypalPlus($this, $request, $response, $invokeArgs); } function processRefund(\InvoicePayment $payment, \Am_Paysystem_Result $result, $amount) { $api = $this->getApi(); $req = $api->createApiRequest($api->getEndpoint(sprintf('/v1/payments/sale/%s/refund',$payment->getInvoice()->data()->get(self::PAYMENT_KEY))), "POST"); $ret = $api->_processRequest($req, new stdClass, $payment->getInvoice()); if(@$ret['state'] == 'completed') return true; } } class Am_PaypalRestAPI { protected $di, $endpoint, $client_id, $secret; const TOKEN_KEY = 'paypal-rest-token'; function __construct(Am_Di $di, $endpoint, $client_id, $secret) { $this->di = $di; $this->endpoint = $endpoint; $this->client_id = $client_id; $this->secret = $secret; } /** * * @return Am_Di */ function getDi() { return $this->di; } function getEndpoint($function) { return $this->endpoint . $function; } function requestToken() { $req = new Am_HttpRequest($this->getEndpoint('/v1/oauth2/token')); $req->setMethod(Am_HttpRequest::METHOD_POST); $req->setHeader('Accept', 'application/json'); $req->setAuth($this->client_id, $this->secret); $req->addPostParameter('grant_type', 'client_credentials'); $resp = $req->send(); if ($resp->getStatus() !== 200) throw new Am_Exception_InternalError(___("Can't obtaint OAuth2 token")); $ret = json_decode($resp->getBody(), true); if (empty($ret['access_token'])) throw new Am_Exception_InternalError(___('Token is empy in response object')); return $ret; } function getToken() { $token = $this->getDi()->store->get(self::TOKEN_KEY); if (empty($token)) { $token = $this->requestToken(); $this->getDi()->store->set(self::TOKEN_KEY, $token['access_token'], "+" . $token['expires_in'] . " seconds"); $token = $token['access_token']; } return $token; } function createPayment($data, Invoice $invoice) { $req = $this->createApiRequest($this->getEndpoint('/v1/payments/payment'), "POST"); return $this->_processRequest($req, $data, $invoice); } function _processRequest(Am_HttpRequest $req, $data, Invoice $invoice) { $log = $invoice->getDi()->invoiceLogRecord; $log->setInvoice($invoice); $log->title = $req->getMethod() . ': ' . $req->getUrl(); $log->add(array('request' => $data), true); $req->setBody(json_encode($data)); $req->setHeader('Content-Type', 'application/json'); $resp = $req->send(); $body = $resp->getBody(); $ret = json_decode($body, true); $log->add(array('response' => $ret), true); if (@$ret['message']) { throw new Am_Exception_InputError($ret['message']); } return $ret; } function executePayment($payment_id, $payer_id, $invoice) { $req = $this->createApiRequest($this->getEndpoint(sprintf('/v1/payments/payment/%s/execute', $payment_id)), 'POST'); return $this->_processRequest($req, array('payer_id' => $payer_id), $invoice); } function createApiRequest($uri, $method = 'GET') { $req = new Am_HttpRequest($uri); $req->setMethod($method); $req->setHeader('Authorization', "Bearer " . $this->getToken()); return $req; } } class Am_Paysystem_Action_HtmlTemplate_PaypalPlus extends Am_Paysystem_Action_HtmlTemplate { protected $_template, $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->view->headScript()->appendFile('https://www.paypalobjects.com/webstatic/ppplus/ppplus.min.js'); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Transaction_PaypalPlus extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->request->get('paymentId'); } function findInvoiceId() { $invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByData(Am_Paysystem_PaypalPlus::PAYMENT_KEY, $this->request->get('paymentId')); if ($invoice) return $invoice->public_id; } public function validateSource() { return true; } public function validateStatus() { $payment_id = $this->request->get('paymentId'); if ($this->invoice->data()->get(Am_Paysystem_PaypalPlus::PAYMENT_KEY) != $this->request->get('paymentId')) throw new Am_Exception_InternalError('Payment was created for different invoice'); $ret = $this->getPlugin()->getApi()->executePayment($payment_id, $this->request->get('PayerID'), $this->invoice); return (@$ret['state'] == 'approved'); } public function validateTerms() { return true; } function processValidated() { $this->invoice->addPayment($this); } } PK\iYY&default/plugins/payment/gocardless.phpnu[Your direct debit instruction has been setup successfully and your first payment of £%invoice.first_total% will typically take 7-10 days to process. Please check your email for confirmation of your payment dates.

      \n

      Please note that your membership access will be granted once your payment has been received.

      \n

      Your invoice reference: %invoice.public_id%

      \n

      %receipt_html%

      "; const DEBUG = true; public function supportsCancelPage() { return true; } public function getSupportedCurrencies() { return array('GBP'); } public function isNotAcceptableForInvoice(Invoice $invoice) { $supportedCountries = array('GB','AT','BE','CY', 'EE','FI','FR', 'DE','GR','IE','IT','LV','LU','MT', 'MC','NL','PT','SM','SK','SI','ES'); if (!in_array($invoice->getCountry(), $supportedCountries)) { return array(___('Direct Debits are not available in your country (%s)', $invoice->getCountry())); } parent::isNotAcceptableForInvoice($invoice); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant_id', array('size' => 10)) ->setLabel('Your Merchant ID'); $form->addText('app_id', array('size' => 64)) ->setLabel('Your App identifier'); $form->addText('app_secret', array('size' => 64)) ->setLabel('Your App secret'); $form->addText('access_token', array('size' => 64)) ->setLabel('Your Merchant access token'); $form->addAdvCheckbox("accept_pending_bills") ->setLabel("Recognize pending payments as completed"); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox(Testing) Account?"); $form->addTextarea("html", array('class' => 'el-wide', "rows"=>20))->setLabel( ___("Payment Instructions for customer\n". "you can enter any HTML here, it will be displayed to\n". "customer when they set up a direct debit using this payment system\n". "you can use the following tags:\n". "%s - Receipt HTML\n". "%s - Invoice Title\n". "%s - Invoice Id\n". "%s - Invoice Total", '%receipt_html%', '%invoice_title%', '%invoice.public_id%', '%invoice.first_total%')); $form->setDefault('html', self::DEFAULT_PENDING_HTML); } public function isConfigured() { return $this->getConfig('merchant_id') && $this->getConfig('app_id') && $this->getConfig('app_secret') && $this->getConfig('access_token'); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $rootURL = $this->getDi()->url('',null,true,2); $url = Am_Html::escape($this->getPluginUrl('ipn')); return <<GoCardless payment plugin configuration 1. Enable "gocardless" payment plugin at aMember CP->Setup->Plugins 2. Configure "GoCardless" payment plugin at aMember CP -> Setup/Configuration -> GoCardless 3. Set up "Webhook URI" in your GoCardless merchant account to $url Set up "Redirect URI" and "Cancel URI" to $rootURL 4. You can test the payments in 'sandbox' mode using Account number : 55779911 Sort code : 20-00-00 CUT; } protected function generate_nonce() { $n = 1; $rand = ''; do { $rand .= rand(1, 256); $n++; } while ($n <= 45); return base64_encode($rand); } public function _process(Invoice $invoice, Am_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); //* Recurring payment: Create a GoCardless Subscription if(!is_null($invoice->second_period)){ $a = new Am_Paysystem_Action_Redirect($url = ($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL) . '/connect/subscriptions/new'); $coef = 1; if($invoice->second_period == Am_Period::MAX_SQL_DATE) { $interval_unit = 'month'; $interval_length = 12*(2037-date('Y')); } else { $second_period = new Am_Period($invoice->second_period); switch ($second_period->getUnit()) { case 'd': $interval_unit = 'day'; break; case 'm': $interval_unit = 'month'; break; case 'y': $interval_unit = 'month'; $coef = 12; break; } $interval_length = $second_period->getCount(); } $first_period = new Am_Period($invoice->first_period); $start_at = new DateTime($first_period->addTo(date('Y-m-d')), new DateTimeZone('UTC')); $payment_details = array( 'amount' => $invoice->second_total, 'interval_length' => $interval_length*$coef, 'interval_unit' => $interval_unit, 'name' => $invoice->getLineDescription(), 'start_at' => $start_at->format('Y-m-d\TH:i:s\Z') ); if($invoice->rebill_times != IProduct::RECURRING_REBILLS) $payment_details['interval_count'] = $invoice->rebill_times; if (doubleval($invoice->first_total)>0) $payment_details['setup_fee'] = $invoice->first_total; } //* One-off payment: Create a GoCardless Bill else { $a = new Am_Paysystem_Action_Redirect($url = ($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL) . '/connect/bills/new'); $payment_details = array( 'amount' => $invoice->first_total, 'name' => $invoice->getLineDescription() ); } //* Build common billing information $user_details = array( 'first_name' => $u->name_f, 'last_name' => $u->name_l, 'email' => $u->email, 'billing_address1' => $u->street, 'billing_address2' => $u->street2, 'billing_town' => $u->city, 'billing_postcode' => $u->zip, 'country_code' => $u->country, ); $payment_details['merchant_id'] = $this->getConfig('merchant_id'); ksort($payment_details); ksort($user_details); if(is_null($invoice->second_period)) { foreach($payment_details as $v => $k) $a->__set("bill[$v]",$k); foreach($user_details as $v => $k) $a->__set("bill[user][$v]",$k); } $a->cancel_uri = $this->getCancelUrl(); $a->client_id = $this->getConfig('app_id'); $a->nonce = $this->generate_nonce(); $a->redirect_uri = $this->getPluginUrl('thanks'); $a->state = $invoice->public_id; if(!is_null($invoice->second_period)) { foreach($payment_details as $v => $k) $a->__set("subscription[$v]",$k); foreach($user_details as $v => $k) $a->__set("subscription[user][$v]",$k); } $date = new DateTime(null, new DateTimeZone('UTC')); $a->timestamp = $date->format('Y-m-d\TH:i:s\Z'); $url = parse_url($a->getUrl()); $a->signature = hash_hmac('sha256',$url['query'], $this->getConfig('app_secret'));; $result->setAction($a); } public function directAction(Am_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { if($request->getRawBody()) { $webhook = $request->getRawBody(); $webhook_array = json_decode($webhook, true); $request = new Am_Request($webhook_array, $request->getActionName()); } if ( 'pending' == $request->getActionName() ) { $invoice = $this->getDi()->invoiceTable->findBySecureId($request->getFiltered('id'), 'PENDING'); if (!$invoice) throw new Am_Exception_InputError(___("Sorry, seems you have used wrong link")); $view = new Am_View; $html = $this->getConfig('html', Am_Paysystem_Gocardless::DEFAULT_PENDING_HTML); $tpl = new Am_SimpleTemplate; $tpl->receipt_html = $view->partial('_receipt.phtml', array('invoice' => $invoice, 'di' => $this->getDi())); $tpl->invoice = $invoice; $tpl->user = $this->getDi()->userTable->load($invoice->user_id); $tpl->invoice_id = $invoice->invoice_id; $tpl->cancel_url = $this->getDi()->url('cancel',array('id'=>$invoice->getSecureId('CANCEL')),false); $tpl->invoice_title = $invoice->getLineDescription(); $view->invoice = $invoice; $view->content = $tpl->render($html) . $view->blocks('payment/offline/bottom'); $view->title = $this->getTitle() . ___(' Setup'); $response->setBody($view->render("layout.phtml")); } else { parent::directAction($request, $response, $invokeArgs); } } function getReturnUrl(Zend_Controller_Request_Abstract $request = null) { if( doubleval($this->invoice->first_total) && !$this->getConfig('accept_pending_bills') ) { return $this->getPluginUrl('pending') . "?id=" . $this->invoice->getSecureId("PENDING"); } else { return $this->getRootUrl() . "/thanks?id=" . $this->invoice->getSecureId("THANKS"); } } public function createTransaction(Am_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gocardless_Ipn($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Request $request, Zend_Controller_Response_Http $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Gocardless_Thanks($this, $request, $response, $invokeArgs); } private function _sendRequest($url, $params, $method = 'POST') { $request = $this->createHttpRequest(); $request->setHeader(array( 'Accept' => 'application/json', 'User-Agent' => 'gocardless-php/v0.3.3', 'Authorization' => 'Bearer '.$this->getConfig('access_token'), )); $request->setAuth($this->getConfig('app_id'), $this->getConfig('app_secret')); $request->setUrl(($this->getConfig('testing') ? Am_Paysystem_Gocardless::SANDBOX_URL : Am_Paysystem_Gocardless::LIVE_URL) . $url); $request->setMethod($method); if (!is_null($params)) { $request->setBody(json_encode($params)); } if (Am_Paysystem_Gocardless::DEBUG) $this->logOther('Request to '.$url, var_export($params, true)); $response = $request->send(); if (Am_Paysystem_Gocardless::DEBUG) $this->logOther('Response to '.$url, var_export($response, true)); return $response; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { // Cancelling subscription $gocardless_id = $invoice->data()->get('gocardless_id'); $response = $this->_sendRequest('/api/v1/subscriptions/'.$gocardless_id.'/cancel', null, 'PUT'); $subscription = json_decode($response->getBody(),true); if ($response->getStatus() !== 200 || 'cancelled' != $subscription['status']) { throw new Am_Exception_InputError('An error occurred while processing your cancellation request'); } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { // Refund Bill $response = $this->_sendRequest('/api/v1/bills/'.$payment->transaction_id.'/refund', null, 'POST'); $bill = json_decode($response->getBody(),true); if ($response->getStatus() !== 201 || 'refunded' != $bill['status']) { throw new Am_Exception_InputError('This payment cannot be refunded'); } } } class Am_Paysystem_Transaction_Gocardless_Base extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { } public function findInvoiceId() { } public function validateSource() { return true; } public function validateTerms() { return true; } public function validateStatus() { return true; } /** * Generates, encodes, re-orders variables for the query string. * * @see GoCardless PHP library https://github.com/gocardless/gocardless-php * Taken from: lib/GoCardless/Utils.php */ public function generate_query_string($params, &$pairs = array(), $namespace = null) { if (is_array($params)) { foreach ($params as $k => $v) { if (is_int($k)) { $this->generate_query_string($v, $pairs, $namespace . '[]'); } else { $this->generate_query_string($v, $pairs, $namespace !== null ? $namespace . "[$k]" : $k); } } if ($namespace !== null) { return $pairs; } if (empty($pairs)) { return ''; } usort($pairs, array($this, 'sortPairs')); $strs = array(); foreach ($pairs as $pair) { $strs[] = $pair[0] . '=' . $pair[1]; } return implode('&', $strs); } else { $pairs[] = array(rawurlencode($namespace), rawurlencode($params)); } } /** * Sorts a pair * * @see GoCardless PHP library https://github.com/gocardless/gocardless-php * Taken from: lib/GoCardless/Utils.php */ public static function sortPairs($a, $b) { $keys = strcmp($a[0], $b[0]); if ($keys !== 0) { return $keys; } return strcmp($a[1], $b[1]); } } class Am_Paysystem_Transaction_Gocardless_Bill extends Am_Paysystem_Transaction_Gocardless_Base { public function getUniqId() { return $this->request->get('id'); } public function findInvoiceId() { //* Look up using source_id (if bill is part of a subscription) or id (if one-off payment) $gocardless_id = ( $this->request->get('source_id') ) ? $this->request->get('source_id') : $this->request->get('id'); $i = Am_Di::getInstance()->invoiceTable->findFirstByData('gocardless_id', $gocardless_id); if($i) { $this->invoice = $i; return $i->public_id; } return null; } public function autoCreate() { try { parent::autoCreate(); } catch (Am_Exception_Paysystem $e) { Am_Di::getInstance()->errorLogTable->logException($e); } } public function processValidated() { if(!$this->invoice) return; if (Am_Paysystem_Gocardless::DEBUG) Am_Di::getInstance()->errorLogTable->log("Billing IPN: Status: {$this->request->get('status')}, Invoice: {$this->invoice->public_id}"); $accept_pending_bills = $this->plugin->getConfig('accept_pending_bills'); switch ($this->request->get('status')) { case 'pending': if ($accept_pending_bills) { $this->invoice->addPayment($this); } break; case 'paid': if (!$accept_pending_bills) { $this->invoice->addPayment($this); } break; case 'failed': case 'cancelled': if ($accept_pending_bills) { $this->invoice->addVoid($this, $this->getUniqId()); } break; case 'refunded': $this->invoice->addRefund($this, $this->getUniqId()); break; case 'chargedback': $this->invoice->addChargeback($this, $this->getUniqId()); break; default: // Do nothing for withdrawn, retried break; } } } class Am_Paysystem_Transaction_Gocardless_Subscription extends Am_Paysystem_Transaction_Gocardless_Base { public function getUniqId() { return $this->request->get('id'); } public function findInvoiceId() { $i = Am_Di::getInstance()->invoiceTable->findFirstByData('gocardless_id', $this->request->get('id')); if($i) { $this->invoice = $i; return $i->public_id; } return null; } public function autoCreate() { try { parent::autoCreate(); } catch (Am_Exception_Paysystem $e) { Am_Di::getInstance()->errorLogTable->logException($e); } } public function processValidated() { if(!$this->invoice) return; if (Am_Paysystem_Gocardless::DEBUG) Am_Di::getInstance()->errorLogTable->log("Subscription IPN: Status: {$this->request->get('status')}, Invoice: {$this->invoice->public_id}"); switch ($this->request->get('status')) { case 'cancelled': case 'expired': $this->invoice->setCancelled(true); break; default: // Do nothing... we didn't really need the switch, // but futureproofing against new statuses :) break; } } } class Am_Paysystem_Transaction_Gocardless_Ipn extends Am_Paysystem_Transaction_Gocardless_Base { public function validate() { $payload = $this->request->get('payload'); $sig = $payload['signature']; unset($payload['signature']); $sign = $this->generate_query_string($payload); $hash = hash_hmac('sha256',$sign,$this->getPlugin()->getConfig('app_secret')); if(!$sig || ($sig != $hash)) throw new Am_Exception_Paysystem_TransactionSource("IPN seems to be received from unknown source, not from the paysystem"); } public function autoCreate() { return; } public function processValidated() { $payload = $this->request->get('payload'); $resource_type = $payload['resource_type']; switch ($resource_type) { case 'bill': foreach($payload['bills'] as $bill) { $request = new Am_Request($bill, $this->request->getActionName()); $transaction = new Am_Paysystem_Transaction_Gocardless_Bill($this->getPlugin(),$request, $this->response, $this->invokeArgs); $transaction->process(); } break; case 'subscription': foreach($payload['subscriptions'] as $subscription) { $request = new Am_Request($subscription, $this->request->getActionName()); $transaction = new Am_Paysystem_Transaction_Gocardless_Subscription($this->getPlugin(),$request, $this->response, $this->invokeArgs); $transaction->process(); } break; default: // do nothing... we don't handle pre-authorizations break; } } } class Am_Paysystem_Transaction_Gocardless_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->request->get('resource_id'); } public function validateSource() { $query = http_build_query(array( 'resource_id' => $this->request->get('resource_id'), 'resource_type' => $this->request->get('resource_type'), 'resource_uri' => $this->request->get('resource_uri'), 'state' => $this->request->get('state') ), '', '&'); return $this->request->get('signature') == hash_hmac('sha256', $query, $this->plugin->getConfig('app_secret')); } public function validateTerms() { // @todo return true; } public function validateStatus() { //* Confirm customer was successfully returned to our site //* This activates the Subscription / Bill at GoCardless $request = $this->plugin->createHttpRequest(); $request->setHeader(array( 'Accept' => 'application/json', 'User-Agent' => 'gocardless-php/v0.3.3' )); $request->setAuth($this->plugin->getConfig('app_id'), $this->plugin->getConfig('app_secret')); $request->setUrl(($this->plugin->getConfig('testing') ? Am_Paysystem_Gocardless::SANDBOX_URL : Am_Paysystem_Gocardless::LIVE_URL) . '/api/v1/confirm'); $request->addPostParameter('resource_id', $this->request->get('resource_id')); $request->addPostParameter('resource_type', $this->request->get('resource_type')); $request->addPostParameter('resource_uri', $this->request->get('resource_uri')); $request->setMethod('POST'); $response = $request->send(); $response = json_decode($response->getBody(),true); //* Store the resource_id of the subscription / bill $this->invoice->data()->set('gocardless_id', $this->request->get('resource_id'))->update(); return true; } public function findInvoiceId() { return $this->request->get('state'); } public function processValidated() { $accept_pending_bills = $this->plugin->getConfig('accept_pending_bills'); // Process free trial payment... if (!doubleval($this->invoice->first_total)) { $this->isfirst = true; $this->invoice->addAccessPeriod($this); } // ... and one-off bills (NB: subscription bills handled by IPN) else if($accept_pending_bills && 'bill' == $this->request->get('resource_type')) { parent::processValidated(); } } }PK\JX)default/plugins/payment/deal-guardian.phpnu[addText("secret", array('class' => 'el-wide')) ->setLabel("Secret Key\n" . 'Can be found at Vendors -> ThirdParty Integrations -> aMember'); } public function __construct(Am_Di $di, array $config) { parent::__construct($di, $config); foreach ($di->paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->productTable->customFields()->add( new Am_CustomFieldText( 'dg_product_id', "DealGuardian Product ID", "ID of corresponding product from your DealGuardian account. Should be specified in this format: product_id-pricepoint_id Where product_id - is ID of product in DelaGuardian, pricepoint_id is ID of price point. If Price point doesn't matter it can be ommited.
      Example:
      Price point 1 of product # 34: 34-1
      Product #36 : 36") ); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { throw new Am_Exception_InputError("Not supported for this payment method!"); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return Am_Paysystem_Transaction_DealGuardian::create($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function canAutoCreate() { return true; } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } function getReadme() { $url = $this->getPluginUrl('ipn'); return <<DealGuardian.Com integration 1. In plugin configuration create any alpha-numeric Secret Key. 2. Create separate products in aMember CP -> Manage Products for each corresponding product from DealGuardian.Com 3. In your DealGuardian.com account -> Vendors -> Third Party Integrations -> MEMBERSHIP SITE SCRIPTS create integration for each product which should be linked to aMember product. Set Secret Key to the same value as you set in Plugin configuration. Set URL to integration to $url 4. For each aMember product set "DealGuardian Product ID". You can get these values from your DealGuardian.com account -> Vendors Third Party Integrations screen. CUT; } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } } class Am_Paysystem_Transaction_DealGuardian extends Am_Paysystem_Transaction_Incoming { /** * @var Invoice $invoice; */ public $invoice; protected $_autoCreateMap = array( 'name_f' => 'buyer_first_name', 'name_l' => 'buyer_last_name', 'email' => 'buyer_email', 'user_external_id' => 'buyer_email', 'invoice_external_id' => array('transaction_subscription_id', 'transaction_parent_id', 'transaction_id'), ); public function getUniqId() { return $this->request->get('transaction_id'); } public function validateSource() { $hash = $this->request->get('security_hash'); $k = md5($s = $this->request->getInt('transaction_id') . $this->request->get('transaction_amount') . $this->getPlugin()->getConfig('secret')) == $hash; return $k; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function autoCreateGetProducts() { $product_id = $this->request->get('product_id'); $price_point = $this->request->get('product_price_point'); if (empty($product_id)) return; $product = $this->getPlugin()->getDi()->productTable->findFirstByData('dg_product_id', $product_id."-".$price_point); if(!$product) $product = $this->getPlugin()->getDi()->productTable->findFirstByData('dg_product_id', $product_id); return $product; } function processValidated() { // Nothing to do here } static function create(Am_Paysystem_DealGuardian $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { switch ($request->get('transaction_type')) { case 'sale' : return new Am_Paysystem_Transaction_DealGuardian_Sale($plugin, $request, $response, $invokeArgs); case 'refund' : return new Am_Paysystem_Transaction_DealGuardian_Refund($plugin, $request, $response, $invokeArgs); case 'subscr_cancel' : return new Am_Paysystem_Transaction_DealGuardian_Refund($plugin, $request, $response, $invokeArgs); default: return null; // Don;t know how to handle IPN message. } } function findInvoiceId() { return null; } } class Am_Paysystem_Transaction_DealGuardian_Sale extends Am_Paysystem_Transaction_DealGuardian { function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_DealGuardian_Refund extends Am_Paysystem_Transaction_DealGuardian { function processValidated() { $this->invoice->addRefund($this, $this->request->get('transaction_parent_id')); } } class Am_Paysystem_Transaction_DealGuardian_Cancel extends Am_Paysystem_Transaction_DealGuardian { function processValidated() { $this->invoice->setCancelled(true); } }PK\billingPlanTable->customFields()->add( new Am_CustomFieldText( 'payone_product_id', 'PayOne Offer ID', 'you have to create similar offer in PayOne and enter its number here' ) ); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("aid")->setLabel('Sub-Account-ID')->addRule('required'); $form->addText("portalid")->setLabel('Portal-ID')->addRule('required'); $form->addText('secret_key', array('class' => 'el-wide')) ->setLabel('Key')->addRule('required'); $form->addSelect("testing", array(), array('options' => array( ''=>'No', '1'=>'Yes' )))->setLabel('Test Mode'); } function getSupportedCurrencies() { return array('EUR', 'AUD', 'CHF', 'DKK', 'GBP', 'NOK', 'NZD', 'SEK', 'USD'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect(self::API_URL); /* */ $params = array( 'aid' => $this->getConfig('aid'), //Sub Account ID 'portalid' => $this->getConfig('portalid'), //Payment portal ID 'mode' => $this->getConfig('testing') ? 'test' : 'live', //Test: Test mode, Live: Live mode 'encoding' => 'UTF-8', //ISO 8859-1 (default), UTF-8 'clearingtype' => 'cc', //elv: Debit payment //cc: Credit card //vor: Prepayment //rec: Invoice //sb: Online bank transfer //wlt: e-wallet //fnc: Financing 'reference' => $invoice->public_id, 'customerid' => $invoice->user_id, 'invoiceid' => $invoice->public_id, 'param' => $invoice->public_id, 'successurl' => $this->getReturnUrl(), //URL "payment successful" (only if responsetype=REDIRECT or required by corresponding request) 'backurl' => $this->getCancelUrl() //URL "faulty payment" (only if responsetype=REDIRECT or required by corresponding request) ); //Parameter („createaccess“) $first_period = new Am_Period($invoice->first_period); $params['request'] = 'createaccess'; $params['productid'] = $invoice->getItem(0)->getBillingPlanData('payone_product_id'); // + + N..7 ID for the offer $params['amount_trail'] = $invoice->first_total * 100; // - + N..6 Total price of all items during the initial term. Must equal the sum (quantity * price) of all items for the initial term (in the smallest currency unit, e.g. Cent). $params['period_unit_trail'] = strtoupper($first_period->getUnit()); // - + Default Time unit for initial term, possible values: Y: Value in years M: Value in months D: Value in days $params['period_length_trail'] = $first_period->getCount(); // - + N..4 Duration of the initial term. Can only be used in combination with period_unit_trail. $params['id_trail'] = $invoice->getItem(0)->billing_plan_id; // + + AN..100 Item number (initial term) $params['no_trail'] = 1; // + + N..5 Quantity (initial term) $params['pr_trail'] = $invoice->first_total * 100; // + + N..7 Unit price of the item in smallest currency unit (initial term) $params['de_trail'] = $invoice->getItem(0)->item_description; // + + AN..255 Description (initial term) $params['ti_trail'] = $invoice->getItem(0)->item_title; // + + AN..100 Title (initial term) //$params['va_trail'] = ''; // - + N..4 VAT rate (% or bp) (initial term) value < 100 = percent value > 99 = basis points if($invoice->second_total>0){ $second_period = new Am_Period($invoice->second_period); $params['amount_recurring'] = $invoice->second_total * 100; // - + N..6 Total price of all items during the subsequent term. Must equal the sum (quantity * price) of all items for the subsequent term (in the smallest currency unit, e.g. Cent). $params['period_unit_recurring'] = strtoupper($second_period->getUnit()); // - + Default Time unit for subsequent term, possible values: Y: Value in years M: Value in months D: Value in days N: only if no subsequent term $params['period_length_recurring'] = $second_period->getCount(); // - + N..4 Duration of the subsequent term. Can only be used in combination with period_unit_recurring. $params['id_recurring'] = $invoice->getItem(0)->billing_plan_id; // - + AN..100 Item number (subsequent term) $params['no_recurring'] = 1; // - + N..5 Quantity (subsequent term) $params['pr_recurring'] = $invoice->second_total * 100; // - + N..7 Unit price of the item in smallest currency unit (subsequent term) $params['de_recurring'] = $invoice->getItem(0)->item_description; // - + AN..255 Description (subsequent term) $params['ti_recurring'] = $invoice->getItem(0)->item_title; // - + AN..100 Title (subsequent term) //$params['va_recurring'] = ''; // - + N..4 VAT rate (% or bp) (subsequent term) value < 100 = percent value > 99 = basis points ///// } /* //Parameter ( „pre-/authorization“ ) $params['request'] = 'authorization'; $params['amount'] = $invoice->first_total * 100; $params['currency'] = $invoice->currency; $params['it'] = 'goods'; //For BSV: Item type $params['id'] = ''; //Your item no. $params['pr'] = $invoice->first_total * 100; //Price in Cent $params['no'] = 1; //Quantity $params['de'] = ''; //Item description //$params['va'] = ''; //VAT (optional) ///// */ ksort($params); $a->hash = strtolower(md5(implode('', $params) . $this->getConfig('secret_key'))); //Hash value (see chapter 3.1.4) //Parameter ( personal data ) $params['firstname'] = $u->name_f; //AN..50 First name $params['lastname'] = $u->name_l; //AN..50 Surname //$params['company'] = ''; //AN..50 Company $params['street'] = $u->street; //AN..50 Street $params['zip'] = $u->zip; //AN..10 Postcode $params['city'] = $u->city; //AN..50 City $params['country'] = $u->country; //Default Country (ISO 3166) $params['email'] = $u->email; //AN..50 Email address $params['language'] = 'en'; //Language indicator (ISO 639) //If the language is not transferred, the browser //language will be used. For a non-supported //language, English will be used. ///// foreach ($params as $k=>$v) $a->addParam ($k, $v); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payone($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payone_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } function getReadme() { return <<Payone payment plugin configuration 1. Configure Portal-ID, Sub-Account-ID and Key at aMember CP -> Setup/Configuration -> Payone You can get IDs and Key from Payone Merchant Interface -> Configuration -> Payment Portals Click 'Edit' link near to an existing Portal or create new one using 'Add Portal' button. Then navigate to 'API-Parameters' tab. 2. Configure 'SessionStatus URL' and 'TransactionStatus URL' at Payone Merchant Interface -> Configuration -> Payment Portals: Advanced to the following URL: %root_surl%/payment/payone/ipn 3. Configure 'PayOne Offer ID' at aMember CP -> Manage Products -> Edit Set it up first at Payone Merchant Interface -> Configuration -> Payment Portals: Offers CUT; } } class Am_Paysystem_Transaction_Payone_Thanks extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('param'); } public function getUniqId() { return $this->request->get('txid'); } public function validateSource() { if ($this->getPlugin()->getConfig('secret_key') != $this->request->get('key')) return false; else return true; } public function validateStatus() { return ($this->request->get('txaction ') == 'paid'); } public function validateTerms() { return true; } public function getInvoice() { return $this->invoice; } } class Am_Paysystem_Transaction_Payone extends Am_Paysystem_Transaction_Incoming { function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); //SessionStatus. As a reply to the request, the string "SSOK" is expected. //TransactionStatus. As a reply to the request, the string "TSOK" is expected. if ($this->request->get('txid') || $this->request->get('txaction')) print "TSOK"; else print "SSOK"; } public function findInvoiceId() { $param = $this->request->get('param'); if (is_array($param)) $param = $param[1]; return $param; } public function getUniqId() { $txid = $this->request->get('txid'); if (is_array($txid)) $txid = $txid[1]; return $txid; } public function validateSource() { $params = $this->request->getParams(); unset($params['key']); ksort($params); $hash = strtolower(md5(implode('', $params) . $this->getPlugin()->getConfig('secret_key'))); //The SessionStatus/TransactionStatus is sent from the following IP addresses: 213.178.72.196, or 213.178.72.197 as well as 217.70.200.0/24. $this->_checkIp(<<request->get('key')) // return false; return true; } public function validateStatus() { if($this->request->get('mode') == 'test' && !$this->getPlugin()->getConfig('testing')){ throw new Am_Exception_Paysystem_TransactionInvalid('Test IPN received but test mode is not enabled'); } return true; } public function validateTerms() { return true; } public function processValidated() { $action = $this->request->get('action'); if (is_array($action)) $action = $action[1]; $txaction = $this->request->get('txaction'); if (is_array($txaction)) $txaction = $txaction[1]; //if ($action == 'add') if ($txaction == 'appointed') // 'paid' { $this->invoice->addPayment($this); } if ($txaction == 'refund') { $this->invoice->addRefund($this, Am_Di::getInstance()->invoicePaymentTable->getLastReceiptId($this->invoice->pk())); } } } PK\Bmkk/default/plugins/payment/junglepay/junglepay.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Junglepay extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_DATE = '$Date$'; const PLUGIN_REVISION = '5.0.6'; const URL_ACC = 'http://my.junglepay.com/dashboard'; const URL_INSTRUCTION = 'http://wiki.txtnation.com/wiki/JunglePay_Widget_Integration_Guide'; const JP_CAMPAIGN_ID= 'junglepay-campaign-id'; protected $defaultTitle = "JunglePay"; protected $defaultDescription = "SMS payments"; public function _initSetupForm(Am_Form_Setup $form) { $form->setTitle('JunglePay'); $form->addText('company_code') ->setLabel('Your company code from txtNation') ->addRule('required'); } public function isConfigured() { return (bool) $this->getConfig('company_code', false); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText(self::JP_CAMPAIGN_ID, "Junglepay campaign ID", null, null, array('size' => 40))); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if(count($invoice->getItems()) > 1) throw new Am_Exception_InternalError('Only one product at invoice is allowed'); $bp = $this->getDi()->billingPlanTable->load($invoice->getItem(0)->billing_plan_id); if(!($campaignId = $bp->data()->get(self::JP_CAMPAIGN_ID))) throw new Am_Exception_InternalError("Product #{$invoice->getItem(0)->item_id} cannot be paid by junglepay - has no Campaign ID"); $a = new Am_Paysystem_Action_HtmlTemplate_Junglepay($this->getDir(), 'payment-junglepay-iframe.phtml'); $a->wkey = $campaignId; $a->refererId = $invoice->public_id; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Junglepay($this, $request, $response, $invokeArgs); } public function thanksAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $log = $this->logRequest($request, 'POSTBACK [thanks]'); if($this->invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->getFiltered('referer'))) { $log->setInvoice($this->invoice)->update(); $response->setRedirect($this->getReturnUrl()); return; } throw new Am_Exception_InputError("Invoice not found"); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $thanks = $this->getPluginUrl('thanks'); $acc = self::URL_ACC; $instruction = self::URL_INSTRUCTION; return <<Junglepay payment plugin readme: Go to your Jungle Pay account ($acc) and create needed number of campaigns using this instruction here $instruction (one aMember product - one JunglePay campaign): At Step 6 - "Tool type" select Javascript. At Step 7 - "Notifications" set: Post URL is $ipn Destination (Password) URL: $thanks After Step 6 - you will see "Your Campaign ID", copy this string to "Junglepay campaign ID" option at aMember product settings page and save it CUT; } } class Am_Paysystem_Transaction_Junglepay extends Am_Paysystem_Transaction_Incoming { protected $vars; public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $this->vars = $this->request->getRequestOnlyParams(); } public function findInvoiceId() { return $this->request->getFiltered('refererid'); } public function getUniqId() { return $this->request->getInt('transactionID'); } public function validateStatus() { return in_array($this->vars['action'], array('mp_confirm_password', 'mp_new_password')); } public function validateTerms() { return true; } public function validateSource() { if($this->getPlugin()->getConfig('company_code') != $this->request->getFiltered('cc')) throw new Am_Exception_Paysystem_TransactionInvalid("Wrong company code [{$this->request->get('cc')}]"); return true; } public function processValidated() { if($this->vars['action'] =='mp_confirm_password') { parent::processValidated(); if(!$this->invoice->comment && ($n = $this->request->get('number')) && ($p = $this->request->get('passwd'))) $this->invoice->updateQuick('comment', "SMS num/pass: $n/$p"); } } } PK\ zzHdefault/plugins/payment/junglepay/scripts/payment-junglepay-iframe.phtmlnu[setLayout('layout.phtml'); ?> PK\<$default/plugins/payment/amex-hpp.phpnu[addText('merchant') ->setLabel("Merchant ID\n" . 'The unique identifier issued to you by your payment provider') ->addRule('required'); $form->addPassword('password') ->setLabel('API Password') ->addRule('required'); } public function isConfigured() { return $this->getConfig('merchant') && $this->getConfig('password'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $req = new Am_HttpRequest(sprintf('https://gateway-japa.americanexpress.com/api/rest/version/23/merchant/%s/session', $this->getConfig('merchant')), Am_HttpRequest::METHOD_POST); $req->setAuth('merchant.' . $this->getConfig('merchant'), $this->getConfig('password')); $req->setBody(json_encode(array( 'apiOperation' => 'CREATE_PAYMENT_PAGE_SESSION', 'order' => array( 'id' => $invoice->public_id, 'amount' => $invoice->first_total, 'currency' => $invoice->currency ), 'paymentPage' => array( 'cancelUrl' => $this->getCancelUrl(), 'returnUrl' => $this->getPluginUrl('thanks') ) ))); $this->logRequest($req); $res = $req->send(); $this->logResponse($res); if ($res->getStatus() != 201) { $result->setFailed(sprintf('Incorrect Responce Status From Paysystem [%s]', $res->getStatus())); return; } $msg = json_decode($res->getBody(), true); if ($msg['result'] == 'ERROR') { $result->setFailed($msg['error']['explanation']); return; } $invoice->data()->set(self::DATA_KEY, $msg['successIndicator'])->update(); $a = new Am_Paysystem_Action_Redirect(self::URL); $a->{'merchant'} = $this->getConfig('merchant'); $a->{'order.description'} = $invoice->getLineDescription(); $a->{'paymentPage.merchant.name'} = $this->getDi()->config->get('site_title'); $a->{'session.id'} = $msg['session']['id']; $this->logRequest($a); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return null; } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_AmexHpp_Thanks($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_AmexHpp_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { $invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByData(Am_Paysystem_AmexHpp::DATA_KEY, $this->request->getParam('resultIndicator')); if ($invoice) return $invoice->public_id; } public function getUniqId() { return $this->request->get('resultIndicator'); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function validateSource() { return true; } } PK\,7,7)default/plugins/payment/1shoppingcart.phpnu[addInteger('merchant_id', array('size' => 20)) ->setLabel('Your Merchant ID#'); $form->addPassword('password')->setLabel("Postback Password\n" . 'Should be the same as in your 1SC account'); $form->addText('key', array('size' => 30)) ->setLabel("API Key\n" . '1SC -> My Account -> API Settings -> Your Current Merchant API Key'); $form->addAdvCheckbox('skip_amount_check') ->setLabel("Skip Amount Check\n" . 'Plugin will not check amount of incomming transaction. This option makes it possible to use coupons on 1SC'); $form->addText('api_resend', array('size' => 60)) ->setLabel("Resend API Requests\n" . 'Specify url of third-party script that should receive API notifications as well'); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('1shoppingcart_id', "1ShoppingCart Product#", "for any products you have to create corresponding product in 1SC admin panel and enter the id# here")); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $result->setAction($a); $a->MerchantID = $this->config['merchant_id']; $a->ProductID = $invoice->getItem(0)->getBillingPlanData('1shoppingcart_id'); $a->AMemberID = $invoice->invoice_id; $a->PostBackURL = $this->getDi()->url("payment/1shoppingcart/ipn",null,false,2); $a->clear = 1; $a->filterEmpty(); $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getActionName() == 'api' && $api_resend = $this->getConfig('api_resend')){ try{ $client = new Am_HttpRequest($api_resend, Am_HttpRequest::METHOD_POST); $client->setHeader('Content-type', 'text/xml'); $client->setBody($request->getRawBody()); $response = $client->send(); } catch(Exception $e) { $this->getDi()->errorLogTable->logException($e); } } parent::directAction($request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'api') return new Am_Paysystem_Transaction_1shoppingcart_api($this, $request, $response, $invokeArgs); else return new Am_Paysystem_Transaction_1shoppingcart($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $thanksURL = $this->getDi()->url('thanks',null,false,2); return <<1ShoppingCart payment plugin configuration 1. Enable "1shoppingcart" payment plugin at aMember CP->Setup->Plugins 2. Configure "1shoppingcart" payment plugin at aMember CP -> Setup/Configuration -> 1ShoppingCart Make sure you set the same API Key in aMember CP and 1ShoppingCart Merchants CP -> My Account -> API Settings -> Your Current Merchant API Key 3. Create equivalents for all aMember products in 1ShoppingCart Merchants CP. Make sure it has the same subscription terms (period, price) as aMember Products. Set "Thanks URL" for all 1ShoppingCart products to $thanksURL Write down product# of all 1ShoppingCart products. 4. Visit aMember CP -> Manage Products, click "Edit" on each product and enter "1ShoppingCart Product#" for each corresponding billing plan, then click "Save". 5. Try your integration - go to aMember signup page, and try to make new signup. ---------------- In case of any issues with IPN Notifications (if members is not activated in aMember automatically) Please try to click 'Repost Order To aMember' link at your 1SC account -> Orders -> Order Details and check is notification receved at aMember CP -> Utilites -> Logs ---------------- 1ShoppingCart in front of aMember configuration instructions can be found here: http://www.amember.com/docs/1ShoppingCart_in_front_of_aMember CUT; } function findOrder($order_id){ return $this->getDi()->invoicePaymentTable->findFirstBy(array('transaction_id' => $order_id, 'paysys_id' => $this->getId())); } } class Am_Paysystem_Transaction_1shoppingcart_api extends Am_Paysystem_Transaction_Incoming { protected $_xml; protected $_order; protected $_client; const APIURL = 'https://www.mcssl.com/API/'; function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $str = $request->getRawBody(); $this->_xml = simplexml_load_string($str); if (!$this->_xml) throw new Am_Exception_Paysystem_TransactionInvalid('Invalid xml received from 1SC: ' . $str); $this->_order = $this->apiRequest('Orders', (string) $this->_xml->Token); $this->_client = $this->apiRequest('Clients', (string) $this->_order->OrderInfo->ClientId); } function apiRequest($table, $value) { $url = self::APIURL . $this->getPlugin()->getConfig('merchant_id') . "/" . $table . "/" . $value; try { $r = new Am_HttpRequest($url, Am_HttpRequest::METHOD_POST); $r->setBody("" . $this->getPlugin()->getConfig('key') . ""); $resp = $r->send()->getBody(); $xml = simplexml_load_string($resp); if (!$xml) throw new Am_Exception_Paysystem_TransactionInvalid('1SC API response is not a valid XML:' . $resp); if ((string) $xml->attributes()->success != 'true') throw new Am_Exception_Paysystem_TransactionInvalid('1SC API response is not sucessfull: ' . $resp); } catch (Exception $e) { Am_Di::getInstance()->errorLogTable->logException($e); return null; } return $xml; } public function autoCreateGetProducts() { $products = array(); foreach ($this->_order->OrderInfo->LineItems->LineItemInfo as $l) { if ($pid = (string) $l->ProductId) $pl = Am_Di::getInstance()->billingPlanTable->findFirstByData('1shoppingcart_id', $pid); if (!$pl) continue; $p = $pl->getProduct(); if ($p) $products[] = $p; } return $products; } public function findInvoiceId() { return $this->generateInvoiceExternalId(); } public function fetchUserInfo() { $countryRecord = Am_Di::getInstance()->CountryTable->findFirstBy(array( 'title' => (string) $this->_client->ClientInfo->CountryName )); if ($countryRecord && $countryRecord->isLoaded()) { $country = $countryRecord->country; $stateRecord = Am_Di::getInstance()->StateTable->findFirstBy( array( 'title' => (string) $this->_client->ClientInfo->StateName, 'country' => $countryRecord->country )); if ($stateRecord && $stateRecord->isLoaded()) $state = $stateRecord->state; } else { $country = $state = ''; } return array( 'name_f' => (string) $this->_client->ClientInfo->FirstName, 'name_l' => (string) $this->_client->ClientInfo->LastName, 'street' => (string) $this->_client->ClientInfo->Address1, 'city' => (string) $this->_client->ClientInfo->City, 'zip' => (string) $this->_client->ClientInfo->Zip, 'email' => (string) $this->_client->ClientInfo->Email, 'country' => $country, 'state' => $state, 'phone' => (string) $this->_client->ClientInfo->Phone ); } function generateUserExternalId(array $userInfo) { return (string) $this->_client->ClientInfo->Id; } public function generateInvoiceExternalId() { $roid = (string) $this->_order->OrderInfo->RecurringOrderId; return ($roid ? $roid : $this->getUniqId()); } function validateSource() { if(!((bool) $this->_order)) return false; if($this->getPlugin()->findOrder($order_id = $this->getUniqId())) throw new Am_Exception_Paysystem_TransactionAlreadyHandled('Transaction '.$order_id.' is already handled'); return true; } public function getUniqId() { return (string) $this->_order->OrderInfo->Id; } public function validateStatus() { return (((string) $this->_order->OrderInfo->OrderStatusType) == 'Accepted'); } public function validateTerms() { return true; } public function processValidated() { if(floatval($this->_order->OrderInfo->GrandTotal) == 0) $this->invoice->addAccessPeriod($this); else $this->invoice->addPayment($this); } function setInvoiceLog(InvoiceLog $log) { parent::setInvoiceLog($log); $this->getPlugin()->logOther('1SC API NOTIFICATION', $this->_xml); $this->getPlugin()->logOther('1SC ORDER', $this->_order->asXML()); $this->getPlugin()->logOther('1SC CLIENT', $this->_client->asXML()); } } class Am_Paysystem_Transaction_1shoppingcart extends Am_Paysystem_Transaction_Incoming { const START_RECURRING = 'start_recurring'; const REBILL = 'rebill'; const PAYMENT = 'payment'; const RECURRING_EOT = 'recurring_eot'; function validateSource() { $vars = $this->request->getPost(); $sign = $vars['VerifySign']; unset($vars['VerifySign']); $vars['PostbackPassword'] = $this->plugin->getConfig('password'); $str = join('', array_values($vars)); $md5 = md5($str); if ($md5 != $sign) { throw new Am_Exception_Paysystem_TransactionInvalid("Verify sign incorrect."); } if($this->getPlugin()->findOrder($order_id = $this->getUniqId())) throw new Am_Exception_Paysystem_TransactionAlreadyHandled('Transaction '.$order_id.' is already handled'); return true; } function getUniqId() { return $this->request->get('OrderID'); } public function getAmount() { return $this->request->get('Amount'); } function validateTerms() { if ($this->getPlugin()->getConfig('skip_amount_check')) return true; $amount = floatval($this->request->get("Amount")); $type = $this->request->get("Status"); if ($type == self::RECURRING_EOT) return true; return ($amount == floatval(($type == self::REBILL ? $this->invoice->second_total : $this->invoice->first_total))); } function findInvoiceId() { return $this->request->get("AMemberID"); } function loadInvoice($invoiceId) { $invoiceId = preg_replace('/-.*/', '', $invoiceId); // Assuming this is invoice imported from v3. $importedInvoiceId = Am_Di::getInstance()->db->selectCell(" SELECT p.invoice_id FROM ?_invoice_payment p LEFT JOIN ?_data d ON d.`table`='invoice_payment' AND d.id = p.invoice_payment_id AND d.`key` = 'am3:id' WHERE d.value=?", $invoiceId); if($importedInvoiceId) $invoice = Am_Di::getInstance()->invoiceTable->load($importedInvoiceId); if(!$invoice) { $invoice = Am_Di::getInstance()->invoiceTable->load($invoiceId); if($invoice->data()->get('am3:id')) $invoice = null; // Imported record. Skip it. } // update invoice_id in the log record if ($invoice && $this->log) { $this->log->updateQuick(array( 'invoice_id' => $invoice->pk(), 'user_id' => $invoice->user_id, )); } return $invoice; } function processValidated() { switch ($this->request->get("Status")) { case self::START_RECURRING : if(!count($this->invoice->getAccessRecords()) && (floatval($this->invoice->first_total) == 0)) $this->invoice->addAccessPeriod($this); else $this->invoice->addPayment($this); break; case self::PAYMENT : case self::REBILL : $this->invoice->addPayment($this); break; case self::RECURRING_EOT : $this->invoice->stopAccess($this); break; } } public function validateStatus() { return true; } }PK\NR**!default/plugins/payment/a1pay.phpnu[addText('a1lite_form_key')->setLabel("Ключ из HTML формы\n" . 'Инструменты -> A1Lite -> Создать кнопку' .'
      '. "затем скопировать 'value' параметра 'key' из полученной формы" .'
      '. 'например 123456 из ' . htmlspecialchars('')); $form->addText('a1lite_api_secret_key')->setLabel("Секретный ключ\n" . 'Инструменты -> A1Lite -> Управление -> Редактирование сервиса'); $form->addSelect('type', array(), array('options' => array( '' => 'Любой тип оплаты', 'wm' => 'WebMoney', 'sms' => 'SMS', 'terminal' => 'Терминал оплаты Qiwi', 'qiwi_wallet' => 'Qiwi кошелек', 'w1' => 'W1', 'rbk_money' => 'РБК Money', 'ym' => 'Яндекс.Деньги', 'card' => 'Visa/MasterCard (ЕКО)', 'mb' => 'Visa/MasterCard (Мастер-Банк)', 'bm' => 'Visa/MasterCard (Банк Москвы)', 'esgp' => 'Терминал ЕСГП', 'russky_standart' => 'Visa/MasterCard (Русский Стандарт)', 'mc' => 'Мобильный платёж' )))->setLabel('Тип оплаты, на который Вы хотите отправить пользователя'); $form->addAdvCheckbox('testing')->setLabel("Тестирование сервиса\n" . 'Имитацию отправки запроса из аккаунта A1pay' .'
      '. 'c передачей данных скрипту-обработчику'); } public function getSupportedCurrencies() { return array('RUR'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::FORM_ACTION_URL); $a->key = $this->getConfig('a1lite_form_key'); $a->cost = $invoice->first_total; $a->name = $invoice->getLineDescription(); $a->default_email = $invoice->getEmail(); $a->order_id = 0; $a->comment = $invoice->public_id; if ($this->getConfig('type')) $a->type = $this->getConfig('type'); //verbose - параметр указывает, что делать в случае возникновения ошибки, если нет данных о пользователе (почты или телефона для способов платежа, где они обязательны). Значения: 1 - выдавать ошибку, 0 - перебрасывать на страницу выбора оплаты. //phone_number - телефонный номер пользователя $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_A1pay($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_A1pay_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme(){ return <<A1pay plugin installation 1. Configure plugin at aMember CP -> Setup/Configuration -> A1pay 2. Configure your A1pay account: - URL скрипта обработчика на Вашем сайте: %root_url%/payment/a1pay/ipn - URL страницы успешной покупки: %root_url%/payment/a1pay/thanks - URL страницы ошибки: %root_url%/cancel 3. Run a test transaction to ensure everything is working correctly. CUT; } } class Am_Paysystem_Transaction_A1pay extends Am_Paysystem_Transaction_Incoming{ public function getUniqId() { return $this->request->get("tid"); } public function findInvoiceId(){ return $this->request->get("comment"); } public function validateSource() { $this->_checkIp(<<request->getPost(); $fields = array('tid', 'name', 'comment', 'partner_id', 'service_id', 'order_id', 'type', 'partner_income', 'system_income'); if ($this->getPlugin()->getConfig('testing') || isset($params['test'])) $fields[] = 'test'; $hash = ''; foreach ($fields as $field) $hash .= $params[$field]; $hash .= $this->getPlugin()->getConfig('a1lite_api_secret_key'); $hash = md5($hash); return ($hash == $params['check']); } public function validateStatus() { return true; } public function validateTerms() { /** * @todo Add real validation here; Need to check variables that will be sent from A1pay. */ return true; } public function getAmount() { // partner_income - сумма в рублях вашего дохода по данному платежу // system_income - сумма в рублях, заплаченная абонентом. Значение может быть больше заявленной цены если клиент заплатил больше. return $this->request->get('system_income'); } public function processValidated() { $this->invoice->addPayment($this); echo 'Ok. Completed.'; exit; } } class Am_Paysystem_Transaction_A1pay_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { return $this->request->get("comment"); } public function getUniqId() { return $this->request->get("tid"); } public function validateStatus() { return true; } public function validateTerms() { return true; } public function validateSource() { return true; /* $params = $this->request->getQuery(); $fields = array('tid', 'name', 'comment', 'partner_id', 'service_id', 'order_id', 'type', 'partner_income', 'system_income'); if ($this->getPlugin()->getConfig('testing') || isset($params['test'])) $fields[] = 'test'; $hash = ''; foreach ($fields as $field) $hash .= $params[$field]; $hash .= $this->getPlugin()->getConfig('a1lite_api_secret_key'); $hash = md5($hash); return ($hash == $params['check']); */ } public function getInvoice() { return $this->invoice; } }PK\#default/plugins/payment/offline.phpnu[defaultTitle = ___("Offline Payment"); $this->defaultDescription = ___("pay using wire transfer or by sending offline check"); parent::__construct($di, $config); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getSupportedCurrencies() { return array_keys(Am_Currency::getFullList()); // support any } public function _initSetupForm(Am_Form_Setup $form) { $form->addTextarea("html", array('class' => 'el-wide', "rows"=>20))->setLabel( ___("Payment Instructions for customer\n". "you can enter any HTML here, it will be displayed to\n". "customer when he chooses to pay using this payment system\n". "you can use the following tags:\n". "%s - Receipt HTML\n". "%s - Invoice Title\n". "%s - Invoice Id\n". "%s - Invoice Total", '%receipt_html%', '%invoice_title%', '%invoice.public_id%', '%invoice.first_total%')); $label = Am_Html::escape(___('preview')); $url = Am_Html::escape($this->getPluginUrl('preview')); $text = ___('Please save your settings before use preview link'); $form->addHtml() ->setHtml(<<$label $text CUT ); } public function _process($invoice, $request, $result) { unset($this->getDi()->session->cart); if ((float)$invoice->first_total == 0) { $invoice->addAccessPeriod(new Am_Paysystem_Transaction_Free($this)); } $result->setAction( new Am_Paysystem_Action_Redirect( $this->getDi()->url("payment/".$this->getId()."/instructions", array('id'=>$invoice->getSecureId($this->getId())),false) ) ); } public function directAction($request, $response, $invokeArgs) { $actionName = $request->getActionName(); switch ($actionName) { case 'instructions' : $invoice = $this->getDi()->invoiceTable->findBySecureId($request->getFiltered('id'), $this->getId()); if (!$invoice) throw new Am_Exception_InputError(___("Sorry, seems you have used wrong link")); $view = new Am_View; $html = $this->getConfig('html', 'SITE OWNER DID NOT PROVIDE INSTRUCTIONS FOR OFFLINE PAYMENT YET'); $tpl = new Am_SimpleTemplate; $tpl->receipt_html = $view->partial('_receipt.phtml', array('invoice' => $invoice, 'di' => $this->getDi())); $tpl->invoice = $invoice; $tpl->user = $this->getDi()->userTable->load($invoice->user_id); $tpl->invoice_id = $invoice->invoice_id; $tpl->cancel_url = $this->getDi()->url('cancel',array('id'=>$invoice->getSecureId('CANCEL')),false); $tpl->invoice_title = $invoice->getLineDescription(); $view->invoice = $invoice; $view->content = $tpl->render($html) . $view->blocks('payment/offline/bottom'); $view->title = $this->getTitle(); $response->setBody($view->render("layout.phtml")); break; case 'preview' : $this->previewAction($request, $response, $invokeArgs); break; default: return parent::directAction($request, $response, $invokeArgs); } } public function createTransaction($request, $response, array $invokeArgs) { //nop } public function previewAction($request, $response, $invokeArgs) { if (!$this->getDi()->authAdmin->getUserId()) throw new Am_Exception_AccessDenied; $view = new Am_View; $form = $this->createPreviewForm(); $form->setDataSources(array($request)); do { if ($form->isSubmitted() /*&& $f->validate()*/) { $v = $form->getValue(); $invoice = $this->getDi()->invoiceRecord; $invoice->toggleFrozen(true); $u = $this->getDi()->userTable->findFirstByLogin($v['user']); if (!$u) { list($el) = $form->getElementsByName('user'); $el->setError(___('User %s not found', $v['user'])); break; } $invoice->setUser($u); if ($v['coupon']) { $invoice->setCouponCode($v['coupon']); $error = $invoice->validateCoupon(); if ($error) { list($el) = $form->getElementsByName('coupon'); $el->setError($error); break; } } foreach ($v['product_id'] as $plan_id => $qty) { $p = $this->getDi()->billingPlanTable->load($plan_id); $pr = $p->getProduct(); try { $invoice->add($pr, $qty); } catch (Am_Exception_InputError $e) { $form->setError($e->getMessage()); break; } } $invoice->calculate(); $invoice->setPaysystem($this->getId()); $invoice->invoice_id = 'ID'; $invoice->public_id = 'PUBLIC_ID'; $html = $this->getConfig('html', 'SITE OWNER DID NOT PROVIDE INSTRUCTIONS FOR OFFLINE PAYMENT YET'); $tpl = new Am_SimpleTemplate; $tpl->receipt_html = $view->partial('_receipt.phtml', array('invoice' => $invoice, 'di' => $this->getDi())); $tpl->invoice = $invoice; $tpl->user = $this->getDi()->userTable->load($invoice->user_id); $tpl->invoice_id = $invoice->invoice_id; $tpl->cancel_url = $this->getDi()->url('cancel',array('id'=>$invoice->getSecureId('CANCEL')),false); $tpl->invoice_title = $invoice->getLineDescription(); $view->invoice = $invoice; $view->content = $tpl->render($html) . $view->blocks('payment/offline/bottom'); $view->title = $this->getTitle(); $response->setBody($view->render("layout.phtml")); return; } } while (false); $view->title = $this->getTitle() . ' · ' . ___("Preview"); $view->content = (string) $form; $view->display('admin/layout.phtml'); } protected function createPreviewForm() { $form = new Am_Form_Admin; $form->addText('user') ->setLabel(___('Enter username of existing user')) ->addRule('required'); $form->addScript()->setScript(<<addElement(new Am_Form_Element_ProductsWithQty('product_id')) ->setLabel(___('Products')) ->loadOptions($this->getDi()->billingPlanTable->selectAllSorted()) ->addRule('required'); $form->addText('coupon')->setLabel(___('Coupon'))->setId('p-coupon'); $form->addScript('script')->setScript(<<addSaveButton(___('Preview')); return $form; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $result->setSuccess(); $invoice->setCancelled(true); } }PK\ t55!default/plugins/payment/korta.phpnu[addInteger("merchant", array('maxlength' => 15, 'size' => 15)) ->setLabel("Korta Merchant") ->addRule('required'); $form->addInteger("terminal", array('maxlength' => 15, 'size' => 15)) ->setLabel("Korta Terminal") ->addRule('required'); $form->addText("secretCode", array('size' => 40)) ->setLabel("Korta Secret Code") ->addRule('required'); $form->addAdvCheckbox("testMode") ->setLabel("Test Mode Enabled"); } protected function getRedirectUrl() { return ($this->getConfig('testMode')) ? self::URL_TEST : self::URL_LIVE; } public function getTestSign() { return ($this->getConfig('testMode')) ? 'TEST' : ''; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $merchant = $this->getConfig('merchant'); $terminal = $this->getConfig('terminal'); $amount = $this->invoice->first_total; $currency = $this->invoice->currency; $description = $this->invoice->getLineDescription(); $checkvaluemd5 = md5($amount.$currency.$merchant.$terminal.$description.$this->getConfig('secretCode').$this->getTestSign('testMode')); $reference = $this->invoice->public_id; $downloadmd5 = md5("2".$checkvaluemd5.$reference. $this->getConfig('secretCode').$this->getTestSign('testMode')); $vars = array( 'merchant' => $merchant, 'terminal' => $terminal, 'amount' => $amount, 'currency' => $currency, 'description' => $description, 'checkvaluemd5' => $checkvaluemd5, 'reference' => $reference, 'downloadmd5' => $downloadmd5, 'name' => $this->invoice->getUser()->getName(), 'address' => $this->invoice->getUser()->street, 'address2' => $this->invoice->getUser()->street2, 'email' => $this->invoice->getUser()->email, 'zip' => $this->invoice->getUser()->zip, 'city' => $this->invoice->getUser()->city, 'country' => $this->invoice->getUser()->country, 'phone' => $this->invoice->getUser()->phone, 'downloadurl' => $this->getPluginUrl('thanks'), 'continueurl' => $this->getCancelUrl(), 'startnewpayment' => 'true', 'terms' => 'Y', 'refermethod' => 'POST', 'refertarget' => '_top', 'look' => 'SIMPLE', ); $action = new Am_Paysystem_Action_Redirect($this->getRedirectUrl() . "?" . http_build_query($vars, '', '&')); $result->setAction($action); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { return <<www.korta.is): NOTE: The plugin not support recurring payments. 1. Login into your merchant account https://service.kortathjonustan.is then: -go to "Webpay" -find needed string, ckick "Setup" -at 'Checkout terminals' fing needed terminal, click 'View' -at 'Webpay setup' find 'merchant', 'terminal' and 'secretcode' fileds and paste data in the same fileds at this page. 2. Click 'Save' button. CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Korta($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Korta($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Korta extends Am_Paysystem_Transaction_Incoming { protected $result; public function process() { $this->result = $this->request->getPost(); // print_rr($downloadmd5); // print_rre($this->result); parent::process(); } public function validateSource() { return md5(htmlentities("2".$this->result['checkvaluemd5'].$this->result['reference'].$this->plugin->getConfig('secretCode').$this->plugin->getTestSign())) == $this->result['downloadmd5']; } public function findInvoiceId() { return (string) $this->result['reference']; } public function validateStatus() { return true; } public function getUniqId() { return (string) $this->result['reference']; } public function validateTerms() { return true; } }PK\>O"/default/plugins/payment/selz/scripts/selz.phtmlnu[setLayout('layout.phtml'); ?> way == 'button'): ?>
      Buy this on Selz
      PK\r0..%default/plugins/payment/selz/selz.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Selz extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_REVISION = '5.0.5'; protected $defaultTitle = 'Selz'; protected $defaultDescription = 'Credit Card Payment'; const SHARED_LINK_FIELD = 'shared-link-field'; const SELZ_ITEM_ID_FIELD = 'selz-item-id-field'; public function _initSetupForm(Am_Form_Setup $form) { $form->addText('verification_key', array('size' => 60)) ->setLabel('Verification key') ->addRule('required'); $form->addSelect('payment_way') ->setLabel('Payment Way') ->loadOptions(array( 'redirect' => 'Redirect to Selz site', 'button' => 'Button at aMember site', 'widget' => 'Widget at aMember site', )); } public function getConfig($key = null, $default = null) { switch($key){ case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText(self::SHARED_LINK_FIELD, "Selz Item Shared Link", "create selz-item with the same billing settings, and enter its shre link here", null, array('size' => 40))); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText(self::SELZ_ITEM_ID_FIELD, "Selz Item Id", "", null, array('size' => 40))); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $items = $invoice->getItems(); if(count($items) > 1) { $exc = new Am_Exception_InternalError("It's impossible purchase " . count($items) . " products at one invoice with Selz-plugin"); $this->getDi()->errorLogTable->logException($exc); throw $exc; } $item = $items[0]; $bp = $this->getDi()->billingPlanTable->load($item->billing_plan_id); $sharedLink = $bp->data()->get(self::SHARED_LINK_FIELD); if(!$sharedLink) { $exc = new Am_Exception_InternalError("Product #{$item->item_id} has no shared link"); $this->getDi()->errorLogTable->logException($exc); throw $exc; } if($this->getConfig('payment_way', 'redirect') == 'redirect') { $a = new Am_Paysystem_Action_Redirect($sharedLink); } else { $a = new Am_Paysystem_Action_HtmlTemplate_Selz($this->getDir(), 'selz.phtml'); $a->link = $sharedLink; $a->inv = $invoice->public_id; $a->thanks = $this->getReturnUrl(); $a->ipn = $this->getPluginUrl('ipn'); $a->way = $this->getConfig('payment_way'); } $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Selz($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme() { $ipn = $this->getPluginUrl('ipn'); return << Sttings -> Developer' add webhook: event: Order Received Callback URL: $ipn Received 'Verification key' set to 'Verification key' option. CUT; } } class Am_Paysystem_Transaction_Selz extends Am_Paysystem_Transaction_Incoming { protected $_order; protected $_autoCreateMap = array( 'name_f' => 'BuyerFirstName', 'name_l' => 'BuyerLastName', 'email' => 'BuyerEmail', 'user_external_id' => 'BuyerEmail', 'invoice_external_id' => 'OrderId', ); function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $str = $request->getRawBody(); $this->_order = json_decode($str, true); } public function fetchUserInfo() { return array( 'name_f' => $this->_order['BuyerFirstName'], 'name_l' => $this->_order['BuyerLastName'], 'email' => $this->_order['BuyerEmail'], ); } function autoCreateInvoice() { $invoiceExternalId = $this->generateInvoiceExternalId(); $invoice = Am_Di::getInstance()->invoiceTable->findFirstByData('external_id', $invoiceExternalId); $products = $this->autoCreateGetProducts(); if (!$invoice && !$products) return null; // If we are able to retrive invoice but doesn;t have products, // we should get products from invoice in order to handle situations when invoice was imported into amember; if($invoice && !$products) { $products = $invoice->getProducts(); } if (!is_array($products)) $products = array($products); $userTable = $this->getPlugin()->getDi()->userTable; $userInfo = $this->fetchUserInfo(); $externalId = $this->generateUserExternalId($userInfo); $user = null; if ($externalId) $user = $userTable->findFirstByData('external_id', $externalId); if (!$user) { $user = $userTable->findFirstByEmail($userInfo['email']); if ($user) $user->data()->set('external_id', $externalId)->update(); } if (!$user) { $user = $userTable->createRecord($userInfo); if(!$user->login) $user->generateLogin(); if(!$user->pass) $user->generatePassword(); else $user->setPass($user->pass); $user->data()->set('external_id', $externalId); $user->insert(); if ($this->getPlugin()->getDi()->config->get('registration_mail')) $user->sendRegistrationEmail(); if ($this->getPlugin()->getDi()->config->get('registration_mail_admin')) $user->sendRegistrationToAdminEmail(); } if ($invoice) { if ($invoice->user_id != $user->user_id) { $invoice = null; // strange!!! } else { $invoice->_autoCreated = true; } } if (!$invoice) { $invoice = $this->getPlugin()->getDi()->invoiceRecord; $invoice->setUser($user); $invoice->add($products[0]); $item = $invoice->getItem(0); $qty = count($products); if($item->qty != $qty) { $period = new Am_Period($item->first_period); $newPeriod = new Am_Period($period->getCount() * $qty, $period->getUnit()); $item->first_period = (string)$newPeriod; $item->qty = $qty; $item->_calculateTotal(); $invoice->first_period = (string)$newPeriod; } $invoice->calculate(); $invoice->data()->set('external_id', $invoiceExternalId); $invoice->paysys_id = $this->plugin->getId(); $invoice->first_period = (string)$newPeriod; $invoice->insert(); $invoice->_autoCreated = true; } if ($invoice && $this->log) { $this->log->updateQuick(array( 'invoice_id' => $invoice->pk(), 'user_id' => $user->user_id, )); } return $invoice; } public function autoCreateGetProducts() { $itemId = ($this->_order['ItemId']) ? $this->_order['ItemId'] : $this->_order['Items'][0]['ItemId']; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData(Am_Paysystem_Selz::SELZ_ITEM_ID_FIELD, $itemId); $product = $billing_plan->getProduct(); if(!$billing_plan || !$this->_order['BuyerEmail']) return; $res = array(); $qty = ($this->_order['Quantity']) ? $this->_order['Quantity'] : $this->_order['Items'][0]['Quantity']; for($i = 0; $i < $qty; $i++) { array_push($res, $product); } return $res; } public function findInvoiceId() { if($id = $this->getPlugin()->getDi()->db->selectCell(" SELECT i.public_id FROM ?_invoice_payment ip LEFT JOIN ?_invoice i USING (invoice_id) WHERE transaction_id = ? ", $this->_order['ReferenceId'])) { return $id; } $itemId = ($this->_order['ItemId']) ? $this->_order['ItemId'] : $this->_order['Items'][0]['ItemId']; $billing_plans = $this->getPlugin()->getDi()->billingPlanTable->findByData(Am_Paysystem_Selz::SELZ_ITEM_ID_FIELD, $itemId); $bpIds = array(); foreach($billing_plans as $bp) $bpIds[] = $bp->pk(); if(empty($bpIds) || !$this->_order['BuyerEmail']) return; $id = $this->getPlugin()->getDi()->db->selectCell(" SELECT ii.invoice_public_id FROM ?_invoice_item ii LEFT JOIN ?_invoice i ON i.invoice_id=ii.invoice_id LEFT JOIN ?_user u ON u.user_id=i.user_id WHERE ii.billing_plan_id IN (?a) AND i.status = ?d AND i.paysys_id = ? AND u.email = ? ORDER BY ii.invoice_id DESC ", $bpIds, Invoice::PENDING, 'selz', $this->_order['BuyerEmail']); if($id) { $invoice = $this->loadInvoice($id); $item = $invoice->getItem(0); $qty = ($this->_order['Quantity']) ? $this->_order['Quantity'] : $this->_order['Items'][0]['Quantity']; if($item->qty != $qty) { $period = new Am_Period($item->first_period); $newPeriod = new Am_Period($period->getCount() * $qty, $period->getUnit()); $item->first_period = (string)$newPeriod; $item->qty = $qty; $item->_calculateTotal(); $item->update(); $invoice->calculate(); $invoice->first_period = (string)$newPeriod; $invoice->update(); } } return $id; } public function getUniqId() { return $this->_order['ReferenceId']; } public function validateSource() { $mess = $this->_order['Timestamp'] . $this->_order['Token']; $aMessage = iconv(iconv_get_encoding("internal_encoding"), "ASCII", $mess); $vk = $this->getPlugin()->getConfig('verification_key'); $aKey = iconv(iconv_get_encoding("internal_encoding"), "ASCII", $vk); $sig = base64_encode(hash_hmac('sha256', $aMessage, $aKey, true)); $signature = $_SERVER["HTTP_X_SELZ_SIGNATURE"]; return ($signature == $sig); } public function validateStatus() { return true; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->_order['TotalPrice']); return true; } } PK\%##$default/plugins/payment/coinsnap.phpnu[addText('api_key', array('class' => 'el-wide')) ->setLabel("API KEY\n" . 'Get it from your Coinsnap account') ->addRule('required'); $form->addPassword('api_secret', array('class' => 'el-wide')) ->setLabel("API SECRET\n" . 'Get it from your Coinsnap account') ->addRule('required'); $form->addAdvcheckbox('testing')->setLabel('Testing mode'); } public function isConfigured() { return $this->getConfig('api_key') && $this->getConfig('api_secret'); } public function getSupportedCurrencies() { return array_keys(Am_Currency::getFullList()); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $req = new Am_Request_Coinsnap($this, "/merchantV1/TriggerSale"); $params = array( //"cryptocurrency" => "", "currency" => $invoice->currency, "amount" => $invoice->first_total, "type" => "html", "webhooks" => array( "success" => array( "merchant_params" => "$invoice->public_id", "url" => $this->getPluginUrl('ipn') ), /*"update" => array( "merchant_params" => "", "url" => "" ), "error" => array( "merchant_params" => "", "url" => "" )*/ ), "html" => array( "success" => array( "url" => $this->getReturnUrl() ), "error" => array( "url" => $this->getCancelUrl() ) ), "customer" => array( "ip" => $user->remote_addr ? $user->remote_addr : $_SERVER['REMOTE_ADDR'], "email" => $user->email ) ); $res = $req->sendPut($params); if(!@$res['success']['html']['redirect'] || @$res['error']) { throw new Am_Exception_InternalError("Coinbase API error:". @$res['error']); } $a = new Am_Paysystem_Action_Redirect($res['success']['html']['redirect']); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Coinbase($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_Coinbase extends Am_Paysystem_Transaction_Incoming { protected $vars; function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $str = $request->getRawBody(); $ret = @json_decode($str, true); if(!$ret) throw new Am_Exception_InternalError("Coinsnap: Can't decode postback: ".$ret); $this->vars = $ret; } public function getUniqId() { return $this->vars['id']; } public function validateSource() { return true; } public function validateStatus() { return ($this->vars['status'] == "confirmed" ? true : false); } public function validateTerms() { return true; } public function findInvoiceId() { return $this->vars['merchant_params']; } } class Am_Request_Coinsnap extends Am_HttpRequest { protected $plugin; protected $log; protected $nonce; protected $route; public function __construct(Am_Paysystem_Coinsnap $plugin, $route, InvoiceLog $log = null) { $this->log = $log; $this->plugin = $plugin; $this->nonce = mt_rand(); $this->route = $route; parent::__construct(($plugin->getConfig('testing') ? Am_Paysystem_Coinsnap::SANDBOX_URL : Am_Paysystem_Coinsnap::LIVE_URL) . $route); } public function sendPost($params) { return $this->sendRequest($params, Am_HttpRequest::METHOD_POST); } public function sendGet() { return $this->sendRequest(array(), Am_HttpRequest::METHOD_GET); } public function sendPut($params) { return $this->sendRequest($params, Am_HttpRequest::METHOD_PUT); } public function sendRequest($params, $method) { $sign = hash_hmac('sha512', $this->route . hash ( 'sha256', $this->nonce . json_encode($params), false ), $this->plugin->getConfig('api_secret'), false ); $this->setHeader ("X-Key", $this->plugin->getConfig('api_key') ); $this->setHeader ("nonce", $this->nonce ); $this->setHeader ("X-Sign", $sign ); $this->setHeader('Content-type', 'application/json'); if ($method == Am_HttpRequest::METHOD_POST || $method == Am_HttpRequest::METHOD_PUT) { $this->setBody(json_encode($params)); } $this->setMethod($method); if(!$this->log) $this->log = $this->plugin->logRequest($this); $ret = $this->send(); $this->log->add($ret); if ($ret->getStatus() != '200') { throw new Am_Exception_InternalError("CoinsnapPay API Error. Status : {$ret->getStatus()}."); } return json_decode($ret->getBody(), true); } }PK\u u &default/plugins/payment/multicards.phpnu[addText('mer_id')->setLabel("MultiCards Merhcant ID"); $form->addText('page_id')->setLabel('MultiCards Page ID'); $form->addText('password')->setLabel('MultiCards Silent Post Password'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $a->deferred_entry = 1; $a->mer_id = $this->getConfig('mer_id'); $a->num_items = 1; $a->mer_url_idx = $this->getConfig('page_id'); $a->item1_desc = $invoice->getLineDescription(); $a->item1_price = $invoice->first_total; $a->item1_qty = 1; $a->user1 = $invoice->public_id; $a->user2 = $invoice->user_id; $a->cust_name = $invoice->getName(); $a->cust_email = $invoice->getEmail(); $a->card_name = $invoice->getName(); $a->cust_address1 = $invoice->getStreet(); $a->cust_city = $invoice->getCity(); $a->cust_country = $invoice->getCountry(); $a->cust_state = $invoice->getState(); $a->cust_zip = $invoice->getZip(); $result->setAction($a); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { try{ parent::directAction($request, $response, $invokeArgs); }catch(Exception $e){ $this->getDi()->errorLogTable->logException($e); } echo ""; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Multicards($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme() { return << Page you specifided in config Set: - Post URL to: %root_url%/payment/multicards/ipn - Silent Post : yes - Post Fields : item1_price,item1_qty,user1,order_num - Silent Post Password: Enter same password that you have entered in Multicards plugin configuration - AllowedReferer: %root_url%/signup It's all CUT; } } class Am_paysystem_Transaction_Multicards extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return $this->request->get('order_num'); } public function findInvoiceId() { return $this->request->get('user1'); } public function validateSource() { return $this->getPlugin()->getConfig('password') == $this->request->get('SilentPostPassword'); } public function validateStatus() { return true; } public function validateTerms() { return ($this->request->get('item1_price') * $this->request->get('item1_qty')) == $this->invoice->first_total; } }PK\MN+default/plugins/payment/netbilling-form.phpnu[addText('account_id') ->setLabel('NetBilling Account ID') ->addRule('required'); $form->addText('site_tag') ->setLabel("NetBilling Site Tag\n" . "create it at your netbilling account -> Setup -> Site Tools -> Site tags") ->addRule('required'); $form->addText('crypto_hash') ->setLabel("MD5 crypto-hash\n" . "create it at your netbilling account -> Fraud Controls -> Fraud Defense -> Step 12") ->addRule('required'); $form->addAdvCheckbox("debugLog") ->setLabel("Debug Log Enabled\n" . "write all requests/responses to log"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Form(self::URL); $user = $invoice->getUser(); $post = array( 'Ecom_BillTo_Postal_Name_First' => $user->name_f, 'Ecom_BillTo_Postal_Name_Last' => $user->name_l, 'Ecom_BillTo_Postal_Street_Line1' => $user->street, 'Ecom_BillTo_Postal_Street_Line2' => $user->street2, 'Ecom_BillTo_Postal_City' => $user->city, 'Ecom_BillTo_Postal_StateProv' => $user->state, 'Ecom_BillTo_Postal_PostalCode' => $user->zip, 'Ecom_BillTo_Postal_CountryCode' => $user->country, 'Ecom_BillTo_Online_Email' => $user->email, 'Ecom_ShipTo_Postal_Name_First' => $user->name_f, 'Ecom_ShipTo_Postal_Name_Last' => $user->name_l, 'Ecom_ShipTo_Postal_City' => $user->city, 'Ecom_ShipTo_Postal_Street_Line1' => $user->street, 'Ecom_ShipTo_Postal_Street_Line2' => $user->street2, 'Ecom_ShipTo_Postal_StateProv' => $user->state, 'Ecom_ShipTo_Postal_PostalCode' => $user->zip, 'Ecom_ShipTo_Postal_CountryCode' => $user->country, 'Ecom_ShipTo_Online_Email' => $user->email, 'Ecom_Ezic_AccountAndSitetag' => $this->getConfig('account_id') . ":" . $this->getConfig('site_tag'), 'Ecom_Cost_Total' => sprintf("%.2f",$invoice->first_total), 'Ecom_Receipt_Description' => $invoice->getLineDescription(), 'Ecom_Ezic_Security_HashFields' => self::Hash_Fields, 'Ecom_Ezic_Payment_AuthorizationType' => 'SALE', 'Ecom_ConsumerOrderID' => $invoice->public_id, ); $hash = $this->getConfig('crypto_hash'); foreach (explode(' ', self::Hash_Fields) as $field) $hash .= $post[$field]; $post['Ecom_Ezic_ProofOfPurchase_MD5'] = strtoupper(md5($hash)); if ($this->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('NetBilling Form [request-data]:' . json_encode($post)); foreach ($post as $key => $value) $a->$key = $value; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'thanks') { if ($this->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('NetBilling Form [response-thanks]:' . json_encode($request->getParams())); $this->invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->getFiltered('Ecom_ConsumerOrderID')); $url = ($request->get('Ecom_Ezic_Response_StatusCode') == 0 || $request->get('Ecom_Ezic_Response_StatusCode') == 'F') ? $this->getCancelUrl() : $this->getReturnUrl(); $response->setRedirect($url); }else parent::directAction($request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_NetbillingForm($this, $request, $response, $invokeArgs); } public function getReadme() { $thanks = $this->getPluginUrl('thanks'); $ipn = $this->getPluginUrl('ipn'); return << Configuration -> Setup/Configuration -> Plugins -> Payment Plugins' and enable "netbilling-form" plugin. 2. Configure plugin: go to 'aMember CP -> Configuration -> Setup/Configuration -> Netbilling Form' and configure it. 3. Configure your NetBilling Account: - go to your NetBilling Account -> Setup -> Site Tools -> Site tags - find your just created tag and click 'conf' link - enter at 'Return URL': $thanks - enter at 'Postback CGI URL': $ipn CUT; } } class Am_Paysystem_Transaction_NetbillingForm extends Am_Paysystem_Transaction_Incoming { public function process() { if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('NetBilling Form [response-ipn]:' . json_encode($this->request->getParams())); parent::process(); } public function validateSource() { $hashFields = explode(' ', Am_Paysystem_NetbillingForm::Hash_Fields); $hash = $this->plugin->getConfig('crypto_hash') . $this->request->getFiltered('Ecom_Ezic_Response_TransactionID') . $this->request->getFiltered('Ecom_Ezic_Response_StatusCode'); foreach ($hashFields as $v) $hash .= $this->request->get($v); return (strtoupper(md5($hash)) == $this->request->getFiltered('Ecom_Ezic_ProofOfPurchase_MD5')); } public function findInvoiceId() { return $this->request->getFiltered('Ecom_ConsumerOrderID'); } public function validateStatus() { switch ($this->request->getFiltered('Ecom_Ezic_TransactionStatus')) { case 0: case 'F': return false; } return true; } public function getUniqId() { return $this->request->getFiltered('Ecom_Ezic_Response_TransactionID'); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->get('Ecom_Cost_Total')); return true; } }PK\@ E6E6*default/plugins/payment/paypal-express.phpnu[domain = $this->getConfig('testing') ? 'www.sandbox.paypal.com' : 'www.paypal.com'; } public function _initSetupForm(Am_Form_Setup $form) { Am_Paysystem_PaypalApiRequest::initSetupForm($form); $form->addAdvCheckbox("dont_verify") ->setLabel( "Disable IPN verification\n" . "Usually you DO NOT NEED to enable this option. However, on some webhostings PHP scripts are not allowed to contact external web sites. It breaks functionality of the PayPal payment integration plugin, and aMember Pro then is unable to contact PayPal to verify that incoming IPN post is genuine. In this case, AS TEMPORARY SOLUTION, you can enable this option to don't contact PayPal server for verification. However, in this case \"hackers\" can signup on your site without actual payment. So if you have enabled this option, contact your webhost and ask them to open outgoing connections to www.paypal.com port 80 ASAP, then disable this option to make your site secure again."); $form->addText('localecode')->setLabel("Locale Code\n" . 'By default: US'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $log = $this->getDi()->invoiceLogRecord; $log->title = "SetExpressCheckout"; $log->paysys_id = $this->getId(); $log->setInvoice($invoice); $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->setExpressCheckout($invoice); //@see misc/paypal-identity Implements Seamless Checkout if ($token = $this->getDi()->store->get('paypal-access-token-' . $invoice->user_id)) { $apireq->addPostParameter('IDENTITYACCESSTOKEN', $token); } $apireq->addPostParameter('LOCALECODE', $this->getConfig('localecode', 'US')); if ($this->getConfig('brandname')) $apireq->addPostParameter('BRANDNAME', $this->getConfig('brandname')); if ($this->getConfig('landingpage_login')) $apireq->addPostParameter('LANDINGPAGE', 'Login'); $log->add($apireq); $response = $apireq->send(); $log->add($response); if ($response->getStatus() != 200) throw new Am_Exception_Paysystem("Error while communicating to PayPal server, please try another payment processor"); parse_str($response->getBody(), $vars); if (get_magic_quotes_gpc()) $vars = Am_Mvc_Request::ss($vars); if (empty($vars['TOKEN'])) throw new Am_Exception_Paysystem("Error while communicating to PayPal server, no token received, please try another payment processor"); $invoice->data()->set(self::PAYPAL_EXPRESS_TOKEN, $vars['TOKEN']); $action = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL); $action->cmd = '_express-checkout'; $action->token = $vars['TOKEN']; $action->useraction = 'commit'; $log->add($action); $result->setAction($action); $this->getDi()->session->paypal_invoice_id = $invoice->getSecureId('paypal'); // if express-checkout chosen, hide and don't require // fields for login, password, email, name and address // if that is new user, // save user info and invoice into temporary storage not to user table // call setExpressCheckout // redirect to paypal // then get back from paypal to am/payment/paypal-express/review // on confirm key pressed, make payment, finish checkout, fill-in fields } public function expressCheckoutAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); $token = $request->getFiltered('token'); if (!$token) throw new Am_Exception_InputError("No required [token] provided, internal error"); $log = $this->getDi()->invoiceLogRecord; $log->title = ""; $log->paysys_id = $this->getId(); $log->title .= " getExpressCheckoutDetails"; $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->getExpressCheckoutDetails($token); $vars = $apireq->sendRequest($log); $invoiceId = filterId(get_first( @$vars['INVNUM'], @$vars['L_PAYMENTREQUEST_0_INVNUM'], // too smart! paypal developers decided to do not pass INVNUM/CUSTOM for transactions with free trial $this->getDi()->session->paypal_invoice_id) ); if (!$invoiceId || !($invoice = $this->getDi()->invoiceTable->findBySecureId($invoiceId, 'paypal'))) throw new Am_Exception_InputError("Could not find invoice related to given payment. Internal error. Your account was not billed, please try again"); $invoiceLog->setInvoice($invoice); $log->setInvoice($invoice); $log->update(); $this->_setInvoice($invoice); /* @var $invoice Invoice */ if ($invoice->isPaid()) { return $response->redirectLocation($this->getReturnUrl()); } $invoice->data()->set(self::PAYPAL_EXPRESS_TOKEN, $token)->update(); if ($invoice->first_total > 0) { // bill initial amount @todo free trial $log->title .= " doExpressCheckout"; $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->doExpressCheckout($invoice, $token, $request->getFiltered('PayerID')); $vars = $apireq->sendRequest($log); //https://developer.paypal.com/docs/classic/express-checkout/ht_ec_fundingfailure10486/ if ($vars['ACK'] == 'Failure' && $vars['L_ERRORCODE0'] == '10486') { $url = $this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL; $url .= '?' . http_build_query(array( 'cmd' => '_express-checkout', 'token' => $invoice->data()->get(self::PAYPAL_EXPRESS_TOKEN), 'useraction' => 'commit' )); return $response->redirectLocation($url); } $transaction = new Am_Paysystem_Transaction_PayPalExpress_DoExpressCheckout($this, $vars); $transaction->setInvoice($invoice); $transaction->process(); } if ($invoice->rebill_times) { $log->title .= " createRecurringPaymentProfile"; $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->createRecurringPaymentProfile($invoice, null, $token, $request->getFiltered('PayerID')); $vars = $apireq->sendRequest($log); if (!in_array($vars['ACK'], array('Success', 'SuccessWithWarning'))) { $this->logError("Not Success response to CreateRecurringPaymentProfile request", $vars); } else { $invoice->data()->set(self::PAYPAL_PROFILE_ID, $vars['PROFILEID'])->update(); if ($invoice->first_total <= 0) { $transaction = new Am_Paysystem_Transaction_PayPalExpress_CreateRecurringPaymentProfile($this, $vars); $transaction->setInvoice($invoice); $transaction->process(); } } } return $response->redirectLocation($this->getReturnUrl()); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == self::PAYPAL_EXPRESS_CHECKOUT) return $this->expressCheckoutAction($request, $response, $invokeArgs); else return parent::directAction($request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paypal($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } // public function hideBricks() // { // return array('email', 'name', 'address'); // } function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = "cancelRecurringPaymentProfile"; $log->paysys_id = $this->getId(); $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->cancelRecurringPaymentProfile($invoice, $invoice->data()->get(self::PAYPAL_PROFILE_ID)); $vars = $apireq->sendRequest($log); $log->setInvoice($invoice); $log->update(); //11556 - Invalid profile status for cancel action; profile should be active or suspended if($vars['ACK'] != 'Success' && $vars['L_ERRORCODE0'] != '11556') throw new Am_Exception_InputError('Transaction was not cancelled. Got error from paypal: '.$vars['L_SHORTMESSAGE0']); $invoice->setCancelled(true); $result->setSuccess(); } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = "refundTransaction"; $log->paysys_id = $this->getId(); $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->refundTransaction($payment, $amount); $res = $apireq->sendRequest($log); $log->setInvoice($payment->getInvoice()); $log->update(); if($res['ACK'] != 'Success') { $result->setFailed('Transaction was not refunded. Got error from paypal: '.$res['L_SHORTMESSAGE0']); return; } $result->setSuccess(); // We will not add refund record here because it will be handeld by IPN script. } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<$url CUT; } } class Am_Paysystem_Transaction_PayPalExpress_DoExpressCheckout extends Am_Paysystem_Transaction_Abstract { protected $vars; public function __construct(Am_Paysystem_Abstract $plugin, array $vars) { $this->vars = $vars; parent::__construct($plugin); } public function getUniqId() { return $this->vars['PAYMENTINFO_0_TRANSACTIONID']; } public function validate() { if (!in_array($this->vars['ACK'], array('Success', 'SuccessWithWarning'))) { throw new Am_Exception_Paysystem_TransactionInvalid("Error: " . $this->vars['L_SHORTMESSAGE0']); } if (!empty($this->vars['PAYMENTREQUEST_0_SHORTMESSAGE'])) throw new Am_Exception_Paysystem_TransactionInvalid("Payment failed: " . $this->vars['PAYMENTREQUEST_0_SHORTMESSAGE']); if (!in_array($this->vars['PAYMENTINFO_0_PAYMENTSTATUS'], array('Completed', 'Processed'))) { throw new Am_Exception_Paysystem_TransactionInvalid("Transaction status is not ok: [" . $this->vars['PAYMENTINFO_0_PAYMENTSTATUS'] . "]"); } return true; } public function getAmount() { return $this->vars['PAYMENTINFO_0_AMT']; } public function findTime() { $d = new DateTime($this->vars['PAYMENTINFO_0_ORDERTIME']); $d->setTimezone(new DateTimeZone(date_default_timezone_get())); return $d; } } class Am_Paysystem_Transaction_PayPalExpress_CreateRecurringPaymentProfile extends Am_Paysystem_Transaction_Abstract { protected $vars; public function __construct(Am_Paysystem_Abstract $plugin, array $vars) { $this->vars = $vars; parent::__construct($plugin); } public function getUniqId() { return $this->vars['PROFILEID'] . '-' . $this->vars['CORRELATIONID']; } public function validate() { if ($this->vars['ACK'] != 'Success') { throw new Am_Exception_Paysystem_TransactionInvalid("Error: " . $this->vars['L_SHORTMESSAGE0']); } } public function getAmount() { return 0; } public function findTime() { $d = new DateTime($this->vars['TIMESTAMP']); $d->setTimezone(new DateTimeZone(date_default_timezone_get())); return $d; } public function processValidated() { $this->invoice->addAccessPeriod($this); } }PK\ addInteger('merchant_id', array('size'=>20)) ->setLabel('SWREG Account#'); $form->addText('product_id', array('size'=>20)) ->setLabel('SWREG Product#'); $form->addText('ip', array('size'=>10)) ->setLabel('SWREG Postback IP, default value is 64.37.103.135'); $form->addPassword('pass', array('size'=>10)) ->setLabel('SWREG API Password'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $id = $this->invoice->getSecureId("THANKS"); $a->t = $invoice->getLineDescription() . " ($id)"; $a->vp = $invoice->first_total; $a->s = $this->getConfig('merchant_id'); $a->p = $this->getConfig('product_id'); $a->v = 0; // variation id $a->d = 0; // delivery id $a->clr = 1; // clear anything customer has in basket $a->q = 1; // qty //$a->bb = 1; // bypass basket $a->fn = $invoice->getFirstName(); $a->sn = $invoice->getLastName(); $a->em = $invoice->getEmail(); //$a->lnk = $this->getCancelUrl(); $result->setAction($a); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $refund = $this->getPluginUrl('refund'); return << Setup -> SWREG CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Swreg_Order($this, $request, $response, $invokeArgs); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'refund') { echo "OK"; ob_flush(); return $this->refundAction($request, $response, $invokeArgs); } else { echo ""; ob_flush(); parent::directAction($request, $response, $invokeArgs); } } public function refundAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $log = $this->logRequest($request); $transaction = new Am_Paysystem_Transaction_Swreg_Refund($this, $request, $response, $invokeArgs); $transaction->setInvoiceLog($log); try { $transaction->process(); } catch (Exception $e) { throw $e; $this->getDi()->errorLogTable->logException($e); throw Am_Exception_InputError(___("Error happened during transaction handling. Please contact website administrator")); } $log->setInvoice($transaction->getInvoice())->update(); } } abstract class Am_Paysystem_Transaction_Swreg extends Am_Paysystem_Transaction_Incoming { public function validateSource() { $this->_checkIp($this->plugin->getConfig('ip')); if ($this->plugin->getConfig('product_id') != $this->request->get('pc')) throw new Am_Exception_Paysystem_TransactionInvalid("Wrong [pc] passed, this transaction is not related to aMember?"); return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_Swreg_Order extends Am_Paysystem_Transaction_Swreg { public function findInvoiceId() { if (preg_match('/\(([0-9A-Za-z]+)(-[0-9A-Za-z]+)*\)/', $this->request->get('user_text'), $regs)) return $regs[1]; } public function getUniqId() { return $this->request->get('o_no'); } public function processValidated() { $this->invoice->addPayment($this); } public function validateTerms() { return $this->request->get('pp') == $this->invoice->first_total; } } class Am_Paysystem_Transaction_Swreg_Refund extends Am_Paysystem_Transaction_Swreg { public function findInvoiceId() { $invoice = Am_Di::getInstance()->invoiceTable->findByReceiptIdAndPlugin($this->getReceiptId(), $this->plugin->getId()); if ($invoice) return $invoice->public_id; } public function getUniqId() { return $this->request->get('order_no'); } public function processValidated() { $this->invoice->addRefund($this, $this->getReceiptId()); echo ""; } public function validateSource() { return true; } } PK\2hq/default/plugins/payment/netdebits/netdebits.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Netdebits extends Am_Paysystem_Abstract { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_DATE = '$Date$'; const PLUGIN_REVISION = '5.0.6'; const LIVE_URL = 'https://www.netdebit-payment.de/pay/'; const TEST_URL = 'https://web.netdebit-test.de/pay/'; const RATES = 'rts'; const KNR = 'knr'; protected $defaultTitle = 'NetDebit'; protected $defaultDescription = 'accepts all major credit cards'; function init() { parent::init(); $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldSelect(self::RATES, 'CON\'s rates', '', '', array('options' => array( '1' => 'First CON Rate', '2' => 'Second CON Rate', '3' => 'Third CON Rate', '4' => 'Fourth CON Rate', '5' => 'Fifth CON Rate', '6' => 'Sixth CON Rate')))); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('SID', array('size' => 20, 'maxlength' => 19)) ->setLabel('Webmaster-ID') ->addRule('required'); $form->addText('PID', array('size' => 20, 'maxlength' => 19)) ->setLabel("PID\n" . 'Everyone who operates own websites gets a PID') ->addRule('required'); $form->addText('CON', array('size' => 20, 'maxlength' => 19)) ->setLabel("CON\n" . 'Each content a.k.a. website is identified by a content id, named CON') ->addRule('required'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function getRecurringType() { return self::REPORTS_NOTHING; } public function getSupportedCurrencies() { return array('EUR', 'USD', 'GBP'); } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_HtmlTemplate_NetDebits($this->getDir(), 'payment-netdebit-redirect.phtml'); $a->SID = $this->getConfig('SID'); $a->PID = $this->getConfig('PID'); $a->CON = $this->getConfig('CON'); $a->VAR1 = $invoice->public_id; $a->ZAH = 2; $item = $invoice->getItem(0); $product_id = $item->item_id; $product = array_shift($this->getDi()->productTable->findByProductId($product_id)); $a->POS = $product->data()->get(self::RATES); $a->KUN = $invoice->getUser()->data()->get(self::KNR) ? 1 : 0; $a->KNR = $invoice->getUser()->data()->get(self::KNR) ? $invoice->getUser()->data()->get(self::KNR) : ''; if($this->getConfig('testing')) $a->F = 9090; else $a->F = 1000; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Netdebits($this, $request, $response, $invokeArgs); } function getReadme() { return <<NetDebit Payment Plugin Configuration You must fill next fields, while Payment setup on your's accout web page: * Pagetitle (Domain e.g. example.com): * URL Mainpage/Startpage (e.g. http://www.example.com): * URL Member-Area (e.g. http://www.example.com/members): * URL Release/Gateway Script (e.g. http://www.example.com/my_custom_gateway_script.php): Example: Pagetile - example.com: URL Mainpage/Startpag - http://www.example.com: URL Member-Area - http://www.example.com/members: URL Release/Gateway Script - http://www.example.com/amember/payment/netdebits/ipn: On step 2 of Payment Setup, please choose next parameters (BookingNumber, Status, CustomerID, VAR1, TermType, TermValue, Amount). CUT; } } class Am_Paysystem_Transaction_Netdebits extends Am_Paysystem_Transaction_Incoming { const NEW_PAYMENT = '0'; const END_OF_MEMBERSHIP = '7'; const DISABLING_THE_ACCOUNT = '9'; const RE_ENABLING_THE_ACCOUNT = '1'; public function findInvoiceId() { return $this->request->getParam('VAR1'); } public function getUniqId() { return $this->request->getParam('BookingNumber'); } public function validateSource() { $GATES = array("213.69.111.70", "213.69.111.71", "213.69.234.76", "213.69.234.74", "195.126.100.14", "213.69.111.78"); $ip = $this->request->getClientIp(false); if(!in_array($ip, $GATES)) return false; $debug = $this->request->getParam('Debug'); if($this->getPlugin()->getConfig('PID') != preg_replace('/^PID/', '', $debug)) return false; return true; } public function validateStatus() { $allowed_status = array('0', '1', '7', '9'); $status = $this->request->getParam('Status'); if(!in_array($status, $allowed_status)) return false; return true; } function processValidated() { echo "Ok = 100"; switch($this->request->getParam('Status')) { case self::NEW_PAYMENT : $this->invoice->addPayment($this); break; case self::END_OF_MEMBERSHIP : $this->invoice->stopAccess($this); $this->invoice->setCancelled($true); break; case self::RE_ENABLING_THE_ACCOUNT : $this->invoice->addPayment($this); break; case self::DISABLING_THE_ACCOUNT : $this->invoice->addRefund($this, $this->getReceiptId(), $this->request->getParam('Amount')); break; } } public function validateTerms() { $custom_id = $this->request->getParam('CustomerID'); if(!is_null($custom_id) && $this->request->getParam('Status') == '0') $this->invoice->getUser()->data()->set(Am_Paysystem_Netdebits::KNR, $this->request->getParam('CustomerID'))->update(); return true; } public function getAmount() { return $this->request->get('Amount'); } }PK\IBBIdefault/plugins/payment/netdebits/scripts/payment-netdebit-redirect.phtmlnu[setLayout('layout.phtml'); ?>

      Zahlung über NetDebit per Lastschrift oder Kreditkarte

      PK\@B&&$default/plugins/storage/selectel.phpnu[getConfig('secret_key') && $this->getConfig('access_key'); } function _initSetupForm(Am_Form_Setup $form) { $form->setTitle('Selectel'); $form->addText('access_key', array('class' => 'el-wide'))->setLabel('Your account login') ->addRule('required'); $form->addPassword('secret_key', array('class' => 'el-wide')) ->setLabel("Password for Cloud Storage\n" . '(separate password then for Control Panel)') ->addRule('required'); $form->addText('expire', array('size' => 5))->setLabel('Video link life-time, min'); $form->setDefault('expire', 15); if ($this->isConfigured()) { try { $containers = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'getContainersList'), array(), array(), $this->cacheLifetime); $containers = array('' => '== Please select public Container ==') + $containers; } catch (Exception $e) { $containers = array('' => 'Please create public container'); } $form->addSelect('links_container', '', array('options' => array_combine($containers, $containers))) ->setLabel("Container for links\n" . 'aMember will create links in the following format: http://yourcloudstorageurl.com/CONTAINERNAME/uniquekey/filename.mp4') ->addRule('required'); } $msg = <<addProlog(<<$msg CUT ); } public function getDescription() { if ($this->isConfigured()) return ___("Files located on Selectel storage. "); else return ___("Selectel storage is not configured"); } /** @return S3 */ protected function getConnector() { if (!$this->_connector) { $this->_connector = new SelectelAPI($this->getConfig('access_key'), $this->getConfig('secret_key')); } return $this->_connector; } /** @access private testing */ public function _setConnector($connector) { $this->_connector = $connector; } public function getItems($path, array & $actions) { $items = array(); if ($path == '') { $buckets = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'getContainersList'), array(), array(), $this->cacheLifetime); foreach ($buckets as $name) $items[] = new Am_Storage_Folder($this, $name, $name); $actions[] = new Am_Storage_Action_Refresh($this, ''); } else { $items[] = new Am_Storage_Folder($this, '..', ''); @list($bucket, $bpath) = explode('/', $path, 2); $ret = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'getContainerFiles'), array($bucket), array(), $this->cacheLifetime); $this->_bucket = $bucket; foreach ($ret as $r) { $items[] = $item = new Am_Storage_File($this, $r['name'], $r['size'], $bucket . '/' . $r['name'], null, null); $item->_hash = $r['hash']; } $actions[] = new Am_Storage_Action_Refresh($this, $path); } return $items; } public function isLocal() { return false; } public function get($path) { list($bucket, $uri) = explode('/', $path, 2); $ret = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'getContainerFiles'), array($bucket), array(), $this->cacheLifetime); $info = @$ret[$uri]; $p = preg_split('|[\\\/]|', $path); // get name $name = array_pop($p); return new Am_Storage_File($this, $name, $info['size'], $path, $info['type'], null); } public function getUrl(Am_Storage_File $file, $expTime) { list($bucket, $uri) = explode('/', $file->getPath(), 2); return $this->getConnector()->getAuthenticatedURL($bucket, $uri, $expTime, $this->getConfig('links_container')); } public function action(array $query, $path, $url, Am_Mvc_Request $request, Am_Mvc_Response $response) { switch ($query['action']) { case 'refresh': $this->getDi()->cacheFunction->clean(); $response->setRedirect($url); break; default: throw new Am_Exception_InputError('unknown action!'); } } } class SelectelAPI { protected $username; protected $password; const AUTH_URL = 'https://auth.selcdn.ru/'; const STORAGE_URL_KEY = 'selectel_storage_url'; const STORAGE_AUTH_TOKEN_KEY = 'selectel_auth_token_key'; function __construct($username, $password) { $this->username = $username; $this->password = $password; } function auth() { $req = new Am_HttpRequest(self::AUTH_URL, Am_HttpRequest::METHOD_GET); $req->setHeader('X-Auth-User', $this->username); $req->setHeader('X-Auth-Key', $this->password); $response = $req->send(); if ($response->getStatus() != 204) throw new Am_Exception_InternalError(sprintf("Selectel: Can't authenticate. Got %s response code.", $response->getStatus())); if (!$response->getHeader('X-Storage-Url')) throw new Am_Exception_InternalError('Selectel: No storage url in response'); $this->setStoredValue( self::STORAGE_URL_KEY, $response->getHeader('X-Storage-Url'), $response->getHeader('X-Expire-Auth-Token') ); if (!$response->getHeader('X-Auth-Token')) throw new Am_Exception_InternalError('Selectel: No auth token in response'); $this->setStoredValue( self::STORAGE_AUTH_TOKEN_KEY, $response->getHeader('X-Auth-Token'), $response->getHeader('X-Expire-Auth-Token') ); } function getContainersList() { $e = $this->__getXML($this->getStorageUrl() . '?format=xml'); $return = array(); foreach ($e->container as $c) { $return[] = (string) $c->name; } return $return; } function getContainerFiles($container) { $e = $this->__getXML($this->getStorageUrl() . '/' . $container . '?format=xml'); $return = array(); foreach ($e->object as $c) { $return[(string) $c->name] = array( 'name' => (string) $c->name, 'size' => (string) $c->bytes, 'hash' => (string) $c->hash, 'type' => (string) $c->content_type ); } return $return; } function getStorageUrl() { if (!$this->getStoredValue(self::STORAGE_URL_KEY)) $this->auth(); return $this->getStoredValue(self::STORAGE_URL_KEY); } function getAuthToken() { if (!$this->getStoredValue(self::STORAGE_AUTH_TOKEN_KEY)) $this->auth(); return $this->getStoredValue(self::STORAGE_AUTH_TOKEN_KEY); } function getAuthenticatedURL($container, $name, $expTime, $linksContainer) { $expires = time() + $expTime; $link_name = $this->getStorageUrl() . $linksContainer. '/' . md5(rand(0, 100) . $container . $name . time()) . '/' . $name; $response = $this->__request($link_name, Am_HttpRequest::METHOD_PUT, array( 'Content-Type' => 'x-storage/onetime-symlink', "X-Object-Meta-Location" => "/" . $container . "/" . $name, "X-Object-Meta-Delete-At" => $expires, "Content-length" => 0 )); return $link_name; } /** * * @param type $uri * @param type $method * @param type $headers * @return HTTP_Request2_Response */ protected function __request($uri, $method = Am_HttpRequest::METHOD_GET, $headers = array()) { $req = new Am_HttpRequest($uri, $method); $req->setHeader('X-Auth-Token', $this->getAuthToken()); if (!empty($headers)) foreach ($headers as $k => $v) $req->setHeader($k, $v); $response = $req->send(); return $response; } protected function __getXML($uri, $method = Am_HttpRequest::METHOD_GET, $headers = array()) { $response = $this->__request($uri, $method, $headers); if (!in_array($response->getStatus(), array(200, 204, 201))) throw new Am_Exception_InternalError( 'Selectel: Incorrect response received. Request to: ' . $uri . ' Response code: ' . $response->getStatus() ); $e = new SimpleXMLElement($response->getBody()); return $e; } /** * * @return Am_Di $di */ protected function getDi() { return Am_Di::getInstance(); } protected function getStoredValue($key) { return $this->getDi()->store->get($key); } protected function setStoredValue($key, $value, $timeout = 86400) { $this->getDi()->store->set($key, $value, "+" . $timeout . " seconds"); } }PK\i"i"default/plugins/storage/s3.phpnu[ 's3.amazonaws.com', 'us-east-2' => 's3-us-east-2.amazonaws.com', 'us-west-2' => 's3-us-west-2.amazonaws.com', 'us-west-1' => 's3-us-west-1.amazonaws.com', 'eu-west-1' => 's3-eu-west-1.amazonaws.com', 'eu-central-1' => 's3.eu-central-1.amazonaws.com', 'ap-southeast-1' => 's3-ap-southeast-1.amazonaws.com', 'ap-southeast-2' => 's3-ap-southeast-2.amazonaws.com', 'ap-northeast-1' => 's3-ap-northeast-1.amazonaws.com', 'sa-east-1' => 's3-sa-east-1.amazonaws.com' ); protected $_regions = array( 'us-east-1' => 'US Standard', 'us-east-2' => 'US East (Ohio)', 'us-west-2' => 'US West (Oregon)', 'us-west-1' => 'US West (N. California)', 'eu-west-1' => 'EU (Ireland)', 'eu-central-1' => 'EU (Frankfurt)', 'ap-southeast-1' => 'Asia Pacific (Singapore)', 'ap-southeast-2' => 'Asia Pacific (Sydney)', 'ap-northeast-1' => 'Asia Pacific (Tokyo)', 'sa-east-1' => 'South America (Sao Paulo)' ); public function isConfigured() { return $this->getConfig('secret_key') && $this->getConfig('access_key'); } function _initSetupForm(Am_Form_Setup $form) { $form->setTitle('Amazon S3'); $form->addText('access_key', array('size' => 40))->setLabel('AWS Access Key') ->addRule('required') ->addRule('regex', 'must be alphanumeric', '/^[A-Z0-9]+$/'); $form->addPassword('secret_key', array('size' => 40))->setLabel('AWS Secret Key') ->addRule('required'); $form->addSelect('region')->loadOptions($this->_regions)->setLabel('Amazon S3 Region'); $form->addText('expire', array('size' => 5))->setLabel('Video link lifetime, min'); $form->setDefault('expire', 15); $form->addAdvCheckbox('use_ssl') ->setLabel(___("Use SSL for Authenticated URLs\n" . "enable this option if you use https for your site")); $msg = ___('Your content on Amazon S3 should not be public. Please restrict public access to your files on Amazon S3 side and ensure you can not access it directly from Amazon S3. aMember use Access Key and Secret Key to generate links with authentication token for users to provide access them to your content on Amazon S3.'); $form->addProlog(<<$msg CUT ); } public function getRegion() { return $this->getConfig('region', 'us-east-1'); } public function getEndpoint() { return $this->_endpoints[$this->getRegion()]; } public function getDescription() { if ($this->isConfigured()) { return ___("Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)"); } else { return ___("Amazon S3 storage is not configured"); } } /** @return S3 */ protected function getConnector() { if (!$this->_connector) { $this->_connector = new S3($this->getConfig('access_key'), $this->getConfig('secret_key'), false, $this->getEndpoint(), $this->getRegion()); switch($this->getRegion()){ case 'eu-central-1' : case 'us-east-2' : $this->_connector->setRequestClass('S3Request_HttpRequest4'); break; default : $this->_connector->setRequestClass('S3Request_HttpRequest2'); } } return $this->_connector; } /** @access private testing */ public function _setConnector($connector) { $this->_connector = $connector; } public function getItems($path, array & $actions) { $items = array(); if ($path == '') { $buckets = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'listBuckets'), array(), array(), $this->cacheLifetime); foreach ($buckets as $name) $items[] = new Am_Storage_Folder($this, $name, $name); $actions[] = new Am_Storage_Action_Refresh($this, ''); } else { @list($bucket, $bpath) = explode('/', $path, 2); $ret = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'getBucket'), array($bucket, null/*$bpath*/, null, 1000/*, $delimiter = '/'*/), array(), $this->cacheLifetime); $this->_bucket = $bucket; $tree = array(); foreach ($ret as $r) { $p = & $tree; $is_dir = substr($r['name'], -1) == '/'; foreach(explode('/', $r['name']) as $part) { if ($part) {$p = & $p[$part];} } if (!$is_dir) { $p = $r; $p['is_blob'] = true; } } $ctree = & $tree; $bpath = array_filter(explode('/', $bpath)); foreach ($bpath as $part) { $ctree = & $ctree[$part]; } $ppath = implode('/', array_slice($bpath, 0, count($bpath)-1)); $parent = $bpath ? rtrim("$bucket/$ppath", "/") : ''; $items[] = new Am_Storage_Folder($this, '..', $parent); foreach ($ctree as $name => $r) { if (isset($r['is_blob'])) { $items[] = $item = new Am_Storage_File($this, $name, $r['size'], $bucket . '/' . $r['name'], null, null); $item->_hash = $r['hash']; } else { $items[] = $item = new Am_Storage_Folder($this, $name, $path . '/' . $name); } } $actions[] = new Am_Storage_Action_Refresh($this, $path); // $actions[] = $x = new Am_Storage_Action_Upload($this, $this->getId() . '::' .$bucket, // $this->renderUpload($bucket)); } return $items; } public function isLocal() { return false; } public function get($path) { list($bucket, $uri) = explode('/', $path, 2); $info = $this->getDi()->cacheFunction->call( array($this->getConnector(), 'getObjectInfo'), array($bucket, $uri), array(), $this->cacheLifetime); $p = preg_split('|[\\\/]|', $path); // get name $name = array_pop($p); return new Am_Storage_File($this, $name, $info['size'], $path, $info['type'], null); } public function getUrl(Am_Storage_File $file, $expTime, $force_download = true) { list($bucket, $uri) = explode('/', $file->getPath(), 2); return $this->getConnector()->getAuthenticatedURL($bucket, $uri, $expTime, false, $this->getConfig('use_ssl'), $force_download); } /* * * https://amember-com.s3.amazonaws.com/filename.jpg * xxx-com * fn.jpg * "123ad031affb55f5b5a1da5f12a42cbf" * */ public function action(array $query, $path, $url, Am_Mvc_Request $request, Am_Mvc_Response $response) { switch ($query['action']) { case 'refresh': $this->getDi()->cacheFunction->clean(); $response->setRedirect($url); break; default: throw new Am_Exception_InputError('unknown action!'); } } function getReadme() { return << Access Keys (Access Key ID and Secret Access Key) CUT; } // protected function renderUpload($bucket) // { // $output = ""; // $output .= "

      Upload file to Amazon S3

      "; // $bucket = Am_Html::escape($bucket); // $output .= "
      "; // $output .= Am_Html::renderArrayAsInputHiddens( $x = // $this->getConnector()->getHttpUploadPostParams($bucket, '', S3::ACL_PRIVATE, // 3600, 1024*1024*30) // ); // $output .= ""; // $output .= "
      "; // return $output; // } }PK\͸cc/default/themes/solid-color/public/css/theme.cssnu[ .am-header .am-header-content-wrapper { border: none; background: none; } .am-header { background: %color%; } .am-layout { background: %color%; } .am-header-line { border:none; background: %color%; } .am-footer .am-footer-content-wrapper { background: %color%; color: inherit; } .am-body { background: none; } .am-body .am-body-content-wrapper { border: none; } .am-header-content-wrapper { padding: 0; } .am-header-content-content { display: none; } .am-header .am-header-content .am-header-content-logo { float: none; margin: 0; } .am-header .am-header-content { text-align: %logo_align%; } .am-main { max-width: %max_width%px; } .am-header-content img { width: %logo_width%; } .am-footer-actions { display:none; } .am-footer .am-footer-content-wrapper { color: %color_c%; }PK\TL L $default/themes/solid-color/Theme.phpnu[removeElementByName('header'); $el = HTML_QuickForm2_Factory::createElement('advradio', 'logo_align', null, array( 'options' => array( 'left' => ___('Left'), 'center' => ___('Center'), 'right' => ___('Right') ) )); $el->setLabel(___('Logo Position')); $form->insertBefore($el, $form->getElementById('logo-link-group')); $el = HTML_QuickForm2_Factory::createElement('advradio', 'logo_width', null, array( 'options' => array( 'auto' => ___('As Is'), '100%' => ___('Responsive') ) )); $el->setLabel(___('Logo Width')); $form->insertBefore($el, $form->getElementById('logo-link-group')); $form->addText('color', array('size' => 7)) ->setLabel("Theme Color\n" . 'you can use any valid HTML color, you can find useful color palette here'); $gr = $form->addGroup() ->setLabel(___('Layout Width')); $gr->setSeparator(' '); $gr->addText('max_width', array('size' => 3)); $gr->addHtml()->setHtml('px'); $form->addSaveCallbacks(array($this, 'findInverseColor'), null); } public function findInverseColor(Am_Config $before, Am_Config $after) { $t_id = "themes.{$this->getId()}.color"; $t_new = "themes.{$this->getId()}.color_c"; $after->set($t_new, $this->inverse($after->get($t_id))); } protected function inverse($color) { $color = str_replace('#', '', $color); if (strlen($color) != 6){ return '#ffffff'; } $rgb = ''; for ($x=0; $x<3; $x++){ $c = 255 - hexdec(substr($color,(2*$x),2)); $c = ($c < 0) ? 0 : dechex($c); $rgb .= (strlen($c) < 2) ? '0'.$c : $c; } return '#'.$rgb; } public function getDefaults() { return parent::getDefaults() + array( 'color' => '#446787', 'color_c' => '#fffff', 'logo_align' => 'left', 'max_width' => 800, 'logo_width' => 'auto' ); } }PK\~..*default/themes/sample/public/css/theme.cssnu[/** This CSS file is included into of each user template after amember.css and before site.css (if it is exists). There you can see variable %bgcolor% - it is configured in setup form (see application/default/themes/sample/Theme.php) and now substituted here. Files with variables must be added to special list ($publicWithVars) of Am_Theme class and these files are routed via special URL. Routed via URL, it is cached in browser for 1 hour. @link Am_View->printLayoutHead() */ body {background-color: %bgcolor%;} PK\0default/themes/sample/public/img/large-alert.pngnu[PNG  IHDR DgAMAOX2tEXtSoftwareAdobe ImageReadyqe<PLTEKKKMMMϙnfS!Ҡ'+!HݤONL-ޥ3aYEt܅{/ܣ0kΙl`B"ڢ!ߥmލҠ(%5!ߏUSPop4Ovs1~qb=yc70,YVLwg?ą:}\ߑQOL(y]¿ˤE͘2˴}=k7JمȉÒQPO$G0ʛ(ܤ4ʒkI+ތ݊0ve=Z‘}6<{pn'agUSQ)o=fc\}VRHnl$ѼVؠP4_|rXʻƥFlaXTKSRPǬڀ48,he\k9np"OONL͹#^YLvx8URLbhcSteA*oa^X¾0Syx-{YWR_YLأ#URJ)WUPvlWlr4!pgR}f7mԝÿ[~)̗iľWSJ1ۃ1\Ny|8s|aj]WGn< |yp[?eʄy,Ӆu9VRIsvlUrˠ+tRNSyFIDATxbA0v /vLـGAвXIp*8mՉ 4-Ў`|X]Gm"\/nbSj}7A.nnXdǼ YaFxCXu F^ Qp콹`>I3-5 1DdXP# oW-v T9a:Pa'm',¢v`8rffff7@!įqC_;ɉ*Kű-eX%).c,) 2]خ;2addText('bgcolor')->setLabel('Background Color')->default = '#00e'; } }PK\O_I I "default/themes/sample/layout.phtmlnu[ <?php p(isset($meta_title) ? $meta_title : $title) ?> printLayoutHead(); ?> placeholder('body-start'); ?>
      _script('_logo.phtml'); ?>
      getConfig('header'); ?>

      Hello From Sample Template

      Here is a sample of theme-based image and you can "override" base images.

      You can change color of this panel here.

      You can find some info about some customizations here.

      _script('_content.phtml'); ?>
      placeholder('body-finish'); ?> PK\'zdefault/views/payment.phtmlnu[setLayout('layout.phtml'); ?> _script('_receipt.phtml'); ?> prolog; ?>
      epilog; ?>PK\zzdefault/views/_flash.phtmlnu[
      PK\aoR  default/views/_receipt.phtmlnu[ blocks('receipt/before') ?>
      getItems() as $p): ?> first_discount > 0) : ?> first_shipping > 0): ?> first_tax > 0): ?>
      item_title)?> getOptions() as $optKey => $opt): ?>
      : 0 ? '+' : '−' ?> first_price = $opt['first_price']; $o->second_price = $opt['second_price']; $o->first_period = $invoice->first_period; $o->second_period = $invoice->second_period; $o->rebill_times = $invoice->rebill_times; $o->currency = $invoice->currency; $t = new Am_TermsText($o); echo $t->getStringForOption(); ?> getOptions() ?>
      qty) ?> getCurrency($p->first_price)) ?> first_discount > 0): ?> getCurrency($p->getFirstSubtotal())?> getCurrency($p->getFirstTotal()) ?>
      first_discount > 0): ?> getCurrency($invoice->first_subtotal)?> getCurrency($invoice->first_subtotal-$invoice->first_discount)?> getCurrency($invoice->first_subtotal) ?>
      getCurrency($invoice->first_discount)?>
      getCurrency($invoice->first_shipping)?>
      (tax_rate) ?>%) getCurrency($invoice->first_tax)?>
      getCurrency($invoice->first_total)?>
      : getTerms())); ?>
      blocks('receipt/after') ?>PK\M%**#default/views/payment-confirm.phtmlnu[layoutNoMenu = true; $this->setLayout('layout.phtml'); if (empty($btnText)) $btnText = ___('Make Payment'); include $this->_script('_receipt.phtml'); ?>
      PK\"쨸default/views/_content.phtmlnu[
      blocks('content/before'); ?>
      _script('_top.phtml'); ?> breadcrumbs() ?> layoutNoTitle)): ?>

      _script('_flash.phtml'); ?>PK\i"default/views/public/css/reset.cssnu[/* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html version: 2.8.1 */ /** * YUI Reset * @module reset * @namespace * @requires */ html { color: #000; background: #FFF; } body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, code, form, fieldset, legend, input, button, textarea, p, blockquote, th, td { margin: 0; padding: 0; } table { border-collapse: collapse; border-spacing: 0; } fieldset, img { border: 0; } address, caption, cite, code, dfn, em, strong, th, var, optgroup { font-style: inherit; font-weight: inherit; } del, ins { text-decoration: none; } li { list-style: none; } caption, th { text-align: left; } h1, h2, h3, h4, h5, h6 { font-size: 100%; font-weight: normal; } q:before, q:after { content: ''; } abbr, acronym { border: 0; font-variant: normal; } sup { vertical-align: baseline; } sub { vertical-align: baseline; } /*because legend doesn't inherit in IE */ legend { color: #000; } input, button, textarea, select, optgroup, option { font-family: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; } /*@purpose To enable resizing for IE */ /*@branch For IE6-Win, IE7-Win */ input, button, textarea, select { *font-size: 100%; } /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html version: 2.8.1 */ /** * YUI Fonts * @module fonts * @namespace yui- * @requires */ /** * Percents could work for IE, but for backCompat purposes, we are using keywords. * x-small is for IE6/7 quirks mode. */ body { font:13px/1.231 arial,helvetica,clean,sans-serif; /* for IE6/7 */ *font-size:small; /* for IE Quirks Mode */ *font:x-small; } /** * Nudge down to get to 13px equivalent for these form elements */ select, input, button, textarea, button { font:99% arial,helvetica,clean,sans-serif; } /** * To help tables remember to inherit */ table { font-size:inherit; font:100%; } /** * Bump up IE to get to 13px equivalent for these fixed-width elements */ pre, code, kbd, samp, tt { font-family:monospace; *font-size:108%; line-height:100%; } PK\j1&default/views/public/css/site-dist.cssnu[/** * You can place your custom CSS statements here * it is better to write everything custom here * because this file won't be replaced during upgrade * Don't forget to rename this file to "site.css" */ PK\{ff!default/views/public/css/ie-7.cssnu[.am-coll-left, .am-coll-right { width: 49%; } .am-form fieldset legend { margin-left: -7px; }PK\Z6$default/views/public/css/amember.cssnu[body, html { height: 100%; font-size: 13px; } .am-layout { min-height: 100%; margin: 0 0 -30px 0; padding: 0; } @media all and (min-width: 800px) { .am-layout { background: url("../img/layout-bg.png") repeat-y top center #ededed; } } .am-credits { margin-top: -2em; color: #333; height: 2em; text-align: center; font-size: 0.8rem; } .am-credits a { color: #3f7fb0 !important; } .am-common { font-family: Tahoma, Arial, san-serif; color: #303030; } .am-common h1 { font-size: 1.5rem; font-weight: normal; color: #333; line-height: 1em; height: auto; margin-bottom: 0.6em; } .am-common h2 { font-size: 1.2rem; line-height: 1em; height: auto; margin-bottom: 0.6em; } .am-common h3 { font-size: 1rem; line-height: 1em; height: auto; font-weight: bold; margin-bottom: 0.6em; } .am-common em { font-style: italic; } .am-common p { padding-bottom: 0.5em; } .am-common strong { font-weight: bold; } .am-common hr { background-color: #dbdbdb; border: 0; width: 100%; height: 1px; } .am-common a { color: #3f7fb0; } .am-common a:focus { outline: none; } .am-common a:hover { text-decoration: none; } .am-common ul { margin: 0 0 1em 2em; } .am-common ul li { list-style-type: disc; } .am-common ol { margin: 0 0 1em 2em; } .am-common ol li { list-style-type: decimal; } .am-main { /* applies to am-header-content/am-body-content-wrapper/am-footer-content-wrapper */ padding-left: 20px; padding-right: 20px; margin: 0 auto; text-align: left; width: 100%; max-width: 800px; box-sizing: border-box; } @media all and (max-width: 320px) { .am-main { padding-left: 10px; padding-right: 10px; } } .am-header { overflow: hidden; background: #325069; } .am-header .am-header-content-wrapper { border-width: 0 1px; border-style: solid; border-color: #688296; background: url("../img/header-wrapper-bg.png") repeat-x top left #355873; } .am-header .am-header-content { padding: 10px 0; overflow: hidden; } .am-header .am-header-content .am-header-content-logo { float: left; margin-right: 1em; } .am-header-line { height: 12px; background: #9c9c9c; border-top: 1px solid #bdbdbd; border-bottom: 1px solid #ebebeb; } @media all and (min-width: 800px) { .am-body { background: url("../img/body-bg.png") repeat-x left top #ededed; } } .am-body .am-body-content-wrapper { text-align: left; background: white; padding-bottom: 50px; padding-top: 1em; } @media all and (min-width: 800px) { .am-body .am-body-content-wrapper { border-color: #dbdbdb; border-width: 0 1px; border-style: solid; } } .am-body .am-body-content-top { overflow: hidden; } .am-footer { color: #919191; height: 30px; } .am-footer .am-footer-content-wrapper { background: #325069; color: white; height: 30px; } .am-footer .am-footer-content { padding-top: 0.5em; } .am-footer .am-footer-content a { color: white; } .am-footer .am-footer-actions { float: right; } @media all and (max-width: 500px) { .am-member-payment-history-items { display: none; } } @media all and (max-width: 600px) { .am-member-payment-history-paysys { display: none; } } ul.am-breadcrumbs { font-size: 90%; margin: 0 0 0.5em; overflow: hidden; padding: 0 1em 0 0; } ul.am-breadcrumbs .am-breadcrumbs-item, ul.am-breadcrumbs .am-breadcrumbs-separator { float: left; margin: 0 0.5em 0 0; padding: 0; list-style: none; } .am-thanks-awaiting-refresh { margin-top: 20px; color: gray; } .am-thanks-status-success { padding-bottom: 1em; color: green; } .am-thanks-payment-details { padding-bottom: 1em; } .am-thanks-login-offer { padding-bottom: 1em; } /* Grid */ .check-all-offer { background-color: #ffc; padding: 0.5em; border: 1px solid white; border-bottom: none; } .filter-wrap { color: #333; background: #dbdbdb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; padding: 0.5em; text-align: right; margin-bottom: 1em; box-shadow: 0 1px 0 #b0b0b0; overflow: hidden; } .filter-wrap .filter-title { float: right; margin-right: 1em; line-height: 2em; } .filter-wrap .filter-inputs { float: right; margin-right: 0.5em; text-align: left; } .filter-wrap .filter-button { float: right; text-align: left; } .filter-wrap form.filter input[type=text] { background-image: url("../img/icons/magnify.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 25px; } .filter-wrap form.filter input[type=text].datepicker { background-image: url("../img/icons/calendar.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 25px; } .group-wrap, .norecord-actions { margin-bottom: 1em; } .group-wrap .link, .norecord-actions .link { display: inline-block; margin: 0.4em 1em; } .grid-total { padding: .5em; text-align: right; } .grid-container { border: 1px solid #a1a1a1; box-shadow: 0 2px 4px #d6d6d6; margin-bottom: 1em; overflow-x: auto; } .grid { width: 100%; } .grid tr.grid-row { border-bottom: 1px solid #ddd; } .grid tr.grid-row.expanded, .grid tr.grid-row.even, .grid tr.grid-row.odd { border-bottom: none; } .grid tr.grid-row.odd td { background-color: #d3dce3; } .grid tr.grid-row.odd td.sorted { background-color: #bed4e2; } .grid tr.grid-row.selected { background: #ffc; } .grid tr.grid-row.selected td { background: none !important; border-bottom: 1px solid #e5e5e5; } .grid tr.grid-row.emphase { background-color: #ffc; } .grid tr.grid-row.emphase td { background: none !important; } .grid tr.grid-row > td { padding: .8em .5em; vertical-align: top; } .grid tr.grid-row > td.break { word-break: break-word; word-wrap: break-word; } .grid th { padding: 0.5em; border: 1px solid white; background: url("../img/grid-header-bg.png") repeat-x top left; color: white; text-shadow: 0 -1px 1px #1e2e3b; } .grid th a { padding-right: 20px; display: block; color: white; text-decoration: none; text-shadow: 0 -1px 1px #1e2e3b; background: url("../img/grid-sortable.png") no-repeat right center; } .grid th a.sorted-asc { background: url("../img/grid-asc.png") no-repeat right center; } .grid th a.sorted-desc { background: url("../img/grid-desc.png") no-repeat right center; } .grid tr.grid-row > td { background: #ededed; } .grid tr.grid-row > td.sorted { background: #d9e6ee; } .grid tr.grid-row > td.actions { text-align: center; } .grid tr.grid-row > td.record-sort { background-image: url("../img/grid-sortable.png"); background-repeat: no-repeat; background-position: center center; cursor: move; } .grid tr.grid-row > td.expandable-data { background: #eef; } .grid tr.grid-row > td.expanded { background: #eef !important; border-bottom-color: #eef; } .grid tr.grid-row > td.expandable { cursor: pointer; } .grid tr.grid-row > td.expandable div.arrow { display: inline-block; width: 7px; height: 5px; overflow: hidden; float: right; margin: 0px; padding-left: 10px; background: url("../img/arrow.png") no-repeat right; } .grid tr.grid-row > td.expandable div.placeholder { padding-right: 1em; } .grid .editable { display: inline-block; width: 8px; height: 8px; overflow: hidden; float: right; margin: 0px; padding-left: 10px; background: url("../img/pencil.png") no-repeat right; } .grid .live-edit, .grid .live-select { cursor: pointer; } .grid .disabled { opacity: .75; filter: Alpha(Opacity=75); } .grid th.required { color: #a94442; text-shadow: none; } .grid tr.grid-row:hover > td { background-color: #bed4e2 !important; } .grid tr.grid-row:hover > td.expanded { background-color: #eef !important; } .grid tr.grid-row.expandable-data-row:hover > td { background-color: #eef !important; } .grid tr.grid-row > td.selected { background: #d9e6ee !important; } .grid.grid-no-highlight tr.grid-row:hover > td { background-color: inherit !important; } .grid.grid-no-highlight tr.grid-row.odd > td { background-color: #d3dce3 !important; } .grid.grid-small { font-size: 80%; } .grid-action-export-preset-list { margin: 1em; } .grid-action-export-preset-list .grid-action-export-preset-list-item { padding-bottom: .5em; } .grid-action-export-preset-list .grid-action-export-preset-list-item:hover .grid-action-export-preset-list-action { display: inline; } .grid-action-export-preset-list .grid-action-export-preset-list-action { display: none; } .grid-action-export-preset-list .grid-action-export-preset-list-action a, .grid-action-export-preset-list .grid-action-export-preset-list-action a:visited { color: #BA2727; } /* END Grid */ .am-account-toolbar { overflow: hidden; margin-bottom: 1em; } .am-account-toolbar-items { overflow: hidden; } .am-tabs-narrow-switch { cursor: pointer; float: left; padding-right: 8px; display: none; } .am-tabs-narrow-dashboard { float: left; padding-right: 8px; display: none; } @media all and (max-width: 500px) { .am-tabs-narrow-switch, .am-tabs-narrow-dashboard { display: block; } .am-lang-title { display: none; } .am-account-toolbar { margin-bottom: 0.5em; overflow: visible; z-index: 10; } .am-account-toolbar .am-account-toolbar-items { padding: 0.5em; background: #eee; } .am-account-toolbar-fixed { position: fixed; width: 100%; top: 0; left: 0; box-shadow: 0 1px 5px grey; } } .am-user-identity-block { background: url("../img/identity-glyph.png") no-repeat left center; font-weight: bold; padding-left: 25px; line-height: 24px; float: left; } .am-user-identity-block a { text-decoration: none; font-weight: normal; } .am-user-identity-block-avatar { font-weight: bold; overflow: hidden; line-height: 24px; float: left; } .am-user-identity-block-avatar a { text-decoration: none; font-weight: normal; } .am-user-identity-block-avatar-pic { overflow: hidden; width: 24px; height: 24px; border-radius: 50%; margin-right: 0.5em; float: left; } .am-user-identity-block-avatar-pic img { width: 24px; height: 24px; } /* two column layout, used for login/sendpass on login and signup page */ .am-layout-two-coll { border: 1px solid #d9d9d9; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; box-shadow: 0 1px 3px #e3e3e3; background-color: #f5f5f5; } @media all and (min-width: 750px) { .am-layout-two-coll { background: url("../img/two-coll-divider-middel.png") repeat-y top center #f5f5f5; } } .am-layout-two-coll .am-layout-two-coll-bottom { clear: both; height: 20px; background-color: #f5f5f5; } @media all and (min-width: 750px) { .am-layout-two-coll .am-layout-two-coll-bottom { background: url("../img/two-coll-divider-bottom.png") repeat-y top center; } } .am-layout-two-coll .am-layout-two-coll-top { clear: both; height: 20px; background-color: #f5f5f5; } @media all and (min-width: 750px) { .am-layout-two-coll .am-layout-two-coll-top { background: url("../img/two-coll-divider-top.png") repeat-y top center; } } @media all and (min-width: 750px) { .am-layout-two-coll .am-coll-left, .am-layout-two-coll .am-coll-right { float: left; width: 50%; } } .am-layout-two-coll .am-coll-left .am-coll-content { margin: 0 1em; } .am-layout-two-coll .am-coll-right .am-coll-content { margin: 0 1em; } /* Pagination */ .am-pagination { clear: both; font-size: 100%; padding: 0.5em 0; margin: 0.5em 0; } .am-pagination a { text-decoration: none; border: solid 1px #91aabd; color: #5e6e7a; background: #d3dce3; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; text-shadow: 0 -1px 1px #fff; } .am-pagination a, .am-pagination span { padding: 0.3em 0.6em; margin-right: 5px; margin-bottom: 5px; font-weight: bold; } .am-pagination .am-pagination-current { background: #8fabbd; color: #fff; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: solid 1px #91aabd; text-shadow: 0 -1px 1px #596d7d; } .am-pagination .am-pagination-current.am-pagination-prev, .am-pagination .am-pagination-current.am-pagination-next { color: #afb5ba; border-color: #cad3db; background: #e3e6e8; text-shadow: none; } /* Tabs - user member area menu */ ul.am-tabs { display: block; overflow: hidden; margin: 0 0 1em 0; padding: 0 0.5em 0.5em 0.5em; background: #dbdbdb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; box-shadow: 0 1px 0 #b0b0b0; text-align: left; } ul.am-tabs #menu-member { width: 1em; height: 1.2em; text-indent: 2em; overflow: hidden; background: url("../img/dashboard.png") no-repeat center center; } ul.am-tabs li.active #menu-member, ul.am-tabs #menu-member:hover { background-image: url("../img/dashboard-h.png"); } ul.am-tabs li { display: block; margin: 0 0.5em 0 0; padding: 0; float: left; background: url("../img/tab-bg.png") repeat-x top left #e8e8e8; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; white-space: nowrap; } ul.am-tabs > li { margin-top: 0.5em; } ul.am-tabs a { display: block; box-sizing: content-box; margin: 0; height: 1.2em; line-height: 1.2em; padding: 0.5em 1em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: 1px solid #ccc; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; text-decoration: none; } ul.am-tabs li.active > a, ul.am-tabs li.normal > a:hover { background: url("../img/tab-hover-bg.png") repeat-x top left #e34b3d; border-color: #c7665b; color: white; text-shadow: 0 -1px 1px #c43d33; } ul.am-tabs li.active, ul.am-tabs li.normal:hover { background: url("../img/tab-hover-bg.png") repeat-x top left #e34b3d; } ul.am-tabs ul { display: none; position: absolute; margin: 0; padding: 0; z-index: 5; } ul.am-tabs ul li { float: none; } ul.am-tabs li:hover > ul { display: block; } ul.am-tabs span.arrow { display: inline-block; position: relative; width: 7px; height: 5px; margin: 0 0 2px 5px; padding: 0; overflow: hidden; z-index: 15; background: url("../img/arrow.png") no-repeat left; } ul.am-tabs a:hover span.arrow, ul.am-tabs li.active span.arrow { background-image: url("../img/arrow-white.png"); } ul.am-tabs .has-children > ul { background: url("../img/tab-bg.png") repeat-x top left #e8e8e8; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border-top-left-radius: 0; border: 1px solid #ccc; min-width: 150px; overflow: hidden; } ul.am-tabs .has-children > ul > li { margin: 0; } ul.am-tabs .has-children > ul a { -webkit-border-radius: 0; border-radius: 0; border: none; background: none; } ul.am-tabs .has-children ul li { border-radius: 0; background: none; } ul.am-tabs .has-children > ul li.active { background-image: url("../img/tab-hover-bg.png"); background-color: #e34b3d; } ul.am-tabs .has-children > a:hover { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } ul.am-tabs li.expanded > a { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } /* END Tabs */ /* Tabs Narrow - user member area menu */ .am-tabs-narrow-stuff { display: none; } .am-tabs-narrow-wrapper { display: none; clear: both; } .am-tabs-narrow-wrapper.am-tabs-narrow-wrapper-open { animation-name: tabs-narrow; animation-duration: .5s; } .am-tabs-narrow-wrapper .am-tabs-narrow-wrapper-tail { background: url("../img/menu-pointer.png") no-repeat right; width: 24px; height: 12px; margin-top: -12px; margin-left: 0.5em; padding-left: 32px; } @keyframes tabs-narrow { from { transform: translateY(10px); } to { transform: translateY(0px); } } ul.am-tabs-narrow { overflow: hidden; margin: 0; padding: 1em; background: #dbdbdb; text-align: left; } ul.am-tabs-narrow ul { margin: 0 0 0 1em; padding: 0; } ul.am-tabs-narrow li { list-style-type: none; } ul.am-tabs-narrow a { padding-bottom: .4em; display: block; } ul.am-tabs-narrow li.active > a { font-weight: bold; } @media all and (max-width: 500px) { .am-tabs-wrapper { display: none; } .am-tabs-narrow-wrapper { display: block; } } @media all and (max-width: 600px) { ul.am-tabs a { padding: 0.4em 0.5em; } ul.am-tabs li { margin: 0 0.2em 0 0; } ul.am-tabs > li { margin-top: 0.2em; } ul.am-tabs { padding: 0 0.2em 0.2em 0.2em; } } /* END Tabs Narrow */ /* Receipt table from thanks.phtml */ .am-receipt { border: 1px solid #E0E0E0; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 1em; padding: 0.5em; border-collapse: collapse; box-shadow: 0 1px 1px #e0e0e0; } .am-receipt table { width: 100%; } .am-receipt td { background-color: #ededed; padding: 0.5em; border: 1px solid white; } .am-receipt th { font-weight: bold; padding: 0.5em; } @media all and (max-width: 500px) { .am-receipt th { padding: 0; font-weight: normal; font-size: 80%; } .am-receipt .am-receipt-terms { font-size: 80%; } } .am-receipt td.am-receipt-total { background-color: #d3dce3; } .am-receipt td.am-receipt-terms { background: none; } .am-receipt td.am-receipt-indent { background: none; } .am-receipt .am-receipt-row-delimiter td { background: none; } .am-receipt .am-receipt-price { width: 20%; text-align: right; } .am-receipt .am-receipt-unit-price { width: 20%; text-align: right; } .am-receipt .am-receipt-qty { width: 10%; text-align: right; } .am-receipt .am-receipt-discounted-price { text-decoration: line-through; color: red; } /* Common Form Elements */ a.button { display: inline-block; text-decoration: none; } a.button, input[type=button], input[type=submit] { background: url("../img/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; padding: 0.5em 1.2em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } a.button:hover, a.button.active, input[type=button]:hover, input[type=submit]:hover, input[type=button].active, input[type=submit].active { cursor: pointer; border-color: #688296; background-image: url("../img/form-button-hover-bg.png"); background-color: #4e80a6; color: white; text-shadow: 0 1px 1px #688296; } input[type=button]:active, input[type=submit]:active { cursor: pointer; background: url("../img/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; padding: 0.5em 1.2em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } input[type=button]:disabled, input[type=submit]:disabled { color: #ccc; border: 1px solid #ccc; background: url("../img/form-button-bg.png") repeat-x top left #e8e8e8; text-shadow: none; } input:disabled, input[readonly], input[type=text][readonly]:focus { background: #e8e8e8; border: 1px solid #ccc; color: #ccc; box-shadow: none; } select, textarea, input[type=text], input[type=password] { padding: 0.5em; border: 1px solid #c2c2c2; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } button:focus, textarea:focus, select:focus, input:focus { outline: none; } textarea:focus, input[type=text]:focus, input[type=password]:focus { background-color: #ffffcf; border-color: #51a7e8; box-shadow: 0 0 2px #51a7e8; } select:focus { border-color: #51a7e8; box-shadow: 0 0 2px #51a7e8; } textarea.error, input.error { background-color: #fce6e6; border: 1px solid #a94442; } /* END Common Form Elements */ /* Form*/ .am-form { margin-bottom: 1em; /* support for form elements without the label */ /* support for wide elements */ } .am-form input, .am-form textarea, .am-form select, .am-form button { line-height: 1em; height: auto; display: inline-block; } .am-form form { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: 1px solid #ddd; border-top: 2px solid #d0d0d0; box-shadow: 0 1px 1px -1px #b0b0b0; background: #fff; margin: 0; padding: 0; text-align: left; } .am-form fieldset { display: block; border: none; padding: 0; margin: 0; } .am-form fieldset legend { width: 100%; display: block; margin: 0; padding: 0.5em 0; font-family: Arial; font-size: 120%; color: #333; white-space: nowrap; background: #f1f1f1; border-bottom: 1px solid #d5d5d5; text-indent: 1em; } .am-form fieldset.am-adv-fieldset > legend { cursor: pointer; color: #3f7fb0; } .am-form fieldset.am-adv-fieldset > legend .am-adv-fieldset-lable { position: relative; } .am-form fieldset.am-adv-fieldset > legend .am-adv-fieldset-lable:after { border-bottom: 1px #9aa9b3 dashed; content: ''; height: 0; left: 0; right: 0; bottom: 1px; position: absolute; } .am-form fieldset.am-adv-fieldset-closed > legend .am-adv-fieldset-lable { font-weight: bold; } .am-form .row:first-child .element-title:first-child { -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .am-form .row.disabled { opacity: .5; } .am-form .row.row-highlight { background: #ffe; } .am-form div.reqnote { clear: both; font-size: 80%; margin: 0.5em 0 0 1em; } .am-form div.row { border-bottom: 1px solid #ededed; margin: 0; } .am-form div.element-title { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: .5em 1em; background-color: #f9f9f9; } @media all and (min-width: 500px) { .am-form div.element-title { background-color: transparent; width: 35%; float: left; text-align: right; padding: 1em 0.5em 1em 1em; } } .am-form div.element-title label { font-weight: bold; color: #555; } .am-form div.element-title .comment, .am-form div.element-title .comment strong, .am-form div.element-title .comment b { color: #777; } .am-form div.element { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: .5em 1em; } @media all and (min-width: 500px) { .am-form div.element { margin-left: 35%; padding: 1em 1em 1em 0.5em; } } @media all and (max-width: 500px) { .am-form div.element input[type=text], .am-form div.element input[type=password], .am-form div.element input[type=submit], .am-form div.element textarea, .am-form div.element select { box-sizing: border-box; width: 100%; margin-bottom: 0.2em; } .am-form div.element input.el-short { width: auto; } } .am-form div.row.no-label .element { margin: 0; padding: 1em 1em; } .am-form div.row.no-label div.element-title { width: 0; display: none; } .am-form div.row.row-wide .element { margin: 0; padding: 0.5em 1em; } .am-form div.row.row-wide .element-title { float: none; width: 100%; text-align: left; padding: 0.5em 1em; } .am-form textarea { overflow: auto; } .am-form input[type=text], .am-form input[type=password], .am-form select, .am-form textarea { padding: 0.5em; } .am-form span.error, .am-form span.required { color: #a94442; } .am-form span.error { display: block; } .am-form input.error, .am-form textarea.error, .am-form select.error { border: 1px solid #a94442; } .am-form select { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; max-width: 100%; } .am-form span.mceEditor { display: block; } input.datepicker, input[type=text].datepicker { background-image: url("../img/icons/calendar.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 25px; } .input_datetime { border: 1px solid #c2c2c2; display: inline-block; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .input_datetime input[type=text] { border: none; text-align: center; } .input_datetime .input_datetime-date { border-radius: 3px 0 0 3px; float: left; display: block; } .input_datetime .input_datetime-time { border-radius: 0 3px 3px 0; float: left; display: block; background: #fafafa; } .el-wide { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; width: 100%; } div.row:after { content: "."; visibility: hidden; display: block; height: 0; clear: both; } /* Special Styles for Signup Form */ .am-signup-form input.valid { background: url("../img/icons/valid.png") white right center no-repeat; } .am-signup-form input.am-with-action.valid { background: url("../img/icons/valid.png") white 90% center no-repeat; } .am-signup-form input.am-product-qty.valid { background-image: none; } .am-aff-referred-by { text-align: center; color: #777; } a.am-brick-product-remove { text-decoration: none; color: #303030; } a.am-brick-product-remove:hover { color: #ba2727; } /* Common styles */ .am-body-content { clear: both; } div.errors ul, ul.error, ul.errors { margin: 0 0 1em 0; padding: 0; background: #fcbdbd; border: 1px solid #faa7a7; color: #ba2727; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } div.errors ul li, ul.error li, ul.errors li { margin-left: 0px; padding: 0.5em 1em; list-style: none; text-align: left; } .error { color: #ba2727; } .am-signup-link { text-align: center; margin-top: 1em; } .am-copyright { margin: 1em 0 0 0; text-align: center; font-size: 75%; } .am-copyright a { text-decoration: none; } /* language choice select */ .am-lang-choice { float: right; line-height: 24px; } .am-lang-choice select { padding: 0.2em; } /* Form Login */ .am-signup-login-form-container { z-index: 150; position: absolute; margin: 0 auto; width: 754px; background-color: white; border: solid 3px #ccc; padding: 20px; } .am-avatar-preview { display: inline-block; border-radius: 50%; overflow: hidden; } .am-auth-form { margin-bottom: 1em; margin: 0 auto; max-width: 350px; } @media all and (min-width: 500px) { .am-auth-form { width: 350px; } } .am-auth-form legend { text-indent: 0; text-align: center; } .am-auth-form div.element-title label { font-weight: normal; } .am-auth-form input[name=login], .am-auth-form input[name=amember_login] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background-image: url("../img/icons/users.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 30px; width: 100%; border-radius: 0; line-height: 1.5em; } .am-auth-form input[name=amember_pass] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background-image: url("../img/icons/key.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 30px; width: 100%; border-radius: 0; line-height: 1.5em; } .am-auth-form input[type=submit] { line-height: 1.5em; } .am-auth-form div.row { background: #f9f9f9; border-bottom: none; } .am-popup .am-login-form legend, .am-popup .am-sendpass-form legend { display: none; } .am-popup .am-login-form form, .am-popup .am-sendpass-form form { border: none; box-shadow: none; } .am-popup .am-login-form .row, .am-popup .am-sendpass-form .row { border: none; } .am-popup .am-login-form .row .element-title, .am-popup .am-sendpass-form .row .element-title { background: none; } .am-popup .am-auth-form div.row { background: none; } .am-popup .am-form.am-auth-form div.element { margin: 0; padding: .5em; } .am-popup .am-form.am-auth-form div.element-title { width: auto; text-align: left; float: none; padding: .5em; } .am-sendpass-form-wrapper { display: none; } .am-form-login-switch { margin-left: 0.5em; } #am-form-login-remember { margin-top: 0.5em; display: block; } /* END Form Login */ .agreement { font-size: 8pt; white-space: pre-wrap; max-height: 300px; overflow: auto; } #mask { z-index: 10000; position: fixed; top: 0; left: 0; -moz-opacity: 0.7; opacity: .70; filter: alpha(opacity=70); background-color: #CCC; width: 100%; height: 100%; zoom: 1; } .am-active-invoice { padding: 0.5em; border: 1px solid #EDEDED; margin-bottom: 0.5em; } .am-active-invoice .am-active-invoice-num { font-weight: bold; } .am-active-invoice .am-active-invoice-terms { font-style: italic; } .am-active-invoice .am-active-invoice-cancel { color: gray; } .am-active-invoice .am-active-invoice-product { color: gray; } .am-active-invoice .am-active-invoice-product-list { margin: 0 0 0 2em; } .am-active-invoice .am-active-invoice-product-list li { list-style-type: disc; } .am-list { margin-bottom: 1em; margin-left: 2em; } .am-list li { list-style-type: disc; } ul.am-widget-list li { list-style-type: none; } .small { font-size: small; font-style: italic; } .am-brick-product-popup-cats { background: #eee; padding: 0.5em; margin-bottom: 1em; } .am-brick-product-popup-cat-active { background: white; } .am-product-title { font-weight: bold; } .am-product-desc { font-size: small; font-style: italic; display: block; } .am-paysystem-title { font-weight: bold; } .am-paysystem-desc { font-size: small; font-style: italic; display: block; } .ajax-link, .local-link, .local { text-decoration: none; position: relative; } .ajax-link:after, .local-link:after, .local:after { border-bottom: 1px #9aa9b3 dashed; content: ''; height: 0; left: 0; right: 0; bottom: 1px; position: absolute; } .am-reuse-card-confirmation { font-size: large; } .am-form div.am-element-recaptcha { margin-left: 0; text-align: center; padding: 1em; } .am-form div.am-element-recaptcha > div { display: inline-block; } /* icons */ .glyph { width: 16px; height: 16px; display: inline-block; background-image: url("../img/sprite/icon.png"); background-repeat: no-repeat; background-position: left center; } #EmailCode { background: #FFFFCF; font-size: 1.2rem; line-height: 150%; } .am-switch-reveal { display: inline-block; width: 16px; height: 16px; margin-left: -24px; cursor: pointer; vertical-align: middle; } .am-switch-reveal-off { background: url("../img/eye-off.png"); } .am-switch-reveal-on { background: url("../img/eye.png"); } .am-flash { display: none; } .am-flash-mask { position: fixed; z-index: 500; opacity: 0.8; left: 0; top: 0; width: 100%; height: 100%; background: #eee; } .am-flash-content { position: fixed; z-index: 501; top: 20%; left: 50%; margin-left: -140px; width: 280px; } .am-flash-content-message { background: #dfe8f0; border: 1px solid #ccddeb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; padding: 0.5em 1em; } .am-flash-content-error { background: #fcbdbd; border: 1px solid #faa7a7; color: #ba2727; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; padding: 0.5em 1em; } /* outline a block in member area */ .am-block { color: #666; background: #fff; border: 1px solid #e0e0e0; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 1em; padding: 1em; box-shadow: 0 1px 1px #e0e0e0; } .am-block ul { margin: 0; padding: 0; } .am-block li { list-style-type: none; margin: 0 0.3em 0 0; } .am-block#drop-me { border-color: #e34b3d; } #drop-me-head { color: #e34b3d; } /* am-info is a notice on page with border and outlined by color */ .am-info { background: #dfe8f0; border: 1px solid #ccddeb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 1em; padding: 0.5em 1em; } .am-notification { background-color: #FFFFCF; border-color: #545454; color: #454430; } .am-block-nodata { text-align: center; padding: 2em; background: #edeef0; font-size: 1.2rem; } /* Invoice Summary on Signup Page */ .am-invoice-summary { color: #666; background: #fff; border: 1px solid #ddd; border-top: 2px solid #d0d0d0; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 1em; padding: 1em; box-shadow: 0 1px 1px -1px #b0b0b0; } .am-invoice-summary table { width: 100%; } .am-invoice-summary td { padding: 0.2em 0.4em; } .am-invoice-summary .am-invoice-summary-item-num { color: #e0e0e0; } .am-invoice-summary .am-invoice-summary-price { text-align: right; width: 20%; } .am-invoice-summary .am-invoice-summary-item-qty { width: 1%; } .am-invoice-summary .am-invoice-summary-subtotal, .am-invoice-summary .am-invoice-summary-discount, .am-invoice-summary .am-invoice-summary-shipping, .am-invoice-summary .am-invoice-summary-tax, .am-invoice-summary .am-invoice-summary-total { text-align: right; font-size: 1.2rem; } .am-invoice-summary .am-invoice-summary-row-subtotal, .am-invoice-summary .am-invoice-summary-row-discount, .am-invoice-summary .am-invoice-summary-row-shipping, .am-invoice-summary .am-invoice-summary-row-tax, .am-invoice-summary .am-invoice-summary-row-total { font-size: 1.2rem; } .am-invoice-summary .am-invoice-summary-item { border-bottom: 1px dashed #e0e0e0; } .am-invoice-summary .am-invoice-summary-item.am-invoice-summary-item-last { border-bottom: none; } .am-invoice-summary tr.am-invoice-summary-delimeter td { padding: 0; } .am-invoice-summary tr.am-invoice-summary-delimeter hr { background: #ededed; margin-top: 0; } .am-popup { margin: 0 auto; padding: 10px 20px 20px 20px; position: absolute; text-align: left; z-index: 10001; display: none; background-color: white; border-width: 3px 0; border-color: #ccc; border-style: solid; min-width: 320px; box-sizing: border-box; } @media all and (min-width: 321px) { .am-popup { border-width: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } } .am-popup .am-popup-close-icon { display: inline-block; background: url("../img/modal-close.png"); width: 12px; height: 12px; float: right; text-decoration: none; } .am-popup .am-popup-header { font-size: 1.1rem; font-weight: bold; overflow: hidden; margin: -10px -20px 1em -20px; background: #eee; padding: 1em; } /* Uploader */ .upload-control { display: inline-block; } .upload-control .upload-control-upload { background: url("../img/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; padding: 0.5em 1.2em; -moz-border-radius: 3px 0 0 3px; -webkit-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } .upload-control .upload-control-upload.upload-control-reupload { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .upload-control .upload-control-browse { display: inline-block; background: url("../img/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; border-left: none; padding: 0.5em 1.2em; -moz-border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; cursor: pointer; } .upload-control .upload-control-upload.hover, .upload-control .upload-control-browse.hover { border-color: #688296; background-image: url("../img/form-button-hover-bg.png"); background-color: #e34b3d; color: white; text-shadow: 0 -1px 1px #688296; } .upload-control span.uploading { background: url("../img/ajax-loader-small.gif") no-repeat left center; padding-left: 20px; } .upload-control .upload-control-upload.upload-control-upload-single { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } /* END Uploader */ .morris-hover { position: absolute; z-index: 1000; } .morris-hover.morris-default-style { border-radius: 10px; padding: 6px; color: #666; background: rgba(255, 255, 255, 0.8); border: solid 2px rgba(230, 230, 230, 0.8); font-family: sans-serif; font-size: 12px; text-align: center; } .morris-hover.morris-default-style .morris-hover-row-label { font-weight: bold; margin: 0.25em 0; } .morris-hover.morris-default-style .morris-hover-point { white-space: nowrap; margin: 0.1em 0; } .am-donation { padding: 0.5em 0; } .am-donation .am-donation-recurring { padding-left: 1em; } .am-donation .smileyface { width: 50px; height: 50px; position: relative; border-radius: 50px; display: block; border: 1px solid #333; background: rgba(255, 230, 50, 0.28); } .am-donation .eyes { width: 4px; height: 8px; background: #333; border-radius: 5px/10px; position: absolute; top: 10px; box-shadow: 0 2px 0 rgba(255, 255, 255, 0.8); } .am-donation .eyes.lefteye { left: 12px; } .am-donation .eyes.righteye { right: 12px; } .am-donation .smile { width: 30px; height: 20px; box-sizing: border-box; border: 2px solid #333; border-top: none; border-right: none; border-left: none; background: transparent; border-radius: 0 0 20px 20px; position: absolute; bottom: 10px; left: 10px; box-shadow: 0 2px 0 rgba(255, 255, 255, 0.8); } .am-donation .am-donation-smile-wrap { overflow: hidden; } .am-donation .am-donation-smile { width: 60px; float: right; } .am-donation .am-donation-slider { margin-right: 80px; padding: 0 1em; } .am-donation .ui-slider-range { background: #71BD26 !important; } .am-donation .ui-slider-handle { border-color: #71BD26 !important; } .am-donation a:focus { outline: none; } .am-donation .am-donation-total { font-size: 130%; font-style: italic; margin-bottom: 0.8em; } .am-donation .am-donation-total-amount { font-weight: bold; } .am-donation .am-donation-smile-wrap .ui-slider { height: 4px; border: 0; background: #eee; } .am-donation .am-donation-smile-wrap .ui-slider-handle { height: 1.6em; width: 1.6em; top: -0.8em; margin-left: -0.8em; border-radius: 0.8em; box-shadow: 0 1px 1px #eee; cursor: move; background: #fefefe; } .am-donation .am-donation-smile-wrap .ui-slider-handle:hover { background: #fefefe; } .am-video-wrapper { text-align: center; background: black; } .am-video { position: relative; overflow: hidden; } .am-video-poster { overflow: hidden; } .am-video-poster-icon { position: absolute; background: url("../img/play.png") center center no-repeat; height: 100%; width: 100%; } .am-video-poster-icon:hover { background-image: url("../img/play-h.png"); } PK\p"%%"default/views/public/css/admin.cssnu[/** Common body styles */ body, html { height: 100%; font-family: Helvetica, Tahoma, Arial, sans-serif; color: #313131; } html { font-size: 13px; } hr { border: none; height: 1px; background: #b0b0b0; } h1 { font-size: 1.5rem; font-weight: normal; color: #333; margin-bottom: 1em; text-shadow: 0 -1px 1px white; } h2 { font-size: 1.2rem; font-weight: bold; margin-bottom: 0.8em; } h3 { font-size: 1rem; font-weight: bold; margin-bottom: 0.8em; } a, a:visited { color: #34536e; } a.link { text-decoration: none; position: relative; } a.link:after { border-bottom: 1px #9aa9b3 solid; content: ''; height: 0; left: 0; right: 0; bottom: 1px; position: absolute; } a.link:hover:after { opacity: 0; } a:focus { outline: none; } a:hover { text-decoration: none; } a.local { text-decoration: none; position: relative; } a.local:after { border-bottom: 1px #9aa9b3 dashed; content: ''; height: 0; left: 0; right: 0; bottom: 1px; position: absolute; } .red, .red a, .red strong { color: #BA2727; } .info { margin-bottom: 1em; padding: 0.5em 1em; background: #dfe8f0; border: 1px solid #ccddeb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; box-shadow: 0 1px 0 #9fafbd; display: none !important; visibility: hidden !important; } strong { font-weight: bold; color: #555; } a strong { color: #34536e; } em { font-style: italic; } p { margin-bottom: 0.5em; } /* Layout */ #header { display: block; overflow: hidden; margin: 0; padding: .8em 2em .8em 1em; height: 25px; background: url("../img/admin/header-bg.png") repeat-x top left; background: linear-gradient(#424242, #212121); line-height: 25px; } #header .header-right { float: right; overflow: hidden; } /** ajax loading element */ .ajax-loading { display: none; position: fixed; margin: 0; padding: 0.5em 1em; top: 10px; left: 40%; z-index: 10000; opacity: 0.9; color: white; line-height: 24px; font-size: 16px; background: black; } .ajax-loading img { float: left; margin: 0 0.5em 0 0; } /* login form */ .user-identity-block { display: inline-block; float: right; margin: 0; padding: 0 0 0 20px; background: url("../img/admin/identity-glyph.png") no-repeat left center; color: white; } .user-identity-block a { color: #ec645a; } .user-identity-block .user-identity-block-user-narrow { display: none; } @media all and (max-width: 765px) { .user-identity-block .user-identity-block-user-narrow { display: inline; } .user-identity-block .user-identity-block-user-wide { display: none; } } .logo-block a { color: white; text-decoration: none; font-size: 17px; } /** language select */ .am-lang-choice div { margin: 0; padding: 2em 1.5em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; background-color: black; color: white; } #lang-switch-icon { cursor: pointer; position: relative; z-index: 100; } #footer { background: #2e2e2e; color: #919191; height: 30px; } .footer-content { margin: 0; padding: 0.5em 2em 0.5em 1em; } .footer-text { overflow: hidden; white-space: nowrap; } .footer-actions { float: right; padding-left: 1em; } .layout { background: url("../img/admin/content-left-bg.png") repeat-y left top #ededed; min-height: 100%; margin-bottom: -30px; overflow: hidden; } .login { background: #ededed; background: radial-gradient(circle, #fafafa, #bdbdbd); padding-top: 6%; box-sizing: border-box; } .layout-two-coll { padding-bottom: 30px; } .coll-left { float: left; padding-bottom: 30px; } .layout-two-coll { margin-left: 210px; } .layout-two-coll:after { content: "."; visibility: hidden; display: block; height: 0; clear: both; } .coll-left { margin-left: -210px; width: 210px; } .coll-right { background: url("../img/admin/content-bg.png") repeat-x top left #ededed; float: right; width: 100%; } .spacer-second { height: 6px; } .spacer-first { display: none; } .coll-right .spacer-second { background: #9c9c9c; } .coll-left .spacer-second { background: #545454; border-right: 10px solid #9c9c9c; } .coll-right .spacer-first { background: #bdbdbd; } .coll-left .spacer-first { background: #8c8c8c; border-right: 10px solid #bdbdbd; } .collapsed .layout { background-image: url("../img/admin/collapsed-content-left-bg.png"); } .collapsed .layout-two-coll { margin-left: 50px; } .collapsed .coll-left { margin-left: -50px; width: 50px; } .collapsed .admin-menu-collapsed { display: block; } .collapsed .admin-menu { display: none; } .content { margin: 0 2em; padding: 1em 0; } .copyright { color: #919191; text-align: center; font-size: 70%; } .admin-warnings ul { margin-bottom: 1em; background: #f3dcdc; color: #ba2727; } .admin-warnings ul li { margin-left: 0px; padding: 0.5em 1em; list-style: none; text-align: left; } .admin-warnings ul strong { color: #ba2727; } .admin-notice ul { margin-bottom: 1em; background: #d3dce3; color: #313131; } .admin-notice ul li { margin-left: 0px; padding: 0.5em 1em; list-style: none; text-align: left; } .admin-notice ul strong { color: #313131; } ul.list { margin-bottom: 1em; margin-left: 2em; } ul.list li { list-style-type: disc; } /* END Layout */ /* Helpers */ .clear { clear: both; } .align-right { text-align: right; } .align-center { text-align: center; } .align-left { text-align: left; } .helper-corner-left { -moz-border-radius: 3px 0 0 0; -webkit-border-radius: 3px 0 0 0; border-radius: 3px 0 0 0; } .helper-corner-right { -moz-border-radius: 0 3px 0 0; -webkit-border-radius: 0 3px 0 0; border-radius: 0 3px 0 0; } /* END Helpers */ /* Pagination */ .am-pagination { clear: both; font-size: 100%; padding: 0.5em 0; margin: 0.5em 0; } .am-pagination a { text-decoration: none; border: solid 1px #91aabd; color: #5e6e7a; background: #d3dce3; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; text-shadow: 0 -1px 1px #fff; } .am-pagination a, .am-pagination span { padding: 0.3em 0.6em; margin-right: 5px; margin-bottom: 5px; font-weight: bold; } .am-pagination .am-pagination-current { background: #8fabbd; color: #fff; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: solid 1px #91aabd; text-shadow: 0 -1px 1px #596d7d; } .am-pagination .am-pagination-current.am-pagination-prev, .am-pagination .am-pagination-current.am-pagination-next { color: #afb5ba; border-color: #cad3db; background: #e3e6e8; text-shadow: none; } /* Grid */ .check-all-offer { background-color: #ffc; padding: 0.5em; border: 1px solid white; border-bottom: none; } .filter-wrap { color: #333; background: #dbdbdb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; padding: 0.5em; text-align: right; margin-bottom: 1em; box-shadow: 0 1px 0 #b0b0b0; overflow: hidden; } .filter-wrap .filter-title { float: right; margin-right: 1em; line-height: 2em; } .filter-wrap .filter-inputs { float: right; margin-right: 0.5em; text-align: left; } .filter-wrap .filter-button { float: right; text-align: left; } .filter-wrap form.filter input[type=text] { background-image: url("../img/icons/magnify.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 25px; } .filter-wrap form.filter input[type=text].datepicker { background-image: url("../img/icons/calendar.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 25px; } .group-wrap, .norecord-actions { margin-bottom: 1em; } .group-wrap .link, .norecord-actions .link { display: inline-block; margin: 0.4em 1em; } .grid-total { padding: .5em; text-align: right; } .grid-container { border: 1px solid #a1a1a1; box-shadow: 0 2px 4px #d6d6d6; margin-bottom: 1em; overflow-x: auto; } .grid { width: 100%; } .grid tr.grid-row { border-bottom: 1px solid #ddd; } .grid tr.grid-row.expanded, .grid tr.grid-row.even, .grid tr.grid-row.odd { border-bottom: none; } .grid tr.grid-row.odd td { background-color: #d3dce3; } .grid tr.grid-row.odd td.sorted { background-color: #bed4e2; } .grid tr.grid-row.selected { background: #ffc; } .grid tr.grid-row.selected td { background: none !important; border-bottom: 1px solid #e5e5e5; } .grid tr.grid-row.emphase { background-color: #ffc; } .grid tr.grid-row.emphase td { background: none !important; } .grid tr.grid-row > td { padding: .8em .5em; vertical-align: top; } .grid tr.grid-row > td.break { word-break: break-word; word-wrap: break-word; } .grid th { padding: 0.5em; border: 1px solid white; background: url("../img/admin/grid-header-bg.png") repeat-x top left; color: white; text-shadow: 0 -1px 1px #1e2e3b; } .grid th a { padding-right: 20px; display: block; color: white; text-decoration: none; text-shadow: 0 -1px 1px #1e2e3b; background: url("../img/admin/grid-sortable.png") no-repeat right center; } .grid th a.sorted-asc { background: url("../img/admin/grid-asc.png") no-repeat right center; } .grid th a.sorted-desc { background: url("../img/admin/grid-desc.png") no-repeat right center; } .grid tr.grid-row > td { background: #ededed; } .grid tr.grid-row > td.sorted { background: #d9e6ee; } .grid tr.grid-row > td.actions { text-align: center; } .grid tr.grid-row > td.record-sort { background-image: url("../img/admin/grid-sortable.png"); background-repeat: no-repeat; background-position: center center; cursor: move; } .grid tr.grid-row > td.expandable-data { background: #eef; } .grid tr.grid-row > td.expanded { background: #eef !important; border-bottom-color: #eef; } .grid tr.grid-row > td.expandable { cursor: pointer; } .grid tr.grid-row > td.expandable div.arrow { display: inline-block; width: 7px; height: 5px; overflow: hidden; float: right; margin: 0px; padding-left: 10px; background: url("../img/arrow.png") no-repeat right; } .grid tr.grid-row > td.expandable div.placeholder { padding-right: 1em; } .grid .editable { display: inline-block; width: 8px; height: 8px; overflow: hidden; float: right; margin: 0px; padding-left: 10px; background: url("../img/pencil.png") no-repeat right; } .grid .live-edit, .grid .live-select { cursor: pointer; } .grid .disabled { opacity: .75; filter: Alpha(Opacity=75); } .grid th.required { color: #a94442; text-shadow: none; } .grid tr.grid-row:hover > td { background-color: #bed4e2 !important; } .grid tr.grid-row:hover > td.expanded { background-color: #eef !important; } .grid tr.grid-row.expandable-data-row:hover > td { background-color: #eef !important; } .grid tr.grid-row > td.selected { background: #d9e6ee !important; } .grid.grid-no-highlight tr.grid-row:hover > td { background-color: inherit !important; } .grid.grid-no-highlight tr.grid-row.odd > td { background-color: #d3dce3 !important; } .grid.grid-small { font-size: 80%; } .grid-action-export-preset-list { margin: 1em; } .grid-action-export-preset-list .grid-action-export-preset-list-item { padding-bottom: .5em; } .grid-action-export-preset-list .grid-action-export-preset-list-item:hover .grid-action-export-preset-list-action { display: inline; } .grid-action-export-preset-list .grid-action-export-preset-list-action { display: none; } .grid-action-export-preset-list .grid-action-export-preset-list-action a, .grid-action-export-preset-list .grid-action-export-preset-list-action a:visited { color: #BA2727; } /* END Grid */ /* Form*/ .am-form { margin-bottom: 1em; /* support for form elements without the label */ /* support for wide elements */ } .am-form input, .am-form textarea, .am-form select, .am-form button { line-height: 1em; height: auto; display: inline-block; } .am-form form { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: 1px solid #ddd; border-top: 2px solid #d0d0d0; box-shadow: 0 1px 1px -1px #b0b0b0; background: #fff; margin: 0; padding: 0; text-align: left; } .am-form fieldset { display: block; border: none; padding: 0; margin: 0; } .am-form fieldset legend { width: 100%; display: block; margin: 0; padding: 0.5em 0; font-family: Arial; font-size: 120%; color: #333; white-space: nowrap; background: #f1f1f1; border-bottom: 1px solid #d5d5d5; text-indent: 1em; } .am-form fieldset.am-adv-fieldset > legend { cursor: pointer; color: #34536e; } .am-form fieldset.am-adv-fieldset > legend .am-adv-fieldset-lable { position: relative; } .am-form fieldset.am-adv-fieldset > legend .am-adv-fieldset-lable:after { border-bottom: 1px #9aa9b3 dashed; content: ''; height: 0; left: 0; right: 0; bottom: 1px; position: absolute; } .am-form fieldset.am-adv-fieldset-closed > legend .am-adv-fieldset-lable { font-weight: bold; } .am-form .row:first-child .element-title:first-child { -moz-border-radius: 3px 3px 0 0; -webkit-border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0; } .am-form .row.disabled { opacity: .5; } .am-form .row.row-highlight { background: #ffe; } .am-form div.reqnote { clear: both; font-size: 80%; margin: 0.5em 0 0 1em; } .am-form div.row { border-bottom: 1px solid #ededed; margin: 0; } .am-form div.element-title { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: .5em 1em; background-color: #f9f9f9; } @media all and (min-width: 500px) { .am-form div.element-title { background-color: transparent; width: 35%; float: left; text-align: right; padding: 1em 0.5em 1em 1em; } } .am-form div.element-title label { font-weight: bold; color: #555; } .am-form div.element-title .comment, .am-form div.element-title .comment strong, .am-form div.element-title .comment b { color: #777; } .am-form div.element { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; padding: .5em 1em; } @media all and (min-width: 500px) { .am-form div.element { margin-left: 35%; padding: 1em 1em 1em 0.5em; } } @media all and (max-width: 500px) { .am-form div.element input[type=text], .am-form div.element input[type=password], .am-form div.element input[type=submit], .am-form div.element textarea, .am-form div.element select { box-sizing: border-box; width: 100%; margin-bottom: 0.2em; } .am-form div.element input.el-short { width: auto; } } .am-form div.row.no-label .element { margin: 0; padding: 1em 1em; } .am-form div.row.no-label div.element-title { width: 0; display: none; } .am-form div.row.row-wide .element { margin: 0; padding: 0.5em 1em; } .am-form div.row.row-wide .element-title { float: none; width: 100%; text-align: left; padding: 0.5em 1em; } .am-form textarea { overflow: auto; } .am-form input[type=text], .am-form input[type=password], .am-form select, .am-form textarea { padding: 0.5em; } .am-form span.error, .am-form span.required { color: #a94442; } .am-form span.error { display: block; } .am-form input.error, .am-form textarea.error, .am-form select.error { border: 1px solid #a94442; } .am-form select { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; max-width: 100%; } .am-form span.mceEditor { display: block; } input.datepicker, input[type=text].datepicker { background-image: url("../img/icons/calendar.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 25px; } .input_datetime { border: 1px solid #c2c2c2; display: inline-block; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .input_datetime input[type=text] { border: none; text-align: center; } .input_datetime .input_datetime-date { border-radius: 3px 0 0 3px; float: left; display: block; } .input_datetime .input_datetime-time { border-radius: 0 3px 3px 0; float: left; display: block; background: #fafafa; } .el-wide { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; width: 100%; } div.row:after { content: "."; visibility: hidden; display: block; height: 0; clear: both; } /* Tabs - user member area menu */ ul.am-tabs { display: block; overflow: hidden; margin: 0 0 1em 0; padding: 0 0.5em 0.5em 0.5em; background: #dbdbdb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; box-shadow: 0 1px 0 #b0b0b0; text-align: left; } ul.am-tabs #menu-member { width: 1em; height: 1.2em; text-indent: 2em; overflow: hidden; background: url("../img/admin/dashboard.png") no-repeat center center; } ul.am-tabs li.active #menu-member, ul.am-tabs #menu-member:hover { background-image: url("../img/admin/dashboard-h.png"); } ul.am-tabs li { display: block; margin: 0 0.5em 0 0; padding: 0; float: left; background: url("../img/admin/tab-bg.png") repeat-x top left #e8e8e8; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; white-space: nowrap; } ul.am-tabs > li { margin-top: 0.5em; } ul.am-tabs a { display: block; box-sizing: content-box; margin: 0; height: 1.2em; line-height: 1.2em; padding: 0.5em 1em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border: 1px solid #ccc; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; text-decoration: none; } ul.am-tabs li.active > a, ul.am-tabs li.normal > a:hover { background: url("../img/admin/tab-hover-bg.png") repeat-x top left #e34b3d; border-color: #c7665b; color: white; text-shadow: 0 -1px 1px #c43d33; } ul.am-tabs li.active, ul.am-tabs li.normal:hover { background: url("../img/admin/tab-hover-bg.png") repeat-x top left #e34b3d; } ul.am-tabs ul { display: none; position: absolute; margin: 0; padding: 0; z-index: 5; } ul.am-tabs ul li { float: none; } ul.am-tabs li:hover > ul { display: block; } ul.am-tabs span.arrow { display: inline-block; position: relative; width: 7px; height: 5px; margin: 0 0 2px 5px; padding: 0; overflow: hidden; z-index: 15; background: url("../img/admin/arrow.png") no-repeat left; } ul.am-tabs a:hover span.arrow, ul.am-tabs li.active span.arrow { background-image: url("../img/admin/arrow-white.png"); } ul.am-tabs .has-children > ul { background: url("../img/admin/tab-bg.png") repeat-x top left #e8e8e8; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; border-top-left-radius: 0; border: 1px solid #ccc; min-width: 150px; overflow: hidden; } ul.am-tabs .has-children > ul > li { margin: 0; } ul.am-tabs .has-children > ul a { -webkit-border-radius: 0; border-radius: 0; border: none; background: none; } ul.am-tabs .has-children ul li { border-radius: 0; background: none; } ul.am-tabs .has-children > ul li.active { background-image: url("../img/admin/tab-hover-bg.png"); background-color: #e34b3d; } ul.am-tabs .has-children > a:hover { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } ul.am-tabs li.expanded > a { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } /* END Tabs */ /* Common Form Elements */ a.button { display: inline-block; text-decoration: none; } a.button, input[type=button], input[type=submit] { background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; padding: 0.5em 1.2em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } a.button:hover, a.button.active, input[type=button]:hover, input[type=submit]:hover, input[type=button].active, input[type=submit].active { cursor: pointer; border-color: #c7665b; background-image: url("../img/admin/form-button-hover-bg.png"); background-color: #e34b3d; color: white; text-shadow: 0 1px 1px #c43d33; } input[type=button]:active, input[type=submit]:active { cursor: pointer; background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; padding: 0.5em 1.2em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } input[type=button]:disabled, input[type=submit]:disabled { color: #ccc; border: 1px solid #ccc; background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; text-shadow: none; } input:disabled, input[readonly], input[type=text][readonly]:focus { background: #e8e8e8; border: 1px solid #ccc; color: #ccc; box-shadow: none; } select, textarea, input[type=text], input[type=password] { padding: 0.5em; border: 1px solid #c2c2c2; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } button:focus, textarea:focus, select:focus, input:focus { outline: none; } textarea:focus, input[type=text]:focus, input[type=password]:focus { background-color: #ffffcf; border-color: #51a7e8; box-shadow: 0 0 2px #51a7e8; } select:focus { border-color: #51a7e8; box-shadow: 0 0 2px #51a7e8; } textarea.error, input.error { background-color: #fce6e6; border: 1px solid #a94442; } /* END Common Form Elements */ .lookup-block { display: inline-block; margin: 0 0 0 2em; float: right; } @media all and (max-width: 600px) { .lookup-block { display: none; } } .lookup-block .ui-autocomplete { border-radius: 0; } .lookup-block .ui-autocomplete li.ui-menu-item { padding: .4em .4em 0; } .lookup-block .ui-autocomplete li.ui-menu-item a { padding: 0; position: relative; display: inline-block; white-space: nowrap; cursor: pointer; color: #34536e; } .lookup-block .ui-autocomplete li.ui-menu-item a.ui-state-focus { color: #34536e; background: none; border: none; margin: 0; } .lookup-block .ui-autocomplete li.ui-menu-item a:after { border-bottom: 1px #9aa9b3 solid; content: ''; height: 0; left: 0; right: 0; bottom: 1px; position: absolute; } .lookup-block .ui-autocomplete li.ui-menu-item a:hover:after { opacity: 0; } .input-lookup { overflow: hidden; line-height: normal; width: 125px; border: 1px solid #c2c2c2; -moz-border-radius: 10px 10px 10px 10px; -webkit-border-radius: 10px 10px 10px 10px; border-radius: 10px 10px 10px 10px; background: #e8e8e8; transition: width .4s, border-radius .4s; } .input-lookup .input-lookup-button { margin: 0; padding: 0.2em 1em; float: right; background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: none; border-left: 1px solid #ccc; -moz-border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; display: none; } .input-lookup .input-lookup-button:active { margin: 0; padding: 0.2em 1em; -moz-border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; border: none; border-left: 1px solid #c7665b; background: url("../img/admin/form-button-hover-bg.png") repeat-x top left #e34b3d; color: white; text-shadow: 0 1px 1px #c43d33; } .input-lookup.hover { border-color: #c7665b; } .input-lookup.state-open { background: white; width: 250px; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .input-lookup.state-open.state-has-value .input-lookup-button { display: block; } .input-lookup.state-open.state-has-value .input-lookup-empty { display: block; } .input-lookup.state-open input[type=text].lookup { cursor: text; background: white; text-align: left; padding-left: 0; } .input-lookup.state-open .input-lookup-input-inner-wrapper { padding-right: 20px; } .input-lookup-input-inner-wrapper { position: relative; } .input-lookup-input { padding: 0.2em; overflow: hidden; } .input-lookup-input .input-lookup-empty { position: absolute; top: 0; right: 0; width: 20px; cursor: pointer; opacity: .3; background: url("../img/icons/decline-d.png") no-repeat center center transparent; display: none; } .input-lookup-input .input-lookup-empty:hover { opacity: 1; background-image: url("../img/icons/decline.png"); } .input-lookup-input input[type=text].lookup { cursor: pointer; margin: 0; padding: 0; border: none; width: 100%; text-align: center; box-sizing: border-box; background-color: #e8e8e8; background-image: url("../img/icons/magnify.png"); background-repeat: no-repeat; background-position: left center; padding-left: 20px; } .input-lookup-input input[type=text].lookup:focus { outline: 0; border: none; box-shadow: none; } /* Menu */ .menu-collapse, .menu-expand { overflow: hidden; } .menu-collapse a, .menu-expand a { display: inline-block; margin-left: 10px; padding: 0.5em 0.5em 0.5em 30px; color: #2e2e2e; text-decoration: none; white-space: nowrap; } .menu-collapse a { background: url("../img/admin/menu-c.png") no-repeat left center; } .menu-expand a { background: url("../img/admin/menu-e.png") no-repeat left center; } .menu-wrapper, .menu-collapse-wrapper { padding-right: 10px; background: url("../img/admin/content-left-bg.png") repeat-y top right; } .admin-menu-item-alert { border-radius: 1.2em; margin-left: 1em; min-width: 1.2em; height: 1.2em; line-height: 1.2em; padding: 0.2em; font-size: 70%; background: #ffe; display: inline-block; text-align: center; color: #333; } ul.admin-menu { text-align: left; background-color: #eef; position: relative; background-image: url("../img/admin/menu-bottom-line.png"); background-repeat: no-repeat; background-position: right bottom; padding-bottom: 1px; } ul.admin-menu a { display: block; padding: 0.5em 0.5em 0.5em 40px; overflow: hidden; color: white; text-shadow: 0 -1px 1px #1f3240; text-decoration: none; white-space: nowrap; text-overflow: ellipsis; } ul.admin-menu li a.bold { /* outlined menu items */ font-weight: bold; } ul.admin-menu > li { background: url("../img/admin/menu-bg.png") repeat-x top left; overflow: hidden; } ul.admin-menu > li.active { background: url("../img/admin/menu-bg-active.png") repeat-x top left; } ul.admin-menu ul li { background: #8fabbd; } ul.admin-menu ul a { color: #244357; border-bottom: 1px solid #85a1b4; text-shadow: none; } ul.admin-menu ul li.active { background: url("../img/admin/menu-subitem-bg-active.png") repeat-x top left; } ul.admin-menu ul li.active a { border-right: none; background: url("../img/admin/menu-subitem-arrow.png") no-repeat right center; } ul.admin-menu > li.opened a.folder { background-image: url("../img/admin/menu-u.png"); background-repeat: no-repeat; background-position: right center; } ul.admin-menu > li.active.opened a.folder { background-image: url("../img/admin/menu-active-u.png"); } ul.admin-menu > li.closed a.folder { background-image: url("../img/admin/menu-d.png"); background-repeat: no-repeat; background-position: right center; } ul.admin-menu > li.active.closed a.folder { background-image: url("../img/admin/menu-active-d.png"); } .menu-glyph { background-image: url("../img/sprite/icon.png"); background-repeat: no-repeat; background-position: left center; } ul.admin-menu .menu-glyph-delimeter { background-image: url("../img/admin/menu-glyph-delimeter.png"); background-repeat: no-repeat; background-position: 32px center; } li.active .menu-glyph-delimeter { background-image: url("../img/admin/menu-glyph-delimeter-active.png"); } ul.admin-menu-collapsed { display: none; position: relative; padding-bottom: 1px; background-color: #eef; background-image: url("../img/admin/collapsed-menu-bottom-line.png"); background-repeat: no-repeat; background-position: right bottom; text-align: left; } ul.admin-menu-collapsed .menu-glyph-delimeter { padding-left: 0.5em; background-image: url("../img/admin/menu-glyph-delimeter-active.png"); background-repeat: no-repeat; background-position: left center; } ul.admin-menu-collapsed a { display: block; padding: 0.5em; overflow: hidden; color: white; text-decoration: none; text-shadow: 0 -1px 1px #1f3240; } ul.admin-menu-collapsed > li { position: relative; background: url("../img/admin/menu-bg.png") repeat-x top left; } ul.admin-menu-collapsed > li.active { background: url("../img/admin/menu-bg-active.png") repeat-x top left; } ul.admin-menu-collapsed > li.active > div > a { border-right: none; } ul.admin-menu-collapsed ul { display: none; position: absolute; left: 40px; top: 0; z-index: 1000; } ul.admin-menu-collapsed ul a { padding-left: 10px; } ul.admin-menu-collapsed ul li.caption { padding: 0.5em 0.5em 0.5em 0; overflow: hidden; background: url("../img/admin/menu-bg-active.png") repeat-x top left; color: white; text-shadow: 0 -1px 1px #1f3240; } ul.admin-menu-collapsed ul li { background: #8fabbd; white-space: nowrap; } ul.admin-menu-collapsed ul a { border-bottom: 1px solid #85a1b4; color: #244357; text-shadow: none; } ul.admin-menu-collapsed li a.bold { /* outlined menu items */ font-weight: bold; } /* END Menu */ /* Form Login */ .form-login-wrapper { padding: 5em 0 1em 0; width: 100%; text-align: center; } .form-send-pass-info { padding: .5em .5em 1em; } .form-login { display: inline-block; width: 100%; max-width: 350px; } .form-login form { border: 1px solid #546E7A; box-shadow: 0 0 10px #aaa; border-width: 2px 1px 1px; background: #f9f9f9; padding-bottom: .8em; } .form-login fieldset legend { text-align: center; border-bottom: none; padding: .8em 0; background: #eceff1; color: #546e7a; } .form-login input[name=login], .form-login input[name=am_admin_login] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background-image: url("../img/icons/users.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 30px; width: 100%; } .form-login input[name=am_admin_passwd] { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background-image: url("../img/icons/key.png"); background-repeat: no-repeat; background-position: 5px center; padding-left: 30px; width: 100%; } .form-login input[name=login], .form-login input[name=am_admin_login], .form-login input[name=am_admin_passwd] { line-height: 1.5em; border-radius: 0; } .form-login input[type=submit] { line-height: 1.5em; } .form-login div.element-title label { line-height: 1em; font-weight: normal; } .form-login div.element, .form-login div.element-title { padding-bottom: .5em; } @media all and (min-width: 500px) { .form-login div.element-title label { line-height: 2em; } } .form-login div.row { border-bottom: none; } .form-login div.row { border: none; } @media all and (min-width: 500px) { .form-login div.row { padding-top: .5em; } } /* END Form Login */ /* Storage Filter */ .input-storage-filter-wrapper { overflow: hidden; padding: 0.4em; border: 1px solid #C2C2C2; border-radius: 0px; margin-bottom: .2em; background: white; } .input-storage-filter-inner-wrapper { position: relative; padding-right: 15px; } .input-storage-filter-empty { position: absolute; top: 0; right: 0; width: 20px; cursor: pointer; opacity: .3; background: url("../img/icons/decline-d.png") no-repeat center center transparent; display: none; } .input-storage-filter-empty:hover { opacity: 1; background-image: url("../img/icons/decline.png"); } input[type=text].input-storage-filter { padding: 0; margin: 0; border: none; width: 100%; } input[type=text].input-storage-filter:focus { border: none; box-shadow: none; } input[type=text].input-storage-filter:focus { border: none; outline: 0; background: none; } /* END Storage Filter */ /* Options Editor Form Element */ .options-editor { padding: 0.4em; border: 1px solid #c2c2c2; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; display: inline-block; } .options-editor div.editable { display: inline-block; width: 8px; height: 8px; overflow: hidden; float: right; margin: 0px; padding-left: 10px; background: url("../img/pencil.png") no-repeat right; } .options-editor table td { padding: 0.5em; vertical-align: middle; } .options-editor table th { padding: 0.5em; vertical-align: middle; font-weight: bold; background: #f1f1f1; color: #555; } .options-editor table a { text-decoration: none; } .options-editor input, .options-editor input[type=checkbox] { margin: 0; } .options-editor tr > td:first-child { padding-left: 10px; } .options-editor tr.option { border-bottom: 1px dashed #ccc; } .options-editor tr.option > td:first-child { background: url("../img/sortable.png") no-repeat left center; } /* END Options Editor Form Element */ /* Setup Menu */ .notebook-wrapper { margin-bottom: 1em; color: #333; background: #dbdbdb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; box-shadow: 0 1px 1px #b0b0b0; padding: 0.5em 0 0 0.5em; } .notebook { width: 100%; } .notebook a { display: block; padding: 0.5em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; text-decoration: none; } .notebook td { background: none; text-align: center; padding-bottom: 0.5em; } .notebook td a { margin-right: 0.5em; } .notebook td.notsel a { background: url("../img/admin/tab-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } .notebook td.notsel a:hover { border: 1px solid #c7665b; background-image: url("../img/admin/tab-hover-bg.png"); background-position: left top; background-repeat: repeat-x; background-color: #e34b3d; color: white; text-shadow: 0 -1px 1px #c43d33; } .notebook td.sel a { border: 1px solid #c7665b; background-image: url("../img/admin/tab-hover-bg.png"); background-position: left top; background-repeat: repeat-x; background-color: #e34b3d; color: white; text-shadow: 0 -1px 1px #c43d33; } /* END Setup Menu */ /* Uploader */ .upload-control { display: inline-block; } .upload-control .upload-control-upload { background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; padding: 0.5em 1.2em; -moz-border-radius: 3px 0 0 3px; -webkit-border-radius: 3px 0 0 3px; border-radius: 3px 0 0 3px; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } .upload-control .upload-control-upload.upload-control-reupload { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .upload-control .upload-control-browse { display: inline-block; background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; border-left: none; padding: 0.5em 1.2em; -moz-border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; border-radius: 0 3px 3px 0; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; cursor: pointer; } .upload-control .upload-control-upload.hover, .upload-control .upload-control-browse.hover { border-color: #c7665b; background-image: url("../img/admin/form-button-hover-bg.png"); background-color: #e34b3d; color: white; text-shadow: 0 -1px 1px #c43d33; } .upload-control span.uploading { background: url("../img/ajax-loader-small.gif") no-repeat left center; padding-left: 20px; } .upload-control .upload-control-upload.upload-control-upload-single { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } /* END Uploader */ /* Translations */ .trans-cancel { clear: both; } textarea.text-edit { width: 90%; } textarea.changed { background: #e4ffc9; } /* END Translations */ .widget-quickstart h2 { margin-bottom: 1.5em !important; } .widget-quickstart li { margin-bottom: 0.4em; overflow: hidden; } .widget-quickstart li img { float: left; padding: 0 0.5em 0.5em 0; } .widget-quickstart-content { padding: 1em; background: #ffffcf; border: solid 1px #a1a1a1; text-align: left; color: #454430; box-shadow: 0 2px 4px #d6d6d6; } .widget-quickstart-disable { float: right; padding-left: 2em; } /* Custom input[type=file] element */ .input-file { width: 400px; overflow: hidden; border: 1px solid #c2c2c2; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; text-align: left; } .input-file-input { padding: 0.4em; height: 1em; position: relative; overflow: hidden; } .input-file-button { float: right; background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: none; border-left: 1px solid #ccc; padding: 0.4em 1em; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } .input-file.hover { border-color: #c7665b; } .input-file.hover .input-file-button { border-color: #c7665b; background-image: url("../img/admin/form-button-hover-bg.png"); background-color: #e34b3d; color: white; text-shadow: 0 -1px 1px #c43d33; } /* END Custom input[type=file] element */ .dashboard { overflow: hidden; } @media all and (min-width: 1100px) { .dashboard .main { margin-right: 500px; padding-right: 1em; } } @media all and (min-width: 1100px) { .dashboard .aside { float: right; width: 500px; } } .dashboard .bottom, .dashboard .top { clear: both; } .dashboard-customize .connectedSortable { border: 1px #244357 dashed; padding-bottom: 50px; margin-bottom: 1em; } .dashboard.dashboard-customize .aside { width: 520px; } .dashboard.dashboard-customize .main { margin-right: 520px; } .dashboard-customize-link-wrapper { overflow: hidden; margin-bottom: 0.4em; } .dashboard-customize-link { float: right; } .container-width-narrow-show { display: none; } .container-width-narrow-hide { display: table-cell; } .container-width-narrow .container-width-narrow-hide { display: none; } .container-width-narrow .container-width-narrow-show { display: table-cell; } div.admin-last div.grid-container { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .widget-ui { border: 2px #8fabbd solid; z-index: 2000; margin-bottom: 0.5em; } .widget-ui-manage { background: url("../img/admin/menu-bg.png") repeat-x top left; color: white; padding: 0.5em 6px; cursor: move; text-shadow: 0 -1px 1px #1f3240; } .widget-ui-conteiner { background: #ededed; position: relative; } .widget-ui-conteiner .widget-ui-content { opacity: .35; filter: Alpha(Opacity=35); padding: 0.5em 6px; } .widget-ui .widget-link { float: right; margin-left: 0.5em; } .widget { margin-bottom: 0.5em; } .widget h2 { margin-bottom: 0.2em; font-weight: normal; } .widget .widget-title-info { color: #c2c2c2; font-size: 1rem; } .widget .grid-container { overflow: hidden; } .widget .grid th { border: none; background: #d3dce3; color: inherit; text-shadow: none; } .widget .grid tr.grid-row > td { border: none; padding: .8em .5em; } .widget .widget-nodata { text-align: center; padding: 2em; background: #e6e6e6; font-size: 1.1rem; } .admin-index-report-wrapper { border: solid 1px #a1a1a1; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; box-shadow: 0 2px 4px #d6d6d6; margin-bottom: 1em; } .admin-index-report { border: solid 1px white; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; overflow: hidden; } .admin-dashboard-wrapper { border: solid 1px #a1a1a1; margin-bottom: 1em; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .admin-dashboard { border-collapse: separate; /* to make radius working */ width: 100%; border: solid 1px white; box-shadow: 0 2px 4px #d6d6d6; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .admin-dashboard td { vertical-align: top; padding: 10px; width: 50%; } .admin-dashboard td.first { border-right: solid 1px white; } .admin-dashboard dl { overflow: hidden; } .admin-dashboard dt { width: 55%; float: left; } .admin-dashboard dd { margin-left: 55%; width: 45%; text-align: right; } .widget-recurring-revenue { border: solid 1px #a1a1a1; box-shadow: 0 2px 4px #d6d6d6; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; padding: 0.5em; background: lightgreen; font-size: 2rem; text-align: center; } ul.widget-top-affiliate { margin: 1em; } ul.widget-top-affiliate li { padding-bottom: 0.2em; } .widget-revenue-goal { border: solid 1px #a1a1a1; box-shadow: 0 2px 4px #d6d6d6; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; font-size: 2rem; } .widget-revenue-goal .progress-bar-conteiner { display: inline-block; width: 100%; color: #333333; background: #dbdbdb; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; text-align: right; } .widget-revenue-goal .progress-bar { position: relative; text-align: left; } .widget-revenue-goal .progress-bar-ontarget .progress-bar-bar { background: lightgreen; } .widget-revenue-goal .progress-bar-bar { z-index: 1; position: absolute; background: #fcbdbd; text-align: center; } .widget-revenue-goal .progress-bar-target-diff { font-size: .8rem; position: absolute; right: 0; bottom: 0; padding: 0.2em; } .widget-revenue-goal .progress-bar-target-diff-positive { color: #488f37; } .widget-revenue-goal .progress-bar-target-diff-negative { color: #BA2727; } .widget-revenue-goal .progress-bar-title { z-index: 2; position: absolute; text-align: center; width: 100%; } .widget-revenue-goal .progress-bar-target { background: white; } .widget-revenue-goal .progress-bar-target .progress-bar-target-bar { height: 2px; background: black; } .widget-label { padding: 0 4px; font-size: 8px; line-height: 9px; text-transform: uppercase; border-radius: 5px; } .widget-label_today { background: #ffffcf; } .widget-label_yesterday { background: #daebd5; } .admin-activity .grid-container { border-left: none; } .admin-activity .admin-activity_event { border-left: 2px solid #a1a1a1; } .admin-activity .admin-activity_event-time { color: #aaa; font-size: 80%; } .admin-activity .admin-activity_event-extra { color: #aaa; } .admin-activity .admin-activity_event-payment { border-left: 2px solid #488f37; } .admin-activity .admin-activity_event-refund { border-left: 2px solid #BA2727; } .admin-activity .admin-activity_payment-amount { font-size: 120%; font-weight: normal; } .admin-activity .admin-activity_payment-amount-sign { color: #488f37; } .admin-activity .admin-activity_refund-amount { font-size: 120%; font-weight: normal; } .admin-activity .admin-activity_refund-amount-sign { color: #BA2727; } .admin-activity .admin-activity_user_note-preview { color: #aaa; } .import-preview { width: 100%; margin: 0; } .import-table-wrapper { overflow: scroll; width: 100%; border: 1px solid #a1a1a1; box-shadow: 0 4px 8px #d6d6d6; clear: both; margin-bottom: 1em; } .import-area { display: inline-block; text-align: center; width: 100%; } /* CKEditor Customiztion */ .cke_button_label.cke_button__createplaceholder_label { display: inline; } /* JQuery UI customization */ .ui-widget { font-size: 13px !important; font-family: Tahoma, Arial, san-serif !important; } .ui-widget-content { color: #313131 !important; } .ui-widget-content a, .ui-widget-content a:visited { color: #34536e; } .ui-autocomplete-loading { background: white url("../js/jquery/images/ui-anim_basic_16x16.gif") right center no-repeat; } button.ui-button.ui-button-text-only { padding: 0.5em 1.2em; font-weight: normal; } button.ui-button.ui-button-text-only .ui-button-text { padding: 0; } button.ui-button.ui-button-text-only.ui-state-default { background: url("../img/admin/form-button-bg.png") repeat-x top left #e8e8e8; border: 1px solid #ccc; color: #555960; text-shadow: 0 -1px 1px #c7c8c9; } button.ui-button.ui-button-text-only.ui-state-hover { border-color: #c7665b; background-image: url("../img/admin/form-button-hover-bg.png"); background-color: #e34b3d; color: white; text-shadow: 0 -1px 1px #c43d33; } .ui-dialog { padding: 0.5em; border: solid 3px #545454; background: #eee; } .ui-dialog .ui-dialog-content { padding: 0; } .ui-dialog .ui-dialog-titlebar { margin: -0.5em -0.5em 0.5em; background: #dbdbdb; border: none; border-radius: 0; padding: 1em; } .ui-dialog .ui-dialog-titlebar .ui-dialog-title { color: #484848; } .ui-dialog .ui-dialog-titlebar .ui-icon-closethick { background-image: url("../img/admin/modal-close.png"); background-position: center; } .ui-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close { border: none; background: none; border-radius: 0; } .ui-dialog .ui-dialog-buttonpane { margin: 0.5em -0.5em -0.5em; padding: 0; } .ui-datepicker-title select { padding: 0.2em; -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; } /* END JQuery UI customization */ .glyph { display: inline-block; background-repeat: no-repeat; background-position: left center; } .sprite-icon { width: 16px; height: 16px; background-image: url("../img/sprite/icon.png"); } .sprite-flag { width: 16px; height: 11px; background-image: url("../img/sprite/flag.png"); } #mask { z-index: 100; position: fixed; top: 0; left: 0; opacity: .50; filter: alpha(opacity=50); background-color: #CCC; width: 100%; height: 100%; zoom: 1; } #flash-message { color: black; top: 10px; right: 10px; padding: 1px; position: fixed; z-index: 1000; } #flash-message div { margin-bottom: 0.2em; padding: 1em; width: 350px; background: #ffffcf; border: solid 3px #545454; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; color: #454430; } #flash-message .message { color: black; } #flash-message .error { color: #ba2727; font-weight: bold; } #advanced-search { transition: top 0.5s ease; } .popup-wide { text-align: left; width: 612px; float: right; } .popup-wide a { color: white; } .popup-wide .popup-top-arrow { height: 32px; background: url("../img/admin/popup-wide-top-arrow.png") no-repeat left bottom; } .popup-wide .popup-top { background: url("../img/admin/popup-wide-top.png") no-repeat left bottom; height: 32px; } .popup-wide .popup-content { padding: 0 2em; overflow: hidden; background: url("../img/admin/popup-wide-content.png") repeat-y left top; color: white; } .popup-wide .popup-bottom { height: 18px; background: url("../img/admin/popup-wide-bottom.png") no-repeat left top; } .popup { width: 412px; float: right; text-align: left; } .popup a { color: white; } .popup .popup-top-arrow { height: 32px; background: url("../img/admin/popup-top-arrow.png") no-repeat left bottom; } .popup .popup-top { height: 32px; background: url("../img/admin/popup-top.png") no-repeat left bottom; } .popup .popup-content { padding: 0 2em; overflow: hidden; background: url("../img/admin/popup-content.png") repeat-y left top; color: white; } .popup .popup-bottom { height: 18px; background: url("../img/admin/popup-bottom.png") no-repeat left top; } .popup select { margin-right: 10px; padding-top: 0.2em; padding-bottom: 0.2em; font-size: 10px; } .search-fields { margin: 1em 0 1em; width: 100%; font-size: 11px; } .search-fields input, .search-fields select, .search-fields button { margin-right: 0.5em; font-size: 1em; } .search-fields select { max-width: 200px; } .search-fields td { vertical-align: top; padding: 1em 0.5em 1em 0; font-size: 1em; } .search-fields td.input { overflow: hidden; } .search-fields td.input > div { float: left; } .search-fields td.name { width: 18%; } .search-fields td.action { padding: 1em 0; width: 16px; } .search-fields tr { border-bottom: 1px dashed #ddd; } .popup input[type=submit] { float: right; } #addSearchField { margin-bottom: 10px; } #save-advanced-search input[type="text"] { background-color: #ffc; width: 100%; box-sizing: border-box; } .dir-browser div.path { padding: 0.5em 0; } .user-invoice { margin-bottom: 1em; padding: 1px; border: 1px solid #a1a1a1; box-shadow: 0 4px 8px #d6d6d6; backgroud: white; } .user-invoice .expand-details { margin-right: 1em; padding-left: 15px; display: inline-block; float: left; background: url("../img/admin/arrow-d.png") no-repeat left center; } .user-invoice .expand-details.open { background-image: url("../img/admin/arrow-u.png"); } .user-invoice-actions { width: 20em; float: right; text-align: right; } .user-invoice-pending { opacity: .75; } .user-invoice-open.user-invoice-pending { opacity: 1; } .user-invoice-header { padding: 0.5em; background-color: #ededed; font-weight: normal; } .user-invoice-record { padding: 0.5em; overflow: hidden; background-color: #f0f0f0; } .pending-invoices { margin-bottom: 1em; } .user-invoice-record-details { overflow: hidden; } .user-invoice-record-details .user-invoice-record-details-products { margin-bottom: 0.2em; width: 45%; float: left; } .user-invoice-record-details .user-invoice-record-details-payments { margin-bottom: 0.2em; width: 45%; float: right; } .user-invoice-record-details .user-invoice-record-details-commissions { clear: both; } .user-access-title { margin-bottom: 1em; } tr.grid-row.user-access-form { border-bottom: none; } tr.grid-row.user-access-form td { background: #bfd3e0; border-color: #bfd3e0; } .access-status-expired { font-style: italic; } .access-status-active { font-weight: bold; color: #555; } .access-status-future { font-style: italic; font-weight: bold; color: #555; } .user-status-pending { font-style: italic; } .user-status-expired { font-style: italic; color: #BA2727; } .user-status-active { font-weight: bold; color: #555; } .user-status-future { font-style: italic; font-weight: bold; color: #555; } .user-status-refunded { color: #BA2727; } div.errors ul { margin-bottom: 1em; background: #fcbdbd; border: 1px solid #faa7a7; color: #ba2727; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } ul.error, ul.errors { background: #fcbdbd; border: 1px solid #faa7a7; color: #ba2727; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 1em; } div.errors ul li { margin-left: 0px; padding: 0.5em 1em; list-style: none; text-align: left; } ul.error li, ul.errors li { margin-left: 0px; padding: 0.5em 1em; list-style: none; text-align: left; } span.error { color: #ba2727; } .tree-nodes { display: inline-block; margin-bottom: 1em; text-align: left; } .tree-nodes > li { font-size: 120%; } .tree-nodes ul { margin-left: 1em; } .tree-nodes li > div { padding: 0.4em; overflow: hidden; } .tree-nodes li > div:hover { background: #dfe8f0; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; } .tree-nodes .tree-actions { padding-left: 2em; float: right; } ._grid_ { width: 100%; } /* collpasible list styles. _..._ added by HtmlReg filter so we cannot avoid it */ ._collapsible_ ._head_ { font-weight: bold; padding-left: 20px; background: url("../img/icons/bullet_toggle_plus.png") no-repeat left center; } ._collapsible_ ._more_ { display: none; padding-left: 40px; background-color: #ffe; } ._collapsible_ ._item_._open_ ._head_ { background: url("../img/icons/bullet_toggle_minus.png") no-repeat left center; } ._collapsible_ ._item_._open_ ._more_ { display: block; } /* entire item - title text and .collapsible-more */ /* */ table._logdetail_ { font-size: 8pt; border-collapse: collapse; } div.upgrades-conteiner { background: #ffffcf; border: 1px solid #545454; color: #454430; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; margin-bottom: 1em; padding: 0.5em 1em; overflow: hidden; } div.upgarde-controll { float: right; } div.upgarde-controll a { text-decoration: none; } ul.upgrades { display: none; } ul.upgrades li { padding-bottom: 0.5em; } div.warning_box { background: none repeat scroll 0 0 #ffffcf; border: 1px solid #545454; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; color: #454430; margin-bottom: 1em; overflow: hidden; padding: 0.5em 1em; } div.mail-editor div.mail-editor-element { margin: 1em 0; } .admin-help { font-size: .83em; vertical-align: super; } .admin-help a { text-decoration: none; } .maint-mode-warning { font-family: Helvetica, Arial, serif; width: 100%; height: 2em; font-size: 12pt; font-weight: bold; color: white; background-color: #E34B3D; text-align: center; padding-top: 1em; } .maint-mode-warning a { color: white; } .disabled-text { color: #777; font-style: italic; } .player-config div { padding: 0.2em 0.4em; display: none; } .magicselect-item-sortable { padding-left: 10px; background: url("../img/sortable.png") no-repeat left center; } .am-sortable-list { overflow-y: auto; max-height: 20em; } .am-sortable-list .am-sortable-list-item { background: url("../img/sortable.png") no-repeat scroll left center transparent; padding: 2px; padding-left: 10px; margin: 3px; width: 50%; } .live-edit-placeholder { font-style: italic; color: #aaa; } .acbp_left, .acbp_right { height: 25px; float: left; margin: 5px 0; } .acbp_left { width: 30%; } .acbp_right { width: 60%; } .am-form div.am-element-recaptcha { margin-left: 0; text-align: center; padding: 1em; } .am-form div.am-element-recaptcha > div { display: inline-block; } .billing-plan-wrap legend { cursor: move; } .morris-hover { position: absolute; z-index: 1000; } .morris-hover.morris-default-style { border-radius: 10px; padding: 6px; color: #666; background: rgba(255, 255, 255, 0.8); border: solid 2px rgba(230, 230, 230, 0.8); font-family: sans-serif; font-size: 12px; text-align: center; } .morris-hover.morris-default-style .morris-hover-row-label { font-weight: bold; margin: 0.25em 0; } .morris-hover.morris-default-style .morris-hover-point { white-space: nowrap; margin: 0.1em 0; } .select2-disabled { color: #bbb; } .plan-title-text { cursor: pointer; } #menu-help{ display: none; visibility: hidden; } /*# sourceMappingURL=admin.css.map */ PK\܏##"default/views/public/img/empty.gifnu[GIF87a,D;PK\Sm vpAg\ƭIDAT8Œka})փL l)Ntqκ8" :Z.SyG"S38U?w]R(vYyy7@ǗkIvQ-)>I YgםNgk@'`4M_)ENG xVgW y[$qFѢ6Vub՜6+Z"2ZoeY'ƘNǀ{X#9\Z>UJwnvFQt 0W7lSj!sR)f1fGDJp "IZ)5)9xpeYRL|_Yf"XN84}'9GvZ=5&pXsUJm؊ ~}Gna+^?̿Hu来IENDB`PK\oJ++#default/views/public/img/play-h.pngnu[PNG  IHDR==baIDATx[{SW#8͖IxHXVSMm:ⴵ/)PNSRgm# "B$ݐsnxdwdΒ{9sݜ ? Q#NGzk&rV'v+y Idڰ5XLb.+ZK aWZ(F!t,ٱ7'N\͓m7&;;^|Y1c?$P܏>w?rt f=oʴ /i"b>A.Ұ?<ȡ㤂Lflꮩ tx`aߣ\SZ2@^!Z޿OXl8 O)&Nfi,th{z 4Ã\(xV˷&n4AN2?J[OZ[폍é8 V35dZbk0۳t:z:.3Yc֐7D  Ò%1[Xě.5-%.ij9s}ϓG~&i{Ihb㵼5&n%XPۢ/19X[{]-j,/ ] 8@c 6f0 MOZ+NrCp m׼L >:t[A}>MtXu@o|5h2^x֠h/8V[HVSђK<+-iP ۠pc+HS٫)z7F\^SM.ehhli&؊~"C_cR9pls6A-+_%NiB(@]z)۠%{gXqYO}D3FMZ^a"vDnD%7G̘q3hQhww羐Vh`˞ ]TUi7mzeit2r6|'sab[c{yX jTXb.NL{ U㴑22eR89{g+-#ɍ}ݨYUBR.Х*+[y'5/&h==XO v7oLjY9rh^#S f#'O G\i]#h~j=mu.A⵭TBE:{FaNdѪ&BIAP~<;Sc/76G7]׳/eqZvVb0UGjz#ص(Hʬ& X 7L(>vm53(R)%3 ʽU99E@9D t*C@>Ls3$ TٯsPHJA1 Lm渡cᆎl9\S3kFt?/sRSJt'+FqU yf?dyC"2&Ѳ@胃]|3Ix&SϿٺV5.,b N ^;~|Nq Rq㨒)FN-u.k2c8N1êl`?x-z5$ţ p)XĚAСIENDB`PK\]lr33(default/views/public/img/sprite/flag.pngnu[PNG  IHDR~ lwô pHYs+ IDATx̝w|uI "* ,wOz5]z׳bWlbE@z&ٝOٝ Ϲnp.w8lԆoL2n&DHiީAc?k :!awpR8:#G4mmmϮ|*tAZxvith`k?B9WQN~Ha[pylF4$]IH t-11 D) Ok_oa --/F.ZJp]P*\?$V@e.[fZgC E糑#M`H8csi_3'AKoHԚԸڞIq&eGV3t1㺚d~8PāA~*$i]e)ڌK^oiYz.[l~|綠xS&,O 7oc$5Rj\-+D\]ޕG31Ir gS>~zr%bQ2;]]äid3z|b[S )ϑ~Yi޻PvKd$СD'fQOMK@Gx (=:K;UO!nJ==5 m~luуk}Z3>,:e>_e)Y n z3tJ8-eZdiL4t} N1޲Uz| 7^`F6\Kbb0Op̮u<~gy .u^{DDPg?Ru m_sR@=ٺA0'$0\z)B.3ҞN^w9= : +:nz.x~ȝ/I<6h̹n nLK@Im*_\ BUpp0t&GS=b"jtK X%nx64VU'[#gn5c ZnWƘRA. ~˖HFsFl2tq|n'棙{VLixI "Z͇P8:_|Ӡ 1\qhAwEo{*,o8 8wj1X`8>hVhB)ʕ֮nΰ k1T‹ { OhY3e WV}=ߙd"ٕ뢒 _,h,vf1aÆ{0 h킖h\v͑+:pg|Ve'~˽Yo#G {I]^kq rVZn؆u3gqsBy:1g"ͳ\5xqPC"~<."ۉ/t=!1]h6$({ߝn<j_EDl{33sgF]=@' >k4¬'QRA9zTkMK[ݶg6n3˫fRpѲZo~m:O%uL8=Th.yl5F^%IK~sulF63 EgrB*:]-q]_gKtF^ 'G۳ލ3y м|OVC E|'jrRR)RH)qM?U?'Lm3|籼wX PZq1|}3,ξe:FDLR?=fʂv|X \AIoV{w?3rdu`Cۏ 1LZ8Fg/36au' ^5@ޚP)525 P^A8:e}`>mNk媌]2 _3t.hx*c Ln0 _SSQBx?kC0qC[@>ԞPi%5(S0bZV~.s_H.{x(:%nemxH,*C#k;sHXDLNzavYU!+VѓΖ^,ڷ ֌.d&)-o2' N _py=O<9zXھ-uoNF #oƓ@p ׯ-?d=m~uO6ٟ>en<9w%\b=_mºaz=osLc-L_6?+ / srEWxwミsv'iS_XOJ\S S!Jsr<=WBޖ1{sQx ‰Gg=!-'бg6J32cF{:(~:(sOzgP_/Wι|[ =5U|GQ&~W9hn}}`Ӂ1p3`֬J۳":K wreA? Bȝo)$oLC4=2NW 4R@Jj1HmH CIa}[&H~C$01d|Ȝƀ4F+0 $X(6Pӧ!ϱ9t4wF|?k֬Y+._s05w煢#fuϯsLl_g : il?ЖA֞ߘWWX@U&`D\oe_(~+'w{[_%:sDwO р6mPIjTm5~]QUEr[CIvvE>;oi=ߟ>{l yv=Yφ+_m:LƊ35(+7褃ʟvo3q{Wۜm|%aqC3>;t%Zk .}l5v6 2@_M"p_&w"Ù6.L<&97wc =Ƕw,mmEΡWtM _ox֪@mNOvuHi3o>ddC$,%+n,N&j^9 ktSY<)ǜK{jlIٍ +x gw0S]KT$ԪgK[/G$}8EPs46rGK޻mi;AsB>`bEhqK,Op/ȷ|B{ NY@E"MvDGsL,ciCMm TofMaaZُaO~cڟcE.o̍ldQ }4s7d3e_y(,JFkVTms&۪_ryG"4!3Cn} &*ƀBos?uC|,>-=e|bٿ߫Kf-v9;05ތ2ډrP>_2|p s%T x<$^?U!zI+5|U/^A Ix?zO8}\ȹ)~<^y57,V&4yυwGh,V*ўz1q}n7:LgV+PA#'OH5]d&[ei<m  h $-z?oK~sXYLExg&5 oeB+A9kBsZs} I ,:.[sQ[ɵtK%L:D v99_,u2}l79¾>dS=fۼk)ݻkPtΩteٮ[MYF8qKsl7wԥ+dz{KgCGZe˲e8p }O>n={7= _/t]RCԬʻJ} pt;N/ tH{g{լnyB9|wL=с;(Ha}04BcMN4=w!o^͍7Hx2f͆Wߝ>oMX%  R8l=D*CPB }n"[HgVa\Dw<[=e!S';GqãW<E.績_rop=Jcl  MG`6 .YE!ן0(ԸBJ+5)̗B!!i26Cc!i nh*7gJ8brV5Ii5} .#q$%Ʊ9 ! S4/: -#8;0BA1hT _z4B(tlh(s?==z| 5E% IL`~xwت,ymݕwA9˗/ϋNYYYxAUYcrz=_G}II$N%ڿ?(lo)b"[]K4u|v눷~LH/w#c9I~ &)[_a(i-%:0o1o%{V폁\͠hp$89X Kf=Os[Yv")0$۫ qmyxDưTDqQĐy582#5_ቼ  ..F a59a |^^$Ć{mH0v;;L|+0D!p\yMx.?yP9c 7P8T{Fɴ]h{Yµmg*TDQ&.muG*T s%?-2/5 UXDaG'}\44"iR߿ EG/ZBEmo$-V ъr  KJ`rx;^k6@1H@5gxt^:FJbu*&bתT񍋻8qf\XħM\8)/:y=7G൥`Q7P<[ G sX64h } ⭞_gbƝ# J4(FBPO;F!Q(%qĊsϫk`8G1B@2^?{f1}zCƏ4a$|~<7_+QN;R~٣!ZPbEW)R1I1C9~* %Q,~gph4J$fW%yȷ\;$hPБ#ߊvj.o8hJS0TSb LM#Gg!G~s@K+K|r|]R?׳I7[J#xVHit?!AC<|@YFz:@ ʻzϔ{BS h ZxUBZJ*̓gLc|i|`[BH_x` mR'3gbn6뛎]wE@?UJ<بTھBτ0nc1q p1A)=?|"O88Dsyδ! wjP(6H#@uD4OGhɥ_̋}wcM#wY;10: 4 tzuq!#=-% &Gw\QhD2fEc_pxЂ)&NBYHhy!P(q6F+vkTy:hMU5&n10>8^w&*ض6% M#TzC3\sV)|է?Ȗx$g}䐚:Y]\Q+ɷwawxz?~'7E/* !4Z)a? M<9jhcreiF.<۷s^q>gOyy|!gynmmYoxkk.o fʄ#<׷}>L|4 1 IDAT8 ڏ[7ڏGH[T72oB#o6p(qN B: $)c$Vo?rI8p׃YRPNZ;^1QLPIMk8OzO/!Z>G/4+r]NگWEdyx/e`8N,%vjiylGǏ-iJzx4,ex'wL O(O:{ڞ&G,9h}{ Sӿ7%7"^';8ÏgCo|@ )zۓB ܝ޾ᒝ<:6T}%&je[|ӧJŏ~Iovh Nz-ʋoinnfر\?|'-gܸq?]Gh ?s ^u$;yЉ0~ȧG;B"Ci<{3_}p`g5a792CQ^޺ʇIQļe^^my89Q'9 (Cj!.[sӼwE ~8O^m_۲.nQ:w{dlzUeBoZ{tשA #x<7\} 9U QDM;S=9$ZHDJSm C^j{N% f~}5UM[OYqlKXLCQ7ղyS)ON$u{x3 wlSf($ٿf}[s$m%4 aBC ]*[bb̙3--70K}:l`ehyB: Ƴ>s俙ۏ<5b[xǣ5~a7Z+\%WYE$374 \?O߯l1 ʫhc#ι_Nh`X^ {Rާ$+Vҕ[mWA qI17_%Y܅%eUY,U wG]h89;FZ(ITI"9Fp@]Σv%jKvQWVG*b{p5G.'ܿ@ #EP2V\0{=EiPk"\$%={e~~= ֿvoʳшv[ڝd _T>ovCw‘-+uQW o/؟˖3k@ + R;BӁ,jXM51:N Ha7JcMe۠?Ck(ϔtl}Pj S>0XQN6\RT(>~)>\^t6HhJv&B)(HLSI>223'_?{=\yi^[|;<n7CǏg]z3#-9z2qyb\{k<O«_HeCkeR (mԅx`#8׿`"fr3K9c>d׭fbO{hQƍǶ۞;;R}Z9z}8\`^t)W&[Rc.D0&11},4e` 7rۭD+w-r6L8g.G#rfx;DLthwA-@"?(߂yx1SF]-ە {m r%J닸~ՃܕdRc()D0w6!'c8sզScZ1H#4'ZyY| Hk_x^~(Oa<̿ÆY}z7~DvܑO3w\{#qxcț3;J[^K&;@F?鿙!h~yBWO VUD#_r3&*;oZn7<@PT;) &5CjSo^ WAÕ5S䃓k7n)L"g>KA?!OAd0N?Z DX(:l}R2y1~+3561;y=0ohH *h 9my3]Td0۽Ͽ}=I5l3o}V[駋Yh%Jj2o_G OJ=ecZ>8Za<ۻ.j>rgkp -yp!?y?eO_{?*-*IW2iIc~!?ڕԏ(-.bGDi2U[lMA䑲!6/MHln(i"1\|B'Gmmz,Y ۅ-4uU.vJP_ZyybvV\i 뺘qST J\h[FJ$)͋X` ;,%l fSԖ l5To^ҕī?␕+ 5)\4d_+)_IqilORqHo!W,#6urxq1I.k@.G;57j>kLJA6]HJu?^t/6T:]6Cff<}+ [;FQ SU1fd<y`l1#\~ߏWNrk^Ia[:aL˫E"ܤ#}vʭLcJȃʋs!Wa^  ,-B.&#``UkijfJLg!KWw5.H EJHRb@ey X!Nos)?(g6Jj[_'ҟ~~0'_meּGvz#{ǵƛb˜Ik~-c%KtSFaLk6/;S~<|3iomituK:ԙ |4m{cj%uJܶ6+s8mF8x]EFkPx ƶebځ1#سf <ŕٿ&k0y,?ua56v h\mқ/o]j7m (L~Ld5ӾĥSsnZ.D>2%KX,m…6'X +wb\A4O~`m&im7| U0б(wأ|sYpY?!YKT]W1`pR,^ [6ޗ#tJm!^մ2-6$ T|MrEWK6ݲCdPv%Mv(CtzGllfqĿ7(t5m:0[JI0cuyȸ.|}bqknEz띳XzAa(6xc ^8*xtc60 `` iXb?؀1jZuCy$ct}絵5Y/:ITjvܮEhA}a=DOߖ5ѩ}I 6].ϴ+,K7|ogPMy1? ܦ_^Bei9zrG! hϑo%V_@ K)bͥ )o(!H-GX}}*ʉNSXj<(b{x??Am %K35ީ68W__tO(ՒAvm^!8WRÐA<-&n`8Wu Cg K jQMEDr&\].>Ne4H T.9zz.m ͂Ef6i˓c|W;6ϺMhjVHCg'11rF~(]I.\h |p$GY&5MRZ "t?4tqdÒUnE9'VPyztW5m8-+ (S;oP:V5ť֖jtmd̢хD-Jt& y}~k\oJ>u™5CE. ;H[S'ϻ 'co@[;tva*ʑ:!I^jےÀXDJJ1x;MBqدa)s!ݨ@)Mei!pYB".T:;O5im7SJQ޸0n 5 lWh1yofɧl6;hk6|1DǁEk WT#[8\Ń| 7~״,1\ټK# ^auuԏe|t%wv Zf|H_4dո'~5*e? /qQ]]8n@xo\&| tua{,׿Nz ֦R*mm*!Ю@xoQsJ >l>=o1>ok-e>Ex͖t̠XCRљD%\ Ә4\Sa w-eP \I*>tFXj9HSjv,BU_kn!MS1<;W90*gy 1v?sBttrWu_?^;>'~V;a9/^Pp5,Y@zj\߄b rcXz 20LQ&?D} ǫ=˗ep`k?DG'k ʲuhW;f\No<zq6gP??o͇Dg"N┋Ӵ2} yr!2尲k /g0l-K:ER /im|xIs&Uu׽SP]:("VŮ{KШKFcITA "uiS;K܅ysgVϞ3)eUrUѰU6$RA~N;V6 U!Ɣ 0Zr/:VZe7Z? sd A= >awJXz[߲|0kaF.^uWΥSFӭp~Bb 'j+ /h`,ب. 3V`̬Dy>%ψ91~Gr}~F 4˕EY캬0q#WkD5JNڕ5%~4A]-JVΧ}uT]5KWH[QH,\Ķ*ijIܖʜoVL)KWү"c,6ҸOfdP_P#7i]>0j~?O?\R܉%Tgሥ5ZNyi%Odɀǎt{~ N<&9࿓vYoE8ԑU.\}VwQxW_痟\ɸW.z ͭ9ntZ@Z*C^!B;iMt/1r_U`4pBDf$Dc,m6_g}81௿u0 [΅ִh:M{IcTxSEMTX$njBKL6P|9758vjbBY Dz5cjquny`,sc5&JC0&K 7on|: %)-w{|[ XU-0T'B b8R "ґj=FuYSCbbuud2g&8bDSg6=bL^["+vy&szNK?2۽/y[ȓ3_up371u@ \5>M4mES'XHfpOKں|yJf~Hdm}6|)W#&#!)< ml'Fь]4ۑ@!$EJ F #Ӄ)>&"FsۂȖO> .\U$w[<.Y)Wuxkl_TI6_;6=P ;\@;sA[!?wXl0 ?=el|jO#\I2Xbd@*JR]X7h @]My<52^L|zi75݃*_4FaegTs #ANE) 1S.;*Ԕҷ3,mEھ-׬KEH%1~{ T1&SK߿kK]Cgu.M5B(Rh+5rs}3.xMzc1?mv0]z! Og^0^A6fm; |êbjr{naV+9׆؋ZO9 Jَϖ|:zڍ|tkqTW kφ{5 G>nrvny-6o]ks`ZG:v.;#K;whp k?z;bH]6;Gt=›7vYf6`kʌ:1$?Z/hL◗qS^PJo3D4R%rܸ^v~5;ُ~ aŊVX<-Z-OkҜ 7zYJ`AXΦ|Գ]}V/8b@3-G{g܆$^^BBՑbiNŐJ"TR]'4;?RA Hd>Ɯ |"˪u![ۜ-s_lY۸y$R~ǚYg$؈? &iSQR0j g )CٖEIIa$,ERܭ"ÅþyBSZχ.$.SH1rˋ';,p7#\QBnaF|w;ANǶqv-['uslNOK OzSkPVgD˿Z>OrZbJp߈14Ugi~%^v}ل_LZuVRk_@$q|I0$VD*<6y'-#Gf?QR:4;`N;%&)- @BB!6Z6V5'"U&DkRK!%%KC]dvlS|l>D&:EHiq jX\^J2JAR<ЖBˋD%m͙uNTн]SR0`@ t"nZE ~m> VgU;؉_iddrIzCrFN a'"% 6_K|r#v&9%q?ȇG1t׳32~;|T.nb/2 T,xh'xh%0(Q_=<̺hG<n 6 6ݚ tiR`o_{ڒq"F >ۉ9?x  "hWi h̻Vsc_{GpٹZeC@ΩNX!?wkm$'2E/t2(ғ}tsQݛggaBjt&hӌ"Q4{S3Qt.7nnƮuSV\Jq?}u/ǩOcq]-B*{of\}w/o,y] ! u_o9xkac7} _QXTWCj.^]1+^z "7Teg)۸2]ѲFj0 |%1VUHqpt &8{B`NZ˲e+(8h\q|i"eh7o9K<3Ҏ9l=^^zq~g~PdLgK<34”3\ظ~Ns "yČTKӟwHL-N@L5^t{F5)e8tvu-✋Kɮ82>m<_ i;#يH)d3yHF2EP N쐎ZKj޷ DO՚C"r))R 00#1e*ÆtPRX+E'w[ER*N]ʱ}ybIO}+`j<c!i$[6/rǏf2*+1֢U B*ʬwUV2u.\8OJ0X/XA<$ќ;~ԝ4'y>; aڢq]$PB@pR}<5 :-'=#/jd|d#k~@h/l݋~g`jt%ߗxqS>9t5@1H'k2r+$"$J!IR"E_>N}[WAE5|6]`B-F;Bu` P[F26^K; Q4]vn=$ʬa@Ev+|sh4U(MNCqOi 5mjay"EJBeeWܘ*a)S`e3 FW6]PZYk'~nBAPNEa#GAeo_/)IdNc?yCG,YBYYYg5󁕒C&}6X̲o_&(o]^7\1&su!y;\eDҺy$ZDRs #Sy f&#/}մpg0+\ Hm0J#O@>Aq :~&[cQK<|I|O w w!$KB)+W7qmv/7^W_C \8Zjߛ֐L~nqp5 %hʣ4&5J^lt !4{QZTHt̸2 ໏NDYNN_ gZu-OQR8ZG}I7N載{2Av<&:d߱Z՝7LƲ,zGoy0:Fe@4VwxT+V.BJ _IWgӱ_|Any95un`/dsPno,ݗΤˑkcbBhiq]A^վ'=Hֶ6ߤ7ߌ}"w e?r9ARMR!'ZE_F4-h+MysqkسJ)Z ;Ei=?]Y=Ϲs _FAwph eY8m4; +39c^S=e]>򣘅Kk3hZ}GM".i;EJry9,s\]m>UndAj#x zTeKYѱ*-%mKҎZju1 C5cڙ g4W[Sa3_v)dy~$ FOiMsޒ?мZ'xALO O%>:IkKɠzOƧlYhsاf®\=?̞͐m jV]og}=g JaxΌFo3<4-4_17RzJ`:ΟyYCrfj Zц@it*0= 6`{5Z9 Ηw)zwjϫiOspvm? +."&piZjawܹDî_8}vZVI0x>D8 o@T ˨!!#$^F$CZYkinnFJ;chU?wcg$vq 曬uu輲1ݦQokh+5h o~^+ ~vF֜?dt%P^A4,G(cBѻ9,V99 a5nŎ]v1Sh6%[)p|6 {A]끱 '7f[N?B(?):X TX\4.1i'؋xx$FQO"ٿ6{ 9qyGFkKv㴒wZԂv31G?f0TcP abv.% 6̦|f׵ԁ=u>! 2[qR iAG"i6/nVrz+dfG57-YLΤa@al?F0uY%;nS¿)}p,_;҄2$Ro8@$Hu:4Nh^Fn59u h;5@ s%um"#8f8S wԁ#-ȥSBrӰ#h UDLoWFpGlH;} ݮ5yrnYّ'J#u$R~9&^qiʋ N:V|1׳IG1:>W^#eR_%71=xNKSkFj8)y\kNep| k26bd*SZ(6lխ)d\Eg")?QAN譵x.}zc9_L3j{c ho$I<\Ұ\x5$³ݺ?k'_5)>$/ k-4sOUbpJg"fr?diϳ72yD^=8S J,v$F6!Y2empkPZy%Bs|5þy±a; K 4i6 QH!N+ <!.1ʴeƭ O>{A~~3cZ)mnF]K$7qjO  ݽV3ɻ"1h*Gʣd>_r&mWU1rbZ: DHD [#7FyQ< =p*?MN| Cl@SR߯WXn[|n#OcʼH Gs5%)E9LH쾒%wnxۤr;fwl_GgmijJPL^m|WRV'KtfD_tXVw6w1 J -N[Oa18翋˞'2w<7"+JKWJJJ|::T"a{~QMF.[g2r@H;&^|va55vNb={qꎕ:T.ߞ\kvN.*ڲˊF a{\O$Y$ޘ~T}Q/I~@EiAYH?Dk"\;^|1V):Kp3OL5c*omDH~e%K;b4I}ܵhhhiOqwR3س\|ReV0-&oPsč\'Wr4^y57+IHǩ4e`X0zEz91NUO |Vjիafm֒yk(}YX4眶o d 5, s,xqUH,{]UX(=ihU=bDx9k]pu&? FK" 8#KК8Bt e A:.)_ƒ7|k?%;;--=Xld_?pfWҶ|9VkV4yۂTg~oCѲd%Z )IxlZvcxz ߆+h~^Y%9CQ_<k@5ߠW1|?w}| aQӭO\kXEXO; 0ZSAhVRd]%BYBĉ0l꫱RR' $') ?7i78Ѭ[Bst Vj5- )Y٩.n%nȠ+^zqcʕ0|xvL_-*] ]]ǫ(ߐa qDF𮦣]sY6-s0[ZV' s|ÙC|b9%2􄟢{䓡 Nh{a$қѧwp= /l=-C1]9De;t(۶H]ΘM\r9||̙3+︃l*}-ؐZKd. / ވq~DB9;[簡v@7E>*xo }YgI&݇Y!8 쀲]fvۥ^ bDoub/ny +!&f88|B9~&5>WfX| [GXpYZyx0QycUk~Ji21Rgg=oI= -Ԛ/;r%BdМ %Z^&%Y%D4뉾!QX'Pgɒ11c4%QHZSҸpi(HoN?8}VҞ\_\N|pke~2N0PTN"̀2MґZ5?=Db74sWY$+!'b**8Hb?Bkmk]q )8PnI N IĆmES>4M}Tc/hh5}**1M-K7f0B2k5e|3{U=--I~1|bpK)һN.t,[ R7Up)YEsXKWLc B`)--}="MrNh}{6ޗū/4 ŸɇTJ#acq߯ y_GnB9^t&$F>pZV{C0_?ل_r΅Ү9ӉHhn|^Ǵ}1)HbDǀ?.=8!J)@+69P)KJH$)-BT /-D1K'^LF)=$-`9p?xYxgzP-<տ'twU1h"'<oyR%u.d(ViO(4 H z[Ŭ$R0 t#u9ר3eEL>}g:)NatpWN+[߽9B'>bUiy5̚E78` Pn^fՉ;'Hqwx@l@HpE2!=ZxmDkp_#ȴspvY\%hJ LZ,y65+wttA+kr =VM=31\ԶպQH-\mJ| Kr 6%ܹp]榍 a^*ӧ᜺u{)9&<%h?DT:ؑ|C48j1BZVV^o|as`h!WA-}Rؐe_ڦ&8ӻ7CjjЉ>&2,Qkjr,bOI k^f~曀4dpErGXŗ-Jp{sMءDRux 8\r4XADT0o K:|dϒB^Qy؇O4Vduamf)}?/x!%%%\zfQ$RKK83C; xwމ=}tS{f(2qZ[: ghO0T3}ƈ7Bdo6ZKÏ-+(rO?K~UL"^OBS׍Ёly _wdo8RY31Wp%?JI8,avNiMv$5;q1eT3C{ hlOD36ʁO읽! ل-`Xmm٢p &䷽%m)7l~3l<7t?;~ (nܾfTH\~1 D*W0>Z5oWwBVmDu_sirϧTH9'E[Jq\.'EVyb D=.8. CL"wWDI$fɌ鶏 B%.dz&OtOEXw)^z)6HTv ȍǓGda)eoox}Xݜ-[\Lӈ=(+~?L,M]^<7'NPvc­NWndp2Jxk.଺7do0曇p KY[ 3k2)PVu~C)\;]/k-Ʈy+캷1lز-C0Dsz(X'-L=ϽK H.B4\)#Qb;E`'(ZDoZEkG榉~nI0-ߊIMw{/In~7z8W5~zOz6Fch.;眬㟊 bٱs`g67c/ +%vݕTgqq}ae(Bu|JAg'~ϳ63p)fGL*9;~ؑ oѲ2<PI^ +E݊?D_MB$~h)>gdX~H{CC&B<*0xj6?8&;cYw6b^j2Ԍ=䖃M 3p`=x-7YC3'RcPt`J: A?9sn0V6 ]`So_Bv5WWݬaҢ(#diҟIsY7w-R[qPv6w95fᗐRc.VXAi`lQ_#jTx#)?˟E(Ng~nxxY~2߹r?Ν1П[} [g6zWz\V.ǗKt]b< BpɻZ.y.|vpC3h| e[U(>|y4NL7,k1B IB)WAҁ$at??Cſ\9h# d̹\&_dE{#a2D yW]mj.Y#^Mǹ"{D sPN=>} :禬#3bzX˽.#(3qcyCx,mW{{;Ğ{.f4hWAVdU{/]d6 6!d7x`:;Y< qHkQuzEauMOen$f[.2r='?<|1Tc.? 1l!LP;COIJì2DV2wy5ђ̙ A=^fW fn'xOߑ[kl|cq$1!ypYϬaDbjF67ΨQXk]:xq/l|~(r!um7 OL)^~O7jddŶFpϳO4svlIXbȿ&~֮žg=;ZUAdzQbZs̳9e0 5с(Nt[l+Jl}{[ "#:׃ƜO)VKr^y;[=^oQ@5x-WՉ~$ҏ.D"\7z.y2͸_8_msE^&[Hk=\R S$y&ɷ ]}ڳļFNu5#,Xo 򫯉qrLL{&R-x 6N;":ߛAiX)iW>Lpl;rUbB fp\IŎe;Rկ*+?dy7Zw ?70LmdҀ\\đ^t-oQI Ғpc.fsYەxFg[e%E1+g}-puZe\eTSH.?m޹v5RyLN#'sEn.6-'m ߤ _ōB{0"淦!$_|9$=|T]:i<}-҆!AIQsw) -kf/].Br ;}d#z͌{yjzZQ|5oS5fſ e_at$9b_5tcrX:ꑉvLb%!$9OVt @H- IDATyd&&k1ԶgM7\t<f>zy F]N}2wy/5]/=5CO-RT!-CӶY$‘ _Obōģ>JN:tJ^wx[ࡊ'Ȩ䀩$2ι6K [み/-Ŗ!yiy;ZnMXP(eI8y/ԙČ5o}ӦZ}\E?;J*ϭЙN؀d #::8YsssQT%7s?έ ԥݵjݪް߽*0]CB6!sEO-oH6gfLG(7~/N\д>To`_n !I; Fɑ4R8_fSf_G=A;➍u؊g7.Lqܑ39o_U<:eoPTv$0I1ܫ}7v9~Q^Rt.~MR9 .^Ipx}zg葠!ʍFNF#k6s _/=}o'R6H66k1*~Q1d;w.=vׅ58}3̶% O#0F&N玀i ԭ:E/:oiG՛)]EӴid/XKi.| Le7x/y(!E?fvCZc#b1Za"@p}A!Cf(?[Oc/?v]gnHL"ۋ}`NZ1z^^>//eWDH搡El .4W-APޅ2VOF6OL_J/G>hIYR1Z^rܪs6▁Ҏ|I'J}ZNtlQ_]]{Zh3O?5kro3NJNP̵-k\vv!'1wn%B4oK8{uߋAxH}s2x(WJpuv;dF=N;ZIc,omt#Y+iwVKZ20ܾsNm>'4Rm))xXeSӕ3W6olQbss~ Co7(l<$Ӿ~%N;Y jUFIWnsu)#ZK$`QdZ׶W1}&/])ɥV+Z EH$KWdpd7ccNdG՝QOU,ډ1J)_^CL,2MFԯ'V}_'k p(Fc՟kIE \صi=ZitV)@yK$`*lN8gdp K(-P:^5OrOz,|kVN`,/v$P+9n>B{beX :]z^+[AphNHTd쟾: oc }~a12^b;ȩu@M伋wؗ$)of@M^Kڜ}EjsbBG%|СK/>8v,'b.jWñO?m+O0f ;3gb s䯼=4-ow@ "&}7cܹLf*'3ߎ1x[(_bZ~L $cVr OoH)EqɵOFæڄkØT\Tas$e%MTT8~%N!ggfן^# $ߜ65V-E_Rwwt\CikW\K+Wr)7InI$H8Xkyk9} ưX'j>o;wicx022ǑFqFrB }El~;N<*h[wl%qHWcbiH/S>Qp 4p&R&$DM,{@,QqCLň Dm V)6<28WHBY~|1QϿ^/Ob w|W6P`5ay|URޝ.4B zbb7dj哂h*%s=&%Bpu0o[& p޴2~aNh؋#TK`LI" ={hVqm_t+*֑e?tX- U4;%&4|?cXXNj9]_R쵄~*P?p)ul;4; 6EhD=r&ZMn/űMX-^"H`1DP<}BD |RD FѾXt;,BydpYi4r&(w {Ì39Np藉FIM"S6~ GHv +uK F$(U2p[ysD3eᗖ ?P|;[#d o&l"') c4GcX+pX]X~Ol@"J9Ça ˊϨdh1VKeM+j1F^VcSR\TpK0F.io)Rؿߟ YLR6t oY9X%u*esj͌ Sc<7[QRq^C#~2:QdEnނ &P5@1+88]cD ha"dT$(Q1$ ۽ȆFn>rYsw& sN#7}Wħt+4)n{FrDA^nItqɆWAG-eđg!:<}*6[BD`~Z:\iI2(:;|'/$rN6K>)$>~ݹ346b8t m w>GQh׉/۟Gz oW<Bkah^CP&ƒ8aDP$#:\ZĂk9CQ8>͆"Yuݩ-(=uK E(=j_0i[Ct\ P$T!!2/gf1{K0I7l&=D 9zjS(1B[2;dZsvgɡ!H6ww)Y#HSE`Ufʰ^ ,ް#St{>o}7V$TM6і1lGxK1 a*CB]"]LZ } bH`LőR(ȖԿۼ&rh!\4YL/불Y% !_Ly`pzIŌo_=Z Jܚx^ "D>F ,` kri87o;w9o_˹I8!3O>Bt! .kfr<3_Q::gTdsBPRe6zN П~@0ceYb\_e[1&м4zn=}oV7mtY+_7Ju㡋0!}>b˝(A&n&mrC}K`x;i6l_b8y_S_X>"7eutURC =L'@M.T<^7(~},mU'Uo-uBٷ/t'Q+4'8T $jBjZPCIJ/:.誕$O3[ xʁӽ M'ťjOx2gu6:0#4xxF3muu Ym]1Mͷp4_y Fv}5R(>GPQN4!{/|l¡^H&ڰXk'4VaߡӀ"|t+ZcuLkye kJ2e퉩"$ᶑ">*f;.铥Vp83 c<>`Dr(ٜ|IX#%V|L|Pq'<RpNV+aa={[{D\Y?h/r^xY][7c»2K:C&NsEG6nͶCO4W (ꪴ TWAEU2-+3 >_]NE NU:vxGe`mOHűe3r? A[ˣ,n#PߎJCXc9%NԀ1e+/;¢oُ|v(uObX9n\5,Ǒ2LAA3#=.>b@i,RvE@|rTɖq'ba"UIܘk(eȑ9'h^tY쇮ug_Zyhݴ8ք p>K$2a|@mg^͸r Oq?}?g}Ecc=sd;_&Qv+5?ӐKNOd3lPL/D=?VʺXc9i:}elf&[7Sgծ:ӕW'kgkT# QhI_~2@Tyݞ<:|?T\΋Jd*EI*j0b|>k>\j?\I1C;#)(5{ Ƨ"0]s+TˉՁKNn6#hW^/b?1qKcCLhH!!8"o68y%JzZ Gl#xeZA^lAEfw1oSm Yj3+{_H(+ ںE&4];FS/Zt- <#V<Dz|bUm`}ú #/8d^*Ϛ 2K׃,ZZ(Z )lE)Vm**h|Z%x"qiJLZMNF~(>*/dvm- Z?n.9/bs&nNF^'~( IDATwu-Jee#N4k&|35qWH zވ U"=u/BB,>mG 4j;ӫ kr8rMurϴy[dUAcD+ނۉFwol$n83JӣK1ә%'T$t;?w%‘~m:mszJ{I6)(3 'ώ0Jaz'}%O崿Mc'9OR[ 4 ;.= o# .-1}w9r [:ЩS7k8EKn1w^ƊrEز~oDH^x.t}8tŠX+quZuevG؄Ć3Cl۶.:>_91#!l٘G.t[o%Rոi5`&CO_KUoV*9;CjG٥Ct0r nɹq1] ߡ9lrʷ>7p'c[m3_v$z(cwXx] *0.J{kZXTe^w*c27ȼ`Q pykq9gO0 %CΗؓv{{SڵX!7wnU|pGV῅#WREuf:m7Y!ځp66"`m֗"puAp=MgF&',bēxrem J`{G̷aZ$}R/mL0^,A|@eqRJP'^ ǽx-sNWRXA[/|bj-|0Q5q=\u=W ,"2 3(ܗ bh_ n{$WhVx%]NQZ=rқi==0&,L-KIʍu3*7#beSק/A?%#YxI)j+ltgR^{md@ηbYU2Qv1w# M;W祟/.Z>u'ɍSsGaᥗ_W^axj=o$y%ټگ9 e&OIf~3 粳J$Z;͕$D0Bo|NvFVb׵'IUp~ \V}E_ wCqm0"'N ̪m)iߓ[ڣ٣=mڭj}8_l5=\^=팻4P-fO#8WpOK!}>KfV7o&^v/?\QvM4ij0t1XzjwltJ"ZZcW^v{:&B؟2캵~4':gLþ:曮__~پGJoLR̙ìY;v>*ۗjNes|frB,O~vxhXJjõϔ o$$= Pth<ࣩx\/9N$rQ Y)/B'>l MJXD_<+'z#4>ZK3 \fC Pnx͈6+LqRLXK$#al?ϙ j?85%Vճ=/|c)h6ofܛJTIfo9^?W+O{G>0ηv̙TIg{#|Џ1cVAܙ:09/̜3 {sxBd~vzQRv[X [F0d'7y*/e=p :%#3P)x=S[gľ"n!u;qJ&1_KU1`1!&њhNoÑwƬS-w4ٚJ9dPy$d`%v@Ø~Yiߦn] ?VTccj>\/9PxA֛ d8s?U+ʈ*!|k߾ܾnjlddde hj侻뼯00tXxԾRJGWwɢWMח!L#HVd':i-U kı!QB耼B|A3iɜr=dB&_bFAsr2!$e6$~o93<'"'qGJ+',"mK5㩇H$H$!kVZ )!%KYJr4OYGN@'~WA 04 !5)MV_3$ʻz71 E ,4:ڸF2 Tk0O7VU)P"g533=2M)C!9;~ iJ&Ɛ֮?i*% 75thǟl⋿o/̹)C}Ҥ?. Wa\goqwBhj*&SOZk!^lց\?A6gهkvo -ZLӬ+N־1 ydQ)?dH:I=l?؟?⊱!"L]֠J|e >?`9|,G$CY;Q: YTλ ה 4Z7q2mKZܽ`Y!֢\_,TfrG6?*{7` VX (+WD&T\Ro8LrCwغz5ݮs(\*0Jh%^#Sh*);\UV45j?Dxf$;EPԦT /88Ini ℗}' ,5TŲ >[#OoR)>B\}D$RDvQl{m7˱o}ApjwJVX6RS b2;SYEE]%F6v@$/yH$mwT+%~ HP|Xk8|(˯߾hM7d@[FК O`QJ 3R|zZ5@oHq=Og;;$D!ge1\=L fU6w}Bbw^~_w~i.7/@f+3()YE>tC%+"!@j %:}a صk.RbNs[+;I& <(S/8Ruo7@ms7A[l`$`P&A0 gJ/dJe{B'خ'C> )p>R DA:en&&kT>>٫ X?$ی25>}Y 3qudd&LX7qazN,4,$8#=cvy>L ݉,d\aR\&Kt} 9"SHݎw ~xY&ÊD*l$hώ-+Y5tl.)w~0oKm: |$G-Qw{l/O$r5}ZȌJٽN]q.4 >0~wn&RW\^gJc&HH$SVHՐQ]C濮Ƽ*'] Z'Ϊƚ|WDRK,{>I^n ߊ*bM: so{Ͽ{PeJ7gbMrzԐx H$8/8嫖J~;r$%%0FkL"AGaAaŭhNNV*"vdsI%dgu8Ž{R=|4|<S#\"; ~!~~"MXf/]ղSx8SWY[+N BA۱Fc"s؋{VX'>   @chj($5n%}y6h$h :zCB HSoKlp%-]MvO6KNAv;- GPSP u?lbAO)[-󨑆 nsc7mV5TZ20%[j#}1[k /cBq&3'Lk7k\ _$[HBBϣYo~0KEC1z4&!Ι[`X \5;vK-iVr=ұO@x,G=e{ "Oh0`c$0ք;+>22FBxPQ1S?#]<8Xx\S~s}tx卂(Bq їCxI'c {~Ng WBYg$ [lb>S#xb]`@'ܜg b[Z6E6nwn?JN] _<$m9|@Vb]k2al`ڦ(J2D%\ `smd}}j kQ8\Bzk=N1vIw7r = ibmwߍ=<:rƌvuGú k@Py"Z䁤$ԧ?W1ih}5P(D'6p`p/0-ίsyK.ieőGPs^R]kkۅ߁q]g%).XY#Z0 w=+Ys;|? FG=~N;wvBmo<B!XXó5J Қc68yNG؇ډ [WDƍCMJ07X3\[8x pF.ꩨ{nܯ[;: `{k6Re?m@*%ulgVJ֕%|1ˠ/-QkD[q8^ۦγ'mʶ_h%`:-`ŒT,X@n^h!\?cR-?̤tΜ;ܸ%[I[rlׁIɠ5֝CDpU6Q\\Bl:,}N_DU[t$JyHi8e%X+E_5’1\'42?ͣ_NʂXRƅ]]sA$JD51 >MCqnK+ŬUL};[JYyh4][vtZmϝ%y mFڴdX)N6kKIH8l6iP EXZn͸=NsמcR0F6qr݂[~tE\OS_W̎*~}P>KVe0c\tDY~>*HCϼ#܃d IDATD=65$0ưȞXkjN), eM5Ͽ3?iY~ɧ7% Phd`al[=DOKalv=2xHBY2QơrR{=M%*h}{\soFnd:^6U/"v_8KIrj4mNZlt{[YB|;;۟`}mKro'yo.L-NloFk-`<m4zdzkG:9.?T.cm!fEND8I絩o&ƽcl"捹ZPpo"4;'% ]?,[SOJLDQbz~SiˣDE$?mx`HLEsmIp[P#aG`N7q*TV#P+/ud4Dq\ H7)|AJο8.赏bJ]~-^{YEB;uR?=!Vfu%le;?\磏?w>qǽt;Ppe *$e`bՂ,I"Z b%_KRjx`۶ž]1o%%f_͒)[b{@N ӦL Bwrر̙3ٳg1ۙx1|-pzB܄꾌kAh}T4s^9Ӿ( G)7\wôO;wSV ؾQ1ɦw۹1aGoGxй 9 ̞ԝIKS8~563C2י>cE 6:KIE˦bo6cel>L8tΤD+ED)hֳْ4'oqŠ;ܾ^{jމCC4FN,My"2 ?hb/6&j cLjÎ͟ӹhxa,nGF8=0>/i% ú ϗh+ Iܷ(Кxjr\e2z񧫯_͍cVE1ȋ1;5 my/3)Gmg^Ic:F}Ew dFj70xoӑ:7M$IA~>WIG 48R 0t sΣ\TzdgDn/ɔQ#[^LG[p*druPƑ4y?H힙t )OZX?R֥3?0?qnݺ{?wX|9}I~v'^{%Vm+&5⣢sbxROdms,T$czuAhê+.iJ;kB"qMJѨ{YY?_~EP1Eo˽ ט}3q$&|C(~hH%U&J߄)Gt.Sv|9ftiJ?o0!_1?}|kx/B,QI VApB` m8HxDCGg٘"ʨn.>>vYo;{}8 Z%$'쒴T{D@TBk1dKJys~OT;"bcGu'ք h3ujί9;H)ގ}fP>hNcD"{E=}tPJcHyw햴Ӥ:uJq6e-ѨaذVD?͐!HOcҤ! kp?ְTҡ`K,8nA^'Q]>!!O^'1 /9fa# FU?h}="3SiN$`]t7'"](tHW%&H?A͐0;w˱Jֹ3eSG[Y[֏%Wg|9Esݻ-/oҊNԯ}*F#8..Ф "uRU"++Yˑ'W:Z'=m>&8>8*\ϝxNb hѢ .LYwތ5x~9֠{չXxBcCҴhт" 'ն=;czt`aCcvU+euR ωo37ȑ)ֽo)ys&a{a1c3 żҏ2E V`& ‹%dYo7;EM! 6YX{>2Ry64R(T~k\NH^8?6sr}cA^s)C KQZwΐ^`ηG! <'Nkma3u$D| HhuT[Sd ξ[r!=i6> YQ%jҴs@<34z(vg5v,y瑞غ5&:O8)ssKXRF[zvaƼqܜ4~&$|3ؐw79dA֮(FNOyJ DJ9B%1J J`æEyʣ@0#m0UBFu8Ҵ3nI=WXP(%9'7~KEuFx k-W~t[]I saÎ >ऑP`UĀm 2)sͽrzGJ ++Lv0͚gӶEs~H]WMaCX}w<1=x]j`X~z} RI>Q×zc8cyo0ҥЪ ۪vzɃK˗cWv--v[,Nypۧk oE*w:3#ʸC\>{ݺggoY8%Ӿy?Oy䑁ˢPgc6um$>/ˣo 0JxXBjd0❤z[Va[sV刿.1O2Ōb't4;?7}m-ryP_^k,lR71ЯJch} Z4DsYS%6QD?- B5HgVR5kZ%ݓ2͉(;(REnT;"mQo 7-w~Ny>O#GcjRO㊵tB@$Na<ύ/1y 0Sq뿅 IA%q[.J5n fܵrZ\|DDoE+W8 /`DtLsk3,[k2 _U@'`/uJ b8-A&䈋d4Q9 K2JC|>S~Y]I^b0!ߔ-x$vv {J;M`ϔ[v c/|nKޭuXQ?'3ΆGK4 ‚˸q71sƐMTEWyill"G h'r>EjqދU=x#Zg$ꡯrׄ3پ35J$"Xceдmǘ++Xn^N/]ɩ n&,_ź<6*0&!#R&NT%׏sasvSh. x}!_H׋фaEW>Cei#$y=U*hK*Ns }E@4Łq{/#XNw"5' 8 !]-?7n/prK<_Iw#UE. IDAT⥥qЪU)ם׫:h0OAMy1'\! c] NfO8T9}Md?|v{+e}Gf&[6R|#XFW]%ywC]kЧ]m ]]8>C7Ln~QasY22_mjAHmY$+g.}ˏ 5 5߱{vz0HZ/X OVA[h -,@Ž'sǽDZ:m\o6I9Dn.4[գSg)K;Lٷ/1uss\;GIyIyy b^fONo} "n>B'H4c}^}44o5/VES$cō='R0֝0(C\%ېLZĉzo9p<we/ŝiu3 0g]]wߍnݺ1m4JBY}*'2he5 ۾)^K_5qxq/t&;;t{+˲/cσ~d,v:*;&wHz('|GmtܬDj%/} ʋ ܠ&%aK" 0g?kAߠfދ"ǝU?2YٖZڵ|⑗_S'?mPu|V(.yzM&c$챿2AqƎF"{5m!##Ӧs)aS/}\@a\(G 4 2uxK2|prr0n ((,@j$ 537#\_W=:i2o6зyr}34<K `O< {dCԮa)#m q8]Zq0yta'<)W>6,+ȭ& QU_ՠٹ3uz~C ڱܹɯ3 ~-^RSPԊgR 뵽zr9'1t yIDgerpk}zk+**bB -X?kKcATu_BN2c*«wS]B[`kz71Ҿt*m{>.X;:ܣ2NlǾv-n^"%b*Rk&l%9|Ɏ-^*(Š5Rg$"LW.9 cR_x;_0_̮ 0utU˞vsʿZi}e!SD9UJ*)I%O϶rZLy i\P._؛Tn0Fy:S0Qv0 ZHTl/ PܨgqAx։P[%ijgt0>3h#7/kuX\%Q}HVa~@b] 3ҰFs:ɶUJ f)ˇþ\зRIHANh,"sCVҼu?讗båi7S͘]bsǜqLtn;0vp[nB$޾+^>K4eJY[0;zҥeqYZ=q~s}H`m;U`_iJV v. }IIX(f*ܘBS4ڮ X!~d^i3f E'Lnz5dy'9TWWc;9oϓO>`$+ҳ'?R*T4BXa"""d#*$N8:>㠞,equBc R*[C^nm`ҷq7Dxf~M?lK)(0ADC9{yv^RN א x '!EF$|?sOIED`me(+:&'  l 5p8yw(zR4%%%,Z B /K^БG"hwA.bUQKѳ'Z"IatI@"BiQ>zIheQ]110B0 LXI-!Ci+8J Blt 'E_όQ8"F@Ӹ5J(~;ěo?{M 7J5rESn D8m\%7h * 0F4QK4ў̏G`pǴ&Ҳ39ELӄBkR,ZDxhqPKnYKې9b{|eGIۖ? ی+|ĸS3ꓪxA\^:f=ȡ6 ua""h#4i(P(889l눨Pf(mpMJc6`8;ixD!Q¿g(`bcjQk-&OĞDcю.ȕ+ǃBY" (Ӿ%*}6e{3.FzHD"P[o!L# jU K1X 15JbS|HR9їD`a6\ۣ }+3adi V\AEk4SV|]Hܙy|e^+@>Zhs̡4߉5yK߅猠tGiB$ºE26Mq@{fSx^@i͛ jj;չ&\J̘aNy߼?Whor}f~$ duwx?4Ԓ @D?oxm fs4!oܥ,m4KH5>f4Z#w#9ûsKy6\9rհbM ʄY ~nAcB fƢ a<hDޱk VΗI~~nB[rL^d8 q|BH(y ǔsBP+ 4P`ڈ2>@X"Rq]r׫<')G#j~ H_"-wyGq´ liBu}&U IڒqyY@@iQ+/B_Ʋ#;a @<~*_OF/hz?)@hS("OrD"3$m3$xd\FTb l *+:"wq?fl~.M]ɡa#M-hB\Ea⤠ -pS'FH>pigsuӄNYڀп4)aC]vW7Z6.;)WR(dE>7hA:Mԇ#ԉ93RMtnOUkrx>-4O,Ko2sS"vlLqZJJZG>&Pq(ĚheySܺf$7<^o=;|| ݺZ B p\LuP%_K5wOhOӼ+R:{FDk\ k.1y3ޝwYQ]MYԬ_Ya@(h\p(8cs(- eT cao-iˢ 02K\zիHmHObUz$]˷?~0*"~m }FR:.\FֵݻzPJI>-Ւ.|={N2c䮶;FJuLd_tað99?wcCUzdlxBբ:a>j4= f#ߧ>ck8wA0<ٱwuZSD%+GIdIbF" 52m@j['B#^9z'kː0cyu(m3ٕ93ǾH;A-9vЌM1Z٬k$?i̜iD3LxF ,ث!.-/nu?ZiM-`xX 0NR8"ofsEX7-=;fRZ7zb4ihNJ:I矧Qq} PO"ęB*Sda DIsa":Qw uk")RR$$JD^{'fъIXtur=D9zFՂJ>ɼdXGpJd?Aq}&bbRb$(Ja(kf Veu?mZ*Vw[aX=nN>~S&}{L}?q1xt1|&B!*]Y4#Jܰܜs9ԅ_K0e⤴1gc2+Jﮞ'5hc.@x+{*۹;#UHGJWGFbӶq>'&"XppڦCD]>MܜO%إuKԿ'$St cXJޟsdZxJ L vC$%_oKl>Yb j`/|8k7kO4r  a}1./p~S/#\BZ綦gQO>^1 *v[ h&C;nU{5ȏZ\u\*X힟(slh$}&VTQ9sP4nV" o-L27ف@+@Y zt<:|~mv]{FLTl:2m{[wny'>46-PN^p _(babTXDp6*';ql}ߧoSt]-{cO8:fٜ$Z\_H*z@F]=Fg뭤I  njgѧKI5M)j"SK4?7p6:It@?D$D_lm]9[-]+MN:pqP}du˖#6Gd IyIyK4%%{Xr%'Nܥn6KJ.ە^eL- k>}"j .iV0(.cPAeuۯDtĭ|5+f#b=%R x 4z?ц!r9#s;~$v=-"|;<ԥ,j )CDR_Q 0Xj&<R?_u@DT'd >$Pж}h^Yx|=vpZw _s*<Aìn03֬,X Tljo[O o 7^$(TX&($Wgb`S^Yg0V12XKh) cNW1 IDATWźbRKMt.L8ѕQ<;Yqޜ[Ng6{qґ?StOt-($ik6&H- Op;a ^f-=,llf,\ŠP˶/u^kx)0s6QxUwp2Z&~IoBd G8tfѭ8$/E//JSǸB*Vp 禌 gqq\uqRGB< T((K}:f v[sp xϿV \oKB8c \Sp?Ї|B쟸q޾3Q}#K6* eᗟ~*eΜ3nt/BUmNǍ|Q]Ϩf˖p`%"_XF}N]$>- XI}4'@x.c88n]*O^HX\\̈#od(dSiZsh-aSX-tk.tqڐV؎a) RdK5++v*KV%$Tܝ`zCIy&nTqa ?RH=@xyc?Dn7udy,;h'q홃lfJ')y<oRW% hsءq*o]dc^ܼg} 9wWۻk焳߂3b)%ӦMcŊyFtyT}Ⳙ-[m3LRUJ*BN;7f lP!O*e0`Wĸ6J%%,a=f.Sr 0=ʟ/;riK#&Syxezl %*BB6kŢ3?ܠюMI|>OsK A>O ^>'~S[  ~{Ga>lOZ?Y1DI+:Ϡ(:M- )Zd!>e$ڎ/"ʅ78'RPIw Z(mbWl Xa`B#!/щmmꢌPoX%YQRfAν:ܱ|?LzgCfb7`lUKD+i 5͍5޷GVcRgV0 #z;@!Aj৏'yi%vS؂v.\k݇vDHAsc!ϴ@[*ld).a+h<!$L+е6y5JP;BUxKpmŎ2,g6^}C˻?mLL\@d[kmBS#]#Ғiv,*LH@'!%Ƭ+JABr(o鈜E!$lMYpmI5ic?H٢:" 3C a x&C_]r[ \sȵcX+*A)B$N9cEo _BK7n͛n}T0pS@IΧKuMUH~Fxॿ5ߩyc䍍/~?; %N j/e$N(TB2<:벅}#eg.8s^f3ҰA5%&'GȌ Ǵv M\&Qf˯K^k 3LNO@bDIG{JJLFhHjidgi(R"W-Wi};9'f˟aV5*ff&U'G A*3Π` MgǢ ϐ$I:/ Vp/ldF"k*0&S4]p풙l_IpVL4s -Z+4 OSRr˷&*]xG(4|`bK.}`| L-8Cb Sbsʠh%1 t@:$4M~p'MDx_I*G'P_"z4`ZմL@|*:Zmp[€_ +W O)ݭNM0Ί!Z Q]J9["%f|7b"zH(|)϶ڿŤM 4VK@\D٤rVօ9~Ǧ3^|P מ~=A/_ "BFƨ#] ?O(Qm9<[A\*n~Cܼ|Vm>+xH$=q᧳\~+ cnDݳXJH/WutrFī!~pßtMDK5a̔;6i|<0:prUC?*fwۏR]]ԫ\iB}~tucBJO}}E\\Jh6}4a. @.'8j>s[;cxnm#@3=^V+>zw;osRANJZ \;w \ P[t@ ֩17Ua4hD$h\ztH庙Ԗڣ3ąJ#yZ?k0 (ioJ!_HX[B6k`4IΞGKyf=:eݥ&i4if3gO7c>y&~T6{?Ghu,~F8{Ώv=ɂjn~%!iܺ[i?ԝt*A*;q1e[ &0*RY^`C6`Ʊɟm ;N!3yKh/ p\ʗLkuk Gs=RxAOORq vtK )ikm-R8+EqzhkĘР#lfN3m_ޗ}8._72,-$!]o hio^r 7a~0mlc #hla.F*PnBHCA9dhH9TDHoMhuOʦ[o!F#i/IOC0>ix[hiOo o«ã}Wsj/Mk< <' > }B5a.h3kbVI_Uk6mzF,I]S?oܶYI &_ޔ۪XHql',=#YvZ'Wu<]8w0Fexo9\c;b )S&=>w*IXY1W ekW cNQI}kEAvŒdPYa2@kl*'=meQ66V|־9>ǎr]o2 @4NCVW&BN'!,tX2h w=6% $uY2nJ{={A؂lNH£6~-pv̏pL8ŋi&mȃl.=XZZZ9s'~kN!I6p%)9Pd3 '$OO*5*+~fIng95M#S)W~'7ZzPRxV*jZT=Dc)SےMoim//zgG͋7oZoY˺%*QkB1HDqs|mS64&antυXH sB5٬k£Pr٦tTu,̌#RI+S 0 Q?n=ݘrJC t%Ƽ J2kuE fm[}֫h 7ShZ IB![GuZik!>4u;:/gk/"Mմ4V"JY'O'$|_ +0}pГ ,~P&bl%,&mT&+'Go7ǐRplpLk6z~ N:HfÉ F/LvV:ml>z:bikz\d.-|/_7?F'>MPhlZ&ah5@Q(けT ~|}Kv*-pNP/Yj>ղX!$;<.xȹ90Ou-%EoTzOd{pB׮%=aB*]} _z 5Ix3I@N6D0e}yN7)i4# w里^r 䞗G*5Z=Ͷ=__\>Om?*LE%uUu̪> `NuèBr|SLkVyH3 €T@|Ze[",e?[xĕ'+L=!X|]^=61ܸqgeɏކ֊t*ecR>ZR iVh3E\ZG]?6e+ĥ9Ys|<;S<46O>I#^* \Ul|-m_*20>t9i!0{*=ekq5cXu` B]d{Qw+N*RNgZ$87gً鄍8-~iik+М'C)%œj>ՅHxc{[fIYZP)/(җRE{{뀂e z|gC祴vjfm(c %1:cUdNksv>ً4LjVF^Mw/3^8Ba5xqNjl`nAUed9vc>q+w1g}"[{}"̤7#Uyls.g9/X 2]?Jg7D!mQhUmg#y,$(Y`FĖ'=xƈݘtVtZZ]GG:~r|kYb6lk+D>~]VVr;]\%J &0 WXT\?xpާ$UUYYT|Z2UW3OJ3&=DkJ~U3+F7%mgk!(tYw8??6lkC."@Jɫ]xŋfFنaT.^4AC(#7U'[&uAIxFX' C:]! 4~Mh#_|FU {#oWiٚƻX?AM?y} PJ2y> to7LYۤȼUK[t#\~ٓ칺RHPJR-?lIykhӂ~uA:.GdJt";+f"~M]w29_[{h Fm9!lg%GCN%HIDATL;ަiB,By@ٲe ڏLee‘ |ZjG񱮓Ϫۓ}6@OMۿ!b}dJq5ӓwOeMFNUUU]Jfn]ۀir1Z)hgIqʟC|>!ys\@DNF2W`"͋]]GՒƝa6Vǣ\3vsO'OuL*=Us5nޢ>9*q_snGgƍ&Tܣ/9}zw%WD>8%8ΝԩS Vz0 i00pxXtl 49 $#5ڴ{Zxj; pgwhWtkQRW.10Z0=ypK/a96>~_#T<:M cyQCu5TVBmZy>(&vass[:pϞIѹw:\34 g~v]Lm`#{^5Dq؊_r}8-Й\J(iNqt`*Poz0(`dW`h椛`}{mA!Аs2:nNVGs}~m,$'/r{˖!x-W3gNu9{' ۇJޡ'>g*eC[uA T`+|{֒\co˞̚>1Lby̹ۋ|5Ι3\IQqσRt)t,7|L,^H_}ivԴ3s7'6o{sxz!!oq謏\kך.A gҽpQ; xt.xnRQ*ܛQfu1@ѳzp`6;8٭p,,L|w*=^tI4Ihcਕ?1~3cOQv ׾Y}G8"x^ZhCZkfzY|{}`Kj$Q}}q҂xЍ'owgR\} c-rpKuS{c.I %@B?I; }%.Ph90i:b> y^Ozh<~3r9I_.+A"r{0]!^Ť; Aķץ2Bc6]3cB"b]scd0ߴ VN;/?i!7$ŽW/nEʯSyxŖF.Vy?>#1qcQ<o}>j[}iW6@Y ܘ-ZW;pW{J ثqӫRWTqzg'-]9,ݵW~q-) ^}a'$z7%N.ݧqƓ@no,_Njf;[;JT^a:ЎְW%=\.7 |! +5yje0pEE_ڰ#>J|;a6x|ϟ;sڡbAg8Ƴ7"-'=ߴgjP>Ngc*8b .;eKmu`躄໑ʽy:T^f1~&SZ 7`֞ }n@o pyGG/o 3_w:0R3(U,9oPggEu+ڳ|_ è~Uc 3ɹ-FFRKæX_?^c2RL:] tiވ .W 5qĽ|cI.y'إTGH?ezI </q $WuQce5 _S?(7GCc˝S:r(w'b.<}bw92!ID~Ǎ 7)Í6GWܽ*re;sFc  жG(t/hPϩ#;0(cxx[ (>~]K>up(X9-xJ}q?v^w8}4~^12q`eo*ĢLX]F;o7[XX*>NE`]?0#f^b[~*?eX/${ռEW?x Ktwg~j{׼=c)#))ݷcq𝽬)B|th^pZ/ J4϶o}\dQ@i{B{>ق=ݽR1)<8>簜Bd#[/S7o਋  [8};8xt~ &n46b97+vP~ *eDm!HΝ mScl1k75و~[z-BRBׯNg"""""?4=8ݎ$!znK˒)hR5~+68p.|AD?㶋mK_Ru@.ꞙ?7}3QWY[aH),6(>9ꗽ|Yw:UV5<ԦMWeM["8 uDDDDDDDtq/^#\(|kNg"в17aRuQYvʗdML""":sF)RR&H)!,RBL?~|(.{1a8 - ][YkͰJK_YUsQ1nͽ zX6ϛ8O?w1yڴiر# g>w9g}(;;;ɜDDDTtD uǸLi@kP C?h?nMD ?޳-`_0Z~:DDD0oL^YCJQq~ˎ.-}I{f QzDt<'Dm|O]aWop%hlTJe=G/XtF"""}Xl.Bt) wTUUxذaIDDD'}DT/ aWn;BĺwDDD?i~AWϧy BUP>9k5P9l&icRf3QZ_A)u:CkR[ֹJJA%KzjHwـ:nsWYt."xFHtt: Q(,_|rEEşR >>066vV>}&8~-nMi lrmy׼t6"""ΝWJSJ TJZ1eNg$""""""!)#^||Lme{IJMƬΏ[6щy+Fi3R5jTә(7NןT=D԰^!čJ)!fu3Ӡ }AZR†VJ+h)FQ,|nNg&""""? cHCݼ#H"8+n k ʀطwo`UZʗ 8B'Eg B߶]z#ff @o]w?S2 B' w(6\ADDD-앶FA Rg¶io?1Ng$""""ߗ#h/oZZJH6QžDkؿp:n\(0_;@^{1c<..'uy _رhQr*֠}A)wV R_ܤɃ.|nN'ڰaim.Y_~kz6mDaÆ8B}uVIν5ѯZ6U3RRA* !O6 )4RNg'"tBsxn`Q"o,Z\*ݲ%l! pWTɼw9Y;>jXMLJ{fFo=+|DzKypW^LW+F EG=(kNLL윜H|>hQQQ*xz!C LDa G٥.Q#Q=D[&[kS^v;ՙmڶm!`sDDWY'(wYd5D59O{Ah@'Kͯκ\DT?s=WifȠA2"""3g΋`pNg$""'lڴke|.Ht;vX{jQCDDDZxqrRI)_R>0|pt6" &\1{9MӈӀ >@[q XmkNKDθWJPJ:u꯮w}Y`F[7яU2לZ}?cNNN~r~?<8⮍7f&QbŊ􈈈̪;}III@YYziӦڂ9111O==7S fkV PZֽJ^7t:/FpV#Sf)}Ϸ@a[57Ono`c}%'c;":Aw.SJkOk?ƐJB+ PZCK b7EQN3s~>j-eUA%XWS 8W5Jߥݨ8/A/үhtNg$""%++ɈBAAWj2D X{/x}>ꮵԋ:JԢ ϭ>ɌDT<ߡCG/\t&"roR)XR A0+t6"8N+++ˣJk}R4uZ)jsR3RY m""""":)][۵Jv; 4B?wRʖÇ|L;d\1#\ZF`ҢCu\vNg$""kΜ9g*4M(P\\]vR7;sh˗' l ^ duZE{r:'1uy _YE|/wSym`Fj˥|Ԩ ?n(~lDT?p 1cƌJI]vwѣYa@":!;i3[n~xd߆ Nmpɒ%;XkիWdgg'i&v 6,DDDT_9Ϥy+#ޮy:/ 8AD U_z8`q?AD'bK9õP7-;Yh uP3Po+DDDDD>?Dx)(V0(aK _t`WLPtV" ֟ tԍـ4aLPJAIunf1]4r:Z E^[_U_B53W90.5Vаli "܄a~D~Qi^e{MuρB;X8ϊN^_ $D{`Z5U] @Ys|tp!MBd$l))gR°9\/JLWZWJߤN(fJpV dmMбo  q;~7.+* P!R, 55\30 dffrq9:'y"MwNC?`K.Süf櫩S!QqW(]tEg !D0GtܹbmM|Gqә(LBk}ʆ :h] `Jg9{M'T!ߏrAvwq3DEM0+9Rr-c+g^( A([[^ ID/Z+T6)ݷœ=7fлD RjZv:7o? HHH@jj*n{ǎLR"4PmЧ+50~ 0 DZ|.JDfm ǪU4P@TJMͶmk׮8x ϟ?O`h Qe0ã~]ד~o:;^dW0lg%wzBOkD{OZGޢE DEE!""./ .zAD0yzGBDDt,ѣGwۿ߈j@m?;"""I)R/*WҀTJkHTG6Ҳk+J~/}>" /7aͲ[0eY_1"3QDDDZhQbRg=|QQQ裏K)o>4bD:8v}ihH ߖM4uc*iuZ+sQi8V5 J ),)ȡC_;m?kvP#"͙3'JJ^֭,Bvv6jjj FRRӶm#<8B4 _ivk-*緍@vq.ΪNg%"[y.;y_T mGE<&pW__~<>t:;L7ǜ5z/&"z'2<XH)BkFxt4d5\{nj,szFrgˆ 3J&xՙg}QH}W'7uu`s0MA[o+H.mț QH].WT04L,BFpuqꄚe0o:#Y&9qkg233PugbZFdC43,iNܶ6sꃙC{&>&! n3x=ADq}.DAy;[߈:q~Kޒ/K˵@tTtDo{ ,'N#8}`08UN21/2V<8@\h?ޟ "&8AD?{M'T!e[jJXo}^:KPvc3x/u829 9 'Ehm{A0 뢣Z"22rֺI`lڴ)Ó7n|]FFFll,PTTvZhq͛cz|ѩk'Zڬ9\)ARP J*GXrJ]0uiѯJmuҀTR ڒuTnSKQXAMqxXa);gٛ[Qϴ2DՕf՞g96pߓ^̇F!>" ֽ#cҫ0o=jjT/TDT)!x%Kra&Zp&\Y"q69ʎ%ZZS/H:}L%Q]q~}lukgX~D KEi5hրZW54Pv[s:7RjZv:7o? HHH@jj*n{9_[Mt_5PZw_? ֖LL >ד<~QIJ5qqf!ľ}h|WlD䬠4_ݺ z D#Dt<㾺u.)U[)$;ϼ=Ϋ"jkNLL윜H|>hQQQqvUU?!C: ":DkLBk}ʆ :h] `Jg9|ZԘFvFvv6^bYT|||All;}tv" qZ[o$BeP1>Jn~kM3Qp \n\qq-ik|2¼nz*"PrQ#xaYnߣFǣ40O PJAk,KKK5k 7o9y]&LxD"Z#K]_W>ҿ*ztYF僮 NLD!&j τPB JR`tn"rEUUBD+z*4 CYe%j.((E*0D䌼%m3wQɗzcS*ڌE_GID;OI# (ƚ *+>th}%e/5I#7?Ng&ZwLJJ:qɹ<@1:myЇ+vV2ʿsOqtf" >%ߢƤ2NؑO9i>Z{Gen IDATYxw ;v옒%Km{ZbQ=$`@wAEv8\KtF"rMpGӋ\ #1|8l=-L=Ng%"g9pTDEEiSN(++K_lY&9Ng%e'&&Bz'DDD[zrjr#\\f&u(cc[6&hkx]?g{^P\D0}srrrx< aY-k0|W 7P$"l_[oLҸ){ u]U.%'?ADDDEH)H){vݷfh1`ς *l/5jw5aDiM2(@ B{x"gDJRJrB$ᰄypݶm_`v{QI)hڴimرcGPJ ߟR^^uVRRRR2v5c5nCzL*]|h-[}QY3nԶg.(酰LE˃Ҡm hո+\yyy.s:8Lzcdr&ynl͚aΝHGRqvj*rvN%"G3vrv~" `YG!_佻sg]}3Q$kJiǵssPJo)BZp1k5 a.g&LӄacCr?!Y(96~щ(D7N@ll,nqnFznQ}AKn櫨ATMb=N-ɫsg%c^/t"x=ADoĀWq]2(x(DLJ,:1n38Nѱ-i4J:VfD/*v?tN" +_:8P}qcj4]R 4b}.\֡)2~7ܻ>ĺQzDt<'?I3!G$ض0BÜ<`yi& P?lb~rk`AΥ%"$Ug&m&mقmh8gklۺuklٲ۷o=MDS[[{W˖-u{ RJDEE}ns069m~FF5`0~^>犂Os,i3^ٴ۞78ľDkן?Ƅ meЖƃ(Fbj50Vfl=ַۣ~gAVX([!x<بzBt~":{\jj*)KQ} <}Җ-uw/nZ}pߕ?~uN%"gMњx_"9,;=;W*HD T(Fl ~u/Qqe)JzvILADR)T**=m7 !οyqY(Rڵk׹yGib֭w1M$%"'zRחO߼遊+^alV`Fk&8?n|Q;ZgϞ=X~=lر{.Zl &w}/MD wh=Be-!5j Q^-ҚDTo(:Eo@a[|kUgԜtEI)hڴimرcGPJ ߟR^^uVRRRR2v5ׁ50^ߓ0-ujtp@]q+aA Fh Y]}=7Ng&(,,k@)UWFmR_޽ b-F l5ᮟ3Q ?(S">Y X|5F" HCʝFD93Y>P\)! 0L.01G$"q %0MW7g}VpSw}aNg$`@":'+˗3!⌔c՗K+޵/C΁O8Bhݺu;%.HZJK(!T ؁e5e쟻g7yјoLD>?D\u0 ڀcPpFX|<| G%a ":>0cUo=0j\8Ht:;oѺ;7+QV RI(%Bd\,&rON>7tɉ(TREdd$ۇٳ͛7Gnn.Ұ}vddd 666e޽ΆeY_:P>p!!lH>κN$"GѴ+e e`#Pط"a1k.fZ3tX" ;vС @mm-ÇsA~~N$>11q\˖-&3׿D Oo7o^N=2=[Ft (肃P ۧߐƎf&:T)-0w\ҥ PRai.p\&aP_Đftb/GDKBp~Z=Fk}!&&ZD Ӛ~mFݏ h0 %7?WX'Fii.^:Ο _ӧcǎSSShڴi\~~~Ayy V߿֭[_\|yәqbR{}k׮GLL k͹s^ 4uƎ+LDޑ&[uEa=p(*e anhez2Q !H) !6xp-]茎۶߰m !D/χ<ض}رc ~GhϞ=iiiBSY( sZe6ՎBS$yCi2 m>Ng'Soʛ{f=E ` RYҍ`@!@,$%ط E\W-GNG޶iR7%`lFĻ݈<<2\.|PRB6"nu>m+X@Dg̘t)F}z|C~ i# zʷ`UݥNg' h<&  JJk$4ͣJ)\.hʾ-#M/ecXIFT1G&;8qnSw[o7jԨv;Bh͚5ӏnݺ,\S}E5|k1ƆaxX[Ev5#Ɨ~}_nD \xxD԰zNW^gZuEG_nFp%en x=6<.ĸLb8ADǓ`тAm}@֔.9mDqZ#*Ng%0uK^&.9r!3ZZc2VСig;{ۼ^D mp nJ5[Sfoe@Z pw9bK^5͓c g;E/T*^zhڴ)ѭ[7?v:7N^p9~tR0L7Du6\|=ߺݧy;:n۲vn0s b@":}޸3 ks붰WêN(8B 5xh&V9 ;4 VH)"ҰE_lZ+ª׆<&QúwDkԘtC/><<617=2CҶ=&j@M@4 \\02&_acAEӹ۾dPjDa&tBmy va!<) J'ZE]nxݴ97sNZZcMVqSZak$ uݺ5l >v{E>":RZc˖-BTT_ %RDTߺӷpى(j׽"1t.gcOMd)Jhly`w5@/}&>*"9*6lyzÒ6+nsc]tV"rF_ [AHDӳG'XTL2%"!0MmPF=>pY({\jj*rrr.A$"x=ADqIk 6Oͺv΋ⳕPue47I3+~jشMDm6vi"DDD`˖-YfZ#;;aaa3f}뭷r}QDt2 -4l!$ $`@ 9D#i鵇ph L%`nrV]97t>" =!D/χ<ض}رc ~GhϞ=iiiBSY(LĄW3RS\Ź@qa] []ZwU5۵PVgD7nl?>^oB(QP. a(0{.p\&aP_Đftb_%%l z0ݱpb؍Ng#"WI5`,.NExkny|vO|l9qNR R=3+Zh:>p:ѱ,_<@`a(5ޫd.w7$4~3!1W-5}ig3tv" ۶͢"@0Drr4Mض h߾=/ bϞ=Xldf"rYR!6|νw:ֱ5Z+;7+QV RI(%Bd\,&rON>7tɉ(Tx=ADq\AD~tn5l?AD3`t+`MM]r4VCg]e(C(\ݷvN=y׽:4D:}uqtjjM6/(//@A\\ܪOںu˗/u:3 Jk(%Mh%LӅoڤA;pS3o>sQh sZe6_Q} s[#[D iaY,˂mGCQCtm5͉D Ě5k:nݺcD!?:6)l'h[ ֖].Ww:2xj$Lo큤Sr:7ȏ.#¢qLh@xf_a+ nE/vkCJ[u(L46a@Vu (Qx8P  <+"-iacMlB0 .V/Q nmƄU3^?sۜ>":t!3{Z%/ ښZZ G]]UԢ+W dq(QxsEzO h}Z@Cc}n}[5F׌_ַ> HX|PDR&V B?!DH@!H!ġxaBcq]gLQuZDbtwwc= 9",_>'5O+[E\:Wרϕ.z _:--mii޽{Z>_N `wم٪7IUtΈסX6m5LOgQagB۱6P Z" 4^~/םnJ!D<Ӯ1Qkݠ$lѣ)--8d2?;;o_:t(nʶmXfͿMQRBq0sKQu91CK>VmOX󚒨A'RW;c".8t$}x * ;@V^=+yHL&R k-D(//'HЯ_?jkkOaaX!)'p 'i⸉DɅ!B2eJֱc^?g4Fp}5w!gϞ˗`ΝuSLiŊ~م?Bkz˖.]J6Ac&fDmTBk=]k-( kur IDAT:xY-(9ed 窰3 ! K)URѕ,J {pX=UUs ;R]%JA?ԲX5"۷c_9^[_hacKo]FSŋTosym4)Oz8v8[S8.oS(m̙x^ <!2C<& 1a} D"Ĵfl4q$"ujsiYÀ҉ѯ<DbtwwcA)EmmmIvDam(mNV/|j4wmq:Vou>n0Ǎlxyu<B8΁!Dq !l ;N^ޅO|\.IΝ0Qfgg/p ! ABzY^s>HbY-cU&aBV`ԥ#*løA(|A,3a|B"'" !{i77_I !21>ך@>yU?_2m|5oIhZ5Bu^Du*?}]==t2D4 W5 OOuDI/(,{' kf|ۛC+_[Fԗh߯,ГUd׵D\pCąHZy% |1B#js3HwB$N&;LDKAz;6' RVtI>T=ꓬo~l>C@x+Ddp-/qQB;|/].V3;7(zn 9t.ͭ@iyG` o@QM2'A(VrB-kNZ> e4F6wmE+àAq^;T {53 ! k{V8%%%DQd2Kss3Fv\!DzBq(rB?ғtV|쩮!ҶښA*@  afd#44๰ !O&?Fk톝_q󚒨A'RW;cjcP^БyVW0$B|.8>lq_\]>W*E.~_^6ʖ`M&B8`ΟoZP\} 2*ǟɼ.3nh!hfD"&N8C<c̖3 ! K !ru p&Bii)KwîΗٕ_8?F#=nF Q4N:;^~\.wc.#NΝ;F1L&CUUտxw[|ű+hZ+~߱mzgaB~X6`cHr!+ߔ I$Jݚiyoh4J&o~^BP} nn kwus]ѰKM.()S***n;vs!N3jԨa .|]sy{Z|vY7eʔVXᇝ]Q8Zimy5*hQJMC`sPڡn޾%-( #8>aUbxyoI\S9pp;})(HJb!D\e̙@_obu}RRB"g-CbrDa)~tp.LD:I7Y2G=^ۛ0AX:Ի.; > GU18""b-U/Ls\%7(c0,k  !>d~PdtJJ]2mϜ*XMYu#Np*{ gѺҲ G6ҪʚƁxd ?O]q#L9M͛B\޿tlCiCw*_V|S5LcN^^s܈ʆWyBb޶LDgY:<7PqPҿCq^X[\qL}˄'>}RG_1XoD;y2S>>9ckg_=4[c^y&i!G},հJƳn:CM;+)DxWkk Hx8R)/^$NyO:u8D/Zr-B(yb-߾c;J7_}uIF~9wZq+aBNxf-OE'XV.d@;(vmM+w]~&B|djQgo];?1tРX4oҙ=Cj(\tg ?vn!đcFiE}uiyv/d\lO%YF*Y Qd\'3_!,ذ)k(K4eS3?f `پaBk-Hx1-8k!BLWOVY7۝>]^4J6A7B|(H$tСrG&/7n\n1üy}WعѹE 1:Ӧ~aԔԲ-v4C*bÎ /> ;"\N'`56hCXAo%kn.gY)uR*(--eÆ dYA)EII \Fnvl!D=#cF~_~jjj>|p1lܸ͛7k[pa.B‘BCy7̘1Zoճ?76sLc-g05k4Ƃ1ueE"SOX˛m|bj-51Ҿ%@ġ#īm PU!'BR{555Ap`G<ߞ良;veq\M,t%ǡ} Bǰb; ҭ-$6cg k[.?!x/kc~37$JN8qϞ=w}7w6/wyǎE3agB35n+xX!D(| qpz.E)}UU T!;%*GKǸ1E41~v?|k\Ӧ !B_H}[&(.˗/㥄erܨmds>|Vm_<´2똁miIg}y)Dqk36YA*C[&*^~O)/k-n:?>f8cgԚ'ijĈA#(b[lڵYKOB3cpњ*C^YyM4jIf$EMBàlh~W6/4JՁf7Κ1WY!lں:3 ! "aE)E2$yZ(PժR[9e˖Q'qW !> "(hڂRj߿yhZW ;0{cNj2v3؛ nX)Ɣ`90Sky)D1#8fZKMeo8(qHq]o7pJd<\)Μү1Wgdu ٝOR%iWE`&R~ٖc/;"\rB<0usZW^c~vV!DaI@!ߢ)tРAoMҥ8zH %=C2:!y!Bȫ\k]A<!Jx%tf}ԩ%D"~in>!DaטiN3Zqgݟqu:&5kc:c-u18+ȥ*fݶ+ËF-D6!ć^Ox&]g`TY#B$;6]qϻ?q-PBp !;m-A6k X A/?loO2sp6<-B;v=*B|r?^B!>ʳek;W]l:uEnmݭIj}u=iqمq߳k_!?.k?q\(cQWUU Ty!DqB!㬄rqc|T6Һ((k r! A0l[aSZ^; =kHvT:y`}󶝔WEQYŮm|Vm_<´2똁miIg}9OQ${8iߒ{Jm! BBv!?6qD"ABC*n7fo-Hg^ kI\=Db}ncSξl%갳 !/<vݺ]C8x(&;줧h4Jkk+w}> O{M/(wm6t>;?L>q"{TϱǨJח B@xxrqḰ oD=8zp~ (6 ,w۶m1pu{{;z2Ll6Gy!GBc ;l_]uF{Uu޺GNzlof_\$yYz:dz[w]q䩼&WF7<`dg *"FzF QdU~䵥_YvdYj%g32Q9N}عaZR@qfr~X>3%/~ckfcR!GZCSˈm矏ݸo-:(6^Tq0v,5p|?Q7(qwVٳg;gkF[[۴\.eZ.[<--}wrtn+_ !Em&hݹ`sӱM-o2V"Uo#{w/(wx xR>%F/Ag;Iz!8Y'\QPπ$H|рC߈LC@MUvEJO!>8TVV,Xp]6eooo?Duu5sg<ϻ9x&Bxg*OiϘ1lɒ%d2***6mWf Dz;DZЄR*]Q>8`-}9.vŰQA+A0QĜ2#HWC/1NO[ v^!DY˅)`UJ ,(k-:.L\| IDATB8K[wQ&V𕒯_ пǎnFeQ[]O&_EMdowr_U^Q=-%g ³ŧ9r1>ZkYB|>Ϻu5j[lAkMOOsV^tQC2ش y>pK% ?R )pL!DX,k0FS[7FP+m컽̾9b8AX!V?fP;A'xUD<6M[عg!tx>aSGbwcZ:iYy>!DzBC`ŋۈD\ w6OeԟX(ߋo#-66>-VsaS)O\Y7ډ_ZIro?c9ēpKw>]6dl6ĉ/~\1!8^} t\[үq3ps&0BM.(l^5 b^$ئ5xQٍ(<4~o>!đ'}Ӻ#e^v5ٽܹihtTv~!Da w (%-صs'U+9TזޑVEg-mrK(zTΜ;{v\'v,mh??z8LDZ`-|(S.DtbD+"ZRNMLo8&p-~ˋݨ*`oZʐހ3e0( 4*0@L0&Q6#-( {})؛`y&զ˪¨QijosIWNsaBy^4:',^kE%撴SrN;7ʘI9>_Q,]ٹӇ^fOV˷E&"něW<)2(6P8J8v2Y\`-aGBDBåJV;7Ͷ[ax Pc+(#OC!>=C6eeNE¼&UPw1\êH5-z~gϖqBt pC8БwfdC"BLRq{4p 1xkF:oXKlZ% 3h"gL9dVBO{`k[k~o'ů`$l^ro<HyBq8z| J'uϦ_?wy5k`Q1[1?aBK !sɺ.Uy(K~_ΫCgg'=yadBRjرcNzzzF|w:NN>䪺{!BBXzORA0+[O3jռrSL⋗u]y|o;>1!]:8};D+5o۱{ӫp#K_wkDi+#BPD~oI/͇f7`Cq53QX[A!Ђ ݶm%===y1444\έL&@&!Gfȑ"'C=6FiM1\zH,xn1CKg1 C:;$Bq؂ fm?vy_ZYYy8τ]/|{fN;,{?<ּw#((AQJ<QJ:P}4!>54cݦ/q2bqp܈e'o_n#FafB xO7̉?}NL*455]rWOܹs[i0*D@}CtoQF#:gL&sQJM;k۪yڨ.ʍ*B#/Hq%O7a QsODodo;|1y!ug[O~W&'  ާ !>ZxDn+ʧ#)5w8<Ja1T@kBy/*8s3pw~qGe"3 7&cRo1XcFY+W_7_Խs ֭}ĈGu\nqrK'L@6]:ydlv\!D!Y٫8$$^n=":_xHt:ESKuO^[1~Y̮\х| Cɀ:Dr- -Fc.`4vn!đ:nv}}=L5L>%KĤIHR~z &DxGZlРAh]v{wК6 c 7nd˖-f.\(B?!8|Ì3Vg5kNn 7c4Z[Ip˜Z\-C Q~@g6gh80oECWu5Ux})+DQ}}f8C&?Uw!xT}`=0"V`UV% /E(62~Bq0A4577XDr]7~]wѯ_?4#SHd~sss.c ! H)z֬YEd`ƌ,YD"A*%+Xa7kgp +.( Z0uE,X,X-0(:ATAp^]]ݱ[?& (x@!DVEusZҶ`zEXĬXmm_AkszFمgӤ3%d#},zRK$Xj%<|0=ogl:B&ę4b^4B[OW*ϢuaGB5}Q>qp"&12Cbrm*Vue_-~@ 3jw? 3p1۠G8Tx2 '%嘌b|9Bc-l9Q>F+5&xwQI@!^ZkR(VR}Ec~s_o0(HY|3?r|~D΍$3=t"8}T|"(Sf}`WG>[ !/]ɮgD]#I?I`}Z$'?wxd[r 6cM H @*@_$ÁT  pbæl)i6I.-[V/+m<S<~_׵쌮\3skqټm4mSuOqk/8(^dzx!m))0f_A6:q#NBuin_"PcQC68"R834)q#fqSqi(D> !ľyBA5\{虇^8?[Y4ݐ{F,: #fE7~+s ;"7^[k1PXXIchoo'PZZJ4zf"H!}=gu7r()r<4Uy%ajtع`8}|N{*31Z%;~9e,A#p01(k ݃Nnƨ4^ر9d=ʀR+|^1'(z&U kZvQRVƛQtvf `cmL)(QÄuM+'jg bƵh,"i:swQT\c)ʇn(2gY}izfi/ ]U=WZ_)ܗ/Xz*nØ _?U7t=/\9"GO-fTGŒ,ȡ <Zk(%%%3IRB|RUUU3كg_3g} 3goQv~!ā7دkq8 lo޼,ysE;K,[^[Ґk5X 5m4ZպtX%Wݼi|a Bk'zkB$"sO&)"|y*jyZ8?@q}u!b"w÷Xx&=MiY!Dٶm/W@'db5eWX ;8+_昁gRFݻwgGQDu]7bR&"ȣHݻwg rl!DseO;+(F;P|"}~(p\k|Kj+l^*%0-W0 F d y睡>D1{aGB{L_=]iQ|}{!Bl?cM0DQee%u݄"u1f2Î-?'Z\6:aG`Lűk A` d}b<+!R0>x)Ȧhv*jydY(:m;QjlGkݰ !rCiE*ODj%вC|xX?+?Qty (`K*#CB _?8{Xc1hcזIJR#S!}Dw!%v!G8s?+pә'C,ȩ@ OF$۠1X4&E;#/ H`^}mѢEg אB1d-;' 럟dw/1m8EEShxILY®!-]+BJe{Z&9ʹq&8wX(ȿ36}H:oday}R رcJ)۷c8D+Ϡ!^>h嗵Y[RE+ChB]ϼFaZK4^l6K}}=HZxQ4}EKg/Gә`$.0}|%#ieDeit 넜^ 硔B)5!kb`uVbU7&PۓX w>pq'zz^YC&Reڻ;;"wR˛O~ygh: aȑQፍG6555+[;ZkAܹsC^#QSSC:fg.v׮jg_}-c>rG17@"Z]A$ x^͸nanGŸ'Y),+- ڧ{Ûn1M7aM5?3]NZ dLT|HS}@^-c,Dp\H$y2I?9fx\vE1ՅlAvM,1*Ri+ՃV&v~!DnXe/qU+ IDATЛ֒Uimppzs#5GZa޼y466[~=f/u?] S ;;hgK|| =@mJ!D6 NX`l"mym wÞwo:Nsat|d/cG !EB)k>fH;oxdU QAcXd B{OHti/_Rv&?@Cc֏>hz}պ#yˋC -ȩ;[= Ǣ]BM3̟u8M j4mQ'b˖-r!aBei .g]]R{ag:^b!DtDkFLYF.0~X]L'EgxL(%/ ( ֘D_K5Cs%8ĆIc-h?snzعgR듽ǎRߜfڸrpvf<2J@@Ittz: p]k$YluL-Bk)0BBخ4Vi4,"/ ֙`h$#Z`ڴ1YwEyzVWVcn  Y8l_'{L:;w}ᵿ9vn!āבaxp&HCVg]5u4liyc[ZꔫPZsٴs5zMO]lw2YW)z Yߒ dNEhL.Bi So9sTK@ՅQqq[W} k6ԯ]׍8ʒ ;"r=!9O!ܸqfD1&p}+dtuVR&x:BZ'\&R}Nk-uҿC?ۧ>(B[RSTS}?P`-ޞDv[S:Oυ];}3g\YIlŶ0 +ZDp&e gR`,h oTt4O߄5L8d7otQ:k56Î-!g$`i0EB:ݍuTM#gTj7ZkV^qr z#-i,^Ə,%3I\`JF/$ˈRrz!D.;ٓv~sѸqnkO3};\|D O=uaE!o}a)PiQ22]zsġ?}k+BybRJ[f)⭴fs;9D ! B *Ç;{A ~xkӴR}=*|8-dͮS !re׮]k׭[W]QQQ2o޼L&رcikk; G}\eѢE}}}}/T*57%j<l;wn޼ ;W8`7|-J gůϼM l a%%ECi}pǁ &\O>#ƑջpL]P8B\ٟD0qr!DnHVvq#qʈؒ|Y!DT_|gGcgm-:cฆ$BJO!ՑN^#v1F XR^VJKǑ B򦦦ӧ_{yh4miijjj9rdT)uxccMMMJaB T~'_=bRAdW/*oSoA?b܊OP9؄Q۷tY*2у.8' ,ւ¶;S}8_-h:Cavh^-/jkI{{ t{wB=R^X8=.>v,!D8xzÚ> {RZ uvk[ӭ**ٶ(vn!D&pI}έܺ+JXkfL5 ,XY&D>B?YB4&E%ޝlJ75(cο?_^tLI*(:9Sc8upm;׌v_VvwZRPBwoTk~o˘ lGi%0#z؊к ^GN Hg<9O't?҅ۮu%8ƉX"%3J*B";B4B{d1G0n4^X7bt|'ĘBza'mت*|--#(5u蝉,H4pΓ]X[vn!ā`汶m8kcеEy1p"_\p/^t:}R k-g^֚1cƠ`ʑeu='6v^ *#LGhޓ; ;"z3,o׎y!+n)$"1=hp@$[loJ`- c R(^D%ܸ/i20WBQLZ / -/"rc=3_ r yga7{/Z߱j2bd}oOʷ:L`yw>+VxJ\eB(NmAw[^#d [ If}ԮgrJ|E;7ߵ&Aq`5>w.Bl#ZZ[|.Y9>MDh-)~o9"B :m6*++Zu܊ $]]]>ZkGB|}^wuũT*f=z:rM6uVjkk/_ 9"RB/K,ټp+cYjc:15h:l6˦MAk-iOU&b`aRupǂ-.-I& =40sL1lB ڰ{{sV%zZ^ء?'VJ];fw7uJY!D~Z%/<3 z{{_>y^5J}Ak]vn!D(̞=4555b1&NHoo/{wcf\};,-m@LlE\/}~7ǃ )_@O&аdTڴQ:֬~EXiw:4Zb1V- )",/ۯ# (e^T@RU &Mw0)v'>m h Fw }~+_z1go;"7ϟ/{r,;戡~`޽{0"L}oQS[C'UuW'~пv',Xz (#fnG/1JJ)Q(Fh!Dn.j\y|zG_8VRegЗEjP/;_/YX&*uB W.9O!G׉"pʼ*['ٵm,QIia aBqW=f/?#7е_=1=hXU3g&R2z_\×.|;_k ;"7ֿݶ{Fx )OY ! ޫ?^߻Kc~B{E8Q"6Xq8Puiʠ})Bܱ$X (Ab ;Ɔs}fJ6wgK/8S4@ &P@+X1Jz /*PJ Sc}2c_s[jё[Կ1ȘBVa{zҞ<+tt۷ulưs !SO{YY͛o1k &4V}.X5:z;x*2j2V2, <|Be d(nczT2l9 !Y~ڎ*RS~s5l4'XMX [)Ƚq `R78&ۅ%r=!9O!k qڅq~җN9X9er!Gvի?1m4Hx74'8OEETm۶a]fv!DH!:f .kK=H"F-ZXC!2B),>zdpQ_ci:[4=qVD*k:btp Ӽ^|*L"*4X c !ruPb A~*NFJm~!I6tT`UP92N6Դh?>ƘMiOU&b`aRupǂ-.-I''3 [YE{e1|qع1{%=6-AA"K(xc;bnbuշN޾AַZt!|m!+X}agB mxiI Z{zRK`,GdlCo2ָzb#]F&"8;QX"p w7Ը>B ,^tZfϞY5cƌAkyR)=еagBQG^H:#d+ŋeeeKzzz-++[L&TQQ]v}e̙477 ;W88?p hpS뀵[rD0c !B @ʷ:L`IAX Dt5FqvȦyBy^5J}Ak]vn!Dn3nU6kJi>ۏ[hTЁf1L?h?%`/`l2^8Xh12UR_K !wO~c eٻs&B)N o;􏼃&^oĢyH, ;[S< Te^mSTs !rCkMgg'UUU477dPiEčL8T*U9cӮZ;̙?OQ6ffxJ[ 65`5B׸u>%;swZޒ^{:f͚R سgnVk=kv^!De1o8X:`:=~_#޶h pckYz#3[gY}0A `RJ gl`е~-2*92 IDAT5xOw&j*l[#JۦF(Le)-uu\P}_R!GZS1FdZ<Ύ(D-A>ewQ؂{'?os߇_ X=Y6?D+!DaƍL>55558Ccc#Ѩ<"+N\ұ1N4ljDZq@ Ji秛c;"7\A{kW/Z{V}"xIsnÎ&*m ;:2Hz:8 vV!āUSSC{{+8Ǘ("lW/93Ɯz8Lg񋛇qM$q MsL!Mww7(VG kQ@Cم\O!>P`YLwmkkܙ EY '`p 'ö ?Bb?Z{jh޶Qʙ|< z 9r<^#G6^2etŘ#W]l#:,lMĪf={kIn<vn!D b&Р@?bҩTɄd7_-߻*8v`No?B GΜ@sТ)N@"Yb4-͊+~13Or&;4PGmŽ/k)t&4eJcU?[m͏yAkMgg'UUU477d1EpBs |5b1okkYէC/ȡWz?{kN.65L>t:J{gu/~_Y#WZ}@7XzJcQ&-ΘVo[ŋjꖧ !rä@@`Ro_[d4i 8[ضmojagB1c J)Rۯ W.D^ !ľyBXkXT5ͭ'}b1ӻvjcc'N8uƌۋR 5Zk***444ҲZ{o!;$1.locbc-6`#ۙ'a"B5EN9C.ژLzúwgKqɆN ! ՠ֯%RPF!`/D6CYM c !r(^ۛ~?bΜ1dlB Pt j&=U7Z+Zk8uжt:y3~hfAA{kFy!չՄ ݒBո3PCx44ɶ]MBs\09߼*!u<+.. !E~ȸOӉX,Xġ >ut.N޾g <c  TooOnKY+twbKKPJFXkɬ}3T)3(!BOO!)Ks*^ް_6beތ4t'پaK[;uuun-0_R3O?fT|kNGԉG^E#.֜8jb[_^shlsvn!D\?;66r_߿w$CuFa-EU  _0C$;yVVnJU¹[~[6q&):}80{kT:zW4"TV?r, ^4(/b5%FSyz5)ey$_j%rƘS׶,~q> ™".=I+ !ģ7#G߹g@Lc08@ B\B!;J4B{9qhC)Y_;߽X&(Nç-zvL^}s3o,k9k^}4. ;"d|殽Q;>NwW٬;v,[-[#H '1?飏>Çn:"Xc wY2^UXEDۿsΑ7ξm7[XyQNsk=ȚD5TS^˚ !rW߾/3HZMwFKi,<2{5Ϭ!ŷ~|aB1^{YfPPP8[9Q.;e| 1$q~N: !rgp:/aZ:Z6n${gqgԀ:F[;fY!ћϽErB}?㠍Q:!D|?%r˦ ?o޿ϷWJ}/w̲iãU: {Xv];nÈ8 2̸r8#( lJ@@QeC!Iwz:@ x~TU]uAP0L?:u1n+rЬE u$zwRK(-{(oܩt~" ~(8b[w})-\XUaOo~D,˲zWo߾'۶ )%aYp\x6@"777nݺu\MXf…Y_~xs˲Y pʣN֐R" "++ ۷G˖-'U\1 nL   |>~`qى(<+WѲ,B!|CiKU 1NJ4T"[@ ڬ{7L  B[r:7M'n8WADDDg#藕ucǎcСp(**±cǰw^KJkĉoIh$ 24 5 @-Z׽ haӱ(lۮm{mۏ.i*k|9ޖm-X(m ZZH9`Z|l EtMJ]CD)tOnK%uEPyFDì[`g2]8R ::!4l$* a@Xc=ʞyN'P_[Vn,=1!y a6,ۆQWJ++'4ZksH)q%  aHMMѣGLKDw;F|BYlb~ aX 1"}'^c9~e |z D&;ۏn%Q$+ :!K_\,xs:5BAtPR+|W]f )Yr7TYW;οA:q>~QK,;qxs{fߗޞ;væ%ؗJ(tJI^v߳6R$0zHLLcDDtV!@+eW@jhY BA+?^hWA]"'^L[u[^e!ujkƷۼh,I-UY(:<}',hܛo¶*@E4,9:4GAk?oQ]OE+'p  !M>-nQ\ջE-.<"&~ /}|JwX6ixiWs͛{qQwKDa4p:9X@F=ꪱu@pΜ9I'[t(ܢᔡG~ғ9"e{`|{w~_!Pc@&x>^f9(|7~CKzM w[?SۯʝED]^wHxyC(;R2!mT[!!1ҿ7c?~D,0&Ʉ7 peܝۜIDRu5_iNu4E iYuǁC8pҰF6` !hGnHA1?eQQR-0&맚uk7ÕZȐ oNWGWe\MP Ƞi+h[A e+(! ZJWȠw]pT0 <ᯐ~]@*/JK7Bw:?׎g\wWwG,Z @ƒJ<-'Z꿤j^8j"sL*{?׽u[thfoG\to/ _d9K@06 T@!`+,KjX!B @( 8OяaB) :8" m9RJTVVe˖(++k_ƃZ;‹'!'LRx^weF́c!O"=ެYAD²ik4 H!'6zi kv{"K\n=n8j!J r͚Z1gZwM̂Pɭ=ZD>ڶnipy<ζj K[DDA ?t5D1:cg9w{Xo/-K@Bw|%ߗ~tn" )%h޼9xLCӧO}mM"i|>yrLb|;ee4݀D9]@(t;vKxc=*´2Ί txaQˏhH ~w:XgQ44O1&Lu[aB(\D&bL4Mpcsŵ'D8o lۻD[R ]-Tu]];3)6 vFtDKBDF`Pkqqqسgrss.sUWA)?l͛7Ǟ={x(iBw.4ddӦMlѢ͛7[\\aJ)9L'h6rhk E* Q\*nƛ ^ZTn" }8 E3pcmZu:/9'** G萔X?掊B\ĵ2ش1!\?AD v͟so "^(@DtU>+aDMvSN&""ö%l( H-PJKATAΑ Ys)W?6p)#-Y!@+QpBk P6@tZU %kE5bހC''"B)>eMU=LGDNQ_8Wn,1:5Zq=&QHIIE?ptut-#ơu_?)h#RG0;t}5Gad#|7aŤ+عuӹ(<fˮ J:x ʷa]r2taH`Ji1/QRA'QD"jHCҷTZ;.ӁD(|C@rߦ@ ?8 _|ҤIyNg$6j~Y'ϵ/=C{܈C8\uThߴ37I=˱~PrI_(9~pZ3K}tXoϝCa?%:$apvp]YR } $l@]@u 5LC8-"ѹ`":?q_MSO_? XW  HDaZ=5gh\ Ԑ@4* &H5lA*\JʺRB)iujVZj(‰bNDa4vWN˖-<))i@rr򮘘!jkk˼^O>dׂ ZBW~DFZ#䓃4bY<)vlDz>/fݮieڒ~c"j%OL,щ(ɧ=> o("rY{c(`GIDATـ.wU! /le RУO܄n0D>Ri޽{s\xk֕75&^>ϗ`F 0r`(..Fjj* l'"o (*vy9 Ko4eLj-Hw8.Rim6=; gMD?]s(9AD_@0{_a) Aas qYm-݋_a&v:'5/JD0kӇ)<r4DwV`eJ[D(&&1" H Fv.5Ji "mS`! _IVf;ۖ ,6 76^o;a/w:t۷mAk7bKm~jٲe9G'"\*M޾=E t4rs`t޽.k'D}\Z+8i[6*Ng"c9  LW,@ Zzl<3+L@p805 }Қ`}PCyIXtN":*\JJ( R ҶqPZC+ -5VJAխZpt" i⪾s5`K KK>?mu&-9o,1hѬt\~%3M`]Ȥ5 mvZ)hՉߥVSE#G~6w^{~Ϟ=w`XXR6B%_K!_,SD~{_μדg}կЦZMw$G#,a{h~s)ʎ@Q6Q/~WHDQ`!Kh$EA( dkKX٪;a @D'X*׮`B*@aRwv-'"R͛7txRSSگ5A+LsQx5 _#OJ]Zޱ&-co:jpщ(|Ǝ[`{affČQ_|1QRRϗcqn @AD"`iM T PqCBkG]GʹDN[޽h0:#i1Ҷ(%,TedIbw4PS ص^$vl -lcQu_lŁzkBHۮ[oϞi2W8GJk׮RJ\r%ƍuIIɿdx?[e˖|r:?K~wqd{ q4.j!]N߱&gU%p-wEuj8{,>p+arؖ^tF"r4 k(:mniBto1b^{9ۜID7z >nWZ :k Brt;*^ > 4@c1@kz.s]DVUQVל"չPZmMrC={7;䦥߿A)e{.|D,;(]-cy&N$յ 2`PQ.'*q.19,aY>&x<OeeB)Nd$"hۂ1G\ Ft (@I 1CJZC &t@2LlkCk4 \.apML~J޺zȚ}oucuOJITc F|eOӹ(ZzkkCdJZBh0(dggr5qg=0 >|RJ۷/L鈨1lor_Qܫm.UwN$RPiw0LJ5PyQc~ F"˿ 5 eY}^OZn"DtҒ%/=se(ԽR4ReJJy;f}Leԧ:1"_W!5?kjq1x-^@籩ԃйb>%PˎYhax3ܖve87Ebn:$m mKO?(,-ԘJ OԧPVN<*0{G.{)~ y(=ywgo۶uzY(kKoʷWAT 3Zs bsq7h P3 ӹqж%bߏT Q@b i)N}~.W=T8p:j!JJZ@HVUM2 c9(w2dH: DDDT/11|Gv~JiW1&`? "< 3r֔Z WsQd3W-x*7e97<`PcMn%\ Z Dլn'潆SGɾDo;j.c<6e v/t6"jT72YTUkq7kD+>m}Q)]MLDa7yǍeYSN " oi]zuy(B; ,B(eY/۶_B)%EsW~_W,aY6LD[UuF[]syÃ\1-1_ƮGߘHD;Dδ#6@ WTNG%"=>$̻ocS8DqƦ_r;+upoPh06 5ogIDDD߮S'[慭}CDKC}~.o=[@j8]QV:bBCq/QЖr 1(h.hhhZ[a LD8m <"TKz~mw`(VZ @KhQ"ۖe]"߸X@qݘYR ұ`D >k > M4 ,.aykZ'*H~ (ADg:өY(-_@ 3 n ~%ԪPО~ ffȿDm}6&o[2Z xf sQOʶ)BR!O1?EDDDX~ݚ }Zc{2%""3""":W~;\k R\)ers=t&"rq [aF ? @C@P)>;& }Ͷmm{.>9RR|Tpg$"d?HkaC6>Z h)~W](Qɍ]0S a0œ%9mKnB>,ꫤJ>1\ xDDDHKkBP󕉈s uuw@ɀ ZCcu*j`wD0|%-56 z]+NYhh9>&!ޏ4.u0p֓5“y/NhZ!mc%[ifAIو`r"j """ Ozt:5N<=Oݽ^iYV^LLׁ@`?Gݾr"""b@":=ue6sQ3gΜ;P|1c2p^=Ss1c•c~e/j-boR$""p:hىW2(wll!{sܳǷ;M3P*Z+5B4-x'.Q:E KBDy`ޯ~ߖ.bә[_rB+k99gz"3Qt;nUyyN%"Ghh?|qr{ˆ"OpŤA'x,DgÈOV>Ft sjӹzFwh ?y9=#FG՟ PL%"""%""sk:QVZ7lv[ֺ;Cd@Ak hޡu1h׬_q@D"""Xh?1c,;{V۶ϧO"ѹ`"C ?VIENDB`PK\))default/views/public/img/menu-pointer.pngnu[PNG  IHDR x0}uJIDATxc`L L3o߾n TT[Bd[B$[BD[B-8-2H-IENDB`PK\`]*default/views/public/img/grid-sortable.pngnu[PNG  IHDRtVIDATxA@ 7 OnՍL$~,I&)(R\l ll{r}>m7+J8{WQ0\.zfIENDB`PK\x1default/views/public/img/two-coll-divider-top.pngnu[PNG  IHDR9sIDATxMI DQOLftLY,XJ4xeBitQ+!ÉzSNshp==CZK`ƾ']AZcNjRRJ ?ZKDB<IENDB`PK\_^$default/views/public/img/body-bg.pngnu[PNG  IHDR)aIDATxķ00!*`q/II))+5esS!bXJ9SvYc`sNls_lK1IENDB`PK\{I+default/views/public/img/default-avatar.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLIDATHݔAo _rQz#&m0322 OTBZkxcDeYbCȡER""H)'8m9{ Cd۶۶Ak}4M0 1I$=yNI=?U}9AUUB spΑeo !9u]aŲ,UUAJ y@D(m9ui(>mJ)4Ms ac;cIUhoga^8 IENDB`PK\+ZZ&default/views/public/img/layout-bg.pngnu[PNG  IHDR &hf!IDATxA w\w-$ QsiAIENDB`PK\[ 99.default/views/public/img/ajax-loader-small.gifnu[GIF89aFFFzzzXXX$$$666hhh! NETSCAPE2.0!Created with ajaxload.info! ,w  !DBAH¬aD@ ^AXP@"UQ# B\; 1 o:2$v@ $|,3 _# d53" s5 e!! ,v i@e9DAA/`ph$Ca%@ pHxFuSx# .݄YfL_" p 3BW ]|L \6{|z87[7!! ,x  e9DE"2r,qPj`8@8bH, *0- mFW9LPE3+ (B"  f{*BW_/ @_$~Kr7Ar7!! ,v 4e9!H"* Q/@-4ép4R+-pȧ`P(6᠝U/  *,)(+/]"lO/*Ak K]A~666!! ,l ie9"* -80H=N; TEqe UoK2_WZ݌V1jgWe@tuH//w`?f~#6#!! ,~ ,e9"* ; pR%#0` 'c(J@@/1i4`VBV u}"caNi/ ] ))-Lel  mi} me[+!! ,y Ie9"M6*¨"7E͖@G((L&pqj@Z %@wZ) pl( ԭqu*R&c `))( s_J>_\'Gm7$+!! ,w Ie9*, (*(B5[1 ZIah!GexzJ0e6@V|U4Dm%$͛p \Gx }@+| =+ 1- Ea5l)+!! ,y )䨞'AKڍ,E\(l&;5 5D03a0--ÃpH4V % i p[R"| #  6iZwcw*!! ,y )䨞,K*0 a;׋аY8b`4n ¨Bbbx,( Ƚ  % >  2*i* /:+$v*!! ,u )䨞l[$ Jq[q 3`Q[5:IX!0rAD8 CvHPfiiQAP@pC %D PQ46  iciNj0w )#!! ,y ). q ,G Jr(J8 C*B,&< h W~-`, ,>; 8RN<, <1T] c' qk$ @)#!;PK\}+default/views/public/img/identity-glyph.pngnu[PNG  IHDRgtEXtSoftwareAdobe ImageReadyqe<IDATxb?cFy/O? 1b,m<𐀐>wo.ř b 7Wp=t= `};t[W.߽q[b x[ʹ?` vej %#@l >*&2i@T:Yr{@Ѷna o{PTH $RD7gՑ[`K^ E}w!˭9vk3P Y;K5C6_PXg7=Wc -_aypE)T2P,*ޡz@Po@R`+Ȁ?R! mcaccggħO4m_1BS(@\Xg¡4%R >M@,"@̎# oA Ы/IENDB`PK\WK(default/views/public/img/dashboard-r.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLNIDATHc`#2?>gϞe$E}0j[B&T24}0H [b}}@JZ0`8IENDB`PK\҆m&%default/views/public/img/grid-asc.pngnu[PNG  IHDRtwIDATxmk`GW`D/v^lne6٦0Q6aapt*^Y>`ΦiM&KS׏7oA!>}0Ts JEQL&i bqA&\5u8 MMCNJJ6VxX bpC`ސ X%qns8n(#W|RfVD"`Yn /7 ˅\6!(:nE< ʃ.'dlI`u'nQ^c( d NW);JDa"!J`AVҰ6 kLdlB!X YMӨJB`IȒHkOr{r k¹Nj=nЖeӲ4 RN qZz!;҉~{RaZyJ%ښF#dg6ul]M1nlsXZZ}tN4n􃧜U߈{`ZlYmwޕOaDQIENDB`PK\U㦈 (default/views/public/img/ajax-loader.gifnu[GIF89a {{{222PPPհ! NETSCAPE2.0!Created with ajaxload.info! , IiabK$F RAT,2S*05//mp!z0;$0C.I*!HC(A@o!39T5\8) `dwxG=Y gwHbvA=0 V\\; ;H0t%HsrY'e$"\#E1CnĎ~J,,AaUw^4I%Pu Q33{0i1TGgwy}%%'R  = 3G%p0 JRo5Ȇ0IĦmykxT_}(^yKs>i_%n=q4e-M¤D! , I)*')Ed]PR A:!zrbw %6"G(d$["JFhaQP`p%†/BFP\cU ?TtW/pG&OtDa_sylD'M q tc b2DM : d% 4%s) uE3 YUtږD$JiM^%o/rvl9'L;99% i9 C "B BDs ^Xf}$P {L?P O4 E咛V$dJ#)pV$! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'Kw}?Kiz6:xKAC&}9tz\ \D5;x Qd( KW  MBIڈM=ˤs⸽8DaJ`@LG! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'KGziz68}z~%XK9:0}% tz\Blc LbQ   lj ųKň x(țPX ,ւ|/"! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'KGziz68}z~%:A/ C} u\ h}b D]=  V)  ڊ9CDK Ku *00StD! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'KGz z5 C: A/ C}u\ Eh}b6[=Wx&)I9Ԭ@oCT?Kd]B76ЫD! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6I ƀH03hոaj U {CIkmbK#cK8 {a8nV:/q:M Cu~Ehk6 [_6P.]6!)V! , IiRͧ"Jd]U RZN JjN2sK6 dI)  LHWG 6 KX젱.6d~zhuur/6 X5I;_t O#E {O9V94;VC/ 6Ø~*'MonbX:~]+V*mK_OrKN@.d~qЦDB֋ 5D;PK\ϡ(default/views/public/img/header-logo.pngnu[PNG  IHDRu(=0UrIDATx]X t`m9U[[`لdEl(BL2KTud& A Y@X$Qp% M9y]'hK9Ј1@ʼnTN\C ,%0 -e-efUF[ ;Y&r/X]c(KvؖY t/UaKDkHFH2^)Qd oťD߄;\%7R dq$}Ef9'xmIȆ.`%l*i*ULpBjvA{Q8{z^XS]KI@\·&"9^,$+f%$*r|98eX41"V^7xh-(s;q2:%uvh1dI\*~*&#Ȝphq"1bgPѩRQ%q19w"MN%Krs^!eW- {t ,"=U>LM?YQ8۩si2V'O-=Zg@1t[< 1?~X? 1ֈ>MegfsFSÅr2]h@}P.c5%MTĘ_)HB>i6i_K>}'rlɤRY_5KG#ivWbrX%L^[7<.$|YOxϳ{Gp]z\̤K0^G~#48VS yM~ `޺ ( ͭ@;ð4w0n, x*~ ,N6ivVk |YTomP5?I lYhS!ym:JU7 ̀?M !FwB*N,B<1 dut5=  E0)nDoDb''^q*y1UqBk:~/C|3H.P_{" p:T! `#_ A> b~db|dS#p~x$—XiQ{aݿԝ_ɠձGwZE |fUV^ *EsP{B[a/އ}+T킰$orUm}R>%R>fLIy'tɤ!,Hdɱ5-ͻUmlw~Ը ޯľ+߰.$;QaI)LaKM~.@!Nm[c7ʡIGߌo7 b^' U$8a2'=cLeltR9M3%%LK$] oF%⥯u_'G.$!ƅ̓Лi+tmn`CxJ! Z cgcwksSeER _pq-ؐ;D?m~*uIJ<[ 5\$1e, wnaooɁLz!pRF 9,$@oxhY&,YCw vpAgxL0IDATHc`R166O CϞ= 7i}8 F#y$H VIENDB`PK\oY{{1default/views/public/img/grid-row-selected-bg.pngnu[PNG  IHDRW:tEXtSoftwareAdobe ImageReadyqe<IDATxQ Q]Lr۞W 1JV]3{ag115/M݈RwO+uZݸ(u-_m8kuӔ|i<ןtC7=v?#J=ԍR7n,J݊On-[OnכZ]tGR.4QiT*REH"UT*REH"UT*REH"UT*REH"UT*REH"UT*REH"UT*REH"UGn $ROIENDB`PK\:(default/views/public/img/modal-close.pngnu[PNG  IHDR Vu\NIDATxc`())^\\܇K1H $PZZ&r$btMD)&YIN"$+YGJ:v$IENDB`PK\C_OO(default/views/public/img/arrow-white.pngnu[PNG  IHDRIDATxc` c84X4#݃!BIENDB`PK\<<'default/views/public/img/attachment.pngnu[PNG  IHDR ?|IDATxc`@ZNݸ0P~;nURRg@zzz~@@(h`. T5쪃555G#9Ⱦ 7(\W ?@31P@Am[VѱZH!|dB]?P.:?'n;P&O 7i7.sA@l:_Ma@ 0 ؀5 yqKIENDB`PK\`6[)default/views/public/img/icons/accept.pngnu[PNG  IHDRaIDATx]/a;pA粻4'Vb'&Rfm=wXgfFm:9"̛?jLu{|}.5Ӄ1!UVh˙q𦈞9!zGmR.?]oh{ ұ2^CorދpS`cfː"ˬ8&Gcߺua<1>'SR֎HubJօQ,ݸ١UK|ťT&i/"u|%G n;r=?p%qL$RX;C7NP6PYm֗_)]`yx栎K+jKzyHgĞe7e c3n\k/\IENDB`PK\{W,default/views/public/img/icons/decline-d.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJIDAT8哻 0 DO:i 8 8*\u<q[R%WqG)둝K "P "2HUG3lEU?#HZ0@?Y@ucy}-Z؛ [fhBYE s٥/z} &IENDB`PK\ecvv+default/views/public/img/icons/accept-d.pngnu[PNG  IHDRa=IDATxj@`wm}.BA1odPH0wCfr1܉G=("Uw=p6|Vwe&RUUi Q(o7a0( %~*iʲM h47$IK( ^?|!>Qlh{n b[Vth4.(ekN©OUgl[ Ap0},]dY ޓL%8qE|?A@OX,mhCuI-e!l6w}VUZ?tݑ!IENDB`PK\BԴ&default/views/public/img/icons/key.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJIDAT8˭1j1EXS.GXY&GnrwˮP";I>)v4k]A0| Qc0sesn:)ιE LDD%"+Y5{?K1BVkZoB<"쭵ә("{"Z$DdBDuGZD&7eY>X"/Y=(ӚըÐi ԥfE5*ys5S7_Ǣ(O5["zOJk njR"r#73W7-o9NIENDB`PK\?FF+default/views/public/img/icons/calendar.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJIDAT8Ւ1n1E߬|. Rrͦ2}NR#Hihs!(1X *kh #PZ 8WGzԕ$uιo?'̞1.xi;8Y&(QYO4ϣ8@/.7a16͢bT+^l9g/1vD{hGНH Cߟo>V[IENDB`PK\Err'default/views/public/img/icons/date.pngnu[PNG  IHDRagAMA7tEXtSoftwareAdobe ImageReadyqe<IDAT8˕RmkA~ԋK$5X% ǂ!#?P@PZ(*EA#ܹۙw:0;3ϼ@J f?WoL` OZ+M9cktyx D7гm\PSt]Io@#/د)[f^ѻ#dHkbG"uݿq\.Xc8YhH|r}/!FsRB(]jT5V?ZxYl6sd2QgwpdC2p8A厊*X,¢<}" W  8s"jR--tiM1eK lT*=L/F#C7~ -:MW1IENDB`PK\=V6default/views/public/img/icons/bullet_toggle_minus.pngnu[PNG  IHDR7gAMA7tEXtSoftwareAdobe ImageReadyqe<aIDAT(cπ2Q+/ދEp, %ւ)XC۱)XdB=6PMu][z+_70!IȓzS5IENDB`PK\=k5default/views/public/img/icons/bullet_toggle_plus.pngnu[PNG  IHDR7gAMA7tEXtSoftwareAdobe ImageReadyqe<cIDAT(cπ2Q+/ދEp, %ćO` PoǦ`1 BrC6uo_?$ }J ƦgIENDB`PK\*default/views/public/img/icons/magnify.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJxIDAT8=Q ZXIV`#3 +-wͧP^lN,NȦt`j{l8B<ս.ox<>R1IaP 8 J:}.iBZet:= m(\5`Vh6m=w˲eY~VHM`w$V(tR2V(˲}4:o~ ClM&3aUUy} \xƋIz%i[$% (\R#4҃e=EQ ~Y]כ1Fui{U!I ƈ#mUbCI%]mX4k 8IENDB`PK\'default/views/public/img/icons/flag.pngnu[PNG  IHDRasBIT|dBIDAT8퓱 @|쿲⨢PQiT @}8{$8ut$ i/1BEALuFMIENDB`PK\==(default/views/public/img/icons/valid.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJIDAT8c`3Y30:{& :0i Ϙq_ά 0)F 6!?CY D'p0}egOތFYD32)ÐC00=C |1c"ad  1 lac^П @NZsUIENDB`PK\Xw  *default/views/public/img/icons/decline.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJIDAT8c`9@9jaywXT.C~Eay07,q;#Blcd_q;zwXTߟȆaCq>g`(YW-+" 0003#(T(CC,A2g܎ â{dě"gxiMIENDB`PK\p|UU(default/views/public/img/icons/users.pngnu[PNG  IHDRVΎWbKGDC pHYsHHFk> vpAg#8nJIDAT8ݑjPߊp3ܬ-2p۹)o':výP%$Rx\J|eY1[d}A)?Yk7@V2kX6"SE"keZc`+ַ+EQLhI仵(0 <UUiod~f-WDz ͋D3|d5SIIENDB`PK\Sm `ΦiM&KS׏7oA!>}0Ts JEQL&i bqA&\5u8 MMCNJJ6VxX bpC`ސ X%qns8n(#W|RfVD"`Yn /7 ˅\6!(:nE< ʃ.'dlI`u'nQ^c( d NW);JDa"!J`AVҰ6 kLdlB!X YMӨJB`IȒHkOr{r k¹Nj=nЖeӲ4 RN qZz!;҉~{RaZyJ%ښF#dg6ul]M1nlsXZZ}tN4n􃧜U߈{`ZlYmwޕOaDQIENDB`PK\b1default/views/public/img/admin/form-button-bg.pngnu[PNG  IHDRtGIDATxMA @S1J& P2QW`)!IENDB`PK\R/default/views/public/img/admin/popup-bottom.pngnu[PNG  IHDRoh%tEXtSoftwareAdobe ImageReadyqe<[IDATxMnAFk~ !-X[΀K$vu;pOfip`k[aw *Yn.2W;/55k 0_|\esqr>)~6s c|Ӽv٘3~˲S6qͣpd #:`?j~8s-y/{7W.?ҿ6 *k՞͑K_=>ye2  b{q2Y]/\ ~ = Jh,ɵ`wdtH@lvJg*%C8S7AJP|# i(" BC*JrZ֢|163d$ vpAgxLRIDATHՕkQwY h%M"$Eb D 6ٙtJ ҙ.*6YHv]̆dl9p}>8ncEd@U'(Z'Zkg֒8cAK`xxLј UuTD&"u+sss߻.8Ƕՠ\.wN!ށo\oZz5mUک߲~HbuٜT@% hXSՑ$z>/nO&Тa%q` nUՁZvM)&Pח1}0~Ƙzd}+"<{8  QL7nU)i[05{α|8Y<ӭSIENDB`PK\~N3default/views/public/img/admin/quickstart/login.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLIDATHՕN0%w$bC"e!oeBm- 1tVձqZD0ί zo 3*ZkUQy@ae]K)oe 4eZk,eaC(Z#mї7HaͲ-zq6eDʜfխ┈.ֈ [(j 3OsM!Imp2. 3?l ":tEI|DԪgh4zkӫ2q{Mۅc_\cH0RIENDB`PK\髣 2default/views/public/img/admin/quickstart/user.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxL$IDATHUnP=u['Tu*??@&B(v<"SJSUB]@ daR!!'r'uz%K~s;wx%6[u_D ֣Si \} " 9Apq˲D0dZūjۅ *JLH=wW$$JLs$iM<̂Ey~n`4mXrii]5yx4 eM]ȧhhldQ\B\q=HD XmVݶ XmGs8S-3x[%P)udq]tZW&渓&,ɝw55]瓵:DyXzb8( _~"m89 vpAgxLIDATHU1kAU.w hw׈6IƙB$!v"avڟ4RH!l,e">0-fy޼f׍U[ pr^lP1DrJᮈd$߈{yNro*"I yGD (Z Z(裌1og8\rSl^s=Hw`ǭkN.'Iқ~X*!c&Ȁ*8r\=𦈼p5kUJ\C(<rc6>^  'p5,he9uGD6},˲UW)Ylj;J\,d`P}"WQ2AnO]t|jK+/h48~x]p>v/O`o?9p4#Kݾ-"lji'yx`]D>1Y`J$oJZۙ[@{lahhxǔ+IENDB`PK\..4default/views/public/img/admin/quickstart/signup.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLIDATH픱 0E@EF"IPTFL,bKc)}>gغ @'c HqkU-ʲ|FD|!pΙtk('{ga5A z3Y{ZkS>*sŀ,byj;VU/^\'f_z7c+aO`TIENDB`PK\6AA6default/views/public/img/admin/quickstart/currency.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLIDATH?AoQ9 E8iag!G -#AVm;]؜p)mD,,`uhq"  g k ٩1FkYU \$x[+c-v"WCD9$Q ȝj:[t9U}2sƘk#`{tDC9_ZnApnTPgj,Kq) QmiuC֞Rgmk"\.&I}zޗzUp8eY4M(83ϫ=`N>.f$ɦsnT* bccZ|jY\`[bUhy= ng[T" 1wvռWrޢ4M_FQ 'p{ ]L/ 2IENDB`PK\⥿;LL3default/views/public/img/admin/quickstart/theme.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLIDATHT1A[ 3ja-8 vpAgxLIDATHݕkQ?s{B*F bk@fV) vho 5!bvj ,$bȎEVHֽus^z̛|MZ-˶YP~htOv{hx*IB-i xB # j K:`MUW+sS~z:0 ~;g#Tu7&"(>T9'R:[x(RD0<.Zs^Okz("K%wcLasvݛ@U@D>Zv$-z;+bW0ҋǹie*`{WmmeU.,!G`"m#-0l 8}=pUUƘ͢|cOr"XP '@aOv]!cJ8D1 sm(WɿT9HN@IENDB`PK\ '2default/views/public/img/admin/quickstart/form.pngnu[PNG  IHDRw=bKGDC pHYsHHFk> vpAgxLIDATH퓻 0 D!/)*))(ؐ#Mϱ88$"w`qWV[J"sr~pht1F!ޣZ8W[,T 7#XX4yC\dNIENDB`PK\o7pN7default/views/public/img/admin/popup-wide-top-arrow.pngnu[PNG  IHDRd GdIDATxAOg KYuh "PmI[PCq %m/R@m$WL~o^׵ռ[KF]]i9nzhV}4^*S%Un(!՜O t!- /74M{-m7܍KFY|;ۺ[ 47AEuuӔ:jD]խΊlÒ Ma%~1=.Ϳ߻Bt_4S_u봽%EvMI_kΟ?gsuTE]5*j5kꬨg#*9?|F[EWrACDDDLuW:%g&=\bzC^,a^L+ """b]\QoM|=i|ѲU .&_a~zKiIENDB`PK\`]0default/views/public/img/admin/grid-sortable.pngnu[PNG  IHDRtVIDATxA@ 7 OnՍL$~,I&)(R\l ll{r}>m7+J8{WQ0\.zfIENDB`PK\/bb)default/views/public/img/admin/menu-e.pngnu[PNG  IHDR;֕J)IDATxڝOj@GmM,]d'C64]E ]z):>Q[&q>̼ߛ7o7e + |8#n 8mFpP$5blπGm̃iw(i PfYKPq#pT-5MSYL\\&upUU{AЙ8[0}#EтKp3tui9(yygz«aE؟8PKƸ I>/H>>z:/SrIENDB`PK\}1default/views/public/img/admin/identity-glyph.pngnu[PNG  IHDRgtEXtSoftwareAdobe ImageReadyqe<IDATxb?cFy/O? 1b,m<𐀐>wo.ř b 7Wp=t= `};t[W.߽q[b x[ʹ?` vej %#@l >*&2i@T:Yr{@Ѷna o{PTH $RD7gՑ[`K^ E}w!˭9vk3P Y;K5C6_PXg7=Wc -_aypE)T2P,*ޡz@Po@R`+Ȁ?R! mcaccggħO4m_1BS(@\Xg¡4%R >M@,"@̎# oA Ы/IENDB`PK\=;vnn0default/views/public/img/admin/menu-active-d.pngnu[PNG  IHDRH5IDATxڭOaTE P*N@5X㒢8¦V)`s!jT懆o_x9M? S r{G=><6Ϧ\8}2 qQx[Dy9PY޶{e:1:γxKkA@ZͷH:#Wy(D^/s[E4==pvF-()K5z걃90#:'n."8OM+ŗoѳr55P&TBx~}=&ʾ@-<1jΜHOӍGIF*fF3h=o$\,nN7o`V?yFIENDB`PK\҆m&+default/views/public/img/admin/grid-asc.pngnu[PNG  IHDRtwIDATxmk`GW`D/v^lne6٦0Q6aapt*^Y>`ΦiM&KS׏7oA!>}0Ts JEQL&i bqA&\5u8 MMCNJJ6VxX bpC`ސ X%qns8n(#W|RfVD"`Yn /7 ˅\6!(:nE< ʃ.'dlI`u'nQ^c( d NW);JDa"!J`AVҰ6 kLdlB!X YMӨJB`IȒHkOr{r k¹Nj=nЖeӲ4 RN qZz!;҉~{RaZyJ%ښF#dg6ul]M1nlsXZZ}tN4n􃧜U߈{`ZlYmwޕOaDQIENDB`PK\ RRKeƁY6Z)o}RAj 3ɲ/^E/_p^- : KeӝBcÆA9o=x 6.u 3'qixtlZg($MgF4-tLjUE-t c$*6%TÖ1D[X=emu>~Ɔ>I`,8 .c@d}|KFBuT |^D[x]ڀmc&8' 2Ae{Az@zI.i^๷M ԂU^fߙko+ԀԂPTcX @j@jV/^ҝG3/y|ҝ'}~4$Gwy lIENDB`PK\(xb+ + .default/views/public/img/admin/header-logo.pngnu[PNG  IHDRw,htEXtSoftwareAdobe ImageReadyqe< IDATxY pMY&lZK%L5Lg0]k-"b2e0LXJR4m_GhmYĖD"!$}z誩9U=]}}fYYYtttСhݺv<4n!III"lLth֬oUU]ggvG7Ng]YYQWWgɀnww92=2 2]bccw487.KtӅv״Ç`Jow4ϟyFW^^~=kMC~G: .\tIbp1Ic\m&ttT7K.jjjZ[51cՎ`IÆ]rEzFEpJX=c־ (9iʕ7ps27,m->ڵkm̛={췼w^;VTT\j߾yΥ@Q 3r )w=6xcǎγ^K:ߺxb7dS;ذ[(3\ x Zϱɓ ,2-ݻ+!8oZlxG}^ǎׯ_?Mwٹsg(czͦo@2`!!!cbb rXйpXߴig s-76o\{C(\wǏ/9L/P7n񑹹 N~e#G.}@LNe+(((>tUõ%%%Dt:]GDD$RL>WWWٳ7'=~M9P/M&L.P󾾾_[/M/1z"(2=ې˗/'bal"ӧO߫^⦨sߨ{#%%%Ϩ/SLV\E|Vif#(wƍk׮Ǩ6,A3w:E`%JVxun@@B+gV~lȑlsm۶mRI rkoʹ/ /fШSNP6"Ғ%KB܆ XbRט@/^V8p>ܱe˖Th ͛7ɞڵ ۷ow[!5a6\HNծ]ڢ -Q7Eݺu=.aLWmǏɂ/[`X/yF꿾!!3VZ 䧧ԮVXQݒϝ:u2Eؼs18J"44ds3gȕH d?q@s¢Evw\6"200pۼyQ\;]:c67p/ѳ\ p)2.i` ag>O9gGEEݤs7oeVG^ %샂F3dpyB8dgp Sa苩E5."bvW*(LGiuTFdŠg6.![ɖiOm"s1tXbeOr9sa暢Wݾ}3f0jNڛՄ۶m;3mڴшt.]L. )nQ?xyy}MIXqG^!U&Өuچ *Р\W=sj5p3gYH|!'DKC643]! [6y+hL>OC =8,Hr֠鏨*=6xW%8;\g7n[-G=|hN2<W3%yR8>Ek|w4?u_< DX^y_8k^`I&"s έ={Cn]\\@4$#-G9._&X'!ӇGWېnݺ$[~Qd81c'u ?'~)j #Fl#i@ 1CĨ ^R@5!$>}E30@ *$WעVPQ'|<& -/GLSFJNe'xbΎX|(sf%Il ݵg6þ5cOnOcSgzɓ':@qP(A ([s (V&_ F&"ɖlmDppq! %RC(1di [%z )FdIU+߰y2I{}sAMR2Ico*>6M wo){ur: [IENDB`PK\9default/views/public/img/admin/menu-subitem-bg-active.pngnu[PNG  IHDRZPQ3tEXtSoftwareAdobe ImageReadyqe<IDATxQ0a:7ڃx}Y}NIĭ;?OEK`?Idh|Y׵i:}\Y(Xw+.y>bzy+,Xe}bKGD pHYs  tIME vYIDAT(υ 1 eO-i}m|m N3s`k p +nBA ;c yE&m;Dҵ)X%y4$9JIENDB`PK\C_OO.default/views/public/img/admin/arrow-white.pngnu[PNG  IHDRIDATxc` c84X4#݃!BIENDB`PK\JZ)default/views/public/img/admin/menu-d.pngnu[PNG  IHDRHNIDATxڭUMoQ寴|[a`)؁fJ)TJAjjqakjm.ljݑ51y,`2d.s{0X,=SL 6~pK ?CAPCk:oFnC@h&thװĆ!d:Bfj.f袐6x55̷\9s}^d8P9)+ETR\y'+z/taJkǒjtึžt^t"!\ob6N -W ;m,<2Tqy7ɭ]=҂183z@ Ž+K/-jF]PQ;u 8;pA-<"Xu?&3 )"4hu ShyͩndSgDh58->%xMiZXe)>#>dWNi@ =hV>37qw)Tء̀z@ &?KU&A K/PCOkmgdEjp qb3?0(4IENDB`PK\ViJJ,default/views/public/img/admin/popup-top.pngnu[PNG  IHDR &>΃IDATxJQ@5&E+ "ԺQXBW.ğn|.u#sʍ29pV =;w&cc"""""""""""""""""""""""""""""""""""""""""209 8qϢ> B.(ደ aEUUe=ɇ&L ÙMκ}yJBNdyRx+,4śa+å.șKtIt O~hl,bMQF8Vµp#|N~PUՑsyüAVэ2)>I*r(qn ?3~QUՑ1=.=hӇezQǢ3' JN| ax7UU9O珘]ءtAGLS`ϭL~S ËGx \ЇX zR/W9EnLZCYFW>Ӎu:R+%:gO=UJ|{x뀪?}JOj%[f I26я=iЗr=*Gָ6OGJ$j铢uSӹxNGtNgmt!m]:h:td4LrD:=/b|xCGtEg8؟PϝxGGvI2[KLov耩ғMR@%%9vTUuI61 UoO\IENDB`PK\ α7default/views/public/img/admin/form-button-hover-bg.pngnu[PNG  IHDRXtxIDATxsaBGlfL˸1Wp:ϳ9&~'Qķ&j؇g7!1ڌ+O,]H⹰" zK<owr[*IqE:IENDB`PK\b)default/views/public/img/admin/tab-bg.pngnu[PNG  IHDRtGIDATxMA @S1Jdefault/views/public/img/admin/menu-glyph-delimeter-active.pngnu[PNG  IHDR(bIDATxM ߛc#`^P:mKIB/bPXq bՠ`eaz;Cs Re!0i~>,jtRfTSH(YIENDB`PK\U1default/views/public/img/admin/popup-wide-top.pngnu[PNG  IHDRd GdOIDATxjTw1LLbHOc!$ 5cA f#\"hpc/Wnl/r*:<xV&8ߙs$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$o1̠hG\gp])W|Y(x-d']nwFg|We\/ò\VʍU?+E줥Avda= a>|l[N,wc `L6fvѭavbguO>99fkZZ.^QyP!FEnfG-gW 4ΏβzXrX~(G `LQaA~VjF٥Mv?(\NiyZ y4$;Ivӣ쨝쪵(ds9rk?Mk.w;.{ua^Z S~hv-iwKEy|QGU{Y]aAv%Gg˹ǹ%~e'v&du#<)pEg|({}5Zw0y4s7_@;v`/vaM^fh 0UVmqY{vmG5߸hS&;avzvX{}9>k/3kxL쬃쮍=۽?_0{R>hS1;qv찅^lĸ.8޺/VŲfXY(>ލr7^Zvb\QWa.8MIENDB`PK\F-default/views/public/img/admin/content-bg.pngnu[PNG  IHDR<bKGD pHYs  tIME  ,)p$IDATcy&r FFFhb8DhA>@:IENDB`PK\;,default/views/public/img/admin/grid-desc.pngnu[PNG  IHDRtIDATxmKSaϿPEA]DvcEHeR췔fAfٙk˅Y $ nLJB) "c0K[t39=۷w! >\}ຟ/|H&@D͠l៿pA |}2DYh4 JRQ jn/vLSk;?R@4#. e"H$(( :{qy:!y&b1xT(("M'E}7 #cBE$hoct:awp49D Ա)zb4,vks|yI%B!0Y;ffJD"tyXԼL6000Y*.GFɬ1 OM!I(IȪI} LEx<DZ'F?(.*u0E`jq }i5k9:,J0=Lc|| -S۴r;ʏ`MC0- r],q߮9(+Bp;+tu{ԌU5YylC/>DZuw6lچcK>:P5_Y@Qn-IENDB`PK\ α/default/views/public/img/admin/tab-hover-bg.pngnu[PNG  IHDRXtxIDATxsaBGlfL˸1Wp:ϳ9&~'Qķ&j؇g7!1ڌ+O,]H⹰" zK<owr[*IqE:IENDB`PK\Hш3default/views/public/img/admin/menu-bottom-line.pngnu[PNG  IHDRbKGD pHYs  tIME  @ IDAT(c4330 F(au8%?IENDB`PK\P7default/views/public/img/admin/menu-glyph-delimeter.pngnu[PNG  IHDR(FIDATxcPu \:?}Zd8"!%*!PP$IJ6"bRJ)م D<:aeIENDB`PK\Tِ5default/views/public/img/admin/popup-wide-content.pngnu[PNG  IHDRdWWIDATx10<:x*cIu׬zvD @Ȅ @L @Ȅ =?zIENDB`PK\JE*default/views/public/img/admin/arrow-d.pngnu[PNG  IHDR SktEXtSoftwareAdobe ImageReadyqe<1IDATxb@01#5L0.`p(dDB@kIENDB`PK\1default/views/public/img/admin/menu-bg-active.pngnu[PNG  IHDR&fPtEXtSoftwareAdobe ImageReadyqe<FIDATxbp#ӝGϙ @?b`>FCHjAav?@ní_IENDB`PK\)^1default/views/public/img/admin/grid-header-bg.pngnu[PNG  IHDRPCtEXtSoftwareAdobe ImageReadyqe<HIDATxڌin0`l,h+6=I%IKXlJeP?X}~3KE=zHf֣[v72bdu49(nZoN07t3p3ɑ!CmÆɪs$nkw6t)g9SpcV~`sbg~jGPy$dFf3%;2dxaXoFw3IL_$c`&BD=7~` fpNjk~pmURdUo}TRTt庄]j#`#02rfNs47an4YR?IENDB`PK\K2default/views/public/img/admin/content-left-bg.pngnu[PNG  IHDR3bKGD pHYs  tIME  #D-IDAT(c 0 F( :::yҞJIENDB`PK\*default/views/public/img/admin/menu-bg.pngnu[PNG  IHDR&fPtEXtSoftwareAdobe ImageReadyqe<CIDATxbg&L301@6ȆC0t?8B?T>b 8Y(IENDB`PK\Ӏ)default/views/public/img/admin/menu-c.pngnu[PNG  IHDR 2ϽIDATxc`]]@G >SSl2&IȊ@811?011E!аm ``EX~Y&WYd$V}|Lπ =xL0O do 3]IENDB`PK\թ,default/views/public/img/admin/header-bg.pngnu[PNG  IHDR<SIDATxڽ @7c.s3"E+3sΥeeQU0c {KVPJ9g "RJ B{sf|Z^IENDB`PK\%C4default/views/public/img/admin/popup-wide-bottom.pngnu[PNG  IHDRd GdVIDATxOKUy񓊦72Q]h9B J@7P3b`V.? S]Vmy@}ppEVתs꺮^n*0rvn<)/],_enp-./<{aWasm-~9, 0R_nfͶAPrP.]4uݵv V^yV޻h#>;k/k-;l +e%?,}ͷ.HZCvr#gхW[_mMuoَVVl|q.KvQvVv|vdcAl?.{eo2 7U{Y]찉.dm]ͽN{qۗ?u${qf쯶.uYeӹy-Ghx|W>O_>e/~:ʞ}5;>.L7sQǛf_t?O1:;Evqvҳ;UY Gٵgwmᵗ拞` 졣죃쥝짭쩕꟎5ros)k=ޗo/kO <*GAE6cGdi^Ίkd.f٭e[۱0FVvэ줵Avtv֙c?eaݕ|Brg` rvbv|v\oOcg 8K|EI363Cq6hÑ70NoSB#L$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I҈8?@IENDB`PK\M2default/views/public/img/admin/popup-top-arrow.pngnu[PNG  IHDR &>΃tEXtSoftwareAdobe ImageReadyqe<aIDATxOQ[DqaX0ƅD aAHD7F qZ&ns;}mR/eLms4sׇ~a.@5M+lhYW1ۊ"ќf T8]&j?wF2g>5t@QIr#gdr*}pMD1{'Lq A80 b0YX6>>S>Ӳ鼔cވ`|}\:υ3q{|_zeِやފhJsPP)M͜$g!}'OF8H)-ɼS9]NC:MGK6}VۜkMγӡA:MR6wD6+]sUλt l,p96pϝuφO_hʹ>e1s'ѕHIgt55-}>KBG{"Cטb )llϖc |^|[ijIfWְW"P<)UjB?m;]Rx_d3x@BT6z.ж[dB1+ѕͺ,±K :@o,?+njp*FO&XSl GBYȘ@,5[l `5:hκpPJňƶ? V:U .@%&FO4(I`ݗ#IENDB`PK\`]+default/views/public/img/admin/sortable.pngnu[PNG  IHDRtVIDATxA@ 7 OnՍL$~,I&)(R\l ll{r}>m7+J8{WQ0\.zfIENDB`PK\~D81default/views/public/img/admin/form-legend-bg.pngnu[PNG  IHDRhSM1tEXtSoftwareAdobe ImageReadyqe<4IDATxav0 qN";tII% >906_;:H[e+ě|SV!ǔ\uaȹq\}ຟ/|H&@D͠l៿pA |}2DYh4 JRQ jn/vLSk;?R@4#. e"H$(( :{qy:!y&b1xT(("M'E}7 #cBE$hoct:awp49D Ա)zb4,vks|yI%B!0Y;ffJD"tyXԼL6000Y*.GFɬ1 OM!I(IȪI} LEx<DZ'F?(.*u0E`jq }i5k9:,J0=Lc|| -S۴r;ʏ`MC0- r],q߮9(+Bp;+tu{ԌU5YylC/>DZuw6lچcK>:P5_Y@Qn-IENDB`PK\}T!default/views/public/img/play.pngnu[PNG  IHDR==batEXtSoftwareAdobe ImageReadyqe<$iTXtXML:com.adobe.xmp LkIDATx]OGg 6lGXP$BP*HTe/zS~]G#$I*Tԉچ:-&XwHc!v=+.v3sfi7s"P@P  ԆtH*Pڇ]?~^fh\qځCBUA%(+S\P *@CE vZ^vʲ\W-a Mqw"3zנhǡO+;}CϜ^>uٻ ?BEC*tp A-1s:#ι 5z84l뼿0Ыz QZ(??(tilKs Koۅň⪪~6_r8#cO-EC!9~JeDb\j8sOg,|6-hګٮ;l'=s)UcFvMz =,r>62z 1s"Oi(I1x}m״Ge3z^C  Gzgd0}14Hc+AқaSV nBD?CϫZe@P k%G>1mփntːihk> ffYahm AWa6 .4 Cwb.kU (4O4O{~ʦe\{4͗qȲsWK֎НNn?c(B;%ʖ]5ݲlMB$ɦim`AQ`֞q{i0|_t]}Gp/9c, u?Dm[73ʲ_VSJ]EB|;\&buIENDB`PK\Vbb default/views/public/img/top.pngnu[PNG  IHDR Mi)IDATxc`4?$芉Ҍ&dqi"$F6DwoIENDB`PK\1default/views/public/img/form-button-hover-bg.pngnu[PNG  IHDR&fPtEXtSoftwareAdobe ImageReadyqe<FIDATxbp#ӝGϙ @?b`>FCHjAav?@ní_IENDB`PK\b#default/views/public/img/tab-bg.pngnu[PNG  IHDRtGIDATxMA @S1J\}ຟ/|H&@D͠l៿pA |}2DYh4 JRQ jn/vLSk;?R@4#. e"H$(( :{qy:!y&b1xT(("M'E}7 #cBE$hoct:awp49D Ա)zb4,vks|yI%B!0Y;ffJD"tyXԼL6000Y*.GFɬ1 OM!I(IȪI} LEx<DZ'F?(.*u0E`jq }i5k9:,J0=Lc|| -S۴r;ʏ`MC0- r],q߮9(+Bp;+tu{ԌU5YylC/>DZuw6lچcK>:P5_Y@Qn-IENDB`PK\ 3default/views/public/img/ajax-loader-small-gray.gifnu[GIF89a===[[[yyy!Created with ajaxload.info! ! NETSCAPE2.0,30Ikc:Nf E1º.`q-[9ݦ9 JkH! ,4N!  DqBQT`1 `LE[|ua C%$*! ,62#+AȐ̔V/cNIBap ̳ƨ+Y2d! ,3b%+2V_ ! 1DaFbR]=08,Ȥr9L! ,2r'+JdL &v`\bThYB)@<&,ȤR! ,3 9tڞ0!.BW1  sa50 m)J! ,2 ٜU]qp`a4AF0` @1Α! ,20IeBԜ) q10ʰPaVڥ ub[;PK\=aa&default/views/public/img/dashboard.pngnu[PNG  IHDRVΎW(IDATxcL3@Au BD0|A0 A dKIENDB`PK\ α)default/views/public/img/tab-hover-bg.pngnu[PNG  IHDRXtxIDATxsaBGlfL˸1Wp:ϳ9&~'Qķ&j؇g7!1ڌ+O,]H⹰" zK<owr[*IqE:IENDB`PK\4default/views/public/img/two-coll-divider-bottom.pngnu[PNG  IHDR9qIDATx]I DQO@LfCVYsbCJ`Z c Bk-z`y5nhzB<6bCPڃ+#jR*(_gDҢAIENDB`PK\)^+default/views/public/img/grid-header-bg.pngnu[PNG  IHDRPCtEXtSoftwareAdobe ImageReadyqe<HIDATxڌin0`l,h+6=I%IKXlJeP?X}~3KE=zHf֣[v72bdu49(nZoN07t3p3ɑ!CmÆɪs$nkw6t)g9SpcV~`sbg~jGPy$dFf3%;2dxaXoFw3IL_$c`&BD=7~` fpNjk~pmURdUo}TRTt庄]j#`#02rfNs47an4YR?IENDB`PK\t%VFF-default/views/public/img/menu-tabs-border.pngnu[PNG  IHDRĉ IDATxcY? ZIENDB`PK\Mv default/views/public/img/eye.pngnu[PNG  IHDRabKGDC pHYsHHFk> vpAg\ƭ7IDAT8ݒ1KBQsMU%hM!-IB46EC46F?A'@!&h=綜B-= ??;zJ`({<z}c`0XfW 7;:\.w\T޿ 8L6ƒRUVG~lm>V 0LΖ乔$IhcIR&0oADQTB<{Ƙ`óWusT=[i)W(.'K_زn !n4=TJ sO@ֳZv* 9Y\'Xk]Z sOzgEk!n@CIENDB`PK\a!F``(default/views/public/img/dashboard-h.pngnu[PNG  IHDR5T'IDATxcO0@^5 !x] } hohĆn߇9IENDB`PK\_v$OO&default/views/public/img/header-bg.pngnu[PNG  IHDRZolIDATxYwFA,^،9/!؞@b [Xl jEjUW/jOЮ{FjIu~S=gn=^4i|X=.b_ S)< ZVZ焾i|vg peAT0EojVu) /J@ @o&6=jb7L 9ֹЙ:z|ZBme|;CF']'G~ C+tfN ##Gt߇Mf [@źq"}.͇rE|}yBc^!tM8p5k#֭uhXZoKΕCF hhOzw Rbds Sޝvvڗ S-VϦkզi_g(xZ:3о6ŬQp1)mpVwlmp6/ w| sꗰgw>[<@0{ 4YaX \jb,AmshhQ<FA sjSW@ Suu,V~U;4;0mWsPcG J ѵr}^xmfS<Й90o}d@|u#3N_J>꼎`>ו*.%f:7dM7]OJ4(P%,7/RKxL}1_LpwM-ЙƶNojf佁 O>Xƴ FB0pֱ~)-'qߐw$oW@ @',d-4Ec }(.G}l/}iؐ' jyż6i}> hhe6⺶a, :0gZ92%y Ycxj h}@_{; N&4Wf25/޻b42PG@ At׿7՚Ό`18ZN:K y7IC\&U^]G@ @#˿iFNg4ه |5~ /iO%mHjOЙq<>2P9!F˽\s 򜠫*|Lzk1:CЗ.RۼLP<=7پoߔV]ڡ|Z@X#_VFh8^Xr|p.t\́ndE_$twJUҠǠ +r+XC C]_E۾>oyj.:ЙNY_z [Y€:Jc2~t=߷({~kh̗f Jg hhDmR jΎw_n * t@N[?ﺗ귴U }oR uفvs7dj;Tp}<)7gooȗ{ hhA]*X؝rvGk臟<G<5ZRA)aߎ36Wyhm-/a蜴g| IENDB`PK\S*3\\%default/views/public/img/sortable.pngnu[PNG  IHDR5#IDATxc`@π $`V]:RIENDB`PK\~D8+default/views/public/img/form-legend-bg.pngnu[PNG  IHDRhSM1tEXtSoftwareAdobe ImageReadyqe<4IDATxav0 qN";tII% >906_;:H[e+ě|SV!ǔ\uaȹq>>NNN\\\```dddiii///mmmyyyEEEsssRRRQQQaaazzz+++KKK! NETSCAPE2.0!-Made by Krasimira Nejcheva (www.loadinfo.net)! ,@pH0dR NrZm*0(LjJC+@P@4/@@jEfiCkB&M,! (+! M E *)SGvJI[DLLwSkk "#l ##_RLlE J I%% S D#&  ! .X@BBH`6b@,A.  1DЀk04I`.H"@C; $b( Kbݔ ! ,770LM0//2HBNNCK2L(608Q*2PF/JTA11I*;//SMD#9)F/>>R;AMOF7<46>345DNM:/2̅:D3PF%F5@H썊a!> !׍+apF(-ы- ͸ K2xO#I2P b7!DrTAd]~x3QH@M2IG,6`,"Q=* f!d3?&,$#@! ,[6UUVkkVWDclleiXWjm[Vml\+qqCmmVUh.Wgp_,XUeH`]oCUbVh,_c+KU>jlC6U`Y6bV`nTrCZeKk^>sStQT gl,CiLd̐Db@U*2,?6zQJ6|\TELE*!Hр.^f ZdHԀ-^ PLFYD07pBh0ldJPKT/]RFյD1QU~ E.!+LfKDxԕ! ,H@<&CG` d 0$Bw* Rh:%AH##PUcg"C|jҁ";!'ЧCdSC >P@ BCORyxC ^fЍXqw Ag #D:uNXOt "DrߊThVʔ̼3r.ҹ1*%˝|(@4b@dܩ<'pa7uRC$"B42PERrXq&N ^x!&Y`bGg fY#*ì I,aH mHj)Adʕaʬk0O2~ܓ` *ȰE 7 j KqC J"V$8iE+?>x`/ 4MqzI]GO T4"KėZYa! ,H&RE` B` 9@@ ThA /dhx"#!#a"GBdTD@dTQY 2\!Gx=y Qf% N")PFU.J/* Tġ |![.m'2J<ϗ/s+X32=?>9G/;Sa @]5"҅/A)TxC.90lG‹!.8(\b‹,dCWd=@B-9'P }? KW 0iXXx E! ,H,*H&: |`@:A ^HD@ H3,80bL8HO<SɤQ 8#Oth9\8JAjtPƞ*M pqO .\ |ia!pQDh>5BƍA:,9u9:$g 3&t a̠&kD7Eb%/8"GH#͔ /8CyAE'@E a1eK<*&ȵK ! O''@/`RF\! ,H&;* 0G DT80  {اB@@@#CB)OMxTf } r*2DuC "f*DUkBMl܋_d#mB>D$.0,v"Bĉg[0%6(!'@>J̩D6e0V"J?uzACبΒK*8`&w:CIxdţ:L>sL׃+@ C<+#%v¯D R2A@1DN)DW UQ! ,HM*X%*!.d@$p `"*6 Q $N$C@XpP%=|h:aA>. RRܔ% d1d(XEF-Z j!DFRt.!Kƒxm&·/TVa 2<c_Dg@ \ 1  . P\@9!ԏ!,C T!th9: QT*$ϡN@ ,7La#LPxB-( FMtu hiAD! ,H@:*$…tl 3\|ӌt* ܴƇu`(~)K\@ƃ, 5!+cjR38:D79i01AbʜJ2+Tp01!1$t*WE߿LM8]'@:&餉S RTZ1J&t>} Q$XAu< C -XT%̣Oy§B+7f\iшB&lHcQa4>|x-ƢAկI~CUHI D@9ӅN5ydt 2tA,=@Dj'6;<K!>`S{'tt:ىL\M@QA^e5X!D;PK\R %default/views/public/js/file-style.jsnu[// // Style input[type=file] // ; (function($) { $.fn.fileStyle = function() { return this.each(function(){ var $this = $(this); if ($this.data('initialized')) { return; } else { if (this.type != 'file') { throw new Error('Element should be input-text to use browser for it'); } $this.data('initialized', 1); } var $file = getLayout(); $this.before($file); $this.change(function(){ var val = $(this).val(); if ( val.length > 40 ) { val = '...' + val.substr(-40); } $file.find('.input-file-input').empty().append(val); }) var $div = $this.wrap($('
      ')).parent().css({ overflow : 'hidden', width : '20px', height : '20px' }).css({ position : 'absolute', 'z-index' : 1000 }); $file.append($div); $this.css({ 'float':'right' }); $div.css({ opacity: 0 }); $file.bind('mouseover mouseout', function(){ $(this).toggleClass('hover') }) $file.mousemove(function(e){ $div.css({ top: getTop(e, $file) + 'px', left: getLeft(e, $file) + 'px' }); }); }) function getLeft(e, $file) { var left = e.pageX - 10; if (left > $file.offset().left + $file.outerWidth() - 10) { left = $file.offset().left + $file.outerWidth() - 20 } if (left < $file.offset().left) { left = $file.offset().left } return left; } function getTop(e, $file) { var top = e.pageY - 10; if (top > $file.offset().top + $file.outerHeight() - 10) { top = $file.offset().top + $file.outerHeight() - 20 } if (top < $file.offset().top) { top = $file.offset().top } return top; } function getLayout() { return $('
      \
      Browse…
      \
      \
      '); } } })(jQuery);PK\@uRR)default/views/public/js/resourceaccess.jsnu[/* * Folder Access editor JS code * @author Alex Scott alex@cgi-central.net */ // todo: // - init start/stop values (function( $ ){ var methods = { init : function( options ) { return this.each(function(){ var $this = $(this), data = $this.data('resourceaccess'); if (data && data.initialized) return; $this.data('resourceaccess', { options: $.extend({ without_period: false }, options) ,initialized : true }); // free access handling $(".free-switch a", $this).click(function(){ var sw = $(this).data("access"); $(".free-switch", $this).hide(); $(".free-switch."+sw+"-access", $this).show(); switch (sw) { case 'protected': $this.resourceaccess("removeItem", 'free_without_login', 0); $this.resourceaccess("removeItem", 'free', 0); break; case 'free': $this.resourceaccess("addItem", 'free', 'Free', 0, "", "", ""); $this.resourceaccess("removeItem", 'free_without_login', 0); break; case 'free_without_login': $this.resourceaccess("addItem", 'free_without_login', 'Free, login not required', 0, "", "", ""); $this.resourceaccess("removeItem", 'free', 0); break; } }); // init items var items = $.parseJSON($(".resourceaccess-init", $this).val()); var select = $(".access-items", $this); if (items) for (cl in items) { var clText = $("optgroup."+cl, select).data('text'); for (id in items[cl]) { var item = items[cl][id]; $this.resourceaccess("addItem", cl, clText, id, item.text, item.start, item.stop); } if (cl == 'free') { $(".protected-access, .free-access", $this).toggle(); break; } if (cl == 'free_without_login') { $(".protected-access, .free_without_login-access", $this).toggle(); break; } } // If the plugin hasn't been initialized yet $(".access-items", $this).change(function() { if (this.selectedIndex <= 0) return; var option = this.options[this.selectedIndex]; var gr = $(option).closest("optgroup"); $this.resourceaccess("addItem", gr.attr("class"), gr.data("text"), option.value.replace(/^[_a-z]*/, ''), option.text, null, null); }); }); } ,removeItem: function(cl, id) { var hiddenName = this.attr("id") + "["+cl+"]["+id+"]"; $("input[type='hidden'][name='"+hiddenName+"']", this).closest(".item").remove(); } ,addItem: function(cl, clText, id, text, start, stop) { var $this = $(this); var el = $("
      "); el.html(" " + clText + " " + text + ""); var x = $("[x]"); x.click(function(){ el.remove(); $(".access-items optgroup."+cl+" option[value='"+cl+id+"']", $this).prop("disabled", false); // todo - enable option }); el.prepend(x); $(".access-items optgroup."+cl+" option[value='"+cl+id+"']", $this).prop("disabled", true); var elid = this.attr("id"); var hidden = $("") hidden.val($.toJSON({ start : start ,stop : stop ,text : text })); el.append(hidden); if (!cl.match(/^free/) && cl != 'user_group_id' && !this.data('resourceaccess').options.without_period) { var astart = $(""); astart.text($(this).resourceaccess("getLinkText",start, true)) .click(function(event){ event.stopPropagation(); methods.openEditor($(this), true, el, cl); }); var astop = $(""); astop.text($(this).resourceaccess("getLinkText",stop, false)) .click(function(event){ event.stopPropagation(); methods.openEditor($(this), false, el, cl); }); el.append(" from ").append(astart).append(" to ").append(astop); } $("."+cl+"-list", this).append(el); return el; } ,getLinkText: function(v, isStart) { switch (true) { case v == '-1d' : return 'forever'; case v == 0 : case v == '' : case v == null: return isStart ? 'start' : 'expiration'; default: return v; } } // open period editor ,openEditor : function(a, isStart, div, cl) { var text = $(""); var select = $(""); select.append(new Option(isStart ? 'start' : 'expiration', '')); select.append(new Option('-th day', 'd')); if (isStart) { var opt = new Option('-nd payment', 'p'); if (cl != 'product_id') $(opt).attr("disabled", true); // allow to select -nd payment only for products not cats select.append(opt); } if (!isStart) select.append(new Option('forever', '-1d')); var span = $(""); span.append(text); span.append(select); var hidden = div.find("input[type='hidden']"); span.bind("outerClick", function(){ var val = $.evalJSON(hidden.val()); var t = null, v = select.val(); if (v != 'd' && v != 'p') t = select[0].options[select[0].selectedIndex].text; else { v = parseInt(text.val()) + v; t = v; } if (isStart) val.start = v; else val.stop = v; hidden.val($.toJSON(val)); a.text(t).show(); span.remove(); }); var val = $.evalJSON(hidden.val()); var v = isStart ? val.start : val.stop; switch (true) { case v && (v.match(/^[0-9]+p$/) != null) : text.val(parseInt(v)); select.val('p'); break; case v && (v.match(/^[0-9]+d$/) != null) : text.val(parseInt(v)); select.val('d'); break; default: select.val(v); text.hide(); } select.change(function(){ text.toggle($(this).val() == 'd' || $(this).val() == 'p'); }); a.hide().after(span); } }; $.fn.resourceaccess = function( method ) { if ( methods[method] ) { return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof method === 'object' || ! method ) { return methods.init.apply( this, arguments ); } else { $.error( 'Method ' + method + ' does not exist on jQuery.resourceaccess' ); } }; })( jQuery ); PK\);}},default/views/public/js/jquery/jquery.ui.cssnu[/*! jQuery UI - v1.10.3 - 2013-12-25 * http://jqueryui.com * Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ /* Layout helpers ----------------------------------*/ .ui-helper-hidden { display: none; } .ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; } .ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } .ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; border-collapse: collapse; } .ui-helper-clearfix:after { clear: both; } .ui-helper-clearfix { min-height: 0; /* support: IE7 */ } .ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } .ui-front { z-index: 100; } /* Interaction Cues ----------------------------------*/ .ui-state-disabled { cursor: default !important; } /* Icons ----------------------------------*/ /* states and images */ .ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } /* Misc visuals ----------------------------------*/ /* Overlays */ .ui-widget-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; } .ui-resizable { position: relative; } .ui-resizable-handle { position: absolute; font-size: 0.1px; display: block; } .ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } .ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; } .ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; } .ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; } .ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; } .ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } .ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } .ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } .ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px; } .ui-selectable-helper { position: absolute; z-index: 100; border: 1px dotted black; } .ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; min-height: 0; /* support: IE7 */ } .ui-accordion .ui-accordion-icons { padding-left: 2.2em; } .ui-accordion .ui-accordion-noicons { padding-left: .7em; } .ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; } .ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } .ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; } .ui-autocomplete { position: absolute; top: 0; left: 0; cursor: default; } .ui-button { display: inline-block; position: relative; padding: 0; line-height: normal; margin-right: .1em; cursor: pointer; vertical-align: middle; text-align: center; overflow: visible; /* removes extra width in IE */ } .ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; } /* to make room for the icon, a width needs to be set here */ .ui-button-icon-only { width: 2.2em; } /* button elements seem to need a little more width */ button.ui-button-icon-only { width: 2.4em; } .ui-button-icons-only { width: 3.4em; } button.ui-button-icons-only { width: 3.7em; } /* button text element */ .ui-button .ui-button-text { display: block; line-height: normal; } .ui-button-text-only .ui-button-text { padding: .4em 1em; } .ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; } .ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; } .ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; } .ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; } /* no icon support for input elements, provide padding by default */ input.ui-button { padding: .4em 1em; } /* button icon element(s) */ .ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; } .ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; } .ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; } .ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; } /* button sets */ .ui-buttonset { margin-right: 7px; } .ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; } /* workarounds */ /* reset extra padding in Firefox, see h5bp.com/l */ input.ui-button::-moz-focus-inner, button.ui-button::-moz-focus-inner { border: 0; padding: 0; } .ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; } .ui-datepicker .ui-datepicker-header { position: relative; padding: .2em 0; } .ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position: absolute; top: 2px; width: 1.8em; height: 1.8em; } .ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } .ui-datepicker .ui-datepicker-prev { left: 2px; } .ui-datepicker .ui-datepicker-next { right: 2px; } .ui-datepicker .ui-datepicker-prev-hover { left: 1px; } .ui-datepicker .ui-datepicker-next-hover { right: 1px; } .ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } .ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } .ui-datepicker .ui-datepicker-title select { font-size: 1em; margin: 1px 0; } .ui-datepicker select.ui-datepicker-month-year { width: 100%; } .ui-datepicker select.ui-datepicker-month, .ui-datepicker select.ui-datepicker-year { width: 49%; } .ui-datepicker table { width: 100%; font-size: .9em; border-collapse: collapse; margin: 0 0 .4em; } .ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } .ui-datepicker td { border: 0; padding: 1px; } .ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } .ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding: 0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } .ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width: auto; overflow: visible; } .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float: left; } /* with multiple calendars */ .ui-datepicker.ui-datepicker-multi { width: auto; } .ui-datepicker-multi .ui-datepicker-group { float: left; } .ui-datepicker-multi .ui-datepicker-group table { width: 95%; margin: 0 auto .4em; } .ui-datepicker-multi-2 .ui-datepicker-group { width: 50%; } .ui-datepicker-multi-3 .ui-datepicker-group { width: 33.3%; } .ui-datepicker-multi-4 .ui-datepicker-group { width: 25%; } .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width: 0; } .ui-datepicker-multi .ui-datepicker-buttonpane { clear: left; } .ui-datepicker-row-break { clear: both; width: 100%; font-size: 0; } /* RTL support */ .ui-datepicker-rtl { direction: rtl; } .ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } .ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } .ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } .ui-datepicker-rtl .ui-datepicker-buttonpane { clear: right; } .ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, .ui-datepicker-rtl .ui-datepicker-group { float: right; } .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width: 0; border-left-width: 1px; } .ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; outline: 0; } .ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; } .ui-dialog .ui-dialog-title { float: left; margin: .1em 0; white-space: nowrap; width: 90%; overflow: hidden; text-overflow: ellipsis; } .ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 21px; margin: -10px 0 0 0; padding: 1px; height: 20px; } .ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; } .ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin-top: .5em; padding: .3em 1em .5em .4em; } .ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; } .ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; } .ui-dialog .ui-resizable-se { width: 12px; height: 12px; right: -5px; bottom: -5px; background-position: 16px 16px; } .ui-draggable .ui-dialog-titlebar { cursor: move; } .ui-menu { list-style: none; padding: 2px; margin: 0; display: block; outline: none; } .ui-menu .ui-menu { margin-top: -3px; position: absolute; } .ui-menu .ui-menu-item { margin: 0; padding: 0; width: 100%; /* support: IE10, see #8844 */ list-style-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7); } .ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; } .ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; min-height: 0; /* support: IE7 */ font-weight: normal; } .ui-menu .ui-menu-item a.ui-state-focus, .ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; } .ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; } .ui-menu .ui-state-disabled a { cursor: default; } /* icon support */ .ui-menu-icons { position: relative; } .ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; } /* left-aligned */ .ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; } /* right-aligned */ .ui-menu .ui-menu-icon { position: static; float: right; } .ui-progressbar { height: 2em; text-align: left; overflow: hidden; } .ui-progressbar .ui-progressbar-value { margin: -1px; height: 100%; } .ui-progressbar .ui-progressbar-overlay { background: url("images/animated-overlay.gif"); height: 100%; filter: alpha(opacity=25); opacity: 0.25; } .ui-progressbar-indeterminate .ui-progressbar-value { background-image: none; } .ui-slider { position: relative; text-align: left; } .ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } .ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; } /* For IE8 - See #6727 */ .ui-slider.ui-state-disabled .ui-slider-handle, .ui-slider.ui-state-disabled .ui-slider-range { filter: inherit; } .ui-slider-horizontal { height: .8em; } .ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } .ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } .ui-slider-horizontal .ui-slider-range-min { left: 0; } .ui-slider-horizontal .ui-slider-range-max { right: 0; } .ui-slider-vertical { width: .8em; height: 100px; } .ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } .ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } .ui-slider-vertical .ui-slider-range-min { bottom: 0; } .ui-slider-vertical .ui-slider-range-max { top: 0; } .ui-spinner { position: relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; } .ui-spinner-input { border: none; background: none; color: inherit; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; } .ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; } /* more specificity required here to overide default borders */ .ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* vertical centre icon */ .ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } .ui-spinner-up { top: 0; } .ui-spinner-down { bottom: 0; } /* TR overrides */ .ui-spinner .ui-icon-triangle-1-s { /* need to fix icons sprite */ background-position: -65px -16px; } .ui-tabs { position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ padding: .2em; } .ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; } .ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom-width: 0; padding: 0; white-space: nowrap; } .ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; } .ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; } .ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; } .ui-tabs .ui-tabs-nav li a, /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } .ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; } .ui-tooltip { padding: 8px; position: absolute; z-index: 9999; max-width: 300px; -webkit-box-shadow: 0 0 5px #aaa; box-shadow: 0 0 5px #aaa; } body .ui-tooltip { border-width: 2px; } /* Component containers ----------------------------------*/ .ui-widget { font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif; font-size: 1.1em; } .ui-widget .ui-widget { font-size: 1em; } .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Trebuchet MS,Tahoma,Verdana,Arial,sans-serif; font-size: 1em; } .ui-widget-content { border: 1px solid #dddddd; background: #eeeeee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; } .ui-widget-content a { color: #333333; } .ui-widget-header { border: 1px solid #e78f08; background: #f6a828 url(images/ui-bg_gloss-wave_35_f6a828_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } .ui-widget-header a { color: #ffffff; } /* Interaction states ----------------------------------*/ .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #cccccc; background: #f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1c94c4; } .ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #1c94c4; text-decoration: none; } .ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #fbcb09; background: #fdf5ce url(images/ui-bg_glass_100_fdf5ce_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #c77405; } .ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #c77405; text-decoration: none; } .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #fbd850; background: #ffffff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #eb8f00; } .ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #eb8f00; text-decoration: none; } /* Interaction Cues ----------------------------------*/ .ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight { border: 1px solid #fed22f; background: #ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x; color: #363636; } .ui-state-highlight a, .ui-widget-content .ui-state-highlight a, .ui-widget-header .ui-state-highlight a { color: #363636; } .ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error { border: 1px solid #cd0a0a; background: #b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat; color: #ffffff; } .ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #ffffff; } .ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #ffffff; } .ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; } .ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } .ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } .ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); /* For IE8 - See #6059 */ } /* Icons ----------------------------------*/ /* states and images */ .ui-icon { width: 16px; height: 16px; } .ui-icon, .ui-widget-content .ui-icon { background-image: url(images/ui-icons_222222_256x240.png); } .ui-widget-header .ui-icon { background-image: url(images/ui-icons_ffffff_256x240.png); } .ui-state-default .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } .ui-state-hover .ui-icon, .ui-state-focus .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } .ui-state-active .ui-icon { background-image: url(images/ui-icons_ef8c08_256x240.png); } .ui-state-highlight .ui-icon { background-image: url(images/ui-icons_228ef1_256x240.png); } .ui-state-error .ui-icon, .ui-state-error-text .ui-icon { background-image: url(images/ui-icons_ffd27a_256x240.png); } /* positioning */ .ui-icon-blank { background-position: 16px 16px; } .ui-icon-carat-1-n { background-position: 0 0; } .ui-icon-carat-1-ne { background-position: -16px 0; } .ui-icon-carat-1-e { background-position: -32px 0; } .ui-icon-carat-1-se { background-position: -48px 0; } .ui-icon-carat-1-s { background-position: -64px 0; } .ui-icon-carat-1-sw { background-position: -80px 0; } .ui-icon-carat-1-w { background-position: -96px 0; } .ui-icon-carat-1-nw { background-position: -112px 0; } .ui-icon-carat-2-n-s { background-position: -128px 0; } .ui-icon-carat-2-e-w { background-position: -144px 0; } .ui-icon-triangle-1-n { background-position: 0 -16px; } .ui-icon-triangle-1-ne { background-position: -16px -16px; } .ui-icon-triangle-1-e { background-position: -32px -16px; } .ui-icon-triangle-1-se { background-position: -48px -16px; } .ui-icon-triangle-1-s { background-position: -64px -16px; } .ui-icon-triangle-1-sw { background-position: -80px -16px; } .ui-icon-triangle-1-w { background-position: -96px -16px; } .ui-icon-triangle-1-nw { background-position: -112px -16px; } .ui-icon-triangle-2-n-s { background-position: -128px -16px; } .ui-icon-triangle-2-e-w { background-position: -144px -16px; } .ui-icon-arrow-1-n { background-position: 0 -32px; } .ui-icon-arrow-1-ne { background-position: -16px -32px; } .ui-icon-arrow-1-e { background-position: -32px -32px; } .ui-icon-arrow-1-se { background-position: -48px -32px; } .ui-icon-arrow-1-s { background-position: -64px -32px; } .ui-icon-arrow-1-sw { background-position: -80px -32px; } .ui-icon-arrow-1-w { background-position: -96px -32px; } .ui-icon-arrow-1-nw { background-position: -112px -32px; } .ui-icon-arrow-2-n-s { background-position: -128px -32px; } .ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } .ui-icon-arrow-2-e-w { background-position: -160px -32px; } .ui-icon-arrow-2-se-nw { background-position: -176px -32px; } .ui-icon-arrowstop-1-n { background-position: -192px -32px; } .ui-icon-arrowstop-1-e { background-position: -208px -32px; } .ui-icon-arrowstop-1-s { background-position: -224px -32px; } .ui-icon-arrowstop-1-w { background-position: -240px -32px; } .ui-icon-arrowthick-1-n { background-position: 0 -48px; } .ui-icon-arrowthick-1-ne { background-position: -16px -48px; } .ui-icon-arrowthick-1-e { background-position: -32px -48px; } .ui-icon-arrowthick-1-se { background-position: -48px -48px; } .ui-icon-arrowthick-1-s { background-position: -64px -48px; } .ui-icon-arrowthick-1-sw { background-position: -80px -48px; } .ui-icon-arrowthick-1-w { background-position: -96px -48px; } .ui-icon-arrowthick-1-nw { background-position: -112px -48px; } .ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } .ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } .ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } .ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } .ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } .ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } .ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } .ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } .ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } .ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } .ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } .ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } .ui-icon-arrowreturn-1-w { background-position: -64px -64px; } .ui-icon-arrowreturn-1-n { background-position: -80px -64px; } .ui-icon-arrowreturn-1-e { background-position: -96px -64px; } .ui-icon-arrowreturn-1-s { background-position: -112px -64px; } .ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } .ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } .ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } .ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } .ui-icon-arrow-4 { background-position: 0 -80px; } .ui-icon-arrow-4-diag { background-position: -16px -80px; } .ui-icon-extlink { background-position: -32px -80px; } .ui-icon-newwin { background-position: -48px -80px; } .ui-icon-refresh { background-position: -64px -80px; } .ui-icon-shuffle { background-position: -80px -80px; } .ui-icon-transfer-e-w { background-position: -96px -80px; } .ui-icon-transferthick-e-w { background-position: -112px -80px; } .ui-icon-folder-collapsed { background-position: 0 -96px; } .ui-icon-folder-open { background-position: -16px -96px; } .ui-icon-document { background-position: -32px -96px; } .ui-icon-document-b { background-position: -48px -96px; } .ui-icon-note { background-position: -64px -96px; } .ui-icon-mail-closed { background-position: -80px -96px; } .ui-icon-mail-open { background-position: -96px -96px; } .ui-icon-suitcase { background-position: -112px -96px; } .ui-icon-comment { background-position: -128px -96px; } .ui-icon-person { background-position: -144px -96px; } .ui-icon-print { background-position: -160px -96px; } .ui-icon-trash { background-position: -176px -96px; } .ui-icon-locked { background-position: -192px -96px; } .ui-icon-unlocked { background-position: -208px -96px; } .ui-icon-bookmark { background-position: -224px -96px; } .ui-icon-tag { background-position: -240px -96px; } .ui-icon-home { background-position: 0 -112px; } .ui-icon-flag { background-position: -16px -112px; } .ui-icon-calendar { background-position: -32px -112px; } .ui-icon-cart { background-position: -48px -112px; } .ui-icon-pencil { background-position: -64px -112px; } .ui-icon-clock { background-position: -80px -112px; } .ui-icon-disk { background-position: -96px -112px; } .ui-icon-calculator { background-position: -112px -112px; } .ui-icon-zoomin { background-position: -128px -112px; } .ui-icon-zoomout { background-position: -144px -112px; } .ui-icon-search { background-position: -160px -112px; } .ui-icon-wrench { background-position: -176px -112px; } .ui-icon-gear { background-position: -192px -112px; } .ui-icon-heart { background-position: -208px -112px; } .ui-icon-star { background-position: -224px -112px; } .ui-icon-link { background-position: -240px -112px; } .ui-icon-cancel { background-position: 0 -128px; } .ui-icon-plus { background-position: -16px -128px; } .ui-icon-plusthick { background-position: -32px -128px; } .ui-icon-minus { background-position: -48px -128px; } .ui-icon-minusthick { background-position: -64px -128px; } .ui-icon-close { background-position: -80px -128px; } .ui-icon-closethick { background-position: -96px -128px; } .ui-icon-key { background-position: -112px -128px; } .ui-icon-lightbulb { background-position: -128px -128px; } .ui-icon-scissors { background-position: -144px -128px; } .ui-icon-clipboard { background-position: -160px -128px; } .ui-icon-copy { background-position: -176px -128px; } .ui-icon-contact { background-position: -192px -128px; } .ui-icon-image { background-position: -208px -128px; } .ui-icon-video { background-position: -224px -128px; } .ui-icon-script { background-position: -240px -128px; } .ui-icon-alert { background-position: 0 -144px; } .ui-icon-info { background-position: -16px -144px; } .ui-icon-notice { background-position: -32px -144px; } .ui-icon-help { background-position: -48px -144px; } .ui-icon-check { background-position: -64px -144px; } .ui-icon-bullet { background-position: -80px -144px; } .ui-icon-radio-on { background-position: -96px -144px; } .ui-icon-radio-off { background-position: -112px -144px; } .ui-icon-pin-w { background-position: -128px -144px; } .ui-icon-pin-s { background-position: -144px -144px; } .ui-icon-play { background-position: 0 -160px; } .ui-icon-pause { background-position: -16px -160px; } .ui-icon-seek-next { background-position: -32px -160px; } .ui-icon-seek-prev { background-position: -48px -160px; } .ui-icon-seek-end { background-position: -64px -160px; } .ui-icon-seek-start { background-position: -80px -160px; } /* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ .ui-icon-seek-first { background-position: -80px -160px; } .ui-icon-stop { background-position: -96px -160px; } .ui-icon-eject { background-position: -112px -160px; } .ui-icon-volume-off { background-position: -128px -160px; } .ui-icon-volume-on { background-position: -144px -160px; } .ui-icon-power { background-position: 0 -176px; } .ui-icon-signal-diag { background-position: -16px -176px; } .ui-icon-signal { background-position: -32px -176px; } .ui-icon-battery-0 { background-position: -48px -176px; } .ui-icon-battery-1 { background-position: -64px -176px; } .ui-icon-battery-2 { background-position: -80px -176px; } .ui-icon-battery-3 { background-position: -96px -176px; } .ui-icon-circle-plus { background-position: 0 -192px; } .ui-icon-circle-minus { background-position: -16px -192px; } .ui-icon-circle-close { background-position: -32px -192px; } .ui-icon-circle-triangle-e { background-position: -48px -192px; } .ui-icon-circle-triangle-s { background-position: -64px -192px; } .ui-icon-circle-triangle-w { background-position: -80px -192px; } .ui-icon-circle-triangle-n { background-position: -96px -192px; } .ui-icon-circle-arrow-e { background-position: -112px -192px; } .ui-icon-circle-arrow-s { background-position: -128px -192px; } .ui-icon-circle-arrow-w { background-position: -144px -192px; } .ui-icon-circle-arrow-n { background-position: -160px -192px; } .ui-icon-circle-zoomin { background-position: -176px -192px; } .ui-icon-circle-zoomout { background-position: -192px -192px; } .ui-icon-circle-check { background-position: -208px -192px; } .ui-icon-circlesmall-plus { background-position: 0 -208px; } .ui-icon-circlesmall-minus { background-position: -16px -208px; } .ui-icon-circlesmall-close { background-position: -32px -208px; } .ui-icon-squaresmall-plus { background-position: -48px -208px; } .ui-icon-squaresmall-minus { background-position: -64px -208px; } .ui-icon-squaresmall-close { background-position: -80px -208px; } .ui-icon-grip-dotted-vertical { background-position: 0 -224px; } .ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } .ui-icon-grip-solid-vertical { background-position: -32px -224px; } .ui-icon-grip-solid-horizontal { background-position: -48px -224px; } .ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } .ui-icon-grip-diagonal-se { background-position: -80px -224px; } /* Misc visuals ----------------------------------*/ /* Corner radius */ .ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { border-top-left-radius: 4px; } .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { border-top-right-radius: 4px; } .ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { border-bottom-left-radius: 4px; } .ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { border-bottom-right-radius: 4px; } /* Overlays */ .ui-widget-overlay { background: #666666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat; opacity: .5; filter: Alpha(Opacity=50); } .ui-widget-shadow { margin: -5px 0 0 -5px; padding: 5px; background: #000000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x; opacity: .2; filter: Alpha(Opacity=20); border-radius: 5px; } PK\V\4 4 3default/views/public/js/jquery/jquery.outerClick.jsnu[/** * jQuery custom event "outerClick". * @author David Brockman Smoliansky http://littleroom.se/ * @license GNU Lesser General Public License: http://creativecommons.org/licenses/LGPL/2.1/ * @version 1.1 * 2009/02/27 * * The outerClick event is fired when an element outside of the target element is clicked. * * Usage: * $(selector).bind("outerClick", fn); // Bind the function fn to the outerClick event on each of the matched elements. * $(selector).outerClick(fn); // Bind the function fn to the outerClick event on each of the matched elements. * $(selector).trigger("outerClick"); // Trigger the outerClick event on each of the matched elements. * $(selector).outerClick(); // Trigger the outerClick event on each of the matched elements. * $(selector).unbind("outerClick", fn); // Unbind the function fn from the outerClick event on each of the matched elements. * $(selector).unbind("outerClick"); // Unbind all outerClick events from each of the matched elements. */ /*global jQuery */ (function ($, elements, OUTER_CLICK) { /** * Check if the event should be fired. * @param {Object} event The click event. * @private */ function check(event) { for (var i = 0, l = elements.length, target = event.target, el; i < l; i++) { el = elements[i]; if (el !== target && !(el.contains ? el.contains(target) : el.compareDocumentPosition ? el.compareDocumentPosition(target) & 16 : 1)) { $.event.trigger(OUTER_CLICK, event, el); } } } $.event.special[OUTER_CLICK] = { setup: function () { var i = elements.length; if (!i) { $.event.add(document, 'click', check); } if ($.inArray(this, elements) < 0) { elements[i] = this; } }, teardown: function () { var i = $.inArray(this, elements); if (i >= 0) { elements.splice(i, 1); if (!elements.length) { $.event.remove(document, 'click', check); } } } }; /** * Event helper outerClick * * @param {Function} [fn] A function to bind to the outerClick event on each of the matched elements. * If fn is omitted the event is triggered. * @return {jQuery} Returns the jQuery object. */ $.fn[OUTER_CLICK] = function (fn) { return fn ? this.bind(OUTER_CLICK, fn) : this.trigger(OUTER_CLICK); }; })(jQuery, [], 'outerClick');PK\8,VAdefault/views/public/js/jquery/images/ui-icons_228ef1_256x240.pngnu[PNG  IHDRIJPLTE""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""3~YtRNS3P/"Uq@f`2 !<BHK Z#'1S,4j8E|)Q$ bJmߜGc?oh@^bKGDH pHYsHHFk>dIDATx] c۶H阒]Kd%٫뺮lmw]|pXm-}X:+iĆQV9\e'AtOS:72YsxMہB&z>nC@r@*aӝ%MFDDDDDDTߖH,ERUn ب\f͹:}4ᦋ{)n[ ̰E K Y Dۇ- +Kl=ӃL`љ|%n a N#5 (4?EDDDD\oWFfq;\E_,W!%zE!F¶. (USHQ0dw)T 8#p,xBK *xXEe K솎%mKX~sFE~tdcaI1Af4dHcGSB`0wev`"{ .GDDDD,dO6k"qkMefS_UKŌ&g~>n H}) LF%8()r![4统qQk0m[Le_70@>1 X0AZVcEV Ltk3EJ44ZﮊN`rt>`˥  AHBLH@cUq=jcM2sJCLiR NQ0=Yi-|4V ]]B^ޞ_H$<$ a=d@ (ZAp_}~s:N{DC>m^ƒS&, ;N&B} <_AB]HuN(B0{h1IKDs j' M8.ӫ1h3df}mq nU{Lo z \=?@ ((e|=ơ麄Ci1r<|OO; `HpQyzԈuZVƲ!)5mC2Lyg;֑RjWa@@VL&Wru=Z ̥=U5} 7;b(nP&sk48ͥ01U Wvk18dqTՌE]qH8 GF K'rOrŗ6"fpT^3c"nMم-/W=tJ,X){P Rm|K>mX8v5h<_{ꘀYF|&_G;&>^W⁃&K(81EB@F&;"L'wfwE-6o&/̫'Xe,>~ee|A=) dQ`}P[KN˂/~)O[dO=3El5'Y$?7mTzզ.\.` WE"""""v)V#]L;zqJr²[\-tҽ5 @ͷϟnT@+;cQhC*TڙAVr?f? Q1T`} Hk,{VZˋTϛ?I̯uQKLMe͆~qym09 S;j5 iQ]7k0UޭGkX3#lY_Цxj޶9`# M [z KuO_z˿Dܭ*kOJ(7n\e ITƨl/U߶uw.~;#r.8 o# 5Lh>1i pVM?/u70 X@L+M+{Fkt{ŧ890`. ĀCR+\/t R; TӲ]aL|efđ >ۣG|P`P8C1K՛A̍<2ۂKrl@L L 8@E>`nPNԍ,p EƆZF lÎ; F7Ȯ; swSz)g7{rsSgȋ(߄~AWytX$NVR_<6p.O8O[OdDk>_OO}JSdmV?W(_m j~=H IԁF>T/{*]IGJ@iqamNF|Q50+ ES8:v`p~vj:Bp96oys% |@H]+@t]Wk}}7FʮrAB\m-_2PY8xՎN.h~@+7z5t_//?0S>)zi0n/B`{DW#`Bo[,gFVЁpP߾C]Bz ,XXfԃA:H k7dZ9oc}o]0vd:R]0ve]刈jу| ? +(OǍ+ #ysߍnpFru<.HȺotM3h}߆P}˗vP}mǀ?WZ@}@@FDl%tEXtdate:create2013-02-01T05:33:10-08:00)`%tEXtdate:modify2013-02-01T05:33:10-08:00X=x.tEXtSoftwareAdobe ImageReadyqe<IENDB`PK\:default/views/public/js/jquery/images/animated-overlay.gifnu[GIF89a((! NETSCAPE2.0! ,(( z KNY#7)zɭv[3ӵϰxPwEa؁FOfVYeΛ||/X\Wr݅o$m^K0>'$uf6G'Xg5Ȩ5)9):ZiYJyڪY! ,((}Q6Úa_y#ʩijK-|˱K3^Pw&KOә=7IfTzLMYhcdX\1iea }wl5CgGB)'hY9IHyȗ ʹYjZGh'j85P! ,(( mQ6,@o-`u$>Iz/ 69~[ޢՄ^Ot6Ac:vN?cUX|f&6ẍ́哲_~G(b8X%x7IXI9x(I:Y*XYvʚP! ,((oˁ;MZY|ƍ舝([99ږ1`P2!H>oQW^dsc2*Siy x[s^ݶVGWwgǸإx舙Y8IIyIZj)Xf):R! ,((CqMZYm5W(F~٩'-:Õ|ڒ1p?X1dFSLӨqne^ACjTpfԷUp|%ƌn]z~mHXx6X9)Hyi9ƈר)Z *Y! ,((˜CMZ5Yo}6-ʕz㒽h1C&'EfrtF9z&ۭ*V:&Tjeu~_}W5hbG6(iV((x:蹊JYY* P! ,((CMZՅl}'vexVZk 򮯱$bR3ƒHPGkBjymhXklvYvֻf7HXH(((9x3%txiY 9i*ZJzWP! ,((CMZՅl}'vexVZ%;ӨU{ZbQ0G͹SSRƆШ 2kYEV}v]xTpg7gvHX'㖨9)רe&) ji:hIZT;PK\|SvAdefault/views/public/js/jquery/images/ui-icons_ffd27a_256x240.pngnu[PNG  IHDRIJPLTEzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzYtRNS3P/"Uq@f`2 !<BHK Z#'1S,4j8E|)Q$ bJmߜGc?oh@^bKGDH pHYsHHFk>dIDATx] c۶H阒]Kd%٫뺮lmw]|pXm-}X:+iĆQV9\e'AtOS:72YsxMہB&z>nC@r@*aӝ%MFDDDDDDTߖH,ERUn ب\f͹:}4ᦋ{)n[ ̰E K Y Dۇ- +Kl=ӃL`љ|%n a N#5 (4?EDDDD\oWFfq;\E_,W!%zE!F¶. (USHQ0dw)T 8#p,xBK *xXEe K솎%mKX~sFE~tdcaI1Af4dHcGSB`0wev`"{ .GDDDD,dO6k"qkMefS_UKŌ&g~>n H}) LF%8()r![4统qQk0m[Le_70@>1 X0AZVcEV Ltk3EJ44ZﮊN`rt>`˥  AHBLH@cUq=jcM2sJCLiR NQ0=Yi-|4V ]]B^ޞ_H$<$ a=d@ (ZAp_}~s:N{DC>m^ƒS&, ;N&B} <_AB]HuN(B0{h1IKDs j' M8.ӫ1h3df}mq nU{Lo z \=?@ ((e|=ơ麄Ci1r<|OO; `HpQyzԈuZVƲ!)5mC2Lyg;֑RjWa@@VL&Wru=Z ̥=U5} 7;b(nP&sk48ͥ01U Wvk18dqTՌE]qH8 GF K'rOrŗ6"fpT^3c"nMم-/W=tJ,X){P Rm|K>mX8v5h<_{ꘀYF|&_G;&>^W⁃&K(81EB@F&;"L'wfwE-6o&/̫'Xe,>~ee|A=) dQ`}P[KN˂/~)O[dO=3El5'Y$?7mTzզ.\.` WE"""""v)V#]L;zqJr²[\-tҽ5 @ͷϟnT@+;cQhC*TڙAVr?f? Q1T`} Hk,{VZˋTϛ?I̯uQKLMe͆~qym09 S;j5 iQ]7k0UޭGkX3#lY_Цxj޶9`# M [z KuO_z˿Dܭ*kOJ(7n\e ITƨl/U߶uw.~;#r.8 o# 5Lh>1i pVM?/u70 X@L+M+{Fkt{ŧ890`. ĀCR+\/t R; TӲ]aL|efđ >ۣG|P`P8C1K՛A̍<2ۂKrl@L L 8@E>`nPNԍ,p EƆZF lÎ; F7Ȯ; swSz)g7{rsSgȋ(߄~AWytX$NVR_<6p.O8O[OdDk>_OO}JSdmV?W(_m j~=H IԁF>T/{*]IGJ@iqamNF|Q50+ ES8:v`p~vj:Bp96oys% |@H]+@t]Wk}}7FʮrAB\m-_2PY8xՎN.h~@+7z5t_//?0S>)zi0n/B`{DW#`Bo[,gFVЁpP߾C]Bz ,XXfԃA:H k7dZ9oc}o]0vd:R]0ve]刈jу| ? +(OǍ+ #ysߍnpFru<.HȺotM3h}߆P}˗vP}mǀ?WZ@}@@FDl%tEXtdate:create2013-02-01T05:33:10-08:00)`%tEXtdate:modify2013-02-01T05:33:10-08:00X=x.tEXtSoftwareAdobe ImageReadyqe<IENDB`PK\ъ88Odefault/views/public/js/jquery/images/ui-bg_diagonals-thick_20_666666_40x40.pngnu[PNG  IHDR((;bKGD1 pHYsHHFk>zIDATH EQM6jE2 bݝ!K2g}/\)W@ -@3K,7:ׁ@k U Hrd sM u ESt.s/rڧ+%tEXtdate:create2013-10-20T19:55:03-07:00%tEXtdate:modify2013-10-20T19:55:03-07:00tIENDB`PK\{0=default/views/public/js/jquery/images/ui-anim_basic_16x16.gifnu[GIF89aݻwwwfffUUUDDD333"""! NETSCAPE2.0!,w $B$B##( R!!,c $PxB +*-[dඁ+i@ )`L ?'I`JGb Ph XB)0׸XQ# } No "tI+ZI!!,\ $P`8* 1h0rx8BQaV  !MDl!4%BBe PDY00!!,] $$I>Q] d"28 GqH9 A2ȀB", DH('4C \0`UL"r(!! ,d $dI`ìkBB m A72, (PX鲪 8@R%a K*D2E {$ft5C%!;PK\Rm  Adefault/views/public/js/jquery/images/ui-icons_222222_256x240.pngnu[PNG  IHDREr@bKGD"b pHYsHHFk>'IDATx{he}?g{1)]K&qqU4kbiKR(HBP(IvJ_ӮIV@nB5iNiGjq& ~A#QrX'9:ܫ{3E{=yo~3g~Mp& 1Xxh8<#dlЅMx1&$5 ~V c$ױ, ƹiN:Z ߊY>"BH!-Cu8t}8!B *OF.[aͲlB&1h>M]hN4MAb̐!(hE15jձcO<6e7,eS(fo16+3y JR|{^3^{88 ~' pxh8<4 g2n6e̘{QpӀPAiۺߖfS(D'L6=T:sfq羀l.cI ǧ=iM>ڠLN{U&&{uo..4~# pxh8<4 gÛp^i/0TWcQ @)yu}`LUc%Tȥ AR@?P-`BKl bZ}Ш͢uJ%U]K2e tsY@,ee豅rjcܭsMn0 AmPy DK(5,lN&bDmrwYDVte$謷 L[C0O P&0+; g3@ pxh8<4Y`OFZ!x#~ Gk @3K@:>PRMA|e]KgF.BtlOY d!(vVX%m#I[RR`2T HwYu=bYPEcU%&@Ĺ]}qo7*GL eQX5U-³8| _ݟ5\5pVH^\ Fآaa5l14[#boP1EiswMJ'5T06B|I,b`ՈPXkB$[-EOHt |3D(id9N6@x/ؠm(#wjPt/Zobq%[:3^~a55 |E닃^E$L-_s, ߫㕔Ņ& _,# F}&.<4 gOrdh9M7L(5꓂.?M(stզ-?:[ڧCr]'YB2lC| leXSpG0KcI~u L0/yLtrI?R%-wǷh$LJV ͿӢ ,g x_7l4* uM+@x<}ãq><#`i :=*ۿ{)_8hspCWғK`B]H"}_PNtQl1YQh+&?x5: ֘aYҭ=\En.YʸJE%uTj5F'b;[vט4u6]lkw3÷, : %& [|||Yiq`:qXc2+u|~/wrz[j-I># ,9Q:#,25@@%S@@6ÅJ{6{)hW~q]t<+|'0Oa 63UHWl;'Z9Z\oO嵁eeƢ[odarEm&ʧ3m6=g^Sx Hjmi(v ۈ{.h_%8nF7y{OFS5:/աWPH+bGx/9IYy.MtTeە,ѿ- Red ;Ә:9kT5mEG|\Wuǣ@^LE 4 gy ; J'U䐎N׷< p2mӫ.ZZ5< V ,p3w=~3jǿě#ʭ|Sfyk=Cn 1]C'I_O*,J՞D\\I}E\$M(E\߮?ƫw NJEb6tz:-?Bp ?XJ $xQJ}!#Ո2Ht!VɽV\'Y366YuJOAa[5e]p9=7t_y?OS_iT<͛32N묳}jHQ RTȢ nfݮ~+ciQ < Ma=|* $@'ԌǕqUO;5~@eI29w" O~ssk{‰$m>v z^2vow` a4cM Cb>q:o=-p`_2 ng:6KXV,2Ǿ6 g3@ śsaR WWB g-N;F[ՒaAVLF<-m VbMC 7K)XPy s~=<ܒ{x!=ÃqRl]/ 0l)'}#^tX孋t8FCY$)PUBE(~ҞV2^*SLHlS'IA[ Zx-V"ȥJ+ \|5uWnLJkܟ(00JyꞄafg6 g3@Ñg[}ZQk?ҳ=zI$ Т:9FWmx:\(W+eF9,*!GhDL8[vo)AaK5S/)^c(WHNW8Tr=opp]MCO?* D΢Ob/hs0ڜb91C9-oۿԗuQFc|W%@HB29/DxD`U:Ƈgi"`%ᄽ t E`t62k)PEѿO,?k_yh(/=@u g3@v@]<]~WD`.f~oʈNVA߈եM ^yMQ|ߛ^-{o~>wЃ (gXץi&X uDU͕l  ғޥߞkPHHCJ~S@O ׋ѓy7 k {25ofϫo{'!'Z%q*)gC\#\'0 P_WL7&AlJ\ Zp, Yxjc O(6zIV u:גTDO9ׄQ<*y =2~/?J,WJQW>Wu?#G/4"K{㧏',Iҟ综E;|Rݠ~W7i86 pxh8<4 r<}8 kGo;uCPv)A<$ց;{l #`FC!f Ӆ/`7(0R!99z@%!/m]AdhvG3@ pxh8<4{P/ 3@} B&^16{. ߠaQo 2lmt!\%@X?5ճa~ ʠM65wka)TF_ 2$x5_9!VxRd1!}'`$Uԇr? Q `7`.k_VzԄp]]GOLXCk3%tEXtdate:create2013-02-01T05:33:10-08:00)`%tEXtdate:modify2013-02-01T05:33:10-08:00X=x.tEXtSoftwareAdobe ImageReadyqe<IENDB`PK\] Fdefault/views/public/js/jquery/images/ui-bg_glass_100_f6f6f6_1x400.pngnu[PNG  IHDRDbKGD1 pHYsHHFk>HIDAT8c5a"oK1|a~Ï ?~Ne%7\(1d4F1G#NP%tEXtdate:create2013-10-20T19:55:02-07:00%tEXtdate:modify2013-10-20T19:55:02-07:00IENDB`PK\Edefault/views/public/js/jquery/images/ui-bg_flat_10_000000_40x100.pngnu[PNG  IHDR(dObKGD݊ pHYsHHFk>IDAT(c`Xu6w%tEXtdate:create2013-10-20T19:55:03-07:00%tEXtdate:modify2013-10-20T19:55:03-07:00tIENDB`PK\`)JOdefault/views/public/js/jquery/images/ui-bg_highlight-soft_100_eeeeee_1x100.pngnu[PNG  IHDRd2bKGD1 pHYsHHFk>XIDAT½ @@я4tU3 #U9-xy<'+w-n[bfL1&T<2GR.%tEXtdate:create2013-10-20T19:55:02-07:00%tEXtdate:modify2013-10-20T19:55:02-07:00IENDB`PK\\\Fdefault/views/public/js/jquery/images/ui-bg_glass_100_fdf5ce_1x400.pngnu[PNG  IHDRAbKGD X pHYsHHFk>IDATH? H&](v_W`5_YmFѤt?˧;=eY<#aƷAY&IRɆh`5`u8FD[9tF'pe͞zΧ=W]{EpK:_ 0~2UE\%tEXtdate:create2013-10-20T19:55:03-07:00%tEXtdate:modify2013-10-20T19:55:03-07:00tIENDB`PK\OkEdefault/views/public/js/jquery/images/ui-bg_glass_65_ffffff_1x400.pngnu[PNG  IHDRG#7vbKGD݊ pHYsHHFk>IDAT(ch`ph4i%tEXtdate:create2013-10-20T19:55:02-07:00%tEXtdate:modify2013-10-20T19:55:02-07:00IENDB`PK\[Odefault/views/public/js/jquery/images/ui-bg_diagonals-thick_18_b81900_40x40.pngnu[PNG  IHDR((S ybKGD X pHYsHHFk>IDATh1 1F6^@-y'kZ@dyɫdLO~2z_}r9oo7[ܹ R `65@Ui]-"U qGfP$j̣`*fS3pTHTK:qnpt̠6I G5Tj̦fj촸ԱӢS$j̣`*fS3pT5vZ\iѩnpt̠hp%tEXtdate:create2013-10-20T19:55:02-07:00%tEXtdate:modify2013-10-20T19:55:02-07:00IENDB`PK\sLdefault/views/public/js/jquery/images/ui-bg_gloss-wave_35_f6a828_500x100.pngnu[PNG  IHDRd5ibKGD X pHYsHHFk>IDATx_gULTT,` JI-,㭓Wz5WE3HG)veZQ{múIf^yƥ֭ٹw>%:%:3Hϸ*y{ERq Se&L6`aUfy ^Sefa;Oz }׵SˇU2f[nqw߁ IYV RWƱB-Uf'%S 6Wʎnsp Oل'ׂrҳ\˷v5S[nS~53|w9 eY\9pea'z{{,;:݂QyFGlҧ<<;z/EX %vT{œڦbѵ<*Y|+uuKհz"75n޺e^+*)sS -<-ך)ޖy xuVYW>ςmYΦwס k|iX!| 0 Sǽq{C˒S|gg?&S>0PtfMEΠRvt[z]4]me*բ%/wayc) ͻWy);C>~,^+uK_ymg[%+73U,גqjV˰v?0 ǿ?Ӧ6㟕޻%}7A>l*ǿ>,&Be^jixklM*}شe\sͼ*Mcϗ'z%wbǔ%3´|Kޭ;aGgUvS$w^?^z(fᵜꫫ蟧dyf㾺%Qm|Gɋ׾]jg[ ]1aG3vZѥtսg{ҳkWc,+ת[U爒Me%|*ϝZ+F~=EyD4p6y=~/~~pݢD|??.{W4][f :'继S `tOYp'|?zG"k3÷'2׿vvlq6'3݅[p?z0랾I{fτG³6wvol lx{p2Lwמ? bOnT~4-m.|,\ 7 ép:=;ݓsSݝ፭~[Hlt7c]ݍ?սug=.;`hKW~O ,l}ͩӍ㾭_;4f\a_Z>>o{z{y oL,^x/zbxBnW>Xw0qn tφ{ m7óݧ˳p{w&\ ߱|!\N_ ?аpbB _/-;5 J0iG+ſX ^C:=ץ?xp".t-G |f/9|>{뼣@ t،F/W›}aKz{8}Ob|yvUKz)00;[Kʯ2|-iꛚJ?SsmӪBGѼEُLcZRK]l}}[&^Sa',~-?/_`e OãqyհfbiXbEZl4dſns&w 0˰?w>&<|2S G 6x,w,)u=)]o;F)\@?mQϵk3(}֌>䭐Ʋӽݴ5'E,Ԋ&^5άueFd|5G|lW)y}t_x0 ^H~4f 3WSe`q*e`ÙeT͆S&@e_N'ۤ*x-}R*Sؚ ԭqVR+^UJ"euJfzlz}G37^^5[relѕLzz#zJEyV<ک]Z>zWJR]t=? d2G+-ݾ^>mkLYЂJSlz+Qfwezt˰v3/ٯ~gLyX}6<,l6é2vòU 2'U3tujJj|%u7MYU[Q+j( lyMϣRy}mUXlFW %>}ED֋fRZR{"x#[gGg3kPuN#?ۏ+w^q2=Q%tb}(lJ꠫Z^e?6llyU(Q(ӕO;_%/j]8޼uF^5fKE$sM;QuЭzv{hGuȦn~oY؞kmp+ަ{-ގ-t˶}2azS~֚v{G[b!/׵"^/k-*Į :GOd[{K(R}o5zs7u>]+*ܫVU %9b?Rf`%̯>[f[<F7ܪ2|+YKl&RϔڲNޟSa'\J]ۙڤ*cqOoI.tXR)TC(ʈ6z,v*֫[:Inxk>%w̋WJ$ֻ\oܗ^f]nJ|7ؾ}65J|7%5>Em_=eV /)m۵dgSWWNBʪ zYcX˫.}(Z>tUKfJz+dPS'ZڊyOXj=JW~i f<&uXRkƭE;7S刺v>xS*kGQJ"ڜo7AZ|צŨyn[j `-#GO p:X(T1%ǁU0} U=)zNz,˰vϞwVȼ^-mqJݯMmq:E7J-NQSjN𰕬unIzEf7oŶ^e5{׸~u+YJu}9dk9ϫ%g(g(} ObN(Z wMɌ0w_:_ ˰v,l˿׾p}`|7u]WJ[ɔe%hT>Cˣn珒}ExgJUFT7Fj*تz[oFVZsD NI~ujEn<c򞹵fW2n} le+a޿{GW?n7 IDATx]]%uzfV^;lY03&)]P 'M@+ȋa k`J!&~H2ք F?!0_&`>u޹?U_3sSu|U]:!D@t 8"t@M;ljH=&Omk3FB8F;@* cOy=kWڅە 3ANI*vP-ast $Hp As21E,ځ ԪGE'ihe]iSǼjvqPr /Y e-ڦt R5wgf I;&ImJmqkۦw4BsȠWM &_ /1n;z_$ 8H`# pDH 8|3h2oF)e>}Hl>LBV-}uҾo|ڵ/l| "o]}HSwǗAs!803@j~yӇ 4h >@")J_9]L;njq (pDH 8"G$@'MqXi}"03]AS(~ @@-$M6 W3'79+OqOh\O< `xTOHp/dg4 "GlՈf+)CO'u*c'TMKh^< uWhzHʇڸq풁| vAM1|B2 t3XbhW rsnZLwpO~8 pđ 8"G$@# pCR~O xDsM* |{oWC;]Հl5)^^ #šNv97> tm aϿ_ k{bW%p@ݖC>۩`ͤqǽ;~>iCZX^[HfalsX'0M _I~9'}~{.@62,hPU@U൓)UCH _\f.*@/gN*C-{g7H4ɼkor?_59]bU/_kp)m/qToLZ8D88"G$@#`ܘ*s> ʧ轎I{`>@1%,`35"G # pDH1{Hg[0 ˖\6%Hqx,Oaflxt! b[WX7wNyZ.ZuCTk qh_|kj~Q@n2=A6-kϺ"-RgZPv \͹8f/-Kp[΃:%,AL&S&D'Ms>A' FUf` JvQ8]6"?_޽C$n\Ba#¬#,5D3fq# p,'?'޷:0+n֚^vx] f 45b{=6v=NWxG8£K3kt͒] -F⛛./復Ou{~#qRyB+xۂJP1 !%3/` >\^dG/N-^ZvP#Y"ho \[LugHz~]()`+8PS~3OY((My~;HĻ}x 9 2SwG 9M\f/A1n~p SN<p-@o.-t>0-[\_g@6 nYNa .B|9>.N&hD[/3 oL59G0>*Z;"x}Œ.QٟJ| LQG5c̍ >Iէ-}{s=5}  _<Գ{ɂWZgԔ5~c|- 8"G$@X,WE Zm}p-oCCmȹA'[69~ ӎP#0*)uQDvi)FF4dAntÐ˞lO6;R,:ElPǔ K:Dۄt).kL9AOqrџWԧlJߢ\&;߈2AK9DiZyQ#5۬|{MHD#JD\8)ju9|1~=O=\Vn~'/PX(,u'0MPŃmq | J~yL1ާ{W/?o ]}uܙ F&*S\=u3~NzߤYq6DR_/MwElJCǯq!Lw]*ԐjΛ O]DCBɡB&@_fd]zva{!_nmSQnoMkn[qP3.)#{>oCz!U&6~߃JeتI]Ӻe9Qa.%sj=;x{DŽy:8"G$@ sɠ|6zCm79V ^Vzk}4*HAɿ6ZtF..2>Ot-fV;W_ٞ,O >Z|ya~萻B ki#@u"ڥ! *7! f3DckTɰCk.sPש;C<}Ra0L;7Lw5@6JCDV#NXFa곮8y>B %:dH Ar'@+2oH:͢ Ӻ]r8C`W;ErV۸ruEP;3*'JcIzkRl `OW*}Cc |NY+UOr1\LSZ5):aPlNw"Cهf9K`>3Jghe|7IqN[ʥ^c7Mq=M*3+1qKʯ3!KfŠ6|#y >_&lʶ&1_TjW`iHCڥټ ,Z7֟Ԫl;w*QwyFϜhc14R6i6h~ P6S]*r3pC۴NB;G~gj!|hϔ}vQ{z,pQGD{~9 )ߛzn&@T>51 偠0I˫\!\rrh3>]Y7PtӴDO[5nA ] alT2A_&\An4'':aOHc 0  w޺{Gg3/R1T0+ޔ0Rm柅`o*~ _g uFjǟ=sxpE)VU9vuZO=j<_>o5@HPGx#;I 0Q#zG$@# pDZK*6Aa\n6v[K(Ѯ0zLI/jnЮ|y.4qE صẄ́xjq {Y>.]!a[!i.d&~RJ4`&@Sۥ sy7wphq= lefy y_Eŵ^ըwXQ" tloޡs9eSR~ڥ|;i6\/$ʗʿx8_t+xp+ި$@'q_Ǔ.t-o\}]m&-t-o}dC>rFO|Ӗw8KCH7V'J M֝`\ W#|{B ̪$y4,}F>nk-PWEAtH=jiY'W;S'QOQL7DO=@w=KFR™?ЛΕN8#(p̯/ b,?Pw%tEXtdate:create2013-02-01T05:33:10-08:00)`%tEXtdate:modify2013-02-01T05:33:10-08:00X=x.tEXtSoftwareAdobe ImageReadyqe<IENDB`PK\]Adefault/views/public/js/jquery/images/ui-icons_ef8c08_256x240.pngnu[PNG  IHDRIJPLTEjYtRNS3P/"Uq@f`2 !<BHK Z#'1S,4j8E|)Q$ bJmߜGc?oh@^bKGDH pHYsHHFk>dIDATx] c۶H阒]Kd%٫뺮lmw]|pXm-}X:+iĆQV9\e'AtOS:72YsxMہB&z>nC@r@*aӝ%MFDDDDDDTߖH,ERUn ب\f͹:}4ᦋ{)n[ ̰E K Y Dۇ- +Kl=ӃL`љ|%n a N#5 (4?EDDDD\oWFfq;\E_,W!%zE!F¶. (USHQ0dw)T 8#p,xBK *xXEe K솎%mKX~sFE~tdcaI1Af4dHcGSB`0wev`"{ .GDDDD,dO6k"qkMefS_UKŌ&g~>n H}) LF%8()r![4统qQk0m[Le_70@>1 X0AZVcEV Ltk3EJ44ZﮊN`rt>`˥  AHBLH@cUq=jcM2sJCLiR NQ0=Yi-|4V ]]B^ޞ_H$<$ a=d@ (ZAp_}~s:N{DC>m^ƒS&, ;N&B} <_AB]HuN(B0{h1IKDs j' M8.ӫ1h3df}mq nU{Lo z \=?@ ((e|=ơ麄Ci1r<|OO; `HpQyzԈuZVƲ!)5mC2Lyg;֑RjWa@@VL&Wru=Z ̥=U5} 7;b(nP&sk48ͥ01U Wvk18dqTՌE]qH8 GF K'rOrŗ6"fpT^3c"nMم-/W=tJ,X){P Rm|K>mX8v5h<_{ꘀYF|&_G;&>^W⁃&K(81EB@F&;"L'wfwE-6o&/̫'Xe,>~ee|A=) dQ`}P[KN˂/~)O[dO=3El5'Y$?7mTzզ.\.` WE"""""v)V#]L;zqJr²[\-tҽ5 @ͷϟnT@+;cQhC*TڙAVr?f? Q1T`} Hk,{VZˋTϛ?I̯uQKLMe͆~qym09 S;j5 iQ]7k0UޭGkX3#lY_Цxj޶9`# M [z KuO_z˿Dܭ*kOJ(7n\e ITƨl/U߶uw.~;#r.8 o# 5Lh>1i pVM?/u70 X@L+M+{Fkt{ŧ890`. ĀCR+\/t R; TӲ]aL|efđ >ۣG|P`P8C1K՛A̍<2ۂKrl@L L 8@E>`nPNԍ,p EƆZF lÎ; F7Ȯ; swSz)g7{rsSgȋ(߄~AWytX$NVR_<6p.O8O[OdDk>_OO}JSdmV?W(_m j~=H IԁF>T/{*]IGJ@iqamNF|Q50+ ES8:v`p~vj:Bp96oys% |@H]+@t]Wk}}7FʮrAB\m-_2PY8xՎN.h~@+7z5t_//?0S>)zi0n/B`{DW#`Bo[,gFVЁpP߾C]Bz ,XXfԃA:H k7dZ9oc}o]0vd:R]0ve]刈jу| ? +(OǍ+ #ysߍnpFru<.HȺotM3h}߆P}˗vP}mǀ?WZ@}@@FDl%tEXtdate:create2013-02-01T05:33:10-08:00)`%tEXtdate:modify2013-02-01T05:33:10-08:00X=x.tEXtSoftwareAdobe ImageReadyqe<IENDB`PK\KbQHHNdefault/views/public/js/jquery/images/ui-bg_highlight-soft_75_ffe45c_1x100.pngnu[PNG  IHDRdtbKGD X pHYsHHFk>IDAT(1 PDSZ 6M!rKJFf,>Ao`x;,,csp>҇uQ`߯i%S)~ζ rV =O・ pl:]ZO?q|%tEXtdate:create2013-10-20T19:55:03-07:00%tEXtdate:modify2013-10-20T19:55:03-07:00tIENDB`PK\f#FQFQ1default/views/public/js/jquery/jquery.validate.jsnu[/*! jQuery Validation Plugin - v1.12.0 - 4/1/2014 * http://jqueryvalidation.org/ * Copyright (c) 2014 Jörn Zaefferer; Licensed MIT */ !function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.validateDelegate(":submit","click",function(b){c.settings.submitHandler&&(c.submitButton=b.target),a(b.target).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(b.target).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.submit(function(b){function d(){var d;return c.settings.submitHandler?(c.submitButton&&(d=a("").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),c.settings.submitHandler.call(c,c.currentForm,b),c.submitButton&&d.remove(),!1):!0}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c;return a(this[0]).is("form")?b=this.validate().form():(b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b})),b},removeAttrs:function(b){var c={},d=this;return a.each(b.split(/\s/),function(a,b){c[b]=d.attr(b),d.removeAttr(b)}),c},rules:function(b,c){var d,e,f,g,h,i,j=this[0];if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(b,c){i[c]=f[c],delete f[c],"required"===c&&a(j).removeAttr("aria-required")}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g),a(j).attr("aria-required","true")),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}),a.extend(a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){return!!a.trim(""+a(b).val())},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(a)).hide())},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(a,b){(9!==b.which||""!==this.elementValue(a))&&(a.name in this.submitted||a===this.lastElement)&&this.element(a)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c=a.data(this[0].form,"validator"),d="on"+b.type.replace(/^validate/,""),e=c.settings;e[d]&&!this.is(e.ignore)&&e[d].call(c,this[0],b)}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){d[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",b).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",b),this.settings.invalidHandler&&a(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler),a(this.currentForm).find("[required], [data-rule-required], .required").attr("aria-required","true")},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c=this.clean(b),d=this.validationTargetFor(c),e=!0;return this.lastElement=d,void 0===d?delete this.invalid[c.name]:(this.prepareElement(d),this.currentElements=a(d),e=this.check(d)!==!1,e?delete this.invalid[d.name]:this.invalid[d.name]=!0),a(b).attr("aria-invalid",!e),this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),e},showErrors:function(b){if(b){a.extend(this.errorMap,b),this.errorList=[];for(var c in b)this.errorList.push({message:b[c],element:this.findByName(c)[0]});this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue").removeAttr("aria-invalid")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)c++;return c},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in c||!b.objectLength(a(this).rules())?!1:(c[this.name]=!0,!0)})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([]),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d=a(b),e=d.attr("type");return"radio"===e||"checkbox"===e?a("input[name='"+d.attr("name")+"']:checked").val():(c=d.val(),"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f=a(b).rules(),g=a.map(f,function(a,b){return b}).length,h=!1,i=this.elementValue(b);for(d in f){e={method:d,parameters:f[d]};try{if(c=a.validator.methods[d].call(this,i,b,e.parameters),"dependency-mismatch"===c&&1===g){h=!0;continue}if(h=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(j){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",j),j}}if(!h)return this.objectLength(f)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c[0].toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+"")},formatAndAdd:function(b,c){var d=this.defaultMessage(b,c.method),e=/\$?\{(\d+)\}/g;"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),this.errorList.push({message:d,element:b,method:c.method}),this.errorMap[b.name]=d,this.submitted[b.name]=d},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d=this.errorsFor(b);d.length?(d.removeClass(this.settings.validClass).addClass(this.settings.errorClass),d.html(c)):(d=a("<"+this.settings.errorElement+">").attr("for",this.idOrName(b)).addClass(this.settings.errorClass).html(c||""),this.settings.wrapper&&(d=d.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(d).length||(this.settings.errorPlacement?this.settings.errorPlacement(d,a(b)):d.insertAfter(b))),!c&&this.settings.success&&(d.text(""),"string"==typeof this.settings.success?d.addClass(this.settings.success):this.settings.success(d,b)),this.toShow=this.toShow.add(d)},errorsFor:function(b){var c=this.idOrName(b);return this.errors().filter(function(){return a(this).attr("for")===c})},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(a){return this.checkable(a)&&(a=this.findByName(a.name).not(this.settings.ignore)[0]),a},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+b+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return this.dependTypes[typeof a]?this.dependTypes[typeof a](a,b):!0},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(a){this.pending[a.name]||(this.pendingRequest++,this.pending[a.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b){return a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),/min|max/.test(c)&&(null===g||/number|range|text/.test(g))&&(d=Number(d)),d||0===d?e[c]=d:g===c&&"range"!==g&&(e[c]=!0);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b);for(c in a.validator.methods)d=f.data("rule"+c[0].toUpperCase()+c.substring(1).toLowerCase()),void 0!==d&&(e[c]=d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0!==e.param?e.param:!0:delete b[d]}}),a.each(b,function(d,e){b[d]=a.isFunction(e)?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(b.min&&b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),b.minlength&&b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:a.trim(b).length>0},email:function(a,b){return this.optional(b)||/^[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])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(a)},date:function(a,b){return this.optional(b)||!/Invalid|NaN/.test(new Date(a).toString())},dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(a)},number:function(a,b){return this.optional(b)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},creditcard:function(a,b){if(this.optional(b))return"dependency-mismatch";if(/[^0-9 \-]+/.test(a))return!1;var c,d,e=0,f=0,g=!1;if(a=a.replace(/\D/g,""),a.length<13||a.length>19)return!1;for(c=a.length-1;c>=0;c--)d=a.charAt(c),f=parseInt(d,10),g&&(f*=2)>9&&(f-=9),e+=f,g=!g;return e%10===0},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(a.trim(b),c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(a.trim(b),c);return this.optional(c)||d>=e},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(a.trim(b),c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||c>=a},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d){if(this.optional(c))return"dependency-mismatch";var e,f,g=this.previousValue(c);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),g.originalMessage=this.settings.messages[c.name].remote,this.settings.messages[c.name].remote=g.message,d="string"==typeof d&&{url:d}||d,g.old===b?g.valid:(g.old=b,e=this,this.startRequest(c),f={},f[c.name]=b,a.ajax(a.extend(!0,{url:d,mode:"abort",port:"validate"+c.name,dataType:"json",data:f,context:e.currentForm,success:function(d){var f,h,i,j=d===!0||"true"===d;e.settings.messages[c.name].remote=g.originalMessage,j?(i=e.formSubmitted,e.prepareElement(c),e.formSubmitted=i,e.successList.push(c),delete e.invalid[c.name],e.showErrors()):(f={},h=d||e.defaultMessage(c,"remote"),f[c.name]=g.message=a.isFunction(h)?h(b):h,e.invalid[c.name]=!0,e.showErrors(f)),g.valid=j,e.stopRequest(c,j)}},d)),"pending")}}}),a.format=function(){throw"$.format has been deprecated. Please use $.validator.format instead."}}(jQuery),function(a){var b,c={};a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)})}(jQuery),function(a){a.extend(a.fn,{validateDelegate:function(b,c,d){return this.bind(c,function(c){var e=a(c.target);return e.is(b)?d.apply(e,arguments):void 0})}})}(jQuery);PK\[FF(default/views/public/js/jquery/jquery.jsnu[/*! jQuery v2.1.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ !function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k="".trim,l={},m=a.document,n="2.1.0",o=function(a,b){return new o.fn.init(a,b)},p=/^-ms-/,q=/-([\da-z])/gi,r=function(a,b){return b.toUpperCase()};o.fn=o.prototype={jquery:n,constructor:o,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=o.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return o.each(this,a,b)},map:function(a){return this.pushStack(o.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},o.extend=o.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||o.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(a=arguments[h]))for(b in a)c=g[b],d=a[b],g!==d&&(j&&d&&(o.isPlainObject(d)||(e=o.isArray(d)))?(e?(e=!1,f=c&&o.isArray(c)?c:[]):f=c&&o.isPlainObject(c)?c:{},g[b]=o.extend(j,f,d)):void 0!==d&&(g[b]=d));return g},o.extend({expando:"jQuery"+(n+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===o.type(a)},isArray:Array.isArray,isWindow:function(a){return null!=a&&a===a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isPlainObject:function(a){if("object"!==o.type(a)||a.nodeType||o.isWindow(a))return!1;try{if(a.constructor&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(b){return!1}return!0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(a){var b,c=eval;a=o.trim(a),a&&(1===a.indexOf("use strict")?(b=m.createElement("script"),b.text=a,m.head.appendChild(b).parentNode.removeChild(b)):c(a))},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":k.call(a)},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?o.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){return null==b?-1:g.call(b,a,c)},merge:function(a,b){for(var c=+b.length,d=0,e=a.length;c>d;d++)a[e++]=b[d];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(c=a[b],b=a,a=c),o.isFunction(a)?(e=d.call(arguments,2),f=function(){return a.apply(b||this,e.concat(d.call(arguments)))},f.guid=a.guid=a.guid||o.guid++,f):void 0},now:Date.now,support:l}),o.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=o.type(a);return"function"===c||o.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
      ",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);o.find=t,o.expr=t.selectors,o.expr[":"]=o.expr.pseudos,o.unique=t.uniqueSort,o.text=t.getText,o.isXMLDoc=t.isXML,o.contains=t.contains;var u=o.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(o.isFunction(b))return o.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return o.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return o.filter(b,a,c);b=o.filter(b,a)}return o.grep(a,function(a){return g.call(b,a)>=0!==c})}o.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?o.find.matchesSelector(d,a)?[d]:[]:o.find.matches(a,o.grep(b,function(a){return 1===a.nodeType}))},o.fn.extend({find:function(a){var b,c=this.length,d=[],e=this;if("string"!=typeof a)return this.pushStack(o(a).filter(function(){for(b=0;c>b;b++)if(o.contains(e[b],this))return!0}));for(b=0;c>b;b++)o.find(a,e[b],d);return d=this.pushStack(c>1?o.unique(d):d),d.selector=this.selector?this.selector+" "+a:a,d},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?o(a):a||[],!1).length}});var y,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=o.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a[0]&&">"===a[a.length-1]&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof o?b[0]:b,o.merge(this,o.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:m,!0)),v.test(c[1])&&o.isPlainObject(b))for(c in b)o.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}return d=m.getElementById(c[2]),d&&d.parentNode&&(this.length=1,this[0]=d),this.context=m,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):o.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(o):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),o.makeArray(a,this))};A.prototype=o.fn,y=o(m);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};o.extend({dir:function(a,b,c){var d=[],e=void 0!==c;while((a=a[b])&&9!==a.nodeType)if(1===a.nodeType){if(e&&o(a).is(c))break;d.push(a)}return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),o.fn.extend({has:function(a){var b=o(a,this),c=b.length;return this.filter(function(){for(var a=0;c>a;a++)if(o.contains(this,b[a]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?o(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&o.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?o.unique(f):f)},index:function(a){return a?"string"==typeof a?g.call(o(a),this[0]):g.call(this,a.jquery?a[0]:a):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(o.unique(o.merge(this.get(),o(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){while((a=a[b])&&1!==a.nodeType);return a}o.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return o.dir(a,"parentNode")},parentsUntil:function(a,b,c){return o.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return o.dir(a,"nextSibling")},prevAll:function(a){return o.dir(a,"previousSibling")},nextUntil:function(a,b,c){return o.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return o.dir(a,"previousSibling",c)},siblings:function(a){return o.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return o.sibling(a.firstChild)},contents:function(a){return a.contentDocument||o.merge([],a.childNodes)}},function(a,b){o.fn[a]=function(c,d){var e=o.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=o.filter(d,e)),this.length>1&&(C[a]||o.unique(e),B.test(a)&&e.reverse()),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return o.each(a.match(E)||[],function(a,c){b[c]=!0}),b}o.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):o.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(b=a.memory&&l,c=!0,g=e||0,e=0,f=h.length,d=!0;h&&f>g;g++)if(h[g].apply(l[0],l[1])===!1&&a.stopOnFalse){b=!1;break}d=!1,h&&(i?i.length&&j(i.shift()):b?h=[]:k.disable())},k={add:function(){if(h){var c=h.length;!function g(b){o.each(b,function(b,c){var d=o.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&g(c)})}(arguments),d?f=h.length:b&&(e=c,j(b))}return this},remove:function(){return h&&o.each(arguments,function(a,b){var c;while((c=o.inArray(b,h,c))>-1)h.splice(c,1),d&&(f>=c&&f--,g>=c&&g--)}),this},has:function(a){return a?o.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],f=0,this},disable:function(){return h=i=b=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,b||k.disable(),this},locked:function(){return!i},fireWith:function(a,b){return!h||c&&!i||(b=b||[],b=[a,b.slice?b.slice():b],d?i.push(b):j(b)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!c}};return k},o.extend({Deferred:function(a){var b=[["resolve","done",o.Callbacks("once memory"),"resolved"],["reject","fail",o.Callbacks("once memory"),"rejected"],["notify","progress",o.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return o.Deferred(function(c){o.each(b,function(b,f){var g=o.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&o.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?o.extend(a,d):d}},e={};return d.pipe=d.then,o.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&o.isFunction(a.promise)?e:0,g=1===f?a:o.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&o.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;o.fn.ready=function(a){return o.ready.promise().done(a),this},o.extend({isReady:!1,readyWait:1,holdReady:function(a){a?o.readyWait++:o.ready(!0)},ready:function(a){(a===!0?--o.readyWait:o.isReady)||(o.isReady=!0,a!==!0&&--o.readyWait>0||(H.resolveWith(m,[o]),o.fn.trigger&&o(m).trigger("ready").off("ready")))}});function I(){m.removeEventListener("DOMContentLoaded",I,!1),a.removeEventListener("load",I,!1),o.ready()}o.ready.promise=function(b){return H||(H=o.Deferred(),"complete"===m.readyState?setTimeout(o.ready):(m.addEventListener("DOMContentLoaded",I,!1),a.addEventListener("load",I,!1))),H.promise(b)},o.ready.promise();var J=o.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===o.type(c)){e=!0;for(h in c)o.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,o.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(o(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f};o.acceptData=function(a){return 1===a.nodeType||9===a.nodeType||!+a.nodeType};function K(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=o.expando+Math.random()}K.uid=1,K.accepts=o.acceptData,K.prototype={key:function(a){if(!K.accepts(a))return 0;var b={},c=a[this.expando];if(!c){c=K.uid++;try{b[this.expando]={value:c},Object.defineProperties(a,b)}catch(d){b[this.expando]=c,o.extend(a,b)}}return this.cache[c]||(this.cache[c]={}),c},set:function(a,b,c){var d,e=this.key(a),f=this.cache[e];if("string"==typeof b)f[b]=c;else if(o.isEmptyObject(f))o.extend(this.cache[e],b);else for(d in b)f[d]=b[d];return f},get:function(a,b){var c=this.cache[this.key(a)];return void 0===b?c:c[b]},access:function(a,b,c){var d;return void 0===b||b&&"string"==typeof b&&void 0===c?(d=this.get(a,b),void 0!==d?d:this.get(a,o.camelCase(b))):(this.set(a,b,c),void 0!==c?c:b)},remove:function(a,b){var c,d,e,f=this.key(a),g=this.cache[f];if(void 0===b)this.cache[f]={};else{o.isArray(b)?d=b.concat(b.map(o.camelCase)):(e=o.camelCase(b),b in g?d=[b,e]:(d=e,d=d in g?[d]:d.match(E)||[])),c=d.length;while(c--)delete g[d[c]]}},hasData:function(a){return!o.isEmptyObject(this.cache[a[this.expando]]||{})},discard:function(a){a[this.expando]&&delete this.cache[a[this.expando]]}};var L=new K,M=new K,N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){var d;if(void 0===c&&1===a.nodeType)if(d="data-"+b.replace(O,"-$1").toLowerCase(),c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?o.parseJSON(c):c}catch(e){}M.set(a,b,c)}else c=void 0;return c}o.extend({hasData:function(a){return M.hasData(a)||L.hasData(a)},data:function(a,b,c){return M.access(a,b,c)},removeData:function(a,b){M.remove(a,b)},_data:function(a,b,c){return L.access(a,b,c)},_removeData:function(a,b){L.remove(a,b)}}),o.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=M.get(f),1===f.nodeType&&!L.get(f,"hasDataAttrs"))){c=g.length; while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=o.camelCase(d.slice(5)),P(f,d,e[d]));L.set(f,"hasDataAttrs",!0)}return e}return"object"==typeof a?this.each(function(){M.set(this,a)}):J(this,function(b){var c,d=o.camelCase(a);if(f&&void 0===b){if(c=M.get(f,a),void 0!==c)return c;if(c=M.get(f,d),void 0!==c)return c;if(c=P(f,d,void 0),void 0!==c)return c}else this.each(function(){var c=M.get(this,d);M.set(this,d,b),-1!==a.indexOf("-")&&void 0!==c&&M.set(this,a,b)})},null,b,arguments.length>1,null,!0)},removeData:function(a){return this.each(function(){M.remove(this,a)})}}),o.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=L.get(a,b),c&&(!d||o.isArray(c)?d=L.access(a,b,o.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=o.queue(a,b),d=c.length,e=c.shift(),f=o._queueHooks(a,b),g=function(){o.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return L.get(a,c)||L.access(a,c,{empty:o.Callbacks("once memory").add(function(){L.remove(a,[b+"queue",c])})})}}),o.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var U="undefined";l.focusinBubbles="onfocusin"in a;var V=/^key/,W=/^(?:mouse|contextmenu)|click/,X=/^(?:focusinfocus|focusoutblur)$/,Y=/^([^.]*)(?:\.(.+)|)$/;function Z(){return!0}function $(){return!1}function _(){try{return m.activeElement}catch(a){}}o.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=o.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return typeof o!==U&&o.event.triggered!==b.type?o.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(E)||[""],j=b.length;while(j--)h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n&&(l=o.event.special[n]||{},n=(e?l.delegateType:l.bindType)||n,l=o.event.special[n]||{},k=o.extend({type:n,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&o.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[n])||(m=i[n]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(n,g,!1)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),o.event.global[n]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,n,p,q,r=L.hasData(a)&&L.get(a);if(r&&(i=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=Y.exec(b[j])||[],n=q=h[1],p=(h[2]||"").split(".").sort(),n){l=o.event.special[n]||{},n=(d?l.delegateType:l.bindType)||n,m=i[n]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||o.removeEvent(a,n,r.handle),delete i[n])}else for(n in i)o.event.remove(a,n+b[j],c,d,!0);o.isEmptyObject(i)&&(delete r.handle,L.remove(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,p=[d||m],q=j.call(b,"type")?b.type:b,r=j.call(b,"namespace")?b.namespace.split("."):[];if(g=h=d=d||m,3!==d.nodeType&&8!==d.nodeType&&!X.test(q+o.event.triggered)&&(q.indexOf(".")>=0&&(r=q.split("."),q=r.shift(),r.sort()),k=q.indexOf(":")<0&&"on"+q,b=b[o.expando]?b:new o.Event(q,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=r.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+r.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:o.makeArray(c,[b]),n=o.event.special[q]||{},e||!n.trigger||n.trigger.apply(d,c)!==!1)){if(!e&&!n.noBubble&&!o.isWindow(d)){for(i=n.delegateType||q,X.test(i+q)||(g=g.parentNode);g;g=g.parentNode)p.push(g),h=g;h===(d.ownerDocument||m)&&p.push(h.defaultView||h.parentWindow||a)}f=0;while((g=p[f++])&&!b.isPropagationStopped())b.type=f>1?i:n.bindType||q,l=(L.get(g,"events")||{})[b.type]&&L.get(g,"handle"),l&&l.apply(g,c),l=k&&g[k],l&&l.apply&&o.acceptData(g)&&(b.result=l.apply(g,c),b.result===!1&&b.preventDefault());return b.type=q,e||b.isDefaultPrevented()||n._default&&n._default.apply(p.pop(),c)!==!1||!o.acceptData(d)||k&&o.isFunction(d[q])&&!o.isWindow(d)&&(h=d[k],h&&(d[k]=null),o.event.triggered=q,d[q](),o.event.triggered=void 0,h&&(d[k]=h)),b.result}},dispatch:function(a){a=o.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(L.get(this,"events")||{})[a.type]||[],k=o.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=o.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(g.namespace))&&(a.handleObj=g,a.data=g.data,e=((o.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==e&&(a.result=e)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!==this;i=i.parentNode||this)if(i.disabled!==!0||"click"!==a.type){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?o(e,this).index(i)>=0:o.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,bb=/<([\w:]+)/,cb=/<|&#?\w+;/,db=/<(?:script|style|link)/i,eb=/checked\s*(?:[^=]|=\s*.checked.)/i,fb=/^$|\/(?:java|ecma)script/i,gb=/^true\/(.*)/,hb=/^\s*\s*$/g,ib={option:[1,""],thead:[1,"","
      "],col:[2,"","
      "],tr:[2,"","
      "],td:[3,"","
      "],_default:[0,"",""]};ib.optgroup=ib.option,ib.tbody=ib.tfoot=ib.colgroup=ib.caption=ib.thead,ib.th=ib.td;function jb(a,b){return o.nodeName(a,"table")&&o.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function kb(a){return a.type=(null!==a.getAttribute("type"))+"/"+a.type,a}function lb(a){var b=gb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function mb(a,b){for(var c=0,d=a.length;d>c;c++)L.set(a[c],"globalEval",!b||L.get(b[c],"globalEval"))}function nb(a,b){var c,d,e,f,g,h,i,j;if(1===b.nodeType){if(L.hasData(a)&&(f=L.access(a),g=L.set(b,f),j=f.events)){delete g.handle,g.events={};for(e in j)for(c=0,d=j[e].length;d>c;c++)o.event.add(b,e,j[e][c])}M.hasData(a)&&(h=M.access(a),i=o.extend({},h),M.set(b,i))}}function ob(a,b){var c=a.getElementsByTagName?a.getElementsByTagName(b||"*"):a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&o.nodeName(a,b)?o.merge([a],c):c}function pb(a,b){var c=b.nodeName.toLowerCase();"input"===c&&T.test(a.type)?b.checked=a.checked:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}o.extend({clone:function(a,b,c){var d,e,f,g,h=a.cloneNode(!0),i=o.contains(a.ownerDocument,a);if(!(l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||o.isXMLDoc(a)))for(g=ob(h),f=ob(a),d=0,e=f.length;e>d;d++)pb(f[d],g[d]);if(b)if(c)for(f=f||ob(a),g=g||ob(h),d=0,e=f.length;e>d;d++)nb(f[d],g[d]);else nb(a,h);return g=ob(h,"script"),g.length>0&&mb(g,!i&&ob(a,"script")),h},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k=b.createDocumentFragment(),l=[],m=0,n=a.length;n>m;m++)if(e=a[m],e||0===e)if("object"===o.type(e))o.merge(l,e.nodeType?[e]:e);else if(cb.test(e)){f=f||k.appendChild(b.createElement("div")),g=(bb.exec(e)||["",""])[1].toLowerCase(),h=ib[g]||ib._default,f.innerHTML=h[1]+e.replace(ab,"<$1>")+h[2],j=h[0];while(j--)f=f.lastChild;o.merge(l,f.childNodes),f=k.firstChild,f.textContent=""}else l.push(b.createTextNode(e));k.textContent="",m=0;while(e=l[m++])if((!d||-1===o.inArray(e,d))&&(i=o.contains(e.ownerDocument,e),f=ob(k.appendChild(e),"script"),i&&mb(f),c)){j=0;while(e=f[j++])fb.test(e.type||"")&&c.push(e)}return k},cleanData:function(a){for(var b,c,d,e,f,g,h=o.event.special,i=0;void 0!==(c=a[i]);i++){if(o.acceptData(c)&&(f=c[L.expando],f&&(b=L.cache[f]))){if(d=Object.keys(b.events||{}),d.length)for(g=0;void 0!==(e=d[g]);g++)h[e]?o.event.remove(c,e):o.removeEvent(c,e,b.handle);L.cache[f]&&delete L.cache[f]}delete M.cache[c[M.expando]]}}}),o.fn.extend({text:function(a){return J(this,function(a){return void 0===a?o.text(this):this.empty().each(function(){(1===this.nodeType||11===this.nodeType||9===this.nodeType)&&(this.textContent=a)})},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=jb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?o.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||o.cleanData(ob(c)),c.parentNode&&(b&&o.contains(c.ownerDocument,c)&&mb(ob(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++)1===a.nodeType&&(o.cleanData(ob(a,!1)),a.textContent="");return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return o.clone(this,a,b)})},html:function(a){return J(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a&&1===b.nodeType)return b.innerHTML;if("string"==typeof a&&!db.test(a)&&!ib[(bb.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(ab,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(o.cleanData(ob(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,o.cleanData(ob(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,n=k-1,p=a[0],q=o.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&eb.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(c=o.buildFragment(a,this[0].ownerDocument,!1,this),d=c.firstChild,1===c.childNodes.length&&(c=d),d)){for(f=o.map(ob(c,"script"),kb),g=f.length;k>j;j++)h=c,j!==n&&(h=o.clone(h,!0,!0),g&&o.merge(f,ob(h,"script"))),b.call(this[j],h,j);if(g)for(i=f[f.length-1].ownerDocument,o.map(f,lb),j=0;g>j;j++)h=f[j],fb.test(h.type||"")&&!L.access(h,"globalEval")&&o.contains(i,h)&&(h.src?o._evalUrl&&o._evalUrl(h.src):o.globalEval(h.textContent.replace(hb,"")))}return this}}),o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){o.fn[a]=function(a){for(var c,d=[],e=o(a),g=e.length-1,h=0;g>=h;h++)c=h===g?this:this.clone(!0),o(e[h])[b](c),f.apply(d,c.get());return this.pushStack(d)}});var qb,rb={};function sb(b,c){var d=o(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:o.css(d[0],"display");return d.detach(),e}function tb(a){var b=m,c=rb[a];return c||(c=sb(a,b),"none"!==c&&c||(qb=(qb||o("').attr({ name : 'uploader-iframe-' + uploaderId, id : 'uploader-iframe-' + uploaderId }); $('body').append($form); $('body').append($frame); $frame.hide(); var $div = $input.wrap('
      ').parent().css({ overflow : 'hidden', width : $uploader.outerWidth(), height : $uploader.outerHeight() }).css({ position : 'absolute', 'z-index' : 10000 }); //emulate onresize event var intervalId = setInterval(function(){ if ($div.css('width')!=$uploader.outerWidth()) $div.css('width', $uploader.outerWidth()); if ($div.css('height')!=$uploader.outerHeight()) $div.css('height', $uploader.outerHeight()); }, 250) //remember inetrval id to clear setInterval in destructure $uploader.data('intervalId', intervalId); $input.css({ 'float':'right' }); $div.css({ opacity: 0 }); $input.bind('mouseover mouseout', function(){ $uploader.toggleClass('hover') }) $uploader.mousemove(function(e){ $div.css({ top: $uploader.offset().top+'px', left: $uploader.offset().left+'px' }); }); $input.change(function() { $this.data('params').onSelect.call($this); $this.data('params').onSubmit.call($this); $uploader.find('span').empty().append('Uploading...').addClass('uploading') $form.submit(); $frame.load(function() { var frame = document.getElementById($frame.attr('id')); var response = $(frame.contentWindow.document.body).text(); //console.log(response); try { response = $.parseJSON(response); } catch (e) { response = { ok : false, error : 'Error of file uploading on server side' }; } //console.log(response); //allow to complete 'load' event up to the end //before remove this element setTimeout(function(){ $this.reupload('addFile', response); }, 10); }); }); } }; $.fn.reupload = function( method ) { if ( methods[method] ) { return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof method === 'object' || ! method ) { return methods.init.apply( this, arguments ); } else { $.error( 'Method ' + method + ' does not exist on jQuery.upload' ); } }; })( jQuery );PK\q?=?= default/views/public/js/admin.jsnu[jQuery(document).ready(function(){ jQuery("input#user-lookup").autocomplete({ minLength: 2, source: amUrl("/admin-users/autocomplete"), select: function( event, ui ) { window.location = ui.item.url; return false; }, }); jQuery(document).on("click","._collapsible_ ._head_", function(){ jQuery(this).closest("._item_").toggleClass('_open_'); }); jQuery('#admin-login').submit(function(){ //jQuery('#admin-login').hide(); jQuery.ajax({ global: false, type : 'POST', url: jQuery('#admin-login form').attr('action'), data: jQuery('#admin-login input').serializeArray(), complete: function (response) { data = jQuery.parseJSON(response.responseText); if (!data) // bad response, redirect to login page { window.location.href = amUrl('/admin') return; } if (data.ok) { jQuery('#admin-login').dialog('destroy'); } else { jQuery("#admin-login .errors li").text(data.err); jQuery("#admin-login .errors").show(); } } }); jQuery('#admin-login input[name="passwd"]').val(''); return false; }); function displayLoginForm() { jQuery('#admin-login').dialog({ modal: true, title: "Administrator Login", width: '500' }); } jQuery(document).ajaxComplete(function (event, request, settings) { jQuery('div.ajax-loading').data("ajaxActive", false).hide(); if (request.status == 402) { var vars = jQuery.parseJSON(request.responseText); jQuery('#admin-login .error').text(vars['err'] ? vars['err'] : null); displayLoginForm(); } }) jQuery(document).ajaxStart(function () { var div = jQuery('div.ajax-loading'); div.data("ajaxActive", true); setTimeout(function () { if (div.data("ajaxActive")) div.show() }, 200); }); populateHtmlHint(); jQuery(document).on('click', "a.html-edit", function () { var id = jQuery(this).data('element-id'); var options = jQuery(this).data('mce-options'); jQuery('#' + jQuery(this).data('wrap-id')).dialog({ autoOpen: true, modal: true, title: jQuery(this).data('title'), width: 800, position: ['center', 100], buttons: { "Ok": function () { jQuery(this).dialog("close"); } }, beforeClose: function (event, ui) { destroyCkeditor(id); }, close: function (event, ui) { jQuery(this).dialog("destroy"); populateHtmlHint(); }, create: function (event, ui) { initCkeditor(id, options); } }); }); jQuery(document).on('click', "a.email-template", function () { var $div = jQuery(''); jQuery('body').append($div); var url = this.href; var actionUrl = url.replace(/\?.*$/, ''); var getQuery = url.replace(/^.*?\?/, ''); var $a = jQuery(this); $div.dialog({ autoOpen: false, modal: true, title: "Email Template", width: 800, position: ['center', 100], buttons: { "Save": function () { $div.find('form#EmailTemplate').ajaxSubmit({ success: function (res) { if (res.content) { $a.closest('.element').empty().append(res.content); } else if (res) { jQuery('#email-template-popup').html(res); return; } $div.dialog('close'); }, beforeSerialize: function () { if (CKEDITOR && CKEDITOR != 'undefined') for (instance in CKEDITOR.instances) CKEDITOR.instances[instance].updateElement(); } }); }, "Cancel": function () { jQuery(this).dialog("close"); } }, close: function () { $div.remove(); } }); jQuery.ajax({ type: 'post', data: getQuery, url: actionUrl, dataType: 'html', success: function (data, textStatus, XMLHttpRequest) { $div.empty().append(data); $div.dialog("open"); } }); return false; }); jQuery(".admin-menu").adminMenu(window.amActiveMenuID); initElements(); jQuery(document).ajaxComplete(function(){ //allow ajax handler to do needed tasks before convert elements setTimeout(initElements, 100); }); // scroll to error message if any var errors = jQuery(".errors:visible:first,.error:visible:first"); if (errors.length) jQuery("html, body").scrollTop(Math.floor(errors.offset().top)); }); function populateHtmlHint(){ jQuery('.html-edit-hint').each(function(){ jQuery(this).empty().text(jQuery(this).closest('.row').find('textarea').val().substr(0, 50)).append('…'); }); } function initElements(){ jQuery("select.magicselect").magicSelect(); jQuery("select.magicselect-sortable").magicSelect({sortable:true}); jQuery("select.am-combobox").select2({ minimumResultsForSearch : 10, width: "resolve" }); jQuery("select.am-combobox-fixed").select2({ disable_search_threshold : 10, width : "300px" }); if (window.amLangCount>1) { jQuery('.translate').translate(); } jQuery('input.options-editor').optionsEditor(); jQuery('.upload').upload(); jQuery('.reupload').reupload(); jQuery('input[type=file].styled').fileStyle(); jQuery('.one-per-line').onePerLine(); initDatepicker(); jQuery(".grid-wrap").ngrid(); populateHtmlHint(); } jQuery(document).on('blur', '.input_datetime-time', function(){ var s = $(this).val().replace(/[^0-9]/g, '').substr(0,4); s = s + '0000'.substr(0, 4-s.length); $(this).val(s.substr(0,2) + ':' + s.substr(2, 2)); }); function flashError(msg){ return flash(msg, 'error', 5000); } function flashMessage(msg){ return flash(msg, 'message', 2500); } function flash(msg, msgClass, timeout) { if (!jQuery('#flash-message').length) jQuery('body').append('
      '); lastId = Math.ceil(10000*Math.random()); var $div = jQuery("") jQuery('#flash-message').append($div); $div.fadeIn('slow'); if (timeout) setTimeout(function(id){ jQuery('#flashMsg-'+id).fadeOut('slow', function(){jQuery(this).remove()}); }, timeout, lastId); } jQuery.fn.serializeAssoc = function() { var res = {}; var arr = jQuery(this).serializeArray(); for (var i in arr) res[ arr[i]['name'] ] = arr[i]['value']; return res; } // modified version of http://alexking.org/blog/2003/06/02/inserting-at-the-cursor-using-javascript jQuery.fn.insertAtCaret = function (myValue) { return this.each(function(){ //IE support if (document.selection) { this.focus(); sel = document.selection.createRange(); sel.text = myValue; this.focus(); } //MOZILLA/NETSCAPE support else if (this.selectionStart || this.selectionStart == '0') { var startPos = this.selectionStart; var endPos = this.selectionEnd; var scrollTop = this.scrollTop; this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length); this.focus(); this.selectionStart = startPos + myValue.length; this.selectionEnd = startPos + myValue.length; this.scrollTop = scrollTop; } else { this.value += myValue; this.focus(); } }); }; function filterHtml(source) { HTMLReg.disablePositioning = true; HTMLReg.validateHTML = false; return HTMLReg.parse(source); } function destroyCkeditor(id) { if (window.configDisable_rte) return; CKEDITOR.instances[id].destroy(); } function initCkeditor(textareaId, options) { if (window.configDisable_rte) return; var placeholderToolbar = null; options = options || {}; if (options.placeholder_items) { placeholderToolbar = { name: 'amember', items: ['CreatePlaceholder'] }; } var toolbar_Am = []; toolbar_Am.push({ name: 'basicstyles', items : ['Bold','Italic','Strike','-','RemoveFormat'] }); if (placeholderToolbar) toolbar_Am.push(placeholderToolbar); toolbar_Am.push({ name: 'paragraph', items : ['NumberedList','BulletedList','-','Outdent','Indent','-','Blockquote','CreateDiv','-','JustifyLeft','JustifyCenter','JustifyRight'] }); toolbar_Am.push({ name: 'insert', items : [ 'Link','Unlink','Image','MediaEmbed','Table','HorizontalRule','PageBreak' ] }); toolbar_Am.push({ name: 'tools', items : [ 'Maximize', 'Source', 'Templates', 'SpellChecker' ] }); toolbar_Am.push({ name: 'clipboard', items : [ 'Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo' ] }); toolbar_Am.push('/'); toolbar_Am.push({ name: 'styles', items : [ 'Styles','Format','Font','FontSize','TextColor','BGColor' ] }); var defaultOptions = { extraPlugins : 'placeholder', autoGrow_maxHeight: 800, baseHref: amUrl(''), customConfig : false, language: window.lang, toolbar: "Am", toolbar_Am : toolbar_Am, allowedContent: true, autoParagraph: false, fullPage: true, fillEmptyBlocks: false, on : { beforeSetMode : function (evt) { evt.editor.config.fullPage = /", { text: "Lifetime", click: function() { jQuery(input).datepicker('setDate', new Date(2037, 11, 31, 1, 0, 0)); //11 is Dec in javascript [0-11] } }).appendTo( buttonPane ).addClass("ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all"); }, 1 ); }, onChangeMonthYear: function( year, month, instance ) { setTimeout(function() { var buttonPane = jQuery( instance ) .datepicker( "widget" ) .find( ".ui-datepicker-buttonpane" ); jQuery( "
      PK\N/ZU**default/views/admin/index.phtmlnu[layoutNoTitle = true; $this->setLayout('admin/layout.phtml'); ?> config->get('dont_check_updates') && Am_Di::getInstance()->authAdmin->getUser()->isSuper()): ?> config->get('dont_check_updates') && Am_Di::getInstance()->authAdmin->getUser()->isSuper() ?>
      blocks('admin/dashboard/top') ?>
      $widget) : ?>
      PK\'KK$default/views/admin/build-demo.phtmlnu[_script('admin/form.phtml'); ?> PK\J<<%default/views/admin/user-layout.phtmlnu[request; $user_id = $request->getInt('user_id', $request->getInt('_u_id')); $user = $user_id ? Am_Di::getInstance()->userTable->load($user_id, false) : null; $this->layoutNoTitle = true; $this->setLayout('admin/layout.phtml'); ?> _script('admin/_error.phtml'); ?> adminTabs($this->di->navigationUserTabs); ?> _script('admin/_user_info.phtml');?> _script('js.country_state.js'); ?> PK\Py&default/views/admin/_user-search.phtmlnu[ PK\^  $default/views/admin/_user_info.phtmlnu[db->selectCell("SELECT ROUND(SUM(amount/base_currency_multi),2) " . "FROM ?_invoice_payment " . "WHERE user_id=?", $user->pk()); $totalRefund = $di->db->selectCell("SELECT ROUND(SUM(amount/base_currency_multi),2) " . "FROM ?_invoice_refund " . "WHERE user_id=?", $user->pk()); ?>
      authAdmin->getUser()->hasPermission('grid_u', 'delete')) : ?>
      %d · %s: %s%s · %s%s: %s · %s: %s%s', ___('ID'), $user->pk(), ___('Username'), $user->login, $di->authAdmin->getUser()->hasPermission('grid_u', 'login-as') ? sprintf(' %s', $this->url('admin-users/login-as', array('id' => $user->pk())), ___('Login as User')) : '', ($user->name_f || $user->name_l) ? sprintf('%s: %s · ', ___('Name'), trim(Am_Html::escape($user->name_f." ".$user->name_l))) : '', ___('Email'), $this->url('admin-email', array('search-type'=>'advanced', 'search'=>json_encode(array('member_id_filter'=>array('val'=>$user->pk()))))), Am_Html::escape($user->email), ___('Total Paid'), Am_Currency::render($totalPaid), ($totalRefund > 0 ? sprintf(' · %s: %s', ___('Refunds'), Am_Currency::render($totalRefund)) : '') ); ?>
      PK\Gvvdefault/views/admin/login.phtmlnu[setLayout('admin/layout-login.phtml'); ?> PK\*Ŝ default/views/admin/_error.phtmlnu[
      PK\Y j default/views/admin/backup.phtmlnu[setLayout('admin/layout.phtml'); ?>
      • You are using your own encryption key, make sure you backup file amember/application/configs/key.php with your database! Please download this file source via FTP (it is impossible to download it using your browser), print it, make 3 copies and put it to safe places. Without contents of this file, it will be ABSOLUTELY IMPOSSIBLE to restore encrypted information from database.

      PK\K default/views/_lang-choice.phtmlnu[config->get('lang.display_choice')): $avail = $di->languagesListUser; $list = array(); if ($enabled = $di->config->get('lang.enabled', array())) foreach ($enabled as $lang) if (!empty($avail[$lang])) $_list[ $lang ] = $avail[$lang]; if ($_list): $_locale = key(Zend_Locale::getDefault()); if (!array_key_exists($_locale, $_list)) list($_locale) = explode('_', $_locale); ?>
      : null))); ?>
      PK\e㟴%default/views/_media.flowplayer.phtmlnu[id); $mediaId = filterId($this->id); $divId = "div-".$scriptId; $rootUrl = $isSecure ? ROOT_SURL : ROOT_URL; $flowPlayerJs = $rootUrl . "/application/default/views/public/js/flowplayer/flowplayer.js"; $flowPlayerIpadJs = $rootUrl . "/application/default/views/public/js/flowplayer/flowplayer.ipad.js"; $flowPlayerSwf = $rootUrl . "/application/default/views/public/js/flowplayer/flowplayer.swf"; ?> jQuery(document).ready(function($) { if (!window.hasOwnProperty('amMediaLoader')) { window.amMediaLoader = true; window.amMediaLoaderLoaded = false; var runAllMedia = function() { window.amMediaLoaderLoaded = true; for (var r in window.amMediaQueue) { if (window.amMediaQueue.hasOwnProperty(r)) { window.amMediaQueue[r](); } } } // if !flowplayer loaded, load it in async mode if (typeof flowplayer == 'function') { runAllMedia(); } else { jQuery.getScript('', function(){ jQuery.getScript('', runAllMedia) }); } } var runMedia = function() { var video_support = !!(document.createElement('video').canPlayType); var video = document.createElement('video'); var idevice = /ip(hone|ad|od)/i.test(navigator.userAgent); var noflash = flashembed.getVersion()[0] === 0; var simulate = !idevice && noflash && video_support && !!(video.canPlayType('').replace(/no/, '')); var $a = jQuery('poster) { echo '
      '; } ?>
      '); $a.attr("href",""); $a.css({ width : '100%', 'max-width' : 'px', 'height' : 'px', display: 'inline-block' }); jQuery("script#").after($a); jQuery(window).resize(function(){ $a.css({ height: Math.max(30, parseInt($a.innerWidth()*/)) + 'px' }); }).resize(); $a.wrap('
      ') flowplayer('', {src: '', wmode: 'opaque'}, ).ipad({validExtensions : null, simulateiDevice : simulate}); } if (window.amMediaLoaderLoaded) { runMedia(); } else { if (!window.hasOwnProperty('amMediaQueue')) { window.amMediaQueue = {}; } window.amMediaQueue.runMedia = runMedia; } }); jQuery(document).ready(function($) { var $a = jQuery(''); $a.attr("href",'' + '?_amember_redirect_url=' + btoa(window.location.href)); $a.text(''); jQuery("script#").after($a); }); PK\My default/views/_login.phtmlnu[_script('_error.phtml'); ?>
      style="display:block;">
      PK\ cdefault/views/changepass.phtmlnu[setLayout('layout.phtml'); $this->headScript() ->appendFile($this->_scriptJs('jquery/jquery.validate.js')); include $this->_script('_form.phtml');PK\L;__#default/views/member/category.phtmlnu[title; $this->setLayout('member/layout.phtml'); ?> description) : ?>

      description) ?>

      resources as $r) : ?>
      _script('resource/_' . $r->getAccessType() . '.phtml') ?>
      PK\ -;  !default/views/member/layout.phtmlnu[setLayout('layout.phtml'); $this->headScript() ->prependFile($this->_scriptJs('jquery/jquery.validate.js')); ?> blocks('member/under-menu') ?> blocks('member/under-contents') ?>PK\aS#*default/views/member/payment-history.phtmlnu[layoutNoTitle = true; $this->setLayout('member/layout.phtml'); ?> headScript()->appendFile($this->_scriptJs('user.js')); ?> blocks('member/payment-history/top') ?>

      _script('member/_invoice.phtml'); ?>
      blocks('member/payment-history/middle') ?>
      isRefunded(); ?>

      blocks('member/payment-history/before-table') ?>
      dattm)?> config->get('send_pdf_invoice') && $di->config->get('pdf_invoice_link')): ?> getDisplayInvoiceId()); ?> getDisplayInvoiceId()); ?> getInvoice()->getItems(); echo implode(', ', array_map(function($i) {return $i->item_title;}, $items)); ?> _paysysName) ?> getCurrency($p->amount)) ?> isRefunded()) : ?> getCurrency($p->refund_amount)); ?>, refund_dattm)); ?>
      blocks('member/payment-history/bottom') ?>PK\ƙȱ default/views/member/_menu.phtmlnu[
      setView($this); echo $m->renderMenu($this->di->navigationUser, array( 'ulClass' => 'am-tabs', 'activeClass' => 'active', 'normalClass' => 'normal', 'disabledClass' => 'disabled', 'maxDepth' => 1, ) ); ?>
      PK\[g"default/views/member/_cancel.phtmlnu[

      PK\EX'default/views/member/_menu-narrow.phtmlnu[
      setView($this); echo $m->renderMenu($this->di->navigationUser, array( 'ulClass' => 'am-tabs-narrow am-tabs-narrow-stuff', 'activeClass' => 'active', 'normalClass' => 'normal', 'disabledClass' => 'disabled', 'maxDepth' => 1, ) ); ?>
      PK\wI #default/views/member/_upgrade.phtmlnu[
      _upgrades as $upgrade): $id = rand(10,999999); ?>
      config->get('allow_coupon_upgrades')): ?>


      PK\/#default/views/member/_invoice.phtmlnu[
      tm_started)) ?> #public_id) ?> _paysysName) ?>, getTerms()) ?> rebill_date): ?> : rebill_date)) ?> _cancelUrl)): ?> isCancelled()): ?> (tm_cancelled)) ?>) isFailed()): ?> _restoreUrl)) : ?>
        getItems() as $item): ?>
      • item_title) ?> _upgrades)): ?> getOptions() as $optKey => $opt): ?>
        : 0 ? '+' : '−' ?> first_price = abs($opt['first_price']); $o->second_price = abs($opt['second_price']); $o->first_period = $invoice->first_period; $o->second_period = $invoice->second_period; $o->rebill_times = $invoice->rebill_times; $o->currency = $invoice->currency; $t = new Am_TermsText($o); echo $t->getStringForOption(); ?> getOptions() ?>
      PK\??default/views/member/main.phtmlnu[blocks('member/main/**'); $title = ___('Your Membership Information'); $this->setLayout('member/layout.phtml'); ?> blocks('member/main/top') ?>
      blocks('member/main/left/top') ?> blocks('member/main/left', '

      %2$s

      %1$s
      '); ?> blocks('member/main/left/bottom') ?>
      blocks('member/main/right/top') ?> blocks('member/main/right', '

      %2$s

      %1$s
      '); ?> blocks('member/main/right/bottom') ?>
      blocks('member/main/bottom') ?>PK\l "default/views/member/profile.phtmlnu[setLayout('member/layout.phtml'); ?> blocks('member/profile/top') ?> _script('_error.phtml'); ?> _script('js.country_state.js'); ?> blocks('member/profile/bottom') ?>PK\default/views/_popup.phtmlnu[PK\!default/views/unsubscribe.phtmlnu[setLayout('layout.phtml'); ?> _script('_error.phtml'); ?>
      : email) ?>
      blocks('unsubscribe/before')?> blocks('unsubscribe', '

      %2$s

      %1$s
      '); ?>PK\  default/views/_login-form.phtmlnu[
      id="am-login-form">
      PK\y@)default/views/_thanks-login-details.phtmlnu[ PK\a*default/views/blocks/unsubscribe-std.phtmlnu[ di->config->get('site_title')); ?>
      PK\Y ! ! 4default/views/blocks/member-main-subscriptions.phtmlnu[
      • getTitle(); ?> - pk()]) : ?> pk()]); ?> pk()] == Am_Period::MAX_SQL_DATE): ?> pk()]); ?> pk()]) && $products_cancel[$p->pk()]) : ?> pk()]) && $products_upgrade[$p->pk()]): ?>
      • getTitle(); ?> - pk()]); ?>

      url('signup') . '">','') ?>

      invoiceTable->load($item->invoice_id); ?> PK\N%-.default/views/blocks/member-identity-std.phtmlnu[
      user->login) ?>
      PK\U2default/views/blocks/member-main-unsubscribe.phtmlnu[user ? $this->user : Am_Di::getInstance()->user; $checked = $u->unsubscribed ? 'checked="checked"' : ''; ?> PK\,default/views/blocks/member-main-links.phtmlnu[ PK\%$0default/views/blocks/member-main-resources.phtmlnu[
        renderLink()) : ?>
      • desc) : ?>
        desc); ?>
      • $t): ?>
      PK\nLL default/views/layout-login.phtmlnu[_script('layout.phtml');PK\pb b !default/views/js.country_state.jsnu[ PK\%default/views/index.phtmlnu[config->get('site_title', 'Index Page'); $this->setLayout('layout.phtml'); ?> url('login') . '">','') ?>. config->get('signup_disable')) : ?> url('signup') .'">','') ?>. PK\mƜdefault/views/login.phtmlnu[layoutNoTitle = true; $title = ___('Please login'); $this->setLayout('layout-login.phtml');?> config->get('signup_disable')) : ?> PK\zdefault/views/_error.phtmlnu[formErrors((array)$error); elseif (!empty($errors)) echo $this->formErrors((array)$errors);PK\_default/views/cancel.phtmlnu[headMeta()->setName('robots', 'noindex,nofollow'); ?> setLayout('layout.phtml'); ?> _script('_error.phtml'); ?>

      PK\` default/views/thanks.phtmlnu[headMeta()->setName('robots', 'noindex,nofollow'); $this->placeholder("head-start")->prepend(sprintf('', Am_Html::escape($_SERVER['HTTP_HOST']))) ?> setLayout('layout.phtml'); ?> tm_started): ?> isConfirmed()): ?> config->get('manually_approve_note', <<IMPORTANT NOTE: We review all new payments manually, so your payment is under review currently.
      You will get email notification after payment will be approved by admin. We are sorry for possible inconvenience. CUT )) ?>
      blocks('thanks/notstarted'); ?> blocks('thanks/unknown'); ?> tm_started): ?> first_total > 0): ?>
      {$this->escape($payment->getDisplayInvoiceId())}") ?>
      {$this->escape($payment->receipt_id)}") ?>
      ' . amDatetime($payment->dattm) . '') ?>
      _script('_receipt.phtml'); ?> blocks('thanks/success'); ?> tm_started ?>PK\TJdefault/views/_logo.phtmlnu[getConfig('logo_link')) : ?> >$default/views/_invoice-summary.phtmlnu[getItems())) : ?>
      getItems(); $cnt = count($items); $index=1; $colspan = 1; $showQty = false; $n = 0; foreach ($items as $item) {if ($item->qty>1) {$showQty = true; $colspan=2; break;}} ?> first_discount > 0 || $invoice->first_shipping > 0 || $invoice->first_tax) : ?> first_discount > 0) :?> first_shipping > 0): ?> first_tax > 0) : ?>
      . item_title) ?> getOptions() as $optKey => $opt): ?>
      : 0 ? '+' : '−' ?> first_price = abs($opt['first_price']); $o->second_price = abs($opt['second_price']); $o->first_period = $invoice->first_period; $o->second_period = $invoice->second_period; $o->rebill_times = $invoice->rebill_times; $o->currency = $invoice->currency; $t = new Am_TermsText($o); echo $t->getStringForOption(); ?> getOptions() ?>
      ×qty) ?> getCurrency($item->first_price)) ?>

      getCurrency($invoice->first_subtotal)?>
      getCurrency($invoice->first_discount)?>
      getCurrency($invoice->first_shipping)?>
      (tax_rate) ?>%) getCurrency($invoice->first_tax)?>
      getCurrency($invoice->first_total)?>
      PK\ #default/views/_media.jwplayer.phtmlnu[id); $mediaId = filterId($this->id); $divId = "div-".$scriptId; $rootUrl = $isSecure ? ROOT_SURL : ROOT_URL; $jwPlayerJs = $rootUrl . "/application/default/views/public/js/jwplayer/jwplayer.js"; $playerParams['width'] = $width; $playerParams['height'] = $height; $playerParams['file'] = $media; $playerParams['image'] = $this->poster; $playerParams['flashplayer'] = $rootUrl . "/application/default/views/public/js/jwplayer/jwplayer.flash.swf"; $playerParams['html5player'] = $rootUrl . "/application/default/views/public/js/jwplayer/jwplayer.html5.js"; $types = array( 'video/mp4' =>'mp4', 'video/flv' =>'flv', 'video/webm' =>'webm', 'audio/mp4' => 'aac', 'audio/mpeg' => 'mp3', 'audio/ogg' => 'vorbis' ); $playerParams['type'] = @$types[$mime]; ?> jQuery(document).ready(function($) { if (!window.hasOwnProperty('amMediaLoader')) { window.amMediaLoader = true; window.amMediaLoaderLoaded = false; var runAllMedia = function() { window.amMediaLoaderLoaded = true; for (var r in window.amMediaQueue) { if (window.amMediaQueue.hasOwnProperty(r)) { window.amMediaQueue[r](); } } } // if !jwplayer loaded, load it in async mode if (typeof jwplayer == 'function') { runAllMedia(); } else { jQuery.getScript('', function(){ jwplayer.key = ''; runAllMedia(); }); } } var runMedia = function() { var $a = jQuery('poster) { echo '
      '; } ?>
      '); $a.attr("href",""); $a.css({ width : '100%', 'max-width' : 'px', 'height' : 'px', display: 'inline-block' }); jQuery("script#").after($a); jQuery(window).resize(function(){ $a.css({ height: parseInt($a.innerWidth()*/) + 'px' }); }).resize(); $a.wrap('
      ') jwplayer('').setup(); jQuery('#'+'').css({display: 'inline-block'}); } if (window.amMediaLoaderLoaded) { runMedia(); } else { if (!window.hasOwnProperty('amMediaQueue')) { window.amMediaQueue = {}; } window.amMediaQueue.runMedia = runMedia; } }); jQuery(document).ready(function($) { var $a = jQuery(''); $a.attr("href",'' + '?_amember_redirect_url=' + btoa(window.location.href)); $a.text(''); jQuery("script#").after($a); }); PK\=188default/views/no-access.phtmlnu[setLayout('layout.phtml');} ?>

      $accessObjectTitle") ?>. escape($orderUrl).'">', ''); ?>.

      PK\ HMM cc/db.xmlnu[
      PK\H3eJJcc/library/CcRebill.phpnu[ 'Started', self::NO_CC => 'No Credit Card saved', self::ERROR => 'Error', self::SUCCESS => 'OK', self::EXCEPTION => 'Exception!', ); return $arr[$status]; } function setStatus($status, $message) { $this->updateQuick(array( 'status' => (int)$status, 'status_msg' => $message, 'status_tm' => $this->getDi()->sqlDateTime, )); return $this; } } class CcRebillTable extends Am_Table { protected $_table = '?_cc_rebill'; protected $_key = 'cc_rebill_id'; public function insert(array $values, $returnInserted = false) { if (empty($values['tm_added'])) $values['tm_added'] = $this->getDi()->sqlDateTime; return parent::insert($values, $returnInserted); } }PK\  cc/library/EcheckRecord.phpnu[maskBan($arr['echeck_ban']); } $arr['echeck_aba'] = preg_replace('/\D+/', '', $arr['echeck_aba']); foreach ($this->_encryptedFields as $f) if (array_key_exists($f, $arr)) $arr[$f] = $this->_table->encrypt($arr[$f]); return $arr; } public function fromRow(array $arr) { // fields to decrypt foreach ($this->_encryptedFields as $f) if (array_key_exists($f, $arr)) $arr[$f] = $this->_table->decrypt($arr[$f]); return parent::fromRow($arr); } /** * Delete existing record for this user_id, then insert this one * @return EcRecord provides fluent interface */ function replace() { if (empty($this->user_id) || $this->user_id <= 0) throw new Am_Exception_InternalError("this->user_id is empty in " . __METHOD__); $this->_table->deleteByUserId($this->user_id); return $this->insert(); } } class EcheckRecordTable extends Am_Table { protected $_crypt; protected $_key = 'echeck_id'; protected $_table = '?_echeck'; protected $_recordClass = 'EcheckRecord'; function encrypt($s){ return $this->_getCrypt()->encrypt($s); } function decrypt($s){ return $this->_getCrypt()->decrypt($s); } function _getCrypt(){ if (empty($this->_crypt)) $this->_crypt = Am_Di::getInstance ()->crypt; return $this->_crypt; } function setCrypt(Am_Crypt $crypt) { $this->_crypt = $crypt; } } PK\߽O;;cc/library/Am/Paysystem/Nmi.phpnu[addText('user') ->setLabel("Your username\n" . 'Username assigned to merchant account') ->addRule('required'); $form->addPassword('pass') ->setLabel("Your password\n" . 'Password for the specified username') ->addRule('required'); $form->addAdvCheckbox('testMode') ->setLabel("Test Mode\n" . 'Test account data will be used'); } public function isConfigured() { return $this->getConfig('user') && $this->getConfig('pass'); } public function loadCreditCard(Invoice $invoice) { if($cc = parent::loadCreditCard($invoice)) return $cc; return $this->getDi()->CcRecordTable->createRecord(); // return fake record for rebill } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $user = $invoice->getUser(); if ($doFirst) // not recurring sale { if (!(float)$invoice->first_total) // first - free { $trAuth = new Am_Paysystem_Networkmerchants_Transaction_Authorization($this, $invoice, $cc); $trAuth->run($result); $transactionId = $trAuth->getUniqId(); $customerVaultId = $trAuth->getCustomerVaultId(); if (!$transactionId || !$customerVaultId) { return $result->setFailed(array("NMI Plugin: Bad auth response.")); } $trVoid = new Am_Paysystem_Networkmerchants_Transaction_Void($this, $invoice, $transactionId, $customerVaultId); $trVoid->run($result); $trFree = new Am_Paysystem_Transaction_Free($this); $trFree->setInvoice($invoice); $trFree->process(); $result->setSuccess($trFree); } else { $trAuth = new Am_Paysystem_Networkmerchants_Transaction_Authorization($this, $invoice, $cc, $invoice->first_total); $trAuth->run($result); $transactionId = $trAuth->getUniqId(); $customerVaultId = $trAuth->getCustomerVaultId(); if (!$transactionId || !$customerVaultId) { return $result->setFailed(array("NMI Plugin: Bad auth response.")); } $trSale = new Am_Paysystem_Networkmerchants_Transaction_Capture($this, $invoice, $doFirst, $transactionId); $trSale->run($result); } $user->data()->set($this->getCustomerVaultVariable(), $customerVaultId)->update(); } else { $customerVaultId = $user->data()->get($this->getCustomerVaultVariable()); if (!$customerVaultId) { return $result->setFailed(array("No saved reference transaction for customer")); } $trSale = new Am_Paysystem_Networkmerchants_Transaction_Sale($this, $invoice, $doFirst, $customerVaultId); $trSale->run($result); } } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $user = $this->getDi()->userTable->load($cc->user_id); $customerVaultId = $user->data()->get($this->getCustomerVaultVariable()); if ($this->invoice) { // to link log records with current invoice $invoice = $this->invoice; } else { // updating credit card info? $invoice = $this->getDi()->invoiceRecord; $invoice->invoice_id = 0; $invoice->user_id = $user->pk(); } // compare stored cc for that user may be we don't need to refresh? if ($customerVaultId && ($cc->cc_number != '0000000000000000')) { $storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk()); if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)) || ($storedCc->cc_expire != $cc->cc_expire))) { $user->data()->set($this->getCustomerVaultVariable(), null)->update(); $customerVaultId = null; } } if (!$customerVaultId) { $trAdd = new Am_Paysystem_Networkmerchants_Transaction_AddCustomer ($this, $invoice, $cc); $trAdd->run($result); $customerVaultId = $trAdd->getCustomerVaultId(); if (!$customerVaultId) { return $result->setFailed(array("PSWW Plugin: Bad add response.")); } $user->data()->set($this->getCustomerVaultVariable(), $customerVaultId)->update(); } /// $cc->cc = $cc->maskCc(@$cc->cc_number); $cc->cc_number = '0000000000000000'; if ($cc->pk()) $cc->update(); else $cc->replace(); $result->setSuccess(); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $customerVaultId = $this->getDi()->userTable->load($payment->user_id)->data()->get($this->getCustomerVaultVariable()); $tr = new Am_Paysystem_Networkmerchants_Transaction_Refund($this, $payment->getInvoice(), $payment->receipt_id, $amount, $customerVaultId); $tr->run($result); } } PK\#+qUqU"cc/library/Am/Paysystem/Echeck.phpnu[getPluginUrl(self::ACTION_ECHECK) ); $action->id = $invoice->getSecureId($this->getId()); $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs){} public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch ($request->getActionName()) { case self::ACTION_IPN: return parent::directAction($request, $response, $invokeArgs); case self::ACTION_UPDATE: return $this->updateAction($request, $response, $invokeArgs); case self::ACTION_CANCEL: return $this->doCancelAction($request, $response, $invokeArgs); case self::ACTION_ECHECK: default: return $this->echeckAction($request, $response, $invokeArgs); } } protected function echeckActionValidateSetInvoice(Am_Mvc_Request $request, array $invokeArgs) { $invoiceId = $request->getFiltered('id'); if (!$invoiceId) throw new Am_Exception_InputError("invoice_id is empty - seems you have followed wrong url, please return back to continue"); $invoice = $this->getDi()->invoiceTable->findBySecureId($invoiceId, $this->getId()); if (!$invoice) throw new Am_Exception_InputError('You have used wrong link for payment page, please return back and try again'); if ($invoice->isCompleted()) throw new Am_Exception_InputError(sprintf(___('Payment is already processed, please go to %sMembership page%s'), "","")); if ($invoice->paysys_id != $this->getId()) throw new Am_Exception_InputError("You have used wrong link for payment page, please return back and try again"); if ($invoice->tm_added < sqlTime('-30 days')) throw new Am_Exception_InputError("Invoice expired - you cannot open invoice after 30 days elapsed"); $this->invoice = $invoice; // set for reference } /** * Show echeck info input page, validate it if submitted */ public function echeckAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->echeckActionValidateSetInvoice($request, $invokeArgs); $p = $this->createController($request, $response, $invokeArgs); $p->setPlugin($this); $p->setInvoice($this->invoice); $p->run(); } /** * Process echeck update request * @param Am_Mvc_Request $request * @param Am_Mvc_Response $response * @param array $invokeArgs */ public function updateAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->getDi()->auth->requireLogin($this->getDi()->url('member',null,false)); $p = $this->createController($request, $response, $invokeArgs); $p->setPlugin($this); $p->run(); } /** * Process "cancel recurring" request * @param Am_Mvc_Request $request * @param Am_Mvc_Response $response * @param array $invokeArgs */ public function doCancelAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $id = $request->getFiltered('id'); $invoice = $this->getDi()->invoiceTable->findBySecureId($id, 'STOP' . $this->getId()); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); if ($invoice->user_id != $this->getDi()->auth->getUserId()) throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]"); if (method_exists($this, 'cancelInvoice')) $this->cancelInvoice($invoice); $invoice->setCancelled(); $response->setRedirect($this->getDi()->url('member/payment-history',null,false)); } /** * To be overriden in children classes * @param Am_Mvc_Request $request * @param Am_Mvc_Response $response * @param array $invokeArgs * @return Am_Mvc_Controller_Echeck */ protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_Echeck($request, $response, $invokeArgs); } /** * Method must return array of self::ECHECK_xxx constants to control which * additional fields will be displayed in the form * @return array */ public function getFormOptions() { $ret = array(self::ECHECK_ADDRESS, self::ECHECK_COUNTRY, self::ECHECK_STATE, self::ECHECK_CITY, self::ECHECK_STREET, self::ECHECK_ZIP); return $ret; } /** * You can do form customization necessary for the plugin * here */ public function onFormInit(Am_Form_Echeck $form) { } /** * You can do custom form validation here. If errors found, * call $form->getElementById('xx-0')->setError('xxx') and * return false * @return bool */ public function onFormValidate(Am_Form_Echeck $form) { return true; } public function doBill(Invoice $invoice, $doFirst, EcheckRecord $echeck = null) { $this->invoice = $invoice; $this->echeck = $echeck; $result = new Am_Paysystem_Result(); $this->_doBill($invoice, $doFirst, $echeck, $result); return $result; } abstract public function _doBill(Invoice $invoice, $doFirst, EcheckRecord $echeck, Am_Paysystem_Result $result); /** * Function can be overrided to change behaviour */ public function storeEcheck(EcheckRecord $echeck, Am_Paysystem_Result $result) { if ($this->storesCcInfo()) { $echeck->replace(); $result->setSuccess(); } return $this; } /** * Method defined for overriding in child classes where EC info is not stored locally * @return EcRecord * @param Invoice $invoice * @throws Am_Exception */ public function loadEcheck(Invoice $invoice) { if ($this->storesCcInfo()) return $this->getDi()->echeckRecordTable->findFirstByUserId($invoice->user_id); } public function prorateInvoice(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date) { /** @todo use "reattempt" config **/ $reattempt = array_filter($this->getConfig('reattempt', array())); sort($reattempt); if (!$reattempt) { $invoice->setStatus(Invoice::RECURRING_FAILED); $invoice->updateQuick('rebill_date', null); return; } $first_failure = $invoice->data()->get(self::FIRST_REBILL_FAILURE); if (!$first_failure) { $invoice->data()->set(self::FIRST_REBILL_FAILURE, $date)->update(); $first_failure = $date; } $days_diff = (strtotime($date) - strtotime($first_failure)) / (24*3600); foreach ($reattempt as $day) if ($day > $days_diff) break; // we have found next rebill date to jump if ($day <= $days_diff){ // Several rebilling attempts failed already. // change status to RECURRING_FAILED; $invoice->setStatus(Invoice::RECURRING_FAILED); $invoice->updateQuick('rebill_date', null); return; } $invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($first_failure." +$day days"))); $tr = new Am_Paysystem_Transaction_Manual($this); if ($invoice->getAccessExpire() < $invoice->rebill_date) $invoice->extendAccessPeriod($invoice->rebill_date); } public function onRebillFailure(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date) { $this->prorateInvoice($invoice, $echeck, $result, $date); if($this->getDi()->config->get('cc.rebill_failed')) $this->sendRebillFailedToUser($invoice, $result->getLastError(), $invoice->rebill_date); } function sendRebillFailedToUser(Invoice $invoice, $failedReason, $nextRebill) { try { if($et = Am_Mail_Template::load('cc.rebill_failed')) { $et->setError($failedReason); $et->setUser($invoice->getUser()); $et->setInvoice($invoice); $et->setProrate( ($nextRebill > $this->getDi()->sqlDate) ? sprintf(___('Our system will try to charge your card again on %s'), amDate($nextRebill)) : "" ); $et->setMailPeriodic(Am_Mail::USER_REQUESTED); $et->send($invoice->getUser()); } }catch(Exception $e) { // No mail exceptions when rebilling; $this->getDi()->errorLogTable->logException($e); } } function sendRebillSuccessToUser(Invoice $invoice) { try { if($et = Am_Mail_Template::load('cc.rebill_success')) { $et->setUser($invoice->getUser()); $et->setInvoice($invoice); $et->setAmount($invoice->second_total); $et->setRebill_date($invoice->rebill_date ? amDate($invoice->rebill_date) : ___('NEVER')); $et->setMailPeriodic(Am_Mail::USER_REQUESTED); $et->send($invoice->getUser()); } } catch(Exception $e) { // No mail exceptions when rebilling; $this->getDi()->errorLogTable->logException($e); } } public function onRebillSuccess(Invoice $invoice, EcheckRecord $echeck, Am_Paysystem_Result $result, $date) { if ($invoice->data()->get(self::FIRST_REBILL_FAILURE)) { $invoice->addToRebillDate(false, $invoice->data()->get(self::FIRST_REBILL_FAILURE)); $invoice->data()->set(self::FIRST_REBILL_FAILURE, null)->update(); } if($this->getDi()->config->get('cc.rebill_success')) $this->sendRebillSuccessToUser($invoice); } // called from Bootstrap_Cc public function ccRebill($date = null) { /** * If plugin can't rebill payments itself, leave it alone. */ if($this->getRecurringType() != self::REPORTS_CRONREBILL) return; $rebillTable = $this->getDi()->ccRebillTable; $processedCount = 0; foreach ($this->getDi()->invoiceTable->findForRebill($date, $this->getId()) as $invoice) { // Invoice must have status RECURRING_ACTIVE in order to be rebilled; if($invoice->status != Invoice::RECURRING_ACTIVE) continue; // If we already have all payments for this invoice unset rebill_date and update invoice status; if($invoice->getPaymentsCount() >= $invoice->getExpectedPaymentsCount()) { $invoice->recalculateRebillDate(); $invoice->updateStatus(); continue; } /* @var $invoice Invoice */ try { $rebill = $rebillTable->createRecord(array( 'paysys_id' => $this->getId(), 'invoice_id' => $invoice->invoice_id, 'rebill_date' => $date, 'status' => CcRebill::STARTED, 'status_msg' => "Not Processed", )); //only one attempt to rebill per day try { $rebill->insert(); } catch (Am_Exception_Db_NotUnique $e) { continue; } $echeck = $this->getDi()->echeckRecordTable->createRecord(); if ($this->storesCcInfo()) { $echeck = $this->loadEcheck($invoice); if (!$echeck) { $rebill->setStatus(CcRebill::NO_CC, "No credit card/echeck saved, cannot rebill"); continue; } } $result = $this->doBill($invoice, false, $echeck); if (!$result->isSuccess()) $this->onRebillFailure($invoice, $echeck, $result, $date); else $this->onRebillSuccess($invoice, $echeck, $result, $date); $rebill->setStatus($result->isSuccess() ? CcRebill::SUCCESS : CcRebill::ERROR, current($result->getErrorMessages())); $processedCount++; } catch (Exception $e) { if (stripos(get_class($e), 'PHPUnit_')===0) throw $e; $rebill->setStatus(CcRebill::EXCEPTION, "Exception " . get_class($e) . " : " . $e->getMessage()); // if there was an exception in billing (say internal error), // we set rebill_date to tomorrow $invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($invoice->rebill_date . ' +1 day'))); $this->getDi()->errorLogTable->logException($e); $this->logError("Exception on rebilling", $e, $invoice); unset($this->invoice); } } // Send message only if rebill executed by cron; if($this->getDi()->config->get('cc.admin_rebill_stats') && (is_null($date) || $date == $this->getDi()->sqlDate) && $processedCount) $this->sendStatisticsEmail(); } protected function getStatisticsRow(Array $r) { if($r['status']!= CcRebill::SUCCESS) { $failed = "Reason: ".$r['status_msg']; if($r['rebill_date']>$this->getDi()->sqlDate) $failed .= "\t Next Rebill Date: ".$r['rebill_date']; }else $failed = ''; $row = sprintf("%s, %s, %s %s, \nInvoice: %s\tAmount: %s\t%s\n%s\n\n", $r['email'], $r['login'], $r['name_f'], $r['name_l'], $r['public_id'], $r['second_total'], $failed, $this->getDi()->url(array('admin-user-payments/index/user_id/%s#invoice-%s', $r['user_id'], $r['invoice_id'])) ); return $row; } protected function sendStatisticsEmail() { $date = $this->getDi()->sqlDate; $success = $failed = ""; $success_count = $failed_count = $success_amount = $failed_amount = 0; if ($et = Am_Mail_Template::load('cc.admin_rebill_stats')) { foreach($this->getDi()->db->selectPage($total, " SELECT r.*, i.second_total, i.user_id, i.invoice_id, i.public_id, i.rebill_date, u.name_f, u.name_l, u.email, u.login FROM ?_cc_rebill r LEFT JOIN ?_invoice i USING(invoice_id) LEFT JOIN ?_user u ON(i.user_id = u.user_id) WHERE status_tm>? and status_tm<=? and r.paysys_id=? ", $date, $this->getDi()->sqlDateTime, $this->getId()) as $r) { if($r['status'] == CcRebill::SUCCESS) { $success_count++; $success_amount+=$r['second_total']; $success .= $this->getStatisticsRow($r); }else{ $failed_count++; $failed_amount += $r['second_total']; $failed .= $this->getStatisticsRow($r);; } } if($success || $failed) { $currency = $this->getDi()->config->get('currency'); $et->setShort_stats(sprintf(___('Success: %d (%0.2f %s) Failed: %d (%0.2f %s)'), $success_count, $success_amount, $currency, $failed_count, $failed_amount, $currency)); $et->setRebills_success(!empty($success) ? $success : ___('No items in this section')); $et->setRebills_failed(!empty($failed) ? $failed : ___('No items in this section')); $et->setPlugin($this->getId()); $et->setMailPeriodic(Am_Mail::ADMIN_REQUESTED); $et->sendAdmin(); } } } protected function _afterInitSetupForm(Am_Form_Setup $form) { // insert title, description fields $form->setTitle(ucfirst(toCamelCase($this->getId()))); $el = $form->addMagicSelect('reattempt', array('multiple'=>'multiple')); $options = array(); for ($i=1;$i<60;$i++) $options[$i] = ___("on %d-th day", $i); $el->loadOptions($options); $el->setLabel(___("Retry On Failure\n". "if the recurring billing has failed,\n". "aMember can repeat it after several days,\n". "and extend customer subscription for that period\n". "enter number of days to repeat billing attempt")); if($this->storesCcInfo() && !$this->_pciDssNotRequired) { $text = "

      WARNING! Every application processing e-check information, must be certified\n" . "as PA-DSS compliant, and every website processing credit cards must\n" . "be certified as PCI-DSS compliant.

      "; $text.= "

      aMember Pro is not yet certified as PA-DSS compliant. We will start certification process\n". "once we get 4.2.0 branch released and stable. This plugins is provided solely for TESTING purproses\n". "Use it for anything else but testing at your own risk.

      "; $form->addProlog(<< $text
      CUT ); } $keyFile = defined('AM_KEYFILE') ? AM_KEYFILE : AM_APPLICATION_PATH . '/configs/key.php'; if (!is_readable($keyFile)) { $random = $this->getDi()->security->randomString(78); $text = "

      To use credit card plugins, you need to create a key file that contains unique\n"; $text .= "encryption key for your website. It is necessary even if the plugin does not\n"; $text .= "store sensitive information.

      "; $text .= "

      In a text editor, create file with the following content (one-line, no spaces before opening <?php):\n"; $text .= "

      <?php return '$random';
      \n"; $text .= "
      save the file as key.php, and upload to amember/application/configs/ folder.\n"; $text .= "This warning will disappear once you do it correctly.

      "; $text .= "

      KEEP A BACKUP COPY OF THE key.php FILE (!)

      "; $form->addProlog(<< $text CUT ); } return parent::_afterInitSetupForm($form); } /** * If plugin require special actions to cancel invoice, cancelInvoice will be called * after Invoice will actually be cancelled by CreditCard Controller. * do nothing by default; * @throws Am_Exception_InputError if failure; * @param Invoice $invoice */ function cancelInvoice(Invoice $invoice) { return true; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $invoice->setCancelled(true); } public function getUpdateEcheckLink($user) { if ($this->storesCcInfo() && $this->getDi()->echeckRecordTable->findFirstByUserId($user->user_id)) { return $this->getPluginUrl('update'); } } }PK\Mb-% % .cc/library/Am/Paysystem/Transaction/Echeck.phpnu[setInvoice($invoice); $this->request = $request; $this->doFirst = $doFirst; } public function run(Am_Paysystem_Result $result) { $this->result = $result; $log = $this->getInvoiceLog(); $log->add($this->request); $this->response = $this->request->send(); $log->add($this->response); $this->validateResponseStatus($this->result); if ($this->result->isFailure()) return; try { $this->parseResponse(); // validate function must set success status $this->validate(); if ($this->result->isSuccess()) $this->processValidated(); } catch (Exception $e) { if ($e instanceof PHPUnit_Framework_Error) throw $e; if ($e instanceof PHPUnit_Framework_Asser ) throw $e; if (!$result->isFailure()) $result->setFailed(___("Payment failed")); $log->add($e); } } /** * Must operate $this->result to set error status or call * $result->setSuccess if all ok */ public function validate() { } /** * Parse response and return it, it will be placed to @link $this->vars * @return mixed */ abstract public function parseResponse(); public function validateResponseStatus(Am_Paysystem_Result $result) { if ($this->response->getStatus() != 200) { $result->setFailed(array("Received invalid response from payment server: " . $this->response->getStatus())); } } /** @return InvoiceLog */ function getInvoiceLog() { if (!$this->log) { $this->log = $this->plugin->getDi()->invoiceLogRecord; if ($this->invoice) { $this->log->invoice_id = $this->invoice->invoice_id; $this->log->user_id = $this->invoice->user_id; } $this->log->paysys_id = $this->getPlugin()->getId(); $this->log->remote_addr = $_SERVER['REMOTE_ADDR']; foreach ($this->plugin->getConfig() as $k => $v) if (is_scalar($v) && (strlen($v) > 4)) $this->log->mask($v); } return $this->log; } }PK\/  2cc/library/Am/Paysystem/Transaction/CreditCard.phpnu[setInvoice($invoice); $this->request = $request; $this->doFirst = $doFirst; } public function run(Am_Paysystem_Result $result) { $this->result = $result; $log = $this->getInvoiceLog(); $log->add($this->request); $this->response = $this->request->send(); $log->add($this->response); $this->validateResponseStatus($this->result); if ($this->result->isFailure()) return; try { $this->parseResponse(); // validate function must set success status $this->validate(); if ($this->result->isSuccess()) $this->processValidated(); } catch (Exception $e) { if ($e instanceof PHPUnit_Framework_Error) throw $e; if ($e instanceof PHPUnit_Framework_Asser ) throw $e; if (!$result->isFailure()) $result->setFailed(___("Payment failed")); $log->add($e); } } /** * Must operate $this->result to set error status or call * $result->setSuccess if all ok */ public function validate() { } /** * Parse response and return it, it will be placed to @link $this->vars * @return mixed */ abstract public function parseResponse(); public function validateResponseStatus(Am_Paysystem_Result $result) { //nop, it is not necessary to validate it here. In most cases REST API //can return different status with detailed //error messages instead of our common one } /** @return InvoiceLog */ function getInvoiceLog() { if (!$this->log) { $this->log = $this->plugin->getDi()->invoiceLogRecord; if ($this->invoice) { $this->log->invoice_id = $this->invoice->invoice_id; $this->log->user_id = $this->invoice->user_id; } $this->log->paysys_id = $this->getPlugin()->getId(); $this->log->remote_addr = $_SERVER['REMOTE_ADDR']; foreach ($this->plugin->getConfig() as $k => $v) if (is_scalar($v) && (strlen($v) > 4)) $this->log->mask($v); } return $this->log; } }PK\ޜ8cc/library/Am/Paysystem/Transaction/Maxmind/Minfraud.phpnu[body = $this->response->getBody(); $this->vars = array(); $list = explode(';', $this->body); foreach ($list as $l) { list($key, $value) = explode('=', $l); $this->vars[$key] = $value; } } public function isEmpty() { if (!@array_key_exists('countryMatch', (array) $this->vars)) return false; return empty($this->body); } public function validate() { $this->riskscore = $this->vars['riskScore']; $payment_records_edit_log = array(); if ($this->vars['carderEmail'] == 'Yes') $payment_records_edit_log[] = 'Email is in database of high risk e-mails'; if ($this->vars['countryMatch'] == 'No' && !$this->plugin->getConfig('maxmind_allow_country_not_matched')) $payment_records_edit_log[] = 'Country of IP address not matches billing address country'; if ($this->vars['highRiskCountry'] == 'Yes' && !$this->plugin->getConfig('maxmind_allow_high_risk_country')) $payment_records_edit_log[] = 'IP address or billing address country is in high risk countries list'; if ($this->vars['anonymousProxy'] == 'Yes' && !$this->plugin->getConfig('maxmind_allow_anonymous_proxy')) $payment_records_edit_log[] = 'Anonymous proxy are not allowed'; if ($this->vars['freeMail'] == 'Yes' && !$this->plugin->getConfig('maxmind_allow_free_mail')) $payment_records_edit_log[] = 'E-mail from free e-mail provider are not allowed'; if ($this->vars['queriesRemaining'] > 0 && $this->vars['queriesRemaining'] < 10) Am_Di::getInstance()->errorLogTable->log("MaxMind queriesRemaining: " . $this->vars['queriesRemaining']); $ccfd_warnings = array( 'IP_NOT_FOUND', 'COUNTRY_NOT_FOUND', 'CITY_NOT_FOUND', 'CITY_REQUIRED', 'POSTAL_CODE_REQUIRED', 'POSTAL_CODE_NOT_FOUND' ); $ccfd_fatal_errors = array( 'INVALID_LICENSE_KEY', 'MAX_REQUESTS_PER_LICENSE', 'IP_REQUIRED', 'LICENSE_REQUIRED', 'COUNTRY_REQUIRED', 'MAX_REQUESTS_REACHED' ); if (count($payment_records_edit_log)) $this->riskscore = 99; if ($this->vars['err'] || count($payment_records_edit_log)) { if (in_array($this->vars['err'], $ccfd_warnings)) Am_Di::getInstance()->errorLogTable->log("MaxMind warning: " . $this->vars['err'] . " maxmindID: " . $this->vars['maxmindID']); if (in_array($this->vars['err'], $ccfd_fatal_errors)) { $payment_records_edit_log[] = $this->vars['err']; } if (count($payment_records_edit_log)) { $this->getInvoiceLog()->add($payment_records_edit_log); return $this->result->setFailed(___('Payment failed')); } } if($this->riskscore > $this->getPlugin()->getConfig('maxmind_risk_score')) return $this->result->setFailed(___('Payment failed')); $this->result->setSuccess($this); } public function getRiskScore() { return $this->riskscore; } public function processValidated() { //do nothing } } PK\jDD6cc/library/Am/Paysystem/Transaction/Maxmind/Number.phpnu[body = $this->response->getBody(); $this->vars = array(); $list = explode(';', $this->body); foreach ($list as $l) { list($key, $value) = explode('=', $l); $this->vars[$key] = $value; } } public function isEmpty() { if (!array_key_exists('phoneType', $this->vars)) return false; return empty($this->body); } public function validate() { if ($this->vars['err']) return $this->result->setFailed(___('Payment failed')); if(!in_array($this->vars['phoneType'], $this->getPlugin()->getConfig('maxmind_tni_phone_types'))) return $this->result->setFailed(___('Payment failed')); $this->result->setSuccess($this); } public function processValidated() { //do nothing } } PK\9j5cc/library/Am/Paysystem/Transaction/Maxmind/Phone.phpnu[body = $this->response->getBody(); $this->vars = array(); $list = explode(';', $this->body); foreach ($list as $l) { list($key, $value) = explode('=', $l); $this->vars[$key] = $value; } } public function isEmpty() { if (!array_key_exists('refid', $this->vars)) return false; return empty($this->body); } public function validate() { if ($this->vars['err']) return $this->result->setFailed(___('Payment failed')); $this->result->setSuccess($this); } public function processValidated() { //do nothing } } PK\ V1&cc/library/Am/Paysystem/CreditCard.phpnu[getPluginUrl(self::ACTION_CC) ); $action->id = $invoice->getSecureId($this->getId()); $result->setAction($action); } public function createTransaction(/*Am_Mvc_Request */$request, /*Am_Mvc_Response */$response, array $invokeArgs){} public function directAction(/*Am_Mvc_Request */$request, /*Am_Mvc_Response */$response, $invokeArgs) { switch ($request->getActionName()) { case self::ACTION_IPN: return parent::directAction($request, $response, $invokeArgs); case self::ACTION_UPDATE: return $this->updateAction($request, $response, $invokeArgs); case self::ACTION_CANCEL: return $this->doCancelAction($request, $response, $invokeArgs); case self::ACTION_CANCEL_PAYMENT: return $this->cancelPaymentAction($request, $response, $invokeArgs); case self::ACTION_THANKS: return $this->thanksAction($request, $response, $invokeArgs); case self::ACTION_CC: default: return $this->ccAction($request, $response, $invokeArgs); } } protected function ccActionValidateSetInvoice(Am_Mvc_Request $request, array $invokeArgs) { $invoiceId = $request->getFiltered('id'); if (!$invoiceId) throw new Am_Exception_InputError("invoice_id is empty - seems you have followed wrong url, please return back to continue"); $invoice = $this->getDi()->invoiceTable->findBySecureId($invoiceId, $this->getId()); if (!$invoice) throw new Am_Exception_InputError('You have used wrong link for payment page, please return back and try again'); if ($invoice->isCompleted()) throw new Am_Exception_InputError(sprintf(___('Payment is already processed, please go to %sMembership page%s'), "","")); if ($invoice->paysys_id != $this->getId()) throw new Am_Exception_InputError("You have used wrong link for payment page, please return back and try again"); if ($invoice->tm_added < sqlTime('-30 days')) throw new Am_Exception_InputError("Invoice expired - you cannot open invoice after 30 days elapsed"); $this->invoice = $invoice; // set for reference } /** * Show credit card info input page, validate it if submitted */ public function ccAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->ccActionValidateSetInvoice($request, $invokeArgs); $p = $this->createController($request, $response, $invokeArgs); $p->setPlugin($this); $p->setInvoice($this->invoice); $p->run(); } /** * Process credit card update request * @param Am_Mvc_Request $request * @param Am_Mvc_Response $response * @param array $invokeArgs */ public function updateAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->getDi()->auth->requireLogin($this->getDi()->url('member',null,false)); $p = $this->createController($request, $response, $invokeArgs); $p->setPlugin($this); $p->run(); } /** * Process "cancel recurring" request * @param Am_Mvc_Request $request * @param Am_Mvc_Response $response * @param array $invokeArgs */ public function doCancelAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $id = $request->getFiltered('id'); $invoice = $this->getDi()->invoiceTable->findBySecureId($id, 'STOP'.$this->getId()); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); if ($invoice->user_id != $this->getDi()->auth->getUserId()) throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]"); if (method_exists($this, 'cancelInvoice')) $this->cancelInvoice($invoice); $invoice->setCancelled(); $response->setRedirect($this->getDi()->surl('member/payment-history', false)); } public function cancelPaymentAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $id = $request->getFiltered('id'); if (!$id && isset($_GET['id'])) $id = filterId($_GET['id']); $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($id); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); if ($invoice->user_id != $this->getDi()->auth->getUserId()) throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]"); $this->invoice = $invoice; // find invoice and redirect to default "cancel" page $response->setRedirect($this->getCancelUrl()); } /** * To be overriden in children classes * @param Am_Mvc_Request $request * @param Am_Mvc_Response $response * @param array $invokeArgs * @return \Am_Mvc_Controller_CreditCard */ protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_CreditCard($request, $response, $invokeArgs); } /** * Method must return array of self::CC_xxx constants to control which * additional fields will be displayed in the form * @return array */ public function getFormOptions(){ $ret = array(self::CC_CODE, self::CC_ADDRESS, self::CC_COUNTRY, self::CC_STATE, self::CC_CITY, self::CC_STREET, self::CC_ZIP); if ($this->getCreditCardTypeOptions()) $ret[] = self::CC_TYPE_OPTIONS; return $ret; } /** * */ public function getCreditCardTypeOptions(){ return array(); } /** * You can do form customization necessary for the plugin * here */ public function onFormInit(Am_Form_CreditCard $form) { } /** * You can do custom form validation here. If errors found, * call $form->getElementById('xx-0')->setError('xxx') and * return false * @return bool */ public function onFormValidate(Am_Form_CreditCard $form) { return true; } /** * Filter and validate cc# * @return null|string null if ok, error message if error */ public function validateCreditCardNumber($cc){ require_once 'ccvs.php'; $validator = new CreditCardValidationSolution; if (!$validator->validateCreditCard($cc)) return $validator->CCVSError; /** @todo translate error messages from ccvs.php */ return null; } public function doBill(Invoice $invoice, $doFirst, CcRecord $cc = null) { $this->invoice = $invoice; $this->cc = $cc; $result = new Am_Paysystem_Result(); $this->_doBill($invoice, $doFirst, $cc, $result); return $result; } public function doMaxmindCheck(Invoice $invoice, CcRecord $cc) { $result = new Am_Paysystem_Result(); $user = $invoice->getUser(); $server = array( 'minfraud.maxmind.com', 'minfraud-us-east.maxmind.com', 'minfraud-us-west.maxmind.com' ); $i = 0; if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) { $client_ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; $forwarded_ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; } else { if (isset($_SERVER["HTTP_CLIENT_IP"])) $client_ip = $_SERVER["HTTP_CLIENT_IP"]; else $client_ip = $_SERVER["REMOTE_ADDR"]; $forwarded_ip = ''; } $ps = new stdclass; $ps->license_key = $this->getConfig('maxmind_license_key'); $ps->bin = substr($cc->cc_number, 0, 6); $ps->i = $client_ip; $ps->forwardedIP = $forwarded_ip; $ps->city = $cc->cc_city; $ps->region = $cc->cc_state; $ps->country = $cc->cc_country; $ps->postal = $cc->cc_zip; list($acc, $domain) = @explode('@', $user->email, 2); $ps->domain = $domain; $ps->emailMD5 = md5(strtolower($user->email)); $ps->usernameMD5 = md5($user->login); $ps->custPhone = $cc->cc_phone; $ps->requested_type = $this->getConfig('maxmind_requested_type'); $ps->shipAddr = $cc->cc_street; $ps->shipCity = $cc->cc_city; $ps->shipRegion = $cc->cc_city; $ps->shipPostal = $cc->cc_city; $ps->shipCountry = $cc->cc_city; $ps->txnID = $invoice->public_id; $ps->sessionID = md5(session_id()); $ps->user_agent = $_SERVER['HTTP_USER_AGENT']; $request = $this->createHttpRequest(); $request->addPostParameter((array) $ps); $request->setMethod(Am_HttpRequest::METHOD_POST); do { //minfraud verification $request->setUrl('https://' . $server[$i] . '/app/ccv2r'); $transaction = new Am_Paysystem_Transaction_Maxmind_Minfraud($this, $invoice, $request, true); $transaction->run($result); $i++; } while ($i < count($server) && $transaction->isEmpty()); $risk_score = $transaction->getRiskScore(); if ($this->getConfig('maxmind_use_telephone_verification') && $risk_score >= $this->getConfig('maxmind_risk_score') && $risk_score <= 10 && !empty($cc->cc_phone)) { //number identification if($this->getConfig('maxmind_use_number_identification')) { $result_number = new Am_Paysystem_Result(); $i = 0; $ps = new stdclass; $ps->l = $this->getConfig('maxmind_license_key'); $ps->phone = preg_replace("/[^\d]+/i", "", $cc->cc_phone); $request_number = $this->createHttpRequest(); $request_number->addPostParameter((array) $ps); $request_number->setMethod(Am_HttpRequest::METHOD_POST); do { $request_number->setUrl('https://' . $server[$i] . '/app/phone_id_http'); $transaction = new Am_Paysystem_Transaction_Maxmind_Number($this, $invoice, $request_number, true); $transaction->run($result_number); $i++; } while ($i < count($server) && $transaction->isEmpty()); if($result_number->isFailure()) return $result_number; } //phone verification /*if($this->getConfig('maxmind_use_telephone_verification')) { $result_phone= new Am_Paysystem_Result(); $i = 0; $ps = new stdclass; $ps->l = $this->getConfig('maxmind_license_key'); $ps->phone = preg_replace("/[^\d]+/i", "", $cc->cc_phone); $request_phone = $this->createHttpRequest(); $request_phone->addPostParameter((array) $ps); $request_phone->setMethod(Am_HttpRequest::METHOD_POST); do { $request_phone->setUrl('https://' . $server[$i] . '/app/telephone_http'); $transaction = new Am_Paysystem_Transaction_Maxmind_Phone($this, $invoice, $request_phone, true); $transaction->run($result_phone); $i++; } while ($i < count($server) && $transaction->isEmpty()); if($result_phone->isFailure()) return $result_phone; }*/ } return $result; } abstract public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result); /** * Function can be overrided to change behaviour */ public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { if ($this->storesCcInfo()) { $cc->replace(); $result->setSuccess(); } return $this; } /** * Method defined for overriding in child classes where CC info is not stored locally * @return CcRecord * @param Invoice $invoice * @throws Am_Exception */ public function loadCreditCard(Invoice $invoice) { if ($this->storesCcInfo()) return $this->getDi()->ccRecordTable->findFirstByUserId($invoice->user_id); } public function prorateInvoice(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date) { /** @todo use "reattempt" config **/ $reattempt = array_filter($this->getConfig('reattempt', array())); sort($reattempt); if (!$reattempt) { $invoice->setStatus(Invoice::RECURRING_FAILED); $invoice->updateQuick('rebill_date', null); return; } $first_failure = $invoice->data()->get(self::FIRST_REBILL_FAILURE); if (!$first_failure) { $invoice->data()->set(self::FIRST_REBILL_FAILURE, $date)->update(); $first_failure = $date; } $days_diff = (strtotime($date) - strtotime($first_failure)) / (24*3600); foreach ($reattempt as $day) if ($day > $days_diff) break; // we have found next rebill date to jump if ($day <= $days_diff){ // Several rebilling attempts failed already. // change status to RECURRING_FAILED; $invoice->setStatus(Invoice::RECURRING_FAILED); $invoice->updateQuick('rebill_date', null); return; } $invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($first_failure." +$day days"))); $tr = new Am_Paysystem_Transaction_Manual($this); if ($invoice->getAccessExpire() < $invoice->rebill_date) $invoice->extendAccessPeriod($invoice->rebill_date); } public function onRebillFailure(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date) { $this->prorateInvoice($invoice, $cc, $result, $date); if($this->getDi()->config->get('cc.rebill_failed')) $this->sendRebillFailedToUser($invoice, $result->getLastError(), $invoice->rebill_date); } function sendRebillFailedToUser(Invoice $invoice, $failedReason, $nextRebill) { try { if($et = Am_Mail_Template::load('cc.rebill_failed')) { $et->setError($failedReason); $et->setUser($invoice->getUser()); $et->setInvoice($invoice); $et->setProrate( ($nextRebill > $this->getDi()->sqlDate) ? sprintf(___('Our system will try to charge your card again on %s'), amDate($nextRebill)) : "" ); $et->setMailPeriodic(Am_Mail::USER_REQUESTED); $et->send($invoice->getUser()); } }catch(Exception $e) { // No mail exceptions when rebilling; $this->getDi()->errorLogTable->logException($e); } } function sendRebillSuccessToUser(Invoice $invoice) { try { if($et = Am_Mail_Template::load('cc.rebill_success')) { $et->setUser($invoice->getUser()); $et->setInvoice($invoice); $et->setAmount($invoice->second_total); $et->setRebill_date($invoice->rebill_date ? amDate($invoice->rebill_date) : ___('NEVER')); $et->setMailPeriodic(Am_Mail::USER_REQUESTED); $et->send($invoice->getUser()); } } catch(Exception $e) { // No mail exceptions when rebilling; $this->getDi()->errorLogTable->logException($e); } } public function onRebillSuccess(Invoice $invoice, CcRecord $cc, Am_Paysystem_Result $result, $date) { if ($invoice->data()->get(self::FIRST_REBILL_FAILURE)) { $invoice->addToRebillDate(false, $invoice->data()->get(self::FIRST_REBILL_FAILURE)); $invoice->data()->set(self::FIRST_REBILL_FAILURE, null)->update(); } if($this->getDi()->config->get('cc.rebill_success')) $this->sendRebillSuccessToUser($invoice); } public function ccRebill($date = null) { /** * If plugin can't rebill payments itself, leave it alone. */ if($this->getRecurringType() != self::REPORTS_CRONREBILL) return; $rebillTable = $this->getDi()->ccRebillTable; $processedCount = 0; foreach ($this->getDi()->invoiceTable->findForRebill($date, $this->getId()) as $invoice) { // Invoice must have status RECURRING_ACTIVE in order to be rebilled; if($invoice->status != Invoice::RECURRING_ACTIVE) continue; // If we already have all payments for this invoice unset rebill_date and update invoice status; if($invoice->getPaymentsCount() >= $invoice->getExpectedPaymentsCount()) { $invoice->recalculateRebillDate(); $invoice->updateStatus(); continue; } /* @var $invoice Invoice */ try { $rebill = $rebillTable->createRecord(array( 'paysys_id' => $this->getId(), 'invoice_id' => $invoice->invoice_id, 'rebill_date' => $date, 'status' => CcRebill::STARTED, 'status_msg' => "Not Processed", )); //only one attempt to rebill per day try { $rebill->insert(); } catch (Am_Exception_Db_NotUnique $e) { continue; } $cc = $this->getDi()->CcRecordRecord; if ($this->storesCcInfo()) { $cc = $this->loadCreditCard($invoice); if (!$cc) { $rebill->setStatus(CcRebill::NO_CC, "No credit card saved, cannot rebill"); continue; } } $result = $this->doBill($invoice, false, $cc); if (!$result->isSuccess()) $this->onRebillFailure($invoice, $cc, $result, $date); else $this->onRebillSuccess($invoice, $cc, $result, $date); $rebill->setStatus($result->isSuccess() ? CcRebill::SUCCESS : CcRebill::ERROR, current($result->getErrorMessages())); $processedCount++; } catch (Exception $e) { if (stripos(get_class($e), 'PHPUnit_')===0) throw $e; $rebill->setStatus(CcRebill::EXCEPTION, "Exception " . get_class($e) . " : " . $e->getMessage()); // if there was an exception in billing (say internal error), // we set rebill_date to tomorrow $invoice->updateQuick('rebill_date', date('Y-m-d', strtotime($invoice->rebill_date . ' +1 day'))); $this->getDi()->errorLogTable->logException($e); $this->logError("Exception on rebilling", $e, $invoice); unset($this->invoice); } } // Send message only if rebill executed by cron; if($this->getDi()->config->get('cc.admin_rebill_stats') && (is_null($date) || $date == $this->getDi()->sqlDate) && $processedCount) $this->sendStatisticsEmail(); } protected function getStatisticsRow(Array $r) { if($r['status']!= CcRebill::SUCCESS) { $failed = "Reason: ".$r['status_msg']; if($r['rebill_date']>$this->getDi()->sqlDate) $failed .= "\t Next Rebill Date: ".$r['rebill_date']; }else $failed = ''; $row = sprintf("%s, %s, %s %s, \nInvoice: %s\tAmount: %s\t%s\n%s\n\n", $r['email'], $r['login'], $r['name_f'], $r['name_l'], $r['public_id'], $r['second_total'], $failed, $this->getDi()->url(array('admin-user-payments/index/user_id/%s#invoice-%s', $r['user_id'], $r['invoice_id'])) ); return $row; } protected function sendStatisticsEmail() { $date = $this->getDi()->sqlDate; $success = $failed = ""; $success_count = $failed_count = $success_amount = $failed_amount = 0; if ($et = Am_Mail_Template::load('cc.admin_rebill_stats')) { foreach($this->getDi()->db->selectPage($total, " SELECT r.*, i.second_total, i.user_id, i.invoice_id, i.public_id, i.rebill_date, u.name_f, u.name_l, u.email, u.login FROM ?_cc_rebill r LEFT JOIN ?_invoice i USING(invoice_id) LEFT JOIN ?_user u ON(i.user_id = u.user_id) WHERE status_tm>? and status_tm<=? and r.paysys_id=? ", $date, $this->getDi()->sqlDateTime, $this->getId()) as $r) { if($r['status'] == CcRebill::SUCCESS) { $success_count++; $success_amount+=$r['second_total']; $success .= $this->getStatisticsRow($r); }else{ $failed_count++; $failed_amount += $r['second_total']; $failed .= $this->getStatisticsRow($r);; } } if($success || $failed) { $currency = $this->getDi()->config->get('currency'); $et->setShort_stats(sprintf(___('Success: %d (%0.2f %s) Failed: %d (%0.2f %s)'), $success_count, $success_amount, $currency, $failed_count, $failed_amount, $currency)); $et->setRebills_success(!empty($success) ? $success : ___('No items in this section')); $et->setRebills_failed(!empty($failed) ? $failed : ___('No items in this section')); $et->setPlugin($this->getId()); $et->setMailPeriodic(Am_Mail::ADMIN_REQUESTED); $et->sendAdmin(); } } } protected function _afterInitSetupForm(Am_Form_Setup $form) { // insert title, description fields $form->setTitle(ucfirst(toCamelCase($this->getId()))); $el = $form->addMagicSelect('reattempt', array('multiple'=>'multiple')); $options = array(); for ($i=1;$i<60;$i++) $options[$i] = ___("on %d-th day", $i); $el->loadOptions($options); $el->setLabel(___("Retry On Failure\n". "if the recurring billing has failed,\n". "aMember can repeat it after several days,\n". "and extend customer subscription for that period\n". "enter number of days to repeat billing attempt")); if($this->canUseMaxmind()) { $form->addFieldset()->setLabel(___('MaxMind Credit Card Fraud Detection')); $form->addAdvCheckbox('use_maxmind')->setLabel(___('Use MaxMind Credit Card Fraud Detection')); $form->addText('maxmind_license_key')->setLabel( ___("Maxmind License Key\n" . "%sObtain a Free or Premium license key%s", '', '')); $form->addSelect('maxmind_requested_type')->setLabel( ___("Requested Type\n" . "To be used if you have multiple plans in one account\n" . "and wish to select type of query you wish to make.\n" . "By default the service uses the highest level available")) ->loadOptions(array( "" => 'Default', "free" => 'Free', "city" => 'City (standard paid service)', "premium" => 'Premium (premium paid service)')); $form->addText('maxmind_risk_score')->setLabel( ___("Risk Score\n" . "Overall %sRisk Score%s (decimal from 0 to 10)\n" . "For orders that return a fraud score of 2.5 and above,\n" . " it is recommended to hold for review,\n" . " or require the validation with the Telephone Verification service\n", '', '')); $form->setDefault('maxmind_risk_score', '2.5'); /*$form->addAdvCheckbox('maxmind_use_telephone_verification')->setLabel( ___("Telephone Verification\n" . "Enable %sTelephone Verification%s service" , '', ''));*/ $form->addAdvCheckbox('maxmind_use_number_identification')->setLabel( ___("Number Identification\n" . "Enable %sTelephone Number Identification (TNI)%s service", '', '')); $form->addMagicSelect('maxmind_tni_phone_types')->setLabel( ___("Allowed Phone Types\n" . "The TNI service is able to categorize customer inputted US and Canadian\n" . "phone numbers into %seight different phone types%s\n" . "such as fixed land line, mobile, VoIP, and invalid phone numbers", '', '')) ->loadOptions(array( '0' => 'Undetermined (Medium Risk Level)', '1' => 'Fixed Line (Low Risk Level)', '2' => 'Mobile (Low-Medium Risk Level)', '3' => 'PrePaid Mobile (Medium-High Risk Level)', '4' => 'Toll-Free (High Risk Level)', '5' => 'Non-Fixed VoIP (High Risk Level)', '8' => 'Invalid Number (High Risk Level)', '9' => 'Restricted Number (High Risk Level)')); $form->addAdvCheckbox('maxmind_allow_country_not_matched')->setLabel( ___("Allow payment if country not matched\n" . "Whether country of IP address matches billing address country\n" . "(mismatch = higher risk)")); $form->addAdvCheckbox('maxmind_allow_high_risk_country')->setLabel( ___("Allow payment if high risk countries\n" . "Whether IP address or billing address country is in\n" . "Egypt, Ghana, Indonesia, Lebanon, Macedonia, Morocco, Nigeria,\n" . "Pakistan, Romania, Serbia and Montenegro, Ukraine, or Vietnam")); $form->addAdvCheckbox('maxmind_allow_anonymous_proxy')->setLabel( ___("Allow payment if anonymous proxy\n" . "Whether IP address is %sAnonymous Proxy%s\n" . "(anonymous proxy = very high risk)", '', '')); $form->addAdvCheckbox('maxmind_allow_free_mail')->setLabel( ___("Allow payment if free e-mail\n" . "Whether e-mail is from free e-mail provider\n" . "(free e-mail = higher risk)")); $form->addElement('script')->setScript(<<storesCcInfo() && !$this->_pciDssNotRequired) { $text = "

      WARNING! Every application processing credit card information, must be certified\n" . "as PA-DSS compliant, and every website processing credit cards must\n" . "be certified as PCI-DSS compliant.

      "; $text.= "

      aMember Pro is not yet certified as PA-DSS compliant. ". "This plugins is provided solely for TESTING purproses\n". "Use it for anything else but testing at your own risk.

      "; $form->addProlog(<< $text CUT ); } $keyFile = defined('AM_KEYFILE') ? AM_KEYFILE : AM_APPLICATION_PATH . '/configs/key.php'; if (!is_readable($keyFile)) { $random = $this->getDi()->security->randomString(78); $text = "

      To use credit card plugins, you need to create a key file that contains unique\n"; $text .= "encryption key for your website. It is necessary even if the plugin does not\n"; $text .= "store sensitive information.

      "; $text .= "

      In a text editor, create file with the following content (one-line, no spaces before opening <?php):\n"; $text .= "

      <?php return '$random';
      \n"; $text .= "
      save the file as key.php, and upload to amember/application/configs/ folder.\n"; $text .= "This warning will disappear once you do it correctly.

      "; $text .= "

      KEEP A BACKUP COPY OF THE key.php FILE (!)

      "; $form->addProlog(<< $text CUT ); } return parent::_afterInitSetupForm($form); } /** * If plugin require special actions to cancel invoice, cancelInvoice will be called * after Invoice will actually be cancelled by CreditCard Controller. * do nothing by default; * @throws Am_Exception_InputError if failure; * @param Invoice $invoice */ function cancelInvoice(Invoice $invoice){ return true; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $result->setSuccess(); $invoice->setCancelled(true); } public function getUpdateCcLink($user) { if ($this->storesCcInfo() && $this->getDi()->ccRecordTable->findFirstByUserId($user->user_id)) { return $this->getPluginUrl('update'); } } public function onDaily() { $this->sendCcExpireMessage(); } public function sendCcExpireMessage() { // Send Message only if plugin is allowed to store CC info. if(!$this->storesCcInfo()) return; if(!$this->getDi()->config->get('cc.card_expire')) return; $oRebillDate = $this->getDi()->dateTime; $oRebillDate->modify(sprintf("+%d days", $this->getDi()->config->get('cc.card_expire_days', 5))); foreach($this->getDi()->db->selectPage($total, " SELECT i.invoice_id, c.cc_expire FROM ?_invoice i LEFT JOIN ?_cc c using(user_id) WHERE i.status = ? and i.rebill_date = ? and CONCAT(SUBSTR(c.cc_expire, 3,2), SUBSTR(c.cc_expire, 1,2)) < ? and i.paysys_id = ? ", Invoice::RECURRING_ACTIVE, $oRebillDate->format('Y-m-d'), $oRebillDate->format('ym'), $this->getId()) as $r) { $invoice = $this->getDi()->invoiceTable->load($r['invoice_id']); if($et = Am_Mail_Template::load('cc.card_expire')) { $et->setUser($invoice->getUser()); $et->setInvoice($invoice); $et->setExpires(substr_replace($r['cc_expire'], '/', 2, 0)); $et->setMailPeriodic(Am_Mail::USER_REQUESTED); $et->send($invoice->getUser()); } } } public function canUseMaxmind() { return false; } } PK\RfWW?cc/library/Am/Paysystem/Networkmerchants/Transaction/Refund.phpnu[amount = $amount; parent::__construct($plugin, $invoice, true); $this->request->addPostParameter('transactionid', $transactionId); $this->request->addPostParameter('customer_vault_id', $customerVaultId); } public function getAmount() { return $this->amount; } public function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('type', 'refund'); $this->request->addPostParameter('amount', $this->getAmount()); } public function processValidated(){} // no process payment } PK\_  Dcc/library/Am/Paysystem/Networkmerchants/Transaction/AddCustomer.phpnu[setCcRecord($cc); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('customer_vault', 'add_customer'); } public function processValidated(){} // no process payment } PK\QQ@cc/library/Am/Paysystem/Networkmerchants/Transaction/Capture.phpnu[request->addPostParameter('transactionid', $transactionid); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('amount', $this->getAmount()); $this->request->addPostParameter('type', 'capture'); } } PK\eWsSS=cc/library/Am/Paysystem/Networkmerchants/Transaction/Sale.phpnu[request->addPostParameter('customer_vault_id', $customerVaultId); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('amount', $this->getAmount()); $this->request->addPostParameter('type', 'sale'); } } PK\fM=cc/library/Am/Paysystem/Networkmerchants/Transaction/Void.phpnu[request->addPostParameter('transactionid', $transactionId); $this->request->addPostParameter('customer_vault_id', $customerVaultId); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('type', 'void'); $this->request->addPostParameter('amount', 1.00); } public function processValidated(){} // no process payment } PK\^S'Fcc/library/Am/Paysystem/Networkmerchants/Transaction/Authorization.phpnu[amount = $amount; parent::__construct($plugin, $invoice, true); $this->setCcRecord($cc); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('type', 'auth'); $this->request->addPostParameter('amount', $this->amount); $this->request->addPostParameter('customer_vault', 'add_customer'); } public function processValidated(){} // no process payment } PK\/ 8cc/library/Am/Paysystem/Networkmerchants/Transaction.phpnu[getGatewayURL(), Am_HttpRequest::METHOD_POST); parent::__construct($plugin, $invoice, $request, $doFirst); $this->addRequestParams(); } private function getUser() { return (!$this->plugin->getConfig('testMode')) ? $this->plugin->getConfig('user') : 'demo'; } private function getPass() { return (!$this->plugin->getConfig('testMode')) ? $this->plugin->getConfig('pass') : 'password'; } public function getAmount() { return $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total; } protected function addRequestParams() { $this->request->addPostParameter('username', $this->getUser()); $this->request->addPostParameter('password', $this->getPass()); } public function getUniqId() { return $this->parsedResponse->transactionid; } public function parseResponse() { parse_str($this->response->getBody(), $this->parsedResponse); $this->parsedResponse = (object)$this->parsedResponse; } public function validate() { switch ($this->parsedResponse->response) { case 1: break; case 2: $err = "Transaction Declined."; break; case 3: $err = "Error in transaction data or system error."; break; default: $err = "Unknown error num: " . $this->parsedResponse->response . "."; break; } if (!empty($err)) { return $this->result->setFailed(array($err, $this->parsedResponse->responsetext)); } $this->result->setSuccess($this); } protected function setCcRecord(CcRecord $cc) { $this->request->addPostParameter('ccnumber', $cc->cc_number); $this->request->addPostParameter('ccexp', $cc->cc_expire); $this->request->addPostParameter('cvv', $cc->getCvv()); $this->request->addPostParameter('firstname', $cc->cc_name_f); $this->request->addPostParameter('lastname', $cc->cc_name_l); $this->request->addPostParameter('address1', $cc->cc_street); $this->request->addPostParameter('city', $cc->cc_city); $this->request->addPostParameter('state', $cc->cc_state); $this->request->addPostParameter('zip', $cc->cc_zip); $this->request->addPostParameter('country', $cc->cc_country); $this->request->addPostParameter('phone', $cc->cc_phone); } public function getCustomerVaultId() { return $this->parsedResponse->customer_vault_id; } } PK\n؋%%cc/library/Am/Form/Echeck.phpnu[plugin = $plugin; $this->formType = $formType; $this->payButtons = array( self::PAYFORM => ___('Subscribe And Pay'), self::ADMIN_UPDATE => ___('Update eCheck Info'), self::USER_UPDATE => ___('Update eCheck Info'), self::ADMIN_INSERT => ___('Update eCheck Info'), ); parent::__construct('ec'); } public function init() { parent::init(); $name = $this->addGroup() ->setLabel(___("Your Name\n" . 'your first and last name')); $name->setSeparator(' '); $name->addRule('required', ___('Please enter your name')); $name->addText('echeck_name_f', array('size' => 15)) ->addRule('required', ___('Please enter first name')) ->addRule('regex', ___('Please enter first name'), '|^[a-zA-Z_\' -]+$|'); $name->addText('echeck_name_l', array('size' => 15)) ->addRule('required', ___('Please enter your last name')) ->addRule('regex', ___('Please enter your last name'), '|^[a-zA-Z_\' -]+$|'); if ($this->formType == self::ADMIN_UPDATE) { $group = $this->addGroup()->setLabel(___("Bank Account Number\n" . 'Up to 20 digits')); $group->addStatic()->setContent('
      '); $group->addStatic('echeck'); $group->addText('echeck_ban', array('autocomplete' => 'off', 'maxlength' => 20, 'style' => 'display:none')) ->addRule('regex', ___('Invalid Bank Account Number'), '/^[a-zA-Z0-9]{1,20}$/'); $group->addScript("")->setScript(<<addStatic()->setContent('
      '); } else { $this->addText('echeck_ban', array('autocomplete' => 'off', 'maxlength' => 20)) ->setLabel(___("Your Bank Account Number\n" . 'Up to 20 digits')) ->addRule('required', ___('Please enter Account Number')) ->addRule('regex', ___('Invalid Account Number'), '/^[a-zA-Z0-9]{1,20}$/'); } $this->addText('echeck_aba', array('autocomplete' => 'off', 'maxlength' => 9)) ->setLabel(___("ABA Routing Number\n" . '9 digits')) ->addRule('required', ___('Please enter Routing Number')) ->addRule('regex', ___('Invalid Routing Number'), '/^[a-zA-Z0-9]{1,9}$/'); $options = $this->plugin->getFormOptions(); if (in_array(Am_Paysystem_Echeck::ECHECK_COMPANY, $options)) { $this->addText(Am_Paysystem_Echeck::ECHECK_COMPANY) ->setLabel(___("Company Name\n" . 'the company name associated with the billing address for ' . 'the transaction')); } if (in_array(Am_Paysystem_Echeck::ECHECK_TYPE_OPTIONS, $options)) { $type = $this->addSelect(Am_Paysystem_Echeck::ECHECK_TYPE_OPTIONS) ->setLabel(___("Bank Account Type\n" . 'please select one')) ->loadOptions(array_merge(array(''=>'-- ' . ___('Please choose') . ' --'), $this->plugin->getEcheckTypeOptions())); $type->addRule('required', ___('Please choose a Bank Account Type')); } if (in_array(Am_Paysystem_Echeck::ECHECK_BANK_NAME, $options)) { $this->addText(Am_Paysystem_Echeck::ECHECK_BANK_NAME, array('autocomplete' => 'off', 'maxlength' => 50)) ->setLabel(___('Bank Name')) ->addRule('required', ___('Please enter Bank Name')); } if (in_array(Am_Paysystem_Echeck::ECHECK_ACCOUNT_NAME, $options)) { $this->addText(Am_Paysystem_Echeck::ECHECK_ACCOUNT_NAME, array('autocomplete' => 'off', 'maxlength' => 50)) ->setLabel(___("Bank Account Name\n" . 'name associated with the bank account')) ->addRule('required', ___('Please enter Bank Account Name')); } if (in_array(Am_Paysystem_Echeck::ECHECK_ADDRESS, $options)) { $fieldSet = $this->addFieldset(___('Address Info')) ->setLabel(___("Address Info\n" . '(must match your credit card statement delivery address)')); if (in_array(Am_Paysystem_Echeck::ECHECK_STREET, $options)) { $street = $fieldSet->addText('echeck_street')->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); } if (in_array(Am_Paysystem_Echeck::ECHECK_STREET2, $options)) { $street2 = $fieldSet->addText('echeck_street2')->setLabel(___('Street Address (Second Line)')) ->addRule('required', ___('Please enter Street Address')); } if (in_array(Am_Paysystem_Echeck::ECHECK_CITY, $options)) { $city = $fieldSet->addText('echeck_city')->setLabel(___('City')) ->addRule('required', ___('Please enter City')); } if (in_array(Am_Paysystem_Echeck::ECHECK_ZIP, $options)) { $zip = $fieldSet->addText('echeck_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); } if (in_array(Am_Paysystem_Echeck::ECHECK_COUNTRY, $options)) { $country = $fieldSet->addSelect('echeck_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); } if (in_array(Am_Paysystem_Echeck::ECHECK_STATE, $options)) { $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); /** @todo load correct states */ $stateSelect = $group->addSelect('echeck_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['echeck_country'], true)); $stateText = $group->addText('echeck_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); } if (in_array(Am_Paysystem_Echeck::ECHECK_PHONE, $options)) { $phone = $fieldSet->addText('echeck_phone', array('size'=>14))->setLabel(___('Phone')) ->addRule('required', ___('Please enter phone number')) ->addRule('regex', ___('Please enter phone number'), '|^[\d() +-]+$|'); } } $buttons = $this->addGroup(); $buttons->addSubmit('_echeck_', array('value' => ' ' . $this->payButtons[$this->formType] . ' ')); if ($this->formType == self::USER_UPDATE) { $buttons->addInputButton('_echeck_', array('value' => ' ' . ___("Back") . ' ', 'onclick' => 'goBackToMember()')); $this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }"); } $this->plugin->onFormInit($this); } /** * Return array of default values based on $user record * @param User $user */ public function getDefaultValues(User $user) { return array( 'echeck_name_f' => $user->name_f, 'echeck_name_l' => $user->name_l, 'echeck_street' => $user->street, 'echeck_street2' => $user->street2, 'echeck_city' => $user->city, 'echeck_state' => $user->state, 'echeck_country' => $user->country, 'echeck_zip' => $user->zip, 'echeck_phone' => $user->phone, ); } public function validate() { return parent::validate() && $this->plugin->onFormValidate($this); } public function getValue() { $ret = parent::getValue(); array_walk_recursive($ret, function(&$v, $k) {$v=trim($v);}); if (!empty($ret['echeck_ban'])) $ret['echeck_ban'] = preg_replace('/\D/', '', $ret['echeck_ban']); return $ret; } public function toEcheckRecord(EcheckRecord $echeck) { $values = $this->getValue(); unset($values['a']); unset($values['id']); unset($values['action']); $echeck->setForInsert($values); } } PK\r\6\6!cc/library/Am/Form/CreditCard.phpnu[setSeparator(' '); $require = !$data['dont_require']; $years = @$data['years']; if (!$years) $years = 10; $m = $this->addSelect('m')->loadOptions($this->getMonthOptions()); if ($require) $m->addRule('required', ___('Invalid Expiration Date - Month')); $y = $this->addSelect('y')->loadOptions($this->getYearOptions($years)); if ($require) $y->addRule('required', ___('Invalid Expiration Date - Year')); } public function getMonthOptions() { $locale = Am_Di::getInstance()->locale; $months = $locale->getMonthNames('wide', false); foreach ($months as $k=>$v) $months[$k] = sprintf('(%02d) %s', $k, $v); $months[''] = ''; ksort($months); return $months; } public function getYearOptions($add){ $years = range(date('Y'), date('Y')+$add); array_unshift($years, ''); return array_combine($years, $years); } public function setValue($value) { if (is_string($value) && preg_match('/^\d{4}$/', $value)) { $value = array( 'm' => (int)substr($value, 0, 2), 'y' => '20' . substr($value, 2, 2), ); } return parent::setValue($value); } protected function updateValue() { $name = $this->getName(); foreach ($this->getDataSources() as $ds) { if (null !== ($value = $ds->getValue($name))) { $this->setValue($value); return; } } return parent::updateValue(); } } class Am_Form_CreditCard extends Am_Form { const PAYFORM = 'payform'; const USER_UPDATE = 'user-update'; const ADMIN_UPDATE = 'admin-update'; const ADMIN_INSERT = 'admin-insert'; protected $payButtons = array(); /** @var Am_Paysystem_CreditCard */ protected $plugin; protected $formType = self::PAYFORM; public function __construct(Am_Paysystem_CreditCard $plugin, $formType = self::PAYFORM) { $this->plugin = $plugin; $this->formType = $formType; $this->payButtons = array( self::PAYFORM => ___('Subscribe And Pay'), self::ADMIN_UPDATE => ___('Update Credit Card Info'), self::USER_UPDATE => ___('Update Credit Card Info'), self::ADMIN_INSERT => ___('Update Credit Card Info'), ); parent::__construct('cc'); } public function init() { parent::init(); $name = $this->addGroup() ->setLabel(___("Cardholder Name\n" . 'cardholder first and last name, exactly as on the card')); $name->setSeparator(' '); $name->addRule('required', ___('Please enter credit card holder name')); $name_f = $name->addText('cc_name_f', array('size'=>15)); $name_f->addRule('required', ___('Please enter credit card holder first name'))->addRule('regex', ___('Please enter credit card holder first name'), '/^[^=:<>{}()"]+$/D'); $name_l = $name->addText('cc_name_l', array('size'=>15)); $name_l->addRule('required', ___('Please enter credit card holder last name'))->addRule('regex', ___('Please enter credit card holder last name'), '/^[^=:<>{}()"]+$/D'); $options = $this->plugin->getFormOptions(); if (in_array(Am_Paysystem_CreditCard::CC_COMPANY, $options)) $company = $this->addText('cc_company') ->setLabel(___("Company Name\n" . 'the company name associated with the billing address for the transaction')); if (in_array(Am_Paysystem_CreditCard::CC_TYPE_OPTIONS, $options)) { $type = $this->addSelect('cc_type') ->setLabel(___("Credit Card Type\n" . 'please select one')) ->loadOptions(array_merge(array(''=>'-- ' . ___('Please choose') . ' --'), $this->plugin->getCreditCardTypeOptions())); $type->addRule('required', ___('Please choose a Credit Card Type')); } if ($this->formType == self::ADMIN_UPDATE) { $group = $this->addGroup() ->setLabel(___("Credit Card Number\n" . "for example: 1111-2222-3333-4444")); $group->addStatic()->setContent('
      '); $group->addStatic('cc'); $cc = $group->addText('cc_number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22, 'style'=>'display:none')); $cc->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/') ->addRule('callback2', 'Invalid CC#', array($this->plugin, 'validateCreditCardNumber')); $group->addScript("")->setScript(<<addStatic()->setContent('
      '); } else { $cc = $this->addText('cc_number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22)) ->setLabel(___("Credit Card Number\n" . 'for example: 1111-2222-3333-4444')); $cc->addRule('required', ___('Please enter Credit Card Number')) ->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/') ->addRule('callback2', 'Invalid CC#', array($this->plugin, 'validateCreditCardNumber')); } $expire = $this->addElement(new Am_Form_Element_CreditCardExpire('cc_expire')) ->setLabel(___("Card Expire\n" . 'Select card expiration date - month and year')) ->addRule('required'); if (in_array(Am_Paysystem_CreditCard::CC_CODE, $options)) { $code = $this->addPassword('cc_code', array('autocomplete'=>'off', 'size'=>4, 'maxlength'=>4)) ->setLabel(___("Credit Card Code\n" . 'The "Card Code" is a three- or four-digit security code ' . 'that is printed on the back of credit cards in the card\'s ' . 'signature panel (or on the front for American Express cards)')); $code->addRule('required', ___('Please enter Credit Card Code')) ->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/'); } if (in_array(Am_Paysystem_CreditCard::CC_MAESTRO_SOLO_SWITCH, $options)) { $issue = $this->addText('cc_issuenum', array('autocomplete'=>'off', 'size'=>20, 'maxlength'=>22)) ->setLabel(___("Card Issue #\n" . 'is required for Maestro/Solo/Switch credit cards only')) ->addRule('regex', ___('Invalid Issue Number'), '/^\d+$/'); $this->addElement(new Am_Form_Element_CreditCardExpire('cc_startdate', null, array('dont_require'=>true, 'years'=>-10))) ->setLabel(___("Card Start Date\n" . 'is required for Maestro/Solo/Switch credit cards only')); } if (in_array(Am_Paysystem_CreditCard::CC_INPUT_BIN, $options)) { $fieldSet = $this->addFieldset()->setLabel(___('Bank Identification')); $fieldSet->addText('_cc_bin_name', array()) ->setLabel(___("Bank Name\n" . 'name of the bank which issued the credit card')); $fieldSet->addText('_cc_bin_phone', array()) ->setLabel(___("Bank Phone\n" . 'customer service phone number listed on back of your credit card')); } if (in_array(Am_Paysystem_CreditCard::CC_ADDRESS, $options)) { $fieldSet = $this->addFieldset(___('Billing Address')) ->setLabel(___("Billing Address\n" . 'must match your credit card statement delivery address')); if (in_array(Am_Paysystem_CreditCard::CC_STREET, $options)) { $street = $fieldSet->addText('cc_street', array('class'=>'el-wide'))->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); } if (in_array(Am_Paysystem_CreditCard::CC_STREET2, $options)) { $street2 = $fieldSet->addText('cc_street2', array('class'=>'el-wide'))->setLabel(___('Street Address (Second Line)')) ->addRule('required', ___('Please enter Street Address')); } if (in_array(Am_Paysystem_CreditCard::CC_HOUSENUMBER, $options)) { $house = $fieldSet->addText('cc_housenumber', array('size'=>15))->setLabel(___('Housenumber')) ->addRule('required', ___('Please enter housenumber')); } if (in_array(Am_Paysystem_CreditCard::CC_CITY, $options)) { $city = $fieldSet->addText('cc_city')->setLabel(___('City')) ->addRule('required', ___('Please enter City')); } if (in_array(Am_Paysystem_CreditCard::CC_PROVINCE_OUTSIDE_OF_US, $options)) { $province = $fieldSet->addText('cc_province', array('size'=>15)) ->setLabel(___("Billing International Province\n" . 'for international provinces outside of US & Canada ' . 'include the province name here')) ->addRule('required', ___('Please choose state')); } if (in_array(Am_Paysystem_CreditCard::CC_ZIP, $options)) { $zip = $fieldSet->addText('cc_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); } if (in_array(Am_Paysystem_CreditCard::CC_COUNTRY, $options)) { $country = $fieldSet->addSelect('cc_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); } if (in_array(Am_Paysystem_CreditCard::CC_STATE, $options)) { $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); /** @todo load correct states */ $stateSelect = $group->addSelect('cc_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['cc_country'], true)); $stateText = $group->addText('cc_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); } if (in_array(Am_Paysystem_CreditCard::CC_PHONE, $options)) { $phone = $fieldSet->addText('cc_phone', array('size'=>14))->setLabel(___('Phone')) ->addRule('required', ___('Please enter phone number')) ->addRule('regex', ___('Please enter phone number'), '|^[\d() +-]+$|'); } } // if free trial set _TPL_CC_INFO_SUBMIT_BUT2 $buttons = $this->addGroup(); $buttons->setSeparator(' '); $buttons->addSubmit('_cc_', array('value'=> $this->payButtons[ $this->formType ])); if ($this->formType == self::USER_UPDATE) { $buttons->addStatic() ->setContent(sprintf('%s', ___("Back"))); $this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }"); } $this->plugin->onFormInit($this); } /** * Return array of default values based on $user record * @param User $user */ public function getDefaultValues(User $user){ return array( 'cc_name_f' => $user->name_f, 'cc_name_l' => $user->name_l, 'cc_street' => $user->street, 'cc_street2' => $user->street2, 'cc_city' => $user->city, 'cc_state' => $user->state, 'cc_country' => $user->country, 'cc_zip' => $user->zip, 'cc_phone' => $user->phone, ); } public function validate() { return parent::validate() && $this->plugin->onFormValidate($this); } public function getValue() { $ret = parent::getValue(); array_walk_recursive($ret, function(&$v, $k) {$v=trim($v);}); if (!empty($ret['cc_number'])) $ret['cc_number'] = preg_replace('/\D/', '', $ret['cc_number']); return $ret; } public function toCcRecord(CcRecord $cc){ $values = $this->getValue(); foreach ($values as $k=>$v) if (is_array($v)) { if(!empty($v['m'])) $values[$k] = sprintf('%02d%02d', $v['m'], substr($v['y'], -2)); elseif(array_key_exists('m', $v)) $values[$k] = ''; } unset($values['_cc_bin_name']); unset($values['_cc_bin_phone']); unset($values['a']); unset($values['id']); if( !empty($values['cc_code'])) $cc->setCvv($values['cc_code']); unset($values['cc_code']); unset($values['action']); $cc->setForInsert($values); } }PK\AR:'cc/library/Am/Mvc/Controller/Echeck.phpnu[plugin = $plugin; } /** * Process the validated form and if ok, display thanks page, * if not ok, return false */ public function processEcheck() { $echeck = $this->getDi()->echeckRecordRecord; $this->form->toEcheckRecord($echeck); $echeck->user_id = $this->invoice->user_id; $result = $this->plugin->doBill($this->invoice, true, $echeck); if ($result->isSuccess()) { if (($this->invoice->rebill_times > 0) && !$echeck->pk()) $this->plugin->storeEcheck($echeck, new Am_Paysystem_Result); $this->_response->redirectLocation($this->plugin->getReturnUrl()); return true; } elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) { $result->getAction()->process($this); // throws Am_Exception_Redirect (!) } else { $this->view->error = $result->getErrorMessages(); } } public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } public function echeckAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); if ($this->form->isSubmitted() && $this->form->validate() && $this->processEcheck()) return; $this->view->form = $this->form; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $this->view->display('echeck/info.phtml'); } public function createForm() { $form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser())) )); $form->addHidden(Am_Mvc_Controller::ACTION_KEY)->setValue($this->_request->getActionName()); $form->addHidden('id')->setValue($this->getFiltered('id')); return $form; } public function preDispatch() { if (!$this->plugin) throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__); } public function createUpdateForm() { $form = new Am_Form_Echeck($this->plugin, Am_Form_CreditCard::USER_UPDATE); $user = $this->getDi()->auth->getUser(true); if (!$user) throw new Am_Exception_InputError("You are not logged-in"); $echeck = $this->getDi()->echeckRecordTable->findFirstByUserId($user->user_id); if (!$echeck) $echeck = $this->getDi()->echeckRecordRecord; $arr = $echeck->toArray(); unset($arr['echeck_ban']); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($arr) )); return $form; } public function updateAction() { $this->form = $this->createUpdateForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $echeck = $this->getDi()->echeckRecordRecord; $this->form->toEcheckRecord($echeck); $echeck->user_id = $this->getDi()->auth->getUserId(); $result = new Am_Paysystem_Result(); $this->plugin->storeEcheck($echeck, $result); if ($result->isSuccess()) { return $this->_response->redirectLocation($this->getDi()->url('member',null,false)); } else { $this->form->getElementById('echeck_ban-0')->setError($result->getLastError()); } } $this->view->form = $this->form; $this->view->invoice = null; $this->view->display_receipt = false; $this->view->display('echeck/info.phtml'); } } PK\*_!II+cc/library/Am/Mvc/Controller/CreditCard.phpnu[plugin = $plugin; } /** * Process the validated form and if ok, display thanks page, * if not ok, return false */ public function processCc() { $cc = $this->getDi()->ccRecordRecord; $this->form->toCcRecord($cc); $cc->user_id = $this->invoice->user_id; if($this->plugin->getConfig('use_maxmind')) { $checkresult = $this->plugin->doMaxmindCheck($this->invoice, $cc); if (!$checkresult->isSuccess()) { $this->view->error = $checkresult->getErrorMessages(); return; } } $result = $this->plugin->doBill($this->invoice, true, $cc); if ($result->isSuccess()) { if (($this->invoice->rebill_times > 0) && !$cc->pk()) $this->plugin->storeCreditCard($cc, new Am_Paysystem_Result); $this->_response->redirectLocation($this->plugin->getReturnUrl()); return true; } elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) { $result->getAction()->process($this); // throws Am_Exception_Redirect (!) } else { $this->view->error = $result->getErrorMessages(); } } public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } public function ccAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); $this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form)); if ($this->form->isSubmitted() && $this->form->validate()) { if ($this->processCc()) return; } $this->view->form = $this->form; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $this->view->display('cc/info.phtml'); } public function createForm() { $form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser())) )); $form->addHidden(Am_Mvc_Controller::ACTION_KEY)->setValue($this->_request->getActionName()); $form->addHidden('id')->setValue($this->getFiltered('id')); return $form; } public function preDispatch() { if (!$this->plugin) throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__); } public function createUpdateForm() { $form = new Am_Form_CreditCard($this->plugin, Am_Form_CreditCard::USER_UPDATE); $user = $this->getDi()->auth->getUser(true); if (!$user) throw new Am_Exception_InputError("You are not logged-in"); $cc = $this->getDi()->ccRecordTable->findFirstByUserId($user->user_id); if (!$cc) $cc = $this->getDi()->ccRecordRecord; $arr = $cc->toArray(); unset($arr['cc_number']); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($arr) )); return $form; } public function updateAction() { $this->form = $this->createUpdateForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $cc = $this->getDi()->ccRecordRecord; $this->form->toCcRecord($cc); $cc->user_id = $this->getDi()->auth->getUserId(); $result = new Am_Paysystem_Result(); $this->plugin->storeCreditCard($cc, $result); if ($result->isSuccess()) { return $this->_response->redirectLocation($this->getDi()->url('member',array('_msg'=>___('Your card details have been updated.')),false)); } else { $this->form->getElementById('cc_number-0')->setError($result->getLastError()); } } $this->view->form = $this->form; $this->view->invoice = null; $this->view->display_receipt = false; $this->view->display('cc/info.phtml'); } } PK\<%@#cc/library/Am/Controller/Echeck.phpnu[plugin = $plugin; } /** * Process the validated form and if ok, display thanks page, * if not ok, return false */ public function processEcheck() { $echeck = $this->getDi()->echeckRecordRecord; $this->form->toEcheckRecord($echeck); $echeck->user_id = $this->invoice->user_id; $result = $this->plugin->doBill($this->invoice, true, $echeck); if ($result->isSuccess()) { if (($this->invoice->rebill_times > 0) && !$echeck->pk()) $this->plugin->storeEcheck($echeck, new Am_Paysystem_Result); $this->redirectLocation($this->plugin->getReturnUrl()); return true; } elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) { $result->getAction()->process($this); // throws Am_Exception_Redirect (!) } else { $this->view->error = $result->getErrorMessages(); } } public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } public function echeckAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); if ($this->form->isSubmitted() && $this->form->validate() && $this->processEcheck()) return; $this->view->form = $this->form; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $this->view->display('echeck/info.phtml'); } public function createForm() { $form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser())) )); $form->addHidden(Am_Controller::ACTION_KEY)->setValue($this->_request->getActionName()); $form->addHidden('id')->setValue($this->getFiltered('id')); return $form; } public function preDispatch() { if (!$this->plugin) throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__); } public function createUpdateForm() { $form = new Am_Form_Echeck($this->plugin, Am_Form_CreditCard::USER_UPDATE); $user = $this->getDi()->auth->getUser(true); if (!$user) throw new Am_Exception_InputError("You are not logged-in"); $echeck = $this->getDi()->echeckRecordTable->findFirstByUserId($user->user_id); if (!$echeck) $echeck = $this->getDi()->echeckRecordRecord; $arr = $echeck->toArray(); unset($arr['echeck_ban']); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($arr) )); return $form; } public function updateAction() { $this->form = $this->createUpdateForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $echeck = $this->getDi()->echeckRecord; $this->form->toEcheckRecord($echeck); $echeck->user_id = $this->getDi()->auth->getUserId(); $result = new Am_Paysystem_Result(); $this->plugin->storeEcheck($echeck, $result); if ($result->isSuccess()) { return $this->redirectLocation(REL_ROOT_URL . '/member'); } else { $this->form->getElementById('echeck_ban-0')->setError($result->getLastError()); } } $this->view->form = $this->form; $this->view->invoice = null; $this->view->display_receipt = false; $this->view->display('echeck/info.phtml'); } } PK\'cc/library/Am/Controller/CreditCard.phpnu[plugin = $plugin; } /** * Process the validated form and if ok, display thanks page, * if not ok, return false */ public function processCc() { $cc = $this->getDi()->ccRecordRecord; $this->form->toCcRecord($cc); $cc->user_id = $this->invoice->user_id; if($this->plugin->getConfig('use_maxmind')) { $checkresult = $this->plugin->doMaxmindCheck($this->invoice, $cc); if (!$checkresult->isSuccess()) { $this->view->error = $checkresult->getErrorMessages(); return; } } $result = $this->plugin->doBill($this->invoice, true, $cc); if ($result->isSuccess()) { if (($this->invoice->rebill_times > 0) && !$cc->pk()) $this->plugin->storeCreditCard($cc, new Am_Paysystem_Result); $this->redirectLocation($this->plugin->getReturnUrl()); return true; } elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) { $result->getAction()->process($this); // throws Am_Exception_Redirect (!) } else { $this->view->error = $result->getErrorMessages(); } } public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } public function ccAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); $this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form)); if ($this->form->isSubmitted() && $this->form->validate()) { if ($this->processCc()) return; } $this->view->form = $this->form; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $this->view->display('cc/info.phtml'); } public function createForm() { $form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser())) )); $form->addHidden(Am_Controller::ACTION_KEY)->setValue($this->_request->getActionName()); $form->addHidden('id')->setValue($this->getFiltered('id')); return $form; } public function preDispatch() { if (!$this->plugin) throw new Am_Exception_InternalError("Payment plugin is not passed to " . __CLASS__); } public function createUpdateForm() { $form = new Am_Form_CreditCard($this->plugin, Am_Form_CreditCard::USER_UPDATE); $user = $this->getDi()->auth->getUser(true); if (!$user) throw new Am_Exception_InputError("You are not logged-in"); $cc = $this->getDi()->ccRecordTable->findFirstByUserId($user->user_id); if (!$cc) $cc = $this->getDi()->ccRecordRecord; $arr = $cc->toArray(); unset($arr['cc_number']); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($arr) )); return $form; } public function updateAction() { $this->form = $this->createUpdateForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $cc = $this->getDi()->ccRecordRecord; $this->form->toCcRecord($cc); $cc->user_id = $this->getDi()->auth->getUserId(); $result = new Am_Paysystem_Result(); $this->plugin->storeCreditCard($cc, $result); if ($result->isSuccess()) { return $this->redirectLocation(REL_ROOT_URL . '/member'); } else { $this->form->getElementById('cc_number-0')->setError($result->getLastError()); } } $this->view->form = $this->form; $this->view->invoice = null; $this->view->display_receipt = false; $this->view->display('cc/info.phtml'); } } PK\Wmu u cc/library/CcRecord.phpnu[_cc_code; } function setCvv($code) { $this->_cc_code = filterId($code); } function maskCc($number) { $number = preg_replace('/\D+/', '', $number); if (strlen($number)<8) return '****************'; return str_repeat('*', strlen($number)-4) . substr($number, -4, 4); } function toRow() { $arr = parent::toRow(); // fields to encrypt if (isset($arr['cc_number'])) { $arr['cc_number'] = preg_replace('/\D+/', '', $arr['cc_number']); if (empty($arr['cc']) || ($arr['cc_number'] != '0000000000000000')) $arr['cc'] = $this->maskCc($arr['cc_number']); } foreach ($this->_encryptedFields as $f) if (array_key_exists($f, $arr)) $arr[$f] = $this->_table->encrypt($arr[$f]); return $arr; } public function fromRow(array $arr) { // fields to decrypt foreach ($this->_encryptedFields as $f) if (array_key_exists($f, $arr)) $arr[$f] = $this->_table->decrypt($arr[$f]); return parent::fromRow($arr); } /** * Delete existing record for this user_id, then insert this one * @return CcRecord provides fluent interface */ function replace() { if (empty($this->user_id) || $this->user_id <= 0) throw new Am_Exception_InternalError("this->user_id is empty in " . __METHOD__); $this->_table->deleteByUserId($this->user_id); return $this->insert(); } function getExpire($format = "%02d%02d") { if ("" == $this->cc_expire) return ""; $m = substr($this->cc_expire, 0, 2); $y = substr($this->cc_expire, 2, 2); return sprintf($format, $m, $y); } } class CcRecordTable extends Am_Table { protected $_crypt; protected $_key = 'cc_id'; protected $_table = '?_cc'; protected $_recordClass = 'CcRecord'; function encrypt($s){ return $this->_getCrypt()->encrypt($s); } function decrypt($s){ return $this->_getCrypt()->decrypt($s); } function _getCrypt(){ if (empty($this->_crypt)) $this->_crypt = Am_Di::getInstance ()->crypt; return $this->_crypt; } function setCrypt(Am_Crypt $crypt) { $this->_crypt = $crypt; } } PK\Wt t cc/email-templates.xmlnu[ cc.admin_rebill_stats 2 en text %site_title%: %plugin% Rebill Statistics (%short_stats%) Outlined below are the results of latest rebilling attempt on %site_title% Here you can find statistics about SUCCESS rebills === %rebills_success% Here you can find statistics about FAILED rebills === %rebills_failed% cc.rebill_failed 1 en text %site_title%: Subscription Renewal Failed Your subscription was not renewed automatically by membership system due to payment failure: %error% %prorate% You may update your credit card info here:. %root_url%/member Thank you for attention! cc.rebill_success 1 en text %site_title%: Subscription Renewed Your subscription has been renewed automatically by our membership system. Your credit card was charged %amount% Next renewal date: %rebill_date% You may login to membership info page at : %root_url%/member cc.card_expire 1 en text %site_title%: Credit Card Expiration Your credit card that we have on file for recurring billing will expire on %expires%. Next recurring billing for invoice %invoice.public_id% is sheduled for %invoice.rebill_date|date%. To avoid any interruption of your subscription, please visit page %root_url%/member and update your credit card information. PK\(""cc/Bootstrap.phpnu[getDi()->plugins_payment->addPath(dirname(__FILE__) . '/plugins'); } function onSetupEmailTemplateTypes(Am_Event $event) { $event->addReturn(array( 'id' => 'cc.admin_rebill_stats', 'title' => 'Cc Rebill Rebill Stats', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'isAdmin' => true, ), 'cc.admin_rebill_stats'); $event->addReturn(array( 'id' => 'cc.rebill_failed', 'title' => 'Cc Rebill Failed', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'vars' => array('user'), ), 'cc.rebill_failed'); $event->addReturn(array( 'id' => 'cc.rebill_failed_admin', 'title' => 'Cc Rebill Failed Admin', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'isAdmin' => true, 'vars' => array('user'), ), 'cc.rebill_failed_admin'); $event->addReturn(array( 'id' => 'cc.rebill_success', 'title' => 'Cc Rebill Success', 'mailPeriodic' => Am_Mail::USER_REQUESTED, 'vars' => array('user'), ), 'cc.rebill_success'); } public function onAdminWarnings(Am_Event $event) { $plugins = $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $key_pl = ''; foreach($plugins as $pl) if($pl instanceof Am_Paysystem_CreditCard) $key_pl = $pl->getId(); $setupUrl = $this->getDi()->url('admin-setup'); ///check for configuration problems if (class_exists('Am_Paysystem_CreditCard', false)) { if(!$this->getDi()->config->get('use_cron')) { $event->addReturn(___('%sEnable%s and %sconfigure%s external cron if you are using credit card payment plugins', '', '', '', '')); } try { $crypt = $this->getDi()->crypt; } catch (Am_Exception_Crypt_Key $e) { if($key_pl) $event->addReturn("Encryption subsystem error: " . '' . $e->getMessage(). ''); else $event->addReturn("Encryption subsystem error: " . $e->getMessage()); } catch (Am_Exception_Crypt $e) { $event->addReturn("Encryption subsystem error: " . $e->getMessage()); } } } public function onHourly(Am_Event $event) { foreach ($this->getPlugins() as $ps) $ps->ccRebill($this->getDi()->sqlDate); } /** @return array of Am_Paysystem_CreditCard */ public function getPlugins() { $this->getDi()->plugins_payment->loadEnabled(); $ret = array(); foreach ($this->getDi()->plugins_payment->getAllEnabled() as $ps) if ($ps instanceof Am_Paysystem_CreditCard || $ps instanceof Am_Paysystem_Echeck) $ret[] = $ps; return $ret; } public function onUserAfterDelete(Am_Event_UserAfterDelete $event) { $this->getDi()->ccRecordTable->deleteByUserId($event->getUser()->pk()); $this->getDi()->echeckRecordTable->deleteByUserId($event->getUser()->pk()); } function onUserTabs(Am_Event_UserTabs $event) { if ($event->getUserId() > 0) { $event->getTabs()->addPage(array( 'id' => 'cc', 'module' => 'cc', 'controller' => 'admin', 'action' => 'info-tab', 'params' => array( 'user_id' => $event->getUserId(), ), 'label' => ___('Credit Cards'), 'order' => 900, 'resource' => 'cc', )); foreach ($this->getPlugins() as $ps) { if($ps instanceof Am_Paysystem_Echeck) { $event->getTabs()->addPage(array( 'id' => 'cc', 'module' => 'cc', 'controller' => 'admin', 'action' => 'info-tab-echeck', 'params' => array( 'user_id' => $event->getUserId(), ), 'label' => ___('Echeck'), 'order' => 901, 'resource' => 'cc', )); break; } } } } function onAdminMenu(Am_Event $event) { $parent = $event->getMenu()->findBy('id', 'utilites'); if (!$parent) $parent = $event->getMenu(); $parent->addPage(array( 'id' => 'ccrebills', 'module' => 'cc', 'controller' => 'admin-rebills', 'label' => ___('Credit Card Rebills'), 'resource' => 'cc', )); /* disabled until real-life tested if (count($this->getPlugins()) > 1) { $parent->addPage(array( 'id' => 'cc-change', 'module' => 'cc', 'controller' => 'admin', 'action' => 'change-paysys', 'label' => 'Change Paysystem', )); } * */ } function onGetPermissionsList(Am_Event $event) { $event->addReturn(___("Can view/edit customer Credit Card information and rebills"), 'cc'); } function onGetMemberLinks(Am_Event $event) { $user = $event->getUser(); if ($user->status == User::STATUS_PENDING) return ; foreach ($this->getPlugins() as $pl) { if($pl instanceof Am_Paysystem_CreditCard && ($link = $pl->getUpdateCcLink($user))) $event->addReturn(___("Update Credit Card Info"), $link); elseif($pl instanceof Am_Paysystem_Echeck && ($link = $pl->getUpdateEcheckLink($user))) $event->addReturn(___("Update Echeck Info"), $link); } } } PK\dR cc/module.xmlnu[ cc Credit Card Billing This module provides ability to bill credit cards directly on your website 4.7.0 PK\sQ$Q$)cc/controllers/AdminConvertController.phpnu[isSuper(); } /** * * @return Am_Crypt */ function getCurrentCryptObject() { $cname = $this->getDi()->getCryptClass(); return (new $cname); } /** * * @return Am_Crypt */ function getOldCryptObject() { $crypt = $this->getCurrentCryptObject(); $oldCrypt = $crypt; $oldSig = $oldCrypt->loadKeySignature(); $cname = Am_Crypt::getClassByMethod($oldSig); if (get_class($oldCrypt) != $cname) { $oldCrypt = new $cname; } if ($oldCrypt->getKeySignature() != $oldSig) { // Now try to load old key file; $path = APPLICATION_PATH . '/configs/key-old.php'; if (!file_exists($path)) throw new Am_Exception_Crypt_Key(___('Unable to find old keyfile. ' . 'Please upload it to %s ' . 'Then refresh page', $path)); // @todo comment $key = include $path; if (!strlen($key)) throw new Am_Exception_Crypt_Key('Key file has incorrect format or the key is empty'); // @todo comment if ($key == 'REPLACE THIS STRING TO YOUR KEYSTRING') throw new Am_Exception_Crypt_Key("You must define a valid key in the file [$path] instead of default"); $oldCrypt = new $cname($key); } return $oldCrypt; } function createBackup() { try { $this->getDi()->db->query("CREATE TABLE ?_cc_backup LIKE ?_cc"); $this->getDi()->db->query("INSERT INTO ?_cc_backup SELECT * FROM ?_cc"); $this->getDi()->db->query("CREATE TABLE ?_config_backup LIKE ?_config"); $this->getDi()->db->query("INSERT INTO ?_config_backup SELECT * FROM ?_config"); } catch (Exception $ex) { $this->getDi()->errorLogTable->logException($ex); throw new Am_Exception_InputError( ___('Unable to backup cc and config tables. ' . 'Check "aMember CP -> Error Log" for more info', $this->getDi()->url('admin-logs')) ); } } function dropBackup() { try { $this->getDi()->db->query('DROP TABLE ?_config_backup'); $this->getDi()->db->query('DROP TABLE ?_cc_backup'); } catch (Exception $ex) { $this->getDi()->errorLogTable->logException($ex); throw new Am_Exception_InputError( ___('Unable to delete backup tables. ' . 'Please delete cc_backup and config_backup tables manually ' . 'Check "aMember CP -> Error Log" for more info ', $this->getDi()->url('admin-logs')) ); } } function restoreBackup() { try { $this->getDi()->db->query('TRUNCATE TABLE ?_config'); $this->getDi()->db->query("INSERT INTO ?_config SELECT * FROM ?_config_backup"); $this->getDi()->db->query('TRUNCATE TABLE ?_cc'); $this->getDi()->db->query("INSERT INTO ?_cc SELECT * FROM ?_cc_backup"); } catch (Exception $ex) { $this->getDi()->errorLogTable->logException($ex); throw new Am_Exception_InputError( ___('Unable to restore back in cc_backup and config_backup tables' . 'Please restore it manually. ' . 'Check "aMember CP -> Error Log" for more info ', $this->getDi()->url('admin-logs')) ); } } function indexAction() { $crypt = $this->getCurrentCryptObject(); $oldCrypt = $this->getOldCryptObject(); $this->view->title = "Convert CC Database"; $startUrl = $this->getDi()->url('cc/admin-convert/do'); if (get_class($oldCrypt) != get_class($crypt)) { $this->view->content = << Encryption method was changed. You have to encrypt database using new encryption method.
      You must backup your database before you'll run this tool. GGI-Central is not responsible for any damage this script may result to. If you have no backup saved, you may loose your data.
      Make backup first, then return to this page.

      CUT1; } else if ($crypt->getKeySignature() != $crypt->loadKeySignature()) { $path = $path = APPLICATION_PATH . '/configs/key-old.php'; $this->view->content = << Encryption key file was changed. Please upload old key file to {$path} and re-encrypt CC table.
      You must backup your database before you'll run this tool. GGI-Central is not responsible for any damage this script may result to. If you have no backup saved, you may loose your data.
      Make backup first, then return to this page.

      CUT2; } else { $this->view->content = <<Key signature stored in database and key signature that was generated are equal. No further actions are required. CUT; } $this->view->display('admin/layout.phtml'); } function doAction() { $this->crypt = $this->getCurrentCryptObject(); $this->oldCrypt = $this->getOldCryptObject(); $this->context = $this->getParam('context'); if (!$this->context) $this->createBackup(); $batch = new Am_BatchProcessor(array($this, 'doWork')); $breaked = !$batch->run($this->context); $breaked ? $this->convertRedirect() : $this->convertComplete(); } function doWork(& $context, Am_BatchProcessor $batch) { $db = $this->getDi()->db; try { $this->done = $db->selectCell("select count(*) from ?_cc where cc_idtotal = $db->selectCell("select count(*) from ?_cc"); $q = $db->queryResultOnly("SELECT * FROM ?_cc WHERE cc_id > ?d", (int) $context); while ($r = $db->fetchRow($q)) { $context = $r['cc_id']; $ccRecord = $this->getDi()->CcRecordRecord; $ccRecord->getTable()->setCrypt($this->oldCrypt); $ccRecord->fromRow($r); if (preg_match('/[^\s\d-]/', $ccRecord->cc_number)) { throw new Am_Exception_InternalError( "Problem with converting to new encryption key. " . "cc record# {$ccRecord->cc_id} could not be converted, " . "it seems the old key has been specified incorrectly. Conversion cancelled."); return; } $ccRecord->getTable()->setCrypt($this->crypt); $ccRecord->update(); $this->done++; if (!$batch->checkLimits()) return; } } catch (Exception $ex) { $this->getDi()->errorLogTable->logException($ex); $this->restoreBackup(); $this->dropBackup(); throw new Am_Exception_InputError( ___('Got an error when attempting to re-encode CC record. ' . 'CC and config tables were restored from backup. ' . 'Check "aMember CP -> Error Log" for more info ', $this->getDi()->url('admin-logs')) ); } return true; } function convertRedirect() { $done = $this->done; $total = $this->total; $url = $this->getUrl('admin-convert', 'do', 'cc', array('context' => $this->context)); $text = $total > 0 ? (___('Converting CC info (%d from %d)', $done, $total) . '. ' . ___('Please wait')) : ___('Converting started'); $text .= '...'; $this->redirectHtml($url, $text, ___('Converting') . '...', false, $done, $total); } function convertComplete() { $this->crypt->saveKeySigunature(); $this->view->assign('title', ___('Done')); ob_start(); print '
      '; print 'Records were re-encoded using new key/encryption method'; print '. '; $url = $this->getUrl('admin-convert', 'index', 'cc'); print '' . ___('Back') . '
      '; $this->view->assign('content', ob_get_clean()); $this->view->display('admin/layout.phtml'); $this->getDi()->db->query("OPTIMIZE TABLE ?_cc"); $this->dropBackup(); } } PK\h*0*0)cc/controllers/AdminRebillsController.phpnu[hasPermission('cc'); } public function init() { parent::init(); $this->view->headScript()->appendScript($this->getJs()); $this->view->placeholder('after-content')->append( ""); } public function renderStatus($obj, $fieldname, $grid, $field) { return $obj->{$fieldname} ? $this->renderTd(sprintf('%d - %s', $obj->{$fieldname}, Am_Currency::render($obj->{$fieldname . '_amt'})), false) : $this->renderTd(''); } protected function createAdapter() { $q = new Am_Query($this->getDi()->ccRebillTable); $q->leftJoin('?_invoice', 'i', 't.invoice_id=i.invoice_id'); $q->clearFields(); $q->groupBy('rebill_date'); $q->addField('t.rebill_date'); $q->addField('(1)', 'is_log'); $q->addField('COUNT(t.rebill_date)', 'total'); $q->addField('SUM(i.second_total/i.base_currency_multi)', 'total_amt'); $q->addField('SUM(IF(t.status=0, 1, 0))', 'status_0'); $q->addField('SUM(IF(t.status=1, 1, 0))', 'status_1'); $q->addField('SUM(IF(t.status=2, 1, 0))', 'status_2'); $q->addField('SUM(IF(t.status=3, 1, 0))', 'status_3'); $q->addField('SUM(IF(t.status=4, 1, 0))', 'status_4'); $q->addField('SUM(IF(t.status=0, i.second_total/i.base_currency_multi, 0))', 'status_0_amt'); $q->addField('SUM(IF(t.status=1, i.second_total/i.base_currency_multi, 0))', 'status_1_amt'); $q->addField('SUM(IF(t.status=2, i.second_total/i.base_currency_multi, 0))', 'status_2_amt'); $q->addField('SUM(IF(t.status=3, i.second_total/i.base_currency_multi, 0))', 'status_3_amt'); $q->addField('SUM(IF(t.status=4, i.second_total/i.base_currency_multi, 0))', 'status_4_amt'); $u = new Am_Query($this->getDi()->invoiceTable, 'i'); $u->addWhere('i.paysys_id IN (?a)', array_merge(array('avoid-sql-error'), $this->getPlugins())); $u->groupBy('rebill_date'); $u->clearFields()->addField('i.rebill_date'); $u->addField('(0)', 'is_log'); $u->addField('COUNT(i.invoice_id)', 'total'); $u->addField('SUM(i.second_total/i.base_currency_multi)', 'total_amt'); for ($i = 1; $i < 11; $i++) $u->addField('(NULL)'); $u->leftJoin('?_cc_rebill', 't', 't.rebill_date=i.rebill_date'); $u->addWhere('i.rebill_date IS NOT NULL'); $u->addWhere('t.rebill_date IS NULL'); $q->addUnion($u); $q->addOrder('rebill_date', true); return $q; } public function createGrid() { $grid = new Am_Grid_ReadOnly('_r', 'Rebills by Date', $this->createAdapter(), $this->_request, $this->view); $grid->setPermissionId('cc'); $grid->addField('rebill_date', 'Date')->setRenderFunction(array($this, 'renderDate')); $grid->addField('status_0', 'Processing Not Finished')->setRenderFunction(array($this, 'renderStatus')); $grid->addField('status_1', 'No CC Saved')->setRenderFunction(array($this, 'renderStatus')); $grid->addField('status_2', 'Error')->setRenderFunction(array($this, 'renderStatus')); $grid->addField('status_3', 'Success')->setRenderFunction(array($this, 'renderStatus')); $grid->addField('status_4', 'Exception!')->setRenderFunction(array($this, 'renderStatus')); $grid->addField('total', 'Total')->setRenderFunction(array($this, 'renderTotal')); $grid->addField('_action', '')->setRenderFunction(array($this, 'renderLink')); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this, 'getTrAttribs')); return $grid; } public function getPlugins() { $this->getDi()->plugins_payment->loadEnabled(); $ret = array(); foreach ($this->getDi()->plugins_payment->getAllEnabled() as $ps) if ($ps instanceof Am_Paysystem_CreditCard || $ps instanceof Am_Paysystem_Echeck) $ret[] = $ps->getId(); return $ret; } public function renderDate(CcRebill $obj) { $raw = $obj->rebill_date; $d = amDate($raw); return $this->renderTd("$d", false); } public function getTrAttribs(& $ret, $record) { if ($record->rebill_date > sqlDate('now')) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } public function renderTotal(CcRebill $obj) { if ($obj->is_log) { return $this->renderTd(sprintf('%d - %s', $obj->total, Am_Currency::render($obj->total_amt)), false); } else { $url = $this->getDi()->url('default/admin-payments/p/invoices/index' , array( '_invoice_filter' => array( 'datf' => 'rebill_date', 'dat1' => amDate($obj->rebill_date), 'dat2' => amDate($obj->rebill_date) ), '_invoice_sort' => 'rebill_date' )); return $this->renderTd(sprintf('%d - %s', $url, $obj->total, Am_Currency::render($obj->total_amt)), false); } } public function renderLink(CcRebill $obj) { $linkRun = $linkDetail = ''; if ($obj->rebill_date <= sqlDate('now')) { if ($obj->status_3 < $obj->total) { $iconRun = $this->getDi()->view->icon('retry', ___('Run')); $back_url = $this->grid->makeUrl(); $linkRun = "$iconRun"; } if ($obj->is_log) { $iconDetail = $this->getDi()->view->icon('view', ___('Details')); $linkDetail = "$iconDetail"; } } return "$linkRun $linkDetail"; } public function renderInvoiceLink($record) { return 'user_id . "#invoice-" . $record->invoice_id) . '" target=_top >' . $record->invoice_id . '/' . $record->public_id . ''; } public function getJs() { $title = ___('Run Rebill Manually'); $title_details = ___('Details'); return <<'); div.load(amUrl("/cc/admin-rebills/detail?_r_d_date=") + date , function(){ div.dialog({ autoOpen: true ,width: 800 ,buttons: {} ,closeOnEscape: true ,title: "$title_details" ,modal: true ,open: function(){ div.ngrid(); } }); }); }); }); jQuery(function(){ jQuery(document).on('submit',"#run-form form", function(){ jQuery(this).ajaxSubmit({target: '#run-form'}); return false; }); }); CUT; } public function createRunForm() { $form = new Am_Form; $form->setAction($this->getUrl(null, 'run')); $s = $form->addSelect('paysys_id')->setLabel(___('Choose a plugin')); $s->addRule('required'); foreach ($this->getModule()->getPlugins() as $p) $s->addOption($p->getTitle(), $p->getId()); $form->addDate('date')->setLabel(___('Run Rebill Manually'))->addRule('required'); $form->addHidden('back_url'); $form->addSubmit('run', array('value' => ___('Run'))); return $form; } public function detailAction() { $date = $this->getFiltered('_r_d_date'); if (!$date) throw new Am_Exception_InputError('Wrong date'); $grid = $this->createDetailGrid($date); $grid->isAjax(false); $grid->runWithLayout('admin/layout.phtml'); } protected function createDetailGrid($date) { $q = new Am_Query($this->getDi()->ccRebillTable); $q->addWhere('t.rebill_date=?', $date); $q->leftJoin('?_invoice', 'i', 'i.invoice_id=t.invoice_id'); $q->leftJoin('?_user', 'u', 'u.user_id=i.user_id'); $q->addField('i.public_id'); $q->addField('u.name_f'); $q->addField('u.name_l'); $q->addField('u.email'); $q->addField('i.user_id'); $q->addField('i.second_total'); $q->addField('i.currency'); $grid = new Am_Grid_ReadOnly('_r_d', ___('Detailed Rebill Report for %s', amDate($date)), $q, $this->_request, $this->view); $grid->setPermissionId('cc'); $grid->addField(new Am_Grid_Field_Date('tm_added', 'Started', true)); $grid->addField('invoice_id', 'Invoice#', true, '', array($this, 'renderInvoiceLink')); $grid->addField('user', 'User')->setRenderFunction(function($obj, $fieldname, $grid, $field){ return sprintf("%s %s (%s)>", $this->getDi()->url('admin-users',array('_u_a'=>'edit','_u_id'=>$obj->user_id)), $obj->name_f, $obj->name_l, $obj->email); }); $grid->addField('paysys_id', ___('Payment System')); $grid->addField('second_total', ___('Amount'))->setRenderFunction(function($obj, $fieldname, $grid, $field){ return $grid->renderTd(Am_Currency::render($obj->second_total, $obj->currency), false); }); $grid->addField(new Am_Grid_Field_Date('rebill_date', 'Date', true))->setFormatDate(); $grid->addField('status', 'Status', true)->setFormatFunction(array('CcRebill', 'getStatusText')); $grid->addField('status_msg', 'Message'); $grid->setCountPerPage(10); return $grid; } public function runAction() { $date = $this->getFiltered('date'); if (!$date) throw new Am_Exception_InputError("Wrong date"); $form = $this->createRunForm(); if ($form->isSubmitted() && $form->validate()) { $value = $form->getValue(); $this->doRun($value['paysys_id'], $value['date']); echo sprintf('
      %s
      ', ___('Rebill Operation Completed for %s', amDate($value['date']))); } else { echo $form; } } public function doRun($paysys_id, $date) { $this->getDi()->plugins_payment->load($paysys_id); $p = $this->getDi()->plugins_payment->get($paysys_id); // Delete all previous failed attempts for this date in order to rebill these invoices again. $this->getDi()->db->query(" DELETE FROM ?_cc_rebill WHERE rebill_date = ? AND paysys_id = ? AND status <> ? ", $date, $paysys_id, ccRebill::SUCCESS); $p->ccRebill($date); } }PK\R?ff"cc/controllers/AdminController.phpnu[hasPermission('cc'); } function infoTabAction() { require_once AM_APPLICATION_PATH . '/default/controllers/AdminUsersController.php'; $this->setActiveMenu('users-browse'); $user_id = $this->_request->getInt('user_id'); if (!$user_id) throw Am_Exception_InputError("Empty [user_id] passsed"); $cc = $this->getDi()->ccRecordTable->findFirstByUserId($user_id); /* @var $cc CcRecord */ $this->view->cc = $cc; $this->view->addUrl = $this->getUrl(null, null, null, 'user_id', $this->getInt('user_id'), array('add'=>1)); if ($cc || $this->_request->getInt('add') || $this->_request->get('_save_')) { $form = $this->createAdminForm((bool)$cc); if ($form) { if ($form->isSubmitted() && $form->validate()) { if (!$cc) $cc = $this->getDi()->ccRecordTable->createRecord(); $form->toCcRecord($cc); $cc->user_id = $user_id; $cc->save(); } elseif ($cc) { $arr = $cc->toArray(); unset($arr['cc_number']); $form->addDataSource(new HTML_QuickForm2_DataSource_Array($arr)); } $this->view->form = $form; $this->view->form->setAction($this->_request->getRequestUri()); } } $this->view->display('admin/cc/info-tab.phtml'); } function infoTabEcheckAction() { require_once AM_APPLICATION_PATH . '/default/controllers/AdminUsersController.php'; $this->setActiveMenu('users-browse'); $user_id = $this->_request->getInt('user_id'); if (!$user_id) throw Am_Exception_InputError("Empty [user_id] passsed"); $echeck = $this->getDi()->echeckRecordTable->findFirstByUserId($user_id); $this->view->echeck = $echeck; $this->view->addUrl = $this->getUrl(null, null, null, 'user_id', $this->getInt('user_id'), array('add'=>1)); if ($echeck || $this->_request->getInt('add') || $this->_request->get('_save_')) { $form = $this->createEcheckAdminForm((bool)$echeck); if ($form) { if ($form->isSubmitted() && $form->validate()) { if (!$echeck) $echeck = $this->getDi()->echeckRecordTable->createRecord(); $form->toEcheckRecord($echeck); $echeck->user_id = $user_id; $echeck->save(); $this->_response->redirectLocation($this->_request->getRequestUri()); } elseif ($echeck) { $arr = $echeck->toArray(); unset($arr['echeck_ban']); $form->addDataSource(new HTML_QuickForm2_DataSource_Array($arr)); } $this->view->form = $form; $this->view->form->setAction($this->_request->getRequestUri()); } } $this->view->display('admin/echeck/info-tab.phtml'); // ???? } function createAdminForm($isUpdate) { $form = null; foreach ($this->getDi()->modules->get('cc')->getPlugins() as $ps) { if($ps instanceof Am_Paysystem_CreditCard) { $form = new Am_Form_CreditCard($ps, $isUpdate ? Am_Form_CreditCard::ADMIN_UPDATE : Am_Form_CreditCard::ADMIN_INSERT ); break; // first one } } return $form; } function createEcheckAdminForm($isUpdate) { $form = null; foreach ($this->getDi()->modules->get('cc')->getPlugins() as $ps) { if($ps instanceof Am_Paysystem_Echeck) { $form = new Am_Form_Echeck($ps, $isUpdate ? Am_Form_Echeck::ADMIN_UPDATE : Am_Form_Echeck::ADMIN_INSERT ); break; // first one } } return $form; } function changePaysysAction() { $form = new Am_Form_Admin; $form->setDataSources(array($this->_request)); $form->addStatic()->setContent(___( 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.')); $ccPlugins = $echeckPlugins = array(); foreach ($this->getModule()->getPlugins() as $ps) { if($ps instanceof Am_Paysystem_CreditCard) $ccPlugins[$ps->getId()] = $ps->getTitle(); elseif($ps instanceof Am_Paysystem_Echeck) $echeckPlugins[$ps->getId()] = $ps->getTitle(); } if(count($ccPlugins) < 2) $ccPlugins = array(); if(count($echeckPlugins) < 2) $echeckPlugins = array(); $options = array('' => '-- ' . ___('Please select') . ' --') + ($ccPlugins ? array(___('Credit Card Plugins') => $ccPlugins) : array()) + ($echeckPlugins ? array(___('Echeck Plugins') => $echeckPlugins) : array()); $from = $form->addSelect('from', array('id' => 'paysys_from'))->setLabel('Move Active Invoices From')->loadOptions($options); $from->addRule('required'); $to = $form->addSelect('to', array('id' => 'paysys_to'))->setLabel('Move To')->loadOptions($options); $to->addRule('required'); $to->addRule('neq', ___('Values must not be equal'), $from); $form->addScript() ->setScript(<<addSaveButton(); if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); $updated = $this->getDi()->db->query("UPDATE ?_invoice SET paysys_id=? WHERE paysys_id=? AND status IN (?a)", $vars['to'], $vars['from'], array(Invoice::RECURRING_ACTIVE)); $this->view->content = "$updated rows changed. New rebills for these invoices will be handled with [{$vars['to']}]"; } else { $this->view->content = (string)$form; } $this->view->title = ___("Change Paysystem"); $this->view->display('admin/layout.phtml'); } } PK\QF00cc/plugins/targetpay-wap.phpnu[addInteger("rtlo", array('maxlength' => 15, 'size' => 15)) ->setLabel("Subaccount (rtlo)") ->addRule('required'); $form->addInteger("service", array('maxlength' => 15, 'size' => 15)) ->setLabel("The ID of your service") ->addRule('required'); } public function isConfigured() { return strlen($this->getConfig('service')) && strlen($this->getConfig('rtlo')); } public function getSupportedCurrencies() { return array('EUR'); } public function storesCcInfo() { return false; } public function getRecurringType() { return self::REPORTS_CRONREBILL; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'ipn') { try { parent::directAction($request, $response, $invokeArgs); } catch (Exception $ex) { $this->getDi()->errorLogTable->logException($ex); } echo '45000'; } else parent::directAction($request, $response, $invokeArgs); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $req = new Am_HttpRequest(self::LIVE_URL_START, Am_HttpRequest::METHOD_POST); $req->addPostParameter(array( 'service' => $this->getConfig('service'), 'ip' => $user->remote_addr ? $user->remote_addr : $_SERVER['REMOTE_ADDR'], 'amount' => $invoice->first_total * 100, 'returnurl' => $this->getReturnUrl(), 'cancelurl' => $this->getCancelUrl(), 'autofirstbilling' => 1, 'pnotifyurl' => $this->getPluginUrl('ipn'), 'notifyurl' => $this->getPluginUrl('ipn'), )); $tr = new Am_Paysystem_Transaction_TargetpayWap_GetOrderUrl($this, $invoice, $req, true); $res = new Am_Paysystem_Result(); $tr->run($res); if (!($url = $tr->getUniqId())) throw new Am_Exception_Paysystem("Could not get order url - [" . $tr->getErrorDescription() . "]"); $a = new Am_Paysystem_Action_Form($url); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_TargetpayWap($this, $request, $response, $invokeArgs); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if (!($trxid = $invoice->getUser()->data()->get(self::INVOICE_TRANSACTION_ID))) throw new Am_Exception_Paysystem("Stored targetpay-wap trxid not found"); $request = new Am_HttpRequest(self::LIVE_URL_FOLLOWUP, Am_HttpRequest::METHOD_POST); $request->addPostParameter(array( 'trxid' => $trxid, 'service' => $this->getConfig('service'), 'amount' => $invoice->second_total * 100, 'rtlo' => $this->getConfig('rtlo'), 'description' => $invoice->getLineDescription(), )); $tr = new Am_paysystem_Transaction_TargetpayWap_Charge($this, $invoice, $request, $doFirst); $tr->run($result); } } class Am_Paysystem_Transaction_TargetpayWap extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { if ($invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByData(Am_Paysystem_TargetpayWap::INVOICE_TRANSACTION_ID, $this->request->get('trxid'))) return $invoice->public_id; } public function getUniqId() { return $this->request->get('paymentid'); } public function validateSource() { return true; } public function validateStatus() { if($this->request->get('status') == 'closed') return true; return intval($this->request->get('errorcode', 0)) == 0; } public function validateTerms() { if($this->request->get('status') == 'closed') return true; return floatval($this->request->get('amount') / 100) == floatval($this->invoice->first_total); } public function processValidated() { if($this->request->get('status') == 'closed') { $this->invoice->setCancelled (); } else { $user = $this->invoice->getUser(); $user->data()->set(Am_Paysystem_TargetpayWap::INVOICE_TRANSACTION_ID, $this->request->get('trxid'))->update(); parent::processValidated(); } } } class Am_Paysystem_Transaction_TargetpayWap_GetOrderUrl extends Am_Paysystem_Transaction_CreditCard { public function getErrorDescription() { return $this->res; } public function getUniqId() { return $this->url; } public function parseResponse() { $this->res = $this->response->getBody(); } public function processValidated() { } public function validate() { $this->url = false; if ($this->response->getStatus() != 200) { $this->result->setFailed(___('Payment failed')); return; } list($code, $extra) = explode(" ", $this->res); if ($code != "000000") { $this->result->setFailed(___('Payment failed')); return; } list($transactionId, $orderUrl) = explode("|", $extra); $this->url = $orderUrl; $this->result->setSuccess($this); $this->invoice->data()->set(Am_Paysystem_TargetpayWap::INVOICE_TRANSACTION_ID, $transactionId)->update(); return true; } } class Am_paysystem_Transaction_TargetpayWap_Charge extends Am_Paysystem_Transaction_CreditCard { public function getUniqId() { return $this->payment_id; } public function parseResponse() { $this->res = $this->response->getBody(); } public function validate() { if ($this->response->getStatus() != 200) { $this->result->setFailed(___('Payment failed')); return; } list($code, $payment_id) = explode(" ", $this->res); if ($code != "000000") { $this->result->setFailed(___('Payment failed')); return; } $this->payment_id = $payment_id; $this->result->setSuccess($this); return true; } }PK\.ѭ+z+zcc/plugins/eway-rapid3.phpnu[ 'System Error', 'S5085' => 'Started 3dSecure', 'S5086' => 'Routed 3dSecure', 'S5087' => 'Completed 3dSecure', 'S5099' => 'Incomplete (Access Code in progress/incomplete)', 'V6000' => 'Validation error', 'V6001' => 'Invalid CustomerIP', 'V6002' => 'Invalid DeviceID', 'V6011' => 'Invalid Payment TotalAmount', 'V6012' => 'Invalid Payment InvoiceDescription', 'V6013' => 'Invalid Payment InvoiceNumber', 'V6014' => 'Invalid Payment InvoiceReference', 'V6015' => 'Invalid Payment CurrencyCode', 'V6016' => 'Payment Required', 'V6017' => 'Payment CurrencyCode Required', 'V6018' => 'Unknown Payment CurrencyCode', 'V6021' => 'EWAY_CARDHOLDERNAME Required', 'V6022' => 'EWAY_CARDNUMBER Required', 'V6023' => 'EWAY_CARDCVN Required', 'V6033' => 'Invalid Expiry Date', 'V6034' => 'Invalid Issue Number', 'V6035' => 'Invalid Valid From Date', 'V6040' => 'Invalid TokenCustomerID', 'V6041' => 'Customer Required', 'V6042' => 'Customer FirstName Required', 'V6043' => 'Customer LastName Required', 'V6044' => 'Customer CountryCode Required', 'V6045' => 'Customer Title Required', 'V6046' => 'TokenCustomerID Required', 'V6047' => 'RedirectURL Required', 'V6051' => 'Invalid Customer FirstName', 'V6052' => 'Invalid Customer LastName', 'V6053' => 'Invalid Customer CountryCode', 'V6058' => 'Invalid Customer Title', 'V6059' => 'Invalid RedirectURL', 'V6060' => 'Invalid TokenCustomerID', 'V6061' => 'Invalid Customer Reference', 'V6062' => 'Invalid Customer CompanyName', 'V6063' => 'Invalid Customer JobDescription', 'V6064' => 'Invalid Customer Street1', 'V6065' => 'Invalid Customer Street2', 'V6066' => 'Invalid Customer City', 'V6067' => 'Invalid Customer State', 'V6068' => 'Invalid Customer PostalCode', 'V6069' => 'Invalid Customer Email', 'V6070' => 'Invalid Customer Phone', 'V6071' => 'Invalid Customer Mobile', 'V6072' => 'Invalid Customer Comments', 'V6073' => 'Invalid Customer Fax', 'V6074' => 'Invalid Customer URL', 'V6075' => 'Invalid ShippingAddress FirstName', 'V6076' => 'Invalid ShippingAddress LastName', 'V6077' => 'Invalid ShippingAddress Street1', 'V6078' => 'Invalid ShippingAddress Street2', 'V6079' => 'Invalid ShippingAddress City', 'V6080' => 'Invalid ShippingAddress State', 'V6081' => 'Invalid ShippingAddress PostalCode', 'V6082' => 'Invalid ShippingAddress Email', 'V6083' => 'Invalid ShippingAddress Phone', 'V6084' => 'Invalid ShippingAddress Country', 'V6085' => 'Invalid ShippingAddress ShippingMethod', 'V6086' => 'Invalid ShippingAddress Fax', 'V6091' => 'Unknown Customer CountryCode', 'V6092' => 'Unknown ShippingAddress CountryCode', 'V6100' => 'Invalid EWAY_CARDNAME', 'V6101' => 'Invalid EWAY_CARDEXPIRYMONTH', 'V6102' => 'Invalid EWAY_CARDEXPIRYYEAR', 'V6103' => 'Invalid EWAY_CARDSTARTMONTH', 'V6104' => 'Invalid EWAY_CARDSTARTYEAR', 'V6105' => 'Invalid EWAY_CARDISSUENUMBER', 'V6106' => 'Invalid EWAY_CARDCVN', 'V6107' => 'Invalid EWAY_ACCESSCODE', 'V6108' => 'Invalid CustomerHostAddress', 'V6109' => 'Invalid UserAgent', 'V6110' => 'Invalid EWAY_CARDNUMBER' ); protected $responseCodesFailed = array( 'D4401' => 'Refer to Issuer', 'D4402' => 'Refer to Issuer, special', 'D4403' => 'No Merchant', 'D4404' => 'Pick Up Card', 'D4405' => 'Do Not Honour', 'D4406' => 'Errror', 'D4407' => 'Pick Up Card, Special', 'D4409' => 'Request In Progress', 'D4412' => 'Invalid Transaction', 'D4413' => 'Invalid Amount', 'D4414' => 'Invalid Card Number', 'D4415' => 'No Issuer', 'D4419' => 'Re-enter Last Transaction', 'D4421' => 'No Action Taken', 'D4422' => 'Suspected Malfunction', 'D4423' => 'Unacceptable Transaction Fee', 'D4425' => 'Unable to Locate Record On File', 'D4430' => 'Format Error', 'D4433' => 'Expired Card, Capture', 'D4434' => 'Suspected Fraud, Retain Card', 'D4435' => 'Card Acceptor, Contact Acquirer, Retain Card', 'D4436' => 'Restricted Card, Retain Card', 'D4437' => 'Contact Acquirer Security Department, Retain Card', 'D4438' => 'PIN Tries Exceeded, Capture', 'D4439' => 'No Credit Account', 'D4440' => 'Function Not Supported', 'D4441' => 'Lost Card', 'D4442' => 'No Universal Account', 'D4443' => 'Stolen Card', 'D4444' => 'No Investment Account', 'D4451' => 'Insufficient Funds', 'D4452' => 'No Cheque Account', 'D4453' => 'No Savings Account', 'D4454' => 'Expired Card', 'D4455' => 'Incorrect PIN', 'D4456' => 'No Card Record', 'D4457' => 'Function Not Permitted to Cardholder', 'D4458' => 'Function Not Permitted to Terminal', 'D4459' => 'Suspected Fraud', 'D4460' => 'Acceptor Contact Acquirer', 'D4461' => 'Exceeds Withdrawal Limit', 'D4462' => 'Restricted Card', 'D4463' => 'Security Violation', 'D4464' => 'Original Amount Incorrect', 'D4466' => 'Acceptor Contact Acquirer, Security', 'D4467' => 'Capture Card', 'D4475' => 'PIN Tries Exceeded', 'D4482' => 'CVV Validation Error', 'D4490' => 'Cut off In Progress', 'D4491' => 'Card Issuer Unavailable', 'D4492' => 'Unable To Route Transaction', 'D4493' => 'Cannot Complete, Violation Of The Law', 'D4494' => 'Duplicate Transaction', 'D4496' => 'System Error' ); protected $responseCodesBeagle = array( 'F7000' => 'Undefined Fraud Error', 'F7001' => 'Challenged Fraud', 'F7002' => 'Country Match Fraud', 'F7003' => 'High Risk Country Fraud', 'F7004' => 'Anonymous Proxy Fraud', 'F7005' => 'Transparent Proxy Fraud', 'F7006' => 'Free Email Fraud', 'F7007' => 'Inernational Transaction Fraud', 'F7008' => 'Risk Score Fraud', 'F7009' => 'Denied Fraud', 'F9010' => 'High Risk Billing Country', 'F9011' => 'High Risk Credit Card Country', 'F9012' => 'High Risk Customer IP Address', 'F9013' => 'High Risk Email Address', 'F9014' => 'High Risk Shipping Country', 'F9015' => 'Multiple card numbers for single email address', 'F9016' => 'Multiple card numbers for single location', 'F9017' => 'Multiple email addresses for single card number', 'F9018' => 'Multiple email addresses for single location', 'F9019' => 'Multiple locations for single card number', 'F9020' => 'Multiple locations for single email address', 'F9021' => 'Suspicious Customer First Name', 'F9022' => 'Suspicious Customer Last Name', 'F9023' => 'Transaction Declined', 'F9024' => 'Multiple transactions for same address with known credit card', 'F9025' => 'Multiple transactions for same address with new credit card', 'F9026' => 'Multiple transactions for same email with new credit card', 'F9027' => 'Multiple transactions for same email with known credit card', 'F9028' => 'Multiple transactions for new credit card', 'F9029' => 'Multiple transactions for known credi card', 'F9030' => 'Multiple transactions for same credit card', 'F9032' => 'Invalid Customer Last Name', 'F9033' => 'Invalid Billing Street', 'F9034' => 'Invalid Shipping Street' ); protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->setTitle('eWay Rapid 3.1'); } function storesCcInfo(){ return false; } protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_CreditCard_EwayRapid3($request, $response, $invokeArgs); } public function getErrorMessage($code) { $message = ''; if(!empty($this->messages[$code])) $message .= $this->messages[$code].", "; if(!empty($this->responseCodesFailed[$code])) $message .= $this->responseCodesFailed[$code]; if(!empty($this->responseCodesBeagle[$code])) $message .= $this->responseCodesBeagle[$code]; return $message; } public function createForm($actionName) { return new Am_Form_EwayRapid3($this); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'ipn') { $accessCode = $request->getFiltered('AccessCode'); $result = new Am_Paysystem_Result(); $transaction = new Am_Paysystem_Transaction_EwayRapid3($this, $accessCode); $transaction->run($result); if (!($invoice = $transaction->getInvoice())) throw new Am_Exception_InputError("Payment failed. Please contact webmaster for details."); $this->_setInvoice($invoice); if ($result->isSuccess()) { return $response->redirectLocation($this->getReturnUrl($invoice)); } else return $response->redirectLocation($this->getCancelUrl($invoice)); } else parent::directAction($request, $response, $invokeArgs); } public function getSupportedCurrencies() { return array('USD', 'CAD', 'GBP', 'EUR', 'AUD', 'NZD'); } public function getRecurringType() { return self::REPORTS_CRONREBILL; } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $transaction = new Am_Paysystem_Transaction_EwayRapid3_Recurring($this, $invoice, $doFirst); $transaction->run($result); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('apikey', 'size=40')->setLabel('Api Key')->addRule('required'); $form->addText('password', 'size=40')->setLabel('Api Password')->addRule('required'); $form->addText('customer_id', 'size=20') ->setLabel("Eway Customer ID\n" . 'Your unique 8 digit eWAY customer ID ' . 'assigned to you when you join eWAY ' . 'e.g. 1xxxxxxx.')->addRule('required'); $form->addText('customer_username', 'size=20') ->setLabel("Eway Username\n" . 'Your username which is used to ' . 'login to eWAY Business Center.')->addRule('required'); $form->addText('customer_password', 'size=20') ->setLabel("Eway Password\n" . 'Your password which is used to ' . 'login to eWAY Business Center.')->addRule('required'); $form->addAdvCheckbox('testing')->setLabel("Test Mode Enabled"); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $transaction = new Am_Paysystem_Transaction_Ewayrapid3_Refund($this, $payment->getInvoice(), $payment->transaction_id, $amount); $transaction->run($result); } } class Am_Paysystem_Transaction_EwayRapid3_Recurring extends Am_Paysystem_Transaction_CreditCard { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice) { parent::__construct($plugin, $invoice, $plugin->createHttpRequest(), $doFirst); $header[] = "Content-Type: text/xml"; $header[] = 'SOAPAction: "https://www.eway.com.au/gateway/managedpayment/ProcessPayment"'; $this->request->setHeader($header); $this->request->setBody($this->createXml($invoice, $doFirst)); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setUrl($this->plugin->getConfig('testing') ? Am_Paysystem_EwayRapid3::API_TOKEN_SANDBOX_URL : Am_Paysystem_EwayRapid3::API_TOKEN_URL); } protected function createXml(Invoice $invoice, $doFirst) { $request = << CUT; $x = new SimpleXMLElement($request); $ns = $x->getNamespaces(); $b = $x->children($ns['soap'])->Body; $bb = $b->addChild('ProcessPayment',"", 'https://www.eway.com.au/gateway/managedpayment'); $h = $x->children($ns['soap'])->Header; $hh = $h->addChild('eWAYHeader',"", 'https://www.eway.com.au/gateway/managedpayment'); $hh->addChild('eWAYCustomerID', $this->plugin->getConfig('customer_id')); $hh->addChild('Username', $this->plugin->getConfig('customer_username')); $hh->addChild('Password', $this->plugin->getConfig('customer_password')); $bb->addChild('managedCustomerID', $invoice->getUser()->data()->get(Am_Paysystem_EwayRapid3::TOKEN)); $bb->addChild('amount', $invoice->second_total*100); $bb->addChild('invoiceReference', $invoice->public_id."-".sprintf("%03d", $invoice->getPaymentsCount())); $bb->addChild('invoiceDescription', $invoice->getLineDescription()); $xml = $x->asXML(); return $xml; } public function getUniqId() { return (string)$this->parsedResponse->ewayTrxnNumber; } public function parseResponse() { $xml = simplexml_load_string($this->response->getBody()); $this->parsedResponse = $xml->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->children('https://www.eway.com.au/gateway/managedpayment')->ProcessPaymentResponse->ewayResponse; } public function validate() { if(strtolower((string)$this->parsedResponse->ewayTrxnStatus) !== 'true') { $message = ''; $errors = explode(",", $this->parsedResponse->ewayTrxnError); foreach($errors as $error) $message .= $this->plugin->getErrorMessage($error).", "; $this->result->setFailed("Internal plugin's errors: ".substr($message, 0, -2)); return; } $this->result->setSuccess($this); return true; } } class Am_Mvc_Controller_CreditCard_EwayRapid3 extends Am_Mvc_Controller_CreditCard { public function createForm() { $invoice = $this->invoice; $result = new Am_Paysystem_Result(); $transaction = new Am_Paysystem_Transaction_EwayRapid3_RequestFormActionUrl($this->plugin, $invoice); $transaction->run($result); if (!$result->isSuccess()) { throw new Am_Exception_InputError(___('Error happened during payment process')); } $response = $transaction->getResponse(); $form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser())) )); $form->addHidden(Am_Mvc_Controller::ACTION_KEY)->setValue($this->_request->getActionName()); $form->addHidden('EWAY_ACCESSCODE')->setValue((string) $response->AccessCode); $form->addHidden('EWAY_PAYMENTTYPE')->setValue('Credit Card'); $form->setAction((string) $response->FormActionURL); return $form; } } class Am_Paysystem_Transaction_EwayRapid3_RequestFormActionUrl extends Am_Paysystem_Transaction_CreditCard { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice) { parent::__construct($plugin, $invoice, $plugin->createHttpRequest(), true); $header[] = "Authorization: Basic " . base64_encode( $plugin->getConfig('apikey') . ':' . $plugin->getConfig('password')); $header[] = "Content-Type: text/xml"; $this->request->setHeader($header); $this->request->setBody($this->createXml($invoice)); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setUrl($this->plugin->getConfig('testing') ? Am_Paysystem_EwayRapid3::CREATE_ACCESS_CODE_SANDBOX_URL : Am_Paysystem_EwayRapid3::CREATE_ACCESS_CODE_URL); } public function getResponse() { return $this->xml; } public function getUniqId() { } public function parseResponse() { $this->xml = new SimpleXMLElement($this->response->getBody()); } protected function createXml(Invoice $invoice) { $user = $invoice->getUser(); $xml = new SimpleXMLElement(''); $xml->addChild('RedirectUrl', $this->plugin->getPluginUrl('ipn')); $xml->addChild('TransactionType', 'Purchase'); $xml->addChild('Method', 'TokenPayment'); $xml->addChild('Customer'); $xml->Customer->addChild('Reference', $user->user_id); $xml->Customer->addChild('FirstName', $user->name_f); $xml->Customer->addChild('LastName', $user->name_l); $xml->Customer->addChild('Street1', $user->street); $xml->Customer->addChild('City', $user->city); $xml->Customer->addChild('State', $user->state); $xml->Customer->addChild('PostalCode', $user->zip); $xml->Customer->addChild('Country', strtolower($user->country)); $xml->Customer->addChild('Email', $user->email); $xml->Customer->addChild('Phone', $user->phone); $xml->addChild('Items'); foreach ($invoice->getItems() as $item) { $xml->Items->addChild('LineItem'); $xml->Items->LineItem->addChild('Description', $item->item_title); } $xml->addChild('Payment'); $xml->Payment->addChild('TotalAmount', $invoice->first_total * 100); $xml->Payment->addChild('InvoiceNumber', $invoice->public_id); $xml->Payment->addChild('CurrencyCode', $invoice->currency); $xml->Payment->addChild('InvoiceDescription', $invoice->getLineDescription()); $xml->Payment->addChild('InvoiceReference', $invoice->public_id); return utf8_encode($xml->asXML()); } public function validate() { if ($this->xml->Errors) { $this->result->setFailed(); return; } $this->result->setSuccess($this); return true; } public function processValidated() { //do not add payment } } class Am_Form_Element_CreditCardExpire_EwayRapid3 extends HTML_QuickForm2_Container_Group { public function __construct($name = null, $attributes = null, $data = null) { parent::__construct($name, $attributes, $data); $this->setSeparator(' '); $require = !$data['dont_require']; $years = @$data['years']; if (!$years) $years = 10; $m = $this->addSelect('EWAY_CARDEXPIRYMONTH')->loadOptions($this->getMonthOptions()); if ($require) $m->addRule('required', ___('Invalid Expiration Date - Month')); $y = $this->addSelect('EWAY_CARDEXPIRYYEAR')->loadOptions($this->getYearOptions($years)); if ($require) $y->addRule('required', ___('Invalid Expiration Date - Year')); } public function getMonthOptions() { $locale = Am_Di::getInstance()->locale; $months = $locale->getMonthNames('wide', false); foreach ($months as $k => $v) $months[$k] = sprintf('(%02d) %s', $k, $v); $months[''] = ''; ksort($months); return $months; } public function getYearOptions($add) { $years = range(date('Y'), date('Y') + $add); array_unshift($years, ''); return array_combine($years, $years); } public function setValue($value) { if (is_string($value) && preg_match('/^\d{4}$/', $value)) { $value = array( 'm' => (int) substr($value, 0, 2), 'y' => '20' . substr($value, 2, 2), ); } return parent::setValue($value); } protected function updateValue() { $name = $this->getName(); foreach ($this->getDataSources() as $ds) { if (null !== ($value = $ds->getValue($name))) { $this->setValue($value); return; } } return parent::updateValue(); } } class Am_Form_EwayRapid3 extends Am_Form_CreditCard { public function init() { $name = $this->addText('EWAY_CARDNAME', array('size' => 30)) ->setLabel(___("Cardholder Name\n" . 'cardholder first and last name, exactly as on the card')); $name->addRule('required', ___('Please enter credit card holder first and last name'))->addRule('regex', ___('Please enter credit card holder first and last name'), '/^[^=:<>{}()"]+$/D'); $options = $this->plugin->getFormOptions(); if (in_array(Am_Paysystem_CreditCard::CC_COMPANY, $options)) $company = $this->addText('cc_company') ->setLabel(___("Company Name\n" . 'the company name associated with the billing address for ' . 'the transaction')); $cc = $this->addText('EWAY_CARDNUMBER', array('autocomplete' => 'off', 'size' => 22, 'maxlength' => 22)) ->setLabel(___("Credit Card Number\n" . 'for example: 1111-2222-3333-4444')); $cc->addRule('required', ___('Please enter Credit Card Number')) ->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/') ->addRule('callback2', 'Invalid CC#', array($this->plugin, 'validateCreditCardNumber')); $expire = $this->addElement(new Am_Form_Element_CreditCardExpire_EwayRapid3()) ->setLabel(___("Card Expire\n" . 'Select card expiration date - month and year')) ->addRule('required'); $code = $this->addPassword('EWAY_CARDCVN', array('autocomplete' => 'off', 'size' => 4, 'maxlength' => 4)) ->setLabel(___("Credit Card Code\n" . 'The "Card Code" is a three- or four-digit security code that ' . 'is printed on the back of credit cards in the card\'s signature ' . 'panel (or on the front for American Express cards).')); $code->addRule('required', ___('Please enter Credit Card Code')) ->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/'); $buttons = $this->addGroup(); $buttons->addSubmit('_cc_', array('value' => ' ' . $this->payButtons[$this->formType] . ' ')); if ($this->formType == self::USER_UPDATE) { $buttons->addInputButton('_cc_', array('value' => ' ' . ___("Back") . ' ', 'onclick' => 'goBackToMember()')); $this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }"); } $this->plugin->onFormInit($this); } } class Am_Paysystem_Transaction_EwayRapid3 extends Am_Paysystem_Transaction_CreditCard { public function __construct(Am_Paysystem_Abstract $plugin, $accessCode, $doFirst = true) { parent::__construct($plugin, null, $plugin->createHttpRequest(), $doFirst); $xml = new SimpleXMLElement(''); $xml->addChild('AccessCode', $accessCode); $xml = utf8_encode($xml->asXML()); $url = $plugin->getConfig('testing') ? Am_Paysystem_EwayRapid3::GET_RESULT_SANDBOX_URL : Am_Paysystem_EwayRapid3::GET_RESULT_URL; $header[] = "Authorization: Basic " . base64_encode( $plugin->getConfig('apikey') . ':' . $plugin->getConfig('password')); $header[] = "Content-Type: text/xml"; $this->request->setUrl($url); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setHeader($header); $this->request->setBody($xml); return $this->request; } protected $responseCodesSuccess = array( 'A2000' => 'Transaction Approved', 'A2008' => 'Honour With Identification', 'A2010' => 'Approved FOr Partial Amount', 'A2011' => 'Approved, VIP', 'A2016' => 'Approved, Update Track 3', ); public function validate() { // A2008 - is positive response according to documentation. https://go.eway.io/s/article/Rapid-Response-Code-A2008-Honour-with-Identification if (!array_key_exists((string) $this->parsedResponse->ResponseMessage, $this->responseCodesSuccess) || !in_array((string) $this->parsedResponse->ResponseMessage, array('A2000', 'A2008')) ) { $this->result->setFailed(); } else { if (!($this->invoice = Am_Di::getInstance()->invoiceTable->findFirstBy(array('public_id' => (string) $this->parsedResponse->InvoiceNumber)))) $this->result->setFailed(); else { $this->log->updateQuick(array( 'invoice_id' => $this->invoice->pk(), 'user_id' => $this->invoice->getUser()->user_id, )); $this->result->setSuccess($this); } } } public function parseResponse() { $this->parsedResponse = simplexml_load_string($this->response->getBody()); } public function getUniqId() { return (string) $this->parsedResponse->TransactionID; } public function processValidated() { $this->invoice->addPayment($this); $this->invoice->getUser()->data()->set(Am_Paysystem_EwayRapid3::TOKEN, (string) $this->parsedResponse->TokenCustomerID)->update(); } } class Am_Paysystem_Transaction_EwayRapid3_Refund extends Am_Paysystem_Transaction_CreditCard { protected $amount; protected $orig_id; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $billNumber, $amount) { parent::__construct($plugin, $invoice, $plugin->createHttpRequest(), true); $this->amount = $amount; $this->orig_id = $billNumber; $header[] = "Authorization: Basic " . base64_encode( $plugin->getConfig('apikey') . ':' . $plugin->getConfig('password')); $header[] = "Content-Type: text/xml"; $this->request->setHeader($header); $this->request->setBody($this->createXml($invoice)); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setUrl($this->plugin->getConfig('testing') ? Am_Paysystem_EwayRapid3::REFUND_SANDBOX_URL : Am_Paysystem_EwayRapid3::REFUND_URL); } public function getResponse() { return $this->xml; } public function getUniqId() { } public function parseResponse() { $this->xml = new SimpleXMLElement($this->response->getBody()); } protected function createXml(Invoice $invoice) { $user = $invoice->getUser(); $xml = new SimpleXMLElement(''); $xml->addChild('Refund'); $xml->Refund->addChild('TotalAmount', $this->amount * 10); $xml->Refund->addChild('InvoiceNumber', $this->invoice->public_id); $xml->Refund->addChild('InvoiceDescription', $this->invoice->getLineDescription()); $xml->Refund->addChild('InvoiceReference', $this->invoice->public_id); $xml->Refund->addChild('CurrencyCode', $this->invoice->currency); $xml->Refund->addChild('TransactionID', $this->orig_id); $xml->addChild('Customer'); $xml->Customer->addChild('Reference', $user->user_id); $xml->Customer->addChild('FirstName', $user->name_f); $xml->Customer->addChild('LastName', $user->name_l); $xml->Customer->addChild('Street1', $user->street); $xml->Customer->addChild('City', $user->city); $xml->Customer->addChild('State', $user->state); $xml->Customer->addChild('PostalCode', $user->zip); $xml->Customer->addChild('Country', strtolower($user->country)); $xml->Customer->addChild('Email', $user->email); $xml->Customer->addChild('Phone', $user->phone); /*$xml->addChild('Items'); foreach ($invoice->getItems() as $item) { $xml->Items->addChild('LineItem'); $xml->Items->LineItem->addChild('Description', $item->item_title); }*/ $xml->addChild('CustomerIP', $this->invoice->getUser()->remote_addr); return utf8_encode($xml->asXML()); } public function validate() { if ($this->xml->Errors) { $this->result->setFailed(); return; } $this->result->setSuccess($this); return true; } public function processValidated() { $this->invoice->addRefund($this, $this->orig_id); } public function getAmount() { return $this->amount; } } PK\*0p0pcc/plugins/paymill.phpnu[ Settings -> API keys) CUT; } public function getSupportedCurrencies() { return array('EUR', 'GBP', 'USD', 'CHF'); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $token = $invoice->getUser()->data()->get(self::TOKEN); if (!$token) return $result->setErrorMessages(array(___('Payment failed'))); if ($doFirst && (doubleval($invoice->first_total) <= 0)) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $tr = new Am_Paysystem_Transaction_Paymill($this, $invoice, $doFirst); $tr->run($result); } } public function getUpdateCcLink($user) { if ($user->data()->get(self::TOKEN)) return $this->getPluginUrl('update'); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { } public function loadCreditCard(Invoice $invoice) { if ($invoice->getUser()->data()->get(self::TOKEN)) return $this->getDi()->CcRecordTable->createRecord(); // return fake record for rebill } protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $controller = new Am_Mvc_Controller_CreditCard_Paymill($request, $response, $invokeArgs); if($this->getConfig('testing')) $controller->setTestMode(); return $controller; } protected function _initSetupForm(Am_Form_Setup $form) { $form->addText('private_key', 'size=40')->setLabel('Private Key')->addRule('required'); $form->addText('public_key', 'size=40')->setLabel('Public Key')->addRule('required'); $form->addSelect("testing", array(), array('options' => array( ''=>'No', '1'=>'Yes' )))->setLabel('Test Mode'); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $tr = new Am_Paysystem_Transaction_Paymill_Refund($this, $payment->getInvoice(), $payment->receipt_id, $amount); $tr->run($result); } } class Am_Mvc_Controller_CreditCard_Paymill extends Am_Mvc_Controller { /** @var Invoice*/ protected $invoice; /** @var Am_Paysystem_Paymill */ protected $plugin; protected $testMode; public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } public function setPlugin($plugin) { $this->plugin = $plugin; } public function setTestMode() { $this->testMode = true; } public function createForm($label, $cc_mask = null) { $form = new Am_Form('cc-paymill'); $name = $form->addGroup() ->setLabel(___("Cardholder Name\n" . 'cardholder first and last name, exactly as on the card')); $name->addRule('required', ___('Please enter credit card holder name')); $name_f = $name->addText('cc_name_f', array('size'=>15, 'id' => 'cc_name_f')); $name_f->addRule('required', ___('Please enter credit card holder first name'))->addRule('regex', ___('Please enter credit card holder first name'), '|^[a-zA-Z_\' -]+$|'); $name_l = $name->addText('cc_name_l', array('size'=>15, 'id' => 'cc_name_l')); $name_l->addRule('required', ___('Please enter credit card holder last name'))->addRule('regex', ___('Please enter credit card holder last name'), '|^[a-zA-Z_\' -]+$|'); $cc = $form->addText('', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22, 'id' => 'cc_number')) ->setLabel(___('Credit Card Number'), ___('for example: 1111-2222-3333-4444')); if ($cc_mask) $cc->setAttribute('placeholder', $cc_mask); $cc->addRule('required', ___('Please enter Credit Card Number')) ->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/'); class_exists('Am_Form_CreditCard', true); // preload element $expire = $form->addElement(new Am_Form_Element_CreditCardExpire('cc_expire')) ->setLabel(___("Card Expire\n" . 'Select card expiration date - month and year')); $code = $form->addPassword('', array('autocomplete'=>'off', 'size'=>4, 'maxlength'=>4, 'id' => 'cc_code')) ->setLabel(___('Credit Card Code'), sprintf(___('The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).'),'
      ','
      ')); $code->addRule('required', ___('Please enter Credit Card Code')) ->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/'); /**/ $fieldSet = $form->addFieldset(___('Address Info')) ->setLabel(___("Address Info\n" . '(must match your credit card statement delivery address)')); $street = $fieldSet->addText('cc_street')->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); $city = $fieldSet->addText('cc_city')->setLabel(___('City')) ->addRule('required', ___('Please enter City')); $zip = $fieldSet->addText('cc_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); $country = $fieldSet->addSelect('cc_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); $stateSelect = $group->addSelect('cc_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['cc_country'], true)); $stateText = $group->addText('cc_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); /**/ $form->addSubmit('', array('value' => $label)); $form->addHidden('id')->setValue($this->_request->get('id')); $form->addHidden('paymill_token', 'id=paymill_token')->addRule('required'); //$key = json_encode($this->plugin->getConfig('public_key')); $key = $this->plugin->getConfig('public_key'); $amount = $this->invoice->isFirstPayment() ? $this->invoice->first_total : $this->invoice->second_total; $amount = sprintf('%.02f', $amount)*100; $form->addProlog(''); $form->addScript()->setScript("var PAYMILL_PUBLIC_KEY = '".$key."';"); if($this->testMode) $form->addScript()->setScript("var PAYMILL_TEST_MODE = true;"); $form->addScript()->setScript(file_get_contents(dirname(__FILE__) . '/../../default/views/public/js/json2.min.js')); $form->addScript()->setScript(<< '') return true; // submit the form! event.stopPropagation(); paymill.createToken({ number: frm.find("#cc_number").val(), // required exp_month: frm.find("[name='cc_expire[m]']").val(), // required exp_year: frm.find("[name='cc_expire[y]']").val(), // required cvc: frm.find("#cc_code").val(), // required amount_int: {$amount}, // required, z.B. "4900" for 49.00 EUR currency: '{$this->invoice->currency}', // required cardholder: frm.find("#cc_name_f").val() + " " + frm.find("#cc_name_l").val() // optional }, function(error, result){ // handle response if (error) { frm.find("input[type=submit]").prop('disabled', null); var el = frm.find("#cc_number"); var cnt = el.closest(".element"); cnt.addClass("error"); cnt.find("span.error").remove(); var errorMessage = ''; switch (error.apierror) { case 'internal_server_error': errorMessage = 'Communication with PSP failed'; break; case 'invalid_public_key': errorMessage = 'Invalid Public Key'; break; case 'unknown_error': errorMessage = 'Unknown Error'; break; case '3ds_cancelled': errorMessage = 'Password Entry of 3-D Secure password was cancelled by the user'; break; case 'field_invalid_card_number': errorMessage = 'Missing or invalid creditcard number'; break; case 'field_invalid_card_exp_year': errorMessage = 'Missing or invalid expiry year'; break; case 'field_invalid_card_exp_month': errorMessage = 'Missing or invalid expiry month'; break; case 'field_invalid_card_exp': errorMessage = 'Card is no longer valid or has expired'; break; case 'field_invalid_card_cvc': errorMessage = 'Invalid checking number'; break; case 'field_invalid_card_holder': errorMessage = 'Invalid cardholder'; break; case 'field_invalid_amount_int': errorMessage = 'Invalid or missing amount for 3-D Secure'; break; case 'field_invalid_amount': errorMessage = 'Invalid or missing amount for 3-D Secure deprecated, see blog post'; break; case 'field_invalid_currency': errorMessage = 'Invalid or missing currency code for 3-D Secure'; break; case 'field_invalid_account_number': errorMessage = 'Missing or invalid bank account number'; break; case 'field_invalid_account_holder': errorMessage = 'Missing or invalid bank account holder'; break; case 'field_invalid_bank_code': errorMessage = 'Missing or invalid bank code '; break; default: errorMessage = error.apierror; } el.after("
      "+errorMessage+"
      "); } else { frm.find("input[name=paymill_token]").val(result.token); frm.submit(); } }); frm.find("input[type=submit]").prop('disabled', 'disabled'); return false; }); }); CUT ); return $form; } public function updateAction() { $user = $this->getDi()->user; $token = $user->data()->get(Am_Paysystem_Paymill::TOKEN); if (!$token) throw new Am_Exception_Paysystem("No credit card stored, nothing to update"); $this->invoice = $this->getDi()->invoiceTable->findFirstBy( array('user_id'=>$user->pk(), 'paysys_id'=>$this->plugin->getId()), 'invoice_id DESC'); if (!$this->invoice) throw new Am_Exception_Paysystem("No invoices found for user and paysystem"); $cc_last4 = $this->invoice->getUser()->data()->get(Am_Paysystem_Paymill::CC_LAST4); $cc_expires = $this->invoice->getUser()->data()->get(Am_Paysystem_Paymill::CC_EXPIRES); $this->form = $this->createForm(___('Update Credit Card Info'), 'XXXX XXXX XXXX ' . $cc_last4); $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'cc_street' => $user->street, 'cc_name_f' => $user->name_f, 'cc_name_l' => $user->name_l, 'cc_zip' => $user->zip, 'cc_expire' => $cc_expires, ))); $result = $this->ccFormAndSaveCustomer(); if ($result->isSuccess()) $this->_redirect($this->getDi()->url('member',null,false,true)); $this->form->getElementById('paymill_token')->setValue(''); $this->view->title = ___('Payment info'); $this->view->display_receipt = false; $this->view->form = $this->form; $this->view->display('cc/info.phtml'); } protected function ccFormAndSaveCustomer() { $vars = $this->form->getValue(); $result = new Am_Paysystem_Result(); if (!empty($vars['paymill_token'])) { if (!$vars['paymill_token']) throw new Am_Exception_Paysystem("No expected token id received"); $this->invoice->getUser()->data() ->set(Am_Paysystem_Paymill::TOKEN, $vars['paymill_token']) ->update(); $result->setSuccess(); // setup session to do not reask payment info within 30 minutes $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session $s->ccConfirmed = true; } return $result; } protected function displayReuse() { $result = new Am_Paysystem_Result; $cc_last4 = $this->invoice->getUser()->data()->get(Am_Paysystem_Paymill::CC_LAST4); $card = 'XXXX XXXX XXXX ' . $cc_last4; $text = ___('Click "Continue" to pay this order using stored credit card %s', $card); $continue = ___('Continue'); $cancel = ___('Cancel'); $action = $this->plugin->getPluginUrl('cc'); $id = Am_Html::escape($this->_request->get('id')); $action = Am_Html::escape($action); $this->view->content .= << $text
         
      CUT; $this->view->display('layout.phtml'); } public function ccAction() { $this->view->title = ___('Payment info'); $this->view->display_receipt = true; $this->view->invoice = $this->invoice; // if we have credit card on file, we will try to use it but we // have to display confirmation first if ($this->invoice->getUser()->data()->get(Am_Paysystem_Paymill::TOKEN)) { $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session if ($this->_request->get('reuse_ok') || (@$s->ccConfirmed === true)) { $result = $this->plugin->doBill($this->invoice, true, $this->getDi()->CcRecordTable->createRecord()); if ($result->isSuccess()) { return $this->_redirect($this->plugin->getReturnUrl()); } else { $this->invoice->getUser()->data() ->set(Am_Paysystem_Paymill::TOKEN, null) ->set(Am_Paysystem_Paymill::CC_EXPIRES, null) ->set(Am_Paysystem_Paymill::CC_LAST4, null) ->set(Am_Paysystem_Paymill::CLIENT_ID, null) ->update(); $this->view->error = $result->getErrorMessages(); $s->ccConfirmed = false; // failed } } elseif ($this->_request->get('reuse_cancel') || (@$s->ccConfirmed === false)) { $s->ccConfirmed = false; } elseif (!isset($s->ccConfirmed)) { return $this->displayReuse(); } } $this->form = $this->createForm(___('Subscribe And Pay')); $result = $this->ccFormAndSaveCustomer(); if ($result->isSuccess()) { $result = $this->plugin->doBill($this->invoice, true, $this->getDi()->CcRecordTable->createRecord()); if ($result->isSuccess()) { return $this->_redirect($this->plugin->getReturnUrl()); } else { $this->invoice->getUser()->data() ->set(Am_Paysystem_Paymill::TOKEN, null) ->set(Am_Paysystem_Paymill::CC_EXPIRES, null) ->set(Am_Paysystem_Paymill::CC_LAST4, null) ->set(Am_Paysystem_Paymill::CLIENT_ID, null) ->update(); $this->view->error = $result->getErrorMessages(); } } $this->form->getElementById('paymill_token')->setValue(''); $this->view->form = $this->form; $this->view->display('cc/info.phtml'); } } class Am_Paysystem_Transaction_Paymill extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst) { $request = new Am_HttpRequest(Am_Paysystem_Paymill::API_ENDPOINT . 'transactions/', 'POST'); $amount = $doFirst ? $invoice->first_total : $invoice->second_total; $request->setAuth($plugin->getConfig('private_key'), '') ->addPostParameter('amount', sprintf('%.02f', $amount)*100) ->addPostParameter('currency', $invoice->currency) ->addPostParameter('token', $invoice->getUser()->data()->get(Am_Paysystem_Paymill::TOKEN)) ->addPostParameter('description', 'Invoice #'.$invoice->public_id.': '.$invoice->getLineDescription()); parent::__construct($plugin, $invoice, $request, $doFirst); } public function getUniqId() { return $this->parsedResponse['data']['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function processValidated() { $this->invoice->getUser()->data() ->set(Am_Paysystem_Paymill::CC_EXPIRES, sprintf('%02d%02d', $this->parsedResponse['data']['payment']['expire_month'], $this->parsedResponse['data']['payment']['expire_year']-2000)) ->set(Am_Paysystem_Paymill::CC_LAST4, $this->parsedResponse['data']['payment']['last4']) ->set(Am_Paysystem_Paymill::CLIENT_ID, $this->parsedResponse['data']['client']['id']) ->update(); //$result = new Am_Paysystem_Result(); //$tr = new Am_Paysystem_Transaction_Paymill_UpdateCustomer($this->plugin, $this->invoice); //$tr->run($result); $this->invoice->addPayment($this); } public function validate() { if (@$this->parsedResponse['error']) { if ($message = $this->parsedResponse['error']) $this->result->setErrorMessages(array($message)); else $this->result->setErrorMessages(array(___('Payment failed'))); return false; } if (isset($this->parsedResponse['data']['response_code']) && $this->parsedResponse['data']['response_code'] != 20000) { $message = $this->getStatusByCode($this->parsedResponse['data']['response_code']); $this->result->setErrorMessages(array($message)); } if ($this->parsedResponse['data']['livemode'] || ($this->parsedResponse['mode'] == 'test' && $this->getPlugin()->getConfig('testing'))) $this->result->setSuccess($this); return true; } public function getStatusByCode($code) { $statusCodes = array( '10001' => 'General undefined response.', '10002' => 'Still waiting on something.', '20000' => 'General success response.', '40000' => 'General problem with data.', '40100' => 'Problem with creditcard data.', '40101' => 'Problem with cvv.', '40102' => 'Card expired or not yet valid.', '40103' => 'Limit exceeded.', '40104' => 'Card invalid.', '40105' => 'expiry date not valid.', '40200' => 'Problem with bank account data.', '40300' => 'Problem with 3d secure data.', '40301' => 'currency / amount mismatch.', '40400' => 'Problem with input data.', '40401' => 'Amount too low or zero.', '40402' => 'Usage field too long.', '40403' => 'Currency not allowed.', '50000' => 'General problem with backend.', '50001' => 'country blacklisted.', '50100' => 'Technical error with credit card.', '50101' => 'Error limit exceeded.', '50102' => 'Card declined by authorization system.', '50103' => 'Manipulation or stolen card.', '50104' => 'Card restricted.', '50105' => 'Invalid card configuration data.', '50200' => 'Technical error with bank account.', '50201' => 'Card blacklisted.', '50300' => 'Technical error with 3D secure.', '50400' => 'Decline because of risk issues.' ); return isset($statusCodes[$code]) ? $statusCodes[$code] : ''; } } class Am_Paysystem_Transaction_Paymill_CreateCustomer extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice) { $request = new Am_HttpRequest(Am_Paysystem_Paymill::API_ENDPOINT . 'clients/', 'POST'); $request->setAuth($plugin->getConfig('private_key'), '') ->addPostParameter('email', $invoice->getEmail()) ->addPostParameter('description', 'Username: ' . $invoice->getUser()->login); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { return $this->parsedResponse['data']['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['data']['id']) { $this->result->setErrorMessages(array('Error storing customer profile')); return false; } $this->result->setSuccess($this); return true; } public function processValidated() { $this->invoice->getUser()->data()->set(Am_Paysystem_Paymill::CLIENT_ID, $this->parsedResponse['data']['id'])->update(); } } class Am_Paysystem_Transaction_Paymill_UpdateCustomer extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice) { $clientId = $invoice->getUser()->data()->get(Am_Paysystem_Paymill::CLIENT_ID); $request = new Am_HttpRequest(Am_Paysystem_Paymill::API_ENDPOINT . 'clients/' . $clientId, 'PUT'); $request->setAuth($plugin->getConfig('private_key'), '') ->addPostParameter('email', $invoice->getEmail()) ->addPostParameter('description', 'Username: ' . $invoice->getUser()->login); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { return $this->parsedResponse['data']['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['data']['id']) { $this->result->setErrorMessages(array('Error storing customer profile')); return false; } $this->result->setSuccess($this); return true; } } class Am_Paysystem_Transaction_Paymill_GetCustomer extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice) { $clientId = $invoice->getUser()->data()->get(Am_Paysystem_Paymill::CLIENT_ID); $request = new Am_HttpRequest(Am_Paysystem_Paymill::API_ENDPOINT . 'clients/' . $clientId , 'GET'); $request->setAuth($plugin->getConfig('private_key'), ''); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { return $this->parsedResponse['data']['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['data']['id']) $this->result->setErrorMessages(array('Unable to fetch payment profile')); $this->result->setSuccess($this); } public function getInfo() { return $this->parsedResponse; } public function processValidated() { } } class Am_Paysystem_Transaction_Paymill_Refund extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); protected $transactionId; protected $amount; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $transactionId, $amount = null) { $this->transactionId = $transactionId; $this->amount = $amount > 0 ? $amount : null; $request = new Am_HttpRequest(Am_Paysystem_Paymill::API_ENDPOINT . 'refunds/' . $transactionId, 'POST'); $request->setAuth($plugin->getConfig('private_key'), ''); if ($this->amount > 0) $request->addPostParameter('amount', sprintf('%.02f', $amount)*100) ->addPostParameter('description', 'Refund from aMember script. Username: ' . $invoice->getUser()->login . ', invoice: ' . $invoice->public_id); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { return $this->parsedResponse['data']['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['data']['id']) $this->result->setErrorMessages(array('Unable to fetch payment profile')); if (@$this->parsedResponse['data']['status'] == 'refunded') $this->result->setSuccess($this); elseif ($message = @$this->parsedResponse['error']) $this->result->setErrorMessages(array($message)); } public function processValidated() { $this->invoice->addRefund($this, $this->transactionId, $this->amount); } } PK\<cc/plugins/graypay.phpnu[getTitle()) $form->setTitle($t); } protected function _initSetupForm(Am_Form_Setup $form) { $form->addText('PxPayUserId') ->setLabel('Your PxPayUserId') ->addRule('required'); $form->addText('PxPayKey', array('size' => 65)) ->setLabel('Your PxPayKey') ->addRule('required'); $form->addText('PostUsername') ->setLabel('Your PostUsername') ->addRule('required'); $form->addPassword('PostPassword') ->setLabel('Your PostPassword') ->addRule('required'); $form->addAdvCheckbox('debugMode') ->setLabel("Debug Mode Enable\n" . "write all requests/responses to log"); } public function isConfigured() { return $this->getConfig('PxPayUserId') && $this->getConfig('PxPayKey'); } public static function getAttributeValue($attr, $xmlStr, $which = 0) { if ($which == 1) { $spos = strpos($xmlStr, $attr . '="'); $xmlStr = substr($xmlStr, $spos + strlen($attr)); } if (false !== ($spos = strpos($xmlStr, $attr . '="')) && false !== ($epos = strpos($xmlStr, '"', $spos + strlen($attr) + 2))) return substr($xmlStr, $spos + strlen($attr) + 2, $epos - $spos - strlen($attr) - 2); return ''; } public static function getTagValue($tag, $xmlStr) { if (false !== strpos($xmlStr, '<' . $tag . '>') && false !== strpos($xmlStr, '')) { $xmlStr = strstr($xmlStr, '<' . $tag . '>'); $end = strpos($xmlStr, ''); return substr($xmlStr, strlen($tag) + 2, $end - (strlen($tag) + 2)); } return ''; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $xmlOut = ''; $xmlOut .= ''; $xmlOut .= '' . $this->getConfig('PxPayUserId') . ''; $xmlOut .= '' . $this->getConfig('PxPayKey') . ''; $xmlOut .= '' . $invoice->first_total . ''; // $xmlOut .= '' . (((float)$invoice->first_total) ? $invoice->first_total : '1.00'). ''; $xmlOut .= '' . $invoice->currency . ''; $xmlOut .= '' . $invoice->getLineDescription() . ''; $xmlOut .= 'Purchase'; // $xmlOut .= '' . (((float)$invoice->first_total) ? 'Purchase' : 'Auth') . ''; $xmlOut .= '' . $invoice->public_id . ''; $xmlOut .= ''; // $xmlOut .= '' . $invoice->getUserId() . ''; $xmlOut .= '' . (($invoice->second_total > 0) ? '1' : '0') . ''; $xmlOut .= '' . $this->getPluginUrl(self::RETURN_URL_SUCCESS) . ''; $xmlOut .= '' . $this->getPluginUrl(self::RETURN_URL_FAIL) . ''; $xmlOut .= ''; $req = new Am_HttpRequest_PaymentExpress($xmlOut, 'GenerateRequest', (bool)$this->getConfig('debugMode')); $xmlIn = $req->getResponseXML(); $url = self::getTagValue('URI', $xmlIn); if (!url) throw new Am_Exception_InternalError( "PaymentExpress[error]. URI is absent. /GenerateRequest/" ); $a = new Am_Paysystem_Action_Redirect(htmlspecialchars_decode($url)); $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { switch ($request->getActionName()) { case self::RETURN_URL_SUCCESS: case self::RETURN_URL_FAIL: $log = $this->logRequest($request); $transaction = $this->createThanksTransaction($request, $response, $invokeArgs); $transaction->setInvoiceLog($log); try { $transaction->process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { // ignore this error, as it happens in "thanks" transaction // we may have received IPN about the payment earlier } catch (Exception $e) { throw $e; $this->getDi()->errorLogTable->logException($e); throw Am_Exception_InternalError(___("Error happened during transaction handling. Please contact website administrator")); } $log->setInvoice($transaction->getInvoice())->update(); $this->invoice = $transaction->getInvoice(); $this->invoice->data()->set(self::DPS_BILLING_ID, $transaction->getDpsBillingId())->update(); $response->setRedirect($this->getReturnUrl()); break; default : parent::directAction($request, $response, $invokeArgs); } } public function loadCreditCard(Invoice $invoice) { return $this->getDi()->CcRecordTable->createRecord(); // return fake record for rebill } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if (!$doFirst) { $dpsBillingId = $invoice->data()->get(self::DPS_BILLING_ID); if(!$dpsBillingId) return $result->setFailed(array("No saved DPS_BILLING_ID for invoice")); $transaction = new Am_Paysystem_Transaction_CreditCard_PaymentExpress_Rebill($this, $invoice, $doFirst, $dpsBillingId); $transaction->run($result); } } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Incoming_PaymentExpress($this, $request, $response, $invokeArgs); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $dpsBillingId = $payment->getInvoice()->data()->get(self::DPS_BILLING_ID); if(!$dpsBillingId) return $result->setFailed(array("No saved DPS_BILLING_ID for invoice")); $transaction = new Am_Paysystem_Transaction_CreditCard_PaymentExpress_Refund($this, $payment->getInvoice(), $dpsBillingId, $amount); $transaction->run($result); } public function getReadme() { return <<Attention: Plugin does not support free-trial payments. Configure plugin at this page and click 'Save' CUT; } } class Am_Paysystem_Transaction_Incoming_PaymentExpress extends Am_Paysystem_Transaction_Incoming { private $xmlResponse; public function findInvoiceId() { return Am_Paysystem_PaymentExpress::getTagValue('TxnId', $this->xmlResponse); } public function getUniqId() { return Am_Paysystem_PaymentExpress::getTagValue('DpsTxnRef', $this->xmlResponse); } public function validateSource() { if(!$this->request->getParam('result')) throw new Am_Exception_InternalError("PaymentExpress[error]. Result is absent at response. /ProcessResponse/"); $xmlOut = ''; $xmlOut .= ''; $xmlOut .= '' . $this->plugin->getConfig('PxPayUserId') . ''; $xmlOut .= '' . $this->plugin->getConfig('PxPayKey') . ''; $xmlOut .= '' . $this->request->getParam('result') . ''; $xmlOut .= ''; $req = new Am_HttpRequest_PaymentExpress($xmlOut, 'ProcessResponse', (bool)$this->plugin->getConfig('debugMode')); $this->xmlResponse = $req->getResponseXML(); return true; } public function validateStatus() { return (Am_Paysystem_PaymentExpress::getTagValue('Success', $this->xmlResponse) > 0); } public function validateTerms() { $this->assertAmount($this->invoice->first_total, Am_Paysystem_PaymentExpress::getTagValue('AmountSettlement', $this->xmlResponse)); return true; } public function getDpsBillingId() { return Am_Paysystem_PaymentExpress::getTagValue('DpsBillingId', $this->xmlResponse); } } class Am_Paysystem_Transaction_CreditCard_PaymentExpress_Rebill extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse; protected $txnType = 'Purchase'; protected $requestType = 'Rebill'; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, $dpsBillingId) { $xmlOut = ''; $xmlOut .= ''; $xmlOut .= ''. $plugin->getConfig('PostUsername') . ''; $xmlOut .= ''. $plugin->getConfig('PostPassword') . ''; $xmlOut .= '' . $invoice->second_total . ''; $xmlOut .= '' . $invoice->currency . ''; $xmlOut .= '' . $invoice->getLineDescription() . ''; $xmlOut .= '' . $this->txnType . ''; $xmlOut .= '' . $invoice->public_id . ''; $xmlOut .= ''; $xmlOut .= '' . $dpsBillingId . ''; $xmlOut .= ''; $request = new Am_HttpRequest_PaymentExpress($xmlOut, $this->requestType, (bool)$plugin->getConfig('debugMode')); $request->setUrl(Am_Paysystem_PaymentExpress::URL_RECURRING); parent::__construct($plugin, $invoice, $request, $doFirst); } public function getUniqId() { return Am_Paysystem_PaymentExpress::getTagValue('DpsTxnRef', $this->parsedResponse); } public function parseResponse() { $this->parsedResponse = $this->response->getBody(); } public function validate() { $success = Am_Paysystem_PaymentExpress::getTagValue('Success', $this->parsedResponse); if ($success != 1) return $this->result->setFailed(array('#'.$success.'-'.Am_Paysystem_PaymentExpress::getTagValue('ResponseText', $this->parsedResponse))); $this->result->setSuccess($this); } } class Am_Paysystem_Transaction_CreditCard_PaymentExpress_Refund extends Am_Paysystem_Transaction_CreditCard_PaymentExpress_Rebill { protected $txnType = 'Purchase'; protected $requestType = 'Rebill'; protected $amount; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $dpsBillingId, $amount) { $this->amount = $amount; parent::__construct($plugin, $invoice, false, $dpsBillingId); } public function getAmount() { return $this->amount; } public function processValidated(){} // no process payment } class Am_HttpRequest_PaymentExpress extends Am_HttpRequest { private $requestType; private $debugMode; public function __construct($xmlOut, $requestType, $debugMode = false) { $this->requestType = $requestType; $this->debugMode = $debugMode; parent::__construct(Am_Paysystem_PaymentExpress::URL, self::METHOD_POST); $this->setBody($xmlOut); } public function getResponseXML() { $response = $this->send(); $xmlIn = $response->getBody(); if (!Am_Paysystem_PaymentExpress::getAttributeValue('valid', $xmlIn)) throw new Am_Exception_InternalError( "PaymentExpress[error]. Invalid request. /{$this->requestType}/" ); return $xmlIn; } public function send() { if ($this->debugMode) Am_Di::getInstance()->errorLogTable->log("PaymentExpress[debug]. [{$this->requestType}]-request: " . $this->getBody()); $response = parent::send(); if ($response->getStatus() != 200) throw new Am_Exception_InternalError( "PaymentExpress[error]. Bad response status [{$response->getStatus()}]. /GenerateRequest/" ); $xmlIn = $response->getBody(); if (!$xmlIn) throw new Am_Exception_InternalError( "PaymentExpress[error]. Null response body. /{$this->requestType}/" ); if ($this->debugMode) Am_Di::getInstance()->errorLogTable->log("PaymentExpress[debug]. [{$this->requestType}]-response: " . $xmlIn); return $response; } }PK\̉_]]&cc/plugins/networkmerchants-hosted.phpnu[getActionName()) { case self::ACTION_PROCESSED: return $this->makepaymentAction($request, $response, $invokeArgs); case self::ACTION_PROCESS: return $this->processAction($request, $response, $invokeArgs); case self::ACTION_SUCCESS: return $this->succeedAction($request, $response, $invokeArgs); case self::ACTION_FAILED: return $this->failedAction($request, $response, $invokeArgs); default: return parent::directAction($request, $response, $invokeArgs); } } private function getInvoice($invoiceId) { if (!$invoiceId) { throw new Am_Exception_InputError("" . "invoice_id is empty - " . "seems you have followed wrong url, " . "please return back to continue"); } return $this->getDi()->invoiceTable->findFirstByPublicId($invoiceId); } private function handleResponse( $gwResponse, Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $result = $gwResponse->result; switch ($result) { case self::NMI_SUCCESS: return $this->thanksAction($request, $response, $invokeArgs); case self::NMI_DECLINED: case self::NMI_FAILED: $message = (string)$gwResponse->{'result-text'}; $this->logError($message); return $this->cancelPaymentAction($request, $response, $invokeArgs); default: throw new Am_Exception("Unhandled NMI transaction result {$result}"); } } static function debug($data) { if (self::$plugin->getConfig('debug')) { self::$plugin->logRequest($data); error_log(print_r($data, 1)); } } public function getUpdateCcLink($user) { if ($user->data()->get('customer_vault_id')) { return $this->getPluginUrl('update'); } } private function failedAction( \Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { $param = $request->getParam('message'); $message = html_entity_decode($param); $view = $this->getDi()->view; $view->title = ___('Update failed'); $view->content = <<NMI Profile updated failed: {$message} CUT; $view->display('member/layout.phtml'); } private function succeedAction( \Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { $view = $this->getDi()->view; $view->title = ___('Successfull update'); $view->content = <<Thank you. Your credit card info has been successfully saved. CUT; $view->display('member/layout.phtml'); } private function processAction( \Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { $APIKey = $this->getConfig('api_key'); $tokenId = $request->get('token-id'); if (!$tokenId) { throw new Am_Exception('No token in request'); } $user = Am_Di::getInstance() ->auth ->getUser(); $xmlRequest = new DOMDocument('1.0','UTF-8'); $xmlRequest->formatOutput = true; $xmlCompleteTransaction = $xmlRequest->createElement('complete-action'); $this->appendXmlNode($xmlRequest, $xmlCompleteTransaction, 'api-key', $APIKey); $this->appendXmlNode($xmlRequest, $xmlCompleteTransaction, 'token-id', $tokenId); $xmlRequest->appendChild($xmlCompleteTransaction); self::debug($xmlRequest->saveXML()); // Process Step Three $data = $this->sendXMLrequest( $xmlRequest, self::GATEWAY_URL); self::debug($data); $gwResponse = @new SimpleXMLElement((string)$data); $result = $gwResponse->result; switch ($result) { case self::NMI_SUCCESS: $customer_id = (string)$gwResponse->{'customer-vault-id'}; if (!$customer_id) { throw new Am_Exception('No customer-vault-id returned on successful transaction'); } $fourlast = (string)$gwResponse->{'billing'}->{'cc-number'}; $user->data()->set('customer_vault_id', $customer_id); $user->data()->set('four_last', $this->cosherCCNum($fourlast)); $user->update(); $response->setRedirect($this->getPluginUrl(self::ACTION_SUCCESS)); break; case self::NMI_DECLINED: case self::NMI_FAILED: $message = (string)$gwResponse->{'result-text'}; $this->logError($message); $url = $this->getPluginUrl(self::ACTION_FAILED) . '?message=' . htmlentities($message); $response->setRedirect($url); break; default: throw new Am_Exception("Unhandled NMI transaction result {$result}"); } } function cancelPaymentAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $id = $request->getFiltered('invoice_id'); if (!$id && isset($_GET['id'])) $id = filterId($_GET['id']); $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($id); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); if ($invoice->user_id != $this->getDi()->auth->getUserId()) throw new Am_Exception_InternalError("User tried to access foreign invoice: [$id]"); $this->invoice = $invoice; // find invoice and redirect to default "cancel" page $response->setRedirect($this->getCancelUrl()); } function cosherCCNum($num) { $subnum = substr($num, -4); return str_pad($subnum, 16, "*", STR_PAD_LEFT); } private function makepaymentAction( \Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { $tokenId = $request->get('token-id'); $APIKey = $this->getConfig('api_key'); $xmlRequest = new DOMDocument('1.0','UTF-8'); $xmlRequest->formatOutput = true; $xmlCompleteTransaction = $xmlRequest->createElement('complete-action'); $this->appendXmlNode($xmlRequest, $xmlCompleteTransaction, 'api-key', $APIKey); $this->appendXmlNode($xmlRequest, $xmlCompleteTransaction, 'token-id', $tokenId); $xmlRequest->appendChild($xmlCompleteTransaction); self::debug($xmlRequest->saveXML()); // Process Step Three $data = $this->sendXMLrequest($xmlRequest, self::GATEWAY_URL); self::debug($data); $gwResponse = @new SimpleXMLElement((string)$data); $customer_id = (string)$gwResponse->{'customer-vault-id'}; if ($customer_id) { $fourlast = (string)$gwResponse->{'billing'}->{'cc-number'}; $invoiceId = $request->getFiltered('invoice_id'); $invoice = $this->getInvoice($invoiceId); $invoice->getUser()->data()->set('customer_vault_id', $customer_id); $invoice->getUser()->data()->set('four_last', $this->cosherCCNum($fourlast)); $invoice->getUser()->update(); } self::debug('here3'); return $this->handleResponse($gwResponse, $request, $response, $invokeArgs); } protected function _initSetupForm(Am_Form_Setup $form) { $key = $form->addText('api_key') ->setLabel("API Key"); $key->addRule('required') ->addRule( 'regex', 'API Keys must be in form of 32 alphanumeric signs', '/^[a-zA-Z0-9]{32}$/'); $form->addText('user') ->setLabel("Your username\n" . 'Username assigned to merchant account') ->addRule('required'); $form->addPassword('pass') ->setLabel("Your password\n" . 'Password for the specified username') ->addRule('required'); $form->addAdvCheckbox('testMode') ->setLabel("Test Mode\n" . 'Test account data will be used'); $form->addAdvCheckbox('debug') ->setLabel("Write debug info"); } function isConfigured() { return $this->getConfig('api_key') && $this->getConfig('user') && $this->getConfig('pass'); } function configBaseForm($formUrl, Am_Form_Nmi $form) { $id = $form->getId(); $cc = $form->addText('billing-cc-number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22)) ->setLabel(___( "Credit Card Number\n" . "for example: 1111-2222-3333-4444")); $cc->addRule('required', ___('Please enter Credit Card Number')) ->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/') ->addRule('callback2', 'Invalid CC#', array($this, 'validateCreditCardNumber')); $form->addElement(new Am_Form_Element_CreditCardExpire('expiration')) ->setLabel(___("Card Expire\n" . 'Select card expiration date - month and year')) ->addRule('required'); $form->addHidden('billing-cc-exp') ->setId('hid-exp'); $code = $form->addPassword('cvv', array('autocomplete'=>'off', 'size'=>4, 'maxlength'=>4)) ->setLabel(___("Credit Card Code\n" . 'The "Card Code" is a three- or four-digit security code ' . 'that is printed on the back of credit cards in the card\'s ' . 'signature panel (or on the front for American Express cards)')); $code->addRule('required', ___('Please enter Credit Card Code')) ->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/'); $form->setAction($formUrl); $form->addScript() ->setScript(<<data() ->get('customer_vault_id'); if ($customer_id) { $fourlast = $this->cosherCCNum( $user ->data() ->get('four_last')); $form->addAdvCheckbox('use_saved') ->setLabel(___( "Use saved card: $fourlast")); } $this->configBaseForm($formUrl, $form); $buttons = $form->addGroup(); $buttons->setSeparator(' '); $buttons->addSubmit('_cc_', array('value'=> 'Subscribe And Pay')); $form->addScript() ->setScript(<< 0 && index < 4) { if($('#use_saved-0').is(':checked')){ $(this).hide(); } else { $(this).show(); } } }); } $('#use_saved-0').prop('checked', true); reChech(); }) CUT ); $this->onFormInit($form); return $form; } function createController( Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_CreditCard_Nmi( $request, $response, $invokeArgs); } function appendXmlNode($domDocument, $parentNode, $name, $value) { $childNode = $domDocument->createElement($name); $childNodeValue = $domDocument->createTextNode($value); $childNode->appendChild($childNodeValue); $parentNode->appendChild($childNode); } function sendXMLrequest(DOMDocument $xmlRequest, $gatewayURL) { $xmlString = $xmlRequest->saveXML(); $request = new Am_HttpRequest($gatewayURL, Am_HttpRequest::METHOD_POST); $request->setConfig('timeout', 7); $request->setConfig('follow_redirects', true); $request->setHeader('Content-type', 'text/xml'); $request->setBody($xmlString); $result = $request->send(); if ($result->getStatus() != 200) { throw new Am_Exception( "Error on request: " . "{$result->getStatus()}: " . "{$result->getBody()}"); } return $result->getBody(); } function createXmlRequest( User $user, Invoice $invoice, $customer_vault_id = null) { $APIKey = $this->getConfig('api_key'); $redirect = $this->getPluginUrl(self::ACTION_PROCESSED) . "?invoice_id={$invoice->public_id}"; $xmlRequest = new DOMDocument('1.0','UTF-8'); $xmlRequest->formatOutput = true; $amount = $invoice->first_total; if (floatval($amount)) { $xmlRoot = $xmlRequest->createElement('sale'); } else { $xmlRoot = $xmlRequest->createElement('validate'); } // Amount, authentication, and Redirect-URL are typically the bare minimum. $this->appendXmlNode($xmlRequest, $xmlRoot,'api-key', $APIKey); $this->appendXmlNode($xmlRequest, $xmlRoot,'redirect-url', $redirect); $this->appendXmlNode($xmlRequest, $xmlRoot, 'ip-address', $user->remote_addr); $this->appendXmlNode($xmlRequest, $xmlRoot, 'currency', $invoice->currency); if (floatval($amount)) { $this->appendXmlNode($xmlRequest, $xmlRoot, 'amount', $amount); } if ($customer_vault_id) { $this->appendXmlNode( $xmlRequest, $xmlRoot, 'customer-vault-id', $customer_vault_id); } else { // Set the Billing and Shipping from what was collected on initial shopping cart form $xmlBillingAddress = $xmlRequest->createElement('billing'); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'first-name', $user->name_f); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'last-name', $user->name_l); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'address1', $user->street); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'city', $user->city); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'state', $user->state); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'postal', $user->zip); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'country', $user->country); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'email', $user->email); $this->appendXmlNode($xmlRequest, $xmlBillingAddress,'phone', $user->phone); $xmlRoot->appendChild($xmlBillingAddress); $xmlShippingAddress = $xmlRequest->createElement('shipping'); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'first-name', $user->name_f); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'last-name', $user->name_l); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'address1', $user->street); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'city', $user->city); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'state', $user->state); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'postal', $user->zip); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'country', $user->country); $this->appendXmlNode($xmlRequest, $xmlShippingAddress,'phone', $user->phone); $xmlRoot->appendChild($xmlShippingAddress); foreach($invoice->getItems() as $item) { // Products already chosen by user $xmlProduct = $xmlRequest->createElement('product'); $this->appendXmlNode($xmlRequest, $xmlProduct, 'product-code' , $item->item_id); $this->appendXmlNode($xmlRequest, $xmlProduct, 'description' , $item->item_description); $this->appendXmlNode($xmlRequest, $xmlProduct, 'unit-cost' , $item->first_price); $this->appendXmlNode($xmlRequest, $xmlProduct, 'quantity' , $item->qty); $this->appendXmlNode($xmlRequest, $xmlProduct, 'total-amount' , $item->first_total); $this->appendXmlNode($xmlRequest, $xmlProduct, 'tax-amount' , $item->first_tax); $this->appendXmlNode($xmlRequest, $xmlProduct, 'discount-amount', $item->first_discount); $this->appendXmlNode($xmlRequest, $xmlProduct, 'tax-type' , $item->tax_group); $xmlRoot->appendChild($xmlProduct); } $userVault = $xmlRequest->createElement('add-customer'); $xmlRoot->appendChild($userVault); } $xmlRequest->appendChild($xmlRoot); return $xmlRequest; } function _doBill( \Invoice $invoice, $doFirst, \CcRecord $cc, \Am_Paysystem_Result $result) { if ($doFirst) { throw new Am_Exception("Just rebill can be handled here"); } $user = $this->invoice->getUser(); $customer_id = $user->data()->get('customer_vault_id'); if (!$customer_id) { return $result->setFailed( array("No saved reference transaction for customer")); } $trSale = new Am_Paysystem_Networkmerchants_Transaction_Sale( $this, $invoice, false, $customer_id); $trSale->run($result); } function storesCcInfo() { return false; } } class Am_Paysystem_Networkmerchants_Transaction_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { public function getUniqId() { return time(); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } function findInvoiceId() { return $this->request->get('invoice_id'); } function processValidated() { if (floatval($this->invoice->first_total)) { $this->invoice->addPayment($this); } else { $this->invoice->addAccessPeriod($this); } } } /** @property Am_Paysystem_NetworkmerchantsHosted $plugin Plugin */ class Am_Mvc_Controller_CreditCard_Nmi extends Am_Mvc_Controller_CreditCard { private function createXmlRequest($user, $apiKey, $customer_vault_id = null) { $redirect = $this->plugin->getPluginUrl(ThePlugin::ACTION_PROCESS); $xmlRequest = new DOMDocument('1.0','UTF-8'); $xmlRequest->formatOutput = true; if ($customer_vault_id) { $xmlSale = $xmlRequest->createElement('update-customer'); } else { $xmlSale = $xmlRequest->createElement('add-customer'); } // Amount, authentication, and Redirect-URL are typically the bare minimum. $this->plugin->appendXmlNode($xmlRequest, $xmlSale,'api-key', $apiKey); $this->plugin->appendXmlNode($xmlRequest, $xmlSale,'redirect-url', $redirect); if ($customer_vault_id) { ThePlugin::appendXmlNode( $xmlRequest, $xmlSale, 'customer-vault-id', $customer_vault_id); } else { // Set the Billing and Shipping from what was collected on initial shopping cart form $xmlBillingAddress = $xmlRequest->createElement('billing'); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'first-name', $user->name_f); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'last-name', $user->name_l); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'address1', $user->street); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'city', $user->city); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'state', $user->state); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'postal', $user->zip); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'country', $user->country); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'email', $user->email); $this->plugin->appendXmlNode($xmlRequest, $xmlBillingAddress,'phone', $user->phone); $xmlSale->appendChild($xmlBillingAddress); $xmlShippingAddress = $xmlRequest->createElement('shipping'); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'first-name', $user->name_f); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'last-name', $user->name_l); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'address1', $user->street); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'city', $user->city); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'state', $user->state); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'postal', $user->zip); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'country', $user->country); $this->plugin->appendXmlNode($xmlRequest, $xmlShippingAddress,'phone', $user->phone); $xmlSale->appendChild($xmlShippingAddress); } $xmlRequest->appendChild($xmlSale); return $xmlRequest; } function updateAction() { if (!$this->plugin->isConfigured()) { throw new Am_Exception( "Plugin networkmerchants-hosted " . "isn\'t configured"); } $APIKey = $this->plugin->getConfig('api_key'); $user = Am_Di::getInstance() ->auth ->getUser(); $customer_id = $user ->data() ->get('customer_vault_id'); $request = $this->createXmlRequest($user, $APIKey, $customer_id); ThePlugin::debug($request->saveXML()); $data = $this->plugin->sendXMLrequest($request, ThePlugin::GATEWAY_URL); ThePlugin::debug($data); // Parse Step One's XML response $gwResponse = @new SimpleXMLElement($data); if ((string)$gwResponse->result == 1) { // The form url for used in Step Two below $formURL = $gwResponse->{'form-url'}; } else { $message = (string)$gwResponse->{'result-text'}; Am_Di::getInstance() ->errorLogTable->log("NMI error, received: $message"); $url = $this->plugin->getPluginUrl(self::ACTION_FAILED) . '?message=' . htmlentities($message); return Am_Di::getInstance()->response->redirectLocation($url); } $form = new Am_Form_Nmi($this->plugin); if ($customer_id) { $ccNum = $user->data()->get('four_last'); $form->addStatic() ->setLabel('Current CC Number:') ->setContent($ccNum); } else { $form->addStatic() ->setContent('You dosn\'t have saved cc data yet'); } $this->plugin->configBaseForm($formURL, $form); $form->addSubmit('_cc_', array('value'=> 'Update')); $this->view->title = ___('Payment info'); $this->view->display_receipt = false; $this->view->form = $form; $this->view->display('cc/info.phtml'); } function createForm() { $user = $this->invoice->getUser(); $customer_id = $user->data()->get('customer_vault_id'); $request = $this->plugin->createXmlRequest($user, $this->invoice, $customer_id); ThePlugin::debug($request->saveXML()); $data = $this->plugin->sendXMLrequest($request, ThePlugin::GATEWAY_URL); ThePlugin::debug($data); // Parse Step One's XML response $gwResponse = @new SimpleXMLElement($data); if ((string)$gwResponse->result == 1) { // The form url for used in Step Two below $formURL = $gwResponse->{'form-url'}; } else { throw new Am_Exception("Error, received " . $data); } $form = $this->plugin->createForm($formURL, $user); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($user)) )); return $form; } } class Am_Form_Nmi extends Am_Form_CreditCard { function init() {} }PK\kD&2&2cc/plugins/paypal-pro.phpnu[ 'Visa', 'MasterCard' => 'MasterCard', 'Discover' => 'Discover', 'Amex' => 'Amex', // 'Maestro' => 'Maestro', // 'Solo' => 'Solo', ); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if(!$doFirst) return; // Recurring payments should not be handled by cron. if (!$invoice->rebill_times) { $request = new Am_Paysystem_PaypalApiRequest($this); $request->doSale($invoice, $cc); } else { $request = new Am_Paysystem_PaypalApiRequest($this); $request->createRecurringPaymentProfile($invoice, $cc); } $tr = new Am_Paysystem_Transaction_PaypalPro_CreateRecurringPaymentsProfile($this, $invoice, $request, $doFirst); $tr->run($result); // send payment request and check response } public function _initSetupForm(Am_Form_Setup $form) { Am_Paysystem_PaypalApiRequest::initSetupForm($form); $form->addAdvCheckbox('send_shipping')->setLabel("Send user's address as shipping address to PayPal"); } public function onSetupForms(Am_Event_SetupForms $event) { parent::onSetupForms($event); $event->getForm('paypal-pro')->removeElementByName('payment.'.$this->getId().'.reattempt'); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Incoming_PaypalPro($this, $request, $response, $invokeArgs); } public function cancelInvoice(Invoice $invoice) { $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = "cancelRecurringPaymentProfile"; $log->paysys_id = $this->getId(); $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->cancelRecurringPaymentProfile($invoice, $invoice->data()->get(self::PAYPAL_PROFILE_ID)); $result = $apireq->sendRequest($log); $log->setInvoice($invoice); $log->update(); if($result['ACK'] != 'Success') throw new Am_Exception_InputError('Transaction was not cancelled. Got error from paypal: '.$result['L_SHORTMESSAGE0']); } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = "refundTransaction"; $log->paysys_id = $this->getId(); $apireq = new Am_Paysystem_PaypalApiRequest($this); $apireq->refundTransaction($payment); $res = $apireq->sendRequest($log); $log->setInvoice($payment->getInvoice()); $log->update(); if($res['ACK'] != 'Success') throw new Am_Exception_InputError('Transaction was not refunded. Got error from paypal: '.$res['L_SHORTMESSAGE0']); $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($res['REFUNDTRANSACTIONID']); $result->setSuccess(); } public function ccRebill($date = null) { /* Disable cron rebill process * Rebills will be handled through IPN. */ } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<PayPal PRO payment plugin installation Up to date instructions how to enable and configure PayPal PRO plugin you may find at http://www.amember.com/docs/Payment/PaypalPro IMPORTANT: You MUST set IPN url in your Paypal Profile to: $url CUT; } public function getUpdateCcLink($user) { return $this->getPluginUrl('update'); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $profiles = array(); //Find all profiles which should be updated. foreach($this->getDi()->db->selectPage($total, " SELECT d.value, i.invoice_id FROM ?_data d LEFT JOIN ?_invoice i ON d.`table` = 'invoice' AND d.`key` = ? AND d.id = i.invoice_id WHERE i.user_id = ? AND i.status = ?", self::PAYPAL_PROFILE_ID, $cc->user_id, Invoice::RECURRING_ACTIVE) as $profile) { $profiles[$profile['value']] = $profile['invoice_id']; } $failures = array(); foreach($profiles as $profile_id=>$invoice_id) { $request = new Am_Paysystem_PaypalApiRequest($this); $request->setCc($invoice = $this->getDi()->invoiceTable->load($invoice_id), $cc); $request->addPostParameter('METHOD', 'UpdateRecurringPaymentsProfile'); $request->addPostParameter('PROFILEID', $profile_id); $request->addPostParameter('NOTE', 'Update CC info, customer IP: '.$this->getDi()->request->getHttpHost()); $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = "updateRecurringPaymentsProfile"; $log->paysys_id = $this->getId(); $res = $request->sendRequest($log); $log->setInvoice($invoice); $log->update(); if($res['ACK'] != 'Success') $failures[] = sprintf('CC info was not updated for profile: %s. Got error from paypal: %s', $profile_id, $res['L_SHORTMESSAGE0']); } if(count($failures)) $result->setFailed ($failures); else $result->setSuccess(); } function createController(\Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_CreditCard_PaypalPro($request, $response, $invokeArgs); } } /** * Overrided to avoid old profile updating on new payment. * Do not call update CC info when new payment is being processed. */ class Am_Mvc_Controller_CreditCard_PaypalPro extends Am_Mvc_Controller_CreditCard { public function processCc() { $cc = $this->getDi()->ccRecordRecord; $this->form->toCcRecord($cc); $cc->user_id = $this->invoice->user_id; if($this->plugin->getConfig('use_maxmind')) { $checkresult = $this->plugin->doMaxmindCheck($this->invoice, $cc); if (!$checkresult->isSuccess()) { $this->view->error = $checkresult->getErrorMessages(); return; } } $result = $this->plugin->doBill($this->invoice, true, $cc); if ($result->isSuccess()) { $this->_response->redirectLocation($this->plugin->getReturnUrl()); return true; } elseif ($result->isAction() && ($result->getAction() instanceof Am_Paysystem_Action_Redirect)) { $result->getAction()->process($this); // throws Am_Exception_Redirect (!) } else { $this->view->error = $result->getErrorMessages(); } } } class Am_Paysystem_Transaction_PaypalPro extends Am_Paysystem_Transaction_CreditCard { public function validate() { if (empty($this->vars['ACK'])) return $this->result->setFailed(___("Payment failed")); if (!in_array($this->vars['ACK'], array('Success', 'SuccessWithWarning'))) return $this->result->setFailed(___("Payment failed") . " : " . $this->vars['ACK']); // The next check is unnecessary. and it lead to an issue when paypal returns SuccessWithWarning response. // In this situation L_SHORTMESSAGE0 will have value. // // if (!empty($this->vars['L_SHORTMESSAGE0'])) // return $this->result->setFailed(___("Payment failed") . " : " . $this->vars['L_SHORTMESSAGE0']); $this->result->setSuccess(); } public function getUniqId() { return @$this->vars['TRANSACTIONID']; } public function parseResponse() { parse_str($this->response->getBody(), $this->vars); if (get_magic_quotes_gpc()) $this->vars = Am_Mvc_Request::ss($this->vars); } public function processValidated() { if ($this->invoice->first_total > 0) $this->invoice->addPayment($this); else $this->invoice->addAccessPeriod($this); // start free trial if (!empty($this->vars['PROFILEID'])) $this->invoice->data()->set(Am_Paysystem_PaypalPro::PAYPAL_PROFILE_ID, $this->vars['PROFILEID'])->update(); } } class Am_Paysystem_Transaction_PaypalPro_CreateRecurringPaymentsProfile extends Am_Paysystem_Transaction_PaypalPro { public function validate() { parent::validate(); // Need to do additional validations. // Sometimes paypal return transacton with ACK = Success ProfileStatus= PendingProfile and without transactionid. // In most situations this means that profile won't be created. So need to wait for IPN message to be sure. if( $this->result->isSuccess() && ($this->vars['PROFILESTATUS'] == 'PendingProfile') && empty($this->vars['TRANSACTIONID']) ) { $this->invoice->data()->set( Am_Paysystem_Transaction_Incoming_PaypalPro::IPN_STATUS_KEY, Am_Paysystem_Transaction_Incoming_PaypalPro::IPN_STATUS_WAITING )->update(); $sleep = 15; // Wait for 15 seconds; do{ sleep(1); $status = $this->invoice->data()->get(Am_Paysystem_Transaction_Incoming_PaypalPro::IPN_STATUS_KEY); }while((--$sleep) && ($status == Am_Paysystem_Transaction_Incoming_PaypalPro::IPN_STATUS_WAITING)); switch($status){ case Am_Paysystem_Transaction_Incoming_PaypalPro::IPN_STATUS_CANCELLED : case Am_Paysystem_Transaction_Incoming_PaypalPro::IPN_STATUS_WAITING : $this->result->reset(); $this->result->setFailed(___("Payment failed")); break; default: $this->vars['TRANSACTIONID'] = $status; } } return $this->result; } } class Am_Paysystem_Transaction_Incoming_PaypalPro extends Am_Paysystem_Transaction_Paypal { const TXN_RECURRING_PAYMENT_PROFILE_CREATED = "recurring_payment_profile_created"; const IPN_STATUS_KEY = 'paypal-ipn-status'; const IPN_STATUS_CANCELLED = 'cancelled'; const IPN_STATUS_WAITING = 'waiting'; function processValidated() { switch($this->txn_type){ case self::TXN_RECURRING_PAYMENT_PROFILE_CREATED : $this->invoice->data()->set(self::IPN_STATUS_KEY, $this->request->get('initial_payment_txn_id'))->update(); break; case self::TXN_RECURRING_PAYMENT_PROFILE_CANCEL : $this->invoice->data()->set(self::IPN_STATUS_KEY, self::IPN_STATUS_CANCELLED)->update(); break; } parent::processValidated(); } }PK\xpS"S"cc/plugins/payonlinesystem.phpnu[addText('merchant_id')->setLabel('Merchant ID'); $form->addText('security_key')->setLabel('Private Security Key'); $form->addSelect('language', '', array( 'options' => array( 'ru' => 'Русский', 'en' => 'English' ) ))->setLabel('Interface language'); $form->addAdvCheckbox('cc_form')->setLabel('Send User to CC form directly'); } function getSupportedCurrencies() { return array('RUB', 'USD', 'EUR'); } function isConfigured() { return $this->getConfig('merchant_id') && $this->getConfig('security_key'); } function getRedirectUrl() { return 'https://secure.payonlinesystem.com/' . $this->getConfig('language', 'ru') . '/payment/'.($this->getConfig('cc_form') ? '' : 'select/'); } public function getSecurityKey(Am_Paysystem_Action_Redirect $a) { return md5(sprintf('MerchantId=%s&OrderId=%s&Amount=%s&Currency=%s&OrderDescription=%s&PrivateSecurityKey=%s', $this->getConfig('merchant_id'), $a->OrderId, $a->Amount, $a->Currency, $a->OrderDescription, $this->getConfig('security_key') )); } public function getIncomingSecurityKey(Am_Mvc_Request $r) { return md5(sprintf('DateTime=%s&TransactionID=%s&OrderId=%s&Amount=%s&Currency=%s&PrivateSecurityKey=%s', $r->get('DateTime'), $r->get('TransactionID'), $r->get('OrderId'), $r->get('Amount'), $r->get('Currency'), $this->getConfig('security_key') )); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getRedirectUrl()); $a->MerchantId = $this->getConfig('merchant_id'); $a->OrderId = $invoice->public_id; $a->Amount = $invoice->first_total; $a->Currency = $invoice->currency; $a->OrderDescription = $invoice->getLineDescription(); $a->ReturnUrl = $this->getReturnUrl(); $a->FailUrl = $this->getCancelUrl(); $a->SecurityKey = $this->getSecurityKey($a); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_PayonlineSystem($this, $request, $response, $invokeArgs); } public function getReadme() { return <<PayOnlineSystem plugin configuration instructions 1. Enable plugin: go to aMember CP -> Setup/Configuration -> Plugins and enable "payonlinesystem" payment plugin. 2. In plugin configuration page set you Merchant ID and Private Security Key ( you can get it from your PayOnlineSystem Account -> Integration Settings) 3. On PayOnlineSystem account -> Integration Settings page enable Callback URL for approved transactions. Callback URL should be set to: %root_surl%/payment/payonlinesystem/ipn NOTE: This is necessary to configure https url in aMember CP -> Setup -> Global -> License & Root URLS. Rebill notifications can be sent to https url only. CUT; } function storesCcInfo() { return false; } function getRefundSecurityKey(Array $vars) { return md5(sprintf('MerchantId=%s&TransactionId=%s&Amount=%s&PrivateSecurityKey=%s', $vars['MerchantId'], $vars['TransactionId'], $vars['Amount'], $this->getConfig('security_key') )); } function getRebillSecurityKey(Array $vars) { return md5(sprintf('MerchantId=%s&RebillAnchor=%s&OrderId=%s&Amount=%s&Currency=%s&PrivateSecurityKey=%s', $vars['MerchantId'], $varsp['RebillAnchor'], $vars['OrderId'], $vars['Amount'], $vars['Currency'], $this->getConfig('security_key') )); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $request = new Am_HttpRequest(self::REFUND_URL, Am_HttpRequest::METHOD_POST); $vars = array( 'MerchantId' => $this->getConfig('merchant_id'), 'TransactionId' => $payment->receipt_id, 'Amount' => $amount, 'ContentType' => 'text' ); $vars['SecurityKey'] = $this->getRefundSecurityKey($vars); foreach ($vars as $k => $v) { $request->addPostParameter($k, $v); } $this->logRequest($request); $response = $request->send(); $this->logResponse($response); if ($response->getStatus() != 200) throw new Am_Exception_InputError("An error occurred during refund request"); parse_str($response->getBody(), $parsed); if ($parsed['Result'] != 'Ok') throw new Am_Exception_InputError("An error occurred during refund request: " . $parsed['Message']); $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($parsed['TransactionId'] . '-refund'); $result->setSuccess($trans); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times && ($invoice->first_total != $invoice->second_total)) { return 'Rebilling amount should be the same as first payment amount.'; } } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $r = new Am_HttpRequest(self::REBILL_URL, Am_HttpRequest::METHOD_POST); $vars = array( 'MerchantId' => $this->getConfig('merchant_id'), 'RebillAnchor' => $invoice->data()->get(self::REBILL_ANCHOR), 'OrderId' => $invoice->public_id . '-' . $invoice->getPaymentsCount(), 'Amount' => $invoice->second_total, 'Currency' => $invoice->currency, 'ContentType' => 'text' ); $vars['SecurityKey'] = $this->getRebillSecurityKey($vars); foreach ($vars as $k => $v) { $r->addPostParameter($k, $v); } $transaction = new Am_Paysystem_Transaction_PayonlineSystemRebill($this, $invoice, $r, $doFirst); $transaction->run($result); } } class Am_Paysystem_Transaction_PayonlineSystem extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('TransactionID'); } public function findInvoiceId() { return $this->request->get('OrderId'); } public function validateSource() { return $this->getPlugin()->getIncomingSecurityKey($this->request) == $this->request->get('SecurityKey'); } public function validateStatus() { return true; } public function validateTerms() { return floatval($this->request->get('Amount')) === floatval($this->invoice->first_total); } public function processValidated() { parent::processValidated(); if ($this->request->get('RebillAnchor')) $this->invoice->data()->set(Am_Paysystem_Payonlinesystem::REBILL_ANCHOR, $this->request->get('RebillAnchor'))->update(); } } class Am_Paysystem_Transaction_PayonlineSystemRebill extends Am_Paysystem_Transaction_CreditCard { public function getUniqId() { return $this->response['TransactionId']; } public function parseResponse() { // TransactionId={TransactionId}&Operation=Rebill&Result={Result}&Status={Status}&Code={Code}&ErrorCode={ErrorCode} parse_str($this->response, $arr); $this->response = $arr; } public function validate() { if ($this->response['Result'] == 'Ok' && $this->response['Status'] != 'Declined') $this->result->setSuccess($this); else $this->result->setFailed('Error processing transaction: ' . $this->response['Status'] . ' - ' . $this->response['ErrorCode']); } }PK\s-..cc/plugins/securepaycomau.phpnu[getConfig('merchant_id')) && strlen($this->getConfig('password')); } function get_xml($arr) { return $s = ''. $this->form_xml($arr); } function form_xml($arr) { $res = ''; foreach($arr as $k=>$v){ $l = preg_replace("/( .*)/i",'',$k); if(is_array($v)) $res.="<$k>".$this->form_xml($v).""; else $res.="<$k>$v"; } return $res; } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $user = $invoice->getUser(); if ($cc->user_id != $user->pk()) throw new Am_Exception_Paysystem("Assertion failed: cc.user_id != user.user_id"); // will be stored only if cc# or expiration changed $this->storeCreditCard($cc, $result); if (!$result->isSuccess()) return; $user->refresh(); // we have both profile id and payment id, run the necessary transaction now if amount > 0 $result->reset(); if ($doFirst && !$invoice->first_total) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $tr = new Am_Paysystem_Transaction_Securepaycomau_Payment($this, $invoice, $doFirst); $tr->run($result); } } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("merchant_id")->setLabel("Merchant ID\n" . '5 or 7-character merchant ID supplied by SecurePay'); $form->addText("password")->setLabel("Payment password\n" . 'Password used for authentication of the merchant\'s request message, supplied by SecurePay'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $user = $this->getDi()->userTable->load($cc->user_id); $clientId = $user->data()->get(self::CLIENT_ID); if ($this->invoice) { // to link log records with current invoice $invoice = $this->invoice; } else { // updating credit card info? $invoice = $this->getDi()->invoiceRecord; $invoice->invoice_id = 0; $invoice->user_id = $user->pk(); } // compare stored cc for that user may be we don't need to refresh? if ($clientId && ($cc->cc_number != '0000000000000000')) { $storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk()); if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)) || ($storedCc->cc_expire != $cc->cc_expire))) { $user->data()->set(self::CLIENT_ID, null)->update(); $clientId = null; } } if (!$clientId) { try { $tr = new Am_Paysystem_Transaction_Securepaycomau_CreateCustomerProfile($this, $invoice, $cc); $tr->run($result); if (!$result->isSuccess()) return; $user->data()->set(self::CLIENT_ID, $tr->getClientId())->update(); } catch (Am_Exception_Paysystem $e) { $result->setFailed($e->getPublicError()); return false; } } /// $cc->cc = $cc->maskCc(@$cc->cc_number); $cc->cc_number = '0000000000000000'; if ($cc->pk()) $cc->update(); else $cc->replace(); $result->setSuccess(); } /*public function getReadme() { return << Customer Information Manager -> Sign Up Now) This is a paid service. 1. Enable and configure plugin in aMember CP -> Setup -> Plugins 2. You NEED to use external cron with this plugins (See Setup/Configuration -> Advanced) CUT; }*/ function isRefundable(InvoicePayment $payment) { return false; } } abstract class Am_Paysystem_Transaction_Securepaycomau extends Am_Paysystem_Transaction_CreditCard { protected $response = null; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst = true) { parent::__construct($plugin, $invoice, $plugin->createHttpRequest(), $doFirst); $this->request->setHeader('Content-type', 'text/xml'); $this->request->setBody($this->createXml()); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setUrl(!$this->plugin->getConfig('testing') ? Am_Paysystem_Securepaycomau::LIVE_URL : Am_Paysystem_Securepaycomau::SANDBOX_URL); } public function parseResponse() { $p = xml_parser_create(); xml_parse_into_struct($p, $this->response->getBody(), $vals, $index); $res = array(); foreach($vals as $v) if(isset($v['value'])) $res[$v['tag']] = $v['value']; $this->response = $res; } } class Am_Paysystem_Transaction_Securepaycomau_CreateCustomerProfile extends Am_Paysystem_Transaction_Securepaycomau { /** @var CcRecord */ protected $cc; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc) { $this->cc = $cc; parent::__construct($plugin, $invoice); } protected function createXml() { $user = $this->invoice->getUser(); $z = date('Z')/60; if($z>=0)$z='+'.$z; $z = date('YdmHis')."000000$z"; $vars = array( 'SecurePayMessage'=>array( 'MessageInfo' => array( 'messageID' => substr(md5($this->invoice->public_id.time()),2), 'messageTimestamp' => $z, 'timeoutValue' => '60', 'apiVersion' => 'spxml-3.0' ), 'MerchantInfo'=>array( 'merchantID'=>$this->getPlugin()->getConfig('merchant_id'), 'password'=>$this->getPlugin()->getConfig('password') ), 'RequestType' => 'Periodic', 'Periodic' => array( 'PeriodicList count="1"' => array( 'PeriodicItem ID="1"' => array( 'actionType' => 'add', 'clientID' => substr(md5(time().$user->user_id),20), 'amount' => 1000, 'periodicType' => '4', 'CreditCardInfo'=>array( 'cardNumber'=>$this->cc->cc_number, 'expiryDate'=>substr($this->cc->cc_expire,0,2).'/'.substr($this->cc->cc_expire, 2,2), 'cvv' => $this->cc->getCvv() ), 'BuyerInfo' => array( 'ip' => $user->remote_addr, 'zipcode' => $user->zip, 'town' => $user->city, 'billingCountry' => $user->country, 'emailAddress' => $user->email, 'firstName' => $user->name_f, 'lastName'=>$user->name_l ) ) ) ) )); $xml = $this->getPlugin()->get_xml($vars); return $xml; } public function getClientId(){ return $this->response['CLIENTID']; } public function validate() { if ($this->response['STATUSCODE'] == '000' && in_array(intval($this->response['RESPONSECODE']),array(0,8,11,16,77))){ $this->result->setSuccess(); return true; } elseif(!@in_array(intval($this->response['RESPONSECODE']),array(0,8,11,16,77))) { $this->result->setFailed((string)$this->response['RESPONSETEXT'].' , ERROR CODE - '.intval($this->response['STATUSCODE'])); return; } else { $this->result->setFailed((string)$this->response['STATUSDESCRIPTION'].' , ERROR CODE - '.intval($this->response['STATUSCODE'])); return; } } function getProfileId() { return (string)$this->xml->customerProfileId; } function getPaymentId() { return (string)$this->xml->customerPaymentProfileIdList->numericString; } public function getUniqId() { return (string)$this->xml->customerProfileId; } public function processValidated() { } } class Am_Paysystem_Transaction_Securepaycomau_Payment extends Am_Paysystem_Transaction_Securepaycomau { protected function createXml() { $user = $this->invoice->getUser(); $z = date('Z')/60; if($z>=0)$z='+'.$z; $z = date('YdmHis')."000000$z"; $vars = array( 'SecurePayMessage'=>array( 'MessageInfo' => array( 'messageID' => substr(md5($this->invoice->public_id.time()),2), 'messageTimestamp' => $z, 'timeoutValue' => '60', 'apiVersion' => 'spxml-3.0' ), 'MerchantInfo'=>array( 'merchantID'=>$this->getPlugin()->getConfig('merchant_id'), 'password'=>$this->getPlugin()->getConfig('password') ), 'RequestType' => 'Periodic', 'Periodic' => array( 'PeriodicList count="1"' => array( 'PeriodicItem ID="1"' => array( 'actionType' => 'trigger', 'clientID' => $user->data()->get(Am_Paysystem_Securepaycomau::CLIENT_ID), 'amount' => intval(($this->doFirst ? $this->invoice->first_total : $this->invoice->second_total)*100), ) ) ) )); return $this->getPlugin()->get_xml($vars); } public function validate() { if ($this->response['STATUSCODE'] == '000' && in_array(intval($this->response['RESPONSECODE']),array(0,8,11,16,77))){ $this->result->setSuccess(); return true; } elseif(!@in_array(intval($this->response['RESPONSECODE']),array(0,8,11,16,77))) { $this->result->setFailed((string)$this->response['RESPONSETEXT'].' , ERROR CODE - '.intval($this->response['STATUSCODE'])); return; } else { $this->result->setFailed((string)$this->response['STATUSDESCRIPTION'].' , ERROR CODE - '.intval($this->response['STATUSCODE'])); return; } $this->result->setSuccess($this); return true; } public function getUniqId() { return $this->response['TXNID']; } public function processValidated() { $this->invoice->addPayment($this); } } PK\@Y,,cc/plugins/dibs-recurring.phpnu[ '208', 'EUR' => '978', 'USD' => '840', 'GBP' => '826', 'SEK' => '752', 'AUD' => '036', 'CAD' => '124', 'ISK' => '352', 'JPY' => '392', 'NZD' => '554', 'NOK' => '578', 'CHF' => '756', 'TRY' => '949'); protected $error_codes = array( '0' => 'Rejected by acquirer', '1' => 'Communication problems', '2' => 'Error in the parameters sent to the DIBS server. An additional parameter called "message" is returned, with a value that may help indentifying error', '3' => 'Error at the acquirer', '4' => 'Credit card expired', '5' => 'Your shop does not support this credit card type, the credit card type could not be identified, or the credit card number was not modulus correct', '6' => 'Instant capture failed', '7' => 'The order number (orderid) is not unique', '8' => 'There number of amount parameters does not correspond to the number given in the split parameter', '9' => 'Control numbers (cvc) are missing', '10' => 'The credit card does not comply with the credit card type', '11' => 'Declined by DIBS Defender', '20' => 'Cancelled by user at 3D Secure authentication step' ); public function getRecurringType() { return self::REPORTS_CRONREBILL; } function storesCcInfo(){ return false; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::FORM_URL); $order_id = $invoice->public_id."-".sprintf("%03d", $invoice->getPaymentsCount()); $currency = $this->getCurrencyCode($invoice); $a->merchant = $this->getConfig('merchant'); $a->amount = intval($invoice->first_total*100); $a->currency = $currency; $a->orderid = $order_id; $a->lang = $this->getConfig('lang'); $a->accepturl = $this->getReturnUrl($request); $a->cancelurl = $this->getCancelUrl($request); $a->continueurl = $this->getReturnUrl(); $a->callbackurl = $this->getPluginUrl('ipn'); $a->preauth = 'true'; if($this->getConfig('testing')) $a->test = 'yes'; $a->md5key = $this->getOutgoingMd5($a); $result->setAction($a); } function getOutgoingMd5(Am_Paysystem_Action_Redirect $a) { return md5($s2 = $this->getConfig('key2').md5($s1 = $this->getConfig('key1')."merchant=".$this->getConfig('merchant'). "&orderid=".$a->orderid."¤cy=".$a->currency."&amount=".$a->amount)); } function getIncomingMd5(Am_Mvc_Request $r, Invoice $invoice) { $currency = $this->getCurrencyCode($invoice); $key = md5($s2 = $this->getConfig('key2').md5($s1 = $this->getConfig('key1')."transact=".$r->get('transact'). "&preauth=true¤cy=".$currency)); return $key; } public function getSupportedCurrencies() { return array_keys($this->currency_codes); } function getCurrencyCode($invoice) { return $this->currency_codes[strtoupper($invoice->currency)]; } function getDibsRecurringError($reason) { return $this->error_codes[$reason]; } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc=null, Am_Paysystem_Result $result) { $request = new Am_HttpRequest(self::TICKET_AUTH_URL, Am_HttpRequest::METHOD_POST); $order_id = $invoice->public_id."-".sprintf("%03d",$invoice->getPaymentsCount() + 1); $currency = $this->getCurrencyCode($invoice); $amount = ($doFirst ? $invoice->first_total : $invoice->second_total) * 100; $post_params = new stdclass; $post_params->merchant = $this->getConfig('merchant'); $post_params->amount = $amount; $post_params->orderId = $order_id; $post_params->ticket = $invoice->data()->get(self::TICKET); $post_params->textreply = 'true'; $post_params->currency = $currency; $post_params->capturenow = 'true'; $post_params->md5key = md5($s2 = $this->getConfig('key2').md5($s1 = $this->getConfig('key1')."merchant=".$this->getConfig('merchant'). "&orderid=".$order_id."&ticket=".$invoice->data()->get(self::TICKET)."¤cy=".$currency."&amount=".$amount)); if($this->getConfig('testing')) $post_params->test = 'yes'; $request->addPostParameter((array)$post_params); $transaction = new Am_Paysystem_Transaction_DibsRecurringSale($this, $invoice, $request, $doFirst); $transaction->run($result); } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $request = new Am_HttpRequest("https://".$this->getConfig('login').":".$this->getConfig('password')."@payment.architrade.com/cgi-adm/refund.cgi"); $invoice = $payment->getInvoice(); $currency = $this->getCurrencyCode($invoice); $post_params = new stdclass; $post_params->merchant = $this->getConfig('merchant'); $post_params->amount = $amount*100; $count = $this->getDi()->db->selectCol("SELECT COUNT(*) FROM ?_invoice_payment WHERE invoice_id=?d AND dattm < ? ", $payment->invoice_id, $payment->dattm); $post_params->orderId = $invoice->public_id."-".sprintf("%03d", array_shift($count)); $post_params->transact = $invoice->data()->get(self::TICKET); $post_params->textreply = 'true'; $post_params->currency = $currency; $post_params->md5key = md5($s2 = $this->getConfig('key2').md5($s1 = $this->getConfig('key1')."merchant=".$this->getConfig('merchant'). "&orderid=".$invoice->public_id."&transact=".$invoice->data()->get(self::TICKET)."&amount=".$amount)); $request->addPostParameter((array)$post_params); $response = $request->send(); $response = $this->parseResponse($response->getBody()); if ($response['result'] === 0) { $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id.'-dibs-refund'); $result->setSuccess($trans); } else { $result->setFailed(array('Error Processing Refund!')); } } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant', array('size' => 20, 'maxlength' => 16)) ->setLabel("Dibs Merchant ID") ->addRule('required'); $form->addText('key1', array('size' => 20, 'maxlength' => 32)) ->setLabel("Dibs Secret Key1") ->addRule('required'); $form->addText('key2', array('size' => 20, 'maxlength' => 32)) ->setLabel("Dibs Secret Key2") ->addRule('required'); $form->addText("login") ->setLabel("Dibs login\n" . "It's needs for performing the refund") ->addRule('required'); $form->addText("password") ->setLabel("Dibs password\n" . "It's needs for performing the refund") ->addRule('required'); $form->addSelect('lang', array(), array('options' => array( 'da' => 'Danish', 'sv' => 'Swedish', 'no' => 'Norwegian', 'en' => 'English', 'nl' => 'Dutch', 'de' => 'German', 'fr' => 'French', 'fi' => 'Finnish', 'es' => 'Spanish', 'it' => 'Italian', 'fo' => 'Faroese', 'pl' => 'Polish' )))->setLabel('The payment window language'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } function getReadme() { return <<DIBS Payment Plugin Configuration 1. Login to DIBS Administration and then go to "integration" -> Return Values. 2. Please check "orderid" parameter. CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_DibsRecurring($this, $request, $response, $invokeArgs); } public function parseResponse($body) { $result = ''; $params = explode("&", $body); foreach($params as $param) { list($k, $v) = explode("=",$param); $result[$k] = $v; } return $result; } } class Am_Paysystem_Transaction_DibsRecurring extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->get('transact'); } public function findInvoiceId() { return $this->request->get('orderid'); } public function validateStatus() { if($this->request->get('statuscode') != NULL) return $this->request->get('statuscode') == '2'; else return true; } public function validateTerms() { return true; } public function validateSource() { //Am_Di::getInstance()->invoiceTable->loadIds($this->request->get('orderid')); $orderid = explode("-",$this->request->get('orderid')); $invoice = Am_Di::getInstance()->invoiceTable->findFirstByPublicId($orderid[0]); if(is_null($invoice)) return; if($this->getPlugin()->getIncomingMd5($this->request, $invoice) != $this->request->get('authkey')) return false; if($this->request->get('transact')){ $invoice->data()->set(Am_Paysystem_DibsRecurring::TICKET, $this->request->get('transact'))->update(); } $result = new Am_Paysystem_Result(); $this->getPlugin()->_doBill($invoice, true, null, $result); return true; } public function processValidated() { } } class Am_Paysystem_Transaction_DibsRecurringSale extends Am_Paysystem_Transaction_CreditCard { public function validate() { if($this->vars['status'] != 'ACCEPTED') { $this->result->setFailed("Payment failed : ".$this->plugin->getDibsRecurringError($this->vars['reason'])); } else { $this->result->setSuccess($this); } } public function parseResponse(){ $body = $this->response->getBody(); return $this->vars = $this->plugin->parseResponse($body); } public function getUniqId() { return $this->vars['transact']; } } PK\/xFxFcc/plugins/uniteller.phpnu[ 'https://wpay.uniteller.ru/pay/', 'result' => 'https://wpay.uniteller.ru/results/', 'refund' => 'https://wpay.uniteller.ru/unblock/', 'rebill' => 'https://wpay.uniteller.ru/recurrent/', ); public static $urlsTest = array( 'pay' => 'https://test.wpay.uniteller.ru/pay/', 'result' => 'https://test.wpay.uniteller.ru/results/', ); private static $meanType = array( 0 => 'Any', 1 => 'VISA', 2 => 'MasterCard', 3 => 'Diners Club', 4 => 'JCB', 5 => 'AMEX (not support now)', ); private static $eMoneyType = array( 0 => 'Any', 1 => 'Яндекс.Деньги', 2 => 'RBK Money', 3 => 'MoneyMail', 4 => 'WebCreds', 5 => 'EasyPay', 6 => 'Platezh.ru', 7 => 'Деньги@Mail.Ru', 8 => 'Мобильный платёж Мегафон', 9 => 'Мобильный платёж МТС', 10 => 'Мобильный платёж Билайн', 11 => 'PayPal', 12 => 'ВКонтакте', 13 => 'Евросеть', 14 => 'Yota.money', 15 => 'QIWI Кошелек', 16 => 'ПлатФон', 17 => 'Moneybookers', 29 => 'WebMoney WMR', ); public function getRecurringType() { return self::REPORTS_CRONREBILL; } public function getFormOptions() { $ret = parent::getFormOptions(); $ret[] = self::CC_PHONE; return $ret; } protected function _initSetupForm(Am_Form_Setup $form) { $form->addText('shopId') ->setLabel(/*"Shop ID"*/"Uniteller Point ID") ->addRule('required'); $form->addText('login') ->setLabel("Login\n" . "from your acount at Uniteller serice") ->addRule('required'); $form->addText('password', array('size' => 80)) ->setLabel("Password\n" . "from your acount at Uniteller serice") ->addRule('required'); $form->addSelect('language') ->setLabel("Interface Language") ->loadOptions(array( 'ru' => 'Russain', 'en' => 'English' )); $form->addSelect('meanType') ->setLabel("Credit Card Payment System\n" . "not use in test mode") ->loadOptions(self::$meanType); $form->addSelect('eMoneyType') ->setLabel("Type of e-Currency\n" . "not use in test mode") ->loadOptions(self::$eMoneyType); $form->addAdvCheckbox("testMode") ->setLabel("Test Mode Enabled"); $form->addAdvCheckbox("debugLog") ->setLabel("Debug Log Enabled\n" . "write all requests/responses to log"); } public function isConfigured() { return $this->getConfig('shopId') && $this->getConfig('login') && $this->getConfig('password'); } public function getUrl($action = 'pay') { if ($this->getConfig('testMode')) { if (isset(self::$urlsTest[$action])) return self::$urlsTest[$action]; $mode = 'TEST'; } else { if (isset(self::$urlsLive[$action])) return self::$urlsLive[$action]; $mode = 'LIVE'; } throw new Am_Exception_InternalError("Unknown action at $mode mode: [$action]"); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc = null, Am_Paysystem_Result $result) { if (!$doFirst) { $tr = new Am_Paysystem_Transaction_CreditCard_UnitellerRebill($this, $invoice, $doFirst); $tr->run($result); } } public function loadCreditCard(Invoice $invoice) { return $this->getDi()->CcRecordTable->createRecord(); // return fake record for rebill } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $post = array( 'Shop_IDP' => $this->getConfig('shopId'), 'Order_IDP' => $invoice->public_id, 'Subtotal_P' => $invoice->first_total, 'URL_RETURN' => $this->getRootUrl(), 'URL_RETURN_OK' => $this->getReturnUrl(), 'URL_RETURN_NO' => $this->getCancelUrl(), 'Language' => $this->getConfig('language'), 'Comment' => $invoice->getLineDescription(), 'FirstName' => $user->name_f, 'LastName' => $user->name_l, 'Email' => $user->email, 'Phone' => $user->phone, 'Address' => $user->street, 'Country' => $this->getDi()->countryTable->getTitleByCode($user->country), //not use now 'State' => $user->state, 'City' => $user->city, 'Zip' => $user->zip, ); if (!$this->getConfig('testMode')) { $post['MeanType'] = $this->getConfig('meanType'); $post['EMoneyType'] = $this->getConfig('eMoneyType'); $post['Signature'] = strtoupper(md5( md5($this->getConfig('shopId')) . "&" . md5($invoice->public_id) . "&" . md5($invoice->first_total) . "&" . md5($this->getConfig('meanType')) . "&" . md5($this->getConfig('eMoneyType')) . "&" . md5('') . "&" . //Lifetime md5('') . "&" . //Customer_ID md5('') . "&" . //Card_ID md5('') . "&" . //IData md5('') . "&" . //PT_Code md5($this->getConfig('password')) )); } else { // for test payment $post['Signature'] = strtoupper(md5( md5($this->getConfig('shopId')) . "&" . md5($invoice->public_id) . "&" . md5($invoice->first_total) . "&" . md5('') . "&" . //meanType md5('') . "&" . //eMoneyType md5('') . "&" . //Lifetime md5('') . "&" . //Customer_ID md5('') . "&" . //Card_ID md5('') . "&" . //IData md5('') . "&" . //PT_Code md5($this->getConfig('password')) )); } if ($this->getConfig('debugLog')) $this->getDi()->errorLogTable->log("UNITELLER [directAction-cc] request: " . json_encode($post)); $a = new Am_Paysystem_Action_Form($this->getUrl()); foreach($post as $k => $v) $a->addParam ($k, $v); $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getActionName() == self::ACTION_IPN) { $log = $this->logRequest($request); if ($this->getConfig('debugLog')) $this->getDi()->errorLogTable->log("UNITELLER [directAction-ipn] request: " . json_encode($request->getParams())); $expSign = strtoupper(md5($request->getParam('Order_ID') . $request->getParam('Status') . $this->getConfig('password'))); $getSign = $request->getParam('Signature'); if ($expSign != $getSign) throw new Am_Exception_InputError("Plugin Uniteller: Bad signature, expected [$expSign], getted [$getSign]"); $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($request->getParam('Order_ID')); if (!$invoice) return; $result = new Am_Paysystem_Result(); $tr = new Am_Paysystem_Transaction_CreditCard_UnitellerResult($this, $invoice, true); $tr->run($result); } else { return parent::directAction($request, $response, $invokeArgs); } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $trans = new Am_Paysystem_Transaction_CreditCard_UnitellerRefund($this, $payment->getInvoice(), $payment->receipt_id, $amount); $trans->run($result); } public function getReadme() { return << contracts -> shop settings and enter: shop URL: {$this->getRootUrl()} notification URL: {$this->getPluginUrl('ipn')} - click "Save" ########################################################## Настройка платежного плагина Uniteller Этот плагин позволяет Вам использвать сервис Uniteller для приема платежей. Для настройки плагина: - зарегистрируйте аккаунт на сайте uniteller.ru - заполните необходимые поля на странице настроек плагина Uniteller (эта страница) если используется тестовый аккаунт в поле "Shop ID" внести значение из личного кабинета -> Договоры -> Shop_ID иначе - из личного кабинета -> Точки продаж -> Uniteller Point ID данные для полей "Login" и "Password" взять из личного кабинет -> Параметры Авторизации - сохраните настройки - в личном кабинете Uniteller "Договоры -> Настройки" заполните поля: URL-адрес магазина: {$this->getRootUrl()} URL для уведомление сервера интернет-магазина об изменившемся статусе счёта/оплаты: {$this->getPluginUrl('ipn')} - сохраните настройки CUT; } } class Am_Paysystem_Transaction_CreditCard_Uniteller extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); protected $act; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst) { $request = new Am_HttpRequest(); parent::__construct($plugin, $invoice, $request, $doFirst); $this->request->setUrl($this->plugin->getUrl($this->act)); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->addRequestParams(); } public function getAmount() { return $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total; } protected function addRequestParams() { } public function getUniqId() { return $this->parsedResponse->orders->order->billnumber; } public function getOrderId() { return $this->parsedResponse->orders->order->ordernumber; } public function parseResponse() { $this->parsedResponse = simplexml_load_string($this->response->getBody()); if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log("UNITELLER [{$this->act}] response: " . json_encode((array)$this->parsedResponse)); } } class Am_Paysystem_Transaction_CreditCard_UnitellerResult extends Am_Paysystem_Transaction_CreditCard_Uniteller { protected $act = 'result'; protected function addRequestParams() { $this->request->addPostParameter('Shop_ID', $this->plugin->getConfig('shopId')); $this->request->addPostParameter('Login', $this->plugin->getConfig('login')); $this->request->addPostParameter('Password', $this->plugin->getConfig('password')); $this->request->addPostParameter('ShopOrderNumber', $this->invoice->public_id); $this->request->addPostParameter('Format', 4); // 1-CSV, 4-XML if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log("UNITELLER [result] request: " . json_encode($this->request->getPostParams())); } public function validate() { switch ($this->parsedResponse->orders->order->status) { case 'Authorized': case 'Paid': break; default: $err = "Error: {$this->parsedResponse->orders->order->status} - {$this->parsedResponse->orders->order->error_comment} [#{$this->parsedResponse->orders->order->error_code}]."; break; } if (!empty($err)) { return $this->result->setFailed(array($err)); } $this->result->setSuccess($this); } } class Am_Paysystem_Transaction_CreditCard_UnitellerRefund extends Am_Paysystem_Transaction_CreditCard_Uniteller { protected $act = 'refund'; protected $amount; protected $orig_id; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $billNumber, $amount) { $this->amount = $amount; parent::__construct($plugin, $invoice, true); $this->orig_id = $billNumber; $this->request->addPostParameter('Shop_ID', $this->plugin->getConfig('shopId')); $this->request->addPostParameter('Login', $this->plugin->getConfig('login')); $this->request->addPostParameter('Password', $this->plugin->getConfig('password')); $this->request->addPostParameter('Billnumber', $billNumber); $this->request->addPostParameter('Subtotal_P', $this->getAmount()); $this->request->addPostParameter('Format', 3); // 1-CSV, 3-XML if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log("UNITELLER [refund] request: " . json_encode($this->request->getPostParams())); } public function getAmount() { return $this->amount; } public function validate() { if((string)$this->parsedResponse->attributes()->firstcode) { return $this->result->setFailed(array("Error: ".(string)$this->parsedResponse->attributes()->secondcode." [#".(string)$this->parsedResponse->attributes()->firstcode."]")); } $this->result->setSuccess($this); } function processValidated() { $this->invoice->addRefund($this, $this->orig_id); } } class Am_Paysystem_Transaction_CreditCard_UnitellerRebill extends Am_Paysystem_Transaction_CreditCard_Uniteller { protected $act = 'rebill'; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst) { parent::__construct($plugin, $invoice, $doFirst); //$this->request->addPostParameter('Billnumber', $billNumber); $this->request->addPostParameter('Subtotal_P', $this->getAmount()); $this->request->addPostParameter('Format', 3); // 1-CSV, 3-XML if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log("UNITELLER [rebill] request: " . json_encode($this->request->getPostParams())); } protected function addRequestParams() { $Order_IDP = $this->invoice->public_id . '-' . Am_Di::getInstance()->security->randomString(4); $this->request->addPostParameter('Shop_IDP', $this->plugin->getConfig('shopId')); $this->request->addPostParameter('Order_IDP', $Order_IDP); $this->request->addPostParameter('Subtotal_P', $this->getAmount()); $this->request->addPostParameter('Parent_Order_IDP', $this->invoice->public_id); $sign = strtoupper(md5( md5($this->plugin->getConfig('shopId')) . "&" . md5($Order_IDP) . "&" . md5($this->getAmount()) . "&" . md5($this->invoice->public_id) . "&" . md5($this->plugin->getConfig('password')) )); $this->request->addPostParameter('Signature', $sign); } public function parseResponse() { list($keys,$values) = explode(PHP_EOL,$this->response->getBody()); $keys = str_getcsv($keys, ';'); $values = str_getcsv($values, ';'); $this->parsedResponse = new stdClass(); foreach($keys as $k => $v) if(!empty($v)) $this->parsedResponse->$v = $values[$k]; if ($this->plugin->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log("UNITELLER [rebill] response: " . json_encode($this->parsedResponse)); } public function validate() { if(isset($this->parsedResponse->ErrorCode)) { return $this->result->setFailed(array("Error: {$this->parsedResponse->ErrorMessage} [#{$this->parsedResponse->ErrorCode}].")); } elseif($this->parsedResponse->Status != 'Authorized' && $this->parsedResponse->Status != 'Paid') { return $this->result->setFailed(array("Error: {$this->parsedResponse->Recommendation}. Status: {$this->parsedResponse->Status}.")); } $this->result->setSuccess($this); } public function getUniqId() { return $this->parsedResponse->BillNumber; } function processValidated() { $this->invoice->addPayment($this); } }PK\M9EyEycc/plugins/stripe.phpnu[getUser()->data()->get(self::TOKEN); if (!$token) return $result->setErrorMessages(array(___('Payment failed'))); if ($doFirst && (doubleval($invoice->first_total) <= 0)) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $tr = new Am_Paysystem_Transaction_Stripe($this, $invoice, $doFirst); $tr->run($result); } } public function getUpdateCcLink($user) { if ($user->data()->get(self::TOKEN)) return $this->getPluginUrl('update'); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { } public function loadCreditCard(Invoice $invoice) { if ($invoice->getUser()->data()->get(self::TOKEN)) return $this->getDi()->CcRecordTable->createRecord(); // return fake record for rebill } protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $invokeArgs['hosted'] = $this->getConfig('hosted'); return new Am_Mvc_Controller_CreditCard_Stripe($request, $response, $invokeArgs); } protected function _initSetupForm(Am_Form_Setup $form) { $form->addText('secret_key', array('class'=>'el-wide'))->setLabel('Secret Key')->addRule('required'); $form->addText('public_key', array('class'=>'el-wide'))->setLabel('Publishable Key')->addRule('required'); $label = "Use Hosted Version (recommended)\n". "this option allows you to display credit card input right on your website\n". "(as a popup) and in the same time it does not require PCI DSS compliance"; if ('https' != substr(ROOT_SURL,0,5)) $label .= "\n" . 'This option requires https on your site'; $form->addAdvCheckbox('hosted', array('id'=>'hosted-version'))->setLabel($label); $form->addText('image_url', array('class'=>'el-wide', 'rel'=>'hosted-version')) ->setLabel("Image URL\nA relative or absolute URL to a square image of your brand or product. Recommended minimum size is 128x128px. Supported image types are: .gif, .jpeg, and .png."); $form->addAdvCheckbox('zip_validate', array('rel'=>'hosted-version')) ->setLabel("Validate Postal Code?\nSpecify whether Checkout should validate the billing postal code"); $form->addScript() ->setScript(<<getInvoice(), $payment->receipt_id, $amount); $tr->run($result); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Stripe_Webhook($this, $request, $response, $invokeArgs); } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<charge.refunded $url CUT; } } class Am_Mvc_Controller_CreditCard_Stripe extends Am_Mvc_Controller { /** @var Invoice*/ protected $invoice; /** @var Am_Paysystem_Stripe */ protected $plugin; public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } public function setPlugin($plugin) { $this->plugin = $plugin; } public function createForm($label, $cc_mask = null) { if($this->getInvokeArg('hosted')) return $this->createFormHosted($label, $cc_mask); else return $this->createFormRegular($label, $cc_mask); } public function createFormHosted($label, $cc_mask = null) { $form = new Am_Form('cc-stripe'); $key = $this->plugin->getConfig('public_key'); $amount = $this->invoice->first_total*100; $currency = $this->invoice->currency; $email = $this->invoice->getEmail(); $name = $this->getDi()->config->get('site_title'); $description = $this->invoice->getLineDescription(); $lang = $this->getDi()->locale->getLanguage(); $plabel = $label; $image = $this->plugin->getConfig('image_url'); $zipvalidate = $this->plugin->getConfig('zip_validate') ? 'true' : 'false'; $form->addHidden('id')->setValue($this->_request->get('id')); $form->addStatic()->setContent(<< CUT ); $form->addScript()->setScript(<<setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($this->getDefaultValues($this->invoice->getUser())) )); return $form; } public function createFormRegular($label, $cc_mask = null) { $form = new Am_Form('cc-stripe'); $name = $form->addGroup() ->setLabel(___("Cardholder Name\n" . 'cardholder first and last name, exactly as on the card')); $name->addRule('required', ___('Please enter credit card holder name')); $name->setSeparator(' '); $name_f = $name->addText('cc_name_f', array('size'=>15, 'id' => 'cc_name_f')); $name_f->addRule('required', ___('Please enter credit card holder first name'))->addRule('regex', ___('Please enter credit card holder first name'), '|^[a-zA-Z_\' -]+$|'); $name_l = $name->addText('cc_name_l', array('size'=>15, 'id' => 'cc_name_l')); $name_l->addRule('required', ___('Please enter credit card holder last name'))->addRule('regex', ___('Please enter credit card holder last name'), '|^[a-zA-Z_\' -]+$|'); $cc = $form->addText('', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22, 'id' => 'cc_number')) ->setLabel(___('Credit Card Number')); if ($cc_mask) $cc->setAttribute('placeholder', $cc_mask); $cc->addRule('required', ___('Please enter Credit Card Number')) ->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/'); class_exists('Am_Form_CreditCard', true); // preload element $expire = $form->addElement(new Am_Form_Element_CreditCardExpire('cc_expire')) ->setLabel(___("Card Expire\n" . 'Select card expiration date - month and year')); $expire->addRule('required', ___('Please enter Credit Card expiration date')); $code = $form->addPassword('', array('autocomplete'=>'off', 'size'=>4, 'maxlength'=>4, 'id' => 'cc_code')) ->setLabel(___("Credit Card Code\n". 'The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).')); $code->addRule('required', ___('Please enter Credit Card Code')) ->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/'); $fieldSet = $form->addFieldset(___('Address Info')) ->setLabel(___("Address Info\n" . '(must match your credit card statement delivery address)')); $street = $fieldSet->addText('cc_street')->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); $city = $fieldSet->addText('cc_city')->setLabel(___('City ')) ->addRule('required', ___('Please enter City')); $zip = $fieldSet->addText('cc_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); $country = $fieldSet->addSelect('cc_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); /** @todo load correct states */ $stateSelect = $group->addSelect('cc_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['cc_country'], true)); $stateText = $group->addText('cc_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); $form->addSubmit('', array('value' => $label)); $form->addHidden('id')->setValue($this->_request->get('id')); $form->addHidden('stripe_info', 'id=stripe_info')->addRule('required'); $key = json_encode($this->plugin->getConfig('public_key')); $form->addScript()->setScript(file_get_contents(AM_APPLICATION_PATH . '/default/views/public/js/json2.min.js')); $form->addScript()->setScript(<< '') return true; // submit the form! event.stopPropagation(); Stripe.setPublishableKey($key); Stripe.createToken({ number: frm.find("#cc_number").val(), cvc: frm.find("#cc_code").val(), exp_month: frm.find("[name='cc_expire[m]']").val(), exp_year: frm.find("[name='cc_expire[y]']").val(), name: frm.find("#cc_name_f").val() + " " + frm.find("#cc_name_l").val(), address_zip : frm.find("[name=cc_zip]").val(), address_line1 : frm.find("[name=cc_street]").val(), address_country : frm.find("[name=cc_country]").val(), address_city : frm.find("[name=cc_city]").val(), address_state : frm.find("[name=cc_state]").val() }, function(status, response){ // handle response if (status == '200') { frm.find("input[name=stripe_info]").val(JSON.stringify(response)); frm.submit(); } else { frm.find("input[type=submit]").prop('disabled', null); var msg; if (response.error.type == 'card_error') msg = response.error.message; else msg = 'Payment failure, please try again later'; var el = frm.find("#cc_number"); var cnt = el.closest(".element"); cnt.addClass("error"); cnt.find("span.error").remove(); el.after("
      "+msg+"
      "); } }); frm.find("input[type=submit]").prop('disabled', 'disabled'); return false; }); }); CUT ); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($this->getDefaultValues($this->invoice->getUser())) )); return $form; } public function getDefaultValues(User $user){ return array( 'cc_name_f' => $user->name_f, 'cc_name_l' => $user->name_l, 'cc_street' => $user->street, 'cc_street2' => $user->street2, 'cc_city' => $user->city, 'cc_state' => $user->state, 'cc_country' => $user->country, 'cc_zip' => $user->zip, 'cc_phone' => $user->phone, ); } public function updateAction() { $user = $this->getDi()->user; $token = $user->data()->get(Am_Paysystem_Stripe::TOKEN); if (!$token) throw new Am_Exception_Paysystem("No credit card stored, nothing to update"); $this->invoice = $this->getDi()->invoiceTable->findFirstBy( array('user_id'=>$user->pk(), 'paysys_id'=>$this->plugin->getId()), 'invoice_id DESC'); if (!$this->invoice) throw new Am_Exception_Paysystem("No invoices found for user and paysystem"); $tr = new Am_Paysystem_Transaction_Stripe_GetCustomer($this->plugin, $this->invoice, $token); $tr->run(new Am_Paysystem_Result()); $info = $tr->getInfo(); if (empty($info['id'])) // cannot load profile { // todo delete old profile, and display cc form again! throw new Am_Exception_Paysystem("Could not load customer profile"); } if(!isset($info['active_card'])) { foreach($info['sources']['data'] as $c) if($c['id'] == $info['default_source']) $info['active_card'] = $c; } $this->form = $this->createForm(___('Update Credit Card Info'), 'XXXX XXXX XXXX ' . $info['active_card']['last4']); $n = preg_split('/\s+/', $info['active_card']['name'], 2); $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'cc_street' => $info['active_card']['address_line1'], 'cc_name_f' => $n[0], 'cc_name_l' => $n[1], 'cc_zip' => $info['active_card']['address_zip'], 'cc_expire' => sprintf('%02d%02d', $info['active_card']['exp_month'], $info['active_card']['exp_year']-2000), ))); $result = $this->ccFormAndSaveCustomer(); if ($result->isSuccess()) $this->_redirect($this->getDi()->url('member',null,false,true)); if(!$this->getInvokeArg('hosted')) { $this->form->getElementById('stripe_info')->setValue(''); $this->view->headScript()->appendFile('https://js.stripe.com/v1/'); } $this->view->title = ___('Payment info'); $this->view->display_receipt = false; $this->view->form = $this->form; $this->view->display('cc/info.phtml'); } protected function ccFormAndSaveCustomer() { $vars = $this->form->getValue(); $result = new Am_Paysystem_Result(); if(!$this->getInvokeArg('hosted')) { if (!empty($vars['stripe_info'])) { $stripe_info = json_decode($vars['stripe_info'], true); if (!$stripe_info['id']) throw new Am_Exception_Paysystem("No expected token id received"); $tr = new Am_Paysystem_Transaction_Stripe_CreateCustomer($this->plugin, $this->invoice, $stripe_info['id']); $tr->run($result); if ($result->isSuccess()) { $this->invoice->getUser()->data() ->set(Am_Paysystem_Stripe::TOKEN, $tr->getUniqId()) ->set(Am_Paysystem_Stripe::CC_EXPIRES, sprintf('%02d%02d', $stripe_info['source']['exp_month'], $stripe_info['source']['exp_year']-2000)) ->set(Am_Paysystem_Stripe::CC_MASKED, 'XXXX' . $stripe_info['source']['last4']) ->update(); // setup session to do not reask payment info within 30 minutes $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session $s->ccConfirmed = true; } else { $this->view->error = $result->getErrorMessages(); } } } else { if ($stripe_info = $this->_request->get('stripeToken')) { $tr = new Am_Paysystem_Transaction_Stripe_CreateCustomer($this->plugin, $this->invoice, $stripe_info); $tr->run($result); if ($result->isSuccess()) { $card = $tr->getCard(); $this->invoice->getUser()->data() ->set(Am_Paysystem_Stripe::TOKEN, $tr->getUniqId()) ->set(Am_Paysystem_Stripe::CC_EXPIRES, sprintf('%02d%02d', $card[0]['exp_month'], $card[0]['exp_year']-2000)) ->set(Am_Paysystem_Stripe::CC_MASKED, 'XXXX' . $card[0]['last4']) ->update(); // setup session to do not reask payment info within 30 minutes $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session $s->ccConfirmed = true; } else { $this->view->error = $result->getErrorMessages(); } } } return $result; } protected function displayReuse() { $result = new Am_Paysystem_Result; $tr = new Am_Paysystem_Transaction_Stripe_GetCustomer($this->plugin, $this->invoice, $this->invoice->getUser()->data()->get(Am_Paysystem_Stripe::TOKEN)); $tr->run($result); if (!$result->isSuccess()) throw new Am_Exception_Paysystem("Stored customer profile not found"); $card = $tr->getInfo(); $last4 = 'XXXX'; foreach($card['sources']['data'] as $c) if($c['id'] == $card['default_source']) $last4 = $c['last4']; $card = 'XXXX XXXX XXXX ' . $last4; $text = ___('Click "Continue" to pay this order using stored credit card %s', $card); $continue = ___('Continue'); $cancel = ___('Cancel'); $action = $this->plugin->getPluginUrl('cc'); $id = Am_Html::escape($this->_request->get('id')); $action = Am_Html::escape($action); $receipt = $this->view->partial('_receipt.phtml', array('invoice' => $this->invoice, 'di'=>$this->getDi())); $this->view->layoutNoMenu = true; $this->view->content .= <<

      $text

         
      CUT; $this->view->display('layout.phtml'); } public function ccAction() { $this->view->title = ___('Payment info'); $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $this->view->invoice = $this->invoice; // if we have credit card on file, we will try to use it but we // have to display confirmation first if ($this->invoice->getUser()->data()->get(Am_Paysystem_Stripe::TOKEN)) { $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session //$s->ccConfirmed = !empty($s->ccConfirmed); if ($this->_request->get('reuse_ok')) { if(@$s->ccConfirmed === true) { $result = $this->plugin->doBill($this->invoice, true, $this->getDi()->CcRecordTable->createRecord()); if ($result->isSuccess()) { return $this->_redirect($this->plugin->getReturnUrl()); } else { $this->invoice->getUser()->data() ->set(Am_Paysystem_Stripe::TOKEN, null) ->set(Am_Paysystem_Stripe::CC_EXPIRES, null) ->set(Am_Paysystem_Stripe::CC_MASKED, null) ->update(); $this->view->error = $result->getErrorMessages(); $s->ccConfirmed = false; // failed } } } elseif ($this->_request->get('reuse_cancel') || (@$s->ccConfirmed === false)) { $s->ccConfirmed = false; } elseif (@$s->ccConfirmed === true) { try{ return $this->displayReuse(); }catch(Exception $e){ // Ignore it. } } } $this->form = $this->createForm(___('Subscribe And Pay')); $result = $this->ccFormAndSaveCustomer(); if ($result->isSuccess()) { $result = $this->plugin->doBill($this->invoice, true, $this->getDi()->CcRecordTable->createRecord()); if ($result->isSuccess()) { return $this->_redirect($this->plugin->getReturnUrl()); } else { $this->invoice->getUser()->data() ->set(Am_Paysystem_Stripe::TOKEN, null) ->set(Am_Paysystem_Stripe::CC_EXPIRES, null) ->set(Am_Paysystem_Stripe::CC_MASKED, null) ->update(); $this->view->error = $result->getErrorMessages(); } } if(!$this->getInvokeArg('hosted')) { $this->form->getElementById('stripe_info')->setValue(''); $this->view->headScript()->appendFile('https://js.stripe.com/v1/'); } $this->view->form = $this->form; $this->view->display('cc/info.phtml'); } } class Am_Paysystem_Transaction_Stripe extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst) { $request = new Am_HttpRequest('https://api.stripe.com/v1/charges', 'POST'); $amount = $doFirst ? $invoice->first_total : $invoice->second_total; $request->setAuth($plugin->getConfig('secret_key'), '') ->addPostParameter('amount', sprintf('%.02f', $amount)*100) ->addPostParameter('currency', $invoice->currency) ->addPostParameter('customer', $invoice->getUser()->data()->get(Am_Paysystem_Stripe::TOKEN)) ->addPostParameter('metadata[invoice]', $invoice->public_id) ->addPostParameter('description', 'Invoice #'.$invoice->public_id.': '.$invoice->getLineDescription()); parent::__construct($plugin, $invoice, $request, $doFirst); } public function getUniqId() { return $this->parsedResponse['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (@$this->parsedResponse['paid'] != 'true') { if ($this->parsedResponse['error']['type'] == 'card_error') $this->result->setErrorMessages(array($this->parsedResponse['error']['message'])); else $this->result->setErrorMessages(array(___('Payment failed'))); return false; } $this->result->setSuccess($this); return true; } } /** * Convert temporary credit card profile to customer record */ class Am_Paysystem_Transaction_Stripe_CreateCustomer extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $token) { $request = new Am_HttpRequest('https://api.stripe.com/v1/customers', 'POST'); $request->setAuth($plugin->getConfig('secret_key'), '') ->addPostParameter('card', $token) ->addPostParameter('email', $invoice->getEmail()) ->addPostParameter('description', 'Username:' . $invoice->getUser()->login); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { return $this->parsedResponse['id']; } public function getCard() { return $this->parsedResponse['cards']['data']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['id']) { $code = @$this->parsedResponse['error']['code']; $message = @$this->parsedResponse['error']['message']; $error = "Error storing customer profile"; if ($code) $error .= " [".$code."]"; if ($message) $error .= " (".$message.")"; $this->result->setErrorMessages(array($error)); return false; } $this->result->setSuccess($this); return true; } public function processValidated() { } } class Am_Paysystem_Transaction_Stripe_GetCustomer extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $token) { $request = new Am_HttpRequest('https://api.stripe.com/v1/customers/' . $token, 'GET'); $request->setAuth($plugin->getConfig('secret_key'), ''); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { return $this->parsedResponse['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['id']) $this->result->setErrorMessages(array('Unable to fetch payment profile')); $this->result->setSuccess($this); } public function getInfo() { return $this->parsedResponse; } public function processValidated() { } } class Am_Paysystem_Transaction_Stripe_Refund extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); protected $charge_id; protected $amount; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $charge_id, $amount = null) { $this->charge_id = $charge_id; $this->amount = $amount > 0 ? $amount : null; $request = new Am_HttpRequest('https://api.stripe.com/v1/charges/' . $this->charge_id . '/refund', 'POST'); $request->setAuth($plugin->getConfig('secret_key'), ''); if ($this->amount > 0) $request->addPostParameter('amount', sprintf('%.2f', $this->amount)*100); parent::__construct($plugin, $invoice, $request, true); } public function getUniqId() { $r = null; foreach ($this->parsedResponse['refunds']['data'] as $refund) { if (is_null($r) || $refund['created'] > $r['created']) { $r = $refund; } } return $r['id']; } public function parseResponse() { $this->parsedResponse = json_decode($this->response->getBody(), true); } public function validate() { if (!@$this->parsedResponse['id']) $this->result->setErrorMessages(array('Unable to fetch payment profile')); $this->result->setSuccess(); } public function processValidated() { $this->invoice->addRefund($this, $this->charge_id, $this->amount); } } class Am_Paysystem_Transaction_Stripe_Webhook extends Am_Paysystem_Transaction_Incoming { public function process() { $this->event = json_decode($this->request->getRawBody(), true); switch ($this->event['type']) { case "charge.refunded" : $r = null; $refundsList = (isset($this->event['data']['object']['refunds']['data']) ? $this->event['data']['object']['refunds']['data'] : $this->event['data']['object']['refunds']); foreach ($refundsList as $refund) { if (is_null($r) || $refund['created'] > $r['created']) { $r = $refund; } } $this->refund = $r; break; } return parent::process(); } public function validateSource() { return (bool)$this->event; } public function validateTerms() { return true; } public function validateStatus() { return true; } public function getUniqId() { switch ($this->event['type']) { case "charge.refunded" : return $this->refund['id']; default : return $this->event['id']; } } public function findInvoiceId() { return $this->event['data']['object']['metadata']['invoice']; } public function processValidated() { switch ($this->event['type']) { case "charge.refunded" : try { $this->invoice->addRefund($this, $this->event['data']['object']["id"], $this->refund['amount']/100); } catch (Am_Exception_Db_NotUnique $e) { //nop, refund is added from aMemeber admin interface } break; } } }PK\n8,D,Dcc/plugins/paymill-dd.phpnu[addText('private_key', 'class=el-wide') ->setLabel('Private Key')->addRule('required'); $form->addText('public_key', 'class=el-wide') ->setLabel('Public Key')->addRule('required'); $form->addAdvCheckbox("testing")->setLabel('Test Mode'); } public function storeEcheck(EcheckRecord $echeck, Am_Paysystem_Result $result) { //nop } public function _doBill(Invoice $invoice, $doFirst, EcheckRecord $echeck, Am_Paysystem_Result $result) { if (!is_null($echeck)) { $user = $this->getDi()->userTable->load($echeck->user_id); $tr = new Am_Paysystem_Transaction_PaymillDd_Payment($this, $user, $echeck->paymill_token); $tr->run($result); } $pay = $invoice->getUser()->data()->get(self::PAYMENT_ID); if (!$pay) { return $result->setFailed(array(___('Payment failed'))); } if ($doFirst && (doubleval($invoice->first_total) <= 0)) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $tr = new Am_Paysystem_Transaction_PaymillDd_Transaction($this, $invoice, $doFirst); $tr->run($result); } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $tr = new Am_Paysystem_Transaction_PaymillDd_Refund($this, $payment, $amount); $tr->run($result); } public function createForm($actionName) { return new Am_Form_EcheckPaymill($this); } public function getReadme() { return << Settings -> API keys) CUT; } } class Am_Form_EcheckPaymill extends Am_Form { public function __construct(Am_Paysystem_Echeck $plugin) { $this->plugin = $plugin; parent::__construct('echeck'); } function init() { $name = $this->addGroup() ->setLabel(___("Account Holder\n" . 'first and last name')); $name->addText('', array('size' => 15, 'id' => 'echeck_name_f')); $name->addText('', array('size' => 15, 'id' => 'echeck_name_l')); $this->addText('', array('autocomplete' => 'off', 'id' => 'echeck_number')) ->setLabel(___("Account Number / IBAN")); $this->addText('', array('autocomplete' => 'off', 'id' => 'echeck_bank')) ->setLabel(___("Bank code / BIC")); $this->addSaveButton(___('Subscribe And Pay')); $this->addHidden('paymill_token', 'id=paymill_token')->addRule('required'); $this->addProlog(''); $key = $this->plugin->getConfig('public_key'); if ($this->plugin->getConfig('testing')) { $this->addScript()->setScript("var PAYMILL_TEST_MODE = true;"); } $this->addScript()->setScript("var PAYMILL_PUBLIC_KEY = '$key';"); $this->addScript()->setScript(<< '') return true; // submit the form! event.stopPropagation(); if (isSepa()) { params = { iban: jQuery("#echeck_number").val().replace(/\s+/g, ""), bic: frm.find("#echeck_bank").val().replace(/\s+/g, ""), accountholder: frm.find("#echeck_name_f").val() + ' ' + frm.find("#echeck_name_l").val() } } else { params = { number: frm.find("#echeck_number").val().replace(/\s+/g, ""), bank: frm.find("#echeck_bank").val().replace(/\s+/g, ""), accountholder: frm.find("#echeck_name_f").val() + ' ' + frm.find("#echeck_name_l").val() } } paymill.createToken(params, function(error, result){ // handle response if (error) { frm.find("input[type=submit]").prop('disabled', null); var el = frm.find("#echeck_number"); var cnt = el.closest(".element"); cnt.addClass("error"); cnt.find("span.error").remove(); var errorMessage = ''; switch (error.apierror) { case 'internal_server_error': errorMessage = 'Communication with PSP failed'; break; case 'invalid_public_key': errorMessage = 'Invalid Public Key'; break; case 'unknown_error': errorMessage = 'Unknown Error'; break; case '3ds_cancelled': errorMessage = 'Password Entry of 3-D Secure password was cancelled by the user'; break; case 'field_invalid_card_number': errorMessage = 'Missing or invalid creditcard number'; break; case 'field_invalid_card_exp_year': errorMessage = 'Missing or invalid expiry year'; break; case 'field_invalid_card_exp_month': errorMessage = 'Missing or invalid expiry month'; break; case 'field_invalid_card_exp': errorMessage = 'Card is no longer valid or has expired'; break; case 'field_invalid_card_cvc': errorMessage = 'Invalid checking number'; break; case 'field_invalid_card_holder': errorMessage = 'Invalid cardholder'; break; case 'field_invalid_amount_int': errorMessage = 'Invalid or missing amount for 3-D Secure'; break; case 'field_invalid_amount': errorMessage = 'Invalid or missing amount for 3-D Secure deprecated, see blog post'; break; case 'field_invalid_currency': errorMessage = 'Invalid or missing currency code for 3-D Secure'; break; case 'field_invalid_account_number': errorMessage = 'Missing or invalid bank account number'; break; case 'field_invalid_account_holder': errorMessage = 'Missing or invalid bank account holder'; break; case 'field_invalid_bank_code': errorMessage = 'Missing or invalid bank code'; break; case 'field_invalid_iban': errorMessage = 'Missing or invalid IBAN'; break; case 'field_invalid_bic': errorMessage = 'Missing or invalid BIC'; break; case 'field_invalid_country': errorMessage = 'Missing or unsupported country (with IBAN)'; break; case 'field_invalid_bank_data': errorMessage = 'Missing or invalid bank data combination'; break; default: errorMessage = error.apierror; } el.after("
      "+errorMessage+"
      "); } else { frm.find("input[name=paymill_token]").val(result.token); frm.submit(); } }); frm.find("input[type=submit]").prop('disabled', 'disabled'); return false; }); }); CUT ); } public function getDefaultValues(User $user) { return array( 'echeck_name_f' => $user->name_f, 'echeck_name_l' => $user->name_l ); } public function toEcheckRecord(EcheckRecord $echeck) { $values = $this->getValue(); unset($values['a']); unset($values['id']); unset($values['action']); $echeck->setForInsert($values); } } abstract class Am_Paysystem_Transaction_PaymillDd_Abstract { protected $log; protected $user; /** @var Invoice */ protected $invoice; protected $plugin; protected $request; protected $params = array(); public function run(Am_Paysystem_Result $result) { $log = $this->getInvoiceLog(); $log->add($this->request); $response = $this->request->send(); $log->add($response); $this->validateResponseStatus($response, $result); if ($result->isFailure()) return; try { $this->parseResponse($response); $this->validateResponse($result); if ($result->isSuccess()) $this->processValidated(); } catch (Exception $e) { $log->add($e); } } protected function validateResponseStatus(HTTP_Request2_Response $response, Am_Paysystem_Result $result) { if ($response->getStatus() != 200) { $result->setFailed(array("Received invalid response from payment server: " . $this->response->getStatus())); } } protected function parseResponse(HTTP_Request2_Response $response) { $this->params = json_decode($response->getBody(), true); } protected function validateResponse(Am_Paysystem_Result $result) { if (!$this->plugin->getConfig('testing') && $this->params['mode'] == 'test') { $result->setFailed(array( 'Attempt to run test trunsaction in live mode' )); return; } $this->validate($result); } abstract protected function validate(Am_Paysystem_Result $result); abstract protected function processValidated(); /** @return InvoiceLog */ protected function getInvoiceLog() { if (!$this->log) { $this->log = $this->getPlugin()->getDi()->invoiceLogRecord; if ($this->invoice) { $this->log->invoice_id = $this->invoice->invoice_id; $this->log->user_id = $this->invoice->user_id; } elseif ($this->user) { $this->log->user_id = $this->user->user_id; } $this->log->paysys_id = $this->getPlugin()->getId(); $this->log->remote_addr = $_SERVER['REMOTE_ADDR']; $this->log->toggleMask(false); } return $this->log; } protected function getPlugin() { return $this->plugin; } } class Am_Paysystem_Transaction_PaymillDd_Payment extends Am_Paysystem_Transaction_PaymillDd_Abstract { public function __construct(Am_Paysystem_Abstract $plugin, User $user, $token) { $this->plugin = $plugin; $this->user = $user; $this->request = new Am_HttpRequest(Am_Paysystem_PaymillDd::API_ENDPOINT . 'payments', Am_HttpRequest::METHOD_POST); $this->request->setAuth($this->plugin->getConfig('private_key'), ''); $this->request->addPostParameter('token', $token); } protected function validate(Am_Paysystem_Result $result) { $result->setSuccess(); } protected function processValidated() { $this->user->data() ->set(Am_Paysystem_PaymillDd::PAYMENT_ID, $this->params['data']['id']) ->update(); } } class Am_Paysystem_Transaction_PaymillDd_PaymentDelete extends Am_Paysystem_Transaction_PaymillDd_Abstract { public function __construct(Am_Paysystem_Abstract $plugin, User $user) { $this->plugin = $plugin; $this->user = $user; $pay = $user->data()->get(Am_Paysystem_PaymillDd::PAYMENT_ID); $this->request = new Am_HttpRequest(Am_Paysystem_PaymillDd::API_ENDPOINT . 'payments/' . $pay, Am_HttpRequest::METHOD_DELETE); $this->request->setAuth($this->plugin->getConfig('private_key'), ''); } protected function validate(Am_Paysystem_Result $result) { $result->setSuccess(); } protected function processValidated() { $this->user->data() ->set(Am_Paysystem_PaymillDd::PAYMENT_ID, null) ->update(); } } class Am_Paysystem_Transaction_PaymillDd_Transaction extends Am_Paysystem_Transaction_PaymillDd_Abstract implements Am_Paysystem_Transaction_Interface { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst) { $this->plugin = $plugin; $this->user = $invoice->getUser(); $this->invoice = $invoice; $pay = $this->user->data()->get(Am_Paysystem_PaymillDd::PAYMENT_ID); $this->request = new Am_HttpRequest(Am_Paysystem_PaymillDd::API_ENDPOINT . 'transactions', Am_HttpRequest::METHOD_POST); $this->request->setAuth($this->plugin->getConfig('private_key'), ''); $this->request->addPostParameter(array( 'amount' => ($doFirst ? $invoice->first_total : $invoice->second_total) * 100, 'currency' => $invoice->currency, 'payment' => $pay, 'description' => $invoice->getLineDescription() )); } protected function validate(Am_Paysystem_Result $result) { if ($this->params['data']['response_code'] != 20000) { $result->setFailed(array(___('Payment Failed'))); return; } if ($this->params['data']['status'] == 'failed') { $result->setFailed(array(___('Payment Failed'))); return; } $result->setSuccess(); } protected function processValidated() { $this->invoice->addPayment($this); } function getTime() { return $this->getPlugin()->getDi()->dateTime; } function getRecurringType() { return $this->getPlugin()->getRecurringType(); } function getUniqId() { return $this->params['data']['id']; } function getPaysysId() { return $this->getPlugin()->getId(); } function getReceiptId() { return $this->params['data']['id']; } function getAmount() { return $this->params['data']['origin_amount'] / 100; } } class Am_Paysystem_Transaction_PaymillDd_Refund extends Am_Paysystem_Transaction_PaymillDd_Abstract implements Am_Paysystem_Transaction_Interface { public function __construct(Am_Paysystem_Abstract $plugin, InvoicePayment $payment, $amount) { $this->plugin = $plugin; $this->user = $payment->getUser(); $this->invoice = $payment->getInvoice(); $this->request = new Am_HttpRequest(Am_Paysystem_PaymillDd::API_ENDPOINT . 'refunds/' . $payment->receipt_id, Am_HttpRequest::METHOD_POST); $this->request->setAuth($this->plugin->getConfig('private_key'), ''); $this->request->addPostParameter(array( 'amount' => ($amount ? $amount : $payment->amount) * 100, )); } protected function validate(Am_Paysystem_Result $result) { if ($this->params['data']['response_code'] != 20000) { $result->setFailed(array(___('Refund Failed'))); return; } $result->setSuccess(); } protected function processValidated() { $this->invoice->addRefund($this, $this->params['data']['transaction']['id']); } function getTime() { return $this->getPlugin()->getDi()->dateTime; } function getRecurringType() { return $this->getPlugin()->getRecurringType(); } function getUniqId() { return $this->params['data']['id']; } function getPaysysId() { return $this->getPlugin()->getId(); } function getReceiptId() { return $this->params['data']['id']; } function getAmount() { return $this->params['data']['amount'] / 100; } }PK\2nZZcc/plugins/payflow.phpnu[getConfig('user') && $this->getConfig('pass'); } public function getSupportedCurrencies() { return array('USD', 'CAD', 'GBP'); } public function allowPartialRefunds() { return true; } protected function createController(\Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { if (!$this->getConfig('advanced')) return parent::createController($request, $response, $invokeArgs); else return new Am_Mvc_Controller_CreditCard_Payflow($request, $response, $invokeArgs); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $addCc = true; // if it is a first charge, or user have valid CC info in file, we should use cc_info instead of reference transaction. // This is necessary when data was imported from amember v3 for example if ($doFirst || (!empty($cc->cc_number) && $cc->cc_number != '0000000000000000')) { if ($doFirst && (doubleval($invoice->first_total) == 0) ) // free trial { $tr = new Am_Paysystem_Payflow_Transaction_Authorization($this, $invoice, $doFirst, $cc); } else { $tr = new Am_Paysystem_Payflow_Transaction_Sale($this, $invoice, $doFirst, $cc); } } else { $user = $invoice->getUser(); $profileId = $user->data()->get(self::USER_PROFILE_KEY); if (!$profileId) return $result->setFailed(array("No saved reference transaction for customer")); $tr = new Am_Paysystem_Payflow_Transaction_Sale($this, $invoice, $doFirst, null, $profileId); } $tr->run($result); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $user = $this->getDi()->userTable->load($cc->user_id); $profileId = $user->data()->get(self::USER_PROFILE_KEY); if ($this->invoice) { // to link log records with current invoice $invoice = $this->invoice; } else { // updating credit card info? $invoice = $this->getDi()->invoiceRecord; $invoice->invoice_id = 0; $invoice->user_id = $user->pk(); } // compare stored cc for that user may be we don't need to refresh? if ($profileId && ($cc->cc_number != '0000000000000000')) { $storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk()); if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)) || ($storedCc->cc_expire != $cc->cc_expire))) { $user->data() ->set(self::USER_PROFILE_KEY, null) ->update(); $profileId = null; } } if (!$profileId) { try { $tr = new Am_Paysystem_Payflow_Transaction_Upload($this, $invoice, $cc); $tr->run($result); if (!$result->isSuccess()) return; $user->data()->set(Am_Paysystem_Payflow::USER_PROFILE_KEY, $tr->getProfileId())->update(); } catch (Am_Exception_Paysystem $e) { $result->setFailed($e->getPublicError()); return false; } } /// $cc->cc = $cc->maskCc(@$cc->cc_number); $cc->cc_number = '0000000000000000'; if ($cc->pk()) $cc->update(); else $cc->replace(); $result->setSuccess(); } protected function _initSetupForm(Am_Form_Setup $form) { $form->addText('vendor')->setLabel('Merchant Vendor Id (main username)'); $form->addText('user')->setLabel('Merchant User Id (of the API user, or the same as Vendor Id)'); $form->addPassword('pass')->setLabel('Merchant Password'); $form->addText('partner')->setLabel('Partner'); $form->setDefault('partner', 'PayPal'); $form->addAdvCheckbox('advanced')->setLabel("Use PayPal Advanced\ncredit card info will be asked in iframe on your website"); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $tr = new Am_Paysystem_Payflow_Transaction_Refund($this, $payment->getInvoice(), $payment->receipt_id, $amount); $tr->run($result); } public function getReadme() { $root = $this->getRootUrl(); return << Hosted Checkout Pages -> Set Up PayPal email address -> set to your paypal e-mail address Return URL -> set to $root/payment/payflow/thanks Enable Secure Token -> yes Click [Save Changes] button Click [Customize] -> Layout C and click [Save and Publish] You now are ready to go with PayPal Advanced. IMPORTANT: As a security measure, reference transactions are disallowed by default. Only your account administrator can enable reference transactions for your account. If you attempt to perform a reference transaction in an account for which reference transactions are disallowed, RESULT value 117 is returned. See PayPal Manager online help for instructions on setting reference transactions and other security features. CUT; } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Payflow_Transaction_Thanks($this, $request, $response, $invokeArgs); } public function thanksAction(\Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { $ret = parent::thanksAction($request, $response, $invokeArgs); foreach ($response->getHeaders() as $h) if ($h['name'] == 'Location') $redirect = $h['value']; if ($response->isRedirect()) { $response->clearAllHeaders()->clearBody(); $url = Am_Html::escape($redirect); $response->setBody( " "); } return $ret; } public function cancelPaymentAction(\Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { $ret = parent::cancelPaymentAction($request, $response, $invokeArgs); foreach ($response->getHeaders() as $h) if ($h['name'] == 'Location') $redirect = $h['value']; if ($response->isRedirect()) { $response->clearAllHeaders()->clearBody(); $url = Am_Html::escape($redirect); $response->setBody( " "); } return $ret; } } class Am_Mvc_Controller_CreditCard_Payflow extends Am_Mvc_Controller_CreditCard { public function ccAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); $this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form)); $trans = new Am_Paysystem_Payflow_Transaction_CreateSecureToken($this->plugin, $this->invoice, true); $res = new Am_Paysystem_Result(); $trans->run($res); //var_dump($res);exit(); //if (!$res->isSuccess()) // throw new Am_Exception_Paysystem("Internal error - cannot get secure token from PayPal API"); $token = $trans->getToken(); $frm = new Am_Form(); $params = array( 'SECURETOKENID' => $trans->getTokenId(), 'SECURETOKEN' => $trans->getToken(), 'CANCELURL' => $this->plugin->getCancelUrl(), 'DISABLERECEIPT' => true, // Determines if the payment confirmation / order receipt page is a PayPal hosted page or a page on the merchant site. 'EMAILCUSTOMER' => true, //'ERRORURL' => $this->plugin->getCancelUrl(), //'RETURNURL' => $this->plugin->getReturnUrl(), 'INVNUM' => $this->invoice->public_id, 'TEMPLATE' => 'MINLAYOUT', // or MOBILE for mobile iframe or TEMPLATEA TEMPLATEB 'SHOWAMOUNT' => (double)$this->invoice->first_total <= 0 ? false : true, ); if ($this->plugin->getConfig('testing')) $params['MODE'] = 'TEST'; $params = http_build_query($params); $html = ''; $frm->addHtml()->setHtml($html)->addClass('no-label'); $this->view->form = $frm; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $this->view->display('cc/info.phtml'); } } class Am_Paysystem_Payflow_Transaction_Thanks extends Am_Paysystem_Transaction_Incoming_Thanks { /* @var $request Am_Mvc_Request */ protected $request; public function __construct(\Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->request = $request; parent::__construct($plugin, $request, $response, $invokeArgs); } public function findInvoiceId() { return $this->request->getFiltered('INVNUM'); } public function getUniqId() { return $this->request->get('PNREF'); } public function validateStatus() { return $this->request->get('RESULT') === '0'; } public function validateTerms() { return true; // checked with securetoken } public function validateSource() { // check if secure token is registered in session $tok = $this->request->get('SECURETOKEN', rand(10,88888)); $k = 'payflow_securetoken_' . $tok; return (bool)Am_Di::getInstance()->session->$k; } public function processValidated() { parent::processValidated(); // TODO if there was a recurring invoice start it // $tr = new Am_Paysystem_Payflow_Transaction_CreateProfile($this->plugin, $this->invoice, $this->getReceiptId()); // $res = new Am_Paysystem_Result(); // $tr->run(res); // if (!$res->isSuccess()) // throw new Am_Exception_Paysystem("Could not start recurring billing for invoice " . $this->invoice->public_id ); } } class Am_Paysystem_Payflow_Transaction extends Am_Paysystem_Transaction_CreditCard { protected $parsedResponse = array(); public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst) { $request = new Am_HttpRequest($plugin->getConfig('testing') ? Am_Paysystem_Payflow::TEST_URL : Am_Paysystem_Payflow::LIVE_URL, Am_HttpRequest::METHOD_POST); parent::__construct($plugin, $invoice, $request, $doFirst); $this->addRequestParams(); } public function run(Am_Paysystem_Result $result) { $reqId = sha1(serialize($this->request->getPostParams())); // unique id of request $this->request->setHeader('X-VPS-REQUEST-ID', $reqId); $this->request->setHeader('X-VPS-CLIENT-TIMEOUT', 60); $this->request->setHeader('X-VPS-VIT-INTEGRATION-PRODUCT', 'aMember Pro'); // $this->request->setHeader('Content-Type', 'text/namevalue'); $this->request->addPostParameter('VERBOSITY', 'HIGH'); return parent::run($result); } protected function addRequestParams() { $this->request->addPostParameter('VENDOR', $this->plugin->getConfig('vendor')); $this->request->addPostParameter('USER', $this->plugin->getConfig('user')); $this->request->addPostParameter('PWD', $this->plugin->getConfig('pass')); $this->request->addPostParameter('PARTNER', $this->plugin->getConfig('partner')); $this->request->addPostParameter('BUTTONSOURCE', 'CgiCentral.aMemberPro'); } public function getUniqId() { return strlen(@$this->parsedResponse->PPREF) ? $this->parsedResponse->PPREF : $this->parsedResponse->PNREF; } public function getReceiptId() { return $this->parsedResponse->PNREF; } public function getAmount() { return $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total; } public function parseResponse() { parse_str($this->response->getBody(), $this->parsedResponse); $this->parsedResponse = (object)$this->parsedResponse; if (!strlen(@$this->parsedResponse->RESULT)) $this->parsedResponse->RESULT = -1; // wrong response received } public function validate() { if ($this->parsedResponse->RESULT != '0') return $this->result->setFailed(array("Transaction declined, please check credit card information")); $this->result->setSuccess($this); } function setCcRecord(CcRecord $cc) { $this->request->addPostParameter(array( 'ACCT' => $cc->cc_number, 'EXPDATE' => $cc->cc_expire, 'BILLTOFIRSTNAME' => $cc->cc_name_f, 'BILLTOLASTNAME' => $cc->cc_name_l, 'BILLTOSTREET' => $cc->cc_street, 'BILLTOCITY' => $cc->cc_city, 'BILLTOSTATE' => $cc->cc_state, 'BILLTOZIP' => $cc->cc_zip, 'BILLTOCOUNTRY' => $cc->cc_country, 'CVV2' => $cc->getCvv(), )); } } class Am_Paysystem_Payflow_Transaction_CreateProfile extends Am_Paysystem_Payflow_Transaction { protected $pnref; public function __construct(\Am_Paysystem_Abstract $plugin, \Invoice $invoice, $pnref) { $this->pnref = $pnref; parent::__construct($plugin, $invoice, false); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter(array( 'TRXTYPE' => 'R', 'ACTION' => 'A', 'TENDER' => 'C', 'PROFILEREFERENCE' => $this->invoice->public_id, 'PROFILENAME' => $this->invoice->getLineDescription(), 'START' => '09182014', 'TERM' => '0', 'PAYPERIOD' => 'MONT', 'AMT' => $this->invoice->second_total, 'ORIGID' => $this->pnref, )); /// [13]=XXXXXX&USER[6]=XXXXX&PWD[8]=XXXXX&TRXTYPE=R&ACTION=A&TENDER=C&PROFILEREFERENCE=XXXX&PROFILENAME[38]=XAXXXXXAXXX&START=09182014&TERM=0&PAYPERIOD=MONT&AMT[4]=1.07&ORIGID=ESJPC2894AFC } } class Am_Paysystem_Payflow_Transaction_Upload extends Am_Paysystem_Payflow_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc) { parent::__construct($plugin, $invoice, true); $this->setCcRecord($cc); } protected function addRequestParams() { parent::addRequestParams(); //https://cms.paypal.com/cms_content/en_US/files/developer/PP_PayflowPro_Guide.pdf $this->request->addPostParameter(array( 'TRXTYPE' => 'A', 'TENDER' => 'C', 'COMMENT' => 'UPDATE CC: ' . $this->invoice->getLineDescription(), 'CUSTIP' => $this->doFirst ? $_SERVER['REMOTE_ADDR'] : $this->invoice->getUser()->get('remote_addr'), 'AMT' => 0 )); } public function getProfileId() { return $this->parsedResponse->PNREF; } public function processValidated() { } } class Am_Paysystem_Payflow_Transaction_Sale extends Am_Paysystem_Payflow_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, CcRecord $cc = null, $referenceId = null) { parent::__construct($plugin, $invoice, $doFirst, $referenceId); if ($cc) $this->setCcRecord($cc); elseif ($referenceId) $this->request->addPostParameter('ORIGID', $referenceId); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter(array( 'TRXTYPE' => 'S', 'TENDER' => 'C', 'AMT' => $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total, 'CURRENCY' => $this->invoice->currency, 'COMMENT' => $this->invoice->getLineDescription(), 'CUSTIP' => $this->doFirst ? $_SERVER['REMOTE_ADDR'] : $this->invoice->getUser()->get('remote_addr'), 'INVNUM' => $this->invoice->public_id . '-' . substr(md5(rand()),1,6), )); if (!$this->doFirst) $this->request->addPostParameter ('RECURRING', 'Y'); } public function processValidated() { if(!$this->doFirst) $this->invoice->getUser()->data()->set(Am_Paysystem_Payflow::USER_PROFILE_KEY, $this->parsedResponse->PNREF)->update(); parent::processValidated(); } } class Am_Paysystem_Payflow_Transaction_Authorization extends Am_Paysystem_Payflow_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, CcRecord $cc) { parent::__construct($plugin, $invoice, $doFirst); $this->setCcRecord($cc); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter(array( 'TRXTYPE' => 'A', 'TENDER' => 'C', 'AMT' => 0, 'COMMENT' => $this->invoice->getLineDescription(), 'CUSTIP' => $this->doFirst ? $_SERVER['REMOTE_ADDR'] : $this->invoice->getUser()->get('remote_addr'), 'INVNUM' => $this->invoice->public_id, )); } public function processValidated() { $this->invoice->addAccessPeriod($this); } } class Am_Paysystem_Payflow_Transaction_Refund extends Am_Paysystem_Payflow_Transaction { protected $origId; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $origId, $amount) { parent::__construct($plugin, $invoice, true); $this->request->addPostParameter('ORIGID', $origId); $this->amount = $amount; $this->request->addPostParameter('AMT', $amount); $this->origId = $origId; } public function getAmount() { return $this->amount; } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter(array( 'TRXTYPE' => 'C', 'TENDER' => 'C', )); } public function processValidated() { $this->result->setSuccess(); $this->invoice->addRefund($this, $this->origId); } } class Am_Paysystem_Payflow_Transaction_CreateSecureToken extends Am_Paysystem_Payflow_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, CcRecord $cc = null, $referenceId = null) { parent::__construct($plugin, $invoice, $doFirst, $referenceId); } protected function addRequestParams() { parent::addRequestParams(); $this->request->setNvpRequest(true); // send without encoding, else paypal handles encoded urls incorrectly $this->request->addPostParameter(array( 'TRXTYPE' => 'S', 'TENDER' => 'C', 'AMT' => $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total, 'CURRENCY' => $this->invoice->currency, 'CREATESECURETOKEN' => 'Y', 'SECURETOKENID' => uniqid('PFP'), 'CANCELURL' => $this->plugin->getRootUrl() . '/payment/payflow/cancel-payment?id=' . $this->invoice->public_id, 'DISABLERECEIPT' => true, // Determines if the payment confirmation / order receipt page is a PayPal hosted page or a page on the merchant site. 'EMAILCUSTOMER' => true, 'ERRORURL' => $this->plugin->getRootUrl() . '/payment/payflow/cancel-payment?id=' . $this->invoice->public_id, 'INVNUM' => $this->invoice->public_id, 'RETURNURL' => $this->plugin->getRootUrl() . '/payment/payflow/thanks', 'TEMPLATE' => 'MINLAYOUT', // or MOBILE for mobile iframe or TEMPLATEA TEMPLATEB 'SHOWAMOUNT' => (double)$this->invoice->first_total <= 0 ? false : true, )); } public function getToken() { return $this->parsedResponse->SECURETOKEN; } public function getTokenId() { return $this->parsedResponse->SECURETOKENID; } public function validate() { $tok = $this->parsedResponse->SECURETOKEN; if ($tok == '') return $this->result->setFailed(array("Transaction declined, cannot get secure token id")); $this->result->setSuccess($this); $k = 'payflow_securetoken_' . $tok; Am_Di::getInstance()->session->$k = 1; } public function getReceiptId() { } public function getUniqId() { } } PK\zBBcc/plugins/wepay-onsite.phpnu[getConfig('client_id')) && strlen($this->getConfig('secret')) && strlen($this->getConfig('token')) && strlen($this->getConfig('account_id')); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if (!($preapproval_id = $invoice->getUser()->data()->get(self::WEPAY_PREAPPROVAL_ID))) throw new Am_Exception_Paysystem("Stored wepay preapproval id not found"); $tr = new Am_Paysystem_Transaction_WepayOnsite_Checkout_Charge($this, $invoice, $doFirst, $preapproval_id); $tr->run($result); } public function _initSetupForm(Am_Form_Setup $form) { $form->addInteger('client_id', array('size' => 20)) ->setLabel('Your Client ID#'); $form->addText('secret', array('size' => 20)) ->setLabel('Your Client Secret'); $form->addText('token', array('size' => 40)) ->setLabel('Your Access Token'); $form->addInteger('account_id', array('size' => 20)) ->setLabel('Your Account ID#'); $form->addSelect('fee_payer')->setLabel(___('Who is paying the fee')) ->loadOptions(array( 'payee' => 'the person receiving the money', 'payer' => 'the person paying', /* 'payee_from_app' => 'if payee is paying for app fee and app is paying for WePay fees' 'payer_from_app' => 'if payer is paying for app fee and the app is paying WePay fees', */ )); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled" . "\n" . "The Test Mode requires a separate developer test account, which can be set up by filling out the following form: https://stage.wepay.com/developer/register"); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $trans = new Am_Paysystem_Transaction_WepayOnsite_Checkout_Refund($this, $payment->getInvoice(), $payment->receipt_id, $amount); $trans->run($result); } function getIframeUri() { $user = $this->getDi()->userTable->load($this->invoice->user_id); $invoice = $this->invoice; $tr = new Am_Paysystem_Transaction_WepayOnsite_GetCheckoutUri($this, $invoice); $result = new Am_Paysystem_Result(); $tr->run($result); if (!$tr->getUniqId()) throw new Am_Exception_Paysystem("Could not get iframe from wepay.com - [".$tr->getErrorDescription()."]"); return $tr->getUniqId(); } // use custom controller protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_CreditCard_WepayOnsite($request, $response, $invokeArgs); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->getActionName() == 'thanks') return $this->thanksAction($request, $response, $invokeArgs); parent::directAction($request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->get('checkout_id')) return new Am_Paysystem_Transaction_WepayOnsite_Checkout($this, $request, $response, $invokeArgs); else return new Am_Paysystem_Transaction_WepayOnsite_Preapproval($this, $request, $response, $invokeArgs); } public function getUpdateCcLink($user) { /* if ($user->data()->get(self::WEPAY_PREAPPROVAL_ID)) { $inv = $this->getDi()->invoiceTable->findFirstBy(array('user_id' => $user->pk(), 'paysys_id' => $this->getId()), 0, 1); if ($inv) return $this->getPluginUrl('update'); } */ } public function getReadme() { return <<createHttpRequest(), $doFirst); $this->request->setHeader("Content-Type", "application/json"); $this->request->setHeader("Authorization", "Bearer " . $this->plugin->getConfig('token')); $this->request->setBody(json_encode((array) $this->createParams())); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setUrl(!$this->plugin->getConfig('testing') ? Am_Paysystem_WepayOnsite::LIVE_URL : Am_Paysystem_WepayOnsite::SANDBOX_URL); } protected function createParams() { $params = new stdclass; $params->account_id = $this->plugin->getConfig('account_id'); $params->fee_payer = $this->plugin->getConfig('fee_payer'); return $params; } public function parseResponse() { $this->res = json_decode($this->response->getBody(), true); } public function validate() { if ($this->response->getStatus() != 200) { $this->result->setFailed(___('Payment failed')); return; } if (!empty($this->res['error_description'])) { $this->result->setFailed(___('Payment failed') . '(' . $this->res['error_description'] . ')'); return; } $this->result->setSuccess($this); return true; } public function getErrorDescription() { return @$this->res['error_description']; } } class Am_Paysystem_Transaction_WepayOnsite_GetCheckoutUri extends Am_Paysystem_Transaction_WepayOnsite { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst = true) { parent::__construct($plugin, $invoice, $doFirst); //recurring if (!is_null($invoice->second_period)) $this->request->setUrl($this->request->getUrl() . "preapproval/create"); else $this->request->setUrl($this->request->getUrl() . "checkout/create"); } protected function createParams() { $params = parent::createParams(); $params->short_description = $this->invoice->getLineDescription(); $params->reference_id = $this->invoice->public_id; $params->mode = 'iframe'; $params->redirect_uri = $this->plugin->getReturnUrl(); $params->callback_uri = $this->plugin->getPluginUrl('ipn'); //recurring if (!is_null($this->invoice->second_period)) { $params->amount = $this->invoice->second_total; $params->auto_recur = 'false'; $params->period = 'daily'; $this->uri = 'preapproval_uri'; } //not recurring else { $params->amount = $this->invoice->first_total; $params->type = 'GOODS'; $this->uri = 'checkout_uri'; } return $params; } public function getUniqId() { return $this->res[$this->uri]; } public function processValidated() { if (!is_null($this->invoice->second_period)) $this->invoice->data()->set(Am_Paysystem_WepayOnsite::WEPAY_PREAPPROVAL_ID, $this->res['preapproval_id'])->update(); else $this->invoice->data()->set(Am_Paysystem_WepayOnsite::WEPAY_PREAPPROVAL_ID, $this->res['checkout_id'])->update(); } } class Am_Mvc_Controller_CreditCard_WepayOnsite extends Am_Mvc_Controller { /** @var Am_Paysystem_WepayOnsite */ protected $plugin; /** @var Invoice */ protected $invoice; public function setPlugin($plugin) { $this->plugin = $plugin; } public function setInvoice($invoice) { $this->invoice = $invoice; } protected function ccError($msg) { $this->view->content .= "" . $msg . ""; $url = $this->_request->getRequestUri(); $url .= (strchr($url, '?') ? '&' : '?') . 'id=' . $this->_request->get('id'); $url = Am_Html::escape($url); $this->view->content .= " " . ___('Return and try again') . ""; $this->view->display('layout.phtml'); exit; } public function ccAction() { $this->view->title = ___('Payment Info'); $this->view->invoice = $this->invoice; $this->view->content = $this->view->render('_receipt.phtml'); return $this->displayHostedPage($this->plugin->getCancelUrl()); } protected function displayHostedPage($cancelUrl) { $uri = $this->plugin->getIframeUri(); $popupTitle = json_encode(___('Credit Card Info')); $this->view->content .= << CUT; $this->_response->setBody($this->view->render('layout.phtml')); } } class Am_Paysystem_Transaction_WepayOnsite_Checkout extends Am_Paysystem_Transaction_Incoming { public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $this->invoice = Am_Di::getInstance()->invoiceTable->findFirstBy(array('public_id' => $request->get('reference_id'))); $this->tr = new Am_Paysystem_Transaction_WepayOnsite_Checkout_Get($plugin, $this->invoice, true, $request); $result = new Am_Paysystem_Result(); $this->tr->run($result); if (!$this->tr->getReferenceId()) throw new Am_Exception_Paysystem(___('Error happened during payment process. ')); } public function findInvoiceId() { return $this->tr->getReferenceId(); } public function getUniqId() { return $this->tr->getUniqId(); } public function validateSource() { return $this->request->get('checkout_id') == $this->invoice->data()->get(Am_Paysystem_WepayOnsite::WEPAY_PREAPPROVAL_ID); } public function validateStatus() { return in_array($this->tr->getState(), array('captured', 'approved', 'authorized')); } public function validateTerms() { return true; } } class Am_Paysystem_Transaction_WepayOnsite_Checkout_Get extends Am_Paysystem_Transaction_WepayOnsite { /** @var Am_Mvc_Request */ protected $getrequest; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst = true, Am_Mvc_Request $getrequest) { $this->getrequest = $getrequest; parent::__construct($plugin, $invoice, $doFirst); $this->request->setUrl($this->request->getUrl() . "checkout"); } protected function createParams() { $params = parent::createParams(); unset($params->fee_payer); unset($params->account_id); $params->checkout_id = $this->getrequest->get('checkout_id'); return $params; } public function getUniqId() { return $this->res['checkout_id']; } public function getReferenceId() { return $this->res['reference_id']; } public function getState() { return $this->res['state']; } public function processValidated() { } } class Am_Paysystem_Transaction_WepayOnsite_Checkout_Charge extends Am_Paysystem_Transaction_WepayOnsite { /** @var Am_Mvc_Request */ protected $preapproval_id; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst = true, $preapproval_id) { $this->preapproval_id = $preapproval_id; parent::__construct($plugin, $invoice, $doFirst); $this->request->setUrl($this->request->getUrl() . "checkout/create"); } protected function createParams() { $params = parent::createParams(); $params->preapproval_id = $this->preapproval_id; $params->amount = $this->invoice->isPaid() ? $this->invoice->first_total : $this->invoice->second_total; $params->type = 'GOODS'; $params->short_description = $this->invoice->getLineDescription(); return $params; } public function getUniqId() { return $this->res['checkout_id']; } public function getState() { return $this->res['state']; } public function processValidated() { $user = $this->invoice->getUser(); $user->data()->set(Am_Paysystem_WepayOnsite::WEPAY_PREAPPROVAL_ID, $this->preapproval_id)->update(); $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_WepayOnsite_Preapproval extends Am_Paysystem_Transaction_Incoming { public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $this->invoice = Am_Di::getInstance()->invoiceTable->findFirstBy(array('public_id' => $request->get('reference_id'))); } public function findInvoiceId() { return $this->invoice->public_id; } public function getUniqId() { return $this->tr->getUniqId(); } public function validateSource() { if ($this->request->get('preapproval_id') != $this->invoice->data()->get(Am_Paysystem_WepayOnsite::WEPAY_PREAPPROVAL_ID)) return false; $this->tr = new Am_Paysystem_Transaction_WepayOnsite_Checkout_Charge($this->getPlugin(), $this->invoice, true, $this->request->get('preapproval_id')); $result = new Am_Paysystem_Result(); $this->tr->run($result); if (!$this->tr->getUniqId()) throw new Am_Exception_Paysystem(___('Error happened during payment process. ')); return true; } public function validateStatus() { return in_array($this->tr->getState(), array('captured', 'approved', 'authorized')); } public function validateTerms() { return true; } public function processValidated() { } } class Am_Paysystem_Transaction_WepayOnsite_Checkout_Refund extends Am_Paysystem_Transaction_WepayOnsite { protected $checkout_id; protected $amount; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $checkout_id, $amount) { $this->checkout_id = $checkout_id; $this->amount = $amount; parent::__construct($plugin, $invoice, $doFirst); $this->request->setUrl($this->request->getUrl() . "checkout/refund"); } protected function createParams() { $params = parent::createParams(); unset($params->fee_payer); unset($params->account_id); $params->checkout_id = $this->checkout_id; $params->amount = $this->amount; $params->refund_reason = 'Refund issued by admin'; return $params; } public function getUniqId() { return $this->res['checkout_id'] . '-refund'; } public function processValidated() { $this->invoice->addRefund($this, $this->checkout_id, $this->amount); } } PK\d/#/#cc/plugins/paddle/paddle.phpnu[getProducts()) > 1) { return array( ___("This paysystem " . "can not work with multiple products in card")); } else { return parent::isNotAcceptableForInvoice($invoice); } } function _initSetupForm(\Am_Form_Setup $form) { $form->addText('vendor_id', array('size' => 10)) ->setLabel("Vendor ID") ->addRule('required'); $form->addTextarea( 'public_key', array( 'class' => 'el-wide textlocal', 'id' => 'comment', 'maxlength' => 900), array('label' => ___("Public Key\n" . "Please include -----BEGIN PUBLIC KEY-----"))) ->addRule('required'); } function createForm($actionName) { $url = $this->getReturnUrl(); return new Am_Form_CreditCard_Paddle($this, $url, $this->invoice); } function createTransaction( Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Paddle_Transaction($this, $request, $response, $invokeArgs); } function init() { $prod_id = new Am_CustomFieldText_Paddle( 'paddle_prod_id', ___('Product ID'), ___("Product ID at paddle.com"), 'number', array('size' => 8)); $key = new Am_CustomFieldText_SecretKey( 'checkout_key', ___('Secret Key'), ___("Checkout Secret Key at paddle.com"), null, array('size' => 8)); $this->getDi()->productTable->customFields()->add($prod_id); $this->getDi()->productTable->customFields()->add($key); } function isConfigured() { return $this->getConfig('vendor_id') && $this->getConfig('public_key'); } function getReadme() { return <<request->getPost('passthrough'); //return '8LRVY'; } function getUniqId() { return $this->request->getPost('p_order_id'); } function validateSource() { $fields = $this->request->getParams(); //$this->plugin->logRequest($params); // Your Paddle 'Public Key' $public_key = $this->plugin->getConfig('public_key'); // Get the p_signature parameter & base64 decode it. $signature = base64_decode($this->request->getPost('p_signature')); //$this->plugin->logRequest($this->request->getPost('p_signature')); //$this->plugin->logRequest($signature); // Get the fields sent in the request, and remove the p_signature parameter //$fields = $this->request->getParams(); unset($fields['p_signature']); $this->filterFields($fields); // ksort() and serialize the fields ksort($fields); foreach($fields as $k => $v) { if(!in_array(gettype($v), array('object', 'array'))) { $fields[$k] = "$v"; } } $data = serialize($fields); $this->plugin->logRequest($data); // Veirfy the signature return openssl_verify( $data, $signature, $public_key, OPENSSL_ALGO_SHA1); } private function filterFields(&$array) { $fields = array( 'p_product_id', 'p_price', 'p_country', 'p_currency', 'p_sale_gross', 'p_tax_amount', 'p_paddle_fee', 'p_coupon_savings', 'p_earnings', 'p_order_id', 'p_coupon', 'p_used_price_override', 'passthrough', 'p_quantity', 'quantity' ); foreach($array as $key => $value) { if (!in_array($key, $fields)) { unset($array[$key]); } } } function validateStatus() { return true; } function validateTerms() { return true; } } class Am_CustomFieldText_Paddle extends Am_CustomFieldText { function addToQF2( HTML_QuickForm2_Container $container, $attr = array(), $data = array(), $runAt = HTML_QuickForm2_Rule::CLIENT_SERVER) { $el = $container->addElement($this->qfType, $this->name, $attr, $data) ->setLabel( !empty($this->description) ? ___($this->title) . "\n" . ___($this->description) : ___($this->title)); if (!empty($this->size)) $el->setAttribute('size', $this->size); if (!empty($this->default)) $el->setValue($this->default); $this->addValidateFunction($el, $runAt); return $el; } } class Am_CustomFieldText_SecretKey extends Am_CustomFieldText_Paddle { function addToQF2( HTML_QuickForm2_Container $container, $attr = array(), $data = array(), $runAt = HTML_QuickForm2_Rule::CLIENT_SERVER) { $el = parent::addToQF2($container, $attr, $data, $runAt); $r = $el->addRule( 'regex', ___("5-10 lowercase alphanumeriv characters"), '/^[a-z0-9]{5,10}$/', $runAt); return $el; } } class Am_Mvc_Controller_CreditCard_Paddle extends Am_Mvc_Controller_CreditCard { function ccAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); $this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form)); if ($this->form->isSubmitted() && $this->form->validate()) { if ($this->processCc()) return; } $this->view->form = $this->form; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->layoutNoMenu = true; $helper = $this->view->headScript(); $helper->appendFile( "https://cdn.paddle.com/paddle/paddle.js"); $helper->appendFile( $this->getDi()->url("application/cc/plugins/paddle/scripts.js",null,false,true)); $this->view->display('cc/info.phtml'); } } class Am_Form_CreditCard_Paddle extends Am_Form_CreditCard { /** * @var Invoice */ private $invoice; private $url; public function __construct( Am_Paysystem_CreditCard $plugin, $url, Invoice $invoice) { $this->invoice = $invoice; $this->url = $url; parent::__construct($plugin); } public function init() { Am_Form::init(); $invoice = $this->invoice; $user = $invoice->getUser(); $this->addStatic('payment-errors') ->setContent(<< CUT ); $products = $this->invoice->getProducts(); /* @var $product Product */ $product = $products[0]; $product_id = $product->data()->get('paddle_prod_id'); if (!$product_id) { throw new Am_Exception( "No paddle_prod_id product " . "is specified for {$product->title}"); } $checkout_key = $product->data()->get('checkout_key'); if (!$checkout_key) { throw new Am_Exception( "No checkout_key " . "is specified for {$product->title}"); } $price = $invoice->first_total; $priceAuthentication = md5($price.$checkout_key); $buttons = $this->addGroup(); $buttons->setSeparator(' '); $buttons->addInputButton('input_button', array( 'value'=> $this->payButtons[ $this->formType ] )) ->addClass('paddle_button') ->setAttribute('data-product', $product_id) ->setAttribute('data-email', $user->email) ->setAttribute('data-passthrough', $invoice->public_id) ->setAttribute('data-url', $this->url) ->setAttribute('data-price', $price) ->setAttribute('data-auth', $priceAuthentication); $vedor_id = $this->plugin->getConfig('vendor_id'); $debug = Am_Paysystem_Paddle::DEBUG; $this->addScript() ->setScript(<<setAction($this->url); $this->plugin->onFormInit($this); } }PK\cc/plugins/paddle/scripts.jsnu[jQuery(function($) { Paddle.Setup({ vendor: vendor, debug: debug }); /*jQuery('input[name="input_button"]').click(function() { var prod_id = $(this).data('product'); var email = $(this).data('email'); var invoice = $(this).data('invoice'); var url = $(this).data('url'); var price = $(this).data('price'); var auth = $(this).data('auth'); $('#row-payment-errors-0').hide(); Paddle.Checkout.open({ product: prod_id, email: email, passthrough: invoice, success: url, price: price, auth: auth, closeCallback: function(data) { console.log(data); $('#payment-errors').html("Payment failed..."); $('#row-payment-errors-0').show(); $('#payment-errors').show(); } }); });*/ }); PK\#PK9cc/plugins/payforit/scripts/payment-payforit-iframe.phtmlnu[setLayout('layout.phtml'); ?> PK\V - - cc/plugins/payforit/payforit.phpnu[_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } } class Am_Paysystem_Payforit extends Am_Paysystem_CreditCard { const PLUGIN_STATUS = self::STATUS_BETA; const PLUGIN_DATE = '$Date$'; const PLUGIN_REVISION = '5.0.6'; const URL = 'https://payforit.txtnation.com/api/'; const TRANSACTION_ID = 'payforit-reference-transaction'; public static $serverIPs = array( '67.23.27.65', '72.32.41.114', '72.32.41.115', '74.54.223.228', '74.54.223.230', '166.78.164.15', '174.143.237.218', '174.143.239.166', ); protected $defaultTitle = "Payforit: Pay with your Credit Card"; protected $defaultDescription = "accepts all major credit cards"; public function _initSetupForm(Am_Form_Setup $form) { $form->addText("company") ->setLabel("Your company name in payforit platform") ->addRule('required'); $form->addText("password", array('size' => 40)) ->setLabel("Your password in payforit platform") ->addRule('required'); $form->addSelect("window") ->setLabel("Type of Payforit Window\n" . "to render for the end user") ->loadOptions(array( 'small' => 'small', 'embed_small ' => 'embed_small ', 'large' => 'large', 'embed_large' => 'embed_large', )); $form->addAdvCheckbox("is_frame") ->setLabel("Use Iframe"); $form->addAdvCheckbox("debugLog") ->setLabel("Debug Log Enabled\n" . "write all requests/responses to log"); // hide reattempt $form->addScript()->setScript('jQuery(function(){jQuery("[id^=\'row-reattempt-\']").remove()});'); } public function init() { parent::init(); if($this->getConfig('is_frame')) { $script = <<getDi()->view->headScript()->appendScript($script); } } public function getRecurringType() { return self::REPORTS_REBILL; } public function storesCcInfo() { return false; } public function getSupportedCurrencies() { return array('GBP'); } public function isConfigured() { return strlen($this->getConfig('company')) && strlen($this->getConfig('password')); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { } private function parsePeriod($period) { preg_match('/(\d+)(\w)/', $period, $matches); @list($_, $num, $per) = $matches; switch ($per) { case 'd': $per = 'days'; break; case 'm': $per = 'months'; break; case 'y': $num *= 12; $per = 'months'; break; default: throw new Am_Exception_InternalError("Unknown period [$period]"); break; } return array( 'period' => $num, 'period_units' => $per, ); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $this->invoice = $invoice; $post = array( 'currency' => $this->invoice->currency, //'currency' => 'GBP', 'company' => $this->getConfig('company'), 'password' => $this->getConfig('password'), 'value' => $this->invoice->first_total, //'value' => 0.25, 'name' => $this->invoice->getLineDescription(), 'description' => $this->invoice->getLineDescription(), 'id' => $this->invoice->public_id, 'window' => $this->getConfig('window'), 'marketing' => 0, 'confirmation' => 0, 'callback_url' => $this->getPluginUrl('ipn'), 'success_url' => $this->getReturnUrl(), 'cancel_url' => $this->getCancelUrl(), ); if ($this->invoice->second_total > 0) // subscription charges { if ($this->invoice->first_total > 0 && $this->invoice->first_total != $this->invoice->second_total) throw new Am_Exception_InternalError('If product has no free trial first price must be the same second price'); if ($this->invoice->first_total > 0 && $this->invoice->first_period != $this->invoice->second_period) throw new Am_Exception_InternalError('If product has no free trial first period must be the same second period'); $post['sub_repeat'] = $this->invoice->rebill_times == IProduct::RECURRING_REBILLS ? 0 : $this->invoice->rebill_times; $period = $this->parsePeriod($this->invoice->second_period); $post['sub_period'] = $period['period']; $post['sub_period_units'] = $period['period_units']; if (!(float)$this->invoice->first_total) { $post['value'] = $this->invoice->second_total; $period = $this->parsePeriod($this->invoice->first_period); $post['sub_free_period'] = $period['period']; $post['sub_free_period_units'] = $period['period_units']; } } if ($this->getConfig('debugLog')) $this->getDi()->errorLogTable->log('Payforit. Request[cc]: ' . json_encode($post)); $req = new Am_HttpRequest(self::URL, Am_HttpRequest::METHOD_POST); $req->addPostParameter($post); $res = $req->send(); if ($res->getStatus() != '200') throw new Am_Exception_InternalError("Payforit API Error: bad status of server response [{$res->getStatus()}]"); if (!$res->getBody()) throw new Am_Exception_InternalError("Payforit API Error: server return null"); $this->logResponse($res->getBody()); if ($this->getConfig('debugLog')) $this->getDi()->errorLogTable->log('Payforit. Response[cc]: ' . $res->getBody()); $response = explode('|', $res->getBody()); if($response[0] != 'OK') { throw new Am_Exception_InternalError("Payforit API Error: {$response[1]}"); } $this->invoice->data()->set(self::TRANSACTION_ID, $response[1])->update(); if (!$this->getConfig('is_frame')) { header('Location: ' . $response[2]); return; } $a = new Am_Paysystem_Action_HtmlTemplate_Payforit($this->getDir(), 'payment-payforit-iframe.phtml'); $a->src = $response[2]; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $log = $this->logRequest($request); switch ($request->getActionName()) { case 'ipn': // first and rebill payments or subscription cancelled if ($this->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('Payforit. Request[ipn]: ' . json_encode($request->getParams())); if ($request->getInt('stop')) // subscription cancelled { if (!in_array($request->getClientIp(), Am_Paysystem_Payforit::$serverIPs)) throw new Am_Exception_Paysystem_TransactionInvalid("Bad server IP [{$request->getClientIp()}]"); $invoice = Am_Di::getInstance()->invoiceTable->findFirstByPublicId($request->getFiltered('key')); $invoice->setCancelled(true); return; } if ($request->getFiltered('status') == 'EXPIRED') // user navigated away from the PFI window without cancelling { return header("HTTP/1.0 200 OK"); } $transaction = new Am_Paysystem_Transaction_Payforit($this, $request, $response, $invokeArgs); try { $transaction->process(); } catch (Exception $e) { $this->getDi()->errorLogTable->logException($e); return header("HTTP/1.0 400 Bad request"); } $this->invoice = $transaction->getInvoice(); $log->setInvoice($this->invoice)->update(); $response->setRedirect($this->getReturnUrl()); break; default: if ($this->getConfig('debugLog')) Am_Di::getInstance()->errorLogTable->log('Payforit. Request[default]: ' . json_encode($request->getParams())); return parent::directAction($request, $response, $invokeArgs); break; } } public function getReadme() { return <<NOTE 1: Refunds are not possible via plugin, payforit service can only process them manually. NOTE 2: Cancel subscription is a feature payforit service plans to add to the API. NOTE 3: If product has no free trial first price must be the same second price. NOTE 4: If product has no free trial first period must be the same second period. CUT; } } class Am_Paysystem_Transaction_Payforit extends Am_Paysystem_Transaction_Incoming_Thanks { public function findInvoiceId() { return $this->request->getFiltered('key'); } public function getUniqId() { return $this->request->getInt('transactionId') . '-' . Am_Di::getInstance()->security->randomString(4); } public function validateStatus() { return $this->request->getFiltered('billed') == 1 && $this->request->getFiltered('status') == 'OK'; } public function validateTerms() { $savesTrId = Am_Di::getInstance()->invoiceTable->findFirstByPublicId($this->findInvoiceId())->data()->get(Am_Paysystem_Payforit::TRANSACTION_ID); $gettedTrId = $this->request->getInt('transactionId'); if ($savesTrId != $gettedTrId) throw new Am_Exception_Paysystem_TransactionInvalid("Getted transactionId [$gettedTrId] does not match saved [$savesTrId]"); return true; } public function validateSource() { if (!in_array($this->request->getClientIp(), Am_Paysystem_Payforit::$serverIPs)) throw new Am_Exception_Paysystem_TransactionInvalid("Bad server IP [{$this->request->getClientIp()}]"); return true; } }PK\Z-}#}#cc/plugins/quickpay.phpnu[ 'Approved.', '001' => 'Rejected by acquirer. See field \'chstat\' and \'chstatmsg\' for further explanation.', '002' => 'Communication error.', '003' => 'Card expired.', '004' => 'Transaction is not allowed for transaction current state.', '005' => 'Authorization is expired.', '006' => 'Error reported by acquirer.', '007' => 'Error reported by QuickPay.', '008' => 'Error in request data.', '009' => 'Payment aborted by shopper.' ); //const WINDOW_URL = 'https://secure.quickpay.dk/form/'; const API_URL = 'https://secure.quickpay.dk/api/'; const SUBSCRIBE = 'subscribe_transaction_number'; public function getFormOptions() { $ret = parent::getFormOptions(); $ret = array_diff($ret,array(self::CC_ADDRESS)); return $ret; } function storesCcInfo(){ return false; } public function getSupportedCurrencies() { return array('DKK', 'EUR', 'SEK', 'NOK', 'USD'); } function isRefundable(InvoicePayment $payment) { return true; } function getErrorMessage($code) { $message = $this->errorMessages[$code]; return $message; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant', array('size' => 20, 'maxlength' => 16)) ->setLabel("The QuickPayId") ->addRule('required'); $form->addText('secret', array('size' => 66, 'maxlength' => 80)) ->setLabel("Secret code") ->addRule('required'); $fl = $form->addFieldset()->setLabel(___('Quickpay parameters')); $fl->addSelect('lang', array(), array('options' => array( 'da' => 'Danish', 'de' => 'German', 'en' => 'English', 'es' => 'Spanish', 'fo' => 'Faeroese', 'fi' => 'Finnish', 'fr' => 'French', 'kl' => 'Greenlandish', 'it' => 'Italian', 'no' => 'Norwegian', 'nl' => 'Dutch', 'pl' => 'Polish', 'ru' => 'Russian', 'sv' => 'Swedish' )))->setLabel("The payment window language"); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc=null, Am_Paysystem_Result $result) { if($doFirst) { //1 Step subscription from api $parsedResponse = $this->processSubscribe($invoice, $cc); if(!$this->checkResponse($parsedResponse, $result)) return; $invoice->data()->set(self::SUBSCRIBE, (string)$parsedResponse->transaction)->update(); //2 Step recurring from api $request = $this->processRecurring($invoice, $doFirst); $transaction = new Am_Paysystem_Transaction_QuickpayCapture($this, $invoice, $request, $doFirst); $transaction->run($result); } else { //2 Step recurring from api $request = $this->processRecurring($invoice, $doFirst); $transaction = new Am_Paysystem_Transaction_QuickpayCapture($this, $invoice, $request, $doFirst); $transaction->run($result); } } function checkResponse($parsedResponse, Am_Paysystem_Result $result) { if((string)$parsedResponse->qpstat != '000') { $result->setFailed("Payment failed: Description - " .$this->getErrorMessage((string)$parsedResponse->qpstat) ." QuickPay message - " .$parsedResponse->qpstatmsg); return false; } return true; } function processSubscribe(Invoice $invoice, CcRecord $cc = null) { $request = new Am_HttpRequest(self::API_URL, Am_HttpRequest::METHOD_POST); $post_params = new stdclass; $post_params->protocol = '6'; $post_params->msgtype = 'subscribe'; $post_params->merchant = $this->getConfig('merchant'); $post_params->ordernumber = $invoice->public_id."-".sprintf("%03d", $invoice->getPaymentsCount()); $post_params->cardnumber = $cc->cc_number; $post_params->expirationdate = $cc->cc_expire; $post_params->cvd = $cc->getCvv(); $post_params->description = "Subscribe from aMember"; if($this->getConfig('testing')) $post_params->testmode = $this->getConfig('testing'); foreach((array)$post_params as $k => $v) { $cstr .= $v; } $cstr .= $this->getConfig('secret'); $post_params->md5check = md5($cstr); $request->addPostParameter((array)$post_params); $response = $request->send(); $parsedResponse = simplexml_load_string($response->getBody()); return $parsedResponse; } function processRecurring(Invoice $invoice, $doFirst = true) { $request = new Am_HttpRequest(self::API_URL, Am_HttpRequest::METHOD_POST); $post_params = new stdclass; $post_params->protocol = '6'; $post_params->msgtype = 'recurring'; $post_params->merchant = $this->getConfig('merchant'); $post_params->ordernumber = $invoice->public_id."-".sprintf("%03d", $invoice->getPaymentsCount())."-R"; $post_params->amount = ($doFirst ? $invoice->first_total : $invoice->second_total) * 100; $post_params->currency = $invoice->currency; $post_params->autocapture = '1'; $post_params->transaction = $invoice->data()->get(self::SUBSCRIBE); foreach((array)$post_params as $k => $v) { $cstr .= $v; } $cstr .= $this->getConfig('secret'); $post_params->md5check = md5($cstr); $request->addPostParameter((array)$post_params); return $request; } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $request = new Am_HttpRequest(self::API_URL, Am_HttpRequest::METHOD_POST); $post_params = new stdclass; $post_params->protocol = '6'; $post_params->msgtype = 'refund'; $post_params->merchant = $this->getConfig('merchant'); $post_params->amount = intval($amount * 100); $post_params->transaction = $payment->receipt_id; foreach((array)$post_params as $k => $v) { $cstr .= $v; } $cstr .= $this->getConfig('secret'); $post_params->md5check = md5($cstr); $request->addPostParameter((array)$post_params); $response = $request->send(); $parsedResponse = simplexml_load_string($response->getBody()); if((string)$parsedResponse->qpstat != '000') { $result->setFailed("Payment failed: Description - " .$this->getErrorMessage((string)$parsedResponse->qpstat) ." QuickPay message - " .$parsedResponse->qpstatmsg); } else { $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id.'-quickpay-refund'); $result->setSuccess($trans); } } function getReadme() { return <<Quickpay configuration: CUT; } } class Am_Paysystem_Transaction_QuickpayCapture extends Am_Paysystem_Transaction_CreditCard { public function validate() { if((string)$this->parsedResponse->qpstat != '000') { $this->result->setFailed("Payment failed: Description - " .$this->getPlugin()->getErrorMessage((string)$this->parsedResponse->qpstat) ." QuickPay message - " .$this->parsedResponse->qpstatmsg); } else { $this->result->setSuccess($this); } } public function parseResponse() { $this->parsedResponse = simplexml_load_string($this->response->getBody()); } public function getUniqId() { return (string)$this->parsedResponse->transaction; } } PK\x..cc/plugins/epay.phpnu[language = $this->getConfig('language', 2); // English default for testing. $a->merchantnumber = $this->getConfig('id'); $a->orderid = $invoice->public_id; $a->currency = Am_Currency::getNumericCode($invoice->currency); $a->amount = $invoice->first_total * 100; $a->accepturl = $this->getReturnUrl(); $a->declineurl = $this->getCancelUrl(); $a->callbackurl = $this->getPluginUrl('ipn'); $a->instantcallback = 1; // Call callback before user returned to accept_url $a->instantcapture = 1; $a->ordertext = $invoice->getLineDescription(); $a->windowstate = 2; if ($invoice->rebill_times) { $a->subscription = 1; $a->subscriptionname = sprintf('Invoice %s, User %s', $invoice->public_id, $invoice->getLogin()); } $a->md5key = $this->getOutgoingMd5($a); $result->setAction($a); } function getSupportedCurrencies() { return array('EUR', 'USD', 'GBP', 'DKK', 'NOK', 'SEK'); } function renameElement(Am_Form $form, $from, $to) { foreach ($form->getElementsByName($from) as $el) $el->setName($to); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc=null, Am_Paysystem_Result $result) { $transaction = new Am_Paysystem_Transaction_EpaySale($this, $invoice, null, $doFirst); $transaction->run($result); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('id')->setLabel('MerchantNumber'); $form->addText('key')->setLabel('Security Key'); $form->addSelect('language', array(), array('options' => array( 2 => 'English', 1 => 'Danish', 3 => 'Swedish', 4 => 'Norwegian', 5 => 'Greenland', 6 => 'Iceland', 7 => 'German', 8 => 'Finnish', 9 => 'Spanish' )))->setLabel('Language'); } public function isConfigured() { return strlen($this->getConfig('id')) && strlen($this->getConfig('key')); } function getEpayError($epay_code, $pbs_code){ $result = $this->APIRequest("subscription", "getEpayError", array( 'merchantnumber' => $this->getConfig('id'), 'language' => $this->getConfig('language'), 'epayresponsecode' => $epay_code )); $result1 = $this->APIRequest("subscription", "getPbsError", array( 'merchantnumber' => $this->getConfig('id'), 'language' => $this->getConfig('language'), 'pbsResponseCode' => $pbs_code )); $xml = $this->getResponseXML($result); $xml1 = $this->getResponseXML($result1); return $xml->getEpayErrorResponse->epayResponseString."
      ".$xml1->getPbsErrorResponse->pbsResponseString; } /** * * @param String $response * @return SimpleXmlElement */ public function getResponseXML($response){ if(!$response) throw new Am_Exception_InternalError("Can't cancel subscription. Empty result received from epay server!"); // We do this to not deal with namespaces. $response = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $response); $xml = simplexml_load_string($response); if($xml === false) throw new Am_Exception_InternalError("Can't parse XML!. Got response: $response"); return $xml->soapBody; } public function cancelInvoice(Invoice $invoice) { $subscriptionid = $invoice->data()->get(self::SUBSCRIPTIONID); if(!$subscriptionid) throw new Am_Exception_InternalError('Subscriptionid is empty in invoice! Nothing to cancel. '); $result = $this->APIRequest("subscription", "deletesubscription", array( 'merchantnumber' => $this->getConfig('id'), 'subscriptionid'=>$subscriptionid )); $xml = $this->getResponseXML($result); if($xml->deletesubscriptionResponse->deletesubscriptionResult != 'true') { throw new Am_Exception_InternalError("Subscription was not cancelled! Got: ".$xml->deletesubscriptionResponse->epayresponse); } // Cancelled; return ; } function createXML($type, $method, $vars){ $request = << CUT; $x = new SimpleXMLElement($request); $ns = $x->getNamespaces(); $m = $x->children($ns['soap'])->addChild($method,"", 'https://ssl.ditonlinebetalingssystem.dk/remote/'.$type); foreach($vars as $k=>$v){ $m->addChild($k, $v); } $xml = $x->asXML(); return $xml; } function APIRequest($type='subscription', $function='',$vars=array()){ try{ $client = new Am_HttpRequest(sprintf("https://ssl.ditonlinebetalingssystem.dk/remote/%s.asmx?op=%s", $type, $function), Am_HttpRequest::METHOD_POST); $client->setHeader('Content-type', 'text/xml'); $client->setHeader('SOAPAction', sprintf("https://ssl.ditonlinebetalingssystem.dk/remote/%s/%s", $type, $function)); $client->setBody($xml = $this->createXML($type, $function, $vars)); $response = $client->send(); }catch(Exception $e){ $this->getDi()->errorLogTable->logException($e); throw new Am_Exception_InputError("Unable to contact webservice. Got error: ".$e->getMessage()); } if(!$response->getBody()) throw new Am_Exception_InputError("Empty response received from API"); return $response->getBody(); } function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Epay($this, $request, $response, $invokeArgs); } function getOutgoingMd5(Am_Paysystem_Action $a) { return md5($a->currency.$a->amount.$a->orderid.$this->getConfig('key')); } function getIncomingMd5(Am_Mvc_Request $r) { $key = md5($s = $r->get('amount').$r->get('orderid').$r->get('tid').$this->getConfig('key')); return $key; } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $result = $this->APIRequest("payment", "credit", array( 'merchantnumber' => $this->getConfig('id'), 'transactionid'=> $payment->receipt_id, 'amount' => $amount*100 )); $xml = $this->getResponseXML($result); if($xml->creditResponse->creditResult == 'true'){ $trans = new Am_Paysystem_Transaction_Manual($this); $trans->setAmount($amount); $trans->setReceiptId($payment->receipt_id.'-epay-refund'); $result->setSuccess($trans); }else{ $result->setFailed(array('Error Processing Refund!')); } } function getReadme(){ return << "Payment system" -> "Go to settings for the "Payment system" Here you have 3 options for MD5 Security check 1: Don't want to use MD5 Disable the MD5 security feature 2: On accepturl only Only your accepturl will be using MD5 security check 3: On accepturl and by authorization Your accepturl and the authorization will be using MD5 security check Select option 2 or 3 then enter a MD5 security key in the "key" field CUT; } } class Am_Paysystem_Transaction_Epay extends Am_Paysystem_Transaction_Incoming{ public function getUniqId() { return $this->request->get('tid'); } public function findInvoiceId() { return $this->request->get('orderid'); } public function validateSource() { return $this->getPlugin()->getIncomingMd5($this->request) == $this->request->get('eKey'); } public function validateStatus() { return true; } public function validateTerms() { return $amount == ($this->first_total *100); } public function processValidated() { $this->invoice->addPayment($this); if($this->request->get('subscriptionid')){ $this->invoice->data()->set(Am_Paysystem_Epay::SUBSCRIPTIONID, $this->request->get('subscriptionid'))->update(); } } } class Am_Paysystem_Transaction_EpaySale extends Am_Paysystem_Transaction_CreditCard { protected $ret; public function run(Am_Paysystem_Result $result) { $subscriptionid = $this->invoice->data()->get(Am_Paysystem_Epay::SUBSCRIPTIONID); $req = $this->plugin->APIRequest('subscription', 'authorize', $vars= array( 'merchantnumber' => $this->plugin->getConfig('id'), 'subscriptionid' => $subscriptionid, 'orderid' => $this->invoice->public_id."-".$this->invoice->getPaymentsCount(), 'amount' => $this->invoice->second_total*100, 'currency' => Am_Currency::getNumericCode($this->invoice->currency), 'instantcapture' => 1, 'description' => 'Recurring payment for invoice '.$this->invoice->public_id, 'email' => $this->invoice->getEmail(), 'ipaddress' => $this->invoice->getUser()->remote_addr )); $log = $this->getInvoiceLog(); $log->add(print_r($vars, true)); $this->ret = $this->plugin->getResponseXML($req); $log->add(print_r($this->ret, true)); if($this->ret->authorizeResponse->authorizeResult != 'true') { $result->setFailed(___("Payment failed"). ":" . $this->plugin->getEpayError($this->ret->authorizeResponse->epayresponse)); } else { $result->setSuccess($this); $this->processValidated(); } } public function getUniqId() { return $this->ret->authorizeResponse->transactionid; } public function parseResponse() { } public function validate() { $this->result->setSuccess($this); } public function processValidated() { $this->invoice->addPayment($this); } }PK\}cc/plugins/eway.phpnu[getConfig('customer_id')); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("customer_id")->setLabel("eWAY customer ID\n" . 'Your unique eWAY customer ID assigned to you when you join eWAY. eg 87654321'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function getGateway() { return $this->getConfig('testing') ? self::GATEWAY_URL_TEST : self::GATEWAY_URL; } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if ($doFirst && !(float)$invoice->first_total) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $xml = new SimpleXMLElement(''); $xml->ewayCustomerID = $this->getConfig('customer_id'); $xml->ewayTotalAmount = $doFirst ? ($invoice->first_total * 100) : ($invoice->second_total * 100); $xml->ewayCustomerFirstName = $cc->cc_name_f; $xml->ewayCustomerLastName = $cc->cc_name_l; $xml->ewayCustomerEmail = $invoice->getUser()->email; $xml->ewayCustomerAddress = $cc->cc_street; $xml->ewayCustomerPostcode = $cc->cc_zip; $xml->ewayCustomerInvoiceDescription = $invoice->getLineDescription(); $xml->ewayCustomerInvoiceRef = $invoice->public_id; $xml->ewayCardHoldersName = sprintf('%s %s', $cc->cc_name_f, $cc->cc_name_l); $xml->ewayCardNumber = $cc->cc_number; $xml->ewayCardExpiryMonth = $cc->getExpire('%1$02d'); $xml->ewayCardExpiryYear = $cc->getExpire('%2$02d'); $xml->ewayTrxnNumber = $invoice->public_id; $xml->ewayOption1 = ''; $xml->ewayOption2 = ''; $xml->ewayOption3 = ''; $xml->ewayCVN = $cc->getCvv(); $request = new Am_HttpRequest($this->getGateway(), Am_HttpRequest::METHOD_POST); $request->setBody($xml->asXML()); $request->setHeader('Content-type', 'text/xml'); $tr = new Am_Paysystem_Transaction_CreditCard_Eway($this, $invoice, $request, $doFirst); $tr->run($result); } } } class Am_Paysystem_Transaction_CreditCard_Eway extends Am_Paysystem_Transaction_CreditCard { public function validate() { $xml = $this->vars; if ($xml->ewayTrxnStatus != 'True') { $this->result->setFailed($xml->ewayTrxnError); return; } $this->result->setSuccess(); } public function parseResponse() { $this->vars = new SimpleXMLElement($this->response->getBody()); return $this->vars; } public function getUniqId() { return $this->vars->ewayTrxnNumber; } }PK\’==0cc/plugins/micropayment-dbt/micropayment-dbt.phpnu[getConfig('key')); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $user = $invoice->getUser(); if ($cc->user_id != $user->pk()) throw new Am_Exception_Paysystem("Assertion failed: cc.user_id != user.user_id"); // will be stored only if cc# or expiration changed $this->storeCreditCard($cc, $result); if (!$result->isSuccess()) return; $user->refresh(); // we have both profile id and payment id, run the necessary transaction now if amount > 0 $result->reset(); if ($doFirst && (doubleval($invoice->first_total) <= 0)) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $request = array( $this->getConfig('key'), $this->getConfig('testing'), $user->data()->get(self::CUSTOMER_VAULT_ID), null, $this->getConfig('project'), '', '', '', ($doFirst ? intval($invoice->first_total*100) : intval($invoice->second_total*100)), $invoice->currency, $invoice->getLineDescription(), $invoice->getLineDescription(), $user->remote_addr ? $user->remote_addr : $_SERVER['REMOTE_ADDR'] ); $tr = new Am_Paysystem_Transaction_MicropaymentDbtSale($this, $invoice, $request, $doFirst); $tr->run($result); } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $transaction = new Am_Paysystem_Transaction_MicropaymentDbtRefund($this, $invoice, $request, $payment->transaction_id); $transaction->run($result); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("key")->setLabel("Access Key\n" . 'You\'ll find your AccessKey in ' . 'ControlCenter --> My Configuration'); $form->addText("project")->setLabel('Project Identifier'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $user = $this->getDi()->userTable->load($cc->user_id); $profileId = $user->data()->get(self::CUSTOMER_VAULT_ID); if ($this->invoice) { // to link log records with current invoice $invoice = $this->invoice; } else { // updating debit card info? $invoice = $this->getDi()->invoiceRecord; $invoice->invoice_id = 0; $invoice->user_id = $user->pk(); } // compare stored cc for that user may be we don't need to refresh? if ($profileId) { if($cc->cc_number != '0000000000000000') { $storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk()); if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)))) $update = true; } else { $result->setSuccess(); return; } } if (!$profileId) { try { $res = self::$dispatcher->customerCreate( $this->getConfig('key'), $this->getConfig('testing'), null, null); if($res) $profileId = $res['customerId']; else return; $user->data()->set(self::CUSTOMER_VAULT_ID, $profileId)->update(); } catch (Exception $e) { $result->setFailed($e->getMessage()); return false; } } try { $res = self::$dispatcher->addressSet( $this->getConfig('key'), $this->getConfig('testing'), $profileId, $cc->cc_name_f, $cc->cc_name_l, $cc->cc_street, $cc->cc_zip, $cc->cc_city, $cc->cc_country); $res = self::$dispatcher->bankaccountSet( $this->getConfig('key'), $this->getConfig('testing'), $profileId, $cc->cc_country,// $cc->cc_company, $cc->cc_number, $cc->cc_name_f.' '.$cc->cc_name_l); } catch(Exception $e) { $result->setFailed($e->getMessage()); return false; } /// $cc->cc = $cc->maskCc(@$cc->cc_number); $cc->cc_number = '0000000000000000'; if ($cc->pk()) $cc->update(); else $cc->replace(); $result->setSuccess(); } public function getDispatcher() { return self::$dispatcher; } public function getReadme() { return <<data()->get(self::CUSTOMER_VAULT_ID)) return $this->getPluginUrl('update'); } } class Am_Paysystem_Transaction_MicropaymentDbtSale extends Am_Paysystem_Transaction_CreditCard { protected $response; protected $sessionData; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $request, $doFirst = true) { parent::__construct($plugin, $invoice, $request, $doFirst); } public function run(Am_Paysystem_Result $result) { $this->result = $result; $log = $this->getInvoiceLog(); $log->add($this->request); try { $this->sessionData = call_user_func_array(array($this->getPlugin()->getDispatcher(),'sessionCreate'),$this->request); $this->response = $this->getPlugin()->getDispatcher()->sessionApprove( $this->getPlugin()->getConfig('key'), $this->getPlugin()->getConfig('testing'), $this->sessionData['sessionId']); $log->add($this->response); if ($this->response['status'] == 'APPROVED'){ $this->processValidated(); $result->setSuccess(); } } catch (Exception $e) { $result->setFailed($e->getMessage()); } } public function getUniqId() { return $this->sessionData['sessionId']; } public function parseResponse() { } } class Am_Mvc_Controller_CreditCard_MicropaymentDbt extends Am_Mvc_Controller_CreditCard { public function createUpdateForm() { $form = new Am_Form_MicropaymentDbt($this->plugin, Am_Form_CreditCard::USER_UPDATE); $user = $this->getDi()->auth->getUser(true); if (!$user) throw new Am_Exception_InputError("You are not logged-in"); $cc = $this->getDi()->ccRecordTable->findFirstByUserId($user->user_id); if (!$cc) $this->getDi()->ccRecordRecord; $arr = $cc->toArray(); unset($arr['cc_number']); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($arr) )); return $form; } } class Am_Form_MicropaymentDbt extends Am_Form { const PAYFORM = 'payform'; const USER_UPDATE = 'user-update'; const ADMIN_UPDATE = 'admin-update'; const ADMIN_INSERT = 'admin-insert'; protected $payButtons = array(); /** @var Am_Paysystem_CreditCard */ protected $plugin; protected $formType = self::PAYFORM; public function __construct(Am_Paysystem_CreditCard $plugin, $formType = self::PAYFORM) { $this->plugin = $plugin; $this->formType = $formType; $this->payButtons = array( self::PAYFORM => ___('Subscribe And Pay'), self::ADMIN_UPDATE => ___('Update Debit Card Info'), self::USER_UPDATE => ___('Update Debit Card Info'), self::ADMIN_INSERT => ___('Update Debit Card Info'), ); parent::__construct('cc'); } public function init() { parent::init(); $name = $this->addGroup() ->setLabel(___("Cardholder Name\n" . 'cardholder first and last name, exactly as on the card')); $name->addRule('required', ___('Please enter debit card holder name')); $name_f = $name->addText('cc_name_f', array('size'=>15)); $name_f->addRule('required', ___('Please enter debit card holder first name'))->addRule('regex', ___('Please enter debit card holder first name'), '|^[a-zA-Z_\' -]+$|'); $name_l = $name->addText('cc_name_l', array('size'=>15)); $name_l->addRule('required', ___('Please enter debit card holder last name'))->addRule('regex', ___('Please enter debit card holder last name'), '|^[a-zA-Z_\' -]+$|'); $options = $this->plugin->getFormOptions(); $company = $this->addText('cc_company') ->setLabel(___('Bank Code')); if ($this->formType == self::ADMIN_UPDATE) { $group = $this->addGroup()->setLabel(___('Debit Card Number'), ___('for example: 1111-2222-3333-4444')); $group->addStatic('cc'); $cc = $group->addText('cc_number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22, 'style'=>'display:none')); $cc->addRule('regex', ___('Invalid Debit Card Number'), '/^[0-9 -]+$/'); $group->addScript("")->setScript(<<addText('cc_number', array('autocomplete'=>'off', 'size'=>22, 'maxlength'=>22)) ->setLabel(___('Debit Card Number'), ___('for example: 1111-2222-3333-4444')); $cc->addRule('required', ___('Please enter Debit Card Number')) ->addRule('regex', ___('Invalid Debit Card Number'), '/^[0-9 -]+$/'); } $fieldSet = $this->addFieldset(___('Address Info')) ->setLabel(___("Address Info\n" . '(must match your debit card statement delivery address)')); $street = $fieldSet->addText('cc_street')->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); $city = $fieldSet->addText('cc_city')->setLabel(___('City')) ->addRule('required', ___('Please enter City')); $zip = $fieldSet->addText('cc_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); $country = $fieldSet->addSelect('cc_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); /** @todo load correct states */ $stateSelect = $group->addSelect('cc_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['cc_country'], true)); $stateText = $group->addText('cc_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); // if free trial set _TPL_CC_INFO_SUBMIT_BUT2 $buttons = $this->addGroup(); $buttons->addSubmit('_cc_', array('value'=> ' ' . $this->payButtons[ $this->formType ] .' ')); if ($this->formType == self::USER_UPDATE) { $buttons->addInputButton('_cc_', array('value'=> ' ' . ___("Back") .' ', 'onclick'=>'goBackToMember()')); $this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }"); } //$this->plugin->onFormInit($this); } /** * Return array of default values based on $user record * @param User $user */ public function getDefaultValues(User $user){ return array( 'cc_name_f' => $user->name_f, 'cc_name_l' => $user->name_l, 'cc_street' => $user->street, 'cc_street2' => $user->street2, 'cc_city' => $user->city, 'cc_state' => $user->state, 'cc_country' => $user->country, 'cc_zip' => $user->zip, 'cc_phone' => $user->phone, ); } public function validate() { return parent::validate();// && $this->plugin->onFormValidate($this); } public function getValue() { $ret = parent::getValue(); array_walk_recursive($ret, function(&$v, $k) {$v=trim($v);}); if (!empty($ret['cc_number'])) $ret['cc_number'] = preg_replace('/\D/', '', $ret['cc_number']); return $ret; } public function toCcRecord(CcRecord $cc){ $values = $this->getValue(); foreach ($values as $k=>$v) if (is_array($v) && !empty($v['m'])) $values[$k] = sprintf('%02d%02d', $v['m'], substr($v['y'], -2)); unset($values['_cc_bin_name']); unset($values['_cc_bin_phone']); unset($values['a']); unset($values['id']); if( !empty($values['cc_code'])) $cc->setCvv($values['cc_code']); unset($values['cc_code']); unset($values['action']); $cc->setForInsert($values); } } PK\Q?66Fcc/plugins/micropayment-dbt/lib/clients/TSimpleHttpClientException.txtnu[streamopen_failed = An Error occured during connect to "{2}:{3}" #{0} "{1}" streamopen_ssl_not_supported = SSL currently not supported streamwrite_failed = An Error occured during writing data to stream "{1}:{2}{3}" {0} streamread_failed = An Error occured during reading data from stream "{1}:{2}{3}"PK\((=cc/plugins/micropayment-dbt/lib/clients/TSimpleHttpClient.phpnu[ _headers; } /** * @param array $value */ public function setHeaders($value) { if( is_array($value) ) { $this -> _headers = $value; } } /** * @param string $name * @param string $value * @param boolean $replace */ public function addHeader($name, $value, $replace=true) { if($replace OR !isset($this -> _headers[$name])) $this -> _headers[$name] = $value; } /** * @param string $name */ public function removeHeader($name) { if(isset($this -> _headers[$name])) unset($this -> _headers[$name]); } /** * @param string $name * @return boolean */ public function isHeader($name) { array_key_exists($name, $this -> _headers); } /** * @param string $name * @return string */ public function getHeader($name) { if(isset($this -> _headers[$name])) return $this -> _headers[$name]; } /** * @param string $value */ public function setBody($value) { $this -> _body = (string)$value; } /** * @return string $value */ public function getBody() { return $this -> _body; } } class TSimpleHttpResponse extends TSimpleHttpBase { /** * @var integer */ private $_statusCode = 0; /** * @var string */ private $_statusMessage = ''; /** * @param integer $code * @param string $message * @param string $body * @param array $headers */ public function __construct($code=0, $message='', $body='', $headers=null) { $this -> setStatusCode($code); $this -> setStatusMessage($message); $this -> setBody($body); $this -> setHeaders($headers); } /** * @param integer $value */ protected function setStatusCode($value) { $this -> _statusCode = (integer)$value; } /** * @return integer */ public function getStatusCode() { return $this -> _statusCode; } /** * @param string $value */ protected function setStatusMessage($value) { $this -> _statusMessage = (string)$value; } /** * @return string */ public function getStatusMessage() { return $this -> _statusMessage; } public function __toString() { return $this -> getBody(); } /** * @param string $data * @return TSimpleHttpResponse */ public static function parse(&$data) { $tmp = preg_split('(\r\n\r\n|\r\r|\n\n)', $data); $code = 0; $message = ''; $body = $data; $headers = array(); $tmpHeader = trim($tmp[0]); if( preg_match('/^HTTP\/\d.\d/i', $tmpHeader) ) { $body = preg_replace('/' . preg_quote($tmpHeader, '/') . '/', '', $body); $body = preg_replace('/^(\r\n\r\n|\r\r|\n\n)/', '', $body); } else { $tmpHeader = ''; } if($tmpHeader) { $proto = false; $tmp = explode("\n", $tmpHeader); foreach($tmp as $row) { if(!$proto) { if( $proto = preg_match('/^HTTP\/\d.\d (\d{3,}) (.*)/i', $row, $matches) ) { $code = $matches[1]; $message = $matches[2]; continue; } } list($k, $v) = preg_split('(: )', $row); $headers[trim($k)] = trim($v); } } // UTF-8 Hack laut Guido if(substr($body, 0, 3) === '') { $body = substr($body, 3); } return new TSimpleHttpResponse($code, $message, $body, $headers); } } class TSimpleHttpClient extends TSimpleHttpBase { const SSL_PORT = 443; const POST = 'POST'; const GET = 'GET'; const AUTHORIZATION_BASIC = 'Basic'; private $_requestMethod = self::POST; /** * @var string */ private $_host = ''; /** * @var integer */ private $_port = 80; /** * @var string */ private $_path = '/'; /** * @var string */ private $_query = ''; /** * @var string */ private $_user = ''; /** * @var string */ private $_pass = ''; /** * @var string */ private $_auth = self::AUTHORIZATION_BASIC; /** * @var resource */ private $fp = null; /** * @param string $method * @param string $uri */ public function __construct($method=TSimpleHttpClient::POST, $uri='') { $this -> setRequestMethod($method); $this -> parseUri($uri); } /** * @return TSimpleHttpResponse * @throws TSimpleHttpClientException */ public function request() { if( $this -> getBody() ) $this -> setRequestMethod(self::POST); $result = ''; switch($this -> getAuthorization() ) { case self::AUTHORIZATION_BASIC: if( $this -> getUser() )$this -> addHeader('Authorization', 'Basic ' . base64_encode($this -> getUser() . ':' . $this -> getPass()) ); break; } // modifications for GET requests do { if($this -> isPost()) break; if($this -> isHeader('Content-type')) $this -> removeHeader('Content-type'); if($this -> isHeader('Content-length')) $this -> removeHeader('Content-length'); } while(0); // modifications for POST requests do { if(!$this -> isPost()) break; if( !$this -> isHeader('Content-length') ) $this -> addHeader('Content-length', (integer)strlen($this -> getBody()) ); } while(0); $query = $this -> getQuery(); if($query) { $path = $this -> getPath(); $path .= '?' .$query; $this -> setPath($path); } $this -> streamOpen(); $this -> streamWrite( sPrintF("%s %s HTTP/1.0\n", $this -> getRequestMethod(), $this -> getPath()) ); $this -> streamWrite( sPrintF("Host: %s \n", $this -> getHost()) ); foreach( $this -> getHeaders() as $hName => $hValue) $this -> streamWrite( sPrintF("%s: %s\n", $hName, $hValue) ); $this -> streamWrite("Connection: close\n\n"); if($this -> isPost() ) $this -> streamWrite( $this -> getBody() . "\n"); while(!$this -> streamEOF() ) { $result .= $this -> streamRead(512); } $this -> streamClose(); return TSimpleHttpResponse::parse($result); } private function streamOpen() { $errno = 0; $errstr = ''; $host = $this -> isSSL() ? 'ssl://' : ''; $host .= $this -> getHost(); $this -> fp = @fSockOpen($host, $this -> getPort(), $errno, $errstr, 30); if(!$this -> fp) throw new TSimpleHttpClientException('streamopen_failed', $errno, $errstr, $this -> getHost(), $this -> getPort()); } private function streamWrite($data) { $result = fWrite($this -> fp, $data); if($result === false) throw new TSimpleHttpClientException('streamwrite_failed', $data, $this -> getHost(), $this -> getPort(), $this -> getPath()); return $result; } private function streamRead($length) { $result = fRead($this -> fp, $length); if($result === false) throw new TSimpleHttpClientException('streamread_failed', $this -> getHost(), $this -> getPort(), $this -> getPath()); return $result; } private function streamEOF() { return fEoF($this -> fp); } private function streamClose() { if($this -> fp) @fClose($this -> fp); } /** * @param string $uri * @return boolean */ public function parseUri($uri) { if( empty($uri) ) return false; $uri = parse_url( $uri); if( isset($uri['port'])) $this -> setPort($uri['port']); if( isset($uri['scheme']) AND $uri['scheme'] == 'https') $this -> setPort(self::SSL_PORT); if( isset($uri['host'])) $this -> setHost($uri['host']); if( isset($uri['path'])) $this -> setPath($uri['path']); if( isset($uri['query'])) $this -> setQuery($uri['query']); if( isset($uri['user'])) $this -> setUser($uri['user']); if( isset($uri['pass'])) $this -> setPass($uri['pass']); if( isset($uri['user']) ) $this -> setAuthorization(self::AUTHORIZATION_BASIC); } /** * @param string $value */ public function setAuthorization($value) { $this -> _auth = $value; } /** * @return string */ public function getAuthorization() { return $this -> _auth; } /** * @param string $value */ public function setRequestMethod($value) { $this -> _requestMethod = $value; } /** * @return string */ public function getRequestMethod() { return $this -> _requestMethod; } /** * @param string $value */ public function setHost($value) { $this -> _host = (string)$value; } /** * @return string */ public function getHost() { return $this -> _host; } /** * @param integer $value */ public function setPort($value) { $this -> _port = (integer)$value; } /** * @return integer */ public function getPort() { return $this -> _port; } /** * @param string $value */ public function setPath($value) { $this -> _path = (string)$value; } /** * @return string */ public function getPath() { return $this -> _path; } /** * @param string $value */ public function setUser($value) { $this -> _user = (string)$value; $this -> setAuthorization(self::AUTHORIZATION_BASIC); } /** * @return string */ public function getUser() { return $this -> _user; } /** * @param string $value */ public function setPass($value) { $this -> _pass = (string)$value; } /** * @return string */ public function getPass() { return $this -> _pass; } /** * @param mixed $value * @param string only if $value is array or object */ public function setQuery($value, $argSeparator='&') { if( is_scalar($value) ) { $this -> _query = (string)$value; } else { $this -> _query = http_build_query($value, '', $argSeparator); } } /** * @param boolean $map * @return mixed */ public function getQuery($map=false) { $result = $this -> _query; if($map) parse_str($this -> _query, $result); return $result; } /** * * @return boolean */ public function isSSL() { return ($this -> _port == self::SSL_PORT); } /** * @return boolean */ public function isPost() { return ($this -> getRequestMethod() == self::POST); } } ?>PK\3cc/plugins/micropayment-dbt/lib/common/messages.txtnu[PK\:GG5cc/plugins/micropayment-dbt/lib/common/TException.phpnu[ _errorCode = $errorCode; $errorMessage = $this -> translateErrorMessage($errorCode); $args = func_get_args(); array_shift($args); parent::__construct( $this -> replaceMessageToken($errorMessage, $args), (is_numeric($errorCode) ? $errorCode : null) ); } /** * @param string $message * @param array $args * @return string */ protected function replaceMessageToken($message, $args) { $n = count($args); $tokens = array(); for($i=0; $i<$n; ++$i) $tokens['{' . $i . '}'] = (string)$args[$i]; return strTr($message, $tokens); } /** * Translates an error code into an error message. * @param string $key error code that is passed in the exception constructor. * @return string the translated error message */ protected function translateErrorMessage($key) { $msgFile = $this -> getErrorMessageFile(); if( ($entries = @file($msgFile) ) === false ) return $key; else { foreach($entries as $entry) { $tmp = explode('=', $entry, 2); $code = isset($tmp[0]) ? $tmp[0] : ''; $message = isset($tmp[1]) ? $tmp[1] : ''; if( trim($code) == $key ) return trim($message); } return $key; } } /** * @return string path to the error message file */ protected function getErrorMessageFile() { return dirname(__FILE__) . '/messages.txt'; } /** * @return string error code */ public function getErrorCode() { return $this -> _errorCode; } /** * @param string $code error code */ public function setErrorCode($code) { $this -> _errorCode = $code; } /** * @return string error message */ public function getErrorMessage() { return $this -> getMessage(); } /** * @param string $message error message */ protected function setErrorMessage($message) { $this -> message = $message; } } class TSystemException extends TException {} class TPhpErrorException extends TSystemException { /** * Constructor. * @param integer $errno error number * @param string $errstr error string * @param string $errfile error file * @param integer $errline error line number */ public function __construct($errno, $errstr, $errfile, $errline) { static $errorTypes = array( E_ERROR => 'Error', E_WARNING => 'Warning', E_PARSE => 'Parsing Error', E_NOTICE => 'Notice', E_CORE_ERROR => 'Core Error', E_CORE_WARNING => 'Core Warning', E_COMPILE_ERROR => 'Compile Error', E_COMPILE_WARNING => 'Compile Warning', E_USER_ERROR => 'User Error', E_USER_WARNING => 'User Warning', E_USER_NOTICE => 'User Notice', E_STRICT => 'Runtime Notice' ); $errorType = isset($errorTypes[$errno]) ? $errorTypes[$errno] : 'Unknown Error'; parent::__construct( sPrintF('[%s] %s (@line %d in file %s)', $errorType, $errstr, $errline, $errfile) ); } } /** * THttpException class * * THttpException represents an exception that is caused by invalid operations * of end-users. The {@link getStatusCode StatusCode} gives the type of HTTP error. */ class THttpException extends TSystemException { private $_statusCode; /** * Constructor. * @param integer $statusCode HTTP status code, such as 404, 500, etc. * @param string $errorCode error message. This can be a string that is listed * in the message file. If so, the message in the preferred language * will be used as the error message. Any rest parameters will be used * to replace placeholders ({0}, {1}, {2}, etc.) in the message. */ public function __construct($statusCode, $errorCode) { $this -> setStatusCode($statusCode); $this -> setErrorCode($errorCode); $errorMessage = $this -> translateErrorMessage($errorCode); $args = func_get_args(); array_shift($args); array_shift($args); $this -> setErrorMessage( $this -> replaceMessageToken($errorMessage, $args) ); } /** * @return integer HTTP status code, such as 404, 500, etc. */ public function getStatusCode() { return $this -> _statusCode; } public function setStatusCode($value) { $this -> _statusCode = (integer)$value; $this -> code = (integer)$value; } } ?>PK\~ZZ;cc/plugins/micropayment-dbt/lib/common/TServiceProtocol.phpnu[PK\66<cc/plugins/micropayment-dbt/lib/common/ServiceReflection.phpnu[ _className = $className; $this -> reflectService($options); } /** * @return ClassServiceReflection */ public function getServiceClassReflection() { return $this -> _serviceClassReflection; } /** * @return string */ public function getClass() { return $this -> _className; } /** * @param integer $options */ protected function reflectService($options=0) { $this -> _serviceClassReflection = ClassServiceReflection::createReflection(new ReflectionClass( $this -> getClass() ) ); } } abstract class BaseServiceReflection { /** * @var string */ private $_type = ''; /** * @var string */ private $_description = ''; /** * @param string $type * @param string $description */ public function __construct($type='', $description='') { $this -> setType($type); $this -> setDescription($description); } /** * @param string $value */ public function setType($value) { $this -> _type = (string)$value; } /** * @return string */ public function getType() { return $this -> _type; } /** * @param string $value */ public function setDescription($value) { $this -> _description = (string)$value; } /** * @return string */ public function getDescription() { return $this -> _description; } protected static function removeCommentElements($value) { $value = preg_replace('/(^[\\s]*\\/\\*\\*)|(^[\\s]\\*\\/)|(^[\\s]*\\*?\\s)|(^[\\s]*)|(^[\\t]*)/ixm', '', $value); $value = preg_replace('/(\*\/)$/i', '', $value); $value = trim($value); return $value; } protected static function prepareDocComment($value) { $value = self::removeCommentElements($value); $value = str_replace("\r", '', $value); $value = preg_replace("/([\\t])+/", "\t", $value); return explode("\n", $value); } /** * @param string $value * @return string */ protected static function getDescriptionBlock($value) { $commentLines = self::prepareDocComment($value); $result = ''; foreach($commentLines as $line) { if($line == '') continue; if($line{0} == '@') continue; $result .= $line; $result .= "\n"; } $result = trim($result); return $result; } } class NamedServiceReflectionBase extends BaseServiceReflection { /** * @var string */ private $_name = null; /** * @param string $name * @param string $type * @param string $description */ public function __construct($name='', $type='', $description='') { parent::__construct($type, $description); $this -> setName($name); } /** * @param string $value */ public function setName($value) { $this -> _name = (string)$value; } /** * @return string */ public function getName() { return $this -> _name; } } class ClassServiceReflection extends BaseServiceReflection { /** * @var MethodServiceReflection[] */ private $_methods = array(); /** * @param MethodServiceReflection[] $value */ public function setMethods($value) { if( !is_array($value) ) return; } /** * @return MethodServiceReflection[] */ public function getMethods() { return $this -> _methods; } /** * @param string $name * @return MethodServiceReflection */ public function getMethod($name) { if( !$this -> hasMethod($name) ) return null; return $this -> _methods[$name]; } /** * @param string $name * @return boolean */ public function hasMethod($name) { return isset($this -> _methods[$name]); } /** * @param MethodServiceReflection $value */ public function addMethod(MethodServiceReflection $value) { $this -> _methods[$value -> getName()] = $value; } static public function createReflection(ReflectionClass $reflection) { $result = new ClassServiceReflection($reflection -> getName(), self::getDescriptionBlock($reflection -> getDocComment())); $methods = $reflection -> getMethods(); foreach($methods as $method) { if( !$method -> isPublic()) continue; $result -> addMethod( MethodServiceReflection::createReflection($method) ); } return $result; } public function getTypes() { $result = array(); foreach($this -> getMethods() as $item) { $result = array_merge($result, $item -> getTypes()); } return $result; } } class MethodServiceReflection extends NamedServiceReflectionBase { /** * @var ParameterServiceReflection[] */ private $_parameters = array(); /** * @var ReturnServiceReflection */ private $_return = null; /** * @param string $name * @param string $type * @param string $description * @param ParameterServiceReflection[] $parameters * @param ReturnServiceReflection $return */ public function __construct($name='', $type='', $description='', $parameters=null, $return=null) { parent::__construct($name, $type, $description); $this -> setParameters($parameters); $this -> setReturn($return); } /** * @param ParameterServiceReflection[] $value */ public function setParameters($value) { if( !is_array($value) ) return; $_parameters = array(); foreach($value as $param) { $this -> addParamter($param); } } /** * @return ParameterServiceReflection[] */ public function getParameters() { return $this -> _parameters; } /** * @return integer */ public function getNumberOfParameters() { return count($this -> _parameters); } /** * @param ParameterServiceReflection $value */ public function addParamter(ParameterServiceReflection $value) { $this -> _parameters[$value -> getName()] = $value; } /** * @param string $name * @return ParameterServiceReflection */ public function getParamter($name) { if( !isset($this -> _parameters[$name]) ) return null; return $this -> _parameters[$name]; } /** * @param ReturnServiceReflection $value */ public function setReturn($value) { if( !$value instanceof ReturnServiceReflection) return; $this -> _return = $value; } /** * @return ReturnServiceReflection */ public function getReturn() { return $this -> _return; } static public function createReflection(ReflectionMethod $reflection) { $comment = $reflection -> getDocComment(); $result = new MethodServiceReflection($reflection -> getName(), '', self::getDescriptionBlock($comment)); $commentLines = self::prepareDocComment($comment); $tmpParams = array(); $return = new ReturnServiceReflection('void', ''); $params = $reflection -> getParameters(); foreach($params as $param) { $name = $param -> getName(); $tmpParams[$name] = new ParameterServiceReflection($name, 'mixed'); /* QUICKFIX: for Bug#62715 in PHP 5.3.16 * @link https://bugs.php.net/bug.php?id=62715 * Fatal error: Uncaught exception 'ReflectionException' with message 'Parameter is not optional' */ if(version_compare(str_replace(PHP_EXTRA_VERSION, '', PHP_VERSION) , '5.3.16', 'eq')) continue; if( $param -> isDefaultValueAvailable() ) { $tmpParams[$name] -> setHasDefault(true); $tmpParams[$name] -> setRequired(false); $tmpParams[$name] -> setDefault( $param -> getDefaultValue(), false); } } foreach($commentLines as $line) { if ($line == '') continue; if ($line{0} != '@') continue; if( preg_match('/^@param\s+([\w\[\]()]+)\s+\$([\w()]+)\s*(.*)/i', $line, $match) ) { $type = $match[1]; $name = $match[2]; $desc = $match[3]; $param = new ParameterServiceReflection($name, $type, $desc); if( preg_match('/\(default=(.*)\)/i', $desc, $regs) ) { $param -> setHasDefault(true); $param -> setRequired(false); $default = $regs[1]; if($default == "''") { $param -> setDefault('', false); } elseif($default{0} == "'") { $default = substr($default, 1, strlen($default) -2); $param -> setDefault($default); } else { $param -> setDefault($default); } $desc = preg_replace('/' . preg_quote('(default=' . $regs[1] . ')', '/') . '/i', '', $desc); $param -> setDescription($desc); } $tmpParams[$name] = $param; } if( preg_match('/^@return\s+([\w\[\]()]+)\s*(.*)/i', $line, $match) ) { $return -> setType($match[1]); $return -> setDescription($match[2]); } if( preg_match('/^@result\s+([\w\[\]()]+)\s+\$([\w()]+)\s*(.*)/i', $line, $match) ) { $name = $match[2]; $type = $match[1]; $desc = $match[3]; if( preg_match('/\(default=(.*)\)/i', $desc, $regs) ) { $resultParam = new ParameterServiceReflection($name, $type, $desc); $resultParam -> setHasDefault(true); $resultParam -> setRequired(false); $default = $regs[1]; if($default == "''") { $resultParam -> setDefault('', false); } elseif($default{0} == "'") { $default = substr($default, 1, strlen($default) -2); $resultParam -> setDefault($default); } else { $resultParam -> setDefault($default); } $desc = preg_replace('/' . preg_quote('(default=' . $regs[1] . ')', '/') . '/i', '', $desc); $resultParam -> setDescription($desc); $return -> addResult( $resultParam ); } else { $return -> addResult( new NamedServiceReflectionBase($name, $type, $desc) ); } } } $result -> setParameters($tmpParams); $result -> setReturn($return); return $result; } public function getTypes() { $result = $this -> getReturn() -> getTypes(); foreach($this -> getParameters() as $item) { $result[$item -> getType()] = $item -> getType(); } return $result; } } class ParameterServiceReflection extends NamedServiceReflectionBase { /** * @var boolean */ private $_hasDefault = false; /** * @var boolean */ private $_required = false; /** * @var mixed */ private $_default = null; /** * @param string $name * @param string $type * @param string $description * @param boolean $required * @param mixed $default */ public function __construct($name='', $type='', $description='', $hasDefault = false, $required=true, $default=null) { parent::__construct($name, $type, $description); $this -> setDefault($default); $this -> setHasDefault($hasDefault); $this -> setRequired($required); } /** * @param mixed $value * @param boolean $typeCast */ public function setDefault($value, $typeCast=true) { if($typeCast) { $type = gettype($value); switch( strToLower($type) ) { case 'boolean': case 'bool': $this -> _default = $value ? true : false; break; case 'double': case 'float': $this -> _default = (float)$value; break; case 'integer': $this -> _default = (integer)$value; break; case 'null': $this -> _default = null; break; case 'string': if($value == 'null') $this -> _default = null; elseif($value == 'true') $this -> _default = true; elseif($value == 'false') $this -> _default = false; else $this -> _default = $value; break; default: $this -> _default = $value; break; } } else { $this -> _default = $value; } $this -> setHasDefault(true); } /** * @return string */ public function getDefault() { return $this -> _default; } public function getDefaultAsText() { $result = $this -> _default; if($result === null) { $result = 'null'; } elseif( is_bool($result) ) { $result = $result ? 'true' : 'false'; } elseif( is_string($result) ) { if( is_numeric($result) OR $result === '' ) { } else { $result = '\'' . $result . '\''; } } return $result; } /** * @param boolean $value */ public function setRequired($value) { $this -> _required = (boolean)$value; } /** * @return boolean */ public function getRequired() { return $this -> _required; } /** * @param boolean $value */ public function setHasDefault($value) { $this -> _hasDefault = (boolean)$value; } /** * @return boolean */ public function getHasDefault() { return $this -> _hasDefault; } } class ReturnServiceReflection extends BaseServiceReflection { /** * @var NamedServiceReflectionBase[] */ protected $_results = array(); /** * @return integer */ public function getNumberOfResults() { return count($this -> _results); } /** * @param NamedServiceReflectionBase[] $value */ public function setResults($value) { if(!is_array($value)) return; } /** * @return NamedServiceReflectionBase[] */ public function getResults() { return $this -> _results; } /** * @param NamedServiceReflectionBase $value */ public function addResult(NamedServiceReflectionBase $value) { $this -> _results[$value -> getName()] = $value; } public function getTypes() { $result = array(); $result[$this -> getType()] = $this -> getType(); foreach($this -> getResults() as $item) { $result[$item -> getType()] = $item -> getType(); } return $result; } } ?>PK\ **>cc/plugins/micropayment-dbt/lib/serializer/TBaseSerializer.phpnu[ $v) { if( !is_numeric($k)) { $result = true; break; } } } return $result; } } ?>PK\\\=cc/plugins/micropayment-dbt/lib/serializer/TNvpSerializer.phpnu[ 0) $result .= self::serializeNVP('@indices', implode(',', array_keys($data)), '#' . $prefix); foreach($data as $key => $value) { $idx = ($deep > 0 ? '[' . $key . ']' : $key); if(is_scalar($value)) { $result .= self::serializeNVP($idx, $value, $prefix); } else { $result .= self::serializeRecursive($value, $prefix . $idx, $deep); } } } elseif( is_array($data) ) { $cnt = count($data); //$result .= self::serializeNVP('@count', $cnt, '#' . $prefix); for($i=0; $i<$cnt; $i++) { $idx = '[' . $i . ']'; if(is_scalar($data[$i])) { $result .= self::serializeNVP($idx, $data[$i], $prefix); } else { $result .= self::serializeRecursive($data[$i], $prefix . $idx, $deep); } } } elseif( is_object($data)) { if($deep > 0) { $reflectionObject = new ReflectionObject($data); $reflectionProperties = $reflectionObject -> getProperties(); $properties = array(); foreach($reflectionProperties as $property) { if( !$property -> isPublic() ) continue; $properties[] = $property -> getName(); } //$result .= self::serializeNVP('@properties', implode(',', $properties), '#' . $prefix); } foreach($data as $key => $value) { $idx = ($deep > 0 ? '.' . $key : $key); if(is_scalar($value)) { $result .= self::serializeNVP($idx, $value, $prefix); } else { $result .= self::serializeRecursive($value, $prefix . $idx, $deep); } } } return $result; } } ?>PK\4d:cc/plugins/micropayment-dbt/lib/serializer/ISerializer.phpnu[PK\6NDDBcc/plugins/micropayment-dbt/lib/services/IMcpDebitService_v1_4.phpnu[PK\ yy(cc/plugins/micropayment-dbt/lib/init.phpnu[PK\Acc/plugins/micropayment-dbt/lib/dispatcher/TServiceDispatcher.phpnu[ setInterface($interface); $this -> setRequestAdapter( TDispatchRequestAdapter::createByServiceProtocol($this, $requestProtocol, $requestAdapterOptions) ); $this -> setResponseAdapter( TDispatchResponseAdapter::createByServiceProtocol($this, $responseProtocol, $responseAdapterOptions) ); $this -> oRequestAdapter -> setServiceUri($serviceUri); } /** * @return ClassServiceReflection */ public function getInterfaceReflection() { return ClassServiceReflection::createReflection( new ReflectionClass($this -> getInterface())); } /** * @param string $name * @param array $params * @return mixed * @todo params mit reflection aufbereiten * @throws TNotificationDispatcherException */ public function send($name, $params=null) { $result = null; $args = array(); $iReflection = $this -> getInterfaceReflection(); if( !$iReflection -> hasMethod($name) ) throw new TServiceDispatcherException('servicemethod_unkown', $name); $nReflection = $iReflection -> getMethod($name); do { if( $nReflection -> getNumberOfParameters() == 0 ) break; $aNpReflection = $nReflection -> getParameters(); $c = -1; foreach($aNpReflection as $npReflection) { ++$c; $paramName = $npReflection -> getName(); $args[$paramName] = $paramValue = null; if( $params AND is_array($params) AND array_key_exists($paramName, $params) ) { $args[$paramName] = $paramValue = $params[$paramName]; continue; } if( $params AND is_array($params) AND array_key_exists($c, $params) ) { $args[$paramName] = $paramValue = $params[$c]; continue; } if( $npReflection -> getHasDefault() ) { $args[$paramName] = $npReflection -> getDefault(); continue; } if( $npReflection -> getRequired() ) throw new TServiceDispatcherException('servicemethod_param_missing', $name, $paramName); } } while(0); $this -> oRequestAdapter -> setMethodName($name); $this -> oRequestAdapter -> setMethodParameters($args); $data = $this -> oRequestAdapter -> call(); return $this -> oResponseAdapter -> unserialize($data, $nReflection); } /** * @param string $name * @param mixed $params */ public function __call($name, $params) { return $this -> send($name, $params); } /** * @param string $value */ public function setInterface($value) { $this -> _interface = $value; } /** * @return string */ public function getInterface() { return $this -> _interface; } /** * @return string */ public function getServiceUri() { return $this -> oRequestAdapter -> getServiceUri(); } /** * @param string $value */ public function setServiceUri($value) { $this -> oRequestAdapter -> setServiceUri($value); } /** * @return string * @see TServiceProtocol */ public function getRequestProtocol() { return $this -> oRequestAdapter -> getServiceProtocol(); } /** * @return string * @see TServiceProtocol */ public function getResponseProtocol() { return $this -> oResponseAdapter -> getServiceProtocol(); } /** * assign response-adapter * * @param IDispatchResponseAdapter $adapder */ public function setResponseAdapter(IDispatchResponseAdapter $adapder) { $this -> oResponseAdapter = $adapder; } /** * return current response-adapter * * @return IDispatchResponseAdapter */ public function getResponseAdapter() { return $this -> oResponseAdapter; } /** * assign server adapter * * @param IDispatchRequestAdapter $adapder */ public function setRequestAdapter(IDispatchRequestAdapter $adapder) { $this -> oRequestAdapter = $adapder; } /** * return current request-adapter * * @return IDispatchRequestAdapter */ public function getRequestAdapter() { return $this -> oRequestAdapter; } } ?>PK\OWJcc/plugins/micropayment-dbt/lib/dispatcher/TServiceDispatcherException.txtnu[servicemethod_unkown = service method named "{0}" do not exists servicemethod_param_missing = service method named "{0}" requires param "{1}"PK\䳒Occ/plugins/micropayment-dbt/lib/dispatcher/adapter/TDispatchResponseAdapter.phpnu[ setManager($manager); $result -> setServiceProtocol($protocol); $result -> setOptions($options); return $result; } /** * @return mixed $value */ public function getData() { return $this -> _data; } /** * @param mixed $value */ protected function setData($value) { $this -> _data = $value; } /** * @return MethodServiceReflection */ public function getReflection() { return $this -> _reflection; } /** * @param MethodServiceReflection $value */ protected function setReflection(MethodServiceReflection $value) { $this -> _reflection = $value; } /** * @param mixed $data * @param MethodServiceReflection $interfaceNotificationReflection * @return mixed */ public function unserialize($data, MethodServiceReflection $interfaceNotificationReflection) { $this -> setData($data); $this -> setReflection($interfaceNotificationReflection); return $this -> formatDataWithReflection( $this -> unserializeData() ); } /** * @param mixed $data */ protected function formatDataWithReflection($data) { if( is_scalar($data)) return $data; $result = array(); $reflection = $this -> getReflection() -> getReturn(); $aResultReflection = $reflection -> getResults(); if(count($aResultReflection) == 0) return $data; foreach($aResultReflection as $resultReflection) { $name = $resultReflection -> getName(); $result[$name] = $value = null; $required = true; $hasValue = false; do { if( !$resultReflection instanceof ParameterServiceReflection ) break; $required = $resultReflection -> getRequired(); if( !$resultReflection -> getHasDefault() ) break; $value = $resultReflection -> getDefault(); $hasValue = true; } while(0); if( array_key_exists($name, $data) ) { $value = $data[$name]; $hasValue = true; switch($value) { case 'null': $value = null; break; case 'true': $value = true; break; case 'false': $value = false; break; } } if( !$hasValue AND $required) throw new TDispatchAdapterException('servicemethod_result_missing', $this -> getReflection() -> getName(), $name); $result[$name] = $value; } return $result; } /** * @return mixed */ abstract protected function unserializeData(); } class TDummyDispatchResponseAdapter extends TDispatchResponseAdapter { protected function unserializeData() { return $this -> getData(); } } ?>PK\bbNcc/plugins/micropayment-dbt/lib/dispatcher/adapter/IDispatchRequestAdapter.phpnu[PK\GGGcc/plugins/micropayment-dbt/lib/dispatcher/adapter/IDispatchAdapter.phpnu[PK\7JzzXcc/plugins/micropayment-dbt/lib/dispatcher/adapter/THttpParamsDispatchRequestAdapter.phpnu[ setStatusCode($statusCode); $this -> _response = $reponse; $this -> setErrorCode($errorCode); $errorMessage = $this -> translateErrorMessage($errorCode); $args = func_get_args(); array_shift($args); array_shift($args); array_shift($args); $this -> setErrorMessage( $this -> replaceMessageToken($errorMessage, $args) ); } /** * @return TSimpleHttpResponse */ public function getResponse() { return $this -> _response; } } class THttpParamsDispatchRequestAdapter extends TDispatchRequestAdapter { /** * * @return TSimpleHttpResponse * @throws SimpleHttpClientException * @throws THttpException */ public function call() { $option = $this -> getOptions(); if(!is_array($option)) $option = array(); if(!isset($option['http-params-servicemethod']) OR $option['http-params-servicemethod'] == '') $option['http-params-servicemethod'] = 'action'; $servicemethodParamName = $option['http-params-servicemethod']; $result = ''; switch( $this -> getServiceProtocol() ) { case TServiceProtocol::HTTP_PARAMS_GET: $client = new TSimpleHttpClient(TSimpleHttpClient::GET, $this -> getServiceUri()); break; case TServiceProtocol::HTTP_PARAMS: case TServiceProtocol::HTTP_PARAMS_POST: default: $client = new TSimpleHttpClient(TSimpleHttpClient::POST, $this -> getServiceUri()); break; } $client -> addHeader('User-Agent', 'MCP-SimpleHttpClient/1.0 API-ServiceDispatcher via HttpParamsDispatchRequestAdapter'); $client -> addHeader('Accept', 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,*/*;q=0.5'); $client -> addHeader('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'); $client -> addHeader('X-MCP-API-RequestServiceProtocol', $this -> getServiceProtocol()); $client -> addHeader('X-MCP-API-ResponseServiceProtocol', $this -> getManager() -> getResponseProtocol()); $methodParameters = http_build_query($this -> getMethodParameters(), null, '&'); parse_str($methodParameters, $methodParameters); $aData = array(); if( !$client -> isPost() ) $aData = $client -> getQuery(true); $aData = array_merge($aData, $methodParameters); $aData[$servicemethodParamName] = $this -> getMethodName(); if( $client -> isPost() ) { $client -> addHeader('Content-type', 'application/x-www-form-urlencoded'); $client -> setBody( http_build_query($aData, null, '&') ); } else { $client -> setQuery($aData); } $result = $client -> request(); switch( $result -> getStatusCode() ) { case 200: // OK break; case 301: // Moved permanently case 302: // Found case 303: // See other case 305: // Use proxy case 307: // Moved temporarily // ::ToDo:: // ggf. Location Header auswerten // und Request umschreiben case 304: // Not modified default: throw new THttpParamsDispatchRequestAdapterHttpException($result -> getStatusCode(), $result -> getStatusMessage(), $result); break; } return $result; } } ?>PK\uGcc/plugins/micropayment-dbt/lib/dispatcher/adapter/TDispatchAdapter.phpnu[ _manager = $manager; } /** * @return IServiceDispatcher */ public function getManager() { return $this -> _manager; } /** * @param string $value * @see TServiceProtocol */ public function setServiceProtocol($value) { $this -> _serviceProtocol = $value; } /** * @return string $value * @see TServiceProtocol */ public function getServiceProtocol() { return $this -> _serviceProtocol; } /** * @param mixed $value */ public function setOptions($value=null) { $this -> _options = $value; } /** * @return mixed $value */ public function getOptions() { return $this -> _options; } } ?>PK\j  Ncc/plugins/micropayment-dbt/lib/dispatcher/adapter/TDispatchRequestAdapter.phpnu[ setManager($manager); $result -> setServiceProtocol($protocol); $result -> setOptions($options); return $result; } /** * @return string */ public function getServiceUri() { return $this -> _serviceUri; } /** * @param string $value */ public function setServiceUri($value) { $this -> _serviceUri = $value; } /** * @return string */ public function getMethodName() { return $this -> _methodName; } /** * @param string $value */ public function setMethodName($value) { $this -> _methodName= $value; } /** * @param array $value */ public function setMethodParameters($value) { $this -> _methodParameters = $value; } /** * @return array */ public function getMethodParameters() { return $this -> _methodParameters; } } class TDummyDispatchRequestAdapter extends TDispatchRequestAdapter { public function call() { return null; } } ?>PK\يPcc/plugins/micropayment-dbt/lib/dispatcher/adapter/TDispatchAdapterException.txtnu[protocol_not_supported = service protocol "{1}" not supported by "{0}" yet protocol_unknown = adapter "{0}" don't know service protocol "{1}" adapter_datatype_not_supported = Response data type "{0}" not supported adapter_protocol_not_supported = {0} do not support service protocol "{1}" use another Adapter servicemethod_result_missing = service method named "{0}" requires result "{1}"PK\)JJRcc/plugins/micropayment-dbt/lib/dispatcher/adapter/TNvpDispatchResponseAdapter.phpnu[ getData(); $result = null; $dataType = gettype($data); switch($dataType) { case 'object': $dataType = get_class($data); case 'TSimpleHttpResponse': $format = $this -> getServiceProtocol(); if( $data -> isHeader('X-MCP-API-ResonseServiceProtocol') ) $format = $data -> getHeader('X-MCP-API-ResonseServiceProtocol'); if( !in_array($format, array($this -> getServiceProtocol(), TServiceProtocol::NONE, TServiceProtocol::UNKNOWN )) ) throw new TDispatchAdapterException('adapter_protocol_not_supported', __CLASS__, $format); $result = TNvpSerializer::unserialize( $data -> getBody() ); break; case 'boolean': case 'integer': case 'boolean': case 'array': case 'null': case 'NULL': $result = TNvpSerializer::unserialize( TNvpSerializer::serialize($data) ); break; case 'string': $result = TNvpSerializer::unserialize($data); break; case 'resource': case 'unknown type': default: throw new TDispatchAdapterException('adapter_datatype_not_supported', $dataType); break; } do { if( !isset($result['error']) ) break; if($result['error'] == 0) break; $code = $result['error']; $msg = isset($result['errorMessage']) ? stripSlashes($result['errorMessage']) : ''; throw new Exception($msg, $code); } while(0); do { if( !isset($result['result']) ) break; if( count($result) > 2) break; $result = $result['result']; } while(0); return $result; } } ?>PK\pkOcc/plugins/micropayment-dbt/lib/dispatcher/adapter/IDispatchResponseAdapter.phpnu[PK\ڢ-)77Dcc/plugins/micropayment-dbt/lib/dispatcher/TNvpServiceDispatcher.phpnu[PK\:Acc/plugins/micropayment-dbt/lib/dispatcher/IServiceDispatcher.phpnu[PK\^i4=''cc/plugins/comenpay.phpnu[addText('paccount_id', array('size' => 5)) ->setLabel('Mid identification number provided by Comen Pay support') ->addRule('required'); $form->addPassword('apiKey', array('class' => 'el-wide')) ->setLabel('API Key') ->addRule('required'); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $client = new SoapClient(self::WSDL); $user = $invoice->getUser(); if ($cc) { $data = array( 'customer_firstname' => $user->name_f ? $user->name_f : $cc->cc_name_f, 'customer_lastname' => $user->name_l ? $user->name_l : $cc->cc_name_l, 'customer_email' => $user->email, 'holder_firstname' => $cc->cc_name_f, 'holder_lastname' => $cc->cc_name_l, 'pan' => $cc->cc_number, 'digit' => $cc->getCvv(), 'exp' => $cc->getExpire('%02d-20%02d') ); $data = base64_encode(serialize($data)); $param = array( $this->getConfig('apiKey'), $data ); $request = new SoapRequestWrapperComenpay($client, 'AddCustomerData', $param); $t = new Am_Paysystem_Transaction_CreditCard_Comenpay_AddCustomerData($this, $invoice, $request, $user); $r = new Am_Paysystem_Result; $t->run($r); if ($r->isFailure()) { $result->setFailed($r->getErrorMessages()); return; } } if (!$user->data()->get(self::COMENPAY_CARD_TOKEN)) { $result->setFailed('Can not process payment: customer has not associated CC'); return; } if ($doFirst && !(float) $invoice->first_total) { //free trial $t = new Am_Paysystem_Transaction_Free($this); $t->setInvoice($invoice); $t->process(); $result->setSuccess(); } else { $payment = null; @list($payment) = $invoice->getPaymentRecords(); $data = array( 'paccount_id' => $this->getConfig('paccount_id'), 'type' => $payment ? 'REBILL' : 'BILL', 'transaction_ip' => $user->last_ip, 'amount_cnts' => 100 * ($doFirst ? $invoice->first_total : $invoice->second_total), 'client_reference' => $invoice->public_id, 'client_customer_id' => $user->pk(), 'affiliate_id' => 0, 'site_url' => $this->getDi()->config->get('site_url'), 'member_login' => $user->login, 'support_url' => $this->getDi()->config->get('site_url'), 'support_tel' => 'N/A', 'support_email' => $this->getDi()->config->get('admin_email'), 'customer_lang' => 'en', 'customer_useragent' => $user->last_user_agent, 'billing_invoicing_id' => 0, 'billing_description' => $invoice->getLineDescription(), 'billing_preauth_duration' => 0, 'billing_rebill_period' => 0, 'billing_rebill_duration' => 0, 'billing_rebill_price_cnts' => 100 * $invoice->second_total, ); if ($payment) { $data['billing_initial_transaction_id'] = $payment->receipt_id; } $param = array( $this->getConfig('apiKey'), $user->data()->get(self::COMENPAY_CARD_TOKEN), $user->data()->get(self::COMENPAY_CARD_KEY), $data ); $request = new SoapRequestWrapperComenpay($client, 'Transaction', $param); $t = new Am_Paysystem_Transaction_CreditCard_Comenpay_Transaction($this, $invoice, $request, $doFirst); $t->run($result); } } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $client = new SoapClient(self::WSDL); $invoice = $payment->getInvoice(); $user = $invoice->getUser(); $data = array( 'paccount_id' => $this->getConfig('paccount_id'), 'type' => 'REFUND', 'transaction_ip' => $user->last_ip, 'amount_cnts' => 100 * $amount, 'client_reference' => $invoice->public_id, 'client_customer_id' => $user->pk(), 'affiliate_id' => 0, 'site_url' => $this->getDi()->config->get('site_url'), 'member_login' => $user->login, 'support_url' => $this->getDi()->config->get('site_url'), 'support_tel' => 'N/A', 'support_email' => $this->getDi()->config->get('admin_email'), 'customer_lang' => 'en', 'customer_useragent' => $user->last_user_agent, 'billing_invoicing_id' => 0, 'billing_description' => $invoice->getLineDescription(), 'billing_preauth_duration' => 0, 'billing_rebill_period' => 0, 'billing_rebill_duration' => 0, 'billing_rebill_price_cnts' => 100 * $invoice->second_total, 'billing_initial_transaction_id' => $payment->receipt_id ); $param = array( $this->getConfig('apiKey'), $user->data()->get(self::COMENPAY_CARD_TOKEN), $user->data()->get(self::COMENPAY_CARD_KEY), $data ); $request = new SoapRequestWrapperComenpay($client, 'Transaction', $param); $t = new Am_Paysystem_Transaction_CreditCard_Comenpay_Transaction_Refund($this, $invoice, $request, $payment->receipt_id, $amount); $t->run($result); } } class SoapRequestWrapperComenpay { protected $client; protected $method; protected $data; public function __construct(SoapClient $client, $method, $data) { $this->client = $client; $this->method = $method; $this->data = $data; } public function send() { $res = call_user_func_array(array($this->client, $this->method), $this->data); return new SoapResponseWrapperComenpay($res); } public function toArray() { $v = end($this->data); return is_array($v) ? $this->data : unserialize(base64_decode($v)); } } class SoapResponseWrapperComenpay { protected $response; public function __construct($response) { $this->response = $response; } public function toArray() { return $this->objectToArray($this->response); } public function getStatus() { return 200; } protected function objectToArray($d) { if (is_object($d)) { $d = get_object_vars($d); } if (is_array($d)) { return array_map(array($this, 'objectToArray'), $d); } else { return $d; } } } class Am_Paysystem_Transaction_CreditCard_Comenpay_AddCustomerData extends Am_Paysystem_Transaction_CreditCard { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $request, $user) { $this->setInvoice($invoice); $this->plugin = $plugin; $this->request = $request; $this->user = $user; } public function parseResponse() { $this->vars = $this->response->toArray(); } public function getUniqId() { return null; } public function validate() { if ($this->vars['status'] == 'OK') { $this->result->setSuccess(); } else { $this->result->setFailed(___('Payment Failed')); } } public function processValidated() { $this->user->data()->set(Am_Paysystem_Comenpay::COMENPAY_CARD_TOKEN, $this->vars['token']); $this->user->data()->set(Am_Paysystem_Comenpay::COMENPAY_CARD_KEY, $this->vars['otpKey']); $this->user->save(); } } class Am_Paysystem_Transaction_CreditCard_Comenpay_Transaction extends Am_Paysystem_Transaction_CreditCard { public function parseResponse() { $this->vars = $this->response->toArray(); } public function getUniqId() { return $this->vars['transaction_id']; } public function validate() { if ($this->vars['status'] == 'OK') { $this->result->setSuccess(); } else { $this->result->setFailed($this->vars['status_reason']); } } public function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_CreditCard_Comenpay_Transaction_Refund extends Am_Paysystem_Transaction_CreditCard_Comenpay_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $request, $receipt, $amount) { $this->setInvoice($invoice); $this->plugin = $plugin; $this->request = $request; $this->receipt = $receipt; $this->amount = $amount; } public function getAmount() { return $this->amount; } public function processValidated() { $this->invoice->addRefund($this, $this->receipt); } } PK\㥹:-:-cc/plugins/authorize-echeck.phpnu[ 'Personal Checking', self::TYPE_BUSINESSCHECKING => 'Business Checking', self::TYPE_SAVINGS => 'Personal Savings', ); public function getRecurringType() { return self::REPORTS_CRONREBILL; } public function getFormOptions() { $ret = parent::getFormOptions(); $ret[] = self::ECHECK_TYPE_OPTIONS; $ret[] = self::ECHECK_BANK_NAME; $ret[] = self::ECHECK_ACCOUNT_NAME; return $ret; } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->setTitle(___("Authorize.NET eCheck")); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("login")->setLabel("API Login ID\n" . 'can be obtained from the same page as Transaction Key (see below)'); $form->addText("tkey")->setLabel("Transaction Key" . "

      The transaction key is generated by the system and can be obtained from Merchant Interface. To obtain the transaction key from the Merchant Interface

      1. Log into the Merchant Interface
      2. Select Settings from the Main Menu
      3. Click on Obtain Transaction Key in the Security section
      4. Type in the answer to the secret question configured on setup
      5. Click Submit
      "); $form->addAdvCheckbox("test_mode") ->setLabel("Test Mode Enabled"); } public function getEcheckTypeOptions() { return $this->acctTypeOptions; } public function _doBill(Invoice $invoice, $doFirst, EcheckRecord $echeck, Am_Paysystem_Result $result) { if ($doFirst && !(float)$invoice->first_total) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { $user = $invoice->getUser(); $ps = new stdclass; $ps->x_Invoice_Num = $invoice->public_id; $ps->x_Cust_ID = $invoice->user_id; $ps->x_Description = $invoice->getLineDescription(); $ps->x_First_Name = $echeck->cc_name_f; $ps->x_Last_Name = $echeck->cc_name_l; $ps->x_Address = $echeck->cc_street; $ps->x_City = $echeck->cc_city; $ps->x_State = $echeck->cc_state; $ps->x_Country = $echeck->cc_country; $ps->x_Zip = $echeck->cc_zip; $ps->x_Tax = $doFirst ? $invoice->first_tax : $invoice->second_tax; $ps->x_Email = $user->email; $ps->x_Phone = $echeck->cc_phone; $ps->x_Amount = $doFirst ? $invoice->first_total : $invoice->second_total; $ps->x_Currency_Code = $invoice->currency; $ps->x_Type = 'AUTH_CAPTURE'; $ps->x_Customer_IP = $user->remote_addr ? $user->remote_addr : $_SERVER['REMOTE_ADDR']; $ps->x_Relay_Response = 'FALSE'; $ps->x_Delim_Data = 'TRUE'; $ps->x_bank_acct_num = $echeck->echeck_ban; $ps->x_bank_aba_code = $echeck->echeck_aba; $ps->x_bank_acct_type = $echeck->echeck_type; $ps->x_bank_name = $echeck->check_bank_name; $ps->x_bank_acct_name = $echeck->echeck_account_name; $ps->x_echeck_type = 'WEB'; $ps->x_recurring_billing = ($invoice->rebill_times) ? 'TRUE' : 'FALSE'; $request = $this->_sendRequest($this->createHttpRequest()); $request->addPostParameter((array) $ps); $transaction = new Am_Paysystem_Transaction_AuthorizeEcheck_Payment($this, $invoice, $request, $doFirst); $transaction->run($result); } } /** @return HTTP_Request2_Response */ public function _sendRequest(Am_HttpRequest $request) { $request->addPostParameter('x_login', $this->getConfig('login')); $request->addPostParameter('x_tran_key', $this->getConfig('tkey')); $request->addPostParameter('x_Delim_Data', "True"); $request->addPostParameter('x_Delim_Char', "|"); $request->addPostParameter('x_Version', "3.1"); $request->addPostParameter('x_method', "ECHECK"); if ($this->getConfig('test_mode')) { $request->addPostParameter("x_test_request", "TRUE"); $request->setUrl(self::SANDBOX_URL); } else { $request->setUrl(self::LIVE_URL); } $request->setMethod(Am_HttpRequest::METHOD_POST); return $request; } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $request = $this->_sendRequest($this->createHttpRequest()); $request->addPostParameter('x_Type', 'CREDIT'); $request->addPostParameter('x_Trans_Id', $this->getConfig('test_mode') ? 0 : $payment->transaction_id); $request->addPostParameter('x_Amount', $amount); $echeck = $this->loadEcheck($payment->getInvoice()); $request->addPostParameter('x_bank_acct_num', $echeck->echeck_ban); $request->addPostParameter('x_bank_aba_code', $echeck->echeck_aba); $request->addPostParameter('x_bank_acct_type', $echeck->echeck_type); $request->addPostParameter('x_bank_name', $echeck->check_bank_name); $request->addPostParameter('x_bank_acct_name', $echeck->echeck_account_name); $request->addPostParameter('x_echeck_type', $echeck->echeck_type == self::TYPE_BUSINESSCHECKING ? 'CCD' : 'PPD'); $transaction = new Am_Paysystem_Transaction_AuthorizeEcheck_Refund($this, $payment->getInvoice(), $request, $payment->transaction_id, $amount); $transaction->run($result); } } class Am_Paysystem_Transaction_AuthorizeEcheck extends Am_Paysystem_Transaction_Echeck //Am_Paysystem_Transaction_CreditCard { const APPROVED = 1; const DECLINED = 2; const ERROR = 3; const HELD = 4; protected $response; protected $res; // Parsed response; public function parseResponse() { $response = $this->response->getBody(); $this->response->approved = false; $this->response->error = true; $vars = explode('|', $response); if ($vars) { if (count($vars) < 10) { $this->response->error_message = "Unrecognized response from AuthorizeNet: $response"; return; } // Set all fields $this->response->response_code = $vars[0]; $this->response->response_subcode = $vars[1]; $this->response->response_reason_code = $vars[2]; $this->response->response_reason_text = $vars[3]; $this->response->authorization_code = $vars[4]; $this->response->avs_response = $vars[5]; $this->response->transaction_id = $vars[6]; $this->response->invoice_number = $vars[7]; $this->response->description = $vars[8]; $this->response->amount = $vars[9]; $this->response->method = $vars[10]; $this->response->transaction_type = $vars[11]; $this->response->customer_id = $vars[12]; $this->response->first_name = $vars[13]; $this->response->last_name = $vars[14]; $this->response->company = $vars[15]; $this->response->address = $vars[16]; $this->response->city = $vars[17]; $this->response->state = $vars[18]; $this->response->zip_code = $vars[19]; $this->response->country = $vars[20]; $this->response->phone = $vars[21]; $this->response->fax = $vars[22]; $this->response->email_address = $vars[23]; $this->response->ship_to_first_name = $vars[24]; $this->response->ship_to_last_name = $vars[25]; $this->response->ship_to_company = $vars[26]; $this->response->ship_to_address = $vars[27]; $this->response->ship_to_city = $vars[28]; $this->response->ship_to_state = $vars[29]; $this->response->ship_to_zip_code = $vars[30]; $this->response->ship_to_country = $vars[31]; $this->response->tax = $vars[32]; $this->response->duty = $vars[33]; $this->response->freight = $vars[34]; $this->response->tax_exempt = $vars[35]; $this->response->purchase_order_number = $vars[36]; $this->response->md5_hash = $vars[37]; $this->response->card_code_response = $vars[38]; $this->response->cavv_response = $vars[39]; $this->response->account_number = $vars[40]; $this->response->card_type = $vars[51]; $this->response->split_tender_id = $vars[52]; $this->response->requested_amount = $vars[53]; $this->response->balance_on_card = $vars[54]; $this->response->approved = ($this->response->response_code == self::APPROVED); $this->response->declined = ($this->response->response_code == self::DECLINED); $this->response->error = ($this->response->response_code == self::ERROR); $this->response->held = ($this->response->response_code == self::HELD); } else { $this->response->error_message = "Error connecting to AuthorizeNet"; } } public function getUniqId() { return ($this->plugin->getConfig('test_mode')) ? $this->response->transaction_id . "-test_mode-" . time() : $this->response->transaction_id; } public function getAmount() { return $this->response->amount; } public function validate() { if ($this->response->approved) { $this->result->setSuccess($this); } else { $this->result->setFailed($this->getErrorMessage()); } } public function getErrorMessage() { return!empty($this->response->error_message) ? $this->response->error_message : $this->response->response_reason_text; } } class Am_Paysystem_Transaction_AuthorizeEcheck_Payment extends Am_Paysystem_Transaction_AuthorizeEcheck { function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_AuthorizeEcheck_Refund extends Am_Paysystem_Transaction_AuthorizeEcheck { protected $orig_id; protected $amount; function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $request, $orig_id, $amount) { parent::__construct($plugin, $invoice, $request, true); $this->orig_id = $orig_id; $this->amount = $amount; } function processValidated() { $this->invoice->addRefund($this, $this->orig_id); } function getAmount() { return $this->amount; } } PK\5v11&cc/plugins/paymentsystemsworldwide.phpnu[addText('user') ->setLabel("Your username\n" . 'Username assigned to merchant account') ->addRule('required'); $form->addPassword('pass') ->setLabel("Your password\n" . 'Password for the specified username') ->addRule('required'); $form->addAdvCheckbox('testMode') ->setLabel("Test Mode\n" . 'Test account data will be used'); } public function isConfigured() { return $this->getConfig('user') && $this->getConfig('pass'); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $user = $invoice->getUser(); if ($doFirst) // not recurring sale { if (!(float)$invoice->first_total) // first - free { $trAddFree = new Am_Paysystem_Paymentsystemsworldwide_Transaction_Authorization($this, $invoice, $cc); $trAddFree->run($result); $transactionId = $trAddFree->getUniqId(); $customerVaultId = $trAddFree->getCustomerVaultId(); if (!$transactionId || !$customerVaultId) { return $result->setFailed(array("PSWW Plugin: Bad auth response.")); } $trVoid = new Am_Paysystem_Paymentsystemsworldwide_Transaction_Void($this, $invoice, $transactionId, $customerVaultId); $trVoid->run($result); $trFree = new Am_Paysystem_Transaction_Free($this); $trFree->setInvoice($invoice); $trFree->process(); $result->setSuccess($trFree); } else { $trAddPay = new Am_Paysystem_Paymentsystemsworldwide_Transaction_AddCustomer ($this, $invoice, $cc); $trAddPay->run($result); $customerVaultId = $trAddPay->getCustomerVaultId(); if (!$customerVaultId) { return $result->setFailed(array("PSWW Plugin: Bad add response.")); } $trSale = new Am_Paysystem_Paymentsystemsworldwide_Transaction_Sale($this, $invoice, $doFirst, $customerVaultId); $trSale->run($result); } $user->data()->set(self::CUSTOMER_VAULT_ID, $customerVaultId)->update(); } else { $customerVaultId = $user->data()->get(self::CUSTOMER_VAULT_ID); if (!$customerVaultId) { return $result->setFailed(array("No saved reference transaction for customer")); } $trSale = new Am_Paysystem_Paymentsystemsworldwide_Transaction_Sale($this, $invoice, $doFirst, $customerVaultId); $trSale->run($result); } } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $user = $this->getDi()->userTable->load($cc->user_id); $customerVaultId = $user->data()->get(self::CUSTOMER_VAULT_ID); if ($this->invoice) { // to link log records with current invoice $invoice = $this->invoice; } else { // updating credit card info? $invoice = $this->getDi()->invoiceRecord; $invoice->invoice_id = 0; $invoice->user_id = $user->pk(); } // compare stored cc for that user may be we don't need to refresh? if ($customerVaultId && ($cc->cc_number != '0000000000000000')) { $storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk()); if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)) || ($storedCc->cc_expire != $cc->cc_expire))) { $user->data()->set(self::CUSTOMER_VAULT_ID, null)->update(); $customerVaultId = null; } } if (!$customerVaultId) { $trAdd = new Am_Paysystem_Paymentsystemsworldwide_Transaction_AddCustomer ($this, $invoice, $cc); $trAdd->run($result); $customerVaultId = $trAdd->getCustomerVaultId(); if (!$customerVaultId) { return $result->setFailed(array("PSWW Plugin: Bad add response.")); } $user->data()->set(self::CUSTOMER_VAULT_ID, $customerVaultId)->update(); } $cc->cc = $cc->maskCc(@$cc->cc_number); $cc->cc_number = '0000000000000000'; if ($cc->pk()) $cc->update(); else $cc->replace(); $result->setSuccess(); } public function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $customerVaultId = $this->getDi()->userTable->load($payment->user_id)->data()->get(self::CUSTOMER_VAULT_ID); $tr = new Am_Paysystem_Paymentsystemsworldwide_Transaction_Refund($this, $payment->getInvoice(), $payment->receipt_id, $amount, $customerVaultId); $tr->run($result); } public function getReadme() { return <<addRequestParams(); } private function getUser() { return (!$this->plugin->getConfig('testMode')) ? $this->plugin->getConfig('user') : 'demo'; } private function getPass() { return (!$this->plugin->getConfig('testMode')) ? $this->plugin->getConfig('pass') : 'password'; } public function getAmount() { return $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total; } protected function addRequestParams() { $this->request->addPostParameter('username', $this->getUser()); $this->request->addPostParameter('password', $this->getPass()); } public function getUniqId() { return $this->parsedResponse->transactionid; } public function parseResponse() { parse_str($this->response->getBody(), $this->parsedResponse); $this->parsedResponse = (object)$this->parsedResponse; } public function validate() { switch ($this->parsedResponse->response) { case 1: break; case 2: $err = "Transaction Declined."; break; case 3: $err = "Error in transaction data or system error."; break; default: $err = "Unknown error num: " . $this->parsedResponse->response . "."; break; } if (!empty($err)) { return $this->result->setFailed(array($err, $this->parsedResponse->responsetext)); } $this->result->setSuccess($this); } protected function setCcRecord(CcRecord $cc) { $this->request->addPostParameter('ccnumber', $cc->cc_number); $this->request->addPostParameter('ccexp', $cc->cc_expire); $this->request->addPostParameter('cvv', $cc->getCvv()); $this->request->addPostParameter('firstname', $cc->cc_name_f); $this->request->addPostParameter('lastname', $cc->cc_name_l); $this->request->addPostParameter('address1', $cc->cc_street); $this->request->addPostParameter('city', $cc->cc_city); $this->request->addPostParameter('state', $cc->cc_state); $this->request->addPostParameter('zip', $cc->cc_zip); $this->request->addPostParameter('country', $cc->cc_country); $this->request->addPostParameter('phone', $cc->cc_phone); } public function getCustomerVaultId() { return $this->parsedResponse->customer_vault_id; } } class Am_Paysystem_Paymentsystemsworldwide_Transaction_Sale extends Am_Paysystem_Paymentsystemsworldwide_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, $customerVaultId) { parent::__construct($plugin, $invoice, $doFirst); $this->request->addPostParameter('customer_vault_id', $customerVaultId); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('amount', $this->getAmount()); $this->request->addPostParameter('type ', 'sale'); } } class Am_Paysystem_Paymentsystemsworldwide_Transaction_Refund extends Am_Paysystem_Paymentsystemsworldwide_Transaction { // public $amount2 = 0; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $transactionId, $amount, $customerVaultId) { $this->amount = $amount; parent::__construct($plugin, $invoice, true); $this->request->addPostParameter('transactionid', $transactionId); $this->request->addPostParameter('customer_vault_id', $customerVaultId); } public function getAmount() { return $this->amount; } public function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('type ', 'refund'); $this->request->addPostParameter('amount', $this->getAmount()); } public function processValidated(){} // no process payment } class Am_Paysystem_Paymentsystemsworldwide_Transaction_Authorization extends Am_Paysystem_Paymentsystemsworldwide_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc) { parent::__construct($plugin, $invoice, true); $this->setCcRecord($cc); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('type', 'auth'); $this->request->addPostParameter('amount', 1.00); $this->request->addPostParameter('customer_vault', 'add_customer'); } public function processValidated(){} // no process payment } class Am_Paysystem_Paymentsystemsworldwide_Transaction_Void extends Am_Paysystem_Paymentsystemsworldwide_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $transactionId, $customerVaultId) { parent::__construct($plugin, $invoice, true); $this->request->addPostParameter('transactionid', $transactionId); $this->request->addPostParameter('customer_vault_id', $customerVaultId); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('type ', 'void'); $this->request->addPostParameter('amount', 1.00); } public function processValidated(){} // no process payment } class Am_Paysystem_Paymentsystemsworldwide_Transaction_AddCustomer extends Am_Paysystem_Paymentsystemsworldwide_Transaction { public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc) { parent::__construct($plugin, $invoice, true); $this->setCcRecord($cc); } protected function addRequestParams() { parent::addRequestParams(); $this->request->addPostParameter('customer_vault', 'add_customer'); } public function processValidated(){} // no process payment }PK\ 4)7.7.cc/plugins/authorize-dpm.phpnu[getId(); $form->addText("login")->setLabel("API Login ID\n" . 'can be obtained from the same page as Transaction Key (see below)'); $form->addText("tkey")->setLabel("Transaction Key\n" . '

      The transaction key is generated by the system and can be obtained from Merchant Interface. To obtain the transaction key from the Merchant Interface

      1. Log into the Merchant Interface
      2. Select Settings from the Main Menu
      3. Click on Obtain Transaction Key in the Security section
      4. Type in the answer to the secret question configured on setup
      5. Click Submit
      '); $form->addText('secret') ->setLabel("Secret Word\n" . "From authorize.net MD5 Hash menu\n" . "You have to create secret word") ->addRule('required'); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled"); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { //nop } protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Mvc_Controller_AuthorizeDpm($request, $response, $invokeArgs); } function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_AuthorizeDpm($this, $request, $response, $invokeArgs); } public function createForm($actionName) { class_exists('Am_Form_CreditCard', true); return new Am_Form_AuthorizeDpm($this); } public function getFingerprint($amount, $currency, $fp_sequence, $fp_timestamp) { return hash_hmac("md5", implode("^", array( $this->getConfig('login'), $fp_sequence, $fp_timestamp, $amount, $currency )), $this->getConfig("tkey")); } public function onInitForm(Am_Form_AuthorizeDpm $form) { $i = $this->invoice; $p = array( 'x_type' => 'AUTH_CAPTURE', 'x_amount' => $i->first_total, 'x_currency_code' => $i->currency, 'x_fp_sequence' => $i->pk(), 'x_fp_timestamp' => time(), 'x_relay_response' => "TRUE", 'x_relay_url' => $this->getPluginUrl('ipn'), 'x_login' => $this->getConfig('login'), 'x_invoice_num' => $i->public_id, 'x_customer_ip' => $_SERVER['REMOTE_ADDR'], 'x_test_request' => $this->getConfig('testing') ? 'TRUE' : 'FALSE' ); $p['x_fp_hash'] = $this->getFingerprint($i->first_total, $i->currency, $p['x_fp_sequence'], $p['x_fp_timestamp']); foreach ($p as $k => $v) { $form->addHidden($k, array('value' => $v)); } } } class Am_Paysystem_Transaction_AuthorizeDpm extends Am_Paysystem_Transaction_Incoming { const APPROVED = 1; public function getUniqId() { return $this->request->getParam('x_trans_id'); } public function findInvoiceId() { return $this->request->getParam('x_invoice_num'); } public function validateSource() { return $this->request->getParam('x_MD5_Hash') == strtoupper( md5( $this->plugin->getConfig('secret') . $this->plugin->getConfig('login') . $this->request->getParam('x_trans_id') . $this->request->getParam('x_amount') ) ); } public function validateStatus() { return true; } public function validateTerms() { $this->assertAmount($this->invoice->first_total, $this->request->getParam('x_amount')); return true; } public function processValidated() { switch ($this->request->getParam('x_response_code')) { case self::APPROVED: $this->invoice->addPayment($this); $redirect_url = $this->plugin->getRootUrl() . "/thanks?id=" . $this->invoice->getSecureId("THANKS"); break; default: $redirect_url = $this->plugin->getRootUrl() . "/cancel?id=" . $this->invoice->getSecureId('CANCEL'); } echo << CUT; exit; } } class Am_Mvc_Controller_AuthorizeDpm extends Am_Mvc_Controller { /** @var Invoice */ public $invoice; /** @var Am_Paysystem_CreditCard */ public $plugin; /** @var Am_Form_CreditCard */ public $form; public function setPlugin(Am_Paysystem_CreditCard $plugin) { $this->plugin = $plugin; } public function setInvoice(Invoice $invoice) { $this->invoice = $invoice; } /** * we only show form, authorize.net process it */ public function ccAction() { // invoice must be set to this point by the plugin if (!$this->invoice) throw new Am_Exception_InternalError('Empty invoice - internal error!'); $this->form = $this->createForm(); $this->getDi()->hook->call(Bootstrap_Cc::EVENT_CC_FORM, array('form' => $this->form)); $this->view->form = $this->form; $this->view->invoice = $this->invoice; $this->view->display_receipt = true; $this->view->display('cc/info.phtml'); } public function createForm() { $form = $this->plugin->createForm($this->_request->getActionName(), $this->invoice); $form->setDataSources(array( $this->_request, new HTML_QuickForm2_DataSource_Array($form->getDefaultValues($this->invoice->getUser())) )); return $form; } } class Am_Form_AuthorizeDpm extends Am_Form { protected $plugin = null; public function __construct(Am_Paysystem_CreditCard $plugin) { $this->plugin = $plugin; return parent::__construct('cc'); } public function init() { parent::init(); $this->setAction($this->plugin->getConfig('testing') ? Am_Paysystem_AuthorizeDpm::SANDBOX_URL : Am_Paysystem_AuthorizeDpm::LIVE_URL); $name = $this->addGroup() ->setLabel(___("Cardholder Name\n" . 'cardholder first and last name, exactly as on the card')); $name->setSeparator(' '); $name->addRule('required', ___('Please enter credit card holder name')); $name_f = $name->addText('x_first_name', array('size' => 15)); $name_f->addRule('required', ___('Please enter credit card holder first name'))->addRule('regex', ___('Please enter credit card holder first name'), '/^[^=:<>{}()"]+$/D'); $name_l = $name->addText('x_last_name', array('size' => 15)); $name_l->addRule('required', ___('Please enter credit card holder last name'))->addRule('regex', ___('Please enter credit card holder last name'), '/^[^=:<>{}()"]+$/D'); $cc = $this->addText('x_card_num', array('autocomplete' => 'off', 'size' => 22, 'maxlength' => 22)) ->setLabel(___("Credit Card Number\n" . 'for example: 1111-2222-3333-4444')); $cc->addRule('required', ___('Please enter Credit Card Number')) ->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/'); $expire = $this->addElement(new Am_Form_Element_CreditCardExpire('cc_expire')) ->setLabel(___("Card Expire\n" . 'Select card expiration date - month and year')) ->addRule('required'); $this->addHidden('x_exp_date'); $this->addScript()->setScript(<<addPassword('x_card_code', array('autocomplete' => 'off', 'size' => 4, 'maxlength' => 4)) ->setLabel(___("Credit Card Code\n" . 'The "Card Code" is a three- or four-digit security code ' . 'that is printed on the back of credit cards in the card\'s ' . 'signature panel (or on the front for American Express cards)')); $code->addRule('required', ___('Please enter Credit Card Code')) ->addRule('regex', ___('Please enter Credit Card Code'), '/^\s*\d{3,4}\s*$/'); $fieldSet = $this->addFieldset(___('Address Info')) ->setLabel(___("Address Info\n" . '(must match your credit card statement delivery address)')); $street = $fieldSet->addText('x_address')->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); $city = $fieldSet->addText('x_city')->setLabel(___('City')) ->addRule('required', ___('Please enter City')); $zip = $fieldSet->addText('x_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); $country = $fieldSet->addSelect('x_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); $stateSelect = $group->addSelect('x_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['x_country'], true)); $stateText = $group->addText('x_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); $buttons = $this->addGroup(); $buttons->addSubmit('_cc_', array('value' => ___('Subscribe And Pay'))); $this->plugin->onInitForm($this); } public function getDefaultValues(User $user) { return array( 'x_first_name' => $user->name_f, 'x_last_name' => $user->name_l, 'x_address' => $user->street, 'x_city' => $user->city, 'x_state' => $user->state, 'x_country' => $user->country, 'x_zip' => $user->zip ); } }PK\R?R?cc/plugins/altcharge.phpnu[addText('api_key')->setLabel('API Key'); $form->addText('mid')->setLabel("Merchant MID\n" . 'Leave empty if you do not have mylpitle MIDs'); } function createForm($actionName) { return new Am_Form_CreditCard_AltchargeCheck($this); } function storesCcInfo() { return false; } public function getCycle(Invoice $invoice) { $p = new Am_Period(); $p->fromString($invoice->second_period); switch ($p->getUnit()) { case Am_Period::DAY : return $p->getCount(); case Am_Period::MONTH : return $p->getCount() * 30; case Am_Period::YEAR : return $p->getCount() * 356; default: throw new Am_Exception_InputError('Incorrect product second period: ' . $p->getUnit()); } } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { list($account_number, $routing_number) = explode('-', $cc->cc_number); $r = new Am_HttpRequest(Am_Paysystem_Altcharge::URL, Am_HttpRequest::METHOD_POST); $r->addPostParameter('userkey', $this->getConfig('api_key')); $r->addPostParameter('type', $invoice->rebill_times ? self::RECURRING : self::SINGLE); $r->addPostParameter('version', '2.6'); $r->addPostParameter('email', $invoice->getEmail()); $r->addPostParameter('firstName', $cc->cc_name_f); $r->addPostParameter('lastName', $cc->cc_name_l); $r->addPostParameter('address1', $cc->cc_street); $r->addPostParameter('city', $cc->cc_city); $r->addPostParameter('state', $cc->cc_state); $r->addPostParameter('zip', $cc->cc_zip); $r->addPostParameter('country', $cc->cc_country); $r->addPostParameter('phone', $cc->cc_phone); $r->addPostParameter('ipaddress', $this->getDi()->request->getClientIp()); $r->addPostParameter('accountNumber', $account_number); $r->addPostParameter('routingNumber', $routing_number); $r->addPostParameter('merchantMID', $this->getConfig('mid', 1)); $r->addPostParameter('currency', $invoice->currency ? $invoice->currency : 'USD'); $r->addPostParameter('misc1', $invoice->public_id); $r->addPostParameter('amount', $invoice->first_total); if ($invoice->rebill_times) { $r->addPostParameter('cycle', $this->getCycle($invoice)); $r->addPostParameter('desc', $invoice->getLineDescription()); } $r->addPostParameter('signature', $this->getDi()->request->get('signature')); $transaction = new Am_Paysystem_Transaction_Altcharge_Sale($this, $invoice, $r, $doFirst); $transaction->run($result); } public function isConfigured() { return strlen($this->getConfig('api_key')); } public function getSupportedCurrencies() { return array( 'AUD', 'CAD', 'CHF', 'CLP', 'CYP', 'DKK', 'DOP', 'EGP', 'EUR', 'HKD', 'HNL', 'HRK', 'ISK', 'JMD', 'JPY', 'MXN', 'SEK', 'SGD', 'THB', 'USD' ); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times && ($invoice->rebill_times != '99999')) return 'Incorrect Rebill Times setting!'; if (($invoice->second_total > 0) && ($invoice->second_total != $invoice->first_total)) return 'Firtst & Second price must be the same in invoice!'; if (($invoice->second_period > 0) && ($invoice->second_period != $invoice->first_period)) return 'Firtst & Second period must be the same in invoice!'; } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $r = new Am_HttpRequest(self::URL, Am_HttpRequest::METHOD_POST); $r->addPostParameter('userkey', $this->getConfig('api_key')); $r->addPostParameter('type', self::REFUND); $r->addPostParameter('version', '2.6'); $r->addPostParameter('transid', $payment->transaction_id); $r->addPostParameter('merchantMID', $this->getPlugin()->getConfig('mid', 1)); $tr = new Am_Paysystem_Transaction_Altcharge_Refund($this, $payment->getInvoice(), $r, $doFirst, $payment->transaction_id); $tr->run($result); } function cancelInvoice(Invoice $invoice) { $r = new Am_HttpRequest(self::URL, Am_HttpRequest::METHOD_POST); $r->addPostParameter('userkey', $this->getConfig('api_key')); $r->addPostParameter('type', self::CANCEL); $r->addPostParameter('version', '2.6'); $r->addPostParameter('transid', $invoice->data()->get(self::INITIAL_TRANSACTION_ID)); $r->addPostParameter('merchantMID', $this->getPlugin()->getConfig('mid', 1)); $tr = new Am_Paysystem_Transaction_Altcharge($this, $payment->getInvoice(), $r, $doFirst); $tr->run(new Am_Paysystem_Result()); } function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Altcharge_Incoming($this, $request, $response, $invokeArgs); } function getReadme() { return <<response; } public function parseResponse() { $this->response = trim($this->response->getBody()); } public function validate() { if (preg_match('/^\d+$/', $this->response)) $this->result->setSuccess($this); else $this->result->setFailed($this->response); } public function processValidated() { // } } class Am_Paysystem_Transaction_Altcharge_Refund extends Am_Paysystem_Transaction_Altcharge { protected $origID; function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $request, $doFirst, $origID) { parent::__construct($plugin, $invoice, $request, $doFirst); $this->origID = $origID; } public function processValidated() { $this->invoice->addRefund($this, $this->origID); } } class Am_Paysystem_Transaction_Altcharge_Sale extends Am_Paysystem_Transaction_Altcharge { function processValidated() { $this->invoice->addPayment($this); $this->invoice->data()->set(Am_Paysystem_Altcharge::INITIAL_TRANSACTION_ID, $this->getUniqId())->update(); } } class Am_Paysystem_Transaction_Altcharge_Incoming extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->getFiltered('misc1'); } public function getUniqId() { return $this->request->get('tid'); } public function validateSource() { $this->_checkIp('208.72.244.208-208.72.244.223'); return true; } public function validateStatus() { return ($this->request->get('status') == 'APPROVED'); } public function validateTerms() { return true; } } class Am_Form_CreditCard_AltchargeCheck extends Am_Form_CreditCard { public function init() { $name = $this->addGroup() ->setLabel(___("Your Name\n" . 'your first and last name')); $name->addRule('required', ___('Please enter your name')); $name_f = $name->addText('cc_name_f', array('size' => 15)); $name_f->addRule('required', ___('Please enter first name'))->addRule('regex', ___('Please enter first name'), '|^[a-zA-Z_\' -]+$|'); $name_l = $name->addText('cc_name_l', array('size' => 15)); $name_l->addRule('required', ___('Please enter your last name'))->addRule('regex', ___('Please enter your last name'), '|^[a-zA-Z_\' -]+$|'); $options = $this->plugin->getFormOptions(); if ($this->formType == self::ADMIN_UPDATE) { $group = $this->addGroup()->setLabel(___('Credit Card Number'), ___('for example: 1111-2222-3333-4444')); $group->addStatic('cc'); $cc = $group->addText('cc_number', array('autocomplete' => 'off', 'size' => 22, 'maxlength' => 22, 'style' => 'display:none')); $cc->addRule('regex', ___('Invalid Credit Card Number'), '/^[0-9 -]+$/') ->addRule('callback2', 'Invalid CC#', array($this->plugin, 'validateCreditCardNumber')); $group->addScript("")->setScript(<<addText('account_number', array('autocomplete' => 'off', 'size' => 22, 'maxlength' => 22)) ->setLabel(___('Your Bank Account Number')) ->addRule('required', ___('Please enter Account Number')) ->addRule('regex', ___('Invalid Account Number'), '/^[0-9]+$/'); $this->addText('routing_number', array('autocomplete' => 'off', 'size' => 9, 'maxlength' => 9)) ->setLabel(___('Your 9 digit ABA Routing Number')) ->addRule('required', ___('Please enter Routing Number')) ->addRule('regex', ___('Invalid Routing Number'), '/^[0-9]+$/'); } $fieldSet = $this->addFieldset(___('Address Info'))->setLabel(___('Address Info')); $street = $fieldSet->addText('cc_street')->setLabel(___('Street Address')) ->addRule('required', ___('Please enter Street Address')); if (in_array(Am_Paysystem_CreditCard::CC_HOUSENUMBER, $options)) { $house = $fieldSet->addText('cc_housenumber', array('size' => 15))->setLabel(___('Housenumber')) ->addRule('required', ___('Please enter housenumber')); } $city = $fieldSet->addText('cc_city')->setLabel(___('City')) ->addRule('required', ___('Please enter City')); if (in_array(Am_Paysystem_CreditCard::CC_PROVINCE_OUTSIDE_OF_US, $options)) { $province = $fieldSet->addText('cc_province', array('size' => 15)) ->setLabel(___("Billing International Province\n" . 'for international provinces outside of US & Canada include the province name here')) ->addRule('required', ___('Please choose state')); } $zip = $fieldSet->addText('cc_zip')->setLabel(___('ZIP')) ->addRule('required', ___('Please enter ZIP code')); $country = $fieldSet->addSelect('cc_country')->setLabel(___('Country')) ->setId('f_cc_country') ->loadOptions(Am_Di::getInstance()->countryTable->getOptions(true)); $country->addRule('required', ___('Please enter Country')); $group = $fieldSet->addGroup()->setLabel(___('State')); $group->addRule('required', ___('Please enter State')); /** @todo load correct states */ $stateSelect = $group->addSelect('cc_state') ->setId('f_cc_state') ->loadOptions($stateOptions = Am_Di::getInstance()->stateTable->getOptions(@$_REQUEST['cc_country'], true)); $stateText = $group->addText('cc_state')->setId('t_cc_state'); $disableObj = $stateOptions ? $stateText : $stateSelect; $disableObj->setAttribute('disabled', 'disabled')->setAttribute('style', 'display: none'); if (in_array(Am_Paysystem_CreditCard::CC_PHONE, $options)) { $phone = $fieldSet->addText('cc_phone', array('size' => 14))->setLabel(___('Phone')) ->addRule('required', ___('Please enter phone number')) ->addRule('regex', ___('Please enter phone number'), '|^[\d() +-]+$|'); } $sig = $this->addFieldset(___('Signature'))->setLabel(___('Signature')); $sig->addElement('html', 'signature')->setHtml(<<
      Please press and hold left mouse button to sign
      EOSIG ); // if free trial set _TPL_CC_INFO_SUBMIT_BUT2 $buttons = $this->addGroup(); $buttons->addSubmit('_cc_', array('value' => ' ' . $this->payButtons[$this->formType] . ' ')); if ($this->formType == self::USER_UPDATE) { $buttons->addInputButton('_cc_', array('value' => ' ' . ___("Back") . ' ', 'onclick' => 'goBackToMember()')); $this->addScript("")->setScript("function goBackToMember(){ window.location = amUrl('/member'); }"); } $this->addProlog(<< EOL ); $this->addEpilog(<< EOL2 ); $this->plugin->onFormInit($this); } /** * Return array of default values based on $user record * @param User $user */ public function getDefaultValues(User $user) { return array( 'cc_name_f' => $user->name_f, 'cc_name_l' => $user->name_l, 'cc_street' => $user->street, 'cc_city' => $user->city, 'cc_state' => $user->state, 'cc_country' => $user->country, 'cc_zip' => $user->zip, 'cc_phone' => $user->phone, ); } public function validate() { return parent::validate() && $this->plugin->onFormValidate($this); } public function getValue() { $ret = parent::getValue(); array_walk_recursive($ret, function(&$v, $k) {$v=trim($v);}); return $ret; } public function toCcRecord(CcRecord $cc) { $values = $this->getValue(); $values['cc_expire'] = '1299'; unset($values['_cc_bin_name']); unset($values['_cc_bin_phone']); unset($values['a']); unset($values['id']); unset($values['cc_code']); unset($values['action']); $values['cc_number'] = $values['account_number'] . '-' . $values['routing_number']; unset($values['account_number']); unset($values['routing_number']); $cc->setForInsert($values); } }PK\&**cc/plugins/cybersource.phpnu[getConfig('merchant_id')) && strlen($this->getConfig('transaction_key')); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("merchant_id") ->setLabel('CyberSource Merchant ID') ->addRule('required'); $form->addText("transaction_key", array('class' => 'el-wide')) ->setLabel('CyberSource SOAP API Security Transaction Key') ->addRule('required'); $form->addAdvCheckbox("test_mode") ->setLabel("Test Mode Enabled"); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $soapData = new stdClass(); $soapData->merchantID = $this->getConfig('merchant_id'); $soapData->merchantReferenceCode = $invoice->public_id . '/' . $invoice->getLineDescription(); $soapData->clientLibrary = 'aMember'; $soapData->clientLibraryVersion = '4.x'; $soapData->clientEnvironment = php_uname(); $soapData->customerID = $user->pk(); $soapData->customerFirstName = $user->name_f; $soapData->customerLastName = $user->name_l; $billTo = new stdClass(); $billTo->firstName = $cc->cc_name_f ? $cc->cc_name_f : $user->name_f; $billTo->lastName = $cc->cc_name_l ? $cc->cc_name_l : $user->name_l; $billTo->street1 = $cc->cc_street ? $cc->cc_street : $user->street; $billTo->city = $cc->cc_city ? $cc->cc_city : $user->city; $billTo->state = $cc->cc_state ? $cc->cc_state : $user->state; $billTo->postalCode = $cc->cc_zip ? $cc->cc_zip : $user->zip; $billTo->country = $cc->cc_country ? $cc->cc_country : $user->country; $billTo->email = $user->email; $billTo->ipAddress = $this->getDi()->request->getClientIp(); $soapData->billTo = $billTo; $card = new stdClass(); $card->accountNumber = $cc->cc_number; $card->expirationMonth = substr($cc->cc_expire, 0, 2); $card->expirationYear = 2000 + substr($cc->cc_expire, 2, 2); $card->cvNumber = $cc->getCvv(); $soapData->card = $card; $purchaseTotals = new stdClass(); $purchaseTotals->currency = $invoice->currency; $soapData->purchaseTotals = $purchaseTotals; $soapData->item = array(); $id = 0; foreach ($invoice->getItems() as $item) { $itm = new stdClass(); $itm->unitPrice = $doFirst ? ( (float)$invoice->first_total ? $item->first_total : 1.00 ) : $item->second_total; $itm->quantity = $item->qty; $itm->id = $id++; $soapData->item[] = $itm; } if ($doFirst && !(float)$invoice->first_total) // first & free { $ccAuthService = new stdClass(); $ccAuthService->run = "true"; $soapData->ccAuthService = $ccAuthService; $trAuth = new Am_Paysystem_Transaction_CreditCard_Cybersource_Auth($this, $invoice, $doFirst, $soapData); $trAuth->run($result); $requestId = $trAuth->getRequestId(); $requestToken = $trAuth->getToken(); if (!$requestId || !$requestToken) { return $result->setFailed(array("CyberSource Plugin: Bad auth response.")); } $soapData->ccAuthService = null; $ccAuthReversalService = new stdClass(); $ccAuthReversalService->authRequestID = $requestId; $ccAuthReversalService->authRequestToken = $requestToken; $ccAuthReversalService->run = "true"; $soapData->ccAuthReversalService = $ccAuthReversalService; $trVoid = new Am_Paysystem_Transaction_CreditCard_Cybersource_Auth($this, $invoice, $doFirst, $soapData); $trVoid->run($result); $trFree = new Am_Paysystem_Transaction_Free($this); $trFree->setInvoice($invoice); $trFree->process(); $result->setSuccess($trFree); } else { $ccCreditService = new stdClass(); $ccCreditService->run = "true"; $soapData->ccCreditService = $ccCreditService; $tr = new Am_Paysystem_Transaction_CreditCard_Cybersource($this, $invoice, $doFirst, $soapData); $tr->run($result); } } public function getReadme() { return <<http://www.cybersource.com/register - generate SOAP API Security Keys by this insctruction http://www.cybersource.com/support_center/implementation/downloads/soap_api/SOAP_toolkits.pdf, paragraph 'Transaction Key' - copy all text of just created key and paste it at 'CyberSource SOAP API Security Transaction Key' plugin option (this page) - fill 'CyberSource Merchant ID' option (this page) - click "Save" CyberSource plugin requires at least these php-extensions:SOAP, OpenSSL and libxml. For configuring your web-server read instruction http://www.cybersource.com/support_center/implementation/downloads/soap_api/SOAP_toolkits.pdf, paragraph 'Preparing your PHP Installation'. ATTENTION: SOAP API Security Keys for test and live account are diffrent always. CUT; } } class Am_Paysystem_Transaction_CreditCard_Cybersource extends Am_Paysystem_Transaction_CreditCard { protected $soapData; function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst, $soapData) { $this->soapData = $soapData; parent::__construct($plugin, $invoice, new Am_Mvc_Request(), $doFirst); } public function validate() { if ($this->vars->reasonCode != 100) { $this->result->setFailed($this->vars->reasonCode . ' - ' . $this->vars->decision); return; } $this->result->setSuccess(); } public function parseResponse() { $this->vars = json_decode(json_encode($this->response));; return $this->vars; } public function getUniqId() { return $this->vars->ccCreditReply->reconciliationID; } public function getRequestId() { return $this->vars->requestID; } public function getToken() { return $this->vars->requestToken; } public function validateResponseStatus(Am_Paysystem_Result $result) { if (empty($this->response)) { $result->setFailed(array("Received empty response from payment server")); } } public function run(Am_Paysystem_Result $result) { $this->result = $result; $log = $this->getInvoiceLog(); try { $soapClient = new SoapClient_Cybersource($this->getPlugin()); } catch (Exception $ex) { throw new Am_Exception_InternalError("Cannot create soapclient object: " . $ex->getMessage()); } $soapResult = $soapClient->runTransaction($this->soapData); $this->response = json_decode(json_encode($soapResult), true); $log->add($this->response); $this->validateResponseStatus($this->result); if ($this->result->isFailure()) return; try { $this->parseResponse(); $this->validate(); if ($this->result->isSuccess()) $this->processValidated(); } catch (Exception $e) { if ($e instanceof PHPUnit_Framework_Error) throw $e; if ($e instanceof PHPUnit_Framework_Asser ) throw $e; if (!$result->isFailure()) $result->setFailed(___("Payment failed")); $log->add($e); } } } class Am_Paysystem_Transaction_CreditCard_Cybersource_Auth extends Am_Paysystem_Transaction_CreditCard_Cybersource { public function processValidated(){} // no process payment } class SoapClient_Cybersource extends SoapClient { protected $merchantId; protected $transactionKey; function __construct($plugin) { $this->merchantId = $plugin->getConfig('merchant_id'); $this->transactionKey = $plugin->getConfig('transaction_key'); parent::__construct(($plugin->getConfig('test_mode')) ? Am_Paysystem_Cybersource::URL_TEST : Am_Paysystem_Cybersource::URL_LIVE); } function __doRequest($request, $location, $action, $version, $one_way = 0) { $soapHeader = "{$this->merchantId}{$this->transactionKey}"; $requestDOM = new DOMDocument('1.0'); $soapHeaderDOM = new DOMDocument('1.0'); try { $requestDOM->loadXML($request); $soapHeaderDOM->loadXML($soapHeader); $node = $requestDOM->importNode($soapHeaderDOM->firstChild, true); $requestDOM->firstChild->insertBefore($node, $requestDOM->firstChild->firstChild); $request = $requestDOM->saveXML(); } catch (DOMException $e) { throw new Am_Exception_InternalError("Error adding UsernameToken: " . $e->getMessage()); } return parent::__doRequest($request, $location, $action, $version, $one_way); } } PK\dLb#b# cc/plugins/beanstream-remote.phpnu[addText("merchant_id")->setLabel('BeanStream Merchant ID'); $form->addText("passcode", array('class' => 'el-wide')) ->setLabel("Recurring billing passcode\n" . "note that this is not the same passcode\nused for Username/Passcode validation\nin the Process Transaction API"); } public function isConfigured() { return strlen($this->getConfig('merchant_id')) && strlen($this->getConfig('passcode')); } public function getSupportedCurrencies() { return array('USD', 'EUR', 'CAD'); } public function onSetupForms(Am_Event_SetupForms $event) { parent::onSetupForms($event); $event->getForm($this->getId())->removeElementByName('payment.'.$this->getId().'.reattempt'); } public function getRecurringType() { return self::REPORTS_REBILL; } public function storesCcInfo() { return false; } public function getFormOptions() { $ret = parent::getFormOptions(); $ret[] = self::CC_PHONE; return $ret; } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if(!$doFirst) throw new Am_Exception_InternalError('Cannot to run rebill from aMember'); $post = array( 'approvedPage' => $this->getReturnUrl(), 'declinedPage' => $this->getCancelUrl(), 'errorPage' => $this->getCancelUrl(), 'merchant_id' => $this->getConfig('merchant_id'), 'trnOrderNumber' => $invoice->public_id, 'trnAmount' => $invoice->first_total, 'ordEmailAddress' => $invoice->getUser()->email, 'ordName' => $invoice->getUser()->getName(), 'trnComments' => $invoice->getLineDescription(), ); if ($invoice->second_total > 0) // subscription charges { if ($invoice->first_total != $invoice->second_total) throw new Am_Exception_InternalError('First price must be the same second price'); if ($invoice->first_period != $invoice->second_period) throw new Am_Exception_InternalError('First period must be the same second period'); list($period, $period_unit) = self::parsePeriod($invoice->first_period); $post['trnRecurring'] = 1; $post['rbBillingPeriod'] = $period_unit; $post['rbBillingIncrement'] = $period; } $post['trnCardOwner'] = $cc->cc_name_f . " " . $cc->cc_name_l; $post['trnCardNumber'] = $cc->cc_number; $post['trnExpMonth'] = substr($cc->cc_expire,0,2); $post['trnExpYear'] = substr($cc->cc_expire,2); $post['ordAddress1'] = $cc->cc_street; $post['ordCity'] = $cc->cc_city; $post['ordCountry'] = $cc->cc_country; $post['ordProvince'] = $cc->cc_state; $post['ordPostalCode'] = $cc->cc_zip; $post['ordPhoneNumber'] = $cc->cc_phone; $action = new Am_Paysystem_Action_Form(self::URL_PT); foreach ($post as $k => $v) { $action->$k = $v; } $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Incoming_Beanstream($this, $request, $response, $invokeArgs); } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $this->cancelInvoice($invoice); parent::cancelAction($invoice, $actionName, $result); } public function cancelInvoice(Invoice $invoice) { if(!($rbAccId = $invoice->data()->get(self::RB_ACCOUNT_ID_KEY))) { throw new Am_Exception_InputError("Subscription can not be cancelled"); } $request = new Am_HttpRequest(self::URL_RB, Am_HttpRequest::METHOD_POST); $request->addPostParameter(array( 'serviceVersion' => '1.0', 'operationType' => 'C', 'merchantId' => $this->getConfig('merchant_id'), 'passCode' => $this->getConfig('passcode'), 'rbAccountId' => $rbAccId, )); $response = $request->send()->getBody(); $xml = simplexml_load_string($response); if((string)$xml->code != 1) { throw new Am_Exception_InternalError("Cancel subscription[{$invoice->pk()}/{$invoice->public_id}] ERROR: " . (string)$xml->message); } $invoice->data()->set(self::RB_ACCOUNT_ID_KEY, null)->update(); return true; } static function parsePeriod($period) { preg_match('/(\d+)(\w)/', $period, $matches); list(, $num, $per) = $matches; $per = strtoupper($per); switch ($per) { case 'Y': if (($num < 1) || ($num > 5)) throw new Am_Exception_InternalError("Period must be in interval 1-5 years"); break; case 'M': if (($num < 1) || ($num > 24)) throw new Am_Exception_InternalError("Period must be in interval 1-24 months"); break; case 'D': if (($num < 1) || ($num > 90)) throw new Am_Exception_InternalError("Period must be in interval 1-90 days"); break; default: throw new Am_Exception_InternalError( "Unknown period unit: $per"); } return array($num, $per); } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); $testUrl = 'http://developer.beanstream.com/quick-start/'; return <<BeanstreamRemote plugin installation 1. Copy 'beanstream-remote.php' file to 'amember_main_directory/application/cc/plugins/' 2. Enable 'beanstream-remote' plugin at 'aMember CP -> Setup/Configuration -> Plugins -> Payment Plugins', select 'beanstream-remote' 3. Configure plugin at 'aMember CP -> Setup/Configuration -> BeanstreamRemote': 'BeanStream Merchant ID' you can find at 'Beanstream Account -> administration -> company info' 'Recurring billing passcode' you can find at 'Beanstream Account -> administration -> account settings -> order settings', then 'Recurring Billing' fieldset and 'API access passcode' option (if it's empty - click 'Generate New Code' button) NOTE:Before using this plugin at live mode you may test it using developer account (registration here - $testUrl) and these test credit crads: TYPE CARD NUMBER | RESPONSE -------------------------------------------- VISA | 4030 0000 1000 1234 | Approved VISA | 4003 0505 0004 0005 | Declined MasterCard | 5100 0000 1000 1004 | Approved MasterCard | 5100 0000 2000 2000 | Declined AMEX | 3711 0000 1000 131 | Approved AMEX | 3424 0000 1000 180 | Declined 4. Go to 'Beanstream Account -> administration -> account settings -> order settings', find 'Response Notification' fieldset and fields 'Payment Gateway' & 'Recurring billing'. Insert to these both field this url: $ipn CUT; } } class Am_Paysystem_Transaction_Incoming_Beanstream extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { if($this->request->getFiltered('billingId')) return $this->request->getFiltered('orderNumber'); return $this->request->getFiltered('trnOrderNumber'); } public function getUniqId() { return $this->request->getFiltered('trnId'); } public function validateSource() { return true; } public function validateStatus() { return $this->request->getFiltered('trnApproved') == 1; } public function validateTerms() { return true; } public function processValidated() { if($rbAccId = $this->request->get('rbAccountId')) $this->invoice->data()->set(Am_Paysystem_BeanstreamRemote::RB_ACCOUNT_ID_KEY, $rbAccId)->update(); parent::processValidated(); } } PK\3#cc/plugins/networkmerchants-ach.phpnu[getConfig('hosted') || $this->getConfig('acceptjs')) return false; else return true; } function allowPartialRefunds() { return true; } public function getRecurringType() { return self::REPORTS_CRONREBILL; } public function getFormOptions() { $ret = parent::getFormOptions(); $ret[] = self::CC_PHONE; return $ret; } public function supportsCancelPage() { return $this->getConfig('hosted'); } public function getSupportedCurrencies() { return array('USD', 'EUR', 'GBP', 'CAD'); } public function isConfigured() { return strlen($this->getConfig('login')) && strlen($this->getConfig('tkey')); } public function _doBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if (!$this->getConfig('hosted') && !$this->getConfig('acceptjs')) { $user = $invoice->getUser(); if ($cc->user_id != $user->pk()) throw new Am_Exception_Paysystem("Assertion failed: cc.user_id != user.user_id"); // will be stored only if cc# or expiration changed $this->storeCreditCard($cc, $result); if (!$result->isSuccess()) return; $user->refresh(); // we have both profile id and payment id, run the necessary transaction now if amount > 0 $result->reset(); } //moved from AIM to CIM elseif(!$invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY)) { $cc = $this->getDi()->ccRecordTable->findFirstByUserId($invoice->user_id); if (!$cc) throw new Am_Exception_Paysystem("No credit card saved, cannot rebill"); $user = $invoice->getUser(); if ($cc->user_id != $user->pk()) throw new Am_Exception_Paysystem("Assertion failed: cc.user_id != user.user_id"); // will be stored only if cc# or expiration changed $this->storeCreditCard($cc, $result); if (!$result->isSuccess()) return; $user->refresh(); // we have both profile id and payment id, run the necessary transaction now if amount > 0 $result->reset(); } $this->_doTheBill($invoice, $doFirst, $cc, $result); } /* process invoice after creating payment profile */ public function _doTheBill(Invoice $invoice, $doFirst, CcRecord $cc, Am_Paysystem_Result $result) { if ($doFirst && (doubleval($invoice->first_total) <= 0)) { // free trial $tr = new Am_Paysystem_Transaction_Free($this); $tr->setInvoice($invoice); $tr->process(); $result->setSuccess($tr); } else { //fix for previously not saved payment profile if(!$invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY)) $this->loadLastProfile($invoice); $tr = new Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfileTransaction($this, $invoice, $doFirst); $tr->run($result); } } /** * Attempt to laod payment profile from Authorize.Net * if profile exists, it is set in user's record. * * Return Am_Paysystem_result * @param Invoice $invoice * @return Am_Paysystem_Result $result; */ public function loadLastProfile(Invoice $invoice) { // fetch list of payment profiles from Auth.Net and save latest to customer $result = new Am_Paysystem_Result(); $tr = new Am_Paysystem_Transaction_AuthorizeCim_GetCustomerProfile($this, $invoice, $invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY)); $tr->run($result); if ($result->isSuccess()) { $invoice->getUser()->data()->set(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY, $tr->getUniqId())->update(); } return $result; } public function _initSetupForm(Am_Form_Setup $form) { $label = "Use Hosted Version (recommended)\n". "this option allows you to display credit card input right on your website\n". "(as a popup) and in the same time it does not require PCI DSS compliance\n". "Maxmind verification will not work if enable this option"; if ('https' != substr(ROOT_SURL,0,5)) $label .= "\n" . 'This option requires https on your site'; $form->addAdvCheckbox('hosted')->setLabel($label); $form->addAdvCheckbox('acceptjs')->setLabel( "Use Accept.JS library to capture CC info\n" . "Using this method, CC info will be submited to Authorize.net servers directly. " . "So it doesn't require PCI DSS compliance" ); $form->addText('public_key', array('class'=>'el-wide', 'rel'=>'acceptjs-version')) ->setLabel("Public key for the merchant\n" . "It can be generated in the Authorize.Net Merchant interface\n" . "at Account > Settings > Security Settings > General Security Settings > Manage Public Client Key."); $form->addAdvCheckbox('zip_validate', array()) ->setLabel("Validate Postal Code?\nSpecify whether Checkout should validate the billing postal code"); $form->addText("login")->setLabel("API Login ID\n" . 'can be obtained from the same page as Transaction Key (see below)'); $form->addText("tkey")->setLabel("Transaction Key\n" . "The transaction key is generated by the system and can be obtained from Merchant Interface. To obtain the transaction key from the Merchant Interface: * Log into the Merchant Interface * Select [Settings] from the Main Menu * Click on [API Login ID and Transaction Key] in the Security section * Type in the answer to the secret question configured on setup * Click Submit"); $form->addSelect("validationMode") ->setLabel("Validation mode for creating customer profile" . "\n" . "Validation mode allows you to generate a test transaction at the time you create a customer payment profile. In Test Mode, only field validation is performed. In Live Mode, a transaction is generated and submitted to the processor with the amount of $0.01. If successful, the transaction is immediately voided. When a value of \"none\" is submitted, no additional validation is performed. ") ->loadOptions(array( 'liveMode' => 'liveMode', 'testMode' => 'testMode', 'none' => 'none' )); $form->addAdvCheckbox("testing")->setLabel("Test Mode Enabled" . "\n" . "The Test Mode requires a separate developer test account, which can be set up by filling out the following form: http://developer.authorize.net/testaccount"); $form->addScript()->setScript(<<pk(); return $userOrId . '-' . substr($this->getDi()->security->siteHash('cim'), 0, 5); } public function storeCreditCard(CcRecord $cc, Am_Paysystem_Result $result) { $user = $this->getDi()->userTable->load($cc->user_id); $profileId = $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY); if ($this->invoice) { // to link log records with current invoice $invoice = $this->invoice; } else { // updating credit card info? $invoice = $this->getDi()->invoiceRecord; $invoice->invoice_id = 0; $invoice->user_id = $user->pk(); } // compare stored cc for that user may be we don't need to refresh? if ($profileId && ($cc->cc_number != '0000000000000000')) { $storedCc = $this->getDi()->ccRecordTable->findFirstByUserId($user->pk()); if ($storedCc && (($storedCc->cc != $cc->maskCc($cc->cc_number)) || ($storedCc->cc_expire != $cc->cc_expire))) { $tr = new Am_Paysystem_Transaction_AuthorizeCim_UpdateCustomerPaymentProfile($this, $invoice, $cc); $tr->run($result); if($result->isFailure()){ // Try to delete all profiles and create new one. $result->reset(); $user->data() ->set(self::USER_PROFILE_KEY, null) ->set(self::PAYMENT_PROFILE_KEY, null) ->update(); $deleteTr = new Am_Paysystem_Transaction_AuthorizeCim_DeleteCustomerProfile($this, $invoice, $profileId); $deleteTr->run($res = new Am_Paysystem_Result); $profileId = null; } } } if (!$profileId) { try { $tr = new Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfile($this, $invoice, $cc); $tr->run($result); if (!$result->isSuccess()) { if($tr->getErrorCode() == 'E00039') { $error = $result->getLastError(); if(preg_match('/A duplicate record with ID (\d+) already exists/', $error, $regs) && $regs[1]) { $user->data()->set(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY, $regs[1])->update(); $result->reset(); $result->setSuccess(); } else { return; } } else if($tr->getErrorCode() == 'E00027') { // Authorize.Net has 2 minutes timeframe before each provide validation attempt in live mode. // If interval between two createCustomerProfile requests is less then 2 minutes Duplicate error will be returned. // We need to inform customer about such delay. $error = $result->getLastError(); if(preg_match('/A duplicate transaction has been submitted/', $error)) { $result->setFailed(___("A duplicate transaction has been submitted. Please wait 2 minutes before next attempt")); } else { return; } } else { return; } }else{ $user->data()->set(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY, $tr->getProfileId())->update(); $user->data()->set(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY, $tr->getPaymentId())->update(); } } catch (Am_Exception_Paysystem $e) { $result->setFailed($e->getPublicError()); return false; } } $paymentProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY); if (!$paymentProfileId) { try { $tr = new Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerPaymentProfile($this, $invoice, $cc); $tr->run($result); if($tr->getErrorCode() == 'E00039') { $error = strtolower($result->getLastError()); if(preg_match('/a duplicate customer payment profile already exists/', $error, $regs)) { $user->data()->set(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY, $tr->getProfileId())->update(); $result->reset(); $result->setSuccess(); } else { return; } } elseif (!$result->isSuccess()) return; $user->data()->set(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY, $tr->getProfileId())->update(); } catch (Am_Exception_Paysystem $e) { $result->setFailed($e->getPublicError()); return false; } } /// $cc->cc = $cc->maskCc(@$cc->cc_number); $cc->cc_number = '0000000000000000'; if ($cc->pk()) $cc->update(); else $cc->replace(); $result->setSuccess(); } public function getReadme() { return <<You need to enable CIM service in your authorize.net account to use this plugin. (Tools -> Customer Information Manager -> Sign Up Now) This is a paid service. 1. Enable and configure plugin in aMember CP -> Setup -> Plugins 2. You NEED to use external cron with this plugins (See aMember CP -> Configuration -> Setup/Configuration -> Advanced) CUT; } function processRefund(InvoicePayment $payment, Am_Paysystem_Result $result, $amount) { $trans = new Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfileTransactionRefund($this, $payment->getInvoice(), $payment, $amount); $trans->run($result); } function createCustomerProfile(Invoice $invoice){ $tr = new Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfile($this, $invoice); $result = new Am_Paysystem_Result(); $tr->run($result); if (!$result->isSuccess()) { if($tr->getErrorCode() == 'E00039') { $error = $result->getLastError(); if(preg_match('/A duplicate record with ID (\d+) already exists/', $error, $regs) && $regs[1]) { $invoice->getUser()->data()->set(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY, $regs[1])->update(); return; } else { throw new Am_Exception_Paysystem("Failed Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfile " . $result->getLastError()); } } else if($tr->getErrorCode() == 'E00027') { // Authorize.Net has 2 minutes timeframe before each provide validation attempt in live mode. // If interval between two createCustomerProfile requests is less then 2 minutes Duplicate error will be returned. // We need to inform customer about such delay. $error = $result->getLastError(); if(preg_match('/A duplicate transaction has been submitted/', $error)) { throw new Am_Exception_Paysystem(___("A duplicate transaction has been submitted. Please wait 2 minutes before next attempt")); } else { throw new Am_Exception_Paysystem("Failed Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfile " . $result->getLastError()); } } throw new Am_Exception_Paysystem("Failed Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfile " . $result->getLastError()); } $invoice->getUser()->data()->set(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY, $tr->getProfileId())->update(); return $tr->getProfileId(); } function getHostedProfilePageToken() { $user = $this->getDi()->userTable->load($this->invoice->user_id); $profileId = $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY); $invoice = $this->invoice; if (!$profileId) $profileId = $this->createCustomerProfile ($invoice); $tr = new Am_Paysystem_Transaction_AuthorizeCim_GetHostedProfilePageRequest($this, $invoice, $profileId); $result = new Am_Paysystem_Result(); $tr->run($result); if(!$tr->getUniqId() && ($tr->getErrorCode() == 'E00040')){ // Profile doesn't exists on Authorize.NET $profileId = $this->createCustomerProfile($invoice); $tr = new Am_Paysystem_Transaction_AuthorizeCim_GetHostedProfilePageRequest($this, $invoice, $profileId); $result = new Am_Paysystem_Result(); $tr->run($result); } if (!$tr->getUniqId()) throw new Am_Exception_Paysystem("Could not get hosted-profile-page-token from authorize.net - connection problem"); return $tr->getUniqId(); } protected function createController(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($this->getConfig('hosted')) return new Am_Mvc_Controller_CreditCard_AuthorizeNet($request, $response, $invokeArgs); elseif ($this->getConfig('acceptjs')) return new Am_Mvc_Controller_CreditCard_AuthorizeNetAcceptJs($request, $response, $invokeArgs); else return parent::createController($request, $response, $invokeArgs); } public function directAction( $request, $response, $invokeArgs) { if ($request->getActionName() == 'iframe') { $p = $this->createController($request, $response, $invokeArgs); $p->setPlugin($this); $p->run(); return; } parent::directAction($request, $response, $invokeArgs); } public function getUpdateCcLink($user) { $inv = $this->getDi()->invoiceTable->findFirstBy(array('user_id' => $user->pk(), 'paysys_id' => $this->getId()), 0, 1); if ($inv) return $this->getPluginUrl('update'); } public function canUseMaxmind() { return true; } } abstract class Am_Paysystem_Transaction_AuthorizeCim extends Am_Paysystem_Transaction_CreditCard { protected $apiName = null; protected $aimResponse = null; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $doFirst = true) { parent::__construct($plugin, $invoice, $plugin->createHttpRequest(), $doFirst); $this->request->setHeader('Content-type', 'text/xml'); $this->request->setBody($this->createXml($this->apiName)->asXml()); $this->request->setMethod(Am_HttpRequest::METHOD_POST); $this->request->setUrl(!$this->plugin->getConfig('testing') ? Am_Paysystem_AuthorizeCim::LIVE_URL : Am_Paysystem_AuthorizeCim::SANDBOX_URL); } /** @return SimpleXmlElement */ protected function createXml($name) { $xml = new SimpleXmlElement('<'.$name.'/>'); $xml['xmlns'] = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'; $xml->merchantAuthentication->name = $this->plugin->getConfig('login'); $xml->merchantAuthentication->transactionKey = $this->plugin->getConfig('tkey'); return $xml; } public function parseResponse() { $body = trim($this->response->getBody()); $body = str_replace('xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"', '', $body); $this->xml = new SimpleXMLElement($body); } public function parseAimString($string) { $vars = explode(',', $string); $this->aimResponse = new stdclass; if (count($vars) < 10) { $this->aimResponse->error_message = "Unrecognized response from Authorize.Net: " . $string; return false; } // Set all fields $this->aimResponse->aimResponse_code = $vars[0]; $this->aimResponse->aimResponse_subcode = $vars[1]; $this->aimResponse->aimResponse_reason_code = $vars[2]; $this->aimResponse->aimResponse_reason_text = $vars[3]; $this->aimResponse->authorization_code = $vars[4]; $this->aimResponse->avs_response = $vars[5]; $this->aimResponse->transaction_id = $vars[6]; $this->aimResponse->invoice_number = $vars[7]; $this->aimResponse->description = $vars[8]; $this->aimResponse->amount = $vars[9]; $this->aimResponse->method = $vars[10]; $this->aimResponse->transaction_type = $vars[11]; $this->aimResponse->customer_id = $vars[12]; $this->aimResponse->first_name = $vars[13]; $this->aimResponse->last_name = $vars[14]; $this->aimResponse->company = $vars[15]; $this->aimResponse->address = $vars[16]; $this->aimResponse->city = $vars[17]; $this->aimResponse->state = $vars[18]; $this->aimResponse->zip_code = $vars[19]; $this->aimResponse->country = $vars[20]; $this->aimResponse->phone = $vars[21]; $this->aimResponse->fax = $vars[22]; $this->aimResponse->email_address = $vars[23]; $this->aimResponse->ship_to_first_name = $vars[24]; $this->aimResponse->ship_to_last_name = $vars[25]; $this->aimResponse->ship_to_company = $vars[26]; $this->aimResponse->ship_to_address = $vars[27]; $this->aimResponse->ship_to_city = $vars[28]; $this->aimResponse->ship_to_state = $vars[29]; $this->aimResponse->ship_to_zip_code = $vars[30]; $this->aimResponse->ship_to_country = $vars[31]; $this->aimResponse->tax = $vars[32]; $this->aimResponse->duty = $vars[33]; $this->aimResponse->freight = $vars[34]; $this->aimResponse->tax_exempt = $vars[35]; $this->aimResponse->purchase_order_number= $vars[36]; $this->aimResponse->md5_hash = $vars[37]; $this->aimResponse->card_code_response = $vars[38]; $this->aimResponse->cavv_response = $vars[39]; $this->aimResponse->account_number = $vars[40]; $this->aimResponse->card_type = $vars[51]; $this->aimResponse->split_tender_id = $vars[52]; $this->aimResponse->requested_amount = $vars[53]; $this->aimResponse->balance_on_card = $vars[54]; return true; } } class Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfile extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'createCustomerProfileRequest'; /** @var CcRecord */ protected $cc; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc = null) { $this->cc = $cc; parent::__construct($plugin, $invoice); } protected function createXml($name) { $xml = parent::createXml($name); $user = $this->invoice->getUser(); $xml->profile->merchantCustomerId = $this->plugin->getMerchantCustomerId($this->cc ? $this->cc->user_id : $this->invoice->user_id); $xml->profile->description = "Username: $user->login"; $xml->profile->email = $user->email; if ($this->cc) { $xml->profile->paymentProfiles->billTo->firstName = $this->cc->cc_name_f; $xml->profile->paymentProfiles->billTo->lastName = $this->cc->cc_name_l; $xml->profile->paymentProfiles->billTo->address = $this->cc->cc_street; $xml->profile->paymentProfiles->billTo->city = $this->cc->cc_city; $xml->profile->paymentProfiles->billTo->state = $this->cc->cc_state; $xml->profile->paymentProfiles->billTo->zip = $this->cc->cc_zip; $xml->profile->paymentProfiles->billTo->country = $this->cc->cc_country; $xml->profile->paymentProfiles->billTo->phoneNumber = $this->cc->cc_phone; $xml->profile->paymentProfiles->payment->creditCard->cardNumber = $this->cc->cc_number; $xml->profile->paymentProfiles->payment->creditCard->expirationDate = $this->cc->getExpire('20%2$02d-%1$02d'); if (strlen($this->cc->getCvv())) $xml->profile->paymentProfiles->payment->creditCard->cardCode = $this->cc->getCvv(); $xml->validationMode = $this->getPlugin()->getConfig('validationMode', 'liveMode'); } if($user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_VALUE)){ $xml->profile->paymentProfiles->billTo->firstName = $this->invoice->getFirstName(); $xml->profile->paymentProfiles->billTo->lastName = $this->invoice->getLastName(); $xml->profile->paymentProfiles->payment->opaqueData->dataDescriptor = $user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_DESCRIPTOR); $xml->profile->paymentProfiles->payment->opaqueData->dataValue = $user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_VALUE); } return $xml; } public function validate() { if ($this->xml->getName() != 'createCustomerProfileResponse') { $this->result->setFailed(___('Payment failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed((string)$this->xml->messages->message->text); return; } $this->result->setSuccess(); return true; } function getProfileId() { return (string)$this->xml->customerProfileId; } function getPaymentId() { return (string)$this->xml->customerPaymentProfileIdList->numericString; } public function getUniqId() { return (string)$this->xml->customerProfileId; } public function processValidated() { } public function getErrorCode(){ return (string)$this->xml->messages->message->code; } } class Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerPaymentProfile extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'createCustomerPaymentProfileRequest'; /** @var CcRecord */ protected $cc; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc = null) { $this->cc = $cc; parent::__construct($plugin, $invoice); } protected function createXml($name) { $xml = parent::createXml($name); $user = $this->invoice->getUser(); $xml->customerProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY); if ($this->cc) { $xml->paymentProfile->billTo->firstName = $this->cc->cc_name_f; $xml->paymentProfile->billTo->lastName = $this->cc->cc_name_l; $xml->paymentProfile->billTo->address = $this->cc->cc_street; $xml->paymentProfile->billTo->city = $this->cc->cc_city; $xml->paymentProfile->billTo->state = $this->cc->cc_state; $xml->paymentProfile->billTo->zip = $this->cc->cc_zip; $xml->paymentProfile->billTo->country = $this->cc->cc_country; $xml->paymentProfile->billTo->phoneNumber = $this->cc->cc_phone; $xml->paymentProfile->payment->creditCard->cardNumber = $this->cc->cc_number; $xml->paymentProfile->payment->creditCard->expirationDate = $this->cc->getExpire('20%2$02d-%1$02d'); if (strlen($this->cc->getCvv())) $xml->paymentProfile->payment->creditCard->cardCode = $this->cc->getCvv(); $xml->validationMode = $this->getPlugin()->getConfig('validationMode', 'liveMode'); } if($user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_VALUE)){ $xml->paymentProfile->billTo->firstName = $this->invoice->getFirstName(); $xml->paymentProfile->billTo->lastName = $this->invoice->getLastName(); $xml->paymentProfile->payment->opaqueData->dataDescriptor = $user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_DESCRIPTOR); $xml->paymentProfile->payment->opaqueData->dataValue = $user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_VALUE); } return $xml; } public function validate() { if ($this->xml->getName() != 'createCustomerPaymentProfileResponse') { $this->result->setFailed(___('Payment failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed((string)$this->xml->messages->message->text); return; } $this->result->setSuccess(); return true; } function getProfileId() { return (string)$this->xml->customerPaymentProfileId; } public function getUniqId() { return (string)$this->xml->customerPaymentProfileId; } public function processValidated() { } public function getErrorCode(){ return (string)$this->xml->messages->message->code; } } class Am_Paysystem_Transaction_AuthorizeCim_UpdateCustomerPaymentProfile extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'updateCustomerPaymentProfileRequest'; /** @var CcRecord */ protected $cc; protected $profileId; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, CcRecord $cc = null) { $this->cc = $cc; parent::__construct($plugin, $invoice); } protected function createXml($name) { $xml = parent::createXml($name); $user = $this->invoice->getUser(); $xml->customerProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY); if ($this->cc) { $xml->paymentProfile->billTo->firstName = $this->cc->cc_name_f; $xml->paymentProfile->billTo->lastName = $this->cc->cc_name_l; $xml->paymentProfile->billTo->address = $this->cc->cc_street; $xml->paymentProfile->billTo->city = $this->cc->cc_city; $xml->paymentProfile->billTo->state = $this->cc->cc_state; $xml->paymentProfile->billTo->zip = $this->cc->cc_zip; $xml->paymentProfile->billTo->country = $this->cc->cc_country; $xml->paymentProfile->billTo->phoneNumber = $this->cc->cc_phone; $xml->paymentProfile->payment->creditCard->cardNumber = $this->cc->cc_number; $xml->paymentProfile->payment->creditCard->expirationDate = $this->cc->getExpire('20%2$02d-%1$02d'); if (strlen($this->cc->getCvv())) $xml->paymentProfile->payment->creditCard->cardCode = $this->cc->getCvv(); $xml->validationMode = $this->getPlugin()->getConfig('validationMode', 'liveMode'); $xml->paymentProfile->customerPaymentProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY); } if($user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_VALUE)){ $xml->paymentProfile->billTo->firstName = $this->invoice->getFirstName(); $xml->paymentProfile->billTo->lastName = $this->invoice->getLastName(); $xml->paymentProfile->payment->opaqueData->dataDescriptor = $user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_DESCRIPTOR); $xml->paymentProfile->payment->opaqueData->dataValue = $user->data()->get(Am_Paysystem_AuthorizeCim::OPAQUE_DATA_VALUE); } return $xml; } public function validate() { if ($this->xml->getName() != 'updateCustomerPaymentProfileResponse') { $this->result->setFailed(___('Payment failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed((string)$this->xml->messages->message->text); return; } $this->result->setSuccess(); return true; } public function getUniqId() { return uniqid(); } public function processValidated() { } } class Am_Paysystem_Transaction_AuthorizeCim_DeleteCustomerProfile extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'deleteCustomerProfileRequest'; protected $profileId; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $profileId) { $this->profileId = $profileId; parent::__construct($plugin, $invoice, true); } protected function createXml($name) { $xml = parent::createXml($name); $xml->customerProfileId = $this->profileId; return $xml; } public function validate() { if ($this->xml->getName() != 'deleteCustomerProfileResponse') { $this->result->setFailed(___('Profile update transaction failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed((string)$this->xml->messages->message->text); return; } $this->result->setSuccess(); return true; } public function getUniqId() { return uniqid(); } public function processValidated() { } } class Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfileTransaction extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'createCustomerProfileTransactionRequest'; /** @var object */ protected $aimResponse; protected function createXml($name) { $xml = parent::createXml($name); $xml->transaction->profileTransAuthCapture->amount = $this->doFirst ? $this->invoice->first_total : $this->invoice->second_total; $xml->transaction->profileTransAuthCapture->tax->amount = $this->doFirst ? $this->invoice->first_tax : $this->invoice->second_tax; $xml->transaction->profileTransAuthCapture->shipping->amount = $this->doFirst ? $this->invoice->first_shipping : $this->invoice->second_shipping; foreach ($this->invoice->getItems() as $item) { /* @var $item InvoiceItem */ $line = $xml->transaction->profileTransAuthCapture->addChild('lineItems'); $line->itemId = $item->item_id; $line->name = substr($item->item_title, 0, 30); $line->quantity = $item->qty; $price = $this->doFirst ? $item->first_price : $item->second_price; if ($price) $line->unitPrice = $price; if ($this->doFirst ? $item->first_tax : $item->second_tax) $line->taxable = 'true'; else $line->taxable = 'false'; } $user = $this->invoice->getUser(); $taxAmount = $this->doFirst ? $this->invoice->first_tax : $this->invoice->second_tax; if ($taxAmount) $xml->transaction->profileTransAuthCapture->tax->amount = $taxAmount; $xml->transaction->profileTransAuthCapture->customerProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY); $xml->transaction->profileTransAuthCapture->customerPaymentProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY); $xml->transaction->profileTransAuthCapture->order->description = $this->invoice->getLineDescription(); $xml->transaction->profileTransAuthCapture->order->purchaseOrderNumber = $this->invoice->public_id . '-' . $this->invoice->getPaymentsCount(); $xml->transaction->profileTransAuthCapture->recurringBilling = $this->doFirst ? 'true' : 'false'; $xml->addChild('extraOptions', 'x_Customer_IP=' . ($user->remote_addr ? $user->remote_addr : $_SERVER['REMOTE_ADDR'])); return $xml; } public function validate() { if ($this->xml->getName() != 'createCustomerProfileTransactionResponse') { $this->result->setFailed(___('Payment failed')); return; } if (!$this->parseAimString($this->xml->directResponse)) { $this->result->setFailed(___('Payment failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed(___('Payment failed')); return; } $this->result->setSuccess($this); return true; } public function getUniqId() { return $this->aimResponse->transaction_id; } public function processValidated() { $this->invoice->addPayment($this); } } class Am_Paysystem_Transaction_AuthorizeCim_CreateCustomerProfileTransactionRefund extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'createCustomerProfileTransactionRequest'; /** @var object */ protected $aimResponse; public $amount; public $transId; function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, InvoicePayment $payment, $amount) { $this->transId = $payment->receipt_id; $this->amount = $amount; parent::__construct($plugin, $invoice); } protected function createXml($name) { $xml = parent::createXml($name); $xml->transaction->profileTransRefund->amount = $this->amount; $user = $this->invoice->getUser(); $xml->transaction->profileTransRefund->customerProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY); $xml->transaction->profileTransRefund->customerPaymentProfileId = $user->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY); $xml->transaction->profileTransRefund->order->description = "Refund for payment: ".$this->transId." amount: ".$this->amount; $xml->transaction->profileTransRefund->order->purchaseOrderNumber = $this->invoice->public_id . '-RFND-' . $this->transId; $xml->transaction->profileTransRefund->transId = $this->transId; return $xml; } public function validate() { if ($this->xml->getName() != 'createCustomerProfileTransactionResponse') { $this->result->setFailed(___('Payment failed')); return; } if (!$this->parseAimString($this->xml->directResponse)) { $this->result->setFailed(___('Payment failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed(___('Payment failed')); return; } $this->result->setSuccess(); return true; } public function getUniqId() { return $this->aimResponse->transaction_id; } public function processValidated() { $this->invoice->addRefund($this, $this->transId, $this->amount); } } class Am_Paysystem_Transaction_AuthorizeCim_GetHostedProfilePageRequest extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'getHostedProfilePageRequest'; /** @var object */ protected $aimResponse; protected $profileId; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $profileId) { $this->profileId = $profileId; parent::__construct($plugin, $invoice, true); } protected function createXml($name) { $xml = parent::createXml($name); $xml->customerProfileId = $this->profileId; /* $xml->hostedProfileSettings->setting[0]->settingName = 'hostedProfileReturnUrl'; $xml->hostedProfileSettings->setting[0]->settingValue = $this->plugin->getReturnUrl(); $xml->hostedProfileSettings->setting[1]->settingName = 'hostedProfileReturnUrlText'; $xml->hostedProfileSettings->setting[1]->settingValue = 'Return'; $xml->hostedProfileSettings->setting[2]->settingName = 'hostedProfileHeadingBgColor'; $xml->hostedProfileSettings->setting[2]->settingValue = ''; */ $xml->hostedProfileSettings->setting[0]->settingName = 'hostedProfilePageBorderVisible'; $xml->hostedProfileSettings->setting[0]->settingValue = 'false'; $xml->hostedProfileSettings->setting[1]->settingName = 'hostedProfileIFrameCommunicatorUrl'; $xml->hostedProfileSettings->setting[1]->settingValue = $this->getPlugin()->getPluginUrl('iframe'); $xml->hostedProfileSettings->setting[2]->settingName = 'hostedProfileValidationMode'; $xml->hostedProfileSettings->setting[2]->settingValue = $this->getPlugin()->getConfig('validationMode', 'liveMode'); return $xml; } public function validate() { if ($this->xml->getName() != 'getHostedProfilePageResponse') { $this->result->setFailed(___('Payment failed')); return; } if ((string)$this->xml->messages->message->code != 'I00001') { $this->result->setFailed(___('Payment failed')); return; } $this->result->setSuccess($this); return true; } public function getUniqId() { return (string)$this->xml->token;; } public function getErrorCode(){ return (string) $this->xml->messages->message->code; } public function processValidated() { } } class Am_Paysystem_Transaction_AuthorizeCim_GetCustomerProfile extends Am_Paysystem_Transaction_AuthorizeCim { protected $apiName = 'getCustomerProfileRequest'; /** @var object */ protected $aimResponse; protected $profileId; public function __construct(Am_Paysystem_Abstract $plugin, Invoice $invoice, $profileId) { $this->profileId = $profileId; parent::__construct($plugin, $invoice, true); } protected function createXml($name) { $xml = parent::createXml($name); $xml->customerProfileId = $this->profileId; return $xml; } public function validate() { if ($this->xml->getName() != 'getCustomerProfileResponse') { $this->result->setFailed(___('Payment failed')); return; } if (!$this->getUniqId()) { $this->result->setFailed(___('Payment failed')); return; } $this->result->setSuccess($this); return true; } public function getUniqId() { // fetch LAST payment profile id from customer profile $ret = ''; foreach ($this->xml->profile->paymentProfiles as $x) $ret = (string)$x->customerPaymentProfileId; return $ret; } public function processValidated() { } } class Am_Mvc_Controller_CreditCard_AuthorizeNet extends Am_Mvc_Controller { /** @var Am_Paysystem_AuthorizeCim */ protected $plugin; /** @var Invoice */ protected $invoice; public function setPlugin($plugin) { $this->plugin = $plugin; } public function setInvoice($invoice) { $this->invoice = $invoice; } protected function ccError($msg) { $this->view->content .= "".$msg.""; $url = $this->_request->getRequestUri(); $url .= (strchr($url, '?') ? '&' : '?') . 'id=' . $this->_request->get('id'); $url = Am_Html::escape($url); $this->view->content .= " ".___('Return and try again').""; $this->view->display('layout.phtml'); exit; } /** * Process a transaction using saved customer payment profile * and do either success redirect, or display error * @return Am_Paysystem_Result */ protected function ccActionProcessAfterProfileExists() { $result = new Am_Paysystem_Result(); $this->plugin->_doTheBill($this->invoice, true, $this->getDi()->CcRecordTable->createRecord(), $result); if (@$result->errorCode == 'E00040') // Customer Profile ID or Customer Payment Profile ID not found { // cleanup customer payment profile $user = $this->invoice->getUser(); $user->data()->set(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY, null); $tr = new Am_Paysystem_Transaction_AuthorizeCim_DeleteCustomerProfile($this->plugin, $this->invoice, $user->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY)); $tr->run(new Am_Paysystem_Result); $user->data()->set(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY, null); $user->data()->update(); } return $result; } public function ccAction() { $this->view->title = ___('Payment Info'); $this->view->invoice = $this->invoice; $this->view->content = $this->view->render('_receipt.phtml'); if ($this->_request->get('result') == 'success') { if (!$this->invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY)) { $ret = $this->plugin->loadLastProfile($this->invoice); if(!$ret->isSuccess()){ $this->ccError($ret->getLastError()); } // check status here? } $result = $this->ccActionProcessAfterProfileExists(); if ($result->isSuccess()) { $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session $s->ccConfirmed = true; $this->_response->setRedirect($this->plugin->getReturnUrl()); } else { $this->ccError($result->getLastError()); } } else { if ($this->invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY)) { // if we have credit card on file, we will try to use it but we // have to display confirmation first $s = new Zend_Session_Namespace($this->plugin->getId()); $s->setExpirationSeconds(60*30); // after 30 minutes we will reset the session $s->ccConfirmed = !empty($s->ccConfirmed); switch ($this->_request->get('result')) { case 'confirm': $s->ccConfirmed = true; break; case 'new' : break; default: if (!$s->ccConfirmed) return $this->displayReuse(); } if ($s->ccConfirmed) { $result = $this->ccActionProcessAfterProfileExists(); if ($result->isSuccess()) { return $this->_response->setRedirect($this->plugin->getReturnUrl()); } } } else { //try to load previously not saved payment profile if($this->plugin->loadLastProfile($this->invoice)->isSuccess()) { return $this->displayReuse(); } } return $this->displayHostedPage($this->plugin->getCancelUrl()); } } protected function displayReuse() { $result = new Am_Paysystem_Result; $tr = new Am_Paysystem_Transaction_AuthorizeCim_GetCustomerProfile($this->plugin, $this->invoice, $this->invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::USER_PROFILE_KEY)); $tr->run($result); if (!$result->isSuccess()) throw new Am_Exception_Paysystem("Stored customer profile not found"); $payprofileid = $this->invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY); foreach ($tr->xml->profile->paymentProfiles as $pp) { if ($payprofileid == (string)$pp->customerPaymentProfileId) { $card = (string)$pp->payment->creditCard->cardNumber; } } if (empty($card)) throw new Am_Exception_Paysystem("Store payment profile not found"); $text = ___('Click "Continue" to pay this order using stored credit card %s', $card); $continue = ___('Continue'); $use_new_card = ___("Use another card"); $url = $this->_request->assembleUrl(false,true); $action = $this->plugin->getPluginUrl('cc'); $id = Am_Html::escape($this->_request->get('id')); $action = Am_Html::escape($action); $this->view->content .= << $text
         $use_new_card
      CUT; $this->view->display('layout.phtml'); } public function updateAction() { $user = $this->getDi()->auth->getUser(true); // dirty hack - load last user invoice to be used in process $this->invoice = $this->getDi()->invoiceTable->findFirstBy(array('user_id' => $user->pk(), 'paysys_id' => $this->plugin->getId()), 0, 1, "invoice_id DESC"); if (!$this->invoice) throw new Am_Exception_InternalError("No active invoices found, but update cc info request received?"); $this->plugin->_setInvoice($this->invoice); $this->view->title = ___('Payment Info'); $this->view->invoice = null; $this->view->content = ""; if ($this->_request->get('result') == 'success') { if(!$user->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY)) { $this->plugin->loadLastProfile($this->invoice); } $this->_redirect($this->getDi()->url('member',null,false,true)); } return $this->displayHostedPage($this->getDi()->url('member',null,false,true)); } protected function displayHostedPage($cancelUrl) { $id = $this->invoice->getUser()->data()->get(Am_Paysystem_AuthorizeCim::PAYMENT_PROFILE_KEY); if ($id) { $method = 'editPayment'; $id = filterId($id); } else { $method = 'addPayment'; $id = null; } $token = $this->plugin->getHostedProfilePageToken(); $domain = $this->plugin->getConfig('testing') ? 'test' : 'secure'; $cancelUrl = json_encode($cancelUrl); $popupTitle = json_encode(___('Credit Card Info')); $plzwt = ___('Please wait while we process your order...'); $plzwt2 = ___('Click here if you do not want to wait any longer (or if your browser does not automatically forward you).'); $this->view->content .= <<
      ').find('pre').text(html);
          }
          else
          {
              var output = jQuery("#row-body-group .element.group");
              var iframe = document.createElement( "iframe" );
              iframe.setAttribute("id", "am_preview_iframe");
              output.append( iframe );
              var doc = (iframe.contentWindow || iframe.contentDocument).document;
      		doc.write(html);
      		doc.close();
              jQuery("#am_preview_iframe").css('height',jQuery("#am_preview_iframe").contents().height())
                  .css('width','100%').css('border','none');
          }
      
          jQuery("input.form-back").click(function(){
              jQuery(this).closest('form').prop('action', jQuery(this).data('href')).submit();
          });
      });
      CUT
                  );
              }
              return $this->indexAction();
          }
      
          function indexAction()
          {
              $this->view->headScript()->appendFile($this->view->_scriptJs("ckeditor/ckeditor.js"));
              $this->view->headScript()->appendFile($this->view->_scriptJs("htmlreg.js"));
              $form = $this->getForm();
      
              if ($this->form->isSubmitted())
                  $this->form->validate();
      
              $this->view->form = $form;
              $this->view->users_found = $this->searchUi->getFoundRows();
              if ($this->_request->getActionName() != 'preview')
                  $this->view->search = $this->searchUi->render();
              else
                  $this->view->search = '


      '; $this->view->filterCondition = $this->searchUi->getActive()->getDescription(); $this->view->display('admin/email.phtml'); } function historyRowsAction() { $q = new Am_Query($this->getDi()->emailSentTable); $q->leftJoin('?_admin', 'a', 't.admin_id=a.admin_id'); $q->addField('a.login', 'admin_login'); $q->setOrder('email_sent_id', 'DESC'); // dirty hack $withWrap = (bool) $this->_request->get('_h_wrap'); unset($_GET['_h_wrap']); $grid = new Am_Grid_Editable('_h', ___('E-Mails History'), $q, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_EMAIL); if ($withWrap) $grid->isAjax(false); $grid->setCountPerPage(20); $grid->addField(new Am_Grid_Field_Date('tm_added', ___('Started'))); $grid->addField('subject', ___('Subject')); $grid->addField('admin_login', ___('Sender')); $grid->addField('count_users', ___('Total')); $grid->addField('sent_users', ___('Sent')); $grid->addField('desc_users', ___('To')) ->setAttrs(array('class' => 'break')); $grid->actionsClear(); $url = $this->getDi()->url('admin-email',array('resend_id'=>'__ID__'),false); $grid->actionAdd(new Am_Grid_Action_Url('resend', ___('Resend'), $url))->setTarget('_top'); $url = $this->getDi()->url('admin-email/send',array('queue_id'=>'__ID__'),false); $grid->actionAdd(new Am_Grid_Action_Url('continue', ___('Continue'), $url)) ->setTarget('_top') ->setIsAvailableCallback(array($this, 'needContinueLink')); if ($this->getDi()->authAdmin->getUser()->isSuper()) { $grid->actionAdd(new Am_Grid_Action_Delete()); } $grid->run($this->getResponse()); } function needContinueLink(EmailSent $s) { return $s->count_users > $s->sent_users; } function sendAction() { if ($this->getParam('back')) return $this->_redirect('admin-email'); check_demo(); if (!$this->saved) { $this->createSendSession(); return $this->sendRedirect(); } $batch = new Am_BatchProcessor(array($this, 'batchSend')); $breaked = !$batch->run($this->saved); $breaked ? $this->sendRedirect() : $this->sendComplete(); } public function batchSend(&$context, Am_BatchProcessor $batch) { if ($this->saved->count_users <= $this->saved->sent_users) return true; // we are done; $q = $this->searchUi->query($this->saved->sent_users, 100); $i = 0; $db = $this->getDi()->db; $foundrows = false; while ($r = $db->fetchRow($q)) { $foundrows = true; if (!$batch->checkLimits()) return false; $r['name'] = $r['name_f'] . ' ' . $r['name_l']; $this->saved->updateQuick(array('last_email' => $r['email'], 'sent_users' => $this->saved->sent_users + 1)); if ($r['email'] == '') continue; $m = $this->getDi()->mail; $m->setPeriodic(Am_Mail::ADMIN_REQUESTED); $m->addHeader('X-Amember-Queue-Id', $this->_request->getFiltered('queue_id')); $m->addUnsubscribeLink(Am_Mail::LINK_USER); $m->addTo($r['email'], $r['name']); if ($reply_to = $this->getParam('reply_to')) { switch ($reply_to) { case 'default' : $email = false; break; case 'other' : $email = $this->getParam('reply_to_other'); $name = null; break; default: preg_match('/^admin-(\d+)$/', $reply_to, $match); $admin = $this->getDi()->adminTable->load($match[1], false); if ($admin) { $email = $admin->email; $name = $admin->getName(); } break; } if ($email = filter_var($email, FILTER_VALIDATE_EMAIL)) { $m->setReplyTo($email, $name); } } $subject = $this->getParam('subject'); $body = $this->getParam('body'); $tpl = new Am_SimpleTemplate(); $tpl->assignStdVars(); if ((strpos($body, '%user.unsubscribe_link%') !== false) || (strpos($subject, '%user.unsubscribe_link%') !== false)) { $r['unsubscribe_link'] = Am_Mail::getUnsubscribeLink($r['email'], Am_Mail::LINK_USER); } $tpl->user = $r; $this->getDi()->hook->call(Am_Event::MAIL_SIMPLE_TEMPLATE_BEFORE_PARSE, array( 'template' => $tpl, 'body' => $body, 'subject' => $subject, 'mail' => $m, 'request' => $this->getRequest() )); $subject = $tpl->render($subject); $body = $tpl->render($body); if ($this->getParam('email_template_layout_id') && ($layout = $this->getDi()->emailTemplateLayoutTable->load($this->getParam('email_template_layout_id', false)))) { $tpl->assign('content', $body); $body = $tpl->render($layout->layout); } $m->setSubject($subject); if ($this->getParam('format') == 'text') { $m->setBodyText($body); } else { $text = strip_tags($body); $html = strpos($body, '$subject$body" : $body; $m->setBodyHtml($html); $m->setBodyText($text); } foreach ($this->getAttachments() as $at) $m->addAttachment($at); try { $m->send(); } catch (Zend_Mail_Exception $e) { trigger_error("Error happened while sending e-mail to $r[email] : " . $e->getMessage(), E_USER_WARNING); } } $this->getDi()->db->freeResult($q); if(!$foundrows) return true; if ($this->saved->count_users <= $this->saved->sent_users) return true; // we are done; } }PK\uy'y'.default/controllers/AdminRebuildController.phpnu[getDi()->plugins_protect->loadEnabled()->getAllEnabled() as $pl) { try { $pl->destroy(); } catch (Exception $e) { } } /// $batch = new Am_BatchProcessor(array($this, 'doWork')); $context = $event->getDoneString(); $batch->run($context) ? $event->setDone() : $event->setDoneString($context); } function doWork(& $context, Am_BatchProcessor $batch) { $pageCount = 1000; if (!strlen($context)) { $changed = $this->getDi()->userTable->checkAllSubscriptionsFindChanged($pageCount); $this->getDi()->db->query("DELETE FROM ?_data WHERE `table`='user' AND `key`=?", self::NEED_REBUILD); if (!$changed) return true; $this->getDi()->db->query(" INSERT INTO ?_data (`table`, `id`, `key`, `value`) SELECT 'user', m.user_id, ?, 1 FROM ?_user m WHERE m.user_id IN (?a)", self::NEED_REBUILD, $changed); $context = 0; return false; } // now select all changed users from user table and run checkSubscriptions on each $q = $this->getDi()->db->queryResultOnly(" SELECT m.* FROM ?_user m LEFT JOIN ?_data d ON (d.`table`='user' AND m.user_id=d.`id` AND d.`key`=?) WHERE d.value > 0 LIMIT ?d, ?d", self::NEED_REBUILD, (int)$context, $pageCount); $count = 0; while ($row = $this->getDi()->db->fetchRow($q)) { $count++; $u = $this->getDi()->userRecord; $u->fromRow($row); $u->checkSubscriptions(false); // access_cache is batch-updated $context++; if (!$batch->checkLimits()) return false; } if (!$count) { $changed = $this->getDi()->userTable->checkAllSubscriptionsFindChanged($pageCount); if (!$changed) { $context = ''; return true; } else { $this->getDi()->db->query(" INSERT INTO ?_data (`table`, `id`, `key`, `value`) SELECT 'user', m.user_id, ?, 1 FROM ?_user m WHERE m.user_id IN (?a)", self::NEED_REBUILD, $changed); return false; } } } } class Am_Invoice_Rebuild { function getDi() { return Am_Di::getInstance(); } function getTitle() { return ___('Invoices Information'); } function onRebuild(Am_Event_Rebuild $event) { $batch = new Am_BatchProcessor(array($this, 'doWork')); $context = $event->getDoneString(); $batch->run($context) ? $event->setDone() : $event->setDoneString($context); } function doWork(& $context, Am_BatchProcessor $batch) { $pageCount = 5000; $q = $this->getDi()->db->queryResultOnly(" SELECT * FROM ?_invoice LIMIT ?d, ?d", (int)$context, $pageCount); $count = 0; while ($row = $this->getDi()->db->fetchRow($q)) { $count++; $invoice = $this->getDi()->invoiceRecord; $invoice->fromRow($row); $invoice->updateStatus(); try { $invoice->recalculateRebillDate(); } catch (Am_Exception_InternalError $e) {}; // ignore error about empty period $context++; if (!$batch->checkLimits()) return; } if (!$count) return true; // finished! } } class AdminRebuildController extends Am_Mvc_Controller { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_REBUILD_DB); } /** @return array id => title */ function getTargetsList() { $list = array('core' => ___('Core'), 'invoice' => ___('Invoice')); foreach ($this->getDi()->hook->getRegisteredHooks('rebuild') as $hook) { $hook = $hook->getCallback(); if (is_array($hook) && is_object($hook[0])) { $obj = $hook[0]; $list[$obj->getId()] = $obj->getTitle(); } } return $list; } /** @return callback|null */ function getTarget($id) { if ($id == 'core') return array(new Am_Core_Rebuild, 'onRebuild'); if ($id == 'invoice') return array(new Am_Invoice_Rebuild, 'onRebuild'); foreach ($this->getDi()->hook->getRegisteredHooks('rebuild') as $hook) { $hook = $hook->getCallback(); if (is_array($hook) && is_object($hook[0])) { $obj = $hook[0]; if ($obj->getId() == $id) return $hook; } } } function indexAction() { $plugin_buttons = ""; foreach ($this->getTargetsList() as $id => $title) { $plugin_buttons .= sprintf(' '.PHP_EOL, $id, $title); } $this->view->title = ___('Rebuild Users Database'); $DONE = ___('DONE'); $CONTINUE = ___('CONTINUE'); $BEGIN = ___('BEGIN'); $info = ___('Sometimes, after configuration errors and as result of software problems, aMember users database and third-party scripts databases becomes out of sync. Then you can run rebuild process manually to get databases fixed.'); $this->view->content = <<
      $info
      $plugin_buttons


      CUT; $this->view->display('admin/layout.phtml'); } function doAction() { if (!$this->_request->isPost() || !$this->_request->get('do')) throw new Am_Exception_InputError("Wrong request"); @ignore_user_abort(true); @set_time_limit(0); @ini_set('memory_limit', AM_HEAVY_MEMORY_LIMIT); $do = $this->_request->getParam('do'); @list($do, $doneString) = explode(":", $do, 2); $callback = $this->getTarget($do); if (!$callback) throw new Am_Exception_InputError("Wrong request - plugin [$do] not found"); $this->printStarted($callback[0]->getTitle() . " Db"); $this->getDi()->adminLogTable->log("Rebuild ".$callback[0]->getTitle() . " Db started"); $event = new Am_Event_Rebuild; $event->setDoneString($doneString); call_user_func($callback, $event); $this->getDi()->adminLogTable->log("Rebuild ".$callback[0]->getTitle() . " Db finished"); $this->printFinished($do, $event); } function printStarted($what) { echo "Rebuilding $what…\n\n"; } function printFinished($plugin, Am_Event_Rebuild $event) { if ($event->needContinue()) { echo ___('CONTINUE') . "($plugin:".htmlentities($event->getDoneString()).")"; } else { echo ___('DONE'); } } }PK\://'default/controllers/LoginController.phpnu[getParam('amember_redirect_url')) $this->setRedirectUrl($this->getParam('amember_redirect_url')); if ($this->getParam('_amember_redirect_url')) $this->setRedirectUrl(base64_decode($this->getParam('_amember_redirect_url'))); if (!$this->redirect_url && $this->getDi()->config->get('protect.php_include.redirect_ok') == 'referer' && isset($_SERVER['HTTP_REFERER'])) { $path = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_PATH); $root_path = parse_url(ROOT_URL, PHP_URL_PATH); if ($path != $_SERVER['REQUEST_URI'] && $path != $root_path . '/thanks' && $path != $root_path . '/sendpass') $this->setRedirectUrl($_SERVER['HTTP_REFERER']); } $this->remember_login = $this->getDi()->config->get($this->configBase . '.remember_login', false); $this->remember_auto = $this->getDi()->config->get($this->configBase . '.remember_auto', false); if ($this->remember_auto) $this->remember_login = true; $this->remember_period = $this->getDi()->config->get($this->configBase . '.remember_period', 60); $this->redirect = $this->getConfiguredRedirectLogout(); } public function changePassAction() { $this->getDi()->auth->requireLogin(); $form = new Am_Form(); $form->addCsrf(); $form->addPassword('pass_current') ->setLabel(___('Your Current Password')) ->addRule('callback', ___('Wrong password'), array($this, 'checkPassword')); $len = $this->getDi()->config->get('pass_min_length', 6); $pass = $form->addPassword('pass', array('size' => 15, 'maxlength' => $this->getDi()->config->get('pass_max_length', 64))) ->setLabel(___("Choose New Password\nmust be %d or more characters", $len)); $pass->addRule('required', ___('Please enter Password')); $pass->addRule('length', sprintf(___('Password must contain at least %d letters or digits'), $len), array($len, $this->getDi()->config->get('pass_max_length', 64))); if ($this->getDi()->config->get('require_strong_password')) { $pass->addRule('regex', ___('Password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars'), $this->getDi()->userTable->getStrongPasswordRegex()); } $pass0 = $form->addPassword('_pass', array('size' => 15)) ->setLabel(___('Confirm New Password')); $pass0->addRule('required'); $pass0->addRule('eq', ___('Password and Password Confirmation are different. Please reenter both'), $pass); $form->addSaveButton(___('Update Password')); if ($form->isSubmitted() && $form->validate()) { $val = $form->getValue(); $user = $this->getDi()->user; $user->setPass($val['pass']); $user->save(); $this->getDi()->auth->setUser($user); $this->_redirect('member'); } else { $view = $this->getDi()->view; $view->layoutNoMenu = true; $view->title = ___('Change Your Password'); $view->content = sprintf('
      %s
      ', ___('We ask you to update your password periodically for security reason.')) . $form; $view->display('layout.phtml'); } } function checkPassword($pass) { return $this->getDi()->auth->getUser()->checkPassword($pass); } public function getAuth() { return $this->getDi()->auth; } public function getHiddenVars() { $arr = parent::getHiddenVars(); if ($this->redirect_url) $arr['amember_redirect_url'] = $this->redirect_url; if ($f = $this->_request->getFiltered('saved_form')) $arr['saved_form'] = $f; return $arr; } public function getLogoutUrl() { return get_first($this->redirect_url, $this->redirect, $this->getDi()->url(''), $this->getDi()->url('',null,false,2)); } protected function getConfiguredRedirect() { $default = $this->getDi()->url('member',null,false); $first = $single = false; switch ($this->getDi()->config->get('protect.php_include.redirect_ok', 'first_url')) { case 'first_url': $first = true; break; case 'single_url': $single = true; break; case 'last_url': break; case 'url': return $this->getDi()->config->get('protect.php_include.redirect_ok_url', $default); default: case 'member': return $default; } $cnt = 0; $resources = $this->getDi()->resourceAccessTable->getAllowedResources($this->getDi()->user, ResourceAccess::USER_VISIBLE_PAGES); if (!$resources) return $default; if (!$first) { $resources = array_reverse($resources); } foreach ($resources as $res) { if ($res instanceof File) continue; $url = $res->getUrl(); if (!empty($res->hide) || !$url) continue; if (!$single) { return $url; } else { $cnt++; $single_url = $url; } } if ($single && ($cnt == 1)) return $single_url; return $default; } protected function getConfiguredRedirectLogout() { switch ($this->getDi()->config->get('protect.php_include.redirect_logout', 'home')) { case 'url': $url = $this->getDi()->config->get('protect.php_include.redirect'); break; case 'referer': $url = isset($_SERVER['HTTP_REFERER']) ? $this->getRedirectUrl($_SERVER['HTTP_REFERER']) : '/'; break; case 'home': default: $url = '/'; } return $url ? $url : '/'; } public function getOkUrl() { $event = new Am_Event(Am_Event::AUTH_GET_OK_REDIRECT, array( 'user' => $this->getDi()->user )); $event->setReturn($this->getConfiguredRedirect()); $this->getDi()->hook->call($event); return get_first($this->redirect_url, $event->getReturn()); } public function indexAction() { if ($this->getAuth()->getUsername()) $this->getDi()->hook->call(new Am_Event_AuthSessionRefresh($this->getAuth()->getUser())); $this->getAuth()->plaintextPass = $this->getPass(); if (!$this->getAuth()->getUserId() && !$this->isPost()) { if ($this->getAuth()->checkExternalLogin($this->getRequest())) return $this->onLogin(self::EXTERNAL); } parent::indexAction(); } public function doLogin(Am_Auth_Abstract $auth, Am_Mvc_Request $r) { $result = parent::doLogin($auth, $r); if ($result->getCode() == Am_Auth_Result::USER_NOT_FOUND) { $event = new Am_Event_AuthTryLogin($this->getLogin(), $this->getPass()); $this->getDi()->hook->call($event); if ($event->isCreated()) // user created, try again! $result = parent::doLogin($auth, $r); } return $result; } public function onLogin($source = self::NORMAL) { $user = $this->getAuth()->getUser(); if ($source == self::NORMAL && $this->remember_login) if ($this->remember_auto || $this->getInt('remember_login')) { Am_Cookie::set('amember_ru', $user->login, $this->getDi()->time + $this->getDi()->config->get($this->configBase . '.remember_period', 60) * 3600 * 24, '/', $this->getDi()->request->getHttpHost(), false, false, true); Am_Cookie::set('amember_rp', $user->getLoginCookie(), $this->getDi()->time + $this->getDi()->config->get($this->configBase . '.remember_period', 60) * 3600 * 24, '/', $this->getDi()->request->getHttpHost(), false, false, true); } return parent::onLogin(); } public function logoutAction() { Am_Cookie::set('amember_ru', null, $this->getDi()->time - 100 * 3600 * 24,'/', $this->getDi()->request->getHttpHost()); Am_Cookie::set('amember_rp', null, $this->getDi()->time - 100 * 3600 * 24,'/', $this->getDi()->request->getHttpHost()); parent::logoutAction(); } /** @return string url to login page */ public function findLoginUrl() { return $this->getDi()->url('login',null,false); } public function renderLoginForm($authResult) { $loginUrl = $this->findLoginUrl(); $this->view->assign('form_action', $loginUrl); $this->view->assign('this_config', $this->getDi()->config->get($this->configBase)); return $this->view->render('_login-form.phtml'); } public function renderLoginPage($html) { $this->view->content = $html; if ($this->_request->isXmlHttpRequest()) { return $this->view->render('_login.phtml'); } $this->view->content = $this->view->render('_login.phtml'); return $this->view->render('login.phtml'); } protected function createAdapter() { return new Am_Auth_Adapter_Password( $this->getLogin(), $this->getPass(), $this->getDi()->userTable, $this->getDi()->config->get('allow_auth_by_savedpass')); } public function setRedirectUrl($url) { if ($url = $this->getRedirectUrl($url)) $this->redirect_url = $url; } protected function getRedirectUrl($url) { $redirect_url = parse_url($url); if (!is_array($redirect_url)) return; if (isset($redirect_url['scheme']) && !in_array($redirect_url['scheme'], array('http', 'https'))) { return; } if (array_key_exists('host', $redirect_url) && !$this->getDi()->config->get('other_domains_redirect')) { $match = false; foreach (array(ROOT_URL, ROOT_SURL) as $u) { $amember_url = parse_url($u); if (Am_License::getMinDomain($amember_url['host']) == Am_License::getMinDomain($redirect_url['host'])) $match = true; } } else { $match = true; } if ($match) return $url; } public function redirectOk() { if ($this->_request->isXmlHttpRequest()) { return $this->_response->ajaxResponse(array('ok' => true, 'url' => $this->getOkUrl())); } return parent::redirectOk(); } }PK\Pff8default/controllers/AdminProductCategoriesController.phpnu[hasPermission('grid_product'); } protected function getTable() { return $this->getDi()->productCategoryTable; } protected function getNote() { return ___('aMember does not respect category hierarchy. Each category is absolutely independent. You can use hierarchy only to organize your categories.'); } protected function getTitle() { return ___('Product Categories'); } } PK\㬜:default/controllers/AdminEmailTemplateLayoutController.phpnu[hasPermission(Am_Auth_Admin::PERM_SETUP); } public function createGrid() { $ds = new Am_Query($this->getDi()->emailTemplateLayoutTable); $grid = new Am_Grid_Editable('_etl', ___('Email Template Layouts'), $ds, $this->_request, $this->view); $grid->addField(new Am_Grid_Field('name', ___('Title'))) ->setRenderFunction(array($this, 'renderTitle')); $grid->setForm(array($this, 'createForm')); $grid->setRecordTitle(___('Layout')); $grid->actionGet('delete') ->setIsAvailableCallback(function($r) {return $r->pk()>AdminEmailTemplateLayoutController::DEFAULT_LAYOUT_THRESHOLD;}); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, function(&$v, $r) { if (!$r->isLoaded() && empty($v['layout'])) { $v['layout'] = '%content%'; } }); return $grid; } public function createForm($grid) { $form = new Am_Form_Admin(); $name = $form->addText('name', array('class' => 'el-wide')) ->setLabel(___('Title')); $r = $grid->getRecord(); if ($r->isLoaded() && $r->pk() < self::DEFAULT_LAYOUT_THRESHOLD) { $name->persistentFreeze(true); $name->toggleFrozen('true'); } else { $name->addRule('required'); } $form->addTextarea('layout', array('rows' => 25, 'class' => 'row-wide el-wide')) ->setLabel(___("Layout\n" . "use placholder %content% for email output")) ->addRule('callback', ___('Your layout has not %content% placeholder'), array($this, 'checkLayout')); return $form; } public function renderTitle($r) { $tpl = $r->pk() > self::DEFAULT_LAYOUT_THRESHOLD ? '%s' : '%s'; return sprintf($tpl, $this->escape($r->name)); } public function checkLayout($c) { return !(strpos($c, '%content%') === false); } }PK\qUb%b%.default/controllers/AdminReportsController.phpnu[hasPermission(Am_Auth_Admin::PERM_REPORT); } public function saveAction() { $savedReport = $this->getDi()->savedReportRecord; $savedReport->setForInsert(array( 'request' => $this->getRequest()->getParam('request'), 'title' => $this->getRequest()->getParam('title'), 'report_id' => $this->getRequest()->getParam('report_id'), 'admin_id' => $this->getDi()->authAdmin->getUser()->pk())); $savedReport->save(); if ($this->getRequest()->getParam('add-to-dashboard')) { $pref_default = array( 'top' => array(), 'bottom' => array(), 'main' => array('users'), 'aside' => array('sales') ); $pref = $this->getDi()->authAdmin->getUser()->getPref(Admin::PREF_DASHBOARD_WIDGETS); $pref = is_null($pref) ? $pref_default : $pref; $pref['main'][] = 'saved-report-' . $savedReport->pk(); $this->getDi()->authAdmin->getUser()->setPref(Admin::PREF_DASHBOARD_WIDGETS, $pref); } $this->_response->ajaxResponse(array( 'status' => 'OK' )); } function runAction() { if (!$this->_request->isPost()) { throw new Am_Exception_InputError('Only POST accepted'); } if (!$reportId = $this->getFiltered('report_id')) { throw new Am_Exception_InternalError("Empty report id passed"); } $r = Am_Report_Abstract::createById($reportId); $r->applyConfigForm($this->_request); $this->view->form = $r->getForm(); $this->view->report = $r; $this->view->content = ''; if (!$r->hasConfigErrors()) { $this->view->serializedRequest = serialize($this->_request->toArray()); $this->view->reportId = $reportId; $this->view->saveReportForm = $this->createSaveReportForm($r->getTitle()); $result = $r->getReport(); foreach ($r->getOutput($result) as $output) $this->view->content .= $output->render(); // default $default = $r->getForm()->getValue(); unset($default['_save_']); unset($default['save']); $this->getSession()->reportDefaults = $default; } $this->view->display('admin/report_output.phtml'); } function indexAction() { $reports = Am_Report_Abstract::getAvailableReports(); $defaults = @$this->getSession()->reportDefaults; if ($defaults) { foreach ($reports as $r) { $r->getForm()->setDataSources(array(new HTML_QuickForm2_DataSource_Array($defaults))); } } $this->view->assign('reports', $reports); $this->view->display('admin/report.phtml'); } function getformAction() { $id = $this->getParam('id'); foreach (Am_Report_Abstract::getAvailableReports() as $r) { if ($r->getId() == $id) { $title = $this->escape($r->getTitle()); $form = $r->getForm(); echo <<$title $form CUT; throw new Am_Exception_Redirect; } } throw new Am_Exception_InputError(sprintf('Can not find report with id [%s]', $id)); } function savefrequencyAction() { if ($this->getRequest()->isPost()) { $this->getDi()->authAdmin->getUser()->setPref(Admin::PREF_REPORTS_SEND_FREQUENCY, $this->getRequest()->getParam('fr')); } } function createSaveReportForm($title) { $form = new Am_Form_Admin(); $form->addText('title', array('class' => 'el-wide')) ->setLabel(___('Title of Report for your Reference')) ->setValue($title) ->addRule('required'); $form->addAdvCheckbox('add-to-dashboard', null, array( 'content' => ___('Add Report to My Dashboard'))) ->setValue(1); return $form; } } class AdminReportsController_Saved extends Am_Mvc_Controller_Grid { protected $layout = null; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_REPORT); } function createGrid() { $ds = new Am_Query($this->getDi()->savedReportTable); $ds->addWhere('admin_id=?', $this->getDi()->authAdmin->getUserId()); $grid = new Am_Grid_Editable('_report', ___('Saved Reports'), $ds, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_REPORT); $grid->setEventId('gridSavedReport'); $grid->addField(new Am_Grid_Field('title', ___('Title'), true)); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_LiveEdit('title')); $grid->actionAdd(new Am_Grid_Action_Url('run-report', ___('Run Report'), '__ROOT__/default/admin-reports/p/saved/runsaved/report_id/__ID__'))->setTarget('_top'); $grid->actionAdd(new Am_Grid_Action_Delete()); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, array($this, 'onRenderGridContent')); return $grid; } function runsavedAction() { if (!$reportId = $this->getFiltered('report_id')) { throw new Am_Exception_InternalError('Empty report id passed'); } $report = $this->getDi()->savedReportTable->load($reportId); if ($report->admin_id != $this->getDi()->authAdmin->getUserId()) { throw new Am_Exception_AccessDenied(); } $r = Am_Report_Abstract::createById($report->report_id); $r->applyConfigForm(new Am_Mvc_Request(unserialize($report->request))); $result = $r->getReport(); $content = ''; foreach ($r->getOutput($result) as $output) { $content .= $output->render() . "

      "; } $this->view->enableReports(); echo sprintf('

      %s

      %s', $this->escape($report->title), $content); } function onRenderGridContent(& $out) { $email = $this->escape($this->getDi()->authAdmin->getUser()->email); $txt = $this->escape(___('Send reports to my email')); $options = array( '' => ___('Never'), Am_Event::DAILY => ___('Daily'), Am_Event::WEEKLY => ___('Weekly'), Am_Event::MONTHLY => ___('Monthly') ); $optionsHtml = Am_Html::renderOptions($options, $this->getDi()->authAdmin->getUser()->getPref(Admin::PREF_REPORTS_SEND_FREQUENCY)); $html = << $txt ($email) CUT; $out .= $html; } } class AdminReportsController extends Am_Mvc_Controller_Pages { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_REPORT); } public function preDispatch() { class_exists('Am_Report', true); class_exists('Am_Report_Standard', true); } public function initPages() { $this->addPage(array($this, 'createIndexController'), 'index', ___('Reports')) ->addPage(array($this, 'createSavedController'), 'saved', ___('Saved Reports')); } public function createIndexController($id, $title, Am_Mvc_Controller $controller) { return new AdminReportsController_Index($controller->getRequest(), $controller->getResponse(), $this->_invokeArgs); } public function createSavedController($id, $title, Am_Mvc_Controller $controller) { return new AdminReportsController_Saved($controller->getRequest(), $controller->getResponse(), $this->_invokeArgs); } public function exportAction() { $reportId = $this->getFiltered('report_id'); $request = unserialize($this->getParam('request')); $r = Am_Report_Abstract::createById($reportId); $r->applyConfigForm(new Am_Mvc_Request($request)); $result = $r->getReport(); $dat = date('YmdHis'); $output = new Am_Report_Csv($result); $data = $output->render(); $this->_helper->sendFile->sendData($data, 'text/csv', "amember_reports-{$reportId}-{$dat}.csv"); throw new Am_Exception_Redirect; } }PK\i-default/controllers/AdminAdminsController.phpnu[isSuper(); } public function createGrid() { $ds = new Am_Query($this->getDi()->adminTable); $grid = new Am_Grid_Editable('_admin', ___('Admin Accounts'), $ds, $this->_request, $this->view); $grid->setRecordTitle(array($this, 'getRecordTitle')); $grid->setEventId('gridAdmin'); $grid->addField(new Am_Grid_Field('admin_id', '#', true, '', null, '1%')); $grid->addField(new Am_Grid_Field('login', ___('Username'), true)); $grid->addField(new Am_Grid_Field('email', ___('E-Mail'), true)); $grid->addField(new Am_Grid_Field('super_user', ___('Super Admin'), true)) ->setRenderFunction('$v->super_user?___("Yes"):___("No")'); $grid->addField(new Am_Grid_Field('last_login', ___('Last login'), true)) ->setRenderFunction(array($this, 'renderLoginAt')); $grid->setForm(array($this, 'createForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_FROM_FORM, array($this, 'valuesFromForm')); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_SAVE, array($this, 'beforeSave')); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_DELETE, array($this, 'beforeDelete')); return $grid; } public function getRecordTitle(Admin $user = null) { return $user ? sprintf('%s (%s)', ___('Admin'), $user->login) : ___('Admin'); } public function checkSelfPassword($pass) { return $this->getDi()->authAdmin->getUser()->checkPassword($pass); } public function createForm() { $mainForm = new Am_Form_Admin(); $form = $mainForm->addFieldset()->setLabel(___('Admin Settings')); $login = $form->addText('login') ->setLabel(___('Admin Username')); $login->addRule('required') ->addRule('length', ___('Length of username must be from %d to %d', 4, 16), array(4,16)) ->addRule('regex', ___('Admin username must be alphanumeric in small caps'), '/^[a-z][a-z0-9_-]+$/') ->addRule('callback2', '-error-', array($this, 'checkUniqLogin')); $set = $form->addGroup()->setLabel(___('First and Last Name')); $set->setSeparator(' '); $set->addText('name_f'); $set->addText('name_l'); $pass = $form->addPassword('_passwd') ->setLabel(___('New Password')); $pass->addRule('length', ___('Length of admin password must be from %d to %d', 6, 16), array(6,16)); $pass->addRule('neq', ___('Password must not be equal to username'), $login); $pass0 = $form->addPassword('_passwd0') ->setLabel(___('Confirm New Password')); $pass0->addRule('eq', ___('Passwords must be the same'), $pass); $form->addText('email') ->setLabel(___('E-Mail Address')) ->addRule('required') ->addRule('callback2', '-error-', array($this, 'checkUniqEmail'));; $super = $form->addAdvCheckbox('super_user') ->setId('super-user') ->setLabel(___('Super Admin')); //Only Super Admin has access to this page $record = $this->grid->getRecord(); if ($this->getDi()->authAdmin->getUserId() == $record->get('admin_id')) $super->toggleFrozen(true); if ($this->getDi()->authAdmin->getUserId() != $record->get('admin_id')) { $group = $form->addGroup('perms') ->setId('perms') ->setLabel(___('Permissions'))->setSeparator('
      '); foreach ($this->getDi()->authAdmin->getPermissionsList() as $perm => $title) { if (is_string($title)) $group->addCheckbox($perm)->setContent($title); else { $gr = $group->addGroup($perm); $gr->addStatic()->setContent('
      '); $gr->addStatic()->setContent('' . $title['__label'] . ''); $gr->addStatic()->setContent('
      '); unset($title['__label']); foreach ($title as $k => $v) { $gr->addCheckbox($k)->setContent($v); $gr->addStatic()->setContent(' '); } $gr->addStatic()->setContent('
      '); $gr->addStatic()->setContent('
      '); } } $mainForm->addScript() ->setScript(<<addFieldset() ->setLabel(___('Authentication')) ->addPassword('self_password') ->setLabel(___("Your Password\n". "enter your current password\n". "in order to edit admin record")); $self_password->addRule('callback', ___('Wrong password'), array($this, 'checkSelfPassword')); return $mainForm; } function checkUniqLogin($login) { $r = $this->grid->getRecord(); if(!$r->isLoaded() || (strcasecmp($r->login, $login)!==0)) { if ($this->getDi()->adminTable->findFirstByLogin($login)) return ___('Username %s is already taken. Please choose another username', Am_Html::escape($login)); } } function checkUniqEmail($email) { $r = $this->grid->getRecord(); if(!$r->isLoaded() || (strcasecmp($r->email, $email)!==0)) { if ($this->getDi()->adminTable->findFirstByEmail($email)) return ___('An Admin Account with the same email already exists.'); } } function renderLoginAt(Admin $a) { return $this->renderTd($a->last_login ? $a->last_ip . ___(' at ') . amDatetime($a->last_login) : null); } function valuesToForm(& $values, Admin $record) { $values['perms'] = $record->getPermissions(); } function valuesFromForm(& $values, Admin $record) { $values['perms'] || ($values['perms'] = array()); $record->setPermissions($values['perms']); unset($values['perms']); } public function beforeSave(array & $values, $record) { check_demo(); unset($values['self_password']); if (!$values['super_user']) { $values['super_user'] = 0; } if (!empty($values['_passwd'])) $record->setPass($values['_passwd']); } public function beforeDelete($record) { if ($this->getDi()->authAdmin->getUserId() == $record->admin_id) throw new Am_Exception_InputError(___('You can not delete your own account')); } }PK\_w-rOrO5default/controllers/AdminEmailTemplatesController.phpnu[hasPermission(Am_Auth_Admin::PERM_EMAIL); } public function deleteAction() { $this->getDi()->emailTemplateTable->load($this->getParam('id'))->delete(); if (!$this->isAjax()) { $this->_redirect($this->getParam('b'), array('prependBase' => false)); } } public function editAction() { if (!$this->getParam('name')) throw new Am_Exception_InputError(___('Name of template is undefined')); $form = $this->createForm($this->getParam('name'), $this->getParam('label')); $tpl = $this->getTpl($this->getParam('copy_from', null)); if (!$form->isSubmitted()) { $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array( array( 'attachments' => $this->prepareAttachments($tpl->attachments, true), 'conditions' => $this->prepareAttachments($tpl->conditions, true), 'days' => $this->prepareAttachments($tpl->days, true), '_admins' => $tpl->recipient_admins ? explode(',', $tpl->recipient_admins) : array(-1), ) + $tpl->toArray() ) )); } if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); unset($vars['label']); if (!$vars['email_template_layout_id']) { $vars['email_template_layout_id'] = null; } $tpl->isLoaded() ? $tpl->setForUpdate($vars) : $tpl->setForInsert($vars); $tpl->conditions = $this->prepareAttachments($vars['conditions']); $tpl->attachments = $this->prepareAttachments($vars['attachments']); $tpl->recipient_admins = implode(',', isset($vars['_admins']) ? $vars['_admins'] : array()); $tpl->save(); } else { echo $this->createActionsForm($tpl) . "\n" . $form . "\n" . $this->getJs(!$tpl->isLoaded()); } } public function pendingNotificationRuleAction() { $form = $this->createPendingNotificationRulesForm($this->getParam('name'), $this->getParam('label')); if ($id = $this->getParam('id')) { $form->addHidden('id') ->setValue($id); $tpl = $this->getDi()->emailTemplateTable->load($id); } else { $tpl = $this->getDi()->emailTemplateRecord; $tpl->setForInsert($this->getDefaultNotificationTemplate($this->getParam('name'))); } if (!$form->isSubmitted()) { $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array( array( 'attachments' => $this->prepareAttachments($tpl->attachments, true), 'conditions' => $this->prepareAttachments($tpl->conditions, true), 'days' => $this->prepareAttachments($tpl->days, true), '_admins' => $tpl->recipient_admins ? explode(',', $tpl->recipient_admins) : array(-1), ) + $tpl->toArray() ) )); } if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); unset($vars['label']); if (!$vars['email_template_layout_id']) { $vars['email_template_layout_id'] = null; } $tpl->isLoaded() ? $tpl->setForUpdate($vars) : $tpl->setForInsert($vars); $tpl->conditions = $this->prepareAttachments($vars['conditions']); $tpl->attachments = $this->prepareAttachments($vars['attachments']); $this->sortDays($vars['days']); $tpl->days = $this->prepareAttachments($vars['days']); $tpl->recipient_admins = implode(',', isset($vars['_admins']) ? $vars['_admins'] : array()); $tpl->save(); $el = new Am_Form_Element_PendingNotificationRules($tpl->name); $el->setLabel($this->getParam('label')); $this->_response->ajaxResponse(array( 'content' => (string) $el )); } else { echo $form; } } public function exportAction() { $this->_helper->sendFile->sendData( $this->getDi()->emailTemplateTable->exportReturnXml(array('email_template_id')), 'text/xml', 'amember-email-templates-' . $this->getDi()->sqlDate . '.xml'); } public function importAction() { $form = new Am_Form_Admin; $import = $form->addFile('import') ->setLabel(___('Upload file [email-templates.xml]')); $form->addStatic('')->setContent(___('WARNING! All existing e-mail templates will be removed from database!')); //$import->addRule('required', 'Please upload file'); //$form->addAdvCheckbox('remove')->setLabel('Remove your existing templates?'); $form->addSaveButton(___('Upload')); if ($form->isSubmitted() && $form->validate()) { $value = $form->getValue(); $fn = $this->getDi()->data_dir . '/import.email-templates.xml'; if (!move_uploaded_file($value['import']['tmp_name'], $fn)) throw new Am_Exception_InternalError(___('Could not move uploaded file')); $xml = file_get_contents($fn); if (!$xml) throw new Am_Exception_InputError(___('Could not read XML')); $count = $this->getDi()->emailTemplateTable->deleteBy(array())->importXml($xml); $this->view->content = ___('Import Finished. %d templates imported.', $count); } else { $this->view->content = (string) $form; } $this->view->title = ___('Import E-Mail Templates from XML file'); $this->view->display('admin/layout.phtml'); } protected function getNumberString($i) { switch ($i) { case 2 : return $i . 'nd'; break; case 3 : return $i . 'rd'; break; default : return $i . 'th'; } } protected function getDayOptions() { $options = array( '0' => ___('Immediately'), ___('Hours') => array( '1h' => ___('Next Hour') ), ___('Days') => array( '1' => ___('Next Day') ) ); for ($i = 2; $i <= 6; $i++) $options[___('Hours')][$i . 'h'] = $this->getNumberString($i) . ___(' hour'); for ($i = 2; $i <= 40; $i++) $options[___('Days')][$i] = $this->getNumberString($i) . ___(' day'); return $options; } protected function getAdminOptions() { $op = array( '-1' => sprintf('%s <%s>', $this->getDi()->config->get('site_title') . ' Admin', $this->getDi()->config->get('admin_email')) ); foreach ($this->getDi()->adminTable->findBy() as $admin) { $op["{$admin->pk()}"] = sprintf('%s <%s>', $admin->getName(), $admin->email); } $op = array_map(array($this, 'escape'), $op); return $op; } protected function getConditionOptions() { $paysys_options = array(); foreach ($this->getDi()->paysystemList->getAllPublic() as $ps) { $paysys_options['PAYSYSTEM-' . $ps->getId()] = ___('Payment System: ') . Am_Html::escape(___($ps->getTitle())); } $product_options = array(); foreach (Am_Di::getInstance()->productTable->getOptions() as $id => $title) { $product_options['PRODUCT-' . $id] = ___('Product: ') . Am_Html::escape(___($title)); } $group_options = array(); foreach (Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions() as $id => $title) { $group_options['CATEGORY-' . $id] = ___('Product Category: ') . Am_Html::escape(___($title)); } $options = array( ___('Payment System') => $paysys_options, ___('Products') => $product_options ); if (count($group_options)) { $options[___('Product Categories')] = $group_options; } return $options; } protected function getTpl($copy_from = null) { if ($copy_from) return $this->getCopiedTpl($copy_from); $tpl = $this->getDi()->emailTemplateTable->getExact( $this->getParam('name'), $this->getParam('lang', $this->getDefaultLang()), $this->getParam('day', null) ); if (!$tpl) { $tpl = $this->getDi()->emailTemplateRecord; $tpl->name = $this->getParam('name'); $tpl->lang = $this->getParam('lang', $this->getDefaultLang()); $tpl->subject = $this->getParam('name'); $tpl->day = $this->getParam('day', null); $tpl->format = 'text'; $tpl->plain_txt = null; $tpl->txt = null; $tpl->attachments = null; } return $tpl; } protected function getCopiedTpl($copy_from) { $sourceTpl = $this->getDi()->emailTemplateTable->getExact( $this->getParam('name'), $copy_from ); if (!$sourceTpl) { throw new Am_Exception_InputError(___('Trying to copy from unexisting template : %s', $copy_from)); } $sourceTpl->lang = $this->getParam('lang', $this->getDefaultLang()); return $sourceTpl; } protected function createForm($name, $label) { $form = new Am_Form_Admin('EmailTemplate'); $form->addHtml('info') ->setLabel(___('Template')) ->setHtml( sprintf('
      %s
      %s
      ', $this->escape($name), $this->escape($label))); $form->addHidden('name'); $langOptions = $this->getLanguageOptions( $this->getDi()->config->get('lang.enabled', array($this->getDi()->config->get('lang.default', 'en'))) ); $lang = $form->addSelect('lang') ->setId('lang') ->setLabel(___('Language')) ->loadOptions($langOptions); if (count($langOptions) == 1) $lang->toggleFrozen(true); $lang->addRule('required'); if ($options = $this->getDi()->emailTemplateLayoutTable->getOptions()) { $form->addSelect('email_template_layout_id') ->setLabel(___('Layout')) ->loadOptions(array(''=>___('No Layout')) + $options); } $tt = Am_Mail_TemplateTypes::getInstance()->find($name); if($tt && !empty($tt['isAdmin'])) { $form->addMagicSelect('_admins') ->setLabel(___('Admin Recipients')) ->loadOptions($this->getAdminOptions()) ->addRule('required'); } else { $form->addText('bcc', array('class' => 'el-wide', 'placeholder' => ___('Email Addresses Separated by Comma'))) ->setLabel(___("BCC\n" . "blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients")) ->addRule('callback', ___('Please enter valid e-mail addresses'), array('Am_Validate', 'emails')); } $form->addElement(new Am_Form_Element_MailEditor($name)); $form->addHidden('label') ->setValue($label); return $form; } protected function createActionsForm(EmailTemplate $tpl) { $form = new Am_Form_Admin('EmailTemplate_Actions'); $form->addHidden('name') ->setValue($tpl->name); $langOptions = $this->getLanguageOptions( $this->getDi()->emailTemplateTable->getLanguages( $tpl->name, null, $tpl->lang ) ); if (count($langOptions)) { $lang_from = $form->addSelect('copy_from') ->setId('another_lang') ->setLabel(___('Copy from another language')) ->loadOptions(array('0' => '--' . ___('Please choose') . ' --') + $langOptions) ->setValue(0); } if (isset($tpl->lang) && $tpl->lang) { $form->addHidden('lang') ->setValue($tpl->lang); } $form->addHidden('label') ->setValue($this->getParam('label')); //we do not show action's form if there is not any avalable action if (!count($langOptions)) { $form = null; } return $form; } protected function createPendingNotificationRulesForm($name, $label) { $form = new Am_Form_Admin('EmailTemplate'); $form->addHtml('info') ->setLabel(___('Template')) ->setHtml( sprintf('
      %s
      %s
      ', $this->escape($name), $this->escape($label))); if ($options = $this->getDi()->emailTemplateLayoutTable->getOptions()) { $form->addSelect('email_template_layout_id') ->setLabel(___('Layout')) ->loadOptions(array(''=>___('No Layout')) + $options); } $tt = Am_Mail_TemplateTypes::getInstance()->find($name); if($tt && !empty($tt['isAdmin'])) { $form->addMagicSelect('_admins') ->setLabel(___('Admin Recipients')) ->loadOptions($this->getAdminOptions()) ->setId('_admins') ->addRule('required'); } else { $form->addText('bcc', array('class' => 'el-wide', 'placeholder' => ___('Email Addresses Separated by Comma'))) ->setLabel(___("BCC\n" . "blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients")) ->addRule('callback', ___('Please enter valid e-mail addresses'), array('Am_Validate', 'emails')); } $form->addHidden('name'); $form->addMagicSelect('days') ->setLabel(___('Days to Send')) ->loadOptions($this->getDayOptions()); $form->addMagicSelect('conditions') ->setLabel(___('Optional Conditions') . "\n" . ___('notification will be sent in case of one of selected products exits in invoice or one of selected payment system was used for invoice')) ->loadOptions($this->getConditionOptions()); $form->addElement(new Am_Form_Element_MailEditor($name, array('upload-prefix'=>'email-pending'))); $form->addHidden('label') ->setValue($label); return $form; } protected function sortDays(& $days) { usort($days, function($el1, $el2) { if ($el1 && substr($el1, -1) != 'h') $el1 = 'z' . $el1; if ($el2 && substr($el2, -1) != 'h') $el2 = 'z' . $el2; return strcmp($el1, $el2); }); } protected function prepareAttachments($att, $isReverse = false) { if ($isReverse) { $att = (!($att == '' || is_null($att)) ? explode(',', $att) : array()); $att = array_filter($att, function($el) {return $el != -1;}); return $att; } else { if (is_array($att)) { $att = array_filter($att, function($el) {return $el != -1;}); } return ((is_array($att) && $att) ? implode(',', $att) : null); } } protected function getLanguageOptions($languageCodes) { $languageNames = $this->getDi()->languagesListUser; $options = array(); foreach ($languageCodes as $k) { list($k, ) = explode('_', $k); $options[$k] = "[$k] " . $languageNames[$k]; } return $options; } protected function getDefaultLang() { list($k, ) = explode('_', $this->getDi()->app->getDefaultLocale()); return $k; } protected function getDefaultNotificationTemplate($name) { switch ($name) { case 'pending_to_user' : $txt = << %invoice_text% CUT; break; default: $txt = ''; } return array( 'email_template_layout_id' => $name == 'pending_to_user' ? 1 : 2, 'subject' => '%site_title%: Pending Payment', 'txt' => $txt, 'format' => 'text', 'attachments' => null, 'conditions' => null, 'days' => null, 'recipient_admins' => null ); } protected function getJs($showOffer = false) { $offerText = json_encode((nl2br(___("This email template is empty in given language.\n" . "Press [Copy] to copy template from default language [English]\n" . "Press [Skip] to type it manually from scratch.")))); $copy = ___("Copy"); $skip = ___("Skip"); if ($showOffer) { $jsOffer = <<
      '); div.append($offerText+"
      ") jQuery('body').append(div); div.dialog({ autoOpen: true, modal : true, title : "", width : 350, position : ['center', 'center'], buttons: { "$copy" : function() { jQuery("#another_lang").val('en'); jQuery("#another_lang").closest('form').ajaxSubmit({ success : function(data) { jQuery('#email-template-popup').empty().append(data); } }); jQuery(this).dialog("close"); }, "$skip" : function() { jQuery(this).dialog("close"); } }, close : function() { div.remove(); } }); CUT; } else { $jsOffer = ''; } return << (function($){ setTimeout(function(){ jQuery("#lang").change(function(){ var importantVars = new Array( 'lang', 'name', 'label' ); jQuery.each(this.form, function() { if (jQuery.inArray(this.name, importantVars) == -1) { if (this.name == 'format') { this.selectedIndex = null; } else { this.value=''; } } }) jQuery(this.form).ajaxSubmit({ success : function(data) { jQuery('#email-template-popup').empty().append(data); } }); }); jQuery("#another_lang").change(function(){ if (this.selectedIndex == 0) return; jQuery(this.form).ajaxSubmit({ success : function(data) { jQuery('#email-template-popup').empty().append(data); } }); }); $jsOffer }, 100); })(jQuery) CUT; } }PK\sK-default/controllers/AdminStatesController.phpnu[country = preg_replace("[^A_Z]", '', $this->_request->country); if (!$this->country) throw new Am_Exception_InputError("country is empty in " . get_class($this)); $this->setActiveMenu('countries'); return parent::preDispatch(); } public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_COUNTRY_STATE); } function createForm() { $form = new Am_Form_Admin; $form->addInteger("tag")->setLabel(___("Sort order"))->addRule('required'); $form->addAdvCheckbox('_is_disabled')->setLabel(___('Is Disabled?')); $form->addText('title')->setLabel(___('Title'))->addRule('required'); if (!$this->grid->getRecord()->pk()) { $gr = $form->addGroup(); $gr->addStatic()->setContent(''.$this->country.'-'); $gr->addText('state',array('size'=>5))->addRule('required'); $gr->setLabel(___('Code')); } $form->addHidden('country'); return $form; } function valuesToForm(& $values, State $record) { if($record->pk() && $record->tag<0) { $values['_is_disabled'] = 1; $values['tag']*=-1; } else { $values['_is_disabled'] = 0; } } function valuesFromForm(& $values, State $record) { if($values['_is_disabled']) { $values['tag'] = ($values['tag'] ? $values['tag']*-1 : -1); } if(!$record->pk()) { $values['state'] = $this->country.'-'.$values['state']; } } public function getTrAttribs(& $ret, $record) { if ($record->tag < 0) { $ret['class'] = isset($ret['class']) ? $ret['class'] . ' disabled' : 'disabled'; } } public function createGrid() { $ds = new Am_Query($this->getDi()->stateTable); $ds->addWhere('t.country=?', $this->country) ->addField('ABS(tag)', 'tag_abs') ->setOrderRaw('tag_abs desc, title'); $grid = new Am_Grid_Editable('_s', ___("Browse States"), $ds, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_COUNTRY_STATE); $grid->addField(new Am_Grid_Field('tag_abs', ___('Sort Order'), true, null, null, '10%')); $grid->addField(new Am_Grid_Field('title', ___('Title'), true)); $grid->addField(new Am_Grid_Field('state', ___('Code'), true)); $grid->addField(new Am_Grid_Field('country', ___('Country'), true)); $grid->setForm(array($this, 'createForm')); $grid->actionDelete('delete'); $grid->addCallback(Am_Grid_ReadOnly::CB_TR_ATTRIBS, array($this,'getTrAttribs')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_FROM_FORM, array($this, 'valuesFromForm')); $grid->actionAdd(new Am_Grid_Action_LiveEdit('title')); $grid->actionAdd(new Am_Grid_Action_Group_CountryStateEnable(false)); $grid->actionAdd(new Am_Grid_Action_Group_CountryStateEnable(true)); $grid->setFilter(new Am_Grid_Filter_CountryState(' ', array('title' => 'LIKE'), array('placeholder' => ___('State Title')))); $grid->actionAdd(new Am_Grid_Action_Url('back', ___("Back to Countries"), $this->getDi()->url('admin-countries',null,false))) ->setType(Am_Grid_Action_Abstract::NORECORD) ->setCssClass('link') ->setTarget('_top'); return $grid; } }PK\"Sdd(default/controllers/CancelController.phpnu[view->invoice = null; $this->view->id = null; $this->view->paysystems = array(); $this->invoice = $this->getDi()->invoiceTable->findBySecureId($this->getFiltered('id'), "CANCEL"); if ($this->invoice) { if ($this->invoice->isPaid()) throw new Am_Exception_InputError("Invoice #$id is already paid"); $this->getDi()->plugins_payment->loadEnabled(); $this->view->paysystems = $this->getDi()->paysystemList->getAllPublicAsArrays(); $this->view->invoice = $this->invoice; $this->view->id = $this->getFiltered('id'); } } function repeatAction() { if (!$this->invoice) throw new Am_Exception_InputError('No invoice found, cannot repeat'); if ($this->invoice->isPaid()) throw new Am_Exception_InputError("Invoice #$id is already paid"); $found = false; foreach ($this->view->paysystems as $ps) if ($ps['paysys_id'] == $this->getFiltered('paysys_id')) { $found = true; break; } if (!$found) return $this->indexAction(); $this->invoice->updateQuick('paysys_id', $this->getFiltered('paysys_id')); if ($err = $this->invoice->validate()) throw new Am_Exception_InputError($err[0]); $payProcess = new Am_Paysystem_PayProcessMediator($this, $this->invoice); $result = $payProcess->process(); if ($result->isFailure()) { $this->view->error = $result->getErrorMessages(); return $this->indexAction(); } } function indexAction() { $form = new Am_Form(); $form->setAction($this->getDi()->url('cancel/repeat',null,false)); $psOptions = array(); foreach ($this->getDi()->paysystemList->getAllPublic() as $ps) { $psOptions[$ps->getId()] = $this->renderPaysys($ps); } if ($this->invoice) { try{ $pl = $this->getDi()->plugins_payment->loadGet($this->invoice->paysys_id); if($pl->supportsCancelPage() && ($cancel_list = $pl->getConfig('cancel_paysys_list'))) { $psOptions = array_intersect_key($psOptions, array_flip($cancel_list)); } } catch (Exception $ex) { //continue } } $paysys = $form->addAdvRadio('paysys_id') ->setLabel(___('Payment System')) ->loadOptions($psOptions); $paysys->addRule('required', ___('Please choose a payment system')); if (count($psOptions) == 1) { $paysys->setValue(key($psOptions)); $paysys->toggleFrozen(true); } $form->addHidden('id') ->setValue($this->getFiltered('id')); $form->addSaveButton(___('Make Payment')); $this->view->form = $form; $this->view->display('cancel.phtml'); } protected function renderPaysys(Am_Paysystem_Description $p) { return sprintf('%s %s', $p->getTitle(), $p->getDescription()); } }PK\z"!  %default/controllers/PayController.phpnu[getDi()->invoiceTable->findBySecureId($this->getParam('secure_id'), 'payment-link'); if (!$invoice || ($invoice->status != Invoice::PENDING)) throw new Am_Exception_InternalError( sprintf('Unknow invoice [%s] or invoice is already processed', filterId($this->getParam('secure_id')))); if (!$invoice->due_date && (sqlDate($invoice->tm_added) < sqlDate("-" . Invoice::DEFAULT_DUE_PERIOD . " days"))) throw new Am_Exception_InputError(___('Invoice is expired')); elseif ($invoice->due_date && ($invoice->due_date < sqlDate('now'))) throw new Am_Exception_InputError(___('Invoice is expired')); $form = new Am_Form(); if (!$invoice->paysys_id) { $psOptions = array(); foreach (Am_Di::getInstance()->paysystemList->getAllPublic() as $ps) { $psOptions[$ps->getId()] = $this->renderPaysys($ps); } $paysys = $form->addAdvRadio('paysys_id') ->setLabel(___('Payment System')) ->loadOptions($psOptions); $paysys->addRule('required', ___('Please choose a payment system')); if (count($psOptions) == 1) $paysys->toggleFrozen(true); } $form->addSaveButton(___('Pay')); $this->view->invoice = $invoice; $this->view->form = $form; $form->setDataSources(array( $this->getRequest() )); if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); if (!$invoice->paysys_id) { $invoice->setPaysystem($vars['paysys_id']); $invoice->save(); } $payProcess = new Am_Paysystem_PayProcessMediator($this, $invoice); $result = $payProcess->process(); throw new Am_Exception_InternalError( sprintf('Error occurred while trying proccess invoice [%s]', filterId($invoice->public_id))); } $this->view->layoutNoMenu = true; $this->view->display('pay.phtml'); } protected function renderPaysys(Am_Paysystem_Description $p) { return sprintf('%s %s', $p->getTitle(), $p->getDescription()); } }PK\EN~~Bdefault/controllers/AdminImportWordpressMagicMembersController.phpnu[db_wordpress = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $order) { $this->user = $user; $this->order = $order; return $this->doWork(); } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`= ? ", WP_IMPORT_ID); } return @$cache[$pid]; } protected function insertAccess($access, $invoice_id=null, $payment_id=null) { $a = $this->getDi()->accessRecord; $a->setDisableHooks(); $a->user_id = $this->user->user_id; $a->begin_date = $access['access_start_date']; $a->expire_date = $access['access_end_date']; if (!is_null($invoice_id)) { $a->invoice_id = $invoice_id; } if (!is_null($payment_id)) { $a->invoice_payment_id = $payment_id; } $a->product_id = $access['product_id']; $a->insert(); } } class InvoiceCreator_Paypal extends InvoiceCreator_Abstract { function doWork() { /*@var $product Product*/ if(!($product = Am_Di::getInstance()->productTable->load($this->_translateProduct($this->order['item_id']), false))) return; /*@var $invoice Invoice*/ $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $invoice->public_id = $this->order['iid']; /*@var $item InvoiceItem*/ $item = $invoice->createItem($product); $item->qty = $this->order['quantity']; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'paypal'; $invoice->tm_added = $this->order['date_added']; $invoice->tm_started = $this->order['date_added']; $invoice->calculate(); $invoice->insert(); $payments = $this->db_wordpress->select(" SELECT txn_id, subscr_id, received, txn_type, ipn_content FROM mm_paypal_ipn_log WHERE order_id = ?d AND (payment_status = ? OR txn_type = ?) ", $this->order['order_id'], 'Completed', 'subscr_cancel'); $cnt = 0; foreach ($payments as $p) { $invoice->data()->set('external_id', $p['subscr_id']); if($p['txn_type'] == 'subscr_cancel') { $invoice->tm_cancelled = $p['received']; $invoice->status = Invoice::RECURRING_CANCELLED; continue; } $data = unserialize($p['ipn_content']); $amount = ($a = $data['mc_gross']) ? $a : $data['payment_gross']; /*@var $payment InvoicePayment*/ $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $data['mc_currency']; $payment->amount = moneyRound($amount); $payment->paysys_id = 'paypal'; $payment->dattm = $p['received']; $payment->receipt_id = $p['subscr_id']; $payment->transaction_id = 'import-paypal-' . $p['txn_id']; $payment->insert(); // access $start = sqlDate($p['received']); $period = new Am_Period($cnt ? $invoice->second_period : $invoice->first_period); $expire = $period->addTo($start); $access = array( 'product_id' => $product->pk(), 'access_start_date' => $start, 'access_end_date' => $expire, ); $this->insertAccess($access, $invoice->pk(), $payment->pk()); $cnt++; } $invoice->update(); $this->user->checkSubscriptions(); } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_wordpress; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_wordpress, array $options = array()) { $this->db_wordpress = $db_wordpress; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { define('AM_DEBUG',true);error_reporting(E_ALL);ini_set('display_errors','On'); $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`= ? ", WP_IMPORT_ID); //print_rre($importedProducts); $prs = $this->db_wordpress->selectCell("SELECT option_value FROM ?_options where option_name='mgm_subscription_packs_options'"); $prs = unserialize($prs); foreach($prs['packs'] as $r) { if (@in_array($r['id'], $importedProducts)) continue; $data = $r; //****************************************************************** // PRODUCT //****************************************************************** if (!in_array($data['membership_type'], $importedProducts)) { $context++; $p = $this->getDi()->productRecord; $p->title = $data['description']; $p->currency = $data['currency']; $p->data()->set(WP_IMPORT_ID, $data['id']); if(@$this->options['keep_product_id']){ $p->disableInsertPkCheck(true); $p->product_id = $r['id']; $p->insert(false)->refresh(); } else $p->insert(); $importedProducts[] = $data['id']; $bp = $p->createBillingPlan(); $bp->title = 'default'; if(@$data['trial_on'] && @$data['trial_duration'] > 0) { $bp->first_price = moneyRound(@$data['trial_cost']); $bp->first_period = $data['trial_duration'].@$data['trial_duration_type']; } else { $bp->first_price = moneyRound(@$data['cost']); $bp->first_period = $data['duration'].$data['duration_type']; } if(array_key_exists('num_cycles',$data)) { if($data['num_cycles'] == '0') { if(moneyRound($data['cost']) > 0) $bp->rebill_times = 99999; else $bp->rebill_times = 0; } elseif($data['num_cycles'] == 1) $bp->rebill_times = 0; else $bp->rebill_times = $data['num_cycles']; if($bp->rebill_times > 1) { $bp->second_price = moneyRound($data['cost']); $bp->second_period = $data['duration'].$data['duration_type']; } } $bp->insert(); } } return true; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { $maxImported = (int) $this->getDi()->db->selectCell(" SELECT `value` FROM ?_data WHERE `table`='user' AND `key`= ? ORDER BY `id` DESC LIMIT 1 ", WP_IMPORT_ID); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_wordpress->queryResultOnly(" SELECT u.* FROM ?_users u WHERE u.ID > ?d ORDER BY u.ID {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_wordpress->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->email = $r['user_email']; $u->added = $r['user_registered']; $u->login = $r['user_login']; list($f,$l) = explode(' ', $r['display_name']); if($f && $l) { $u->name_f = $f; $u->name_l = $l; } else { list($f,$l) = preg_split('/(?=[A-Z])/', $r['display_name'], -1, PREG_SPLIT_NO_EMPTY); if($f && $l) { $u->name_f = $f; $u->name_l = $l; } else { $u->name_f = $r['display_name']; $u->name_l = $r['display_name']; } } $u->is_approved = 1; $u->data()->set(WP_IMPORT_ID, $r['ID']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time $u->pass = $r['user_pass']; if(@$this->options['keep_user_id']){ $u->disableInsertPkCheck(true); $u->user_id = $r['ID']; } try { if(@$this->options['keep_user_id']) $u->insert(false)->refresh(); else $u->insert(); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } } class Am_Import_Payment3 extends Am_Import_Abstract { function doWork(& $context) { define('AM_DEBUG',true);error_reporting(E_ALL);ini_set('display_errors','On'); $q = $this->db_wordpress->queryResultOnly(" SELECT t.*,top.option_value as ccbill_subscription_id,DATE(t.transaction_dt) as begin_date FROM ?_mgm_transactions t LEFT JOIN ?_mgm_transaction_options top ON t.id = top.transaction_id and top.option_name = 'ccbill_subscription_id' WHERE t.status in('Active','Awaiting Cancelled') ORDER BY t.id LIMIT ?d, 1000 ", $context); $products = array(); while ($r = $this->db_wordpress->fetchRow($q)) { //$this->getDi()->errorLogTable->log('batch '.time().' - '.$r['id']); if($this->getDi()->db->selectCell("SELECT 'value' from ?_data where `key` = ? and `table` = 'access'", WP_IMPORT_ID) > 0 ) { $context++; continue; } if (!$this->checkLimits()) { $this->getDi()->errorLogTable->log('checkLimits'); return; } $data = json_decode($r['data'],true); if(!$data['id']) $data['id'] = $data['pack_id']; if(!$data['id']) { $context++; continue; } $amount = moneyRound($data['cost']); if(!@$products[$data['id']]) $products[$data['id']] = $this->getDi()->productTable->load($data['id']); if(!$amount) { //add just access $a = $this->getDi()->accessRecord; if(@$this->options['use_wp_id']) { $a->user_id = $r['user_id']; $a->product_id = $data['id']; } else { //todo } $a->begin_date = $r['begin_date']; $p = new Am_Period($products[$data['id']]->getBillingPlan()->first_period); $a->expire_date = $p->addTo($a->begin_date); $a->data()->set(WP_IMPORT_ID,$r['id']); try{ $a->insert(); } catch(Am_Exception $ex) { $this->getDi()->errorLogTable->logException($ex); echo "Could not import transaction: " . $ex->getMessage() . "
      \n"; } $context++; } else { $invoice = false; foreach($this->getDi()->invoiceTable->findBy(array('user_id' => $r['user_id'])) as $invoice_) { if($invoice) continue; if($item_ = $this->getDi()->invoiceItemTable->findFirstBy(array('invoice_id' => $invoice_->invoice_id,'item_type' => 'product', 'item_id' => $data['id']))) $invoice = $invoice_; } if(!$invoice) { $invoice = $this->getDi()->invoiceRecord; if(@$this->options['use_wp_id']) { try{ $invoice->setUser($this->getDi()->userTable->load($r['user_id'])); $invoice->add($products[$data['id']]); } catch(Am_Exception $ex) { echo "Could not import transaction: " . $ex->getMessage() . "
      \n"; $context++; continue; } } else { //todo } $invoice->currency = $data['currency']; $invoice->calculate(); $invoice->setPaysystem('ccbill'); $invoice->insert(); } //************************************* $payment = $this->getDi()->invoicePaymentRecord; $payment->amount = $amount; $payment->currency = $data['currency']; $payment->dattm = $r['transaction_dt']; $payment->paysys_id = 'ccbill'; $payment->invoice_id = $invoice->pk(); $payment->receipt_id = $r['ccbill_subscription_id'] ? $r['ccbill_subscription_id'] : $r['id']; $payment->user_id = $r['user_id']; $payment->transaction_id = $r['ccbill_subscription_id']; $payment->invoice_public_id = $invoice->public_id; try{ $payment->insert(); } catch(Am_Exception $ex) { echo "Could not import transaction: " . $ex->getMessage() . "
      \n"; $context++; continue; } //********************************** $a = $this->getDi()->accessRecord; if(@$this->options['use_wp_id']) { $a->user_id = $r['user_id']; $a->product_id = $data['id']; } else { //todo } $a->begin_date = $r['begin_date']; $p = new Am_Period($products[$data['id']]->getBillingPlan()->first_period); $a->expire_date = $p->addTo($a->begin_date); $a->invoice_id = $invoice->pk(); $a->invoice_payment_id = $payment->pk(); $a->transaction_id = $r['ccbill_subscription_id']; $a->invoice_public_id = $invoice->public_id; $a->data()->set(WP_IMPORT_ID,$r['id']); $a->insert(); $context++; } } return true; } } class AdminImportWordpressMagicMembersController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_wordpress; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->wordpress_db = null; $this->getSession()->wordpress_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->wordpress_import = null; } if (!$this->getSession()->wordpress_db) return $this->askDbSettings(); $this->db_wordpress = Am_Db::connect($this->getSession()->wordpress_db); if (!$this->getSession()->wordpress_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->wordpress_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_wordpress, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from Wordpress Magic Members Plugin"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->wordpress_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-wordpress-magic-members",array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->wordpress_import = array( 'import' => $val['import'], 'user' => @$val['user'], 'product' => @$val['product'], 'payment' => @$val['payment'], 'pr_link' => @$val['pr_link'], ); $this->_redirect('admin-import-wordpress-magic-members'); return; } } $this->view->title = "Import Wordpress Magic Members Plugin Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createCleanUpForm(){ $form = new Am_Form_Admin(); $total_products = $this->getDi()->db->selectCell('SELECT count(product_id) FROM ?_product'); $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`= ? ",WP_IMPORT_ID); $total_users = $this->getDi()->db->selectCell('SELECT count(user_id) FROM ?_user'); $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`= ? ",WP_IMPORT_ID); $form->addStatic()->setLabel('IMPORTANT INFO')->setContent(<<Clean UP process cannot be reversed, so if you don't understand what are you doing, please navigate away from this page!
      Sometimes this is necessary to remove all data from aMember's database and start import over. This form helps to do this in one go. Please make sure that you don't have any importand data in database, because it can't be restored after clean up. This is good idea to make a backup before "Clean Up" operation.
      DATA WHICH WILL BE REMOVED BY THIS OPERATION:
      User Accounts
      User Invoices/Payments
      User CC info
      Products enabled by setting below
      Affiliate data(if aff module is enabled)
      Newsletter subscriptions data(if newsletter module is enabled)
      Helpdesk tickets(if helpdesk module is enabled)
      EOL ); $form->addAdvCheckbox('remove_products')->setLabel('Remove products'); $form->addAdvCheckbox('remove_invoices')->setLabel('Remove Invoices only'); $form->addPassword('password')->setLabel('Please confirm your Admin password'); $form->addSaveButton('Clean Up'); return $form; } function cleanUpData($value){ if(@$value['remove_invoices']) $tables = array('access', 'access_cache', 'access_log', 'cc', 'coupon', 'coupon_batch', 'invoice', 'invoice_item', 'invoice_log', 'invoice_payment', 'invoice_refund'); else $tables = array('access', 'access_cache', 'access_log', 'cc', 'coupon', 'coupon_batch', 'invoice', 'invoice_item', 'invoice_log', 'invoice_payment', 'invoice_refund', 'saved_pass', 'user', 'user_status', 'user_user_group'); if(@$value['remove_products']) $tables = array_merge($tables, array('billing_plan', 'product', 'product_product_category')); if($this->getDi()->modules->isEnabled('helpdesk')) $tables = array_merge($tables, array('helpdesk_ticket', 'helpdesk_message')); if($this->getDi()->modules->isEnabled('newsletter')) $tables = array_merge($tables, array('newsletter_list', 'newsletter_user_subscription')); // Doing cleanup foreach($tables as $table){ $this->getDi()->db->query('TRUNCATE TABLE ?_'.$table); } // Doing data table separately. if(!@$value['remove_products']){ $where = "where `table` <> 'product' and `table`<>'billing_plan'"; } elseif(!@$value['remove_invoices']){ $where = "where `table` in('access','invoice_item','invoice') "; }else $where = ''; $this->getDi()->db->query('delete from ?_data '.$where); $this->redirectHtml($this->getDi()->url('admin-import-wordpress-magic-members'), 'Records removed'); } function cleanAction(){ $this->form = $this->createCleanUpForm(); $this->form->addDataSource($this->_request); if($this->form->isSubmitted() && $this->form->validate()){ $value = $this->form->getValue(); // Validate password; $admin = $this->getDi()->authAdmin->getUser(); if(!$admin->checkPassword($value['password'])){ $this->form->setError('Incorrect Password!'); }else{ $this->cleanUpData($this->form->getValue()); } } $this->view->title = "Clean up Database"; $this->view->content = (string)$this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { define('AM_DEBUG',true);error_reporting(E_ALL);ini_set('display_errors','On'); $form = new Am_Form_Admin; if($total_products = $this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_product")) $form->addStatic() ->setLabel(___('Clean up v4 Database')) ->setContent( sprintf(___('Use this %slink%s to delete data from aMember v4 database and use clean database for import'), '', '')); //****************************************************************** // PRODUCTS //****************************************************************** $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`= ? ", WP_IMPORT_ID); $prs = $this->db_wordpress->selectCell("SELECT option_value FROM ?_options where option_name='mgm_subscription_packs_options'"); $prs = unserialize($prs); $total = count($prs['packs']); /** count imported */ $cb = $form->addGroup(); $cb->setLabel('Import Products'); if ($imported_products >= $total) { $cb->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb->addRadio('import', array('value' => 'product')); } $cb->addStatic()->setContent('
      Keep the same Product IDs'); $keep_id_chkbox = $cb->addCheckbox('product[keep_product_id]'); if($total_products){ $keep_id_chkbox->setAttribute('disabled'); $cb->addStatic() ->setContent('Product table have records already. Please use Clean Up if you want to keep the same product IDs'); } if ($imported_products) { //****************************************************************** // USERS //****************************************************************** $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`= ? ", WP_IMPORT_ID); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('
      Keep the same user IDs'); $keep_id_chkbox = $cb->addCheckbox('user[keep_user_id]'); if($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_user")){ $keep_id_chkbox->setAttribute('disabled'); $cb->addStatic() ->setContent('User database have records already. Please use Clean Up if you want to keep the same user IDs'); } } $cb->setLabel('Import Users'); //****************************************************************** // PAYMENTS //****************************************************************** $imported_payments = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='access' AND `key`= ? ", WP_IMPORT_ID); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_mgm_transactions WHERE status in('Active','Awaiting Cancelled')"); if ($imported_payments >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_payments) $cb->addStatic()->setContent("partially imported ($imported_payments of $total total)

      "); $cb->addRadio('import', array('value' => 'payment')); $cb->addStatic()->setContent('
      Use WP products and users IDs'); $keep_id_chkbox = $cb->addCheckbox('payment[use_wp_id]'); } $cb->setLabel('Import Payments'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->wordpress_db = $this->form->getValue(); $this->_redirect('admin-import-wordpress-magic-members'); } else { $this->view->title = "Import Wordpress Membership Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('Wordpress MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('Wordpress MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('Wordpress MySQL Password'); $form->addText('db')->setLabel('Wordpress MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('Wordpress Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'wp_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_users LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } PK\{%؎؎.default/controllers/AdminImport3Controller.phpnu[product_id = $id; } public function calculateStartDate($paymentDate, Invoice $invoice) { return $paymentDate; } public function getBillingPlanData() { return null; } public function getBillingPlanId() { return null; } public function getCurrencyCode() { return 'USD'; } public function getDescription() { return ''; } public function getFirstPeriod() { return '1d'; } public function getFirstPrice() { return '0.0'; } public function getIsCountable() { } public function getIsTangible() { } public function getTax() { return self::ALL_TAX; } public function getOptions() { } public function getProductId() { return $this->product_id; } public function getRebillTimes() { } public function getSecondPeriod() { return '1d'; } public function getSecondPrice() { return 0.0; } public function getTitle() { return 'Deleted Product #'.$this->product_id; } public function getType() { return 'imported-product'; } public function setOptions(array $options) { } public function addQty($requestedQty, $itemQty) { return 1; } public function findItem(array $existingInvoiceItems) { foreach ($existingInvoiceItems as $item) if ($item->item_id == $this->getProductId()) return $item; } public function getIsVariableQty() { } public function getQty() { } public function getTaxGroup() { return -1; } } /** Generate am4 invoices from amember 3 payments array */ abstract class InvoiceCreator_Abstract { /** @param User $user */ protected $user; /** v3User */ protected $v3user; // all payments protected $payments = array(); // grouped by invoice protected $groups = array(); // prepared Invoices protected $invoices = array(); // protected $paysys_id; const AM3_RECURRING_DATE = '2036-12-31'; const AM3_LIFETIME_DATE = '2039-12-31'; public function getDi() { return Am_Di::getInstance(); } public function __construct($paysys_id) { $this->paysys_id = $paysys_id; } function process(User $user, array $payments, array $v3user) { $this->user = $user; $this->v3user = $v3user; foreach ($payments as $p) { $this->prepare($p); $this->payments[$p['payment_id']] = $p; } $this->groupByInvoice(); $this->beforeWork(); return $this->doWork(); } function groupByInvoice() { $this->groups[] = $this->payments; } function prepare(array &$p) { if (empty($p['data'][0]['BASKET_PRODUCTS'])) $p['data'][0]['BASKET_PRODUCTS'] = array($p['product_id']); if (empty($p['data']['BASKET_PRICES'])) $p['data']['BASKET_PRICES'] = array( $p['product_id'] => $p['amount'], ); // $p['data']['CANCELLED'] = 1 // $p['data']['CANCELLED_AT'] = 11/02/2010 16:01:34 // $p['data']['COUPON_DISCOUNT'] => 0 // $p['data']['TAX_AMOUNT'] => // $p['data']['TAXES'] => '' // $p['data']['ORIG_ID'] } function beforeWork() {} abstract function doWork(); static function factory($paysys_id) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id); else return new InvoiceCreator_Standard($paysys_id); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='am3:id'"); } return @$cache[$pid]; } } /** * Handles not-recurring payments from any plugin */ class InvoiceCreator_Standard extends InvoiceCreator_Abstract { public function doWork() { $t_ = $this->getDi()->dateTime; $t_->modify('-1 days'); $rebill_date = $t_->format('Y-m-d'); foreach ($this->groups as $list) { $byDate = array(); $totals = array(); // totals by date $coupon = null; $cancelled = null; foreach ($list as $p) { $d = date('Y-m-d', strtotime($p['tm_added'])); $byDate[ $d ][] = $p; @$totals[ $d ] += $p['amount']; if(!empty($p['data'][0]['coupon'])) $coupon = $p['data'][0]['coupon']; if(!empty($p['data']['CANCELLED_AT'])) $cancelled = date('Y-m-d H:i:s', strtotime($p['data']['CANCELLED_AT'])); elseif(@$p['data']['CANCELLED']) $cancelled = date('Y-m-d H:i:s', time()); } // there is a number of dates - was it a recurring payment?? // if (count($byDate) > 1) $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $pidItems = array(); foreach ($list as $p) { $pid = $p['product_id']; if (@$pidItems[$pid]) continue; $pidItems[$pid] = 1; $newP = $this->_translateProduct($pid); if ($newP) { $pr = Am_Di::getInstance()->productTable->load($newP); $item = $invoice->createItem($pr); if (empty($invoice->first_period)) $invoice->first_period = $pr->getBillingPlan()->first_period; } else { $item = $invoice->createItem(new ImportedProduct($pid)); $invoice->first_period = '1d'; } $item->add(1); $item->_calculateTotal(); $invoice->addItem($item); } if(!is_null($coupon)) { $invoice->setCouponCode($coupon); $invoice->validateCoupon(); } $invoice->currency = $item->currency ? $item->currency : Am_Currency::getDefault(); $invoice->calculate(); $invoice->paysys_id = $this->paysys_id; $invoice->tm_added = $list[0]['tm_added']; $invoice->tm_started = $list[0]['tm_completed']; $invoice->public_id = $list[0]['payment_id']; $invoice->first_total = current($totals); if($invoice->rebill_times){ // Recurring if($cancelled) { $invoice->tm_cancelled = $cancelled; $invoice->status = Invoice::RECURRING_CANCELLED; }else { $invoice->status = Invoice::RECURRING_ACTIVE; $invoice->rebill_date = $rebill_date; } }else{ $invoice->status = Invoice::PAID; } foreach ($list as $p) $pidlist[] = $p['payment_id']; $invoice->data()->set('am3:id', implode(',', $pidlist)); if(empty($invoice->currency)) $invoice->currency=Am_Currency::getDefault(); if (@$p['data']['PAYPAL_PROFILE_ID']) $invoice->data()->set('paypal-profile-id', $p['data']['PAYPAL_PROFILE_ID']); $invoice->insert(); // insert payments and access foreach ($list as $p) { $newP = $this->_translateProduct($p['product_id']); if (!$invoice->isZero() && empty($p['data']['ORIG_ID'])) { $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->currency = $invoice->currency; $payment->invoice_id = $invoice->pk(); $payment->invoice_public_id = $invoice->public_id; if (count($list) == 1) { $payment->amount = $p['amount']; } elseif ($p['data']['BASKET_PRICES']) { $payment->amount = array_sum($p['data']['BASKET_PRICES']); } else { $payment->amount = 0; foreach ($list as $pp) if (@$p['data']['ORIG_ID'] == $p['payment_id']) $payment->amount += $pp['amount']; } $payment->paysys_id = $this->paysys_id; $payment->dattm = $p['tm_completed']; $payment->receipt_id = $p['receipt_id']; $payment->transaction_id = $p['receipt_id'] . '-import-' . mt_rand(10000, 99999).'-'.intval($p['payment_id']); if(!empty($p['tax_amount'])||!empty($p['data']['TAX_AMOUNT'])){ $payment->tax = $p['tax_amount']?$p['tax_amount'] : $p['data']['TAX_AMOUNT']; if(empty($invoice->first_tax)) { $invoice->first_tax = $payment->tax; $invoice->updateQuick('first_tax'); }else if(empty($invoice->second_tax)){ $invoice->second_tax = $payment->tax; $invoice->updateQuick('second_tax'); } } $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='am3:id',`value`=?", $payment->pk(), $p['payment_id']); } if ($newP) // if we have imported that product { $a = $this->getDi()->accessRecord; $a->setDisableHooks(); $a->user_id = $this->user->user_id; $a->begin_date = $p['begin_date']; $a->expire_date = $p['expire_date']; $a->invoice_id = $invoice->pk(); if (!$invoice->isZero()) { $a->invoice_payment_id = $payment->pk(); } $a->product_id = $newP; $a->insert(); } } } } // group using public function groupByInvoice() { $parents = array(); foreach ($this->payments as $p) { $k = @$p['data'][0]['ORIG_ID']; if (!empty($p['data'][0]['RENEWAL_ORIG'])) { $k = intval(preg_replace('/RENEWAL_ORIG:\s+/', '', $p['data'][0]['RENEWAL_ORIG'])); // look for first payment while ($x = @$parents[$k]) { $k = $x; } } if ($k && $k != $p['payment_id']) { $parents[ $p['payment_id'] ] = $k; } else { // single $k = $p['payment_id']; } $this->groups[$k][] = $p; } } } class InvoiceCreator_AuthorizeCim extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'authorize-cim'; } function doWork(){ parent::doWork(); // First make sure that user's record have ccInfo created; $storedCc = Am_Di::getInstance()->ccRecordTable->findFirstByUserId($this->user->pk()); if(!$storedCc){ $storedCc = Am_Di::getInstance()->CcRecordRecord; $storedCc->user_id = $this->user->pk(); $storedCc->cc_expire = '1237'; $storedCc->cc_number = '0000000000000000'; $storedCc->cc = $storedCc->maskCc(@$storedCc->cc_number); $storedCc->insert(); } if($user_profile = $this->v3user['data']['authorize_cim_user_profile_id']) { $this->user->data()->set('authorize_cim_user_profile_id', $user_profile); } if($payment_profile = $this->v3user['data']['authorize_cim_payment_profile_id']) { $this->user->data()->set('authorize_cim_payment_profile_id', $payment_profile); } $this->user->data()->update(); } } class InvoiceCreator_Abnamro extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'abnamro'; } function doWork(){ parent::doWork(); // First make sure that user's record have ccInfo created; $storedCc = Am_Di::getInstance()->ccRecordTable->findFirstByUserId($this->user->pk()); if(!$storedCc){ $storedCc = Am_Di::getInstance()->CcRecordRecord; $storedCc->user_id = $this->user->pk(); $storedCc->cc_expire = '1237'; $storedCc->cc_number = '0000000000000000'; $storedCc->cc = $storedCc->maskCc(@$storedCc->cc_number); $storedCc->insert(); } if($user_profile = $this->v3user['data']['abnamro_alias']) $this->user->data()->set('abnamro_alias', $user_profile)->update(); } } class InvoiceCreator_MonerisR extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'moneris'; } } class InvoiceCreator_NetbillingCc extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'netbilling'; } } class InvoiceCreator_Moneris extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'moneris-cc'; } } class InvoiceCreator_AuthorizeAim extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'authorize-aim'; } } class InvoiceCreator_GoogleCheckout extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'google-checkout'; } } class InvoiceCreator_PayflowPro extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'payflow'; } } class InvoiceCreator_TwocheckoutR extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'twocheckout'; } } class InvoiceCreator_Linkpoint extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'firstdata'; } } class InvoiceCreator_PayflowLink extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'payflow-link'; } } class InvoiceCreator_Epayeu extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'epay'; } function doWork() { $t_ = $this->getDi()->dateTime; $t_->modify('-1 days'); $rebill_date = $t_->format('Y-m-d'); foreach ($this->groups as $list) { $byDate = array(); $totals = array(); // totals by date $coupon = null; $cancelled = null; foreach ($list as $p) { $d = date('Y-m-d', strtotime($p['tm_added'])); $byDate[ $d ][] = $p; @$totals[ $d ] += $p['amount']; if(!empty($p['data'][0]['coupon'])) $coupon = $p['data'][0]['coupon']; if(!empty($p['data']['CANCELLED_AT'])) $cancelled = date('Y-m-d H:i:s', strtotime($p['data']['CANCELLED_AT'])); elseif(@$p['data']['CANCELLED']) $cancelled = date('Y-m-d H:i:s', time()); } // there is a number of dates - was it a recurring payment?? // if (count($byDate) > 1) $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $pidItems = array(); foreach ($list as $p) { $pid = $p['product_id']; if (@$pidItems[$pid]) continue; $pidItems[$pid] = 1; $newP = $this->_translateProduct($pid); if ($newP) { $pr = Am_Di::getInstance()->productTable->load($newP); $item = $invoice->createItem($pr); if (empty($invoice->first_period)) $invoice->first_period = $pr->getBillingPlan()->first_period; } else { $item = $invoice->createItem(new ImportedProduct($pid)); $invoice->first_period = '1d'; } $item->add(1); $item->_calculateTotal(); $invoice->addItem($item); } if(!is_null($coupon)) { $invoice->setCouponCode($coupon); $invoice->validateCoupon(); } $invoice->currency = $item->currency ? $item->currency : Am_Currency::getDefault(); $invoice->calculate(); $invoice->paysys_id = $this->paysys_id; $invoice->tm_added = $list[0]['tm_added']; $invoice->tm_started = $list[0]['tm_completed']; $invoice->public_id = $list[0]['payment_id']; $invoice->first_total = current($totals); if($invoice->rebill_times){ // Recurring if($cancelled) { $invoice->tm_cancelled = $cancelled; $invoice->status = Invoice::RECURRING_CANCELLED; }else { $invoice->status = Invoice::RECURRING_ACTIVE; $invoice->rebill_date = $rebill_date; } }else{ $invoice->status = Invoice::PAID; } foreach ($list as $p) $pidlist[] = $p['payment_id']; $invoice->data()->set('am3:id', implode(',', $pidlist)); if(empty($invoice->currency)) $invoice->currency=Am_Currency::getDefault(); if (@$p['data']['PAYPAL_PROFILE_ID']) $invoice->data()->set('paypal-profile-id', $p['data']['PAYPAL_PROFILE_ID']); //REQUIRED PART TO IMPORT RECURRING SUBCRIPTIONS if (@$p['data']['epayeu_subscription_id']) $invoice->data()->set('epay_subscriptionid', $p['data']['epayeu_subscription_id']); $invoice->insert(); // insert payments and access foreach ($list as $p) { $newP = $this->_translateProduct($p['product_id']); if (empty($p['data']['ORIG_ID'])) { $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->currency = $invoice->currency; $payment->invoice_id = $invoice->pk(); $payment->invoice_public_id = $invoice->public_id; if (count($list) == 1) { $payment->amount = $p['amount']; } elseif ($p['data']['BASKET_PRICES']) { $payment->amount = array_sum($p['data']['BASKET_PRICES']); } else { $payment->amount = 0; foreach ($list as $pp) if (@$p['data']['ORIG_ID'] == $p['payment_id']) $payment->amount += $pp['amount']; } $payment->paysys_id = $this->paysys_id; $payment->dattm = $p['tm_completed']; $payment->receipt_id = $p['receipt_id']; $payment->transaction_id = $p['receipt_id'] . '-import-' . mt_rand(10000, 99999).'-'.intval($p['payment_id']); $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='am3:id',`value`=?", $payment->pk(), $p['payment_id']); } if ($newP) // if we have imported that product { $a = $this->getDi()->accessRecord; $a->setDisableHooks(); $a->user_id = $this->user->user_id; $a->begin_date = $p['begin_date']; $a->expire_date = $p['expire_date']; $a->invoice_id = $invoice->pk(); $a->invoice_payment_id = $payment->pk(); $a->product_id = $newP; $a->insert(); } } } } } class InvoiceCreator_PaypalR extends InvoiceCreator_Abstract { // $p['data'][x]['txn_id'] // $p['receipt_id'] - subscription id // $p['data'][x]['txn_type] // $p['data']['paypal_vars'] = unserialize p1=>, a1=>, m1=> function doWork() { $t_ = $this->getDi()->dateTime; $t_->modify('-1 days'); $rebill_date = $t_->format('Y-m-d'); foreach ($this->groups as $group_id => $list) { $txn_types = array(); $currency = ""; $product_ids = array(); $signup_params = array(); foreach ($list as $p) { foreach ($p['data'] as $k => $d) { if (is_int($k) && !empty($d['txn_type'])) @$txn_types[$d['txn_type']]++; if(is_int($k) && !empty($d['mc_currency'])) $currency = $d['mc_currency']; if (@$d['txn_type'] == 'subscr_signup') { $signup_params = $d; } elseif (@$d['txn_type'] == 'web_accept') { $signup_params = $d; } } @$product_ids[ $p['product_id'] ]++; } $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); foreach ($product_ids as $pid => $count) { $newP = $this->_translateProduct($pid); if ($newP) { $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($newP)); } else { $item = $invoice->createItem(new ImportedProduct($pid)); } $item->add(1); $item->_calculateTotal(); $invoice->addItem($item); } $invoice->paysys_id = 'paypal'; $invoice->tm_added = $list[0]['tm_added']; $invoice->tm_started = $list[0]['tm_completed']; $invoice->public_id = $signup_params['invoice']? preg_replace('/-.*/', '', $signup_params['invoice']) : $list[0]['payment_id']; $invoice->currency = $currency ? $currency : $item->currency; // Set currency; if(empty($invoice->currency)) $invoice->currency = Am_Currency::getDefault(); if (!empty($txn_types['web_accept'])) // that is not-recurring { $invoice->first_total = $signup_params['mc_gross']; $item = current($invoice->getItems()); $invoice->first_period = $item->first_period; $invoice->status = Invoice::PAID; } else { // recurring if ($signup_params) { $invoice->first_period = $invoice->second_period = strtolower(str_replace(' ', '', $signup_params['period3'])); $invoice->first_total = $invoice->second_total = $signup_params['mc_amount3']; if (!empty($signup_params['mc_amount1'])) { $invoice->first_total = $signup_params['mc_amount1']; $invoice->first_period = strtolower(str_replace(' ', '', $signup_params['period1'])); } if (!$signup_params['recurring']) { $invoice->rebill_times = 1; } elseif ($signup_params['recur_times']) { $invoice->rebill_times = $signup_params['recur_times']; } else { $invoice->rebill_times = IProduct::RECURRING_REBILLS; } } else { // get terms from products $invoice->rebill_times = -1; foreach ($product_ids as $pid => $count) { $newPid = $this->_translateProduct($pid); if (!$newPid) continue; $pr = Am_Di::getInstance()->productTable->load($newPid); $invoice->first_total += $pr->getBillingPlan()->first_price; $invoice->first_period = $pr->getBillingPlan()->first_period; $invoice->second_total += $pr->getBillingPlan()->second_price; $invoice->second_period = $pr->getBillingPlan()->second_period; $invoice->rebill_times = max(@$invoice->rebill_times, $pr->getBillingPlan()->rebill_times); } if($invoice->rebill_times == -1) $invoice->rebill_times = IProduct::RECURRING_REBILLS; } if (@$txn_types['subscr_eot']) { $invoice->status = Invoice::RECURRING_FINISHED; } elseif (@$txn_types['subscr_cancel']) { $invoice->status = Invoice::RECURRING_CANCELLED; foreach ($list as $p) if (!empty($p['data']['CANCELLED_AT'])) $invoice->tm_cancelled = sqlTime($p['data']['CANCELLED_AT']); } elseif (@$txn_types['subscr_payment']) { $invoice->status = Invoice::RECURRING_ACTIVE; $invoice->rebill_date = $rebill_date; } $invoice->data()->set('paypal_subscr_id', $group_id); } foreach ($list as $p) $pidlist[] = $p['payment_id']; $invoice->data()->set('am3:id', implode(',', $pidlist)); $invoice->insert(); // insert payments and access foreach ($list as $p) { $newP = $this->_translateProduct($p['product_id']); $tm = null; $txnid = null; foreach ($p['data'] as $k => $d) { if (is_int($k) && !empty($d['payment_date'])) { $tm = $d['payment_date']; } if (is_int($k) && !empty($d['txn_id'])) { $txnid = $d['txn_id']; } } $tm = new DateTime(get_first($tm, $p['tm_completed'], $p['tm_added'], $p['begin_date'])); $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->invoice_public_id = $invoice->public_id; $payment->amount = $p['amount']; $payment->paysys_id = 'paypal'; $payment->dattm = $tm->format('Y-m-d H:i:s'); if(!empty($p['tax_amount'])||!empty($p['data']['TAX_AMOUNT'])){ $payment->tax = $p['tax_amount']?$p['tax_amount'] : $p['data']['TAX_AMOUNT']; if(empty($invoice->first_tax)) { $invoice->first_tax = $payment->tax; $invoice->updateQuick('first_tax'); }else if(empty($invoice->second_tax)){ $invoice->second_tax = $payment->tax; $invoice->updateQuick('second_tax'); } } if ($txnid) $payment->receipt_id = $txnid; $payment->transaction_id = 'import-paypal-' . mt_rand(10000, 99999).'-'.intval($p['payment_id']); $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='am3:id',`value`=?", $payment->pk(), $p['payment_id']); if ($newP) // if we have imported that product { $a = $this->getDi()->accessRecord; $a->user_id = $this->user->user_id; $a->setDisableHooks(); $a->begin_date = $p['begin_date']; /// @todo handle payments that were cancelled but still active in amember 3. Calculate expire date in this case. if((($p['expire_date'] == self::AM3_RECURRING_DATE) || ($p['expire_date'] == self::AM3_LIFETIME_DATE )) && array_key_exists('subscr_cancel', $txn_types)){ $a->expire_date = $invoice->calculateRebillDate(count($list)); }else{ $a->expire_date = $p['expire_date']; } $a->invoice_id = $invoice->pk(); $a->invoice_payment_id = $payment->pk(); $a->product_id = $newP; $a->insert(); } } } } public function groupByInvoice() { foreach ($this->payments as $p) { $k = $p['receipt_id']; if (!strlen($k)) $k = $p['payment_id']; $this->groups[$k][] = $p; } } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db3; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db3, array $options = array()) { $this->db3 = $db3; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret){ $this->session->unsetAll(); $this->importFinished(); } return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); /** * Ability to hook into import process after all records are imported. */ public function importFinished(){ } } class Am_Import_Product3 extends Am_Import_Abstract { function serialize_fix_callback($match) { return 's:' . strlen($match[2]); } public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='am3:id'"); $q = $this->db3->queryResultOnly("SELECT * FROM ?_products"); while ($r = $this->db3->fetchRow($q)) { if (in_array($r['product_id'], $importedProducts)) continue; $context++; $data= unserialize($r['data']); if(!is_array($data)){ $data = preg_replace_callback( '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|d:|i:|o:|N;))!s', array($this, "serialize_fix_callback"), $r['data'] ); $data = unserialize($data); if(!is_array($data)) throw new Am_Exception_InternalError("Can't unserialize product data."); } foreach ($data as $k => $v) $r[$k] = $v; $p = $this->getDi()->productRecord; if(@$this->options['keep_product_id']){ $p->disableInsertPkCheck(true); $p->product_id = $r['product_id']; $p->require_other = implode(',', (array)@$r['require_other']); $p->prevent_if_other = implode(',', (array)@$r['prevent_if_other']); } $p->renewal_group = @$r['renewal_group']; $p->title = $r['title']; $p->description = $r['description']; $p->sort_order = $r['order']; $p->tax_group = @$r['use_tax'] ? IProduct::ALL_TAX : IProduct::NO_TAX; $p->trial_group = @$r['trial_group']; if (!empty($r['currency'])) $currency = $r['currency']; $p->data()->set('am3:id', $r['product_id']); foreach ($r as $k => $v) if (preg_match('/currency$/', $k)) $currency = $v; if(empty($currency)) $currency = Am_Currency::getDefault(); if($r['scope'] == 'disabled') $p->is_disabled = true; // subuser if (in_array('subusers', $this->getDi()->modules->getEnabled()) && @$this->options['keep_product_id']) { $subusersCount = $subusersGroup = null; foreach ($r as $k => $v) { if(preg_match('/^subusers_count_(.*)$/', $k, $match)) { $subusersCount = intval($v); $subusersGroup = $match[1]; break; } } if($subusersCount && $subusersGroup) { if($subs3 = $this->db3->selectCell("SELECT blob_value FROM ?_config WHERE `name` = 'subusers.groups'")) $subProducts = unserialize($subs3); if(is_array($subProducts) && !empty($subProducts[$subusersGroup])) { $p->subusers_count = $subusersCount; $p->data()->set('subusers_groups', $subusersGroup); $p->subusers_product_id = $subProducts[$subusersGroup]['product_id']; } } } if(@$this->options['keep_product_id']) $p->insert(false)->refresh(); else $p->insert(); // product credits if (!empty($r['download_credits'])) $p->data()->set('credit', $r['download_credits'])->insert(); $bp = $p->createBillingPlan(); $bp->title = 'default'; $bp->currency = $currency; if (!empty($r['is_recurring'])) { if (!empty($r['trial1_days'])) { $bp->first_price = $r['trial1_price']; $bp->first_period = $r['trial1_days']; $bp->second_price = $r['price']; $bp->second_period = $r['expire_days']; } else { $bp->first_price = $bp->second_price = $r['price']; $bp->first_period = $bp->second_period = $r['expire_days']; } $bp->rebill_times = !empty($r['rebill_times']) ? $r['rebill_times'] : IProduct::RECURRING_REBILLS; } else { // not recurring $bp->first_price = $r['price']; $bp->first_period = $r['expire_days']; $bp->rebill_times = 0; } if (!empty($r['terms'])) $bp->terms = $r['terms']; //1SC if(@$r['1shoppingcart_id']) $bp->data()->set('1shoppingcart_id',$r['1shoppingcart_id']); //Clickbank if(@$r['clickbank_id']) $bp->data()->set('clickbank_product_id',$r['clickbank_id']); //Plimus if(@$r['contr_id']) $bp->data()->set('plimus_contract_id',$r['contr_id']); //Paypal if(@$r['paypal_id']) $bp->data()->set('paypal_id',$r['paypal_id']); //Zombaio if(@$r['zombaio_id']) $bp->data()->set('zombaio_pricing_id',$r['zombaio_id']); //Verotel if(@$r['verotel_id']) $bp->data()->set('verotel_id',$r['verotel_id']); //CCBill if(@$r['ccbill_id']) $bp->data()->set('ccbill_product_id',$r['ccbill_id']); if(@$r['ccbill_subaccount_id']) $bp->data()->set('ccbill_subaccount_id',$r['ccbill_subaccount_id']); if(@$r['ccbill_cc_form']) $bp->data()->set('ccbill_form_id',$r['ccbill_cc_form']); //Safecart if(@$r['safecart_sku']) $bp->data()->set('safecart_sku',$r['safecart_sku']); if(@$r['safecart_product']) $bp->data()->set('safecart_product',$r['safecart_product']); //Fastspring if(@$r['fastspring_id']) $bp->data()->set('fastspring_product_id',$r['fastspring_id']); if(@$r['fastspring_name']) $bp->data()->set('fastspring_product_name',$r['fastspring_name']); $bp->insert(); } return true; } } class Am_Import_User3 extends Am_Import_Abstract { protected static $cfDs = null; protected $crypt = null; protected $chunkSize=200; function checkLimits(){ $ret = parent::checkLimits(); return $ret && ($this->chunkSize-- > 0); } function getCfDataSource() { if (is_null(self::$cfDs)) { self::$cfDs = new Am_Grid_DataSource_CustomField(array(), $this->getDi()->userTable); } return self::$cfDs; } function translateValidateFunc($name) { return strtr($name, array( 'vf_require' => 'required', 'vf_integer' => 'integer', 'vf_number' => 'numeric', 'vf_email' => 'email' )); } function importAddFieldDefs() { $member_fields = $this->db3->selectCell("SELECT blob_value FROM ?_config WHERE name=?", 'member_fields'); $def3 = array(); if ($member_fields) { $_def3 = unserialize($member_fields); $def3 = array(); foreach ($_def3 as $v) { $def3[$v['name']] = $v; } $_def4 = $this->getDi()->userTable->customFields()->getAll(); $def4 = array(); foreach ($_def4 as $v) { $def4[$v->getName()] = $v; } foreach ($def3 as $name => $def) { if (!isset($def4[$name])) { $cf = $this->getCfDataSource(); $def = array_merge($def, (array)$def['additional_fields']); $def['values'] = array ( 'default' => (array)@$def['default'], 'options' => @$def['options'] ); $def['validate_func'] = array_filter(array($this->translateValidateFunc($def['validate_func']))); if($def['sql']) { //try to check existing columns in ?_user try { $this->getDi()->db->select("SELECT ?# from ?_user LIMIT 1",$def['name']); } catch (Am_Exception_Db $e) { $cf->insertRecord(null, $def); } continue; } $cf->insertRecord(null, $def); } } $this->getDi()->userTable->addFieldsFromSavedConfig(); foreach($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) $this->getDi()->resourceAccessTable->setAccess(amstrtoint($field->name), Am_CustomField::ACCESS_TYPE, array( ResourceAccess::FN_FREE_WITHOUT_LOGIN => array( json_encode(array( 'start' => null, 'stop' => null, 'text' => ___('Free Access without log-in') ))) )); } } return $def3; } function getCryptCompat(){ if(is_null($this->crypt)){ $this->crypt = new Am_Crypt_Compat(); } return $this->crypt; } function doWork(& $context) { if (!$this->session->addFieldDef3) $this->session->addFieldDef3 = $this->importAddFieldDefs(); $maxImported = (int)$this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='am3:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db3->queryResultOnly("SELECT * FROM ?_members WHERE member_id > ?d { AND (IFNULL(status,?d) > 0 OR IFNULL(is_affiliate,0) > 0) } ORDER BY member_id LIMIT ?d ", $maxImported, @$this->options['exclude_pending'] ? 0 : DBSIMPLE_SKIP, $count ? $count : $this->chunkSize+1); while ($r = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return false; $r['data'] = unserialize($r['data']); $u = $this->getDi()->userRecord; foreach (array( 'login', 'email', 'name_f', 'name_l', 'street', 'city', 'state', 'country', 'state', 'zip', 'remote_addr', 'added', 'unsubscribed', 'phone', 'is_affiliate', 'aff_payout_type', ) as $k) { if (strlen(@$r[$k])) $u->set($k, $r[$k]); elseif (!empty($r['data'][$k])) $u->set($k, $r[$k]); } if ($r['aff_id'] > 0) { $u->aff_id = $this->getDi()->db->selectCell("SELECT `id` FROM ?_data WHERE `table`='user' AND `key`='am3:id' AND value=?d", $r['aff_id']); $u->aff_added = $r['added']; } if ($r['is_affiliate']) { foreach ($r['data'] as $k => $v) { if (strpos($k, 'aff_')===0) { $u->data()->set($k, $v); } } } $u->setPass($r['pass'], true); // do not salt passwords heavily to speed-up $u->data()->set('am3:id', $r['member_id']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time //import additional fields foreach ($this->session->addFieldDef3 as $def) { $value = $def['additional_fields']['sql'] ? $r[$def['name']] : $r['data'][$def['name']]; $u->setForInsert(array($def['name'] => $value)); } if(@$this->options['keep_user_id']){ $u->disableInsertPkCheck(true); $u->user_id = $r['member_id']; } try { if(@$this->options['keep_user_id']) $u->insert(false)->refresh(); else $u->insert(); if (!empty($r['data']['cc-hidden']) && class_exists('CcRecord', true)) { $cc = $this->getDi()->ccRecordRecord; $cc->user_id = $u->pk(); foreach (array('cc_country', 'cc_street', 'cc_city', 'cc_company', 'cc_state', 'cc_zip', 'cc_name_f', 'cc_name_l', 'cc_phone', 'cc_type') as $k) { if (!empty($r['data'][$k])) $cc->set($k, $r['data'][$k]); } $ccnum = $this->getCryptCompat()->decrypt($r['data']['cc-hidden']); $cc->cc_number = $ccnum; $cc->cc_expire = $r['data']['cc-expire']; $cc->insert(); } $this->insertPayments($r['member_id'], $u, $r); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } // downloads & credits hystory $sql_credits = array(); $sql_downloads = array(); if(!empty($r['data']['downloads'])) { $db = Am_Di::getInstance()->db; $db->query(" CREATE TABLE IF NOT EXISTS ?_credit ( credit_id int not null auto_increment PRIMARY KEY, dattm datetime not null, user_id int not null, value int not null comment 'positive value: credit, negavive value: debit', comment varchar(255) not null comment 'useful for debit comments', access_id int null comment 'will be set to related access_id for credit records', reference_id varchar(255) null comment 'you can set it to your internal operation reference# to link, is not used in aMember', INDEX (user_id, dattm) ) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci "); $db->query(" CREATE TABLE IF NOT EXISTS ?_history_downloads ( downloads_id int(11) NOT NULL AUTO_INCREMENT, filename varchar(255) NOT NULL, cost int(11) NOT NULL, user_id int(11) NOT NULL, dattm datetime NOT NULL, remote_addr varchar(15) DEFAULT NULL, PRIMARY KEY (`downloads_id`) ) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci "); foreach ($r['data']['downloads'] as $d) { $sql_credits[] = "('".sqlTime($d['time'])."', ".$u->pk().", -".$d['cost'].", 'For download file [".$d['filename']."]')"; $sql_downloads[] = "('".$d['filename']."', ".$d['cost'].", ".$u->pk().", '".sqlTime($d['time'])."')"; } $db->query(" INSERT INTO ?_credit (dattm, user_id, value, comment) VALUES " . join(',', $sql_credits)); $db->query(" INSERT INTO ?_history_downloads (filename, cost, user_id, dattm) VALUES " . join(',', $sql_downloads)); } if(isset($r['data']['download_credits'])) { $db = Am_Di::getInstance()->db; $db->query("CREATE TABLE IF NOT EXISTS ?_credit ( credit_id int not null auto_increment PRIMARY KEY, dattm datetime not null, user_id int not null, value int not null comment 'positive value: credit, negavive value: debit', comment varchar(255) not null comment 'useful for debit comments', access_id int null comment 'will be set to related access_id for credit records', reference_id varchar(255) null comment 'you can set it to your internal operation reference# to link, is not used in aMember', INDEX (user_id, dattm) )"); // insert records with no related "credit" $db->query(" INSERT INTO ?_credit SELECT null as credit_id, IFNULL(p.dattm, a.begin_date) as dattm, a.user_id, d.`value`*it.qty as `value`, pr.title as comment, a.access_id, null as reference_id FROM ?_access a LEFT JOIN ?_credit c ON a.access_id = c.access_id INNER JOIN ?_data d ON d.`table`='product' AND d.`id`=a.product_id AND d.`key`='credit' AND d.`value` > 0 LEFT JOIN ?_invoice_payment p ON a.invoice_payment_id=p.invoice_payment_id LEFT JOIN ?_invoice_item it ON it.invoice_id = a.invoice_id and it.item_id=a.product_id LEFT JOIN ?_product pr ON a.product_id = pr.product_id WHERE a.user_id=?d AND c.credit_id IS NULL ", $u->pk()); $balance = $db->selectCell("SELECT SUM(`value`) FROM ?_credit WHERE user_id=?d ", $u->pk()); if ($r['data']['download_credits'] != $balance) $db->query("INSERT INTO ?_credit SET ?a ", array( 'dattm' => '1970-01-01', 'user_id' => $u->pk(), 'value' => $r['data']['download_credits'] - $balance, 'comment' => 'import')); } // subusers if (in_array('subusers', $this->getDi()->modules->getEnabled())) { if(!empty($r['data']['parent_id'])) { $u->subusers_parent_id = intval($r['data']['parent_id']); $u->update(); } if(!empty($r['data']['subusers_groups_id'])) { if(!is_array($subusers_groups_id = $r['data']['subusers_groups_id'])) $subusers_groups_id = unserialize($subusers_groups_id); if(!empty($subusers_groups_id)) { $sql = array(); foreach ($this->getDi()->db->selectCol(" SELECT `id` FROM ?_data WHERE `table`='product' AND `key`='subusers_groups' AND `value` IN (?a) ", $subusers_groups_id) as $masterProductId) { if($prId = $this->getDi()->productTable->load($masterProductId)->subusers_product_id) $sql[] = "(" . $prId . "," . $u->pk() . ")"; } if(!empty($sql)) try { $this->getDi()->db->query("INSERT INTO ?_subusers_subscription (product_id, user_id) VALUES " . join(',', $sql)); } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import subusers subscription: " . $e->getMessage() . "
      \n"; } } } } } return true; } function insertPayments($member_id, User $u, Array $r) { /** * worldpay,safepay,metacharge,alertpay,localweb sets ORIG_ID to parent transaction * * paypal_pro sets $payment['data']['PAYPAL_PROFILE_ID'] * * additional_access by product settings: * $newp['receipt_id'] = 'ADDITIONAL ACCESS:' . $payment['receipt_id']; * $newp['data'][0]['ORIG_ID'] = $payment_id; * * */ $payments = $this->db3->select("SELECT * FROM ?_payments WHERE member_id=$member_id AND (completed > 0) AND (paysys_id <> '') ORDER BY payment_id"); $byPs = array(); foreach ($payments as $payment_id => $p) { $p['data'] = @unserialize($p['data']); $byPs[ $p['paysys_id'] ][] = $p; } foreach ($byPs as $paysys_id => $list) { InvoiceCreator_Abstract::factory($paysys_id)->process($u, $list, $r); } // if ($payments) // $u->checkSubscriptions(true); } /** * Need to set next invoice_id to be greater then last payment_id in v3 payments table. * (required by 1SC payment plugin) may be required for other payment plugins as well. */ function importFinished(){ parent::importFinished(); $nextId = Am_Di::getInstance()->db->selectCell("SELECT MAX(invoice_id) FROM ?_invoice"); $nextId++; $lastv3PaymentId = $this->db3->selectCell("SELECT MAX(payment_id) FROM ?_payments"); if($nextId <= $lastv3PaymentId) Am_Di::getInstance()->db->query('ALTER TABLE ?_invoice AUTO_INCREMENT = ?d',$lastv3PaymentId+1); } } class Am_Import_Affclicks3 extends Am_Import_Abstract { public function doWork(&$context) { $importedCommissions = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='aff_click' AND `key`='am3:id'"); $q = $this->db3->queryResultOnly("SELECT * FROM ?_aff_clicks LIMIT ?d, 100000", $context); while ($a = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return false; if (in_array($a['log_id'], $importedCommissions)) continue; $context++; $click = $this->getDi()->affClickRecord; $click->time = $a['time']; $click->remote_addr = $a['remote_addr']; $click->referer = $a['referrer']; $click->aff_id = $this->getDi()->db->selectCell("SELECT `id` FROM ?_data WHERE `table`='user' AND `key`='am3:id' and value=?",$a['aff_id']); $click->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='aff_click', `id`=?d, `key`='am3:id', `value`=?d", $click->pk(), $a['log_id']); } return true; } } class Am_Import_Affbanners3 extends Am_Import_Abstract { public function doWork(&$context) { $links = $this->db3->selectCell("SELECT blob_value FROM ?_config where name='aff.links' LIMIT 1"); if($links) { $links = unserialize($links); foreach($links as $id => $link){ try { $this->getDi()->db->query("INSERT INTO ?_aff3_banner (banner_link_id,url,type) values (?,?,'l')",$id,$link['url']); } catch (Am_Exception_Db_NotUnique $e) { continue; } $context++; } } $banners = $this->db3->selectCell("SELECT blob_value FROM ?_config where name='aff.banners' LIMIT 1"); if($banners) { $banners = unserialize($banners); foreach($banners as $id => $banner){ try { $this->getDi()->db->query("INSERT INTO ?_aff3_banner (banner_link_id,url,type) values (?,?,'b')",$id,$banner['url']); } catch (Am_Exception_Db_NotUnique $e) { continue; } $context++; } } return true; } } class Am_Import_Aff3 extends Am_Import_Abstract { public function getProductTr() { return $this->getDi()->db->selectCol(" SELECT value as ARRAY_KEY, id FROM ?_data WHERE `table` = 'product' AND `key`='am3:id' "); } public function getUsersTr() { return $this->getDi()->db->selectCol(" SELECT value as ARRAY_KEY, id FROM ?_data WHERE `table` = 'user' AND `key`='am3:id' "); } public function doWork(&$context) { $tr = $this->getUsersTr(); $prTr = $this->getProductTr(); // import is_affiliate, aff_xx field values, and aff_id from users table $importedCommissions = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='aff_commission' AND `key`='am3:id'"); $q = $this->db3->queryResultOnly("SELECT * FROM ?_aff_commission LIMIT ?d, 1000000", $context); while ($a = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return; if (in_array($a['commission_id'], $importedCommissions)) continue; $context++; $comm = $this->getDi()->affCommissionRecord; $comm->date = $a['date']; $comm->amount = $a['amount']; $comm->record_type = ($a['record_type'] == 'credit')? AffCommission::COMMISSION : AffCommission::VOID; $comm->receipt_id = $a['receipt_id'] . uniqid('-am4-import-'); $comm->invoice_id = (int)$this->getDi()->db->selectCell("SELECT `id` FROM ?_data WHERE `table`='invoice' AND `key`='am3:id' AND FIND_IN_SET(?, `value`)", $a['payment_id']); if (empty($comm->invoice_id)) { echo "No invoice found for am3 payment#{$a['payment_id']}"; continue; } $comm->invoice_payment_id = (int)$this->getDi()->db->selectCell("SELECT `id` FROM ?_data WHERE `table`='invoice_payment' AND `key`='am3:id' AND `value`=?d", $a['payment_id']); $comm->product_id = intval($prTr[$a['product_id']]); $comm->aff_id = @$tr[ $a['aff_id'] ]; if (!$comm->aff_id) { echo "No affiliate found #{$a['aff_id']}.skipping\n
      "; continue; } $comm->is_first = $a['is_first']; $comm->tier = $a['tier']; $comm->payout_detail_id = is_null($a['payout_id']) ? $a['payout_id'] : - $this->getPayout($a['payout_date'], $a['payout_type'], $a['payout_id']); // must be fixed to payout_detail_ids $comm->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='aff_commission', `id`=?d, `key`='am3:id', `value`=?d", $comm->pk(), $a['commission_id']); } // now handle payouts $rows = $this->getDi()->db->select("SELECT payout_detail_id, aff_id, SUM(amount) as s FROM ?_aff_commission WHERE payout_detail_id < 0 GROUP BY payout_detail_id, aff_id "); $db = $this->getDi()->db; foreach ($rows as $row) { $d = $this->getDi()->affPayoutDetailRecord; $d->aff_id = $row['aff_id']; $d->amount = $row['s']; $d->is_paid = 1; $d->payout_id = - $row['payout_detail_id']; // was temp. stored here with - $d->insert(); $db->query("UPDATE ?_aff_commission SET payout_detail_id=?d WHERE aff_id=?d AND payout_detail_id=?d", $d->pk(), $row['aff_id'], $row['payout_detail_id']); } // calculate totals return true; } function getPayout($date, $type, $id) { if (!$date) $date = $id; if (!$type) $type = 'paypal'; if (empty($this->session->payouts[$date][$type])) { $p = $this->getDi()->affPayoutRecord; $p->type = $type; $p->date = $date; $p->thresehold_date = $date; $p->insert(); $this->session->payouts[$date][$type] = $p->pk(); } return $this->session->payouts[$date][$type]; } } class Am_Import_Newsletter3 extends Am_Import_Abstract { protected $threadsTr = array(); /** return am3 product# -> am4 product# array */ public function getProductTr() { return $this->getDi()->db->selectCol(" SELECT value as ARRAY_KEY, id FROM ?_data WHERE `table` = 'product' AND `key`='am3:id' "); } public function importThreads() { $tr = $this->getProductTr(); foreach ($this->db3->select("SELECT * FROM ?_newsletter_thread") as $arr) { $t = $this->getDi()->newsletterListRecord; $t->title = $arr['title']; $t->desc = $arr['description']; if (!$arr['is_active']) $t->disabled = 1; if ($arr['blob_auto_subscribe']) $t->auto_subscribe = 1; $avail = array_filter(explode(',', $arr['blob_available_to'])); $t->insert(); $threadsTr[ $arr['thread_id'] ] = $t->pk(); foreach ($avail as $s) { @list($a, $p) = explode('-', $s, 2); switch ($a) { case 'guest': break; case 'active': $t->addAccessListItem(-1, null, null, ResourceAccess::FN_CATEGORY); break; case 'expired': // no idea how to import it break; case 'active_product': if (in_array("expired_product-$p", $avail)) $exp = '-1d'; else $exp = null; if(isset($tr[$p])) $t->addAccessListItem($tr[$p], null, $exp, ResourceAccess::FN_PRODUCT); break; case 'expired_product': // handled above if active is present, else skipped break; } } } $this->session->threadsTr = $threadsTr; } public function doWork(&$context) { if (!$this->session->threadsTr) $this->importThreads(); $this->threadsTr = $this->session->threadsTr; $q = $this->db3->queryResultOnly("SELECT * FROM ?_newsletter_member_subscriptions LIMIT ?d, 9000000", $context); while ($a = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return; $context++; $r = $this->getDi()->newsletterUserSubscriptionRecord; $r->list_id = $this->threadsTr[$a['thread_id']]; if (empty($r->list_id)) { print "List not found in amember4: " . $a['thread_id'] . "
      \n"; continue; } $r->user_id = $this->getDi()->db->selectCell("SELECT `id` FROM ?_data WHERE `table`='user' AND `key`='am3:id' AND `value`=?d", $a['member_id']); if (empty($r->user_id)) { print "User not found in amember4: " . $a['member_id'] . "
      \n"; continue; } $r->type = NewsletterUserSubscription::TYPE_USER; $r->is_active = $a['status'] > 0; $r->insert(); } return true; } } class Am_Import_Coupon3 extends Am_Import_Abstract { static $batches; function createBatch(Array $r){ if(!empty(self::$batches[$r['batch_id']])) { return self::$batches[$r['batch_id']]; } $batch = $this->getDi()->couponBatchRecord; $batch->begin_date = $r['begin_date']; $batch->comment = $r['comment']; if(strpos($r['discount'], '%')===false) { $batch->discount_type = 'number'; $batch->discount = $r['discount']; } else { $batch->discount_type = 'percent'; $batch->discount = doubleval($r['discount']); } $batch->expire_date = $r['expire_date']; $batch->is_disabled = $r['locked']; $batch->is_recurring = (int)@$r['is_recurring']; $batch->use_count = $r['use_count']; $batch->user_use_count = $r['member_use_count']; $batch->product_ids = $r['product_id'] ? implode(',', $this->getDi()->db->selectCol("select id from ?_data where `table`='product' and `key`='am3:id' and `value` in (?a)", array_map('intval', explode(',', $r['product_id'])))) : null; $batch->insert(); self::$batches[$r['batch_id']] = $batch->pk(); return self::$batches[$r['batch_id']]; } public function doWork(&$context) { // Imported coupons $importedCoupons = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='coupon' AND `key`='am3:id'"); $q = $this->db3->queryResultOnly("SELECT * FROM ?_coupon LIMIT ?d,9000000",$context); while ($r = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return; if (in_array($r['coupon_id'], $importedCoupons)) continue; $context++; $coupon = $this->getDi()->couponRecord; $coupon->code = $r['code']; $coupon->batch_id = $this->createBatch($r); $coupon->used_count = $r['used_count']; $coupon->insert(); $coupon->data()->set('am3:id', $r['coupon_id'])->update(); } return true; } } class Am_Import_Paypalprofileid3 extends Am_Import_Abstract { public function doWork(&$context) { $q = $this->getDi()->db->queryResultOnly("SELECT invoice_id FROM ?_invoice WHERE paysys_id='paypal-pro' LIMIT ?d,9000000",$context); while ($r = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return; $invoice = $this->getDi()->invoiceTable->load($r['invoice_id']); $context++; $paypal_profile_id = $invoice->data()->get('paypal-profile-id'); if(!empty($paypal_profile_id)) continue; $am3ids = explode(',',$invoice->data()->get('am3:id')); rsort($am3ids); $paypal_profile_id = ''; $i=0; while (empty($paypal_profile_id) && $i < count($am3ids)) { $data = $this->db3->selectCell("SELECT data FROM ?_payments WHERE payment_id=?",$am3ids[$i]); $i++; $data = unserialize($data); $paypal_profile_id = $data['PAYPAL_PROFILE_ID']; } if(empty($paypal_profile_id)) continue; $invoice->data()->set('paypal-profile-id', $paypal_profile_id)->update(); } return true; } } class Am_Import_Folder3 extends Am_Import_Abstract { public function doWork(&$context) { $q = $this->db3->queryResultOnly("SELECT * FROM ?_folders"); while ($r = $this->db3->fetchRow($q)) { $context++; if(!($folder = $this->getDi()->folderTable->findFirstBy(array('url'=>$r['url'])))) { $folder = $this->getDi()->folderRecord; $folder->path = $r['path']; $folder->url = $r['url']; $folder->method = 'new-rewrite';//$r['method']; $folder->title = $r['url']; $folder->hide = 1; $folder->insert(); } $folder->clearAccess(); $leave = false; foreach(explode(',',$r['product_ids']) as $pid){ if($pid == 'ALL') { $folder->addAccessListItem(-1, NULL, NULL, 'product_category_id'); $leave = true; } elseif($newpid = $this->getDi()->db->selectCell("SELECT id FROM ?_data WHERE `table`='product' AND `key`='am3:id' AND value=?",$pid)){ $folder->addAccessListItem($newpid, NULL, NULL, 'product_id'); $leave = true; } } if(!$leave) $folder->delete(); } /*if($this->db3->selectCell("SHOW TABLES LIKE ?",$this->db3->getPrefix().'products_links')) { //we have incremental links $q = $this->db3->queryResultOnly("SELECT * FROM ?_products_links"); while ($r = $this->db3->fetchRow($q)) { $context++; if(!($folder = $this->getDi()->folderTable->findFirstBy(array('url'=>$r['link_url'])))) { $folder = $this->getDi()->folderRecord; $folder->path = $r['link_path']; $folder->url = $r['link_url']; $folder->method = 'new-rewrite';//$r['method']; $folder->title = $r['link_title']; $folder->insert(); } if($newpid = $this->getDi()->db->selectCell("SELECT id FROM ?_data WHERE `table`='product' AND `key`='am3:id' AND value=?",$r['link_product_id'])) { $this->get_start_stop($r['link_start_delay'], $r['link_duration']); $folder->addAccessListItem($newpid, $r['link_start_delay'].'d', $r['link_duration'].'d', 'product_id'); } } }*/ return true; } function get_start_stop(&$start,&$stop) { if (preg_match('/^(-?\d+)(\w+)$/', strtolower($start), $regs)){ switch ($regs[2]){ case 'd': $i=1;break; case 'w': $i=7;break; case 'm': $i=31;break; case 'y': $i=365;break; default : $i=0; } $start = $regs[1]*$i; } else $start = 0; if(trim(strtolower($stop))=='lifetime'){ $stop = -1; return; } if (preg_match('/^(-?\d+)(\w+)$/', strtolower($stop), $regs)){ switch ($regs[2]){ case 'd': $i=1;break; case 'w': $i=7;break; case 'm': $i=31;break; case 'y': $i=365;break; default : $i=0; } $stop = $regs[1]*$i; $stop+=$start; } else $stop = -1; } } class Am_Import_Productlinks3 extends Am_Import_Abstract { public function doWork(&$context) { $q = $this->db3->queryResultOnly("SELECT * FROM ?_products"); while ($r = $this->db3->fetchRow($q)) { $context++; $r['data'] = unserialize($r['data']); if(!($link = $this->getDi()->linkTable->findFirstBy(array('title'=>$r['title'])))) { if($newpid = $this->getDi()->db->selectCell("SELECT id FROM ?_data WHERE `table`='product' AND `key`='am3:id' AND value=?",$r['product_id'])) { $link = $this->getDi()->linkRecord; $link->url = $r['data']['url']; $link->title = $r['title']; if(isset($link->url)) { $link->insert(); $link->addAccessListItem($newpid, NULL, NULL, 'product_id'); } foreach ((array)preg_split('/[\r\n]+/', trim($r['data']['add_urls'])) as $u) { if (!strlen($u)) continue; list($k, $v) = @preg_split('/\|/', $u); if (!$v) $v = $r['title']; if (!$k) continue; $link = $this->getDi()->linkRecord; $link->url = $k; $link->title = $v; $link->insert(); $link->addAccessListItem($newpid, NULL, NULL, 'product_id'); } } } } return true; } } class Am_Import_Integration3 extends Am_Import_Abstract { public function doWork(&$context) { $q = $this->db3->queryResultOnly("SELECT * FROM ?_products WHERE product_id > ? order by product_id",$context); while ($r = $this->db3->fetchRow($q)) { if (!$this->checkLimits()) return false; $context++; $r['data'] = unserialize($r['data']); if($newpid = $this->getDi()->db->selectCell("SELECT id FROM ?_data WHERE `table`='product' AND `key`='am3:id' AND value=?",$r['product_id'])) { $ints = array('vbulletin3_access' => 'vbulletin'); foreach($ints as $v3name => $v4name) { if(@count($r['data'][$v3name])) { foreach($r['data'][$v3name] as $v3group) { $create = true; foreach($this->getDi()->integrationTable->findBy(array('plugin' => $v4name)) as $integration) { if(!$create) continue; $vars = @unserialize($integration->vars); if($vars['gr'] == $v3group) { $create = false; $integration->addAccessListItem($newpid, NULL, NULL, 'product_id'); } } if($create) { $integration = $this->getDi()->integrationRecord; $integration->plugin = $v4name; $integration->vars = serialize(array('gr' => $v3group)); $integration->insert(); $integration->addAccessListItem($newpid, NULL, NULL, 'product_id'); } } } } } } return true; } } class AdminImport3Controller extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db3; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->amember3_db = null; $this->getSession()->amember3_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->amember3_import = null; } if (!$this->getSession()->amember3_db) return $this->askDbSettings(); $this->db3 = Am_Db::connect($this->getSession()->amember3_db); if (!$this->getSession()->amember3_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->amember3_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_".ucfirst($import) . "3"; $importer = new $class($this->db3, (array)@$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from aMember 3"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->amember3_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import3",array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function createCleanUpForm(){ $form = new Am_Form_Admin(); $total_products = $this->getDi()->db->selectCell('SELECT count(product_id) FROM ?_product'); $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='am3:id'"); $total_users = $this->getDi()->db->selectCell('SELECT count(user_id) FROM ?_user'); $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='am3:id'"); $form->addStatic()->setLabel('IMPORTANT INFO')->setContent(<<Clean UP process cannot be reversed, so if you don't understand what are you doing, please navigate away from this page!
      Sometimes this is necessary to remove all data from aMember's database and start import over. This form helps to do this in one go. Please make sure that you don't have any importand data in database, because it can't be restored after clean up. This is good idea to make a backup before "Clean Up" operation.
      DATA WHICH WILL BE REMOVED BY THIS OPERATION:
      User Accounts
      User Invoices/Payments
      User CC info
      Products enabled by setting below
      Affiliate data(if aff module is enabled)
      Newsletter subscriptions data(if newsletter module is enabled)
      Helpdesk tickets(if helpdesk module is enabled)
      EOL ); $form->addAdvCheckbox('remove_products')->setLabel('Remove products'); $form->addPassword('password')->setLabel('Please confirm your Admin password'); $form->addSaveButton('Clean Up'); return $form; } function cleanUpData($value){ $tables = array('access', 'access_cache', 'access_log', 'cc', 'coupon', 'coupon_batch', 'invoice', 'invoice_item', 'invoice_log', 'invoice_payment', 'invoice_refund', 'saved_pass', 'user', 'user_status', 'user_user_group'); if($this->getDi()->modules->isEnabled('aff')) $tables = array_merge($tables, array('aff_click', 'aff_commission', 'aff_lead', 'aff_payout', 'aff_payout_detail')); if(@$value['remove_products']) $tables = array_merge($tables, array('billing_plan', 'product', 'product_product_category')); if($this->getDi()->modules->isEnabled('helpdesk')) $tables = array_merge($tables, array('helpdesk_ticket', 'helpdesk_message')); if($this->getDi()->modules->isEnabled('newsletter')) $tables = array_merge($tables, array('newsletter_list', 'newsletter_user_subscription')); // Doing cleanup foreach($tables as $table){ $this->getDi()->db->query('delete from ?_'.$table); } // Doing data table separately. if(!@$value['remove_products']){ $where = "where `table` <> 'product' and `table`<>'billing_plan'"; }else $where = ''; $this->getDi()->db->query('delete from ?_data '.$where); $this->redirectHtml($this->getDi()->url('admin-import3',null,false), 'Records removed'); } function cleanAction(){ $this->form = $this->createCleanUpForm(); $this->form->addDataSource($this->_request); if($this->form->isSubmitted() && $this->form->validate()){ $value = $this->form->getValue(); // Validate password; $admin = $this->getDi()->authAdmin->getUser(); if(!$admin->checkPassword($value['password'])){ $this->form->setError('Incorrect Password!'); }else{ $this->cleanUpData($this->form->getValue()); } } $this->view->title = "Clean up Database"; $this->view->content = (string)$this->form; $this->view->display('admin/layout.phtml'); } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->amember3_import = array( 'import' => $val['import'], 'user' => @$val['user'], 'product' => @$val['product'] ); $this->_redirect('admin-import3'); return; } } $this->view->title = "Import aMember3 Information"; $this->view->content = (string)$this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='am3:id'"); $total = $this->db3->selectCell("SELECT COUNT(*) FROM ?_products"); if($total_products = $this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_product")) $form->addStatic() ->setLabel(___('Clean up v4 Database')) ->setContent( sprintf(___('Use this %slink%s to delete data from aMember v4 database and use clean database for import'), '', '')); $cb = $form->addGroup(); if ($imported_products >= $total) { $cb->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); $cb->addStatic()->setContent('
      Keep the same Product IDs'); $keep_id_chkbox = $cb->addCheckbox('product[keep_product_id]'); if ($imported_products < $total // imported not all products && $this->db3->selectCell("SELECT COUNT(*) FROM ?_products WHERE data like '%subusers_count%'") // subusers plugin is used at am3 installation && !in_array('subusers', $this->getDi()->modules->getEnabled())) // subusers module is not enabled at am4 installation { $cb->addStatic()->setContent('
      Enable [subusers] module in Setup/Configuration to import subusers information'); } if($total_products){ $keep_id_chkbox->setAttribute('disabled'); $cb->addStatic() ->setContent('Product table have records already. Please use Clean Up if you want to keep the same product IDs'); } // Import coupons $imported_coupons = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='coupon' AND `key`='am3:id'"); $totalc = $this->db3->selectCell("SELECT COUNT(*) FROM ?_coupon"); if($imported_products){ if ($imported_coupons >= $totalc) { $cb = $form->addStatic()->setContent("Imported ($imported_coupons of $totalc)"); } else { $cb = $form->addRadio('import', array('value' => 'coupon')); } $cb->setLabel('Import Coupons'); } //import folders without actual protection /*if ($imported_products) { $total = $this->db3->selectCell("SELECT COUNT(*) FROM ?_folders"); if ($total){ $cb = $form->addRadio('import', array('value' => 'folder')); $cb->setLabel('Import Folders'); } } //import integrations if ($imported_products) { $cb = $form->addRadio('import', array('value' => 'integration')); $cb->setLabel('Import Integrations'); } //import product links if ($imported_products) { $cb = $form->addRadio('import', array('value' => 'productlinks')); $cb->setLabel('Import Product Links'); }*/ if ($imported_products && ($imported_coupons||!$totalc)) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='am3:id'"); $total = $this->db3->selectCell("SELECT COUNT(*) FROM ?_members"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); $cb->addStatic()->setContent('
      Do not import pending users'); $cb->addCheckbox('user[exclude_pending]'); $cb->addStatic()->setContent('
      Keep the same user IDs'); $keep_id_chkbox = $cb->addCheckbox('user[keep_user_id]'); if($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_user")){ $keep_id_chkbox->setAttribute('disabled'); $cb->addStatic() ->setContent('User database have records already. Please use Clean Up if you want to keep the same user IDs'); } } $cb->setLabel('Import User and Payment Records'); if ($imported_users ) { if ($this->getDi()->modules->isEnabled('aff')) { $imported_comm = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='aff_commission' AND `key`='am3:id'"); $total = $this->db3->selectCell("SELECT COUNT(*) FROM ?_aff_commission"); $imported_clicks = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='aff_click' AND `key`='am3:id'"); $total_clicks = $this->db3->selectCell("SELECT COUNT(*) FROM ?_aff_clicks"); $gr =$form->addGroup() ->setLabel('Import Affiliate Commissions and Refs'); if ($imported_comm>=$total) { $gr->addStatic()->setContent("Imported ($imported_comm of $total)"); } else { if ($imported_comm) $gr->addStatic()->setContent("partially imported ($imported_comm of $total total)

      "); $gr->addRadio('import', array('value' => 'aff')); } $gr =$form->addGroup() ->setLabel('Import Affiliate Clicks'); if ($imported_clicks>=$total_clicks) { $gr->addStatic()->setContent("Imported ($imported_clicks of $total_clicks)"); } else { if ($imported_clicks) $gr->addStatic()->setContent("partially imported ($imported_clicks of $total_clicks total)

      "); $gr->addRadio('import', array('value' => 'affclicks')); } $gr =$form->addGroup() ->setLabel('Import Affiliate Banners and Links'); $gr->addRadio('import', array('value' => 'affbanners')); $gr->addStatic()->setContent("Workaround to have old links working"); } else $form->addStatic()->setContent('Enable [aff] module in Setup/Configuration to import information'); if ($this->getDi()->modules->isEnabled('newsletter')) $form->addRadio('import', array('value' => 'newsletter')) ->setLabel('Import Newsletter Threads and Subscriptions'); else $form->addStatic()->setContent('Enable [newsletter] module in Setup/Configuration to import information'); } } //import PAYPAL_PROFILE_ID for previously wrongly imported invoices /*if ($imported_users) { $total = $this->db3->selectCell("SELECT COUNT(*) FROM ?_folders"); if ($total){ $cb = $form->addRadio('import', array('value' => 'paypalprofileid')); $cb->setLabel("Import Paypal Profile ID's"); } }*/ $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->amember3_db = $this->form->getValue(); $this->_redirect('admin-import3'); } else { $this->view->title = "Import aMember3 Information"; $this->view->content = (string)$this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('aMember3 MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('aMember3 MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('aMember3 MySQL Password'); $form->addText('db')->setLabel('aMember3 MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('aMember3 Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'amember_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_members LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } class InvoiceCreator_Braintree extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'braintree'; } function doWork(){ parent::doWork(); // First make sure that user's record have ccInfo created; $storedCc = Am_Di::getInstance()->ccRecordTable->findFirstByUserId($this->user->pk()); if(!$storedCc){ $storedCc = Am_Di::getInstance()->CcRecordRecord; $storedCc->user_id = $this->user->pk(); $storedCc->cc_expire = '1237'; $storedCc->cc_number = '0000000000000000'; $storedCc->cc = $storedCc->maskCc(@$storedCc->cc_number); $storedCc->insert(); } if($user_profile = $this->v3user['data']['braintree_customer_vault_id']) { $this->user->data()->set('braintree_customer_id', $user_profile); } $this->user->data()->update(); } } class InvoiceCreator_BeanstreamRemote extends InvoiceCreator_Standard { function __construct($paysys_id) { $this->paysys_id = 'beanstream-remote'; } function doWork() { $t_ = $this->getDi()->dateTime; $t_->modify('-1 days'); $rebill_date = $t_->format('Y-m-d'); foreach ($this->groups as $list) { $byDate = array(); $totals = array(); // totals by date $coupon = null; $cancelled = null; $invoice = null; foreach ($list as $p) { $d = date('Y-m-d', strtotime($p['tm_added'])); $byDate[ $d ][] = $p; @$totals[ $d ] += $p['amount']; if(!empty($p['data'][0]['coupon'])) $coupon = $p['data'][0]['coupon']; if(!empty($p['data']['CANCELLED_AT'])) $cancelled = date('Y-m-d H:i:s', strtotime($p['data']['CANCELLED_AT'])); elseif(@$p['data']['CANCELLED']) $cancelled = date('Y-m-d H:i:s', time()); } if((count($list) == 1) && (!$list[0]['data']['beanstream_rbaccountid']) && ($rbAccountId = $this->findRbAccountId($list[0]))) { $invoice = $this->getDi()->invoiceTable->findFirstByData('rb-account-id', $rbAccountId); } if(!$invoice) { $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $pidItems = array(); foreach ($list as $p) { $pid = $p['product_id']; if (@$pidItems[$pid]) continue; $pidItems[$pid] = 1; $newP = $this->_translateProduct($pid); if ($newP) { $pr = Am_Di::getInstance()->productTable->load($newP); $item = $invoice->createItem($pr); if (empty($invoice->first_period)) $invoice->first_period = $pr->getBillingPlan()->first_period; } else { $item = $invoice->createItem(new ImportedProduct($pid)); $invoice->first_period = '1d'; } $item->add(1); $item->_calculateTotal(); $invoice->addItem($item); } if(!is_null($coupon)) { $invoice->setCouponCode($coupon); $invoice->validateCoupon(); } $invoice->currency = $item->currency ? $item->currency : Am_Currency::getDefault(); $invoice->calculate(); $invoice->paysys_id = $this->paysys_id; $invoice->tm_added = $list[0]['tm_added']; $invoice->tm_started = $list[0]['tm_completed']; $invoice->public_id = $list[0]['payment_id']; $invoice->first_total = current($totals); if($invoice->rebill_times){ // Recurring if($cancelled) { $invoice->tm_cancelled = $cancelled; $invoice->status = Invoice::RECURRING_CANCELLED; }else { $invoice->status = Invoice::RECURRING_ACTIVE; $invoice->rebill_date = $rebill_date; } }else{ $invoice->status = Invoice::PAID; } foreach ($list as $p) $pidlist[] = $p['payment_id']; $invoice->data()->set('am3:id', implode(',', $pidlist)); if(empty($invoice->currency)) $invoice->currency=Am_Currency::getDefault(); //REQUIRED PART TO IMPORT RECURRING SUBCRIPTIONS if (@$p['data']['beanstream_rbaccountid']) $invoice->data()->set('rb-account-id', $p['data']['beanstream_rbaccountid']); $invoice->insert(); } // insert payments and access foreach ($list as $p) { $newP = $this->_translateProduct($p['product_id']); if (empty($p['data']['ORIG_ID'])) { $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->currency = $invoice->currency; $payment->invoice_id = $invoice->pk(); $payment->invoice_public_id = $invoice->public_id; if (count($list) == 1) { $payment->amount = $p['amount']; } elseif ($p['data']['BASKET_PRICES']) { $payment->amount = array_sum($p['data']['BASKET_PRICES']); } else { $payment->amount = 0; foreach ($list as $pp) if (@$p['data']['ORIG_ID'] == $p['payment_id']) $payment->amount += $pp['amount']; } $payment->paysys_id = $this->paysys_id; $payment->dattm = $p['tm_completed']; $payment->receipt_id = $p['receipt_id']; $payment->transaction_id = $p['receipt_id'] . '-import-' . mt_rand(10000, 99999).'-'.intval($p['payment_id']); $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='am3:id',`value`=?", $payment->pk(), $p['payment_id']); } if ($newP) // if we have imported that product { $a = $this->getDi()->accessRecord; $a->setDisableHooks(); $a->user_id = $this->user->user_id; $a->begin_date = $p['begin_date']; $a->expire_date = $p['expire_date']; $a->invoice_id = $invoice->pk(); $a->invoice_payment_id = $payment->pk(); $a->product_id = $newP; $a->insert(); } } } } protected function findRbAccountId($currentPayment) { $rbAccountId = false; foreach ($this->groups as $list) { $p = $list[0]; if($p['payment_id'] >= $currentPayment['payment_id']) break; if($p['product_id'] != $currentPayment['product_id']) continue; if(isset($p['data']['beanstream_rbaccountid'])) $rbAccountId = $p['data']['beanstream_rbaccountid']; } return $rbAccountId; } } class InvoiceCreator_MicropaymentDbt extends InvoiceCreator_Standard{ function __construct($paysys_id) { $this->paysys_id = 'micropayment-dbt'; } function doWork(){ parent::doWork(); // First make sure that user's record have ccInfo created; $storedCc = Am_Di::getInstance()->ccRecordTable->findFirstByUserId($this->user->pk()); if(!$storedCc){ $storedCc = Am_Di::getInstance()->CcRecordRecord; $storedCc->user_id = $this->user->pk(); $storedCc->cc_expire = '1237'; $storedCc->cc_number = '0000000000000000'; $storedCc->cc = $storedCc->maskCc(@$storedCc->cc_number); $storedCc->insert(); } if($user_profile = $this->v3user['data']['micropayment_dbt_customer_vault_id']) { $this->user->data()->set('micropayment_dbt_customer_vault_id', $user_profile); } $this->user->data()->update(); } } PK\ّ&default/controllers/FileController.phpnu[_getFile(self::CD_ATTACHMENT); } public function getAction() { return $this->_getFile(self::CD_INLINE); } protected function _getFile($attachment) { $path = $this->getParam('path'); if ($path[0] != '.') {$path = '.' . $path;} $file = $this->getDi()->uploadTable->findFirstByPath($path); if (!$file) { throw new Am_Exception_InputError('File Not Found'); } if (!$this->getDi()->uploadAcl->checkPermission($file, Am_Upload_Acl::ACCESS_READ, $this->getDi()->auth->getUser())) { throw new Am_Exception_AccessDenied; } return $this->pushFile($file, $attachment); } protected function pushFile(Upload $file, $attachment=self::CD_INLINE) { $this->_helper->sendFile($file->getFullPath(), $file->getType(), array( 'disposition' => $attachment, 'filename' => $file->getName(), 'cache' => array( 'max-age' => 3600 ) )); } }PK\ZZ8default/controllers/AdminImportYourMembersController.phpnu[packs); } function getAll() { return $this->packs; } } class AdminImportYourMembersController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_yourmembers; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->yourmembers_db = null; $this->getSession()->yourmembers_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->yourmembers_import = null; } if (!$this->getSession()->yourmembers_db) return $this->askDbSettings(); $this->db_yourmembers = Am_Db::connect($this->getSession()->yourmembers_db); if (!$this->getSession()->yourmembers_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->yourmembers_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_yourmembers, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from Wordpress Your Members Plugin"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->yourmembers_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-your-members", array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->yourmembers_import = array( 'import' => $val['import'], 'user' => @$val['user'], ); $this->_redirect('admin-import-your-members'); return; } } $this->view->title = "Import Wordpress Your Members Plugin Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='ym:id'"); $memberTypes = unserialize($this->db_yourmembers->selectCell("SELECT option_value FROM ?_options where option_name='ym_packs'")); $total = $memberTypes->getCount(); if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); // Import coupons $imported_coupons = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='coupon' AND `key`='ym:id'"); $totalc = $this->db_yourmembers->selectCell("SELECT COUNT(*) FROM ?_ym_coupon"); if ($imported_products) { if ($imported_coupons >= $totalc) { $cb = $form->addStatic()->setContent("Imported ($imported_coupons of $totalc)"); } else { $cb = $form->addRadio('import', array('value' => 'coupon')); } $cb->setLabel('Import Coupons'); } if ($imported_products && ($imported_coupons || !$totalc)) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='ym:id'"); $total = $this->db_yourmembers->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->yourmembers_db = $this->form->getValue(); $this->_redirect('admin-import-your-members'); } else { $this->view->title = "Import Wordpress Your Members Plugin Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('Wordpress MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('Wordpress MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('Wordpress MySQL Password'); $form->addText('db')->setLabel('Wordpress MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('Wordpress Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'wp_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_ym_transaction LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } abstract class InvoiceCreator_Abstract { /** User */ protected $user; // all payments protected $payments = array(); // grouped by invoice protected $groups = array(); // prepared Invoices protected $invoices = array(); // protected $paysys_id; /** @var DbSimple_Mypdo */ protected $db_yourmembers; public function getDi() { return Am_Di::getInstance(); } public function __construct($paysys_id, DbSimple_Interface $db) { $this->db_yourmembers = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $payments) { $this->user = $user; // foreach ($payments as $p) // { // $this->payments[$p['id']] = $p; // } $this->payments = $payments; $this->groupByInvoice(); $this->beforeWork(); return $this->doWork(); } function beforeWork() { } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='ym:id'"); } return @$cache[$pid]; } } class Am_Import_Coupon3 extends Am_Import_Abstract { static $batches; function createBatch(Array $r) { } public function doWork(&$context) { throw new Am_Exception_InputError("Not implemented"); } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_yourmembers; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_wordpress, array $options = array()) { $this->db_yourmembers = $db_wordpress; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='ym:id'"); $products = unserialize($this->db_yourmembers->selectCell("SELECT option_value FROM ?_options where option_name='ym_packs'")); foreach ($products->getAll() as $r) { if (in_array($r['id'], $importedProducts)) continue; $context++; $p = $this->getDi()->productRecord; $p->title = $r['account_type']; $p->description = $r['description']; $p->is_disabled = $r['hide_subscription'] ? 1 : 0; $p->data()->set('ym:id', $r['id']); $p->currency = $r['currency']; $p->insert(); $bp = $p->createBillingPlan(); $bp->title = 'default'; $bp->second_price = $r['cost']; $bp->second_period = $r['duration'] . $r['duration_type']; if ($r['trial_on']) { $bp->first_price = $r['trial_cost']; $bp->first_period = $r['trial_duration'] . $r['trial_duration_type']; } else { $bp->first_price = $bp->second_price; $bp->first_period = $bp->second_period; } $bp->rebill_times = $r['num_cycles'] ? $r['num_cycles'] - 1 : IProduct::RECURRING_REBILLS; $bp->insert(); $p->default_billing_plan_id = $bp->pk(); $p->data()->set('zombaio_pricing_id', $r['zombaio_price_id'])->update(); $p->update(); } return true; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { //$crypt = $this->getDi()->crypt; $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='ym:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_yourmembers->queryResultOnly("SELECT u.*, um1.meta_value as first_name, um2.meta_value as last_name FROM ?_users u LEFT JOIN ?_usermeta um1 on u.ID= um1.user_id and um1.meta_key = 'first_name' LEFT JOIN ?_usermeta um2 on u.ID= um2.user_id and um2.meta_key = 'last_name' WHERE u.ID > ?d ORDER BY u.ID {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_yourmembers->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->email = $r['user_email']; $u->added = $r['user_registered']; $u->login = $r['user_login']; $u->name_f = (string) $r['first_name']; $u->name_l = (string) $r['last_name']; $u->is_approved = 1; $u->data()->set('ym:id', $r['ID']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time $u->pass = $r['user_pass']; try { $u->insert(); $this->insertPayments($r['ID'], $u); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } function insertPayments($id, User $u) { $data = $this->db_yourmembers->selectPage($total, "select t.*, a.name as action from ?_ym_transaction t left join ?_ym_transaction_action a on t.action_id = a.id where user_id=? order by unixtime", $id); $data = $data ? $data : array(); $payments = array(); foreach ($data as $d) { if (!isset($payments[$d['transaction_id']])) $payments[$d['transaction_id']] = new YourMembers_Transaction($u); $payments[$d['transaction_id']]->addTransactionData($d); } InvoiceCreator_Abstract::factory('standard', $this->db_yourmembers)->process($u, $payments); } } class YourMembers_Transaction { var $ipn = array(); const IPN = 10; const PRODUCT_ID = 12; const STATUS_UPDATE = 11; const ACCESS_EXTENSION = 9; const PAYMENT = 1; const ACCESS_EXPIRITY = 8; const ACCOUNT_TYPE = 2; var $product_id = null; var $user; var $paysys; var $access; function __construct(User $user) { $this->user = $user; } function addTransactionData($data) { switch ($data['action_id']) { case self::IPN : $this->ipn = unserialize($data['data']); break; case self::PRODUCT_ID : $this->product_id = $data['data']; break; case self::PAYMENT : $this->payment = $data; break; case self::ACCESS_EXTENSION: $this->access = $data; break; case self::STATUS_UPDATE: if (preg_match('/Cancelled/', $data['data']) && empty($this->cancel)) { $this->cancel = $data; } break; case self::ACCOUNT_TYPE: case self::ACCESS_EXPIRITY: break; default: throw new Am_Exception_InternalError("Unknown transaction type: " . $data['action_name']); } } function getProductId() { if (is_null($this->product_id)) { $this->product_id = Am_Di::getInstance()->db->selectCell("select product_id from ?_access where user_id =? order by begin_date desc limit 1", $this->user->pk()); } return $this->product_id; } function process() { if (!empty($this->cancel)) { $invoice = YourMembers_IPN::create($this)->getInvoice(); if (empty($invoice)) return; $invoice->setCancelled(); $invoice->update(); }else if (!$this->product_id) return; // Unable to find product ID here; if (!empty($this->ipn['ym_process'])) { $this->paysys = $this->ipn['ym_process']; } $product = Am_Di::getInstance()->productTable->findFirstByData('ym:id', $this->product_id); if (!$product) return; if (!empty($this->payment)) { if (empty($this->ipn)) { return; } if (empty($this->paysys)) return; $ipn = YourMembers_IPN::create($this); $invoice = $ipn->getInvoice(); $invoice_payment = Am_Di::getInstance()->invoicePaymentRecord; $invoice_payment->amount = $ipn->getAmount(); $invoice_payment->currency = $invoice->currency; $invoice_payment->dattm = date('Y-m-d H:i:s', $this->payment['unixtime']); $invoice_payment->invoice_id = $invoice->pk(); $invoice_payment->paysys_id = $ipn->getPaysysId(); $invoice_payment->receipt_id = $ipn->getReceiptId(); $invoice_payment->transaction_id = sprintf('import-%s', $invoice_payment->receipt_id); $invoice_payment->user_id = $this->user->pk(); $invoice_payment->insert(); } if (!empty($this->access)) { $access = Am_Di::getInstance()->accessRecord; $access->user_id = $this->user->pk(); $access->setDisableHooks(); $access->begin_date = date('Y-m-d', $this->access['unixtime']); $access->expire_date = date('Y-m-d', $this->access['data']); $access->product_id = $product->pk(); if (!empty($invoice)) $access->invoice_id = $invoice->pk(); if (!empty($invoice_payment)) $access->invoice_payment_id = $invoice_payment->pk(); $access->insert(); } } function findInvoiceId() { } } class YourMembers_IPN { protected $transaction; function __construct(YourMembers_Transaction $transaction) { $this->transaction = $transaction; } function getInvoiceId() { return null; } function getPaysysId() { return null; } function getAmount() { return null; } function getReceiptId() { return null; } function getInvoice() { $invoice_id = $this->getInvoiceId(); if (empty($invoice_id)) return null; if (preg_match('/^buy_subscription_(.*)/', $invoice_id, $r)) $invoice_id = $r[1]; $invoice_id = $this->getPaysysId() . "_" . $invoice_id; $invoice = Am_Di::getInstance()->invoiceTable->findFirstBy(array('public_id' => $invoice_id)); if (!$invoice) { $invoice = Am_Di::getInstance()->invoiceRecord; $invoice->user_id = $this->transaction->user->pk(); $invoice->add($product = Am_Di::getInstance()->productTable->findFirstByData('ym:id', $this->transaction->product_id), 1); $invoice->calculate(); $invoice->tm_added = date('Y-m-d H:i:s', $this->transaction->payment['unixtime']); $invoice->tm_started = date('Y-m-d H:i:s', $this->transaction->payment['unixtime']); $invoice->public_id = $invoice_id; $invoice->paysys_id = $this->getPaysysId(); $invoice->status = Invoice::PAID; $invoice->data()->set('ym:id', $invoice_id); $invoice->insert(); $invoice->public_id = $invoice_id; $invoice->update(); } return $invoice; } /** * * @param YourMembers_Transaction $transaction * @return YourMembers_IPN * @throws Am_Exception_InternalError */ static function create(YourMembers_Transaction $transaction) { $cname = "YourMembers_IPN_" . $transaction->paysys; if (!class_exists($cname, false)) { return new self($transaction); } return new $cname($transaction); } } class YourMembers_IPN_ym_zombaio extends YourMembers_IPN { function getInvoiceId() { return $this->transaction->ipn['extra']; } function getPaysysId() { return 'zombaio'; } function getAmount() { return $this->transaction->ipn['Amount']; } function getReceiptId() { return $this->transaction->ipn['SUBSCRIPTION_ID'] . '-' . $this->transaction->ipn['TRANSACTION_ID']; } } class YourMembers_IPN_ym_paypal extends YourMembers_IPN { function getInvoiceId() { return $this->transaction->ipn['item_number']; } function getPaysysId() { return 'paypal'; } function getAmount() { return $this->transaction->ipn['mc_gross'] ? $this->transaction->ipn['mc_gross'] : $this->transaction->ipn['payment_gross']; } function getReceiptId() { return $this->transaction->ipn['txn_id']; } } class InvoiceCreator_Standard extends InvoiceCreator_Abstract { function doWork() { $user = $this->user; foreach ($this->groups as $oid => $list) { $list->process(); } $this->user->checkSubscriptions(); } public function groupByInvoice() { $this->groups = $this->payments; } } PK\ukk3default/controllers/AdminPlayerConfigController.phpnu[createForm(); $config = $this->getRequest()->getParam('config'); $config = $config ? unserialize($config) : $this->getDi()->config->get('flowplayer', array()); $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array( $config ) )); echo (string) $form; } function updateAction() { $form = $this->createForm(); $form->setDataSources(array( new HTML_QuickForm2_DataSource_SuperGlobal('GET') )); $val = $this->filterValues($form->getValue()); if ($this->getRequest()->getParam('_id') != '--custom--') { $this->presetUpdate($this->getRequest()->getParam('_id'), $val); } echo serialize($val); } protected function presetUpdate($id, $val) { $presets = $this->getDi()->store->getBlob('flowplayer-presets'); $presets = @unserialize($presets) ? unserialize($presets) : array(); $presets[$id]['config'] = $val; $this->getDi()->store->setBlob('flowplayer-presets', serialize($presets)); } protected function filterValues($values) { foreach ($values as $k => $v) { if ($k[0] == '_') unset($values[$k]); } return $values; } function presetSaveAction() { $presets = $this->getDi()->store->getBlob('flowplayer-presets'); $presets = @unserialize($presets) ? unserialize($presets) : array(); $id = 'preset-' . mktime(); $presets[$id] = array( 'name' => $this->getRequest()->getParam('name'), 'config' => unserialize($this->getRequest()->getParam('config')) ); $this->getDi()->store->setBlob('flowplayer-presets', serialize($presets)); $this->_response->ajaxResponse(array( 'id' => $id, 'name' => $this->getRequest()->getParam('name'), 'config' => $this->getRequest()->getParam('config') )); } function presetDeleteAction() { $id = $this->getRequest()->getParam('_id'); if (!$id) throw new Am_Exception_InputError("_id is note defined in request"); $presets = $this->getDi()->store->getBlob('flowplayer-presets'); $presets = @unserialize($presets) ? unserialize($presets) : array(); if (!isset($presets[$id])) throw new Am_Exception_InputError(sprintf('Can not find preset with id [%s]', $id)); $config = serialize($presets[$id]['config']); foreach ($this->getDi()->videoTable->findByConfig($id) as $video) { $video->config = $config; $video->save(); } unset($presets[$id]); $this->getDi()->store->setBlob('flowplayer-presets', serialize($presets)); $this->_response->ajaxResponse(array( 'id' => $id, 'config' => $config )); } function presetAction() { $form = new Am_Form_Admin('player-config-preset'); $form->addElement('text', 'name') ->setLabel(___('Name of Preset')); echo (string) $form; } /** * * @return Am_Form_Admin */ function createForm() { $form = new Am_Form_Admin('player-config'); $setupForm = new Am_Form_Setup_VideoPlayer(); $setupForm->setupElements($form); return $form; } } PK\ v>``&default/controllers/TestController.phpnu[vars['filter'] as $v) if ($v) return true; } public function setDateField($dateField) { $this->dateField = $dateField; } protected function applyFilter() { class_exists('Am_Form', true); $filter = (array)$this->vars['filter']; $q = $this->grid->getDataSource(); $dateField = $this->vars['filter']['datf']; if (!array_key_exists($dateField, $this->getDateFieldOptions())) throw new Am_Exception_InternalError (sprintf('Unknown date field [%s] submitted in %s::%s', $dateField, __CLASS__, __METHOD__)); /* @var $q Am_Query */ if ($filter['dat1']) $q->addWhere("t.$dateField >= ?", Am_Form_Element_Date::createFromFormat(null, $filter['dat1'])->format('Y-m-d 00:00:00')); if ($filter['dat2']) $q->addWhere("t.$dateField <= ?", Am_Form_Element_Date::createFromFormat(null, $filter['dat2'])->format('Y-m-d 23:59:59')); if (@$filter['text']) { switch (@$filter['type']) { case 'invoice': $q->addWhere('(t.invoice_id=? OR t.invoice_public_id=?)', $filter['text'], $filter['text']); break; case 'receipt': $q->addWhere('receipt_id LIKE ?', '%'.$filter['text'].'%'); break; case 'coupon': $q->leftJoin('?_invoice', 'i', 't.invoice_id=i.invoice_id'); $q->addWhere('i.coupon_code=?', $filter['text']); break; } } if (@$filter['product_id']){ $q->leftJoin('?_invoice_item', 'ii', 't.invoice_id=ii.invoice_id') ->addWhere('ii.item_type=?', 'product') ->addWhere('ii.item_id=?', $filter['product_id']); } if (@$filter['dont_show_refunded']) $q->addWhere('t.refund_dattm IS NULL'); } public function renderInputs() { $prefix = $this->grid->getId(); $filter = (array)$this->vars['filter']; $filter['datf'] = Am_Html::escape(@$filter['datf']); $filter['dat1'] = Am_Html::escape(@$filter['dat1']); $filter['dat2'] = Am_Html::escape(@$filter['dat2']); $filter['text'] = Am_Html::escape(@$filter['text']); $pOptions = array('' => '-' . ___('Filter by Product') . '-'); $pOptions = $pOptions + Am_Di::getInstance()->productTable->getOptions(); $pOptions = Am_Html::renderOptions( $pOptions, @$filter['product_id'] ); $options = Am_Html::renderOptions(array( '' => '***', 'invoice' => ___('Invoice'), 'receipt' => ___('Payment Receipt'), 'coupon' => ___('Coupon Code') ), @$filter['type']); $dOptions = $this->getDateFieldOptions(); if (count($dOptions) === 1) { $dSelect = sprintf('%s: ', current($dOptions), $prefix, key($dOptions)); } else { $dSelect = sprintf('', $prefix, Am_Html::renderOptions($dOptions, @$filter['datf'])); } $start = ___('Start Date'); $end = ___('End Date'); $dsr = $this->renderDontShowRefunded(); return << $pOptions $dSelect

      $dsr CUT; } public function renderDontShowRefunded() { $filter = (array) $this->vars['filter']; return sprintf('', $this->grid->getId(), $this->grid->getId(), (@$this->vars['filter']['dont_show_refunded'] == 1 ? 'checked' : ''), Am_Html::escape(___('do not show refunded payments')) ); } public function getDateFieldOptions() { return array('dattm' => ___('Payment Date')); } public function renderStatic() { return << jQuery(function(){ jQuery(document).ajaxComplete(function(){ jQuery('input.datepicker').datepicker({ defaultDate: window.uiDefaultDate, dateFormat:window.uiDateFormat, changeMonth: true, changeYear: true }).datepicker("refresh"); }); }); CUT; } } class AdminUserPaymentsController extends Am_Mvc_Controller { public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission('grid_invoice', 'browse') || $admin->hasPermission('grid_access', 'browse') || $admin->hasPermission('grid_payment', 'browse'); } function preDispatch() { $this->user_id = intval($this->_request->user_id); if (!in_array($this->_request->getActionName(), array('log', 'data', 'invoice'))) { if ($this->user_id <= 0) throw new Am_Exception_InputError("user_id is empty in " . get_class($this)); } $this->setActiveMenu('users-browse'); return parent::preDispatch(); } public function createAdapter() { $adapter = $this->_createAdapter(); $query = $adapter->getQuery(); $query->addWhere('t.user_id=?d', $this->user_id); return $adapter; } public function invoiceDetailsAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'browse'); $this->getDi()->plugins_payment->loadEnabled(); $this->view->invoice = $this->getDi()->invoiceTable->load($this->getInt('id')); $this->view->display('admin/_user_invoices-details.phtml'); } public function paymentAction() { $totalFields = array(); $query = new Am_Query($this->getDi()->invoicePaymentTable); $query->leftJoin('?_user', 'm', 'm.user_id=t.user_id') ->addField("(SELECT GROUP_CONCAT(item_title SEPARATOR ', ') FROM ?_invoice_item WHERE invoice_id=t.invoice_id)", 'items') ->addField('m.login', 'login') ->addField('m.email', 'email') ->addField('m.street', 'street') ->addField('m.city', 'city') ->addField('m.state', 'state') ->addField('m.country', 'country') ->addField('m.phone', 'phone') ->addField('m.zip', 'zip') ->addField("concat(m.name_f,' ',m.name_l)", 'name') ->addField('t.invoice_public_id', 'public_id') ->addWhere('t.user_id=?', $this->user_id); $query->setOrder("invoice_payment_id", "desc"); $grid = new Am_Grid_Editable('_payment', ___('Payments'), $query, $this->_request, $this->view); $grid->actionsClear(); $grid->addField(new Am_Grid_Field_Date('dattm', ___('Date/Time'))); $grid->addField('invoice_id', ___('Invoice')) ->setGetFunction(array($this, '_getInvoiceNum')) ->addDecorator( new Am_Grid_Field_Decorator_Link( 'admin-user-payments/index/user_id/{user_id}#invoice-{invoice_id}', '_top')); $grid->addField('receipt_id', ___('Receipt')); $grid->addField('paysys_id', ___('Payment System')); array_push($totalFields, $grid->addField('amount', ___('Amount'), true, 'right')->setGetFunction(array($this, '_getAmount'))); if ($this->getDi()->plugins_tax->getEnabled()) { array_push($totalFields, $grid->addField('tax', ___('Tax'), true, 'right')->setGetFunction(array($this, '_getTax'))); } $grid->addField(new Am_Grid_Field_Expandable('refund_amount', ___('Refunded'), true, 'right')) ->setPlaceholder(function($amt, $r){ return sprintf('%s', Am_Currency::render($amt, $r->currency)); }) ->setAjax('admin-payments/get-refunds?id={invoice_payment_id}') ->setIsNeedExpandFunction(function($val, $obj, $field, $fieldObj){ return !is_null($obj->$field); }); $grid->addField('items', ___('Items')); $grid->setFilter(new Am_Grid_Filter_UserPayments); $action = new Am_Grid_Action_Export(); $action->addField(new Am_Grid_Field('dattm', ___('Date Time'))) ->addField(new Am_Grid_Field('receipt_id', ___('Receipt'))) ->addField(new Am_Grid_Field('paysys_id', ___('Payment System'))) ->addField(new Am_Grid_Field('amount', ___('Amount'))) ->addField(new Am_Grid_Field('tax', ___('Tax'))) ->addField(new Am_Grid_Field_Date('refund_dattm', ___('Refunded'))) ->addField(new Am_Grid_Field('login', ___('Username'))) ->addField(new Am_Grid_Field('name', ___('Name'))) ->addField(new Am_Grid_Field('email', ___('Email'))) ->addField(new Am_Grid_Field('street', ___('Street'))) ->addField(new Am_Grid_Field('city', ___('City'))) ->addField(new Am_Grid_Field('state', ___('State'))) ->addField(new Am_Grid_Field('country', ___('Country'))) ->addField(new Am_Grid_Field('phone', ___('Phone'))) ->addField(new Am_Grid_Field('zip', ___('Zip Code'))) ->addField(new Am_Grid_Field('items', ___('Items'))) ->addField(new Am_Grid_Field('invoice_id', ___('Invoice'))) ->addField(new Am_Grid_Field('public_id', ___('Invoice (Public Id)'))) ; $grid->actionAdd($action); if ($this->getDi()->config->get('send_pdf_invoice')) { $grid->actionAdd(new Am_Grid_Action_ExportPdf); } $action = $grid->actionAdd(new Am_Grid_Action_Total()); foreach ($totalFields as $f) $action->addField($f, 'ROUND(%s / base_currency_multi, 2)'); $grid->runWithLayout('admin/user-layout.phtml'); } function _getInvoiceNum(Am_Record $invoice) { return $invoice->invoice_id . '/' . $invoice->public_id; } function _getAmount(Am_Record $p) { return Am_Currency::render($p->amount, $p->currency); } function _getTax(InvoicePayment $p) { return Am_Currency::render($p->tax, $p->currency); } public function resendPaymentLinkAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); $invoice = $this->getDi()->invoiceTable->load($this->getParam('invoice_id')); $form = new Am_Form_Admin('add-invoice'); $tm_due = $form->addDate('tm_due')->setLabel(___('Due Date')); $tm_due->setValue($invoice->due_date < sqlDate('now') ? sqlDate('+7 days') : $invoice->due_date); $message = $form->addTextarea('message', array('class' => 'el-wide')) ->setLabel(___("Message\n" . 'will be included to email to user')); $form->addElement('email_link', 'invoice_pay_link') ->setLabel(___('Email Template with Payment Link')); $form->setDataSources(array($this->getRequest())); if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); $invoice->due_date = $vars['tm_due']; $invoice->save(); $et = Am_Mail_Template::load('invoice_pay_link', $invoice->getUser()->lang ? $invoice->getUser()->lang : null); $et->setUser($invoice->getUser()); $et->setUrl($this->getDi()->url('pay/'.$invoice->getSecureId('payment-link'),null,false)); $et->setMessage($vars['message']); $et->setInvoice($invoice); $et->setInvoice_text($invoice->render()); $et->setInvoice_html($invoice->renderHtml()); $et->setProduct_title(implode(", ", array_map( function ($item){ return $item->title; }, $invoice->getProducts() ))); $et->send($invoice->getUser()); $this->_response->ajaxResponse(array( 'ok'=>true, 'msg'=>___('Invoice link has been sent to user again'), 'invoice_id' => $invoice->pk(), 'due_date_html' => amDate($invoice->due_date))); } else { echo $form; } } public function addInvoiceAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'insert'); $form = new Am_Form_Admin('add-invoice'); $tm_added = $form->addDateTime('tm_added')->setLabel(___('Date/Time')); $tm_added->setValue($this->getDi()->sqlDateTime); $tm_added->addRule('required'); $form->addText('comment', array('class' => 'el-wide'))->setLabel(___("Comment\nfor your reference")); $form->addElement(new Am_Form_Element_ProductsWithQty('product_id'))->setLabel(___('Products')) ->loadOptions($this->getDi()->billingPlanTable->selectAllSorted()) ->addRule('required'); $form->addSelect('paysys_id')->setLabel(___('Payment System')) ->setId('add-invoice-paysys_id') ->loadOptions(array(''=>'') + $this->getDi()->paysystemList->getOptions()); $couponEdit = $form->addText('coupon')->setLabel(___('Coupon'))->setId('p-coupon'); $gr = $form->addGroup() ->setLabel(___("Discount\n" . 'additional discount to invoice total besides coupon')); $gr->setSeparator(' '); $gr->addStatic() ->setContent(___('First Price')); $gr->addText('d_first', array('size' => 4, 'placeholder' => '0')); $gr->addStatic() ->setContent(___('Second Price')); $gr->addText('d_second', array('size' => 4, 'placeholder' => '0')); $action = $form->addAdvRadio('_action') ->setLabel(___('Action')) ->setId('add-invoice-action') ->loadOptions(array( 'pending' => ___('Just Add Pending Invoice'), 'pending-payment' => ___('Add Invoice and Payment/Access Manually'), 'pending-send' => ___('Add Pending Invoice and Send Link to Pay It to Customer') ))->setValue('pending'); $receipt = $form->addText('receipt')->setLabel(___('Receipt#')) ->setId('add-invoice-receipt'); $tm_due = $form->addDate('tm_due')->setLabel(___('Due Date')); $tm_due->setValue(sqlDate('+7 days')); $tm_due->setId('add-invoice-due'); $message = $form->addTextarea('message', array('class' => 'el-wide'))->setLabel(___("Message\nwill be included to email to user")); $message->setId('add-invoice-message'); $form->addElement('email_link', 'invoice_pay_link') ->setLabel(___('Email Template with Payment Link')); $form->addScript()->setScript(<<addAdvCheckbox('skip_pr', null, array('content' => ___('do not validate product requirements for this invoice'))); $form->addSaveButton(); $form->setDataSources(array($this->getRequest())); do { if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); $invoice = $this->getDi()->invoiceRecord; $invoice->setUser($this->getDi()->userTable->load($this->user_id)); $invoice->tm_added = sqlTime($vars['tm_added']); if ($vars['coupon']) { $invoice->setCouponCode($vars['coupon']); $error = $invoice->validateCoupon(); if ($error) { $couponEdit->setError($error); break; } } foreach ($vars['product_id'] as $plan_id => $qty) { $p = $this->getDi()->billingPlanTable->load($plan_id); $pr = $p->getProduct(); try { $invoice->add($pr, $qty); } catch (Am_Exception_InputError $e) { $form->setError($e->getMessage()); break 2; } } $invoice->comment = $vars['comment']; if ($vars['skip_pr']) $invoice->toggleValidateProductRequirements(false); if ($vars['d_first'] || $vars['d_second']) { $invoice->setDiscount($vars['d_first'], $vars['d_second']); } $invoice->calculate(); switch ($vars['_action']) { case 'pending' : if (!$this->_addPendingInvoice($invoice, $form, $vars)) break 2; break; case 'pending-payment' : if (!$this->_addPendingInvoiceAndPayment($invoice, $form, $vars)) break 2; break; case 'pending-send' : if (!$this->_addPendingInvoiceAndSend($invoice, $form, $vars)) break 2; break; default: throw new Am_Exception_InternalError(sprintf('Unknown action [%s] as %s::%s', $vars['_action'], __CLASS__, __METHOD__)); } $this->getDi()->adminLogTable->log("Add Invoice (#{$invoice->invoice_id}/{$invoice->public_id}, Billing Terms: " . new Am_TermsText($invoice) . ")", 'invoice', $invoice->invoice_id); return $this->_response->redirectLocation($this->getDi()->url('admin-user-payments/index/user_id/' . $this->user_id,null,false)); } // if } while (false); $this->view->content = '

      ' . ___('Add Invoice') . ' (' . ___('return') . ')

      ' . (string)$form; $this->view->display('admin/user-layout.phtml'); } protected function _addPendingInvoice(Invoice $invoice, Am_Form $form, $vars) { if ($vars['paysys_id']) { try { $invoice->setPaysystem($vars['paysys_id'], false); } catch (Am_Exception_InputError $e) { $form->setError($e->getMessage()); return false; } } $errors = $invoice->validate(); if ($errors) { $form->setError(current($errors)); return false; } $invoice->data()->set('added-by-admin', $this->getDi()->authAdmin->getUserId()); $invoice->save(); return true; } protected function _addPendingInvoiceAndPayment(Invoice $invoice, Am_Form $form, $vars) { if (!$vars['paysys_id']) $form->getElementById('add-invoice-paysys_id')->setError(___('This field is required for choosen action')); if (!$vars['receipt']) $form->getElementById('add-invoice-receipt')->setError(___('This field is required for choosen action')); if (!$vars['paysys_id'] || !$vars['receipt']) return false; try { $invoice->setPaysystem($vars['paysys_id'], false); } catch (Am_Exception_InputError $e) { $form->setError($e->getMessage()); return false; } $errors = $invoice->validate(); if ($errors) { $form->setError(current($errors)); return false; } $invoice->data()->set('added-by-admin', $this->getDi()->authAdmin->getUserId()); $invoice->save(); if($invoice->first_total<=0){ $invoice->addAccessPeriod(new Am_Paysystem_Transaction_Free($this->getDi()->plugins_payment->get($vars['paysys_id']))); } else { $transaction = new Am_Paysystem_Transaction_Manual($this->getDi()->plugins_payment->get($vars['paysys_id'])); $transaction->setAmount($invoice->first_total) ->setReceiptId($vars['receipt']) ->setTime(new DateTime($vars['tm_added'])); $invoice->addPayment($transaction); } try { $invoice->recalculateRebillDate(); } catch (Am_Exception_InternalError $e) {}; // ignore error about empty period return true; } protected function _addPendingInvoiceAndSend(Invoice $invoice, Am_Form $form, $vars) { if ($vars['paysys_id']) { try { $invoice->setPaysystem($vars['paysys_id'], false); } catch (Am_Exception_InputError $e) { $form->setError($e->getMessage()); return false; } } $errors = $invoice->validate(); if ($errors) { $form->setError(current($errors)); return false; } $invoice->data()->set('added-by-admin', $this->getDi()->authAdmin->getUserId()); $invoice->due_date = $vars['tm_due']; $invoice->save(); $et = Am_Mail_Template::load('invoice_pay_link', $invoice->getUser()->lang ? $invoice->getUser()->lang : null); $et->setUser($invoice->getUser()); $et->setUrl($this->getDi()->url('pay/'.$invoice->getSecureId('payment-link'),null,false)); $et->setMessage($vars['message']); $et->setInvoice($invoice); $et->setInvoice_text($invoice->render()); $et->setInvoice_html($invoice->renderHtml()); $et->setProduct_title(implode(", ", array_map(function($item) {return $item->title;}, $invoice->getProducts()))); $et->send($invoice->getUser()); return true; } public function calculateAccessDatesAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_access', 'insert'); $invoice = $this->getDi()->invoiceRecord; $invoice->setUser($this->getDi()->userTable->load($this->user_id)); $product = $this->getDi()->productTable->load($this->getRequest()->getParam('product_id')); $invoice->add($product); $begin_date = $product->calculateStartDate($this->getDi()->sqlDate, $invoice); $p = new Am_Period($product->getBillingPlan()->first_period); $expire_date = $p->addTo($begin_date); $this->_response->ajaxResponse(array( 'begin_date' => $begin_date, 'expire_date' => $expire_date )); } public function getAddForm($set_date = true) { $form = new Am_Form_Admin; $form->setAction($url = $this->getUrl(null, 'addpayment', null, 'user_id',$this->user_id)); $form->addText("receipt_id", array('tabindex' => 2)) ->setLabel(___("Receipt#")) ->addRule('required'); $amt = $form->addSelect("amount", array('tabindex' => 3), array('intrinsic_validation' => false)) ->setLabel(___("Amount")); $amt->addRule('required', ___('This field is required')); if ($this->_request->getInt('invoice_id')) { $invoice = $this->getDi()->invoiceTable->load($this->_request->getInt('invoice_id')); if ((doubleval($invoice->first_total) === 0.0) || $invoice->getPaymentsCount()) $amt->addOption($invoice->second_total, $invoice->second_total); else $amt->addOption($invoice->first_total, $invoice->first_total); } $form->addSelect("paysys_id", array('tabindex' => 1)) ->setLabel(___("Payment System")) ->loadOptions($this->getDi()->paysystemList->getOptions()); $date = $form->addDateTime("dattm", array('tabindex' => 4)) ->setLabel(___("Date/Time Of Transaction")); $date->addRule('required', ___('This field is required')); if($set_date) $date->setValue(sqlTime('now')); $form->addHidden("invoice_id"); $form->addSaveButton(); return $form; } function getAccessRecords() { return $this->getDi()->accessTable->selectObjects("SELECT a.*, p.title as product_title FROM ?_access a LEFT JOIN ?_product p USING (product_id) WHERE a.user_id = ?d ORDER BY begin_date, expire_date, product_title ", $this->user_id); } public function createAccessForm() { static $form; if (!$form) { $form = new Am_Form_Admin; $form->setAction($url = $this->getUrl(null, 'addaccess', null, 'user_id', $this->user_id)); $sel = $form->addSelect('product_id', array('class' => 'el-wide am-combobox')); $options = $this->getDi()->productTable->getOptions(); $sel->addOption(___('Please select an item...'), ''); foreach ($options as $k => $v) $sel->addOption($v, $k); $sel->addRule('required', ___('This field is required')); $form->addText('comment', array('class' => 'el-wide', 'placeholder' => ___('Comment for Your Reference'))); $form->addDate('begin_date')->addRule('required', ___('This field is required')); $form->addDate('expire_date')->addRule('required', ___('This field is required')); $form->addAdvCheckbox('does_not_send_autoresponder'); $form->addSaveButton(___('Add Access Manually')); } return $form; } public function indexAction() { $this->getDi()->plugins_payment->loadEnabled(); $this->view->invoices = $this->getDi()->invoiceTable->findByUserId($this->user_id, null, null, 'tm_added DESC'); $this->view->savedFormOptions = $this->getDi()->savedFormTable->getOptions(); foreach ($this->view->invoices as $invoice) { $invoice->_cancelUrl = null; if ($invoice->getStatus() == Invoice::RECURRING_ACTIVE && $this->getDi()->plugins_payment->isEnabled($invoice->paysys_id)) { $plugin = $this->getDi()->plugins_payment->get($invoice->paysys_id); if ($url = $plugin->getAdminCancelUrl($invoice)) { $invoice->_cancelUrl = $url; } } } $this->view->aInvoiceBrowse = $this->getDi()->authAdmin->getUser()->hasPermission('grid_invoice', 'browse'); $this->view->aInvoiceInsert = $this->getDi()->authAdmin->getUser()->hasPermission('grid_invoice', 'insert'); $this->view->aInvoiceEdit = $this->getDi()->authAdmin->getUser()->hasPermission('grid_invoice', 'edit'); $this->view->aInvoiceDelete = $this->getDi()->authAdmin->getUser()->hasPermission('grid_invoice', 'delete'); $this->view->aAccessBrowse = $this->getDi()->authAdmin->getUser()->hasPermission('grid_access', 'browse'); $this->view->aAccessInsert = $this->getDi()->authAdmin->getUser()->hasPermission('grid_access', 'insert'); $this->view->aAccessEdit = $this->getDi()->authAdmin->getUser()->hasPermission('grid_access', 'edit'); $this->view->aAccessDelete = $this->getDi()->authAdmin->getUser()->hasPermission('grid_access', 'delete'); $this->view->user_id = $this->user_id; $this->view->addForm = $this->getAddForm(); $this->view->accessRecords = $this->getAccessRecords(); $this->view->accessForm = $this->createAccessForm()->toObject(); $this->view->display('admin/user-invoices.phtml'); } public function changeAccessDateAction(){ $this->getDi()->authAdmin->getUser()->checkPermission('grid_access', 'edit'); $this->_response->setHeader("Content-Type", "application/json", true); try { if(!($access_id = $this->_request->getInt('access_id'))) throw new Am_Exception_InputError('No access_id submitted'); switch($this->_request->getFiltered('field')){ case 'begin_date' : $field = 'begin_date'; break; case 'expire_date' : $field = 'expire_date'; break; default: throw new Am_Exception_InputError('Invalid field type. You can change begin or expire date fields only'); } if(!($value = $this->_request->get('access_date'))) throw new Am_Exception_InputError('No new value submitted'); $value = new DateTime($value); $access = $this->getDi()->accessTable->load($access_id); $old_value = $access->get($field); if($old_value != $value) { $access->set($field, $value->format('Y-m-d')); if(!$access->data()->get('ORIGINAL_'.strtoupper($field))) $access->data()->set('ORIGINAL_'.strtoupper($field), $old_value); $access->update(); // Update cache and execute hooks $access->getUser()->checkSubscriptions(true); $this->getDi()->adminLogTable->log( "Access date ($field) changed from $old_value to {$access->$field} for user_id={$access->user_id}", 'access', $access->access_id); } echo json_encode(array('success'=>true, 'reload'=>true)); }catch(Exception $e){ echo json_encode(array('success'=>false, 'error'=>$e->getMessage())); } } public function refundAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_payment', 'insert'); do { $this->invoice_payment_id = $this->getInt('invoice_payment_id'); if (!$this->invoice_payment_id) { $res = array( 'success' => false, 'text' => ___("Not payment# submitted"), ); continue; } $p = $this->getDi()->invoicePaymentTable->load($this->invoice_payment_id); /* @var $p InvoicePayment */ if (!$p) { $res = array( 'success' => false, 'text' => ___("No payment found"), ); continue; } if ($this->user_id != $p->user_id) { $res = array( 'success' => false, 'text' => ___("Payment belongs to another customer"), ); continue; } if ($p->isFullRefunded()) { $res = array( 'success' => false, 'text' => ___("Payment is already refunded"), ); continue; } $amount = sprintf('%.2f', $this->_request->get('amount')); if ($p->amount < $amount) { $res = array( 'success' => false, 'text' => ___("Refund amount cannot exceed payment amount"), ); continue; } if ($this->_request->getInt('manual')) { $el = new Am_Form_Element_Date; $dattm = $el->convertReadableToSQL($this->_request->get('dattm')); if (!$dattm) $dattm = sqlDate('now'); $dattm .= date(' H:i:s'); if ($dattm < $p->dattm){ $res = array( 'success' => false, 'text' => ___("Refund date cannot be before payment date"), ); continue; } switch ($type = $this->_request->getFiltered('type')) { case 'refund': case 'chargeback': $pl = $this->getDi()->plugins_payment->loadEnabled()->get($p->paysys_id); if (!$pl) { $res = array( 'success' => false, 'text' => ___("Could not load payment plugin [%s]", $pl), ); continue 2; } $invoice = $p->getInvoice(); $transaction = new Am_Paysystem_Transaction_Manual($pl); $transaction->setAmount($amount); $transaction->setReceiptId($p->receipt_id . '-manual-'.$type); $transaction->setTime(new DateTime($dattm)); if ($type == 'refund') $invoice->addRefund($transaction, $p->receipt_id); else $invoice->addChargeback($transaction, $p->receipt_id); break; case 'correction': $this->getDi()->accessTable->deleteBy(array('invoice_payment_id' => $this->invoice_payment_id)); $invoice = $p->getInvoice(); $p->delete(); $invoice->updateStatus(); break; default: $res = array( 'success' => false, 'text' => ___("Incorrect refund [type] passed: %s", $type), ); continue 2; } $res = array( 'success' => true, 'text' => ___("Payment has been successfully refunded"), ); } else { // automatic /// ok, now we have validated $p here $pl = $this->getDi()->plugins_payment->loadEnabled()->get($p->paysys_id); if (!$pl){ $res = array( 'success' => false, 'text' => ___("Could not load payment plugin [%s]", $pl), ); continue; } /* @var $pl Am_Paysystem_Abstract */ $result = new Am_Paysystem_Result; $pl->processRefund($p, $result, $amount); if ($result->isSuccess()) { if ($transaction = $result->getTransaction()) { $p->getInvoice()->addRefund($result->getTransaction(), $p->receipt_id, $amount); } $res = array( 'success' => true, 'text' => ___("Payment has been successfully refunded"), ); } elseif ($result->isAction()) { $action = $result->getAction(); if ($action instanceof Am_Paysystem_Action_Redirect) { $res = array( 'success' => 'redirect', 'url' => $result->getUrl(), ); } else {// todo handle other actions if necessary throw new Am_Exception_NotImplemented("Could not handle refund action " . get_class($action)); } } elseif ($result->isFailure()) { $res = array( 'success' => false, 'text' => implode(";", $result->getErrorMessages()), ); } } } while (false); $this->_response->setHeader("Content-Type", "application/json", true); echo json_encode($res); } function addaccessAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_access', 'insert'); $form = $this->createAccessForm(); if ($form->validate()) { $access = $this->getDi()->accessRecord; $val = $form->getValue(); $access->setForInsert($val); unset($access->save); $access->user_id = $this->user_id; $access->data()->set('added', $this->getDi()->sqlDateTime); $access->data()->set('admin', $this->getDi()->authAdmin->getUser()->login); $access->insert(); $this->getDi()->adminLogTable->log("Add Access (user #{$access->user_id}, product #{$access->product_id}, {$access->begin_date} - {$access->expire_date})", 'access', $access->access_id); if (!$val['does_not_send_autoresponder']) { $user = $this->getDi()->userTable->load($this->user_id); $this->getDi()->emailTemplateTable->sendZeroAutoresponders($user, $access); } $form->setDataSources(array(new Am_Mvc_Request(array()))); $form->getElementById('begin_date-0')->setValue(''); $form->getElementById('expire_date-0')->setValue(''); } else { } return $this->indexAction(); } function delaccessAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_access', 'delete'); $access = $this->getDi()->accessTable->load($this->getInt('id')); if ($access->user_id != $this->user_id) throw new Am_Exception_InternalError("Wrong access record to delete - member# does not match"); $logaccess = $access; $access->delete(); $this->getDi()->adminLogTable->log("Delete Access (user #{$logaccess->user_id}, product #{$logaccess->product_id}, {$logaccess->begin_date} - {$logaccess->expire_date})", 'access', $logaccess->access_id); return $this->indexAction(); } function addpaymentAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_payment', 'insert'); $invoice = $this->getDi()->invoiceTable->load($this->_request->getInt('invoice_id')); if (!$invoice || $invoice->user_id != $this->user_id) throw new Am_Exception_InputError('Invoice not found'); $form = $this->getAddForm(false); if (!$form->validate()) { echo $form; return; } $vars = $form->getValue(); $transaction = new Am_Paysystem_Transaction_Manual($this->getDi()->plugins_payment->get($vars['paysys_id'])); $transaction->setAmount($vars['amount'])->setReceiptId($vars['receipt_id'])->setTime(new DateTime($vars['dattm'])); if(floatval($vars['amount']) == 0) $invoice->addAccessPeriod($transaction); else $invoice->addPayment($transaction); $form->setDataSources(array(new Am_Mvc_Request(array()))); $form->addHidden('saved-ok'); $this->getDi()->adminLogTable->log("Add Payment (user #{$invoice->user_id}, invoice #{$invoice->public_id}, amount - $vars[amount], receipt - $vars[receipt_id])", 'invoice', $invoice->invoice_id); echo $form; } function stopRecurringAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); // todo: rewrote stopRecurring $invoiceId = $this->_request->getInt('invoice_id'); if (!$invoiceId) throw new Am_Exception_InputError('No invoice# provided'); $invoice = $this->getDi()->invoiceTable->load($invoiceId); $plugin = $this->getDi()->plugins_payment->loadGet($invoice->paysys_id, true); $result = new Am_Paysystem_Result(); $result->setSuccess(); try { $plugin->cancelAction($invoice, 'cancel-admin', $result); } catch (Exception $e) { $this->_response->ajaxResponse(array('ok' => false, 'msg' => $e->getMessage())); return; } if ($result->isSuccess()) { $invoice->setCancelled(true); $this->getDi()->adminLogTable->log("Invoice Cancelled", 'invoice', $invoice->pk()); $this->_response->ajaxResponse(array('ok' => true)); } elseif ($result->isAction()) { $action = $result->getAction(); if ($action instanceof Am_Paysystem_Action_Redirect) $this->_response->ajaxResponse(array('ok'=> false, 'redirect' => $action->getUrl())); else $action->process(); // this .. simply will not work hopefully we never get to this point } else { $this->_response->ajaxResponse(array('ok' => false, 'msg' => $result->getLastError())); } } function startRecurringAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); if(!defined('AM_ALLOW_RESTART_CANCELLED')) { $this->_response->ajaxResponse(array('ok' => false, 'msg' => ___('Restart is not allowed'))); return; } $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); $invoiceId = $this->_request->getInt('invoice_id'); if (!$invoiceId) throw new Am_Exception_InputError('No invoice# provided'); $invoice = $this->getDi()->invoiceTable->load($invoiceId); $invoice->setCancelled(false); $this->getDi()->adminLogTable->log('Invoice Restarted', 'invoice', $invoice->pk()); $this->_response->ajaxResponse(array('ok' => true)); } function changeRebillDateAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); $invoice_id = $this->_request->getInt('invoice_id'); $form = new Am_Form_Admin; $form->addDate('rebill_date'); $vals = $form->getValue(); $rebill_date = $vals['rebill_date']; try{ if(!$invoice_id) throw new Am_Exception_InputError('No invoice provided'); $invoice = $this->getDi()->invoiceTable->load($invoice_id); // Invoice must be recurring active and rebills should be controlled by paylsystem, // otherwise this doesn't make any sence if(($invoice->status != Invoice::RECURRING_ACTIVE) || ($invoice->getPaysystem()->getRecurringType() != Am_Paysystem_Abstract::REPORTS_CRONREBILL) ) throw new Am_Exception_InputError('Unable to change rebill_date for this invoice!'); $rebill_date = new DateTime($rebill_date); $old_rebill_date = $invoice->rebill_date; $invoice->updateQuick('rebill_date', $rebill_date->format('Y-m-d')); $invoice->data()->set('first_rebill_failure', null)->update(); $this->getDi()->invoiceLogTable->log($invoice_id, null, ___('Rebill Date changed from %s to %s', $old_rebill_date, $invoice->rebill_date)); $this->_response->ajaxResponse(array('ok'=>true, 'msg'=>___('Rebill date has been changed!'))); }catch(Exception $e){ $this->_response->ajaxResponse(array('ok'=>false, 'msg'=>$e->getMessage())); } } function logAction() { $this->getDi()->authAdmin->getUser()->checkPermission(Am_Auth_Admin::PERM_LOGS_INVOICE); $invoice = $this->getDi()->invoiceTable->load($this->_request->getInt('invoice_id')); $this->getResponse()->setHeader('Content-type', 'text/xml'); echo $invoice->exportXmlLog(); } function dataAction() { $this->getDi()->authAdmin->getUser()->checkPermission(Am_Auth_Admin::PERM_LOGS_INVOICE); $invoice = $this->getDi()->invoiceTable->load($this->_request->getInt('invoice_id')); $this->getResponse()->setHeader('Content-type', 'text/xml'); $x = new XMLWriter(); $x->openMemory(); $x->setIndent(true); $x->startElement('invoice-data-items'); foreach ($invoice->data()->getAll() as $k => $v) { $x->startElement('item'); $x->writeAttribute('name', $k); $x->text($v); $x->endElement(); } $x->endElement(); echo $x->flush(); } function approveAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); $invoiceId = $this->_request->getInt('invoice_id'); if (!$invoiceId) throw new Am_Exception_InputError('No invoice# provided'); $invoice = $this->getDi()->invoiceTable->load($invoiceId); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$invoiceId]"); $invoice->approve(); $this->_redirect('admin-user-payments/index/user_id/'.$invoice->user_id.'#invoice-'.$invoiceId); } function invoiceAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'browse'); if($payment_id = $this->_request->getInt('payment_id')) { $payment = $this->getDi()->invoicePaymentTable->load($this->_request->getInt('payment_id')); } else if($refund_id = $this->_request->getInt('refund_id')) { $payment = $this->getDi()->invoiceRefundTable->load($this->_request->getInt('refund_id')); } $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $pdfInvoice = Am_Pdf_Invoice::create($payment); $pdfInvoice->setDi($this->getDi()); $this->_helper->sendFile->sendData($pdfInvoice->render(), 'application/pdf', $pdfInvoice->getFileName()); } function replaceProductAction() { $this->getDi()->authAdmin->getUser()->checkPermission('grid_invoice', 'edit'); $item = $this->getDi()->invoiceItemTable->load($this->_request->getInt('id')); $form = new Am_Form_Admin('replace-product-form'); $form->setDataSources(array($this->_request)); $form->method = 'post'; $form->addHidden('id'); $form->addHidden('user_id'); $form->addStatic() ->setLabel(___('Replace Product')) ->setContent("#{$item->item_id} [$item->item_title]"); $sel = $form->addSelect('product_id')->setLabel(___('To Product')); $options = array('' => '-- ' . ___('Please select') . ' --'); foreach ($this->getDi()->billingPlanTable->getProductPlanOptions() as $k => $v) if (strpos($k, $item->item_id.'-')!==0) $options[$k] = $v; $sel->loadOptions($options); $sel->addRule('required'); $form->addSubmit('_save', array('value' => ___('Save'))); if ($form->isSubmitted() && $form->validate()) { try { list($p,$b) = explode("-", $sel->getValue(), 2); $item->replaceProduct(intval($p), intval($b)); $this->getDi()->adminLogTable->log("Inside invoice: product #{$item->item_id} replaced to product #$p (plan #$b)", 'invoice', $item->invoice_id); return $this->_response->ajaxResponse(array('ok'=>true)); } catch (Am_Exception $e) { $sel->setError($e->getMessage()); } } echo $form; } }PK\,default/controllers/AdminClearController.phpnu[hasPermission(Am_Auth_Admin::PERM_CLEAR); } function getItems() { $di = $this->getDi(); $items = array( 'access_log' => array( 'method' => array($this->getDi()->accessLogTable, 'clearOld'), 'title' => ___('Access Log'), 'desc' => ___('access log table (used by admin only)'), ), 'error_log' => array( 'method' => array($this->getDi()->errorLogTable, 'clearOld'), 'title' => ___('Error Log'), 'desc' => ___('error_log table (used by admin only)'), ), 'inc_users' => array( 'method' => array($this->getDi()->userTable, 'clearPending'), 'title' => 'Incomplete Users', 'desc' => 'records of users (excl. affiliates) with no any active subscriptions', ), 'inc_users_aff' => array( 'method' => function ($date) use ($di) { $di->userTable->clearPending($date, true); }, 'title' => 'Incomplete Users and Affiliates', 'desc' => 'records of users (incl. affiliates) with no any active subscriptions', ), 'inc_payments' => array( 'method' => array($this->getDi()->invoiceTable, 'clearPending'), 'title' => 'Incomplete Invoices', 'desc' => 'records of incomplete payments attempts', ), 'exp_users' => array( 'method' => array($this->getDi()->userTable, 'clearExpired'), 'title' => 'Expired Users', 'desc' => 'records of users (excl. affiliates) with expired subscriptions', ), 'exp_users_aff' => array( 'method' => function ($date) use ($di) { $di->userTable->clearExpired($date, true); }, 'title' => 'Expired Users and Affiliates', 'desc' => 'records of users (incl. affiliates) with expired subscriptions', ), 'admin_log' => array( 'method' => array($this->getDi()->adminLogTable, 'clearOld'), 'title' => ___('Admin Log'), 'desc' => ___('admin log table (used by admin only)'), ), ); $event = new Am_Event(Am_Event::CLEAR_ITEMS); $this->getDi()->hook->call(Am_Event::CLEAR_ITEMS, $event); $items = array_merge($items, $event->getReturn()); return $items; } function createForm() { $form = new Am_Form_Admin; $form->setAction($this->getUrl(null, 'clear')); $form->addDate('dat') ->setLabel(___("Date to Purge\nall records prior to this date will be removed from selected tables")) ->addRule('required'); $section = $form->addFieldset('tables')->setLabel(___('Tables to Purge')); foreach ($this->getItems() as $id => $item) { $section->addAdvCheckbox($id)->setLabel($item['title'] . "\n" . $item['desc']); } $form->addSaveButton(___('Clear')); return $form; } function getForm() { if (!$this->form) $this->form = $this->createForm(); return $this->form; } function clearAction() { check_demo(); $form = $this->getForm(); if (!$form->validate()) return $this->indexAction(); $vars = $form->getValue(); if ($vars['dat'] >= $this->getDi()->sqlDate) throw new Am_Exception_InputError(___('Please select date before today'), 0); $tt = array(); foreach ($this->getItems() as $id => $item) { if (!$vars[$id]) continue; $tt[] = $item['title']; call_user_func($item['method'], $vars['dat']); $this->getDi()->adminLogTable->log("Cleaned up [{$item['title']}] to $vars[dat]"); } $this->view->content = $this->view->title = ___('Records Deleted Sucessfully'); $this->view->content .= sprintf(' %s', $this->getUrl(null, 'index'), ___('Back')); $this->view->display('admin/layout.phtml'); } function indexAction() { /* @var Am_Form */ $form = $this->getForm(); if (!$this->_request->dat) $this->_request->setParam('dat', date('Y-m-d', time() - 3600 * 24 * 30)); $form->setDataSources(array($this->_request)); $this->view->title = ___('Delete Old Records'); $this->view->content = (string)$form; $this->view->display('admin/layout.phtml'); } }PK\({.default/controllers/AdminLicenseController.phpnu[addText('root_url', array('class' => 'el-wide')) ->setLabel(___("Root URL\nroot script URL, usually %s", 'http://www.yoursite.com/amember')) ->addRule('callback2', '-error-must-be-returned-', array($this, 'validateRootUrl')); $this->addText('root_surl', array('class' => 'el-wide')) ->setLabel(___("Secure Root URL\nsecure URL, usually %s", 'https://www.yoursite.com/amember')) ->addRule('callback2', '-error-must-be-returned-', array($this, 'validateRootUrl')); $this->addAdvCheckbox('force_ssl') ->setLabel(___("Force https Connection\n" . "redirect all request to https")) ->addRule('callback2', '-error-must-be-returned-', array($this, 'validateSsl')); $check_url = json_encode(Am_Di::getInstance()->url('admin-license/check')); $this->addScript() ->setScript(<<config->get('license'); $this->addTextarea('license', array( 'class' => 'el-wide', 'rows' => count(explode("\n", $license)) + 1, )) ->setLabel(___("License Key")) ->addRule('required') ->addRule('notregex', ___('You have license keys from past versions of aMember, please replace it with latest, one-line keys'), '/====\s+LICENSE/') ->addRule('callback', ___('Valid license key are one-line string,starts with L and ends with X'), array($this, 'validateKeys')); if ($_ = Am_License::getInstance()->getLicenses()) { $cnt = array(); foreach($_ as $domain => $expire) { $cnt[] = sprintf('
    • %s %s
    • ', $domain, in_array($expire, array('2099-12-31', Am_Period::MAX_SQL_DATE)) ? ___('Lifetime') : ___("expires %s", amDate($expire))); } $cnt = sprintf('
        %s
      ', implode('', $cnt)); } else { $cnt = ___('No License Configured'); } } else { $cnt = "Using TRIAL Version - expires ==TRIAL_EXPIRES=="; } $this->addStatic()->setLabel(___('Configured License Keys'))->setContent(sprintf('
      %s
      ', $cnt)); parent::init(); $this->addSaveButton(___('Update License Information')); } function validateKeys($keys) { $keys = explode("\n", $keys); $ok = 0; foreach ($keys as $k) { $k = trim($k, "\t\n\r "); if (empty($k)) continue; if (!preg_match('/^L[A-Za-z0-9\/=+]+X$/', $k)) continue; $ok++; } return $ok > 0; } function validateRootUrl($url) { if (defined('APPLICATION_HOSTED')) return; if (!preg_match('/^http(s|):\/\/.+$/', $url)) return ___('URL must start from %s or %s', 'http://', 'https://'); if (preg_match('/\/+$/', $url)) return ___('URL must be specified without trailing slash'); } function validateSsl($ssl, $el) { $vars = $el->getContainer()->getValue(); if ($ssl) { if (!preg_match('/^https:/', $vars['root_surl'])) { return ___('You need to properly setup HTTPS on your server to enable this option'); } try { $req = new Am_HttpRequest($vars['root_surl'] . '/login'); $resp = $req->send(); if ($resp->getStatus() != 200) return ___('You need to properly setup HTTPS on your server to enable this option'); } catch (Exception $e) { return ___('You need to properly setup HTTPS on your server to enable this option'); } } } } class AdminLicenseController extends Am_Mvc_Controller { function checkAdminPermissions(Admin $admin) { return $admin->isSuper(); } function indexAction() { $this->view->title = ___('Fix aMember Pro License Key'); $this->view->msg = Am_License::getInstance()->check(); $form = new Am_Form_Admin_FixLicense(); if (!$form->isSubmitted()) { $form->setDataSources(array( new HTML_QuickForm2_DataSource_Array($this->getDefaults()) )); } if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); Am_Config::saveValue('license', $vars['license']); Am_Config::saveValue('root_url', $vars['root_url']); Am_Config::saveValue('root_surl', $vars['root_surl']); Am_Config::saveValue('force_ssl', $vars['force_ssl']); return Am_Mvc_Response::redirectLocation($this->getDi()->url('admin-license')); } $this->view->form = $form; $this->view->display('admin/fixlicense.phtml'); } function checkAction() { try { $req = new Am_HttpRequest($this->getParam('root_surl') . '/login'); $resp = $req->send(); $this->getResponse()->ajaxResponse($resp->getStatus() == 200); } catch (Exception $e) { $this->getResponse()->ajaxResponse(false); } } protected function getDefaults() { return array( 'license' => $this->getDi()->config->get('license'), 'root_url' => $this->getDi()->config->get('root_url'), 'root_surl' => $this->getDi()->config->get('root_surl'), 'force_ssl' => $this->getDi()->config->get('force_ssl') ); } }PK\w 䞎'default/controllers/ErrorController.phpnu[render('error.phtml'); } }PK\D\\+default/controllers/AdminLogsController.phpnu[dateField = $dateField[0] == '@' ? substr($dateField, 1) : $dateField; $this->isTimestamp = $dateField[0] == '@'; $this->fields = $fields; $this->placeholder = $placeholder; } protected function applyFilter() { class_exists('Am_Form', true); $query = $this->grid->getDataSource()->getDataSourceQuery(); $callback = $this->isTimestamp ? function($_) {return amstrtotime($_);} : function($_) {return $_;}; if ($d1 = $this->getParam('d1')) { $query->addWhere("t.{$this->dateField} >= ?", call_user_func($callback, Am_Form_Element_Date::createFromFormat(null, $d1)->format('Y-m-d 00:00:00'))); } if ($d2 = $this->getParam('d2')) { $query->addWhere("t.{$this->dateField} <= ?", call_user_func($callback, Am_Form_Element_Date::createFromFormat(null, $d2)->format('Y-m-d 23:59:59'))); } if ($q = $this->getParam('q')) { foreach ($this->fields as $field => $op) { $alias = null; if (preg_match('/^(.*)\.(.*)$/', $field, $_)) { $alias = $_[1]; $field = $_[2]; } $c = new Am_Query_Condition_Field($field, $op, $op == 'LIKE' ? "%$q%" : $q, $alias); if (!isset($condition)) $condition = $c; else $condition->_or($c); } $query->add($condition); } } function renderInputs() { $prefix = $this->grid->getId(); $d1 = Am_Html::escape($this->getParam('d1')); $d2 = Am_Html::escape($this->getParam('d2')); $q = Am_Html::escape($this->getParam('q')); $placeholder = Am_Html::escape($this->placeholder); $start = ___('Start Date'); $end = ___('End Date'); return << CUT; } public function getTitle() { return ''; } } class Am_Grid_Filter_LogEntity_Mail extends Am_Grid_Filter_LogEntity { protected $varList = array('q', 'd1', 'd2', 's'); function renderInputs() { return parent::renderInputs() . ' ' . $this->renderInputSelect('s', array( '' => ___('All'), 1 => ___('Sent'), 2 => ___('Not Sent') )); } protected function applyFilter() { parent::applyFilter(); if ($status = $this->getParam('s')) { $cond = $status == 1 ? 'sent IS NOT NULL' : 'sent IS NULL'; $this->grid->getDataSource()->getDataSourceQuery() ->addWhere($cond); } } } class AdminLogsController extends Am_Mvc_Controller_Pages { public function initPages() { $admin = $this->getDi()->authAdmin->getUser(); if ($admin->hasPermission(Am_Auth_Admin::PERM_LOGS)) $this->addPage(array($this,'createErrors'), 'errors', ___('Errors')); if ($admin->hasPermission(Am_Auth_Admin::PERM_LOGS_ACCESS)) $this->addPage(array($this, 'createAccess'), 'access', ___('Access')); if ($admin->hasPermission(Am_Auth_Admin::PERM_LOGS_INVOICE)) $this->addPage(array($this, 'createInvoice'), 'invoice', ___('Invoice')); if ($admin->hasPermission(Am_Auth_Admin::PERM_LOGS_MAIL)) $this->addPage(array($this, 'createMailQueue'), 'mailqueue', ___('Mail Queue')); if ($admin->hasPermission(Am_Auth_Admin::PERM_LOGS_ADMIN)) $this->addPage(array($this, 'createAdminLog'), 'adminlog', ___('Admin Log')); } public function checkAdminPermissions(Admin $admin) { foreach(array( Am_Auth_Admin::PERM_LOGS, Am_Auth_Admin::PERM_LOGS_ACCESS, Am_Auth_Admin::PERM_LOGS_INVOICE, Am_Auth_Admin::PERM_LOGS_MAIL, Am_Auth_Admin::PERM_LOGS_ADMIN ) as $perm) { if ($admin->hasPermission($perm)) return true; } return false; } public function createErrors() { $q = new Am_Query($this->getDi()->errorLogTable); $q->setOrder('log_id', 'desc'); $g = new Am_Grid_ReadOnly('_error', ___('Error/Debug Log'), $q, $this->getRequest(), $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_LOGS); $g->addField(new Am_Grid_Field_Date('time', ___('Date/Time'))); $g->addField(new Am_Grid_Field_Expandable('url', ___('URL'), true)) ->setPlaceholder(Am_Grid_Field_Expandable::PLACEHOLDER_SELF_TRUNCATE_BEGIN) ->setMaxLength(25); $g->addField(new Am_Grid_Field('remote_addr', ___('IP'))); $g->addField(new Am_Grid_Field_Expandable('error', ___('Message'), true, '', null, '45%')) ->setPlaceholder(Am_Grid_Field_Expandable::PLACEHOLDER_SELF_TRUNCATE_END) ->setMaxLength(500) ->setAttrs(array('class' => 'break')); $f = $g->addField(new Am_Grid_Field_Expandable('trace', ___('Trace'))) ->setAjax($this->getDi()->url('admin-logs/get-trace?id={log_id}', null,false)); $g->setFilter(new Am_Grid_Filter_LogEntity('time', array( 'url' => 'LIKE', 'remote_addr' => 'LIKE', 'referrer' => 'LIKE', 'error' => 'LIKE', ), 'URL/IP/Referrrer/Error')); return $g; } function getTraceAction() { $this->getDi()->authAdmin->getUser()->checkPermission(Am_Auth_Admin::PERM_LOGS); $log = $this->getDi()->errorLogTable->load($this->getParam('id')); echo highlight_string($log->trace, true); } public function createAccess() { $query = new Am_Query($this->getDi()->accessLogTable); $query->leftJoin('?_user', 'm', 't.user_id=m.user_id') ->addField("m.login", 'member_login') ->addField("CONCAT(m.name_f, ' ', m.name_l)", 'member_name'); $query->setOrder('time', 'desc'); $g = new Am_Grid_Editable('_access', ___('Access Log'), $query, $this->getRequest(), $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_LOGS_ACCESS); $g->actionsClear(); $g->addField(new Am_Grid_Field_Date('time', ___('Date/Time'))); $g->addField(new Am_Grid_Field('member_login', ___('User'), true, '', array($this, 'renderAccessMember'))); $g->addField(new Am_Grid_Field_Expandable('url', ___('URL'))) ->setPlaceholder(Am_Grid_Field_Expandable::PLACEHOLDER_SELF_TRUNCATE_BEGIN) ->setMaxLength(25); $g->addField(new Am_Grid_Field('remote_addr', ___('IP'))); $g->addField(new Am_Grid_Field_Expandable('referrer', ___('Referrer'))) ->setPlaceholder(Am_Grid_Field_Expandable::PLACEHOLDER_SELF_TRUNCATE_BEGIN) ->setMaxLength(25); $g->setFilter(new Am_Grid_Filter_LogEntity('time', array( 'remote_addr' => 'LIKE', 'referrer' => 'LIKE', 'url' => 'LIKE', ), 'URL/IP/Referrer')); $g->actionAdd(new Am_Grid_Action_Export); return $g; } public function createInvoice() { $query = new Am_Query(new InvoiceLogTable); $query->addField("m.login", "login"); $query->addField("m.user_id", "user_id"); $query->addField("i.public_id"); $query->leftJoin("?_user", "m", "t.user_id=m.user_id"); $query->leftJoin("?_invoice", "i", "t.invoice_id=i.invoice_id"); $query->setOrder('log_id', 'desc'); $g = new Am_Grid_Editable('_invoice', ___('Invoice Log'), $query, $this->getRequest(), $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_LOGS_INVOICE); $userUrl = new Am_View_Helper_UserUrl(); $g->addField(new Am_Grid_Field_Date('tm', ___('Date/Time'))); $g->addField(new Am_Grid_Field('invoice_id', ___('Invoice'), true, '', array($this, 'renderInvoice'))); $g->addField(new Am_Grid_Field('login', ___('User'))) ->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $g->addField(new Am_Grid_Field('remote_addr', ___('IP'))); $g->addField(new Am_Grid_Field('paysys_id', ___('Paysystem'))); $g->addField(new Am_Grid_Field('title', ___('Title'))); $g->addField(new Am_Grid_Field_Expandable('details', ___('Details'), false)) ->setAjax($this->getDi()->url('admin-logs/get-invoice-details?id={log_id}',null,false)); $g->actionsClear(); $g->actionAdd(new Am_Grid_Action_InvoiceRetry('retry')); $g->setFilter(new Am_Grid_Filter_LogEntity('tm', array( 'paysys_id' => 'LIKE', 'title' => 'LIKE', 'type' => 'LIKE', 'details' => 'LIKE', 'remote_addr' => '=', 'invoice_id' => '=', 'user_id' => '=' ), ___('Filter by string or by invoice#/member#'))); $g->actionAdd(new Am_Grid_Action_Group_Callback('retrygroup', ___("Repeat Action Handling"), array('Am_Grid_Action_InvoiceRetry', 'groupCallback'))); $g->addCallback(Am_Grid_ReadOnly::CB_RENDER_STATIC, function(& $out, $grid) { $out .= << CUT; }); return $g; } public function renderInvoice($record) { return $record->invoice_id ? sprintf('%s/%s', $this->escape($this->getDi()->url("admin-user-payments/index/user_id/".$record->user_id."#invoice-".$record->invoice_id,null,false)), $record->invoice_id, $record->public_id) : '—' ; } public function renderAccessMember($record) { return sprintf('%s (%s)', $this->getView()->userUrl($record->user_id), $record->member_login, $record->member_name); } public function renderRec(AdminLog $record) { $text = ""; if ($record->tablename || $record->record_id) $text = $this->escape($record->tablename . ":" . $record->record_id); // @todo - add links here to edit pages return sprintf('%s', $text); } function getInvoiceDetailsAction() { $this->getDi()->authAdmin->getUser()->checkPermission(Am_Auth_Admin::PERM_LOGS_INVOICE); $log = $this->getDi()->invoiceLogTable->load($this->getParam('id')); echo $this->renderInvoiceDetails($log); } public function renderInvoiceDetails(Am_Record $obj) { $ret = ""; $ret .= "
      \n"; $rows = $obj->getRenderedDetails(); $open = count($rows) == 1 ? 'open' : ''; foreach ($rows as $row) { $popup = @$row[2]; if ($popup) $popup = sprintf('

      Encoded details
      %s
      ', $popup); $ret .= "\t
      \n"; $ret .= "\t\t
      $row[0]
      \n"; $ret .= "\t\t
      $row[1]$popup
      \n"; $ret .= "\t
      \n"; } $ret .= "
      \n\n"; return $ret; } public function createMailQueue() { $ds = new Am_Query($this->getDi()->mailQueueTable); $ds->clearFields(); $ds->addField('recipients') ->addField('added') ->addField('sent') ->addField('subject') ->addField('queue_id'); $ds->setOrder('added', true); $g = new Am_Grid_Editable('_mail', ___("E-Mail Queue"), $ds, $this->getRequest(), $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_LOGS_MAIL); $g->addField(new Am_Grid_Field('recipients', ___('Recipients'), true, '', null, '20%')); $g->addField(new Am_Grid_Field_Date('added', ___('Added'), true)); $g->addField(new Am_Grid_Field_Date('sent', ___('Sent'), true)); $g->addField(new Am_Grid_Field('subject', ___('Subject'), true, '', null, '30%')) ->setRenderFunction(array($this, 'renderSubject')); $g->addField(new Am_Grid_Field_Expandable('queue_id', ___('Mail'), false, '', null, '20%')) ->setAjax($this->getDi()->url('admin-logs/get-mail?id={queue_id}',null,false)) ->setSafeHtml(true); $g->setFilter(new Am_Grid_Filter_LogEntity_Mail('@added', array( 'subject' => 'LIKE', 'recipients' => 'LIKE', ), 'Subject/Recipient')); $g->actionsClear(); $g->actionAdd(new Am_Grid_Action_MailRetry('retry')); if ($this->getDi()->authAdmin->getUser()->isSuper()) { $g->actionAdd(new Am_Grid_Action_Delete); $g->actionAdd(new Am_Grid_Action_Group_Delete); } $g->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, function (& $out, $g) { $st_label = array( Am_Mail_Queue::QUEUE_DISABLED => ___('Disabled'), Am_Mail_Queue::QUEUE_OK => ___('Ok'), Am_Mail_Queue::QUEUE_ONLY_INSTANT => ___('Only Instant'), Am_Mail_Queue::QUEUE_FULL => ___('Full') ); $q = Am_Mail_Queue::getInstance(); if ($q->getQueueStatus() == Am_Mail_Queue::QUEUE_DISABLED) return; $status_label = Am_Html::escape(___('Queue Status')); $status = Am_Html::escape($st_label[$q->getQueueStatus()]); $out = << $status_label: $status
      CUT . $out; }); return $g; } function getMailAction() { $this->getDi()->authAdmin->getUser()->checkPermission(Am_Auth_Admin::PERM_LOGS_MAIL); $mail = $this->getDi()->mailQueueTable->load($this->getParam('id')); echo $this->renderMail($mail); } function renderMail(Am_Record $obj) { $_body = $obj->body; $atRendered = null; $headersRendered = ''; foreach (unserialize($obj->headers) as $headerName => $headerVal) { if (isset($headerVal['append'])) { unset($headerVal['append']); $headerVal = implode(',' . "\r\n" . ' ', $headerVal); } else { $headerVal = implode("\r\n", $headerVal); } $_headers[strtolower($headerName)] = $headerVal; if (strpos($headerVal, '=?') === 0) $headerVal = mb_decode_mimeheader($headerVal); $headersRendered .= '' . $headerName . ': ' . nl2br(Am_Html::escape($headerVal)) . '
      '; } $part = new Zend_Mail_Part(array( 'headers' => $_headers, 'content' => $_body )); $canHasAttacments = false; list($type) = explode(";", $part->getHeader('content-type')); if ($type == 'multipart/alternative') { $msgPart = $part->getPart(2); } else { $msgPart = $part->isMultipart() ? $part->getPart(1) : $part; if ($msgPart->isMultipart()) { $msgPart = $msgPart->getPart(2); //html part } $canHasAttacments = true; } list($type) = explode(";", $msgPart->getHeader('content-type')); $encoding = $msgPart->getHeader('content-transfer-encoding'); $content = $msgPart->getContent(); if ($encoding && $encoding == 'quoted-printable') { $content = quoted_printable_decode($content); } else { $content = base64_decode($content); } switch ($type) { case 'text/plain': $bodyRendered = sprintf('
      %s
      ', Am_Html::escape($content)); break; case 'text/html': $bodyRendered = sprintf('', Am_Html::escape($content)); break; } //attachments $atRendered = ''; if ($canHasAttacments) { if ($part->isMultipart()) { for ($i=2; $i<=$part->countParts(); $i++) { $attPart = $part->getPart($i); preg_match('/filename="(.*)"/', $attPart->{'content-disposition'}, $matches); $filename = @$matches[1]; $atRendered .= sprintf("– %s (%s)", $filename, $attPart->{'content-type'}) . '
      '; } } } $attachTitle = ___('Attachments'); return $headersRendered . '
      ' . $bodyRendered . ($atRendered ? '
      ' . $attachTitle . ':
      ' . $atRendered : ''); } function renderSubject(Am_Record $m) { $s = $m->subject; if (strpos($s, '=?') === 0) $s = mb_decode_mimeheader($s); return "". Am_Html::escape($s) . ""; } public function createAdminLog() { $ds = new Am_Query($this->getDi()->adminLogTable); $ds->setOrder('log_id', 'desc'); $g = new Am_Grid_ReadOnly('_admin', ___('Admin Log'), $ds, $this->getRequest(), $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_LOGS_ADMIN); $g->addField(new Am_Grid_Field_Date('dattm', ___('Date/Time'), true)); $g->addField(new Am_Grid_Field('admin_login', ___('Admin'), true)) ->addDecorator(new Am_Grid_Field_Decorator_Link($this->getDi()->url("admin-admins?_admin_a=edit&_admin_id={admin_id}",null,false), '_top')); $g->addField(new Am_Grid_Field('ip', ___('IP'), true, '', null, '10%')); $g->addField(new Am_Grid_Field('message', ___('Message'))); $g->addField(new Am_Grid_Field('record', ___('Record')))->setRenderFunction(array($this, 'renderRec')); $g->setFilter(new Am_Grid_Filter_LogEntity('dattm', array( 'message' => 'LIKE', 'record_id' => 'LIKE', 'tablename' => 'LIKE', 'ip' => '=' ), 'Message/Record Id/Table')); return $g; } } class Am_Grid_Action_InvoiceRetry extends Am_Grid_Action_Abstract { protected $type = self::SINGLE; public function __construct($id = null, $title = null) { $this->title = ___('Repeat Action Handling'); parent::__construct($id, $title); $this->setTarget('_top'); } public function isAvailable($record) { return (strpos($record->details, 'type="incoming-request"') !== false); } public static function repeat(InvoiceLog $invoiceLog, array & $response) { Am_Di::getInstance()->plugins_payment->load($invoiceLog->paysys_id); $paymentPlugin = Am_Di::getInstance()->plugins_payment->get($invoiceLog->paysys_id); $paymentPlugin->toggleDisablePostbackLog(true); /* @var $paymentPlugin Am_Paysystem_Abstract */ try { $request = $invoiceLog->getFirstRequest(); if (!$request instanceof Am_Mvc_Request) throw new Am_Exception_InputError('Am_Mvc_Request is not saved for this record, this action cannot be repeated'); $resp = new Am_Mvc_Response(); Am_Di::getInstance()->router->route($request); $paymentPlugin->toggleDisablePostbackLog(true); $paymentPlugin->directAction($request, $resp, array('di' => Am_Di::getInstance())); $response['status'] = 'OK'; $response['msg'] = ___('The action has been repeated, ipn script response [%s]', $resp->getBody()); } catch (Exception $e) { $response['status'] = 'ERROR'; $response['msg'] = sprintf("Exception %s : %s", get_class($e), $e->getMessage()); } } public function run() { echo $this->renderTitle(); $invoiceLog = Am_Di::getInstance()->invoiceLogTable->load($this->getRecordId()); $response = array(); try { self::repeat($invoiceLog, $response); } catch (Exception $e) { $response['status'] = 'ERROR'; $response['msg'] = $e->getMessage(); } echo "RESULT: $response[status]
      "; echo $response['msg']; echo "

      \n"; echo $this->renderBackUrl(); } static function groupCallback($id, InvoiceLog $record, Am_Grid_Action_Group_Callback $action, Am_Grid_Editable $grid) { @set_time_limit(3600); try { $req = $record->getFirstRequest(); if (!$req) { echo "
      \n$record->log_id: SKIPPED"; return; } $response = array(); self::repeat($record, $response); } catch (Exception $e) { $response['status'] = 'Error'; $response['msg'] = $e->getMessage(); } echo "
      \n$record->log_id: {$response['status']} : {$response['msg']}"; } } class Am_Grid_Action_MailRetry extends Am_Grid_Action_Abstract { protected $type = self::SINGLE; public function __construct($id = null, $title = null) { $this->title = ___('Resend Email'); parent::__construct($id, $title); $this->setTarget('_top'); } public function isAvailable($record) { return !$record->sent; } public function run() { echo $this->renderTitle(); $record = Am_Di::getInstance()->mailQueueTable->load($this->getRecordId()); $row = $record->toArray(); $response = array(); try { Am_Mail_Queue::getInstance()->getTransport() ->sendFromSaved($row['from'], $row['recipients'], $row['body'], unserialize($row['headers']), $row['subject']); $row['sent'] = Am_Di::getInstance()->time; Am_Di::getInstance()->db->query("UPDATE ?_mail_queue SET sent=?d WHERE queue_id=?d", $row['sent'], $row['queue_id']); $response['status'] = 'OK'; $response['msg'] = ___('Email has been send'); } catch (Exception $e) { $response['status'] = 'ERROR'; $response['msg'] = $e->getMessage(); } echo "RESULT: $response[status]
      "; echo $response['msg']; echo "

      \n"; echo $this->renderBackUrl(); } }PK\p@1default/controllers/AdminChangePassController.phpnu[addPassword('self_password') ->setLabel(___("Your Password\n". "enter your current password ". "in order to edit admin record")); $self_password->addRule('required'); $self_password->addRule('callback', ___('Wrong password'), array($this, 'checkCurrentPassword')); $pass = $this->addPassword('pass') ->setLabel(___('New Password')); $pass->addRule('length', ___('Length of admin password must be from %d to %d', 6, 16), array(6,16)); $pass->addRule('neq', ___('Password must not be equal to username'), Am_Di::getInstance()->authAdmin->getUser()->login); $pass0 = $this->addPassword('_passwd0') ->setLabel(___('Confirm New Password')); $pass0->addRule('eq', ___('Passwords must be the same'), $pass); parent::init(); $this->addSaveButton(); } public function checkCurrentPassword($pass) { return Am_Di::getInstance()->authAdmin->getUser()->checkPassword($pass); } } class AdminChangePassController extends Am_Mvc_Controller { public function checkAdminPermissions(Admin $admin) { return true; } function indexAction() { $this->view->title = ___('Change Password'); $form = new Am_Form_Admin_ChangePassForm(); if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); $admin = $this->getDi()->authAdmin->getUser(); $admin->setPass($vars['pass']); $admin->save(); $this->getDi()->authAdmin->setUser($admin); return $this->_response->redirectLocation($this->getDi()->url('admin',null,false)); } $this->view->form = $form; $this->view->display('admin/form.phtml'); } }PK\D%UU@default/controllers/AdminImportWordpressMembershipController.phpnu[user; foreach ($this->groups as $oid => $list) { if(!@$list['payment']){ // Create an access and that's all; foreach($list['access'] as $v){ $product = $this->getDi()->productTable->findFirstByData('wm:id', $v['sub_id']); if(!$product) continue; $access = $this->getDi()->accessRecord; $access->user_id = $this->user->pk(); $access->setDisableHooks(); $access->begin_date = date('Y-m-d', strtotime($v['startdate'])); $access->expire_date = date('Y-m-d', strtotime($v['expirydate'])); $access->product_id = $product->pk(); $access->insert(); } }else{ // Create new invoice; $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $invoice->add($product = $this->getDi()->productTable->findFirstByData('wm:id', $list['payment'][0]['sub_id']), 1); $invoice->calculate(); $invoice->tm_added = date('Y-m-d H:i:s', $list['payment'][0]['stamp']); $invoice->tm_started = date('Y-m-d H:i:s', $list['payment'][0]['stamp']); $invoice->public_id = $oid; $invoice->paysys_id = 'paypal'; $invoice->status = Invoice::PAID; $invoice->data()->set('wm:id', $oid); $invoice->insert(); foreach ($list['payment'] as $rec) { switch ($rec['status']) { case 'Completed' : // Add payment record; $payment = $this->getDi()->invoicePaymentRecord; $payment->amount = $rec['amount']/100; $payment->currency = $rec['currency']; $payment->dattm = date('Y-m-d H:i:s', $rec['stamp']); $payment->invoice_id = $invoice->pk(); $payment->paysys_id = $invoice->paysys_id; $payment->receipt_id = $rec['txn_id']; $payment->transaction_id = sprintf('import-%s', $payment->receipt_id); $payment->user_id = $this->user->pk(); $payment->insert(); break; case 'Refunded' : $refund = $this->getDi()->invoiceRefundRecord; $refund->invoice_id = $invoice->pk(); $refund->user_id = $this->user->pk(); $refund->paysys_id = $invoice->paysys_id; $refund->receipt_id = $refund->transaction_id = $rec['txn_id']; $refund->dattm = date('Y-m-d H:i:s', $rec['stamp']); $refund->currency = $rec['currency']; $refund->amount = -$rec['amount']/100; $refund->insert(); break; } } if(@$list['access']) foreach(@$list['access'] as $rec){ // Insert Access; $access = $this->getDi()->accessRecord; $access->user_id = $this->user->pk(); $access->setDisableHooks(); $access->begin_date = date('Y-m-d', strtotime($rec['startdate'])); $access->expire_date = date('Y-m-d', strtotime($rec['expirydate'])); $access->invoice_id = $invoice->pk(); $access->product_id = $product->pk(); $access->insert(); break; } } } $this->user->checkSubscriptions(); } public function groupByInvoice() { foreach ($this->payments as $p) { $type = ($p['status'] == 'Access' ? 'access' : 'payment'); $this->groups[$p['sub_id'].'-'.$p['user_id']][$type][] = $p; } } } class AdminImportWordpressMembershipController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_wordpress; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->wordpress_db = null; $this->getSession()->wordpress_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->wordpress_import = null; } if (!$this->getSession()->wordpress_db) return $this->askDbSettings(); $this->db_wordpress = Am_Db::connect($this->getSession()->wordpress_db); if (!$this->getSession()->wordpress_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->wordpress_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_wordpress, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from Wordpress Membership Plugin"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->wordpress_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-wordpress-membership", array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->wordpress_import = array( 'import' => $val['import'], 'user' => @$val['user'], ); $this->_redirect('admin-import-wordpress-membership'); return; } } $this->view->title = "Import Wordpress Membership Plugin Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='wm:id'"); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_m_subscriptions"); if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); // Import coupons $imported_coupons = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='coupon' AND `key`='wm:id'"); $totalc = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_m_coupons"); if($imported_products){ if ($imported_coupons >= $totalc) { $cb = $form->addStatic()->setContent("Imported ($imported_coupons of $totalc)"); } else { $cb = $form->addRadio('import', array('value' => 'coupon')); } $cb->setLabel('Import Coupons'); } if ($imported_products && ($imported_coupons||!$totalc)) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='wm:id'"); $total = $this->db_wordpress->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->wordpress_db = $this->form->getValue(); $this->_redirect('admin-import-wordpress-membership'); } else { $this->view->title = "Import Wordpress Membership Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('Wordpress MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('Wordpress MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('Wordpress MySQL Password'); $form->addText('db')->setLabel('Wordpress MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('Drupal Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'wp_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_m_subscriptions LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } class Am_Import_Coupon3 extends Am_Import_Abstract { static $batches; function createBatch(Array $r){ $batch = $this->getDi()->couponBatchRecord; $batch->begin_date = $r['coupon_startdate']; if($r['discount_type'] == 'amt') { $batch->discount_type = 'number'; $batch->discount = $r['discount']; } else { $batch->discount_type = 'percent'; $batch->discount = doubleval($r['discount']); } $batch->expire_date = $r['coupon_enddate']; $batch->is_disabled = 0; $batch->is_recurring = 0; $batch->use_count = $r['coupon_uses']; $batch->user_use_count = $r['coupon_uses']; $batch->product_ids = $r['coupon_sub_id'] ? $this->getDi()->db->selectCell("select id from ?_data where `table`='product' and `key`='wm:id' and `value`=?", $r['coupon_sub_id']) : ""; $batch->insert(); return $batch->pk(); } public function doWork(&$context) { // Imported coupons $importedCoupons = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='coupon' AND `key`='wm:id'"); $q = $this->db_wordpress->queryResultOnly("SELECT * FROM ?_m_coupons LIMIT ?d,9000000",$context); while ($r = $this->db_wordpress->fetchRow($q)) { if (!$this->checkLimits()) return; if (in_array($r['id'], $importedCoupons)) continue; $context++; $coupon = $this->getDi()->couponRecord; $coupon->code = $r['couponcode']; $coupon->batch_id = $this->createBatch($r); $coupon->used_count = $r['coupon_used']; $coupon->insert(); $coupon->data()->set('wm:id', $r['id'])->update(); } return true; } } abstract class InvoiceCreator_Abstract { /** User */ protected $user; // all payments protected $payments = array(); // grouped by invoice protected $groups = array(); // prepared Invoices protected $invoices = array(); // protected $paysys_id; /** @var DbSimple_Mypdo */ protected $db_wordpress; public function getDi() { return Am_Di::getInstance(); } public function __construct($paysys_id, DbSimple_Interface $db) { $this->db_wordpress = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $payments) { $this->user = $user; foreach ($payments as $p) { $this->payments[$p['id']] = $p; } $this->groupByInvoice(); $this->beforeWork(); return $this->doWork(); } function beforeWork() { } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='wm:id'"); } return @$cache[$pid]; } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_wordpress; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_wordpress, array $options = array()) { $this->db_wordpress = $db_wordpress; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='wm:id'"); $q = $this->db_wordpress->queryResultOnly("SELECT * FROM ?_m_subscriptions"); while ($r = $this->db_wordpress->fetchRow($q)) { if (in_array($r['id'], $importedProducts)) continue; $context++; $p = $this->getDi()->productRecord; $p->title = $r['sub_name']; $p->description = $r['sub_description']; $p->sort_order = $r['order_num']; $p->is_disabled = $r['sub_active'] ? 0 : 1; $p->data()->set('wm:id', $r['id']); $p->insert(); $bpdata = $this->db_wordpress->selectRow("select * from ?_m_subscriptions_levels where sub_id = ?", $r['id']); $bp = $p->createBillingPlan(); $bp->title = 'default'; switch($bpdata['sub_type']){ case 'finite' : $bp->first_price = $bpdata['level_price']; $bp->first_period = $bpdata['level_period'].$bpdata['level_period_unit']; $bp->rebill_times = 0; break; case 'indefinite' : $bp->first_price = $bpdata['level_price']; $bp->first_period = Am_Period::MAX_SQL_DATE; $bp->rebill_times = 0; break; case 'serial' : $bp->first_price = $bp->second_price = $bpdata['level_price']; $bp->first_period = $bp->second_period = $bpdata['level_period'].$bpdata['level_period_unit']; $bp->rebill_times = IProduct::RECURRING_REBILLS; break; } $bp->insert(); } return true; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { //$crypt = $this->getDi()->crypt; $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='wm:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_wordpress->queryResultOnly("SELECT u.*, um1.meta_value as first_name, um2.meta_value as last_name FROM ?_users u LEFT JOIN ?_usermeta um1 on u.ID= um1.user_id and um1.meta_key = 'first_name' LEFT JOIN ?_usermeta um2 on u.ID= um2.user_id and um2.meta_key = 'last_name' WHERE u.ID > ?d ORDER BY u.ID {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_wordpress->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->email = $r['user_email']; $u->added = $r['user_registered']; $u->login = $r['user_login']; $u->name_f = (string)$r['first_name']; $u->name_l = (string)$r['last_name']; $u->is_approved = 1; $u->data()->set('wm:id', $r['ID']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time $u->pass = $r['user_pass']; try { $u->insert(); $this->insertPayments($r['ID'], $u); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } function insertPayments($id, User $u) { $payments = $this->db_wordpress->select(" (select concat('tr', transaction_ID) as id, transaction_subscription_ID as sub_id, transaction_user_ID as user_id, transaction_paypal_ID as txn_id, transaction_total_amount as amount, transaction_status as status, '' as startdate, '' as expirydate, transaction_stamp as stamp , transaction_currency as currency from ?_m_subscription_transaction where transaction_user_ID=?) union (select concat('rel', rel_id) as id, sub_id, user_id, '' as txn_id, 0 as amount, 'Access', startdate, expirydate, 0 as stamp, '' as currency from ?_m_membership_relationships where user_id =?) order by user_id desc ", $id,$id); $payments = $payments ? $payments : array(); //to add access if exists InvoiceCreator_Abstract::factory('standard', $this->db_wordpress)->process($u, $payments); } } PK\n= = *default/controllers/NoAccessController.phpnu[view->accessObjectTitle = $this->getParam('title', ___('protected area')); $this->view->orderUrl = $this->getDi()->url('signup', false); $this->view->display('no-access.phtml'); } function folderAction() { $id = $this->_request->getInt('id'); if (!$id) throw new Am_Exception_InputError("Empty folder#"); $folder = $this->getDi()->folderTable->load($id); if(empty($folder)) throw new Am_Exception_InputError("Folder not found"); // Check if login cookie exists. If not, user is not logged in and should be redirected to login page. $pl = $this->getDi()->plugins_protect->loadGet('new-rewrite'); // User will be there only if file related to folder doesn't exists. // So if main file exists, this means that user is logged in but don't have an access. // If main file doesn't exists, redirect user to new-rewrite in order to recreate it. // Main file will be created even if user is not active. if (is_file($pl->getFilePath($pl->getEscapedCookie()))) { if ($folder->no_access_url) { $this->_response->redirectLocation($folder->no_access_url); } else { $this->view->accessObjectTitle = ___("Folder %s (%s)", $folder->title, $folder->url); $this->view->orderUrl = $this->getDi()->url('signup', false); $this->view->display('no-access.phtml'); } } else { $url = $this->getDi()->url('protect/new-rewrite', array( 'f' => $id, 'url' => $this->getParam('url', $folder->getUrl()), ), false); return $this->_response->redirectLocation($url); } } function contentAction() { $id = $this->_request->getInt('id'); $type = $this->_request->getFiltered('type'); if (!$id) throw new Am_Exception_InputError("Empty folder#"); $regestry = $this->getDi()->resourceAccessTable->getAccessTables(); if (isset($regestry[$type]) && ($r = $regestry[$type]->load($id, false))) { $title = ___($r->getLinkTitle()); } else { $title = ___("Protected Content [%s-%d]", $type, $id); } $this->view->accessObjectTitle = $title; $this->view->orderUrl = $this->getDi()->url('signup', false); $this->view->useLayout = !$this->getRequest()->isXmlHttpRequest(); $this->view->display('no-access.phtml'); } }PK\BU̴'default/controllers/AudioController.phpnu[getPlayerConfig($media); $view = new Am_View; $params = array( 'key' => $this->getDi()->config->get('flowplayer_license'), 'height' => 30, 'width' => 500, 'plugins' => array( 'controls' => array( 'fullscreen' => false, 'height' => 30, 'autoHide' => false ), 'audio' => array( 'url' => $view->_scriptJs("flowplayer/flowplayer.audio.swf"), ) ), 'clip' => array( 'autoPlay' => (isset($config['autoPlay']) && $config['autoPlay']) ? true : false, 'provider' => 'audio' ) ); return $params; } public function getJWPlayerParams(ResourceAbstractFile $media) { return array( 'key' => $this->getDi()->config->get('jwplayer_license'), 'height' => 30, 'width' => 500 ); } }PK\H,,(default/controllers/MemberController.phpnu[getDi()->auth->requireLogin($this->getDi()->url('member',null,false,2)); $this->user = $this->getDi()->user; $this->view->assign('user', $this->user); $this->user_id = $this->user->pk(); } function paymentHistoryAction() { $psList = $this->getDi()->paysystemList; $this->view->activeInvoices = $this->getDi()->invoiceTable->selectObjects("SELECT * FROM ?_invoice i WHERE status IN (?a) AND user_id=? ORDER BY tm_started DESC", array( Invoice::RECURRING_ACTIVE, Invoice::PAID, Invoice::RECURRING_CANCELLED, Invoice::RECURRING_FAILED), $this->user_id); foreach ($this->view->activeInvoices as $invoice) { $invoice->_paysysName = $psList->getTitle($invoice->paysys_id); // if there is only 1 item, offer upgrade path $invoice->_upgrades = array(); if (in_array($invoice->getStatus(), array(Invoice::PAID, Invoice::RECURRING_ACTIVE))) { foreach ($invoice->getItems() as $item) { $item->_upgrades = $this->getDi()->productUpgradeTable->findUpgrades($invoice, $item); } } if ($this->getDi()->config->get('allow_cancel')) { if ($invoice->getStatus() == Invoice::RECURRING_ACTIVE) { $invoice->_cancelUrl = null; try { $ps = $this->getDi()->plugins_payment->loadGet($invoice->paysys_id, false); if ($ps) $invoice->_cancelUrl = $ps->getUserCancelUrl($invoice); } catch (Exception $e){} } } if ($this->getDi()->config->get('allow_restore')) { if(in_array($invoice->getStatus(), array(Invoice::RECURRING_CANCELLED, Invoice::RECURRING_FAILED))) { $invoice->_restoreUrl = null; try { $ps = $this->getDi()->plugins_payment->loadGet($invoice->paysys_id, false); if ($ps) $invoice->_restoreUrl = $ps->getUserRestoreUrl($invoice); } catch (Exception $e){} } } } $this->view->payments = $this->getDi()->invoicePaymentTable->findByUserId($this->user_id, null, null, 'dattm DESC'); foreach ($this->view->payments as $payment) { $payment->_paysysName = $psList->getTitle($payment->paysys_id); } $this->view->display('member/payment-history.phtml'); } function setError($error) { $this->view->assign('error', $error); return false; } function addRenewAction() { $this->_redirect('signup'); } function indexAction() { $products_cancel = array(); $recurringInvoices = $this->getDi()->invoiceTable->selectObjects("SELECT * FROM ?_invoice i WHERE status=? AND user_id=?", Invoice::RECURRING_ACTIVE, $this->user_id); if ($this->getDi()->config->get('allow_cancel')) { foreach ($recurringInvoices as $invoice) { $cancelUrl = null; try { $ps = $this->getDi()->plugins_payment->loadGet($invoice->paysys_id, false); if ($ps) $cancelUrl = $ps->getUserCancelUrl($invoice); } catch (Exception $e){} if ($cancelUrl) { /* @var $invoice Invoice */ foreach ($invoice->getItems() as $item) { if ($item->item_type == 'product') { $products_cancel[$item->item_id] = $cancelUrl; } } } } } $products_upgrade = array(); $activeInvoices = $this->getDi()->invoiceTable->selectObjects("SELECT * FROM ?_invoice i WHERE status IN (?a) AND user_id=? ORDER BY tm_started DESC", array(Invoice::RECURRING_ACTIVE, Invoice::PAID, Invoice::RECURRING_CANCELLED), $this->user_id); foreach ($activeInvoices as $invoice) { foreach ($invoice->getItems() as $item) { if ($product = $item->tryLoadProduct()) { if ($upgrades = $this->getDi()->productUpgradeTable->findUpgrades($invoice, $item)) { $item->_upgrades = $upgrades; $products_upgrade[$product->pk()] = $item; } } } } $this->view->assign('member_products', $this->getDi()->user->getActiveProducts()); $this->view->assign('member_future_products', $this->getDi()->user->getFutureProducts()); $member_links = array ( $this->getDi()->url('logout',null,false,2) => ___('Logout'), $this->getDi()->url('profile',null,false,2) => ___('Change Password/Edit Profile'), $this->getDi()->url('member/payment-history',null,false,2) => ___('Payments History') ); $event = new Am_Event(Am_Event::GET_MEMBER_LINKS, array('user' => $this->user)); $event->setReturn($member_links); $this->view->assign('member_links', $this->getDi()->hook->call($event) ->getReturn()); $left_member_links = $this->getDi()->hook ->call(Am_Event::GET_LEFT_MEMBER_LINKS, array('user' => $this->user)) ->getReturn(); $this->view->assign('left_member_links', $left_member_links); $resources = $this->getDi()->resourceAccessTable ->getAllowedResources($this->getDi()->user, ResourceAccess::USER_VISIBLE_TYPES); $this->view->assign('resources', $resources); foreach ($resources as $k => $r) { if (!$r->renderLink()) unset($resources[$k]); } if (!$resources && !$left_member_links) $this->getDi()->blocks->remove('member-main-resources'); $this->view->assign('products_expire', $this->getDi()->user->getActiveProductsExpiration()); $this->view->assign('products_rebill', $this->getDi()->user->getActiveProductsRebill()); $this->view->assign('products_begin', $this->getDi()->user->getFutureProductsBeginning()); $this->view->assign('products_cancel', $products_cancel); $this->view->assign('products_upgrade', $products_upgrade); $this->view->display('member/main.phtml'); } function getInvoiceAction() { $id = $this->getDi()->security->reveal($this->getParam('id')); if (!$id) throw new Am_Exception_InputError("Wrong invoice# passed"); $payment = $this->getDi()->invoicePaymentTable->load($id); if (!$payment) throw new Am_Exception(___("Invoice not found")); if ($payment->user_id != $this->user->user_id) throw new Am_Exception_Security("Foreign invoice requested : [$id] for {$this->user->user_id}"); $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $pdfInvoice = Am_Pdf_Invoice::create($payment); $pdfInvoice->setDi($this->getDi()); $this->_helper->sendFile->sendData($pdfInvoice->render(), 'application/pdf', $pdfInvoice->getFileName()); } function upgradeAction() { $id = $this->getFiltered('invoice_id'); if (!$id) throw new Am_Exception_InputError("Wrong invoice# passed"); $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($id); /* @var $invoice Invoice */ if (!$invoice) throw new Am_Exception_InputError(___("Invoice not found")); if ($invoice->user_id != $this->user->user_id) throw new Am_Exception_Security("Foreign invoice requested : [$id] for {$this->user->user_id}"); // right now we only can handle first item $item = null; foreach ($invoice->getItems() as $it) { if ($it->pk() == $this->getDi()->security->reveal($this->getParam ('invoice_item_id'))) $item = $it; } $upgrade = $this->getDi()->productUpgradeTable->load($this->_request->getInt('upgrade')); if (!$invoice->canUpgrade($item, $upgrade)) throw new Am_Exception_Security("Cannot process upgrade"); $newInvoice = $invoice->doUpgrade($item, $upgrade, $this->getParam('coupon')); $newInvoice->toggleValidateProductRequirements(false);//we already checked it @see Invoice::canUpgrade if (($newInvoice->getStatus() == Invoice::PENDING) && !$newInvoice->data()->get('upgrade-pending')) { if ($err = $newInvoice->validate()) throw new Am_Exception_InputError($err[0]); $newInvoice->save(); $payProcess = new Am_Paysystem_PayProcessMediator($this, $newInvoice); try { $result = $payProcess->process(); } catch (Am_Exception_Redirect $e) { throw $e; } if ($result->isFailure()) throw new Am_Exception_InputError(current($result->getErrorMessages())); } if ($newInvoice->isCompleted()) { $this->_redirect('member/payment-history?' . http_build_query(array( '_msg' => ___('Product upgrade finished successfully') . '.'))); } else { $this->_redirect('member/payment-history?' . http_build_query(array( '_msg' => ___('Processing your product upgrade') . '...'))); } } function restoreRecurringAction(){ if (!$this->getDi()->config->get('allow_restore')) throw new Am_Exception_InputError; // load invoice to work with $id = $this->getFiltered('invoice_id'); if (!$id) throw new Am_Exception_InputError("Wrong invoice# passed"); $invoice = $this->getDi()->invoiceTable->findFirstByPublicId($id); /* @var $invoice Invoice */ if (!$invoice) throw new Am_Exception_InputError(___("Invoice not found")); if ($invoice->user_id != $this->user->user_id) throw new Am_Exception_Security("Foreign invoice requested : [$id] for {$this->user->user_id}"); $newInvoice = $invoice->doRestoreRecurring(); $newInvoice->setPaysystem($invoice->paysys_id); $err = $newInvoice->validate(); if ($err) throw new Am_Exception_InputError($err[0]); $newInvoice->data()->set(Invoice::ORIG_ID, $invoice->pk()); $newInvoice->insert(); $payProcess = new Am_Paysystem_PayProcessMediator($this, $newInvoice); $result = $payProcess->process(); } }PK\6  +default/controllers/AdminAuthController.phpnu[addFieldset() ->setLabel(___('Restore Password')); if (Am_Recaptcha::isConfigured() && $this->getDi()->config->get('recaptcha')) { $captcha = $fs->addGroup(null, array('class' => 'row-wide')); $captcha->addRule('callback', ___('Anti Spam check failed'), array($this, 'validateCaptcha')); $captcha->addStatic('captcha')->setContent($this->getDi()->recaptcha->render()); } $login = $fs->addText('login', array('class' => 'el-wide')) ->setLabel(___('Username/Email')); $login->addRule('callback', ___('User is not found in database'), array($this, 'checkLogin')); $this->addSubmit('_', array('value' => ___('Get New Password'))); } public function validateCaptcha() { $resp = ''; foreach ($this->getDataSources() as $ds) { if ($resp = $ds->getValue('g-recaptcha-response')) break; } return $this->getDi()->recaptcha->validate($resp); } public function checkLogin($login) { if (!$admin = $this->getDi()->adminTable->findFirstByLogin($login)) { $admin = $this->getDi()->adminTable->findFirstByEmail($login); } return (boolean) $admin; } public function getDi() { return Am_Di::getInstance(); } } class AdminAuthController extends Am_Mvc_Controller_Auth { protected $loginField = 'am_admin_login'; protected $passField = 'am_admin_passwd'; protected $loginType = Am_Auth_BruteforceProtector::TYPE_ADMIN; const EXPIRATION_PERIOD = 2; //hrs const CODE_STATUS_VALID = 1; const CODE_STATUS_EXPIRED = -1; const CODE_STATUS_INVALID = 0; const SECURITY_CODE_STORE_PREFIX ='admin-restore-password-request-'; protected function checkAdminAuthorized() { // nop } public function getAuth() { return $this->getDi()->authAdmin; } public function changePassAction() { $s = $this->getRequest()->getFiltered('s'); if (!$this->checkCode($s, $admin)) { $this->view->title = ___('Security code is invalid'); $url = $this->getDi()->url('admin-auth/send-pass'); $this->view->content = '"; $this->view->display('admin/layout-login.phtml'); return; } $pass = $this->getDi()->security->randomString(10); $et = Am_Mail_Template::load('send_password_admin', null, true); $et->setUser($admin); $et->setPass($pass); $et->send($admin); $admin->setPass($pass); $admin->update(); $this->getDi()->store->delete(self::SECURITY_CODE_STORE_PREFIX . $s); $this->view->title = ___('Password changed'); $url = $this->getDi()->url('admin'); $this->view->content = '"; $this->view->display('admin/layout-login.phtml'); } public function sendPassAction() { $form = new Admin_RestorePassForm; $this->view->form = $form; if ($form->isSubmitted() && $form->validate()) { $vars = $form->getValue(); $login = $vars['login']; //admin should be found for sure. we already tried it while validating form $admin = $this->getDi()->adminTable->findFirstByLogin($login); if (!$admin) { $admin = $this->getDi()->adminTable->findFirstByEmail($login); } $this->sendSecurityCode($admin); $this->view->message = ___('Link to reset your password was sent to your Email.'); $this->view->form = null; //do not show form } else { $this->view->message = ___("Please enter your username or email\n" . "address. You will receive a link to create\n" . "a new password via email."); } $this->view->display('admin/send-pass.phtml'); } protected function checkCode($code, &$admin) { $data = $this->getDi()->store->get(self::SECURITY_CODE_STORE_PREFIX . $code); if (!$data) { return false; } list($admin_id, $pass, $email) = explode('-', $data, 3); $admin = $this->getDi()->adminTable->load($admin_id); if ($admin->pass != $pass || $admin->email != $email) { return false; } return true; } private function sendSecurityCode(Admin $admin) { $security_code = $this->getDi()->security->randomString(16); $securitycode_expire = sqlTime(time() + self::EXPIRATION_PERIOD * 60 * 60); $et = Am_Mail_Template::load('send_security_code_admin', null, true); $et->setUser($admin); $et->setUrl($this->getDi()->url('admin-auth/change-pass',array('s'=> $security_code),false)); $et->setHours(self::EXPIRATION_PERIOD); $et->send($admin); $data = array( $admin->pk(), $admin->pass, $admin->email ); $this->getDi()->store->set( self::SECURITY_CODE_STORE_PREFIX . $security_code, implode('-', $data), $securitycode_expire ); } function indexAction() { if ($this->_request->isXmlHttpRequest() && !$this->_request->isPost()) { header('Content-type: text/plain; charset=UTF-8'); header('HTTP/1.0 402 Admin Login Required'); return $this->_response->ajaxResponse(array('err' => ___('Admin Login Required'), 'ok' => false)); } if ($this->getDi()->authAdmin->getUserId()) { Am_Mvc_Response::redirectLocation($this->getDi()->url('admin', false)); } // only store if GET, nothing already stored, and no params in URL if ($this->_request->isGet() && empty($this->getSession()->admin_redirect) && !$this->_request->getQuery() && $this->checkUri($this->_request->getRequestUri())) { $this->getSession()->admin_redirect = $this->_request->getRequestUri(); } return parent::indexAction(); } protected function checkUri($uri) { //allow only valid uri without parameters. $uri = trim(substr($uri, strlen($this->getDi()->url(''))), '/'); if (strpos('admin-auth', $uri) !== false) return false; //protect against endless redirect loop return preg_match('/^[-a-zA-Z0-9]+(\/[-a-zA-Z0-9]*)*$/', $uri); } public function renderLoginForm($authResult) { return $this->view->render('admin/_login.phtml'); } public function renderLoginPage($html) { $this->view->content = $html; return $this->view->render('admin/login.phtml'); } protected function createAdapter() { return new Am_Auth_Adapter_AdminPassword( $this->getLogin(), $this->getPass(), $this->getDi()->adminTable); } public function getLogoutUrl() { return $this->getDi()->url('admin', false); } public function getOkUrl() { $uri = $this->getUriFromSession(); return $uri ? $uri : $this->getDi()->url('admin', false); } public function redirectOk() { if ($this->_request->isXmlHttpRequest()) { header("Content-type: text/plain; charset=UTF-8"); header('HTTP/1.0 200 OK'); echo json_encode(array('ok' => true, 'adminLogin' => $this->getAuth()->getUsername())); } else parent::redirectOk(); } protected function getUriFromSession() { $uri = $this->getSession()->admin_redirect; $this->getSession()->admin_redirect = null; return ($uri && $this->checkUri($uri)) ? $uri : null; } }PK\hh/default/controllers/AdminUserNoteController.phpnu[setActiveMenu('users-browse'); $this->user_id = $this->getInt('user_id'); if (!$this->user_id) throw new Am_Exception_InputError("Wrong URL specified: no member# passed"); parent::preDispatch(); } function createGrid() { $ds = new Am_Query($this->getDi()->userNoteTable); $ds = $ds->addWhere('user_id=?', $this->user_id) ->leftJoin('?_admin', 'a', 't.admin_id=a.admin_id') ->addField('a.login') ->addField('a.name_f') ->addField('a.name_l') ->addOrder('dattm', 'DESC'); $grid = new Am_Grid_Editable('_un', ___('Notes'), $ds, $this->getRequest(), $this->getView(), $this->getDi()); $grid->addField(new Am_Grid_Field_Date('dattm', 'Date/Time'))->setFormatDatetime(); $grid->addField('login', ___('Admin'), true) ->setRenderFunction(array($this, 'renderAdmin')); $grid->addField('content', ___('Message')) ->setRenderFunction(array($this, 'renderMessage')); $grid->setFormValueCallback('attachments', array('RECORD', 'unserializeIds'), array('RECORD', 'serializeIds')); $grid->setFilter(new Am_Grid_Filter_Text(___('Search by Message'), array('content' => 'LIKE'))); $grid->actionGet('delete')->setIsAvailableCallback(array($this, 'canEdit')); $grid->actionGet('edit')->setIsAvailableCallback(array($this, 'canEdit')); $grid->setRecordTitle(___('Note')); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_INSERT, array($this, 'beforeInsert')); $grid->setForm(array($this, 'createForm')); return $grid; } function canEdit(Am_Record $record) { $admin = $this->getDi()->authAdmin->getUser(); return $admin->isSuper() || ($admin->pk() == $record->admin_id); } function renderAdmin($record) { return $this->renderTd(sprintf('%s %s (%s)', $record->name_f, $record->name_l, $record->login)); } function renderMessage(Am_Record $record) { $msg = sprintf('
      %s
      ', $this->escape($record->content)); $att = ''; foreach ($record->unserializeIds($record->attachments) as $upload_id) { $upload = $this->getDi()->uploadTable->load($upload_id); $att .= sprintf('
      %s (%s)', $this->getDi()->url('admin-upload/get', array('id'=>$upload->pk())), $this->escape($upload->name), $this->escape($upload->getSizeReadable())); } $msg .= $att ? '
      ' . $att : $att; return $this->renderTd($msg, false); } function createForm() { $form = new Am_Form_Admin; $form->addTextarea('content', array('rows' => 10, 'class' => "no-label el-wide")) ->setLabel(___('Message')); $form->addUpload('attachments', array('multiple' => 1), array('prefix' => 'user_note')) ->setJsOptions('{fileBrowser:false}') ->setLabel(___('Attach File')); return $form; } function beforeInsert($vars, $record) { $record->dattm = $this->getDi()->sqlDateTime; $record->user_id = $this->user_id; $record->admin_id = $this->getDi()->authAdmin->getUserId(); } }PK\XvII,default/controllers/AdminSetupController.phpnu[hasPermission(Am_Auth_Admin::PERM_SETUP); } function getConfigValues() { $c = new Am_Config; $c->read(); $ret = $this->_getConfigValues('', $c->getArray()); // strip keys encoded for form foreach ($ret as $k => $v) { if (preg_match('/___/', $k)) unset($ret[$k]); } return $ret; } function _getConfigValues($prefix, $node) { $ret = array(); foreach ($node as $k => $v) { if (!is_array($v) || (isset($v[0]) || isset($v[1]))) { $ret[$prefix . $k] = $v; } else { $ret = array_merge_recursive($ret, $this->_getConfigValues("$prefix$k.", $v)); } } return $ret; } function indexAction() { $this->_request->setParam('p', 'global'); return $this->displayAction(); } function displayAction() { $this->setActiveMenu('setup'); $this->p = filterId($this->_request->getParam('p')); if ($this->p === 'ajax') return $this->ajaxAction(); $this->initSetupForms(); $this->form = $this->getForm($this->p, false); $this->form->prepare(); if ($this->form->isSubmitted()) { $this->form->setDataSources(array($this->_request)); if ($this->form->validate() && $this->form->saveConfig()) { $this->getDi()->adminLogTable->log(sprintf('Update Configuration [%s]', $this->form->getPageId())); $this->redirectHtml($this->getUrl(null, $this->p), ___('Config values updated...')); return; } } else { $cfg = $this->getConfigValues(); unset($cfg['p']); unset($cfg['page']); unset($cfg['hp_c']); $this->form->setDataSources(array( new HTML_QuickForm2_DataSource_Array($cfg), new HTML_QuickForm2_DataSource_Array($this->form->getDefaults()), )); } $this->view->assign('p', $this->p); $this->view->assign('pages', $this->renderPages()); $this->form->replaceDotInNames(); $this->view->assign('pageObj', $this->form); $this->view->assign('form', $this->form); $this->view->display('admin/setup.phtml'); } public function ajaxAction() { $this->p = filterId($this->_request->getParam('_p')); $this->initSetupForms(); $this->form = $this->getForm($this->p, false); $this->form->prepare(); $this->form->setDataSources(array($this->_request)); $this->form->ajaxAction($this->getRequest()); } function renderPages() { $chunks = array_chunk($this->forms, 8, true); $out = ""; foreach ($chunks as $chunk) { $out .= ""; $i = 0; foreach ($chunk as $k => $page) { $out .= $this->renderPage($page); $i++; } if ($i < 7) $out .= sprintf("\n", 8 - $i); $out .= "\n"; } return $out; } function renderPage(Am_Form_Setup $form) { $cl = ($form->getPageId() == $this->p) ? 'sel' : 'notsel'; return sprintf('%s' . "\n", $cl, $this->getUrl(null, $form->getPageId()), $form->getComment(), $form->getTitle()); } function initSetupForms() { @class_exists('Am_Form_Setup_Standard', true); foreach ($this->getDi()->modules->getEnabled() as $module) { $fn = AM_APPLICATION_PATH . '/' . $module . '/library/SetupForms.php'; if (!file_exists($fn)) continue; include_once $fn; } foreach (get_declared_classes() as $class) { if (is_subclass_of($class, 'Am_Form_Setup')) { $rc = new ReflectionClass($class); if ($rc->isAbstract()) continue; if ($class == 'Am_Form_Setup_Theme') continue; $this->addForm(new $class); } } foreach ($this->getDi()->plugins as $k => $mgr) { $mgr->loadEnabled()->getAllEnabled(); } $event = new Am_Event_SetupForms($this); $this->getDi()->hook->call($event); } function addForm(Am_Form_Setup $form) { $id = $form->getPageId(); if (isset($this->forms[$id])) throw new Am_Exception_InternalError("Form [$id] is already exists"); $this->forms[$id] = $form; return $this; } /** @return Am_Form_Setup */ function getFormByTitle($title) { foreach ($this->forms as $f) { if ($f->getTitle() == $title) return $f; } $form = new Am_Form_Setup(strtolower(filterId($title))); $form->setTitle($title); $this->addForm($form); return $form; } function getForm($id, $autoCreate = true) { if (isset($this->forms[$id])) return $this->forms[$id]; if (!$autoCreate) throw new Am_Exception_InputError("Form [$id] does not exists"); $form = new Am_Form_Setup($id); $this->addForm($form); return $form; } static public function getInstance() { if (!self::$instance) self::$instance = new self; return self::$instance; } public function preDispatch() { $vars = $this->_request->toArray(); foreach ($vars as $k => $v) { $kk = Am_Form_Setup::name2dots($k); if ($kk != $k) { unset($vars[$k]); $vars[$kk] = $v; } } $this->_request->setParams($vars); } }PK\  *default/controllers/AdminBanController.phpnu[hasPermission(Am_Auth_Admin::PERM_BAN); } public function initPages() { $this->addPage(array($this, 'createGrid'), 'ip', ___('IP Address')) ->addPage(array($this, 'createGrid'), 'email', ___('E-Mail Address')) ->addPage(array($this, 'createGrid'), 'login', ___('Username')); } function createGrid($id, $title) { $ds = new Am_Query($this->getDi()->banTable); $ds->addWhere("`type` = ?", $id); $g = new Am_Grid_Editable('_'.$id, ___('Disallow new Signups by %s', $title), $ds, $this->_request, $this->view); $g->setPermissionId(Am_Auth_Admin::PERM_BAN); $g->setForm(array($this, 'createForm')); $g->addField('value', ___('Locked Value')); $g->addField('comment', ___('Comment')); $g->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, array($this, 'renderConfig')); $g->setFilter(new Am_Grid_Filter_Text(' ', array( 'value' => 'LIKE', 'comment' => 'LIKE' ), array('placeholder' => ___('Locked Value/Comment')))); return $g; } public function createForm(Am_Grid_Editable $grid) { $id = substr($grid->getId(),1); $form = new Am_Form_Admin; $form->addText('value', array('class' => 'el-wide')) ->setLabel(___("Value\nuse % as wildcard mask")) ->addRule('required'); $form->addHidden('type') ->setValue($id); $form->addText('comment', array('class' => 'el-wide')) ->setLabel(___('Comment')); return $form; } public function configSaveAction() { $type = $this->getRequest()->getFiltered('c'); if ($type == 'default') $type = 'ip'; $action = $this->getFiltered('a'); Am_Config::saveValue('ban.'.$type.'_action', $action); $this->_redirect('default/admin-ban/p/' . $type); } public function renderConfig(& $output, $grid) { $type = substr($grid->getId(), 1); $url = $this->escape($this->getUrl(null, 'config-save')); $checked1 = $checked2 = ""; if ($this->getDi()->config->get('ban.'.$type.'_action') == 'die') { $checked2 = 'selected="selected"'; } else { $checked1 = 'selected="selected"'; } $text = ___("Choose action when locked %s used by customer during signup", '['.$type.']'); $opt1 = ___("Display error message"); $opt2 = ___("Die and show ugly error message"); $output .= <<
      $text
      CUT; } }PK\ūnEHEH1default/controllers/AdminImportOss6Controller.phpnu[db_oss->select("SELECT ProductID AS ARRAY_KEY, s.* FROM ?_subscriptions s WHERE UserID=?", $this->user->data()->get('oss6:id')); foreach ($this->groups as $pid => $list) { $data = unserialize($list[0]['Details']); $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $newP = $this->_translateProduct($pid); $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($newP)); $item->qty = 1; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'paypal'; $invoice->tm_added = $list[0]['Date']; $invoice->tm_started = $list[0]['Date']; $invoice->public_id = $list[0]['UniqID']; $invoice->currency = $data['mc_currency']; $invoice->calculate(); $invoice->status = Invoice::PAID; if (isset($list[0]['subscr_id'])) { $invoice->data()->set('external_id', $list[0]['subscr_id']); } foreach ($list as $p) $pidlist[] = $p['ID']; $invoice->data()->set('oss6:id', implode(',', $pidlist)); $invoice->insert(); // insert payments foreach ($list as $p) { $newP = $this->_translateProduct($p['ProductID']); $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = $p['Cost']; $payment->paysys_id = 'paypal'; $payment->dattm = $p['Date']; $payment->receipt_id = $p['txn_id']; $payment->transaction_id = 'import-paypal-' . mt_rand(10000, 99999); $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='oss6:id',`value`=?", $payment->pk(), $p['ID']); } if (isset($access[$pid])) { $this->insertAccess($access[$pid], $invoice->pk(), $payment->pk()); unset($access[$pid]); } } //add other access as manually added if ($access) { foreach ($access as $a) { $this->insertAccess($a); } } $this->user->checkSubscriptions(); } protected function insertAccess($access, $invoice_id = null, $payment_id = null) { $newP = $this->_translateProduct($access['ProductID']); $a = $this->getDi()->accessRecord; $a->user_id = $this->user->user_id; $a->setDisableHooks(); $a->begin_date = $access['StartDate']; $a->expire_date = $access['ExpireDate'] ? $access['ExpireDate'] : Am_Period::RECURRING_SQL_DATE; if (!is_null($invoice_id)) { $a->invoice_id = $invoice_id; } if (!is_null($payment_id)) { $a->invoice_payment_id = $payment_id; } $a->product_id = $newP; $a->insert(); } public function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$p['ProductID']][] = $p; } } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { //$crypt = $this->getDi()->crypt; $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='oss:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_oss->queryResultOnly("SELECT * FROM ?_users WHERE id > ?d ORDER BY id {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_oss->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->name_f = (string) $r['firstname']; $u->name_l = (string) $r['lastname']; $u->email = $r['email']; $u->added = $r['signup_date']; $u->remote_addr = $r['signup_ip']; $u->login = $r['username']; $u->setPass($r['plain_password'], true); // do not salt passwords heavily to speed-up $u->data()->set('external_id', $this->findPayerId($r['id'])); $u->data()->set('oss6:id', $r['id']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time try { $u->insert(); $this->insertPayments($r['id'], $u); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } function findPayerId($id) { $payerId = null; $payment = $this->db_oss->selectRow(" select * from ?_payments where payment_system_code = 'paypal' and Status = 'completed' and UserID = ? and subscr_id is not null and subscr_id >'' ", $id); if ($payment) { $details = unserialize($payment['Details']); $payerId = isset($details['payer_id']) ? $details['payer_id'] : $payerId; } return $payerId; } function insertPayments($id, User $u) { $payments = $this->db_oss->select(" select * from ?_payments p left join ?_payments_products pr on p.ID = pr.PaymentId where payment_system_code = 'paypal' and Status='completed' and UserID=? and Details like '%subscr_payment%'", $id); $payments = $payments ? $payments : array(); //to add access if exists $byPs = array( 'paypal' => array() ); foreach ($payments as $p) { $byPs['paypal'][] = $p; } foreach ($byPs as $paysys_id => $list) { InvoiceCreator_Abstract::factory($paysys_id, $this->db_oss)->process($u, $list); } } } abstract class InvoiceCreator_Abstract { /** User */ protected $user; // all payments protected $payments = array(); // grouped by invoice protected $groups = array(); // prepared Invoices protected $invoices = array(); // protected $paysys_id; /** @var DbSimple_Mypdo */ protected $db_oss; public function getDi() { return Am_Di::getInstance(); } public function __construct($paysys_id, DbSimple_Interface $db) { $this->db_oss = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $payments) { $this->user = $user; foreach ($payments as $p) { $this->payments[$p['ID']] = $p; } $this->groupByInvoice(); $this->beforeWork(); return $this->doWork(); } function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$p['product_id']][] = $p; } } function beforeWork() { } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='oss6:id'"); } return @$cache[$pid]; } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_oss; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_oss, array $options = array()) { $this->db_oss = $db_oss; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='oss6:id'"); $q = $this->db_oss->queryResultOnly("SELECT * FROM ?_groups"); while ($r = $this->db_oss->fetchRow($q)) { if (in_array($r['id'], $importedProducts)) continue; $r['Duration'] = unserialize($r['Duration']); $r['Url'] = unserialize($r['Url']); $context++; $p = $this->getDi()->productRecord; $p->title = $r['_group']; $p->description = $r['comment']; $p->currency = $r['Url']['currency']; $p->data()->set('oss6:id', $r['id']); $p->insert(); $bp = $p->createBillingPlan(); $bp->title = 'default'; if ($r['price'] != 0) { $bp->first_price = $r['Url']['a1'] > 0 ? $r['Url']['a1'] : $r['Url']['a3']; $bp->first_period = $r['Url']['p1'] > 0 ? $r['Url']['p1'] . strtolower($r['Url']['t1']) : $r['Url']['p3'] . strtolower($r['Url']['t3']); $bp->second_price = $r['Url']['a3']; $bp->second_period = $r['Url']['p3'] . strtolower($r['Url']['t3']); $bp->rebill_times = IProduct::RECURRING_REBILLS; } else { // not free $bp->first_price = $r['price']; $bp->first_period = $r['Duration']['days'] ? $r['Duration']['days'] . 'd' : ($r['Duration']['months'] ? $r['Duration']['months'] . 'm' : $r['Duration']['years'] . 'y'); $bp->rebill_times = 0; } $bp->insert(); } return true; } } class AdminImportOss6Controller extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_oss; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->oss_db = null; $this->getSession()->oss_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->oss_import = null; } if (!$this->getSession()->oss_db) return $this->askDbSettings(); $this->db_oss = Am_Db::connect($this->getSession()->oss_db); if (!$this->getSession()->oss_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->oss_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_oss, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from OSS6"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->oss_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-oss6",array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->oss_import = array( 'import' => $val['import'], 'user' => @$val['user'], ); $this->_redirect('admin-import-oss6'); return; } } $this->view->title = "Import OSS6 Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='oss6:id'"); $total = $this->db_oss->selectCell("SELECT COUNT(*) FROM ?_groups"); if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); if ($imported_products) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='oss6:id'"); $total = $this->db_oss->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->oss_db = $this->form->getValue(); $this->_redirect('admin-import-oss6'); } else { $this->view->title = "Import OSS6 Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('OSS6 MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('OSS6 MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('OSS6 MySQL Password'); $form->addText('db')->setLabel('OSS6 MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('OSS6 Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'oss6_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_users LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } }PK\AXkk2default/controllers/AdminTransGlobalController.phpnu[getBaseTranslationData($language); $result = $this->mergeWithCustomTranslation($result, $language); break; case self::FETCH_MODE_REWRITTEN : $result = Am_Di::getInstance()->translationTable->getTranslationData($language); $base = $this->getBaseTranslationData($language); foreach ($result as $k=>$v) { if (!key_exists($k, $base)) { unset($result[$k]); } } break; case self::FETCH_MODE_UNTRANSLATED : $result = $this->getBaseTranslationData($language); $result = $this->mergeWithCustomTranslation($result, $language); $flip = array_flip($result); $result = array_filter($result, function($v) use ($flip) { return (bool)(!$v || $v == $flip[$v]); }); break; default: throw new Am_Exception_InternalError('Unknown fetch mode : ' . $fetchMode); break; } if (isset($result[self::LOCALE_KEY])) { $locale = $result[self::LOCALE_KEY]; unset($result[self::LOCALE_KEY]); } return $result; } public function createTranslation($language) { $filename = $this->getFileName($language); $path = Am_Di::getInstance()->root_dir . "/application/default/language/user/{$filename}"; if ($error = $this->validatePath($path)) { return $error; } $content = $this->getFileContent($language); file_put_contents($path, $content); return ''; } private function mergeWithCustomTranslation($translationData, $language) { $custom = Am_Di::getInstance()->translationTable->getTranslationData($language); foreach ($translationData as $k=>$v) { if (isset($custom[$k])) { $translationData[$k] = $custom[$k]; } } return $translationData; } private function getBaseTranslationData($language) { return $this->_getBaseTranslationData($language); } private function validatePath($path) { if (file_exists($path)) { return ___('File %s is already exist. You can not create already existing translation.', $path); } $dir = dirname($path); if (!is_writeable($dir)) { return ___('Folder %s is not a writable for the PHP script. Please
      chmod this file using webhosting control panel file manager or using your
      favorite FTP client to 777 (write and read for all)
      Please, don\'t forget to chmod it back to 755 after creation of translation', $dir); } return ''; } abstract protected function _getBaseTranslationData($language); abstract function getFileName($language); abstract function getFileContent($language, $translationData = array()); } class TranslationDataSource_PHP extends TranslationDataSource_Abstract { function getFileName($language) { return $language . '.php'; } function getFileContent($language, $translationData = array()) { $expectedLocaleName = $language; $locale = new Zend_Locale($expectedLocaleName); //prepend local to start of array $translationData = array_reverse($translationData); $translationData[self::LOCALE_KEY] = $locale; $translationData = array_reverse($translationData); $out = ''; $out .= " $msgstr) { $out .= "\t"; $out .= sprintf("'%s'=>'%s',", str_replace("'", "\'", $msgid), str_replace("'", "\'", $msgstr) ); $out .= PHP_EOL; } $out .= "\t''=>''" . PHP_EOL; $out .= ");"; return $out; } protected function _getBaseTranslationData($language) { $result = include(AM_APPLICATION_PATH . "/default/language/user/default.php"); $result = array_merge($result, (array)@include(AM_APPLICATION_PATH . "/default/language/user/{$language}.php")); $result = array_merge($result, (array)@include(AM_APPLICATION_PATH . "/default/language/admin/default.php")); $result = array_merge($result, (array)@include(AM_APPLICATION_PATH . "/default/language/admin/{$language}.php")); return $result; } } class TranslationDataSource_PO extends TranslationDataSource_Abstract { function getFileName($language) { return $language . '.po'; } function getFileContent($language, $translationData=array()) { $expectedLocaleName = $language; $locale = new Zend_Locale($expectedLocaleName); //prepend local to start of array $translationData = array_reverse($translationData); $translationData[self::LOCALE_KEY] = $locale; $translationData = array_reverse($translationData); $out = ''; foreach ($translationData as $msgid => $msgstr) { $out .= sprintf('msgid "%s"', $this->prepare($msgid, true)); $out .= PHP_EOL; $out .= sprintf('msgstr "%s"', $this->prepare($msgstr, true)); $out .= PHP_EOL; $out .= PHP_EOL; } return $out; } protected function _getBaseTranslationData($language) { $result= array(); $result = $this->getTranslationArray(AM_APPLICATION_PATH . "/default/language/user/default.pot"); $result = array_merge($result, $this->getTranslationArray(AM_APPLICATION_PATH . "/default/language/user/{$language}.po")); return $result; } private function getTranslationArray($file) { $result = array(); $fPointer = fopen($file, 'r'); $part = ''; while (!feof($fPointer)) { $line = fgets($fPointer); $part .= $line; if (!trim($line)) { //entity divided with empty line in file $result = array_merge($result, $this->getTranslationEntity($part)); $part = ''; } } fclose($fPointer); unset($result['']);//unset meta return $result; } private function getTranslationEntity($contents) { $result = array(); $matches = array(); $matched = preg_match( '/(msgid\s+("([^"]|\\\\")*?"\s*)+)\s+' . '(msgstr\s+("([^"]|\\\\")*?"\s*)+)/u', $contents, $matches ); if ($matched) { $msgid = $matches[1]; $msgid = preg_replace( '/\s*msgid\s*"(.*)"\s*/s', '\\1', $matches[1]); $msgstr = $matches[4]; $msgstr = preg_replace( '/\s*msgstr\s*"(.*)"\s*/s', '\\1', $matches[4]); $result[$this->prepare($msgid)] = $this->prepare($msgstr); } return $result; } private function prepare($string, $reverse = false) { if ($reverse) { $smap = array('"', "\n", "\t", "\r"); $rmap = array('\\"', '\\n"' . "\n" . '"', '\\t', '\\r'); return (string) str_replace($smap, $rmap, $string); } else { $smap = array('/"\s+"/', '/\\\\n/', '/\\\\r/', '/\\\\t/', '/\\\\"/'); $rmap = array('', "\n", "\r", "\t", '"'); return (string) preg_replace($smap, $rmap, $string); } } } class TranslationDataSource_DB extends TranslationDataSource_Abstract { public function createTranslation($language) { throw new Am_Exception_InputError('Local translations can not be created'); } function getFileName($language) { throw new Am_Exception_InputError('Local translations can not be exported'); } function getFileContent($language, $translationData = array()) { throw new Am_Exception_InputError('Local translations can not be exported'); } protected function _getBaseTranslationData($language) { $result = array(); foreach (Am_Di::getInstance()->db->select("SELECT title, description FROM ?_product") as $r) { $result[ $r['title'] ] = ""; $result[ $r['description'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT terms FROM ?_billing_plan WHERE terms<>''") as $r) { $result[ $r['terms'] ] = ""; } foreach ((array)Am_Di::getInstance()->config->get('member_fields') as $field) { $result[ $field['title'] ] = ""; $result[ $field['description'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title, `desc` FROM ?_folder") as $r) { $result[ $r['title'] ] = ""; $result[ $r['desc'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title, `desc` FROM ?_file") as $r) { $result[ $r['title'] ] = ""; $result[ $r['desc'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title, `desc` FROM ?_page") as $r) { $result[ $r['title'] ] = ""; $result[ $r['desc'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title, `desc` FROM ?_link") as $r) { $result[ $r['title'] ] = ""; $result[ $r['desc'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title, `desc` FROM ?_video") as $r) { $result[ $r['title'] ] = ""; $result[ $r['desc'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title FROM ?_resource_category") as $r) { $result[ $r['title'] ] = ""; $result[ $r['description'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT title FROM ?_user_group") as $r) { $result[ $r['title'] ] = ""; } foreach (Am_Di::getInstance()->db->select("SELECT fields FROM ?_saved_form") as $r) { $fields = json_decode($r['fields'], true); foreach ($fields as $field){ if (isset($field['labels'])) { foreach ($field['labels'] as $k => $v) { $result[ $v ] = ""; } } } } $event = new Am_Event(Am_Event::GET_BASE_TRANSLATION_DATA); $event->setReturn($result); Am_Di::getInstance()->hook->call($event); return $event->getReturn(); } } class Am_Grid_DataSource_Array_Trans extends Am_Grid_DataSource_Array { /* @var TranslationDataProvider_Abstract */ protected $tDataSource = null; protected $language = null; protected $_order_f = null; protected $_order_d = null; public function __construct($language) { $this->tDataSource = $this->createTDataSource(); $this->language = $language; $translationData = $this->tDataSource->getTranslationData( $this->language, TranslationDataSource_Abstract::FETCH_MODE_ALL ); return parent::__construct(self::prepareArray($translationData)); } public function getLanguage() { return $this->language; } public static function prepareArray($translationData) { $records = array(); foreach ($translationData as $base => $trans) { $record = new stdClass(); $record->base = $base; $record->trans = $trans; $records[] = $record; } return $records; } /** * @return TranslationDataSource_Abstract */ public function getTDataSource() { return $this->tDataSource; } public function setOrder($fieldNameOrRaw, $desc=null) { $this->_order_f = $fieldNameOrRaw; $this->_order_d = $desc; return parent::setOrder($fieldNameOrRaw, $desc); } //this method is only for use in Am_Grid_Filter public function _friendGetOrder() { return array($this->_order_f, $this->_order_d); } protected function createTDataSource() { return new TranslationDataSource_PHP(); } } class Am_Grid_Action_NewTrans extends Am_Grid_Action_Abstract { protected $title = "Create New"; protected $type = self::NORECORD; public function run() { $form = $this->getForm(); if (!$form->isSubmitted()) { // nop } elseif ($form->validate()) { $error = $this->grid->getDataSource() ->getTDataSource() ->createTranslation( $this->grid->getCompleteRequest()->getParam('new_language') ); if ($error) { $form->setError($error); } else { Zend_Locale::hasCache() && Zend_Locale::clearCache(); Zend_Translate::hasCache() && Zend_Translate::clearCache(); Am_Di::getInstance()->cache->clean(); $this->grid->redirectBack(); } } echo $this->renderTitle(); echo $form; } public function getForm() { $languageTranslation = Am_Locale::getSelfNames(); $avalableLocaleList = Zend_Locale::getLocaleList(); $existingLanguages = Am_Di::getInstance()->languagesListUser; $languageOptions = array(); foreach ($avalableLocaleList as $k=>$v) { $locale = new Zend_Locale($k); if (!array_key_exists($locale->getLanguage(), $existingLanguages) && isset($languageTranslation[$locale->getLanguage()])) { $languageOptions[$locale->getLanguage()] = "($k) " . $languageTranslation[$locale->getLanguage()]; } } asort($languageOptions); $form = new Am_Form_Admin(); $form->setAction($this->grid->makeUrl(null)); $form->addElement('select', 'new_language') ->setLabel(___('Language')) ->loadOptions($languageOptions) ->setId('languageSelect'); $form->addElement('hidden', 'a') ->setValue('new'); $form->addSaveButton(); foreach ($this->grid->getVariablesList() as $k) { if ($val = $this->grid->getRequest()->get($k)) { $form->addHidden($this->grid->getId() .'_'. $k)->setValue($val); } } return $form; } } class Am_Grid_Action_ExportTrans extends Am_Grid_Action_Abstract { protected $title = "Export"; protected $type = self::NORECORD; public function run() { if (!$language = $this->grid->getCompleteRequest()->get('language')) { $language = Am_Di::getInstance()->locale->getLanguage(); } $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; //return response without layout $outputDataSource = new TranslationDataSource_PO(); $inputDataSource = $this->grid->getDataSource()->getTDataSource(); $filename = $outputDataSource->getFileName($language); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache"); header('Content-type: text/plain'); header("Content-Disposition: attachment; filename=$filename"); echo $outputDataSource->getFileContent($language, $inputDataSource->getTranslationData($language, TranslationDataSource_Abstract::FETCH_MODE_REWRITTEN)); } } class Am_Grid_Filter_Trans extends Am_Grid_Filter_Abstract { protected $language = null; protected $varList = array('filter', 'mode'); public function __construct($lang) { $this->title = ' '; $this->language = $lang; } public function setLanguage($lang) { $this->language = $lang; } protected function getLanguage() { return $this->language; } protected function applyFilter() { $tDataSource = $this->grid->getDataSource()->getTDataSource(); $translationData = $tDataSource->getTranslationData( $this->getLanguage(), $this->getParam('mode', TranslationDataSource_Abstract::FETCH_MODE_ALL) ); $translationData = $this->filter($translationData, $this->getParam('filter')); $this->grid->getDataSource()->_friendSetArray( Am_Grid_DataSource_Array_Trans::prepareArray($translationData) ); list($fieldname, $desc) = $this->grid->getDataSource()->_friendGetOrder(); if ($fieldname) { $this->grid->getDataSource()->setOrder($fieldname, $desc); } } function renderInputs() { $options = array( TranslationDataSource_Abstract::FETCH_MODE_ALL => 'All', TranslationDataSource_Abstract::FETCH_MODE_REWRITTEN => 'Customized Only', TranslationDataSource_Abstract::FETCH_MODE_UNTRANSLATED => 'Untranslated Only' ); $filter = ___('Display Mode').' '; $filter .= $this->renderInputSelect('mode', $options, array('id'=>'trans-mode')); $filter .= ' '.___('Filter by String').' '; $filter .= $this->renderInputText('filter'); $filter .= sprintf('', $this->getLanguage()); return $filter; } protected function filter($array, $filter) { if (!$filter) return $array; foreach ($array as $k=>$v) { if (false === stripos($k, $filter) && false === stripos($v, $filter)) { unset($array[$k]); } } return $array; } } class AdminTransGlobalController extends Am_Mvc_Controller_Grid { protected $language = null; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_TRANSLATION); } public function init() { $this->getView()->headScript()->appendScript($this->getJs()); if ($language = $this->_request->get('language')) { $this->language = $language; } else { $locale = new Zend_Locale(Zend_Registry::get('Zend_Translate')->getLocale()); $this->language = $locale->getLanguage(); } parent::init(); } public function createGrid() { $grid = $this->_createGrid(___('Global Translations')); $grid->actionAdd(new Am_Grid_Action_NewTrans); $grid->setPermissionId(Am_Auth_Admin::PERM_TRANSLATION); $actionExport = new Am_Grid_Action_ExportTrans(); $actionExport->setTarget('_top'); $grid->actionAdd($actionExport); return $grid; } protected function _createGrid($title) { $ds = $this->createDS($this->getLanguage()); $grid = new Am_Grid_Editable('_trans', $title, $ds, $this->_request, $this->view); $grid->addField(new Am_Grid_Field('base', ___('Key/Default'), true, '', null, '50%')) ->setRenderFunction(function($obj, $f, $grid, $field){ return $grid->renderTd(nl2br($grid->escape($obj->$f)), false); }); $grid->addField(new Am_Grid_Field('trans', ___('Current'), true, '', array($this, 'renderTrans'), '50%')); $grid->setFilter(new Am_Grid_Filter_Trans($this->getLanguage())); $grid->actionsClear(); $grid->setRecordTitle(___('Translation')); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, array($this, 'wrapContent')); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, array($this, 'wrapTable')); return $grid; } protected function createDS($language) { return new Am_Grid_DataSource_Array_Trans($language); } function wrapTable(& $out, $grid) { $out = '
      ' . $out . sprintf('', $this->getLanguage()); $vars = $this->grid->getVariablesList(); $vars[] = 'p'; //stay on current page foreach ($vars as $var) { if ($val = $this->grid->getRequest()->getParam($var)) { $out .= sprintf('', $this->grid->getId() . '_' . $var, $val); } } $out .= '
      ' . '
      '; } function wrapContent(& $out, $grid) { $out = $this->renderLanguageSelection() . $out; } function renderTrans($record) { return $this->renderTd(sprintf('', base64_encode($record->base), Am_Html::escape($record->trans)), false); } public function getLanguage() { return $this->language; } function saveAction() { $trans = $this->getRequest()->getParam('trans', array()); $translationData = $this->grid->getDataSource() ->getTDataSource() ->getTranslationData( $this->getLanguage(), TranslationDataSource_Abstract::FETCH_MODE_ALL ); $toReplace = array(); foreach ($trans as $k=>$v) { $k = base64_decode($k); if ( $v != $translationData[$k] ) { $toReplace[$k] = $v; } } if (count($toReplace)) { $this->getDi()->translationTable->replaceTranslation($toReplace, $this->language); if (Zend_Translate::hasCache()) { Zend_Translate::clearCache(); } } $_POST['trans'] = $_GET['trans'] = null; $this->grid->getRequest()->setParam('trans', null); $this->grid->getCompleteRequest()->setParam('trans', null); $this->getRequest()->setParam('trans', null); $url = $this->getDi()->url('admin-trans-global/index', $this->getRequest()->toArray(), false); $this->_request->isXmlHttpRequest() ? $this->redirectAjax($url, ___('Redirect')) : $this->_response->redirectLocation($url); } function redirectAjax($url, $text) { return printf( "
      " . "%s" . "" . "
      " , $this->escape($text) , $this->escape($url), $this->escape(___('Click here if you do not want to wait any longer (or if your browser does not automatically forward you).')) ); } protected function renderLanguageSelection() { $form = new Am_Form_Admin(); $form->addElement('select', 'language') ->setLabel(___('Language')) ->setValue($this->getLanguage()) ->loadOptions($this->getLanguageOptions()); $renderer = HTML_QuickForm2_Renderer::factory('array'); $form->render($renderer); $form = $renderer->toArray(); $filter = ''; foreach ($form['elements'] as $el) { $filter .= ' ' . $el['label'] . ' ' . $el['html']; } return sprintf("
      \n", $this->escape($this->getUrl(null, 'index'))) . $filter . "
      \n" ; } protected function getLanguageOptions() { return $this->getDi()->languagesListUser; } protected function getJs() { $revertIcon = $this->getView()->icon('revert'); $cancel_title = ___('Cancel All Changes in Translations on Current Page'); $jsScript = <<{$revertIcon}').attr('title', jQuery(this).data('value')).click(function(){ input = jQuery(this).prev(); input.attr('value', input.data('value')); jQuery(this).remove(); input.removeClass('changed'); changedNum--; if (!changedNum && jQuery(".am-pagination").hasClass('hidden')) { jQuery(".am-pagination").next().remove(); jQuery(".am-pagination").removeClass('hidden'); jQuery(".am-pagination").show(); } return false; }) changedNum++; jQuery(this).after(aRevert); aRevert.before(' '); } var aCancel = jQuery('$cancel_title').click(function(){ jQuery(".text-edit").filter(".changed").each(function(){ input = jQuery(this); input.attr('value', input.data('value')); input.next().remove(); input.removeClass('changed'); }) if (jQuery(".am-pagination").hasClass('hidden')) { jQuery(".am-pagination").next().remove(); jQuery(".am-pagination").removeClass('hidden'); jQuery(".am-pagination").show(); } changedNum = 0; return false; }) aCancel = aCancel.wrap('
      ').parents('div'); if (jQuery(".am-pagination").css('display')!='none') { jQuery(".am-pagination").addClass('hidden') jQuery(".am-pagination").after(aCancel); jQuery(".am-pagination").hide(); } }) })(jQuery) CUT; return $jsScript; } }PK\g3default/controllers/AdminFileDownloadController.phpnu[getDi()->fileDownloadTable); $query->leftJoin('?_file', 'f', 'f.file_id=t.file_id') ->addField('f.title', 'title') ->addWhere('user_id=?', $this->getParam('user_id')); $grid = new Am_Grid_Editable('_file_download', ___("File Downloads"), $query, $this->_request, $this->view); $grid->setPermissionId(Am_Auth_Admin::PERM_LOGS_DOWNLOAD); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_Delete()); $grid->actionAdd(new Am_Grid_Action_Group_Delete()); $grid->addField(new Am_Grid_Field_Date('dattm', ___('Date/Time'))); $grid->addField('remote_addr', ___('IP')); $grid->addField('title', ___('File')); return $grid; } } PK\З:'default/controllers/VideoController.phpnu[getPlayerConfig($media); if ($media->poster_id || !empty($config['poster_id'])) $config['autoPlay'] = true; $params = array ( 'key' => $this->getDi()->config->get('flowplayer_license'), 'height' => @$config['height'], 'width' => @$config['width'], 'clip' => array( 'autoPlay' => (isset($config['autoPlay']) && $config['autoPlay']) ? true : false, 'autoBuffering' => (isset($config['autoBuffering']) && $config['autoBuffering']) ? true : false, 'bufferLength' => isset($config['bufferLength']) ? $config['bufferLength'] : 3, 'scaling' => isset($config['scaling']) ? $config['scaling'] : 'scale' ) ); $position_map = array( 'top-right' => array('top' => 20, 'right' => 20), 'top-left' => array('top' => 20, 'left' => 20), 'bottom-right' => array('bottom' => 20, 'right' => 20), 'bottom-left' => array('bottom' => 20, 'left' => 20), ); if (!empty($config['logo_id'])) { $logo = $this->getDi()->uploadTable->load($config['logo_id'], false); $logo_url = $logo ? $this->getDi()->url('upload/get/' . preg_replace('/^\./', '', $logo->path),false) : ''; $params['logo'] = array_merge(array( 'url' => $logo_url, 'fullscreenOnly' => false, ), $position_map[!empty($config['logo_position']) ? $config['logo_position'] : 'top-right']); } if ($media->cc_id) { $cc = $this->getDi()->uploadTable->load($media->cc_id, false); $cc_url = $this->getDi()->url('upload/get/' . preg_replace('/^\./', '', $cc->path),false); $cc_postion = !empty($config['cc_position']) ? $config['cc_position'] : 'top'; //switch position of button depending of subtitles position //(we need opposite position to avoid messy) $cc_button_token = $cc_postion == 'top' ? 'bottom' : 'top'; $params['plugins']['captions'] = array( 'url' => "flowplayer.captions.swf", 'captionTarget' => 'content', 'button' => array( $cc_button_token => 30 ) ); $params['clip']['captionUrl'] = $cc_url; $params['plugins']['content']['url'] = "flowplayer.content.swf"; $params['plugins']['content'][$cc_postion] = 30; } return $params; } public function getJWPlayerParams(ResourceAbstractFile $media) { $config = $this->getPlayerConfig($media); if ($media->poster_id || !empty($config['poster_id'])) $config['autoPlay'] = true; switch(@$config['scaling']){ case 'orig' : $stretching = 'none'; break; case 'fit' : $stretching = 'uniform'; break; case 'scale' : $stretching = 'exactfit'; break; default: $stretching = 'uniform'; } $params = array( 'key' => $this->getDi()->config->get('jwplayer_license'), 'height' => @$config['height'], 'width' => @$config['width'], 'autostart' => @$config['autoPlay'], 'stretching' => $stretching ); if (!empty($config['logo_id'])) { $logo = $this->getDi()->uploadTable->load($config['logo_id'], false); $logo_url = $logo ? $this->getDi()->url('upload/get/' . preg_replace('/^\./', '', $logo->path),false) : ''; $params['logo'] = array( 'file' => $logo_url, 'postion' => !empty($config['logo_position']) ? $config['logo_position'] : 'top-right' ); } return $params; } }PK\dKУ-default/controllers/AdminBackupController.phpnu[hasPermission(Am_Auth_Admin::PERM_BACKUP_RESTORE); } function preDispatch() { if ($this->getDi()->modules->isEnabled('cc')) throw new Am_Exception_AccessDenied(___('Online backup is disabled if you have CC payment plugins enabled. Use offline backup instead')); } function backupAction() { check_demo(); if (!$this->_request->isPost()) throw new Am_Exception_InputError(___('Backup can be runned by POST request only')); $dat = date('Y_m_d-Hi'); $host = strtolower(preg_replace('/[^a-zA-Z0-9\.]/', '', preg_replace('/^www\./', '', $_SERVER['HTTP_HOST']))); $fn = "am-$host-$dat.sql"; while (@ob_end_clean()); $bp = $this->getDi()->backupProcessor; if ($bp->isGzip()) header("Content-Type: application/x-gzip"); else header("Content-Type: text/sql"); header("Content-Disposition: attachment; filename=$fn" . ($bp->isGzip() ? ".gz" : "" ) ); $stream = fopen('php://output', 'wb'); if (!$stream) throw new Am_Exception_InternalError('Could not open php://output stream'); $bp->run($stream); $this->getDi()->adminLogTable->log('Downloaded backup'); exit(); // no any output later! } function indexAction() { $this->view->display('admin/backup.phtml'); } }PK\c\1SS0default/controllers/AdminVatReportController.phpnu[hasPermission(Am_Auth_Admin::PERM_REPORT); } function indexAction() { $grid = $this->createMainGrid(); $grid->runWithLayout('admin/layout.phtml'); } function detailsAction() { $grid = $this->createDetailsGrid(); $grid->runWithLayout('admin/layout.phtml'); } function createDetailsGrid() { $grid = new Am_Grid_EU_Vat_Report_Details('_eu_vat_details', ___('EU VAT Report Details'), $this->getDetailsDataSource(), $this->getRequest(), $this->view, $this->getDi()); $grid->setPermissionId(Am_Auth_Admin::PERM_REPORT); $grid->return_url = $this->getRequest()->get('return_url'); return $grid; } function getDetailsDataSource() { $ds = new Am_Query($this->getDi()->invoicePaymentTable); $ds->leftJoin( '?_user', 'u', 't.user_id = u.user_id' ) ->leftJoin( '?_data', 'user_country', 't.invoice_id = user_country.id and user_country.`table` = "invoice" and user_country.`key`="tax_user_country"' ) ->leftJoin( '?_data', 'invoice_ip', 't.invoice_id = invoice_ip.id and invoice_ip.`table` = "invoice" and invoice_ip.`key`="tax_invoice_ip"' ) ->leftJoin( '?_data', 'invoice_ip_country', 't.invoice_id = invoice_ip_country.id and invoice_ip_country.`table` = "invoice" and invoice_ip_country.`key`="tax_invoice_ip_country"' ) ->leftJoin( '?_data', 'user_registration_ip', 't.invoice_id = user_registration_ip.id and user_registration_ip.`table` = "invoice" and user_registration_ip.`key`="tax_user_registration_ip"' ) ->leftJoin( '?_data', 'user_registration_ip_country', 't.invoice_id = user_registration_ip_country.id and user_registration_ip_country.`table` = "invoice" and user_registration_ip_country.`key`="tax_user_registration_ip_country"' ) ->leftJoin( '?_data', 'self_validation_country', 't.invoice_id = self_validation_country.id and self_validation_country.`table` = "invoice" and self_validation_country.`key`="tax_self_validation_country"' ) ->leftJoin( '?_invoice_refund', 'refund', 't.invoice_payment_id = refund.invoice_payment_id' ) ->leftJoin( '?_invoice', 'invoice', 't.invoice_id = invoice.invoice_id' ) ->addField('if(user_country.value is null, if(u.country is null, "", u.country), user_country.value)', 'country') ->addField('concat(u.name_f, " ", u.name_l)', 'name') ->addField('u.email') ->addField('u.street') ->addField('u.zip') ->addField('u.state') ->addField('u.city') ->addField('u.tax_id') ->addField('invoice.tax_rate') ->addField('round(if(refund.amount, (t.amount-refund.amount) - (t.amount-refund.amount)*if(t.tax, t.tax, 0)/t.amount, t.amount-if(t.tax, t.tax, 0))/t.base_currency_multi, 2)', 'total_amount') ->addField('round(if(refund.amount, (t.amount-refund.amount)*if(t.tax, t.tax, 0)/t.amount, if(t.tax, t.tax, 0))/t.base_currency_multi,2)', 'tax_amount') ->addField('invoice_ip.value', 'inv_ip') ->addField('invoice_ip_country.value', 'inv_ip_country') ->addField('user_registration_ip.value', 'reg_ip') ->addField('user_registration_ip_country.value', 'reg_ip_country') ->addField('self_validation_country.value', 'self_country') ->addField('refund.invoice_refund_id', 'invoice_refund_id'); return $ds; } /** * @return Am_Query $query; */ function getMainDataSource() { $ds = new Am_Query($this->getDi()->invoicePaymentTable); $ds->leftJoin('?_user', 'u', 't.user_id = u.user_id') ->leftJoin('?_data', 'user_country', 't.invoice_id = user_country.id and `table` = "invoice" and `key`="tax_user_country"') ->leftJoin('?_invoice_refund', 'refund', 't.invoice_payment_id = refund.invoice_payment_id') ->leftJoin('?_invoice', 'invoice', 't.invoice_id = invoice.invoice_id') ->addField('if(user_country.value is null, if(u.country is null, "", u.country), user_country.value)', 'country') ->addField('invoice.tax_rate') ->addField('round(sum(if(refund.amount, t.amount-refund.amount, t.amount)/t.base_currency_multi),2)', 'sales_amount') ->addField('round(sum(if(refund.amount, (t.amount-refund.amount)*if(t.tax, t.tax, 0)/t.amount, if(t.tax, t.tax, 0))/t.base_currency_multi),2)', 'tax_amount') ->addField('round(sum(if(refund.amount, (t.amount-refund.amount) - (t.amount-refund.amount)*if(t.tax, t.tax, 0)/t.amount, t.amount-if(t.tax, t.tax, 0))/t.base_currency_multi),2)', 'sales_without_tax_amount') ->addField('concat(if(user_country.value is null, if(u.country is null, "", u.country), user_country.value), "-", if(invoice.tax_rate is null, "", invoice.tax_rate))', 'country_rate'); $ds->groupBy('country_rate', ''); $ds->addOrder('country'); return $ds; } /** * @return Am_Grid_Readonly $grid */ function createMainGrid() { $grid = new Am_Grid_EU_Vat_Report('_eu_vat_main', ___('EU Vat Report'), $this->getMainDataSource(), $this->getRequest(), $this->view, $this->getDi()); $grid->setPermissionId(Am_Auth_Admin::PERM_REPORT); return $grid; } } class Am_Grid_EU_Vat_Report_Details extends Am_Grid_Editable { protected $totals = array(); function __construct($id, $title, \Am_Grid_DataSource_Interface_Editable $ds, \Am_Mvc_Request $request, \Am_View $view, \Am_Di $di = null) { parent::__construct($id, $title, $ds, $request, $view, $di); $this->_request = $request; } function init() { parent::init(); $this->addField('dattm', ___('Payment Date'))->setGetFunction(function ($record, $grid, $field){ return amDatetime($record->dattm); }); $this->addField('display_invoice_id', ___('Receipt ID')); $this->addField('name', ___('Consumer Name')); $this->addField('email', ___('Consumer Email')); $this->addField('country', ___('Country')); $this->addField('address', ___('Address'))->setGetFunction(function($record, $grid, $field) { return join(", ", array($record->street, $record->city, $record->zip, $record->state, $record->country)); }); $this->addField('inv_ip', ___('IP(Country)'))->setGetFunction(function($record, $grid, $field) { return $record->inv_ip . "(" . ($record->inv_ip_country ? $record->inv_ip_country : ___('undefined')) . ")"; }); $this->addField('reg_ip', ___('Registration IP(Country)'))->setGetFunction(function($record, $grid, $field) { return $record->reg_ip . "(" . ($record->reg_ip_country ? $record->reg_ip_country : ___('undefined')) . ")"; }); $this->addField('self_country', ___('Confirmed Manually')); $this->addField('tax_id', ___('VAT ID')); $this->addField('receipt_id', ___('Paysystem Receipt ID')); $this->totals[] = $this->addField('total_amount', ___('Amount excl. Tax')); $this->totals[] = $this->addField('tax_amount', ___('VAT')); $this->addField('tax_rate', ___('VAT Rate'))->setGetFunction(function($record, $grid, $field){ return $record->{$field} ? $record->{$field}."%" : "-"; }); $this->setFilter(new Am_Grid_Filter_EU_VAT_Details); } public function initActions() { $this->actionAdd(new Am_Grid_Action_Export('eu_vat_details_export', ___('Export'))); $this->actionAdd(new Am_Grid_EU_Vat_Action_Back); $this->actionAdd($action = new Am_Grid_Action_Total_Vat); foreach ($this->totals as $field) { $action->addField($field); } } public function getAmount($record, $grid, $field) { return Am_Currency::render($record->{$field}); } function renderTitle($noTags = false) { if ($noTags) return $this->title; $total = $this->getDataSource()->getFoundRows(); $page = $this->getCurrentPage(); $count = $this->getCountPerPage(); $ret = ""; $ret .= '

      '; $ret .= Am_Html::escape($this->title); $msgs = array(); $filter = $this->getFilter()->getFilterVars(); list($dat1, $dat2) = $this->getFilter()->getDates(); if ($country = @$filter['country']) { $msgs[] = ___('Country: %s', Am_Html::escape(implode(", ", (array)$country))); } if ($paysys_id = @$filter['paysys_id']) { $msgs[] = ___('Paysystem: %s', Am_Html::escape($paysys_id)); } $msgs[] = ___("Period: %s-%s", amDate($dat1), amDate($dat2)); if ($total) { $msgs[] = ___("displaying records %d-%d from %d", $page * $count + 1, min($total, ($page + 1) * $count), $total); } else { $msgs[] = ___("no records"); } if ($msgs) $ret .= ' (' . implode(", ", $msgs) . ')'; $ret .= "

      "; return $ret; } } class Am_Grid_EU_Vat_Action_Back extends Am_Grid_Action_Abstract { protected $type = self::NORECORD; protected $url; protected $attributes = array( 'target' => '_top' ); public function getUrl($record = null, $id = null) { return $this->grid->return_url; } public function run() { //nop } } class Am_Grid_EU_Vat_Report extends Am_Grid_Editable { protected $totals = array(); function init() { parent::init(); $this->addField('country', ___('Country'))->setGetFunction(function($record, $grid, $field) { static $countries; if (!is_array($countries)) $countries = array(); if (!$record->country) return ''; if (!isset($countries[$record->country])) $countries[$record->country] = Am_Di::getInstance()->countryTable->getTitleByCode($record->country); return $record->country . "(" . $countries[$record->country] . ")"; }); $this->totals[] = $this->addField('sales_amount', ___('Consumer Sales'))->setGetFunction(array($this, 'getAmount')); $this->totals[] = $this->addField('sales_without_tax_amount', ___('Amount excl. VAT'))->setGetFunction(array($this, 'getAmount')); $this->addField('tax_rate', ___('VAT Rate'))->setGetFunction(function($record, $grid, $field){ return $record->{$field} ? $record->{$field}."%" : "-"; }); $this->totals[] = $this->addField('tax_amount', ___('VAT Amount'))->setGetFunction(array($this, 'getAmount')); $this->setFilter(new Am_Grid_Filter_EU_VAT_Report()); } public function getAmount($record, $grid, $field) { return Am_Currency::render($record->{$field}); } function initActions() { $this->actionAdd(new Am_Grid_Action_Export); $this->actionAdd(new Am_Grid_Action_EU_VAT_RowDetails('_details', 'Details')); $this->actionAdd(new Am_Grid_Action_EU_VAT_Details('_full_details', 'Details')); $action = $this->actionAdd(new Am_Grid_Action_Total_Vat()); foreach ($this->totals as $f) { $action->addField($f, '%s'); } } function renderTitle($noTags = false) { if ($noTags) return $this->title; $total = $this->getDataSource()->getFoundRows(); $page = $this->getCurrentPage(); $count = $this->getCountPerPage(); $ret = ""; $ret .= '

      '; $ret .= Am_Html::escape($this->title); $msgs = array(); if ($total) { $msgs[] = ___("displaying records %d-%d from %d", $page * $count + 1, min($total, ($page + 1) * $count), $total); } else { $msgs[] = ___("no records"); } if ($this->filter && $this->filter->isFiltered()) { $override = array(); $dates = $this->filter->getDates(); $msgs[] = sprintf("%s %s - %s", ___('period'), amDate($dates[0]), amDate($dates[1])); } if ($msgs) $ret .= ' (' . implode(", ", $msgs) . ')'; $ret .= "

      "; return $ret; } } class Am_Grid_Action_EU_VAT_RowDetails extends Am_Grid_Action_Abstract { function __construct($id, $title) { parent::__construct($id, $title, null); $this->attributes['target'] = '_top'; } function getUrl($record = null, $id = null) { $vars = $this->grid->getFilter()->getFilterVars(); $params = array( '_eu_vat_details_filter'=> @$vars['filter'], 'return_url'=> Am_Di::getInstance()->request->assembleUrl(false,true), ); if(!is_null($record)) { $params['_eu_vat_details_filter']['country'][] = $record->country; $params['_eu_vat_details_filter']['tax_rate'] = $record->tax_rate; } return Am_Di::getInstance()->url("admin-vat-report/details", $params, false); } public function run() { } } class Am_Grid_Action_EU_VAT_Details extends Am_Grid_Action_EU_VAT_RowDetails { protected $type = self::HIDDEN; public function setGrid(Am_Grid_Editable $grid) { parent::setGrid($grid); if ($this->hasPermissions()) { $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, array($this, 'renderLink')); } } public function renderLink(& $out) { $out .= sprintf('', $this->getUrl()); } } abstract class Am_Grid_Filter_EU_VAT extends Am_Grid_Filter_Abstract { protected function applyFilter() { $filter = & $this->vars['filter']; $q = $this->grid->getDataSource(); if (!isset($filter['period'])) $filter['period'] = Am_Interval::PERIOD_THIS_MONTH; list($dat1, $dat2) = $this->getDates(); $q->addWhere('(t.dattm >=? and t.dattm<=?)', $dat1 . " 00:00:00", $dat2 . " 23:59:59"); if (@$filter['paysys_id']) { $q->addWhere('t.paysys_id in (?a)', $filter['paysys_id']); } if (@$filter['country']) { $q->addHaving('country in (?a)', $filter['country']); } if (@$this->vars['filter']['dont_show_empty']) $q->addHaving('tax_amount >0'); } function getFilterVars(){ return $this->vars; } function getDates() { $filter = $this->vars['filter']; if ($filter['period'] == 'exact') { $dat1 = Am_Form_Element_Date::createFromFormat(null, $filter['dat1'])->format('Y-m-d'); $dat2 = Am_Form_Element_Date::createFromFormat(null, $filter['dat2'])->format('Y-m-d'); } else { list($dat1, $dat2) = $this->grid->getDi()->interval->getStartStop($filter['period']); } return array($dat1, $dat2); } function isFiltered() { return true; } public function getTitle() { return ''; } } class Am_Grid_Filter_EU_VAT_Report extends Am_Grid_Filter_EU_VAT { protected function applyFilter() { parent::applyFilter(); $filter = &$this->vars['filter']; $q = $this->grid->getDataSource(); if (@$filter['paysys_id']) { $q->addField('concat(t.paysys_id, "-", country)', 'pscountry'); $q->addField('t.paysys_id', 'filter_paysys'); $q->groupBy('pscountry, invoice.tax_rate', ''); } } public function renderInputs() { $prefix = $this->grid->getId(); $filter = (array) $this->vars['filter']; $filter['dat1'] = Am_Html::escape(@$filter['dat1']); $filter['dat2'] = Am_Html::escape(@$filter['dat2']); $countryOptions = array(); $countryOptions = $countryOptions + Am_Di::getInstance()->countryTable->getOptions(); $countryOptions = Am_Html::renderOptions( $countryOptions, @$filter['country'] ); $paysysOptions = array(); $paysysOptions = $paysysOptions + Am_Di::getInstance()->paysystemList->getOptions(); $paysysOptions = Am_Html::renderOptions( $paysysOptions, @$filter['paysys_id'] ); $pOptions = array(); $period = array( Am_Interval::PERIOD_THIS_MONTH, Am_Interval::PERIOD_LAST_MONTH, Am_Interval::PERIOD_THIS_QUARTER, Am_Interval::PERIOD_LAST_QUARTER, Am_Interval::PERIOD_THIS_YEAR, Am_Interval::PERIOD_LAST_YEAR, Am_Interval::PERIOD_ALL ); $i = $this->grid->getDi()->interval; foreach ($period as $k) { $pOptions[$k] = $i->getTitle($k); } $pOptions['exact'] = ___('Exact Period'); $pOptions = Am_Html::renderOptions( $pOptions, @$filter['period'] ); $start = ___('Start Date'); $end = ___('End Date'); $offer_country = '-' . ___('Filter by Country') . '-'; $offer_paysys = '-' . ___('Filter by Paysystem') . '-'; $dSelect = ___('Report Dates'); $pSelect = ___('Report Period'); $dont_show_empty_checked = (@$filter['dont_show_empty'] == 1 ? 'checked' : ''); $dont_show_empty_label = ___('Do not include records with empty VAT'); return << $pSelect   
      $dSelect   
        

      CUT; } } class Am_Grid_Filter_EU_VAT_Details extends Am_Grid_Filter_EU_VAT { public function renderInputs() { // Nothing to show; } function renderFilter() { // Nothing to show; } } class Am_Grid_Action_Total_Vat extends Am_Grid_Action_Total { public function renderOut(& $out) { $titles = array(); $sql = $this->ds->getSql(); $totals = array(); foreach ($this->fields as $field) { /* @var $field Am_Grid_Field */ $name = $field->getFieldName(); $titles['_' . $name] = $field->getFieldTitle(); $totals[] = sprintf( '%s %s: %s', ___('Total'), $field->getFieldTitle(), Am_Currency::render(Am_Di::getInstance()->db->selectCell("select sum(total_qry.$name) from ($sql ) as total_qry")) ); } $html = sprintf('
      %s
      ', implode(',', $totals)); $out = preg_replace('|(isSuper(); } function indexAction() { $tables = $this->getDi()->db->selectCol("SHOW TABLES LIKE ?", $this->getDi()->config->get('db.mysql.prefix').'%'); foreach ($tables as $t){ print ___('Reparing') . " {$db->config[prefix]}$t..."; ob_end_flush(); $db->query("REPAIR TABLE {$db->config[prefix]}$t"); print ___('OK') . '
      '; } print ___('tables restored.'); } } PK\:+default/controllers/LogAccessController.phpnu[getDi()->auth->getUserId() && ($url = $this->getRequest()->getHeader('REFERER'))){ $this->getDi()->accessLogTable->logOnce( $this->getDi()->auth->getUserId(), $this->getRequest()->getClientIp(), $url); } } }PK\4-default/controllers/UnsubscribeController.phpnu[getParam('e')) throw new Am_Exception_InputError("Empty e-mail parameter passed - wrong url"); $s = $this->getFiltered('s'); if (!Am_Mail::validateUnsubscribeLink($e, $s, Am_Mail::LINK_USER)) throw new Am_Exception_InputError(___('Wrongly signed URL, please contact site admin')); $this->view->user = $this->getDi()->userTable->findFirstByEmail($e); if (!$this->view->user) throw new Am_Exception_InputError(___("Wrong parameters, error #1253")); if ($this->_request->get('yes')) { $this->view->user->unsubscribed = 1; $this->view->user->update(); $this->getDi()->hook->call(Am_Event::USER_UNSUBSCRIBED_CHANGED, array('user'=>$this->view->user, 'unsubscribed' => 1)); return $this->_redirect('member?' . http_build_query(array('_msg'=>___('Status of your subscription has been changed.')), '', '&')); } elseif ($this->_request->get('no')) { return $this->_redirect('member'); } $this->view->e = $e; $this->view->s = $s; if (!$this->getDi()->blocks->get($this->view, 'unsubscribe')) { $this->getDi()->blocks->add(new Am_Block('unsubscribe', ___('Unsubscribe'), 'unsubscribe-std', null, 'unsubscribe-std.phtml')); } $this->view->display('unsubscribe.phtml'); } }PK\&AA-default/controllers/AdminUploadController.phpnu[getRequest()->getParam('prefix'); $secure = $this->getRequest()->getParam('secure'); if (!$prefix) { throw new Am_Exception_InputError('prefix is undefined'); } if (!$this->getDi()->uploadAcl->checkPermission($prefix, Am_Upload_Acl::ACCESS_LIST, $this->getDi()->authAdmin->getUser())) { throw new Am_Exception_AccessDenied(); } if (in_array($prefix, array('downloads', 'video', 'personal-content', 'softsale'))) { list($storageId, $path, $query) = $this->getDi()->plugins_storage->splitPath($this->_request->get('path', 'upload::')); $storagePlugins = $this->getDi()->plugins_storage->loadEnabled()->getAllEnabled(); } else { list($storageId, $path, $query) = $this->getDi()->plugins_storage->splitPath($this->_request->get('path', 'upload::')); $storageId = 'upload'; $path = 'upload::'; $storagePlugins = array($this->getDi()->plugins_storage->loadGet($storageId)); } $storage = $this->getDi()->plugins_storage->loadGet($storageId); $storage->setPrefix($prefix); $grid = new Am_Storage_Grid($storage, $this->_request, $this->_response, $storagePlugins); $grid->setSecure($secure); if ($query) { $grid->action($query, $path, $this->view); } else { $grid->render($path, $this->view); } } public function getAction() { if (!$file = $this->getDi()->plugins_storage->getFile($this->getParam('id'))) { throw new Am_Exception_InputError("Can not fetch file for id: {$this->getParam('id')}"); } // @todo detect if file is upload and then check permissions // if (!$this->getDi()->uploadAcl->checkPermission($file, // Am_Upload_Acl::ACCESS_READ, // $this->getDi()->authAdmin->getUser())) { // throw new Am_Exception_AccessDenied(); // } if ($path = $file->getLocalPath()) { $this->_helper->sendFile($path, $file->getMime(), array('filename' => $file->getName())); } else { $this->_response->redirectLocation($file->getUrl(600)); } exit; } protected function getUploadIds(Am_Upload $upload) { $upload_ids = array(); foreach($upload->getUploads() as $upload) { $upload_ids[] = $upload->pk(); } return $upload_ids; } public function reUploadAction() { $file = $this->getDi()->uploadTable->load($this->getParam('id')); if (!$this->getDi()->uploadAcl->checkPermission($file, Am_Upload_Acl::ACCESS_WRITE, $this->getDi()->authAdmin->getUser())) { throw new Am_Exception_AccessDenied(); } $upload = new Am_Upload($this->getDi()); try { $upload->processReSubmit('upload', $file); if ($file->isValid()) { $data = array ( 'ok' => true, 'name' => $file->getName(), 'filename' => $file->getFilename(), 'size_readable' => $file->getSizeReadable(), 'upload_id' => $file->pk(), 'mime' => $file->mime ); } else { $data = array( 'ok' => false, 'error' => 'No files uploaded', ); } } catch (Am_Exception $e) { $data = array( 'ok' => false, 'error' => 'No files uploaded', ); $this->getDi()->errorLogTable->logException($e); } echo json_encode($data); } public function uploadAction() { if (!$this->getDi()->uploadAcl->checkPermission($this->getParam('prefix'), Am_Upload_Acl::ACCESS_WRITE, $this->getDi()->authAdmin->getUser())) { throw new Am_Exception_AccessDenied(); } $secure = $this->getParam('secure', false); $upload = new Am_Upload($this->getDi()); $upload->setPrefix($this->getParam('prefix')); $upload->loadFromStored(); $ids_before = $this->getUploadIds($upload); $upload->processSubmit('upload'); //find currently uploaded file $x = array_diff($this->getUploadIds($upload), $ids_before); $upload_id = array_pop($x); try { $upload = $this->getDi()->uploadTable->load($upload_id); $data = array ( 'ok' => true, 'name' => $upload->getName(), 'size_readable' => $upload->getSizeReadable(), 'upload_id' => $secure ? Am_Form_Element_Upload::signValue($upload->pk()) : $upload->pk(), 'mime' => $upload->mime ); } catch (Am_Exception $e) { $data = array( 'ok' => false, 'error' => 'No files uploaded', ); $this->getDi()->errorLogTable->logException($e); } echo json_encode($data); } public function getSizeAction() { $file = $this->getDi()->uploadTable->load($this->getParam('id')); if (!$file) { throw new Am_Exception_InputError( 'Can not fetch file for id : ' . $this->getParam('id') ); } if (!$this->getDi()->uploadAcl->checkPermission($file, Am_Upload_Acl::ACCESS_READ, $this->getDi()->authAdmin->getUser())) { throw new Am_Exception_AccessDenied(); } if ($size = getimagesize($file->getFullPath()) ) { echo json_encode( array ( 'width' => $size[0], 'height' => $size[1] ) ); } else { echo json_encode(false); } } }PK\wlala0default/controllers/AdminImportDapController.phpnu[db_dap = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $payments) { $this->user = $user; foreach ($payments as $p) { $this->payments[$p['id']] = $p; } $this->groupByInvoice(); $this->beforeWork(); return $this->doWork(); } function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$p['product_id']][] = $p; } } function beforeWork() { } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='dap:id'"); } return @$cache[$pid]; } } class InvoiceCreator_Paypal extends InvoiceCreator_Abstract { function doWork() { $access = $this->db_dap->select("SELECT product_id AS ARRAY_KEY, u.* FROM ?_users_products_jn u WHERE user_id=?", $this->user->data()->get('dap:id')); foreach ($this->groups as $pid => $list) { $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $newP = $this->_translateProduct($pid); $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($newP)); $item->qty = 1; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $invoice->paysys_id = 'paypal'; $invoice->tm_added = $list[0]['time']; $invoice->tm_started = $list[0]['time']; $invoice->public_id = $list[0]['trans_num']; $invoice->currency = $list[0]['payment_currency']; $invoice->calculate(); $invoice->status = Invoice::PAID; parse_str($list[0]['trans_blob'], $trans_params); if (isset($trans_params['subscr_id'])) { $invoice->data()->set('external_id', $trans_params['subscr_id']); } foreach ($list as $p) $pidlist[] = $p['id']; $invoice->data()->set('dap:id', implode(',', $pidlist)); $invoice->insert(); // insert payments foreach ($list as $p) { $newP = $this->_translateProduct($p['product_id']); $tm = new DateTime($p['time']); $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = $p['payment_value']; $payment->paysys_id = 'paypal'; $payment->dattm = $tm->format('Y-m-d H:i:s'); $payment->receipt_id = $p['trans_num']; $payment->transaction_id = 'import-paypal-' . mt_rand(10000, 99999); $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='dap:id',`value`=?", $payment->pk(), $p['id']); } if (isset($access[$pid])) { $this->insertAccess($access[$pid], $invoice->pk(), $payment->pk()); unset($access[$pid]); } } //add other access as manually added if ($access) { foreach ($access as $a) { $this->insertAccess($a); } } $this->user->checkSubscriptions(); } protected function insertAccess($access, $invoice_id = null, $payment_id = null) { $newP = $this->_translateProduct($access['product_id']); $a = $this->getDi()->accessRecord; $a->user_id = $this->user->user_id; $a->setDisableHooks(); $a->begin_date = $access['access_start_date']; $a->expire_date = $access['access_end_date']; if (!is_null($invoice_id)) { $a->invoice_id = $invoice_id; } if (!is_null($payment_id)) { $a->invoice_payment_id = $payment_id; } $a->product_id = $newP; $a->insert(); } public function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$p['product_id']][] = $p; } } } class InvoiceCreator_Clickbank extends InvoiceCreator_Abstract { function doWork() { $access = $this->db_dap->select("SELECT transaction_id AS ARRAY_KEY, u.* FROM ?_users_products_jn u WHERE user_id=?", $this->user->data()->get('dap:id')); foreach ($this->groups as $trans => $list) { $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); $set = array(); foreach ($list as $k) { $pid = $k['product_id']; if (isset($set[$pid])) continue; $newP = $this->_translateProduct($pid); $item = $invoice->createItem(Am_Di::getInstance()->productTable->load($newP)); $item->qty = 1; $item->first_discount = 0; $item->first_shipping = 0; $item->first_tax = 0; $item->second_discount = 0; $item->second_shipping = 0; $item->second_tax = 0; $item->_calculateTotal(); $invoice->addItem($item); $set[$pid] = 1; } $invoice->paysys_id = 'clickbank'; $invoice->tm_added = $list[0]['time']; $invoice->tm_started = $list[0]['time']; $invoice->public_id = $list[0]['trans_num']; $invoice->currency = $list[0]['payment_currency']; $invoice->calculate(); $invoice->status = Invoice::PAID; $invoice->data()->set('external_id', $trans); foreach ($list as $p) $pidlist[] = $p['id']; $invoice->data()->set('dap:id', implode(',', $pidlist)); $invoice->insert(); // insert payments foreach ($list as $p) { $newP = $this->_translateProduct($p['product_id']); $tm = new DateTime($p['time']); $payment = $this->getDi()->invoicePaymentRecord; $payment->user_id = $this->user->user_id; $payment->invoice_id = $invoice->pk(); $payment->currency = $invoice->currency; $payment->amount = $p['payment_value']; $payment->paysys_id = 'clickbank'; $payment->dattm = $tm->format('Y-m-d H:i:s'); $payment->receipt_id = $p['trans_num']; $payment->transaction_id = 'import-clickbank-' . mt_rand(10000, 99999); $payment->insert(); $this->getDi()->db->query("INSERT INTO ?_data SET `table`='invoice_payment',`id`=?d,`key`='dap:id',`value`=?", $payment->pk(), $p['id']); if (isset($access[$p['id']])) { $this->insertAccess($access[$p['id']], $invoice->pk(), $payment->pk()); unset($access[$p['id']]); } } } //add other access as manually added if ($access) { foreach ($access as $a) { $this->insertAccess($a); } } $this->user->checkSubscriptions(); } protected function insertAccess($access, $invoice_id = null, $payment_id = null) { $newP = $this->_translateProduct($access['product_id']); $a = $this->getDi()->accessRecord; $a->user_id = $this->user->user_id; $a->setDisableHooks(); $a->begin_date = $access['access_start_date']; $a->expire_date = ($access['access_end_date'] == '9999-12-31' ? '2037-12-31' : $access['access_end_date']); if (!is_null($invoice_id)) { $a->invoice_id = $invoice_id; } if (!is_null($payment_id)) { $a->invoice_payment_id = $payment_id; } $a->product_id = $newP; $a->insert(); } public function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$this->getInvoiceExternalId($p['trans_num'])][] = $p; } } function getInvoiceExternalId($transaction) { if (strpos($transaction, '-') !== false) { list($trans, ) = explode('-', $transaction); } else if (strpos($transaction, ':') !== false) { list(,, $trans) = explode(':', $transaction); } else { $trans = $transaction; } return $trans; } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_dap; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_dap, array $options = array()) { $this->db_dap = $db_dap; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='dap:id'"); $q = $this->db_dap->queryResultOnly("SELECT * FROM ?_products"); while ($r = $this->db_dap->fetchRow($q)) { if (in_array($r['id'], $importedProducts)) continue; $context++; $p = $this->getDi()->productRecord; $p->title = $r['name']; $p->description = $r['description']; $p->data()->set('dap:id', $r['id']); $p->insert(); $bp = $p->createBillingPlan(); $bp->title = 'default'; if ($r['is_recurring'] == 'Y') { $bp->first_price = $r['trial_price'] > 0 ? $r['trial_price'] : $r['price']; $bp->first_period = $r['recurring_cycle_1'] . 'd'; $bp->second_price = $r['price']; $bp->second_period = ($r['recurring_cycle_2'] ? $r['recurring_cycle_2'] : $r['recurring_cycle_1']) . 'd'; $bp->rebill_times = $r['total_occur'] ? $r['total_occur'] : IProduct::RECURRING_REBILLS; } else { // not recurring $bp->first_price = $r['price']; $bp->first_period = Am_Period::MAX_SQL_DATE; $bp->rebill_times = 0; } $bp->insert(); } return true; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { //$crypt = $this->getDi()->crypt; $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='dap:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_dap->queryResultOnly("SELECT * FROM ?_users WHERE id > ?d AND account_type = 'U' ORDER BY id {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_dap->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->name_f = (string) $r['first_name']; $u->name_l = (string) $r['last_name']; $u->email = $r['email']; $u->street = trim(sprintf('%s %s', $r['address1'], $r['address2'])); $u->city = $r['city']; $u->state = $r['state']; //@todo translate satate $u->country = $r['country']; //@todo translate country $u->phone = $r['phone']; $u->zip = $r['zip']; $u->added = $r['signup_date']; $u->is_affiliate = $r['is_affiliate'] == 'Y' ? 1 : 0; $u->remote_addr = $r['ipaddress']; if ($r['user_name']) { $u->login = $r['user_name']; } else { $u->generateLogin(); } $u->setPass($r['password'], true); // do not salt passwords heavily to speed-up $u->data()->set('paypal_email', $r['paypal_email']); $u->data()->set('external_id', ($this->findPayerId($r['id'])? : $r['email'])); $u->data()->set('dap:id', $r['id']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time try { $u->insert(); $this->insertPayments($r['id'], $u); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } function findPayerId($id) { $payerId = null; $payment = $this->db_dap->selectRow("SELECT t.*, u.id AS user_id FROM ?_transactions t LEFT JOIN ?_users u ON IF(u.paypal_email IS NULL OR u.paypal_email = '', u.email = t.payer_email, u.paypal_email = t.payer_email) WHERE u.id=$id AND t.status IN (1, 5) AND t.trans_type = 'subscr_payment' AND payment_status = 'Completed'"); if ($payment) { parse_str($payment['trans_blob'], $trans_params); $payerId = isset($trans_params['payer_id']) ? $trans_params['payer_id'] : $payerId; } return $payerId; } function insertPayments($id, User $u) { $payments = $this->db_dap->select("SELECT t.*, u.id AS user_id FROM ?_transactions t LEFT JOIN ?_users u ON IF(u.paypal_email IS NULL OR u.paypal_email = '', u.email = t.payer_email, u.paypal_email = t.payer_email) WHERE u.id=$id AND t.status IN (1,5) AND t.trans_type = 'subscr_payment' AND t.payment_status = 'Completed' AND t.payment_processor = 'PAYPAL' ORDER BY t.id"); $payments = $payments ? $payments : array(); //to add access if exists $byPs = array( 'paypal' => array() ); foreach ($payments as $p) { $byPs['paypal'][] = $p; } // Select clickbank payments; $payments = $this->db_dap->select("" . "SELECT * FROM ?_transactions " . "WHERE (user_id=? OR payer_email=?) " . "AND status IN (1,5) " . "AND trans_type='ctransaction' " . "AND payment_status='Completed' " . "AND payment_processor = 'CLICKBANK'" . "", $id, $u->data()->get('paypal_email') ? $u->data()->get('paypal_email') : $u->email); foreach ($payments as $p) { $byPs['clickbank'][] = $p; } foreach ($byPs as $paysys_id => $list) { if ($list) InvoiceCreator_Abstract::factory($paysys_id, $this->db_dap)->process($u, $list); } } } class AdminImportDapController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_dap; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->dap_db = null; $this->getSession()->dap_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->dap_import = null; } if (!$this->getSession()->dap_db) return $this->askDbSettings(); $this->db_dap = Am_Db::connect($this->getSession()->dap_db); if (!$this->getSession()->dap_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->dap_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_dap, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from DAP"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->dap_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-dap",array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->dap_import = array( 'import' => $val['import'], 'user' => @$val['user'], ); $this->_redirect('admin-import-dap'); return; } } $this->view->title = "Import DAP Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='dap:id'"); $total = $this->db_dap->selectCell("SELECT COUNT(*) FROM ?_products"); if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); if ($imported_products) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='dap:id'"); $total = $this->db_dap->selectCell("SELECT COUNT(*) FROM ?_users WHERE account_type='U'"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->dap_db = $this->form->getValue(); $this->_redirect('admin-import-dap'); } else { $this->view->title = "Import DAP Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('DAP MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('DAP MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('DAP MySQL Password'); $form->addText('db')->setLabel('DAP MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('DAP Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => 'dap_', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_users LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } } PK\)+default/controllers/AdminInfoController.phpnu[hasPermission(Am_Auth_Admin::PERM_SYSTEM_INFO); } function indexAction() { check_demo(); $this->view->title = ___('Version Info'); $trial = ""; if ('==TRIAL==' != '=='.'TRIAL==') { $trial = "Trial Version (expires ==TRIAL_EXPIRES==)"; } if ('==LITE==' != '==' . 'LITE==') { $trial = "LITE Version"; } $am_version = AM_VERSION; $zend_version = Zend_Version::VERSION; $cron_last_run = Am_Cron::getLastRun() ? amDatetime(Am_Cron::getLastRun()) : ___('Never'); $cron_last_run_title = ___('Cron Last Run'); $now = amDatetime('now'); $now_title = ___('Current Server Date and Time'); $timezone = date_default_timezone_get(); $timezone_title = ___('Server Timezone'); $phpversion = phpversion() . " (".php_sapi_name().")"; $os=substr(php_uname(),0,28); if (strlen($os)==28) $os="$os..."; $mysql = $this->getDi()->db->selectCell("SELECT VERSION()"); $db = $this->getDi()->getParameter('db'); $dsn = sprintf("mysql://%s@%s:%d/%s.%s", $db['mysql']['user'], $db['mysql']['host'], @$db['mysql']['port'] ? $db['mysql']['port'] : 3306, $db['mysql']['db'], $db['mysql']['prefix']); $root = $this->getDi()->root_dir; $root_title = ___('Root Folder'); $modules = array(); foreach ($this->getDi()->modules->getEnabled() as $m) { $fn = AM_APPLICATION_PATH . '/' . $m . '/module.xml'; if (!file_exists($fn)) continue; $xml = simplexml_load_file($fn); if (!$xml) continue; $version = "(" . $xml->version . ")"; $modules[] = "$m $version"; } $modules = join("
      ", $modules); $modules_title = ___('Modules'); $plugins = ""; foreach (array_merge( $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(), $this->getDi()->plugins_protect->loadEnabled()->getAllEnabled()) as $p) { $rClass = new ReflectionClass(get_class($p)); $plugins .= sprintf("%s (%s - %s)
      \n", $p->getId(), preg_replace('/\$'.'Revision: (\d+).*/', '$1', $rClass->getConstant('PLUGIN_REVISION')), preg_replace('/\$'.'Date: (.+?)\s+.+/', '$1', $rClass->getConstant('PLUGIN_DATE'))); } $plugins_title = ___('Plugins'); $_ = explode('_', get_class($this->getDi()->cacheBackend)); $cacheBackend = array_pop($_); $cacheBackend_title = ___('Cache Backend'); $version_title = ___('Software version info'); $amInfo = <<
      $now_title $now
      $timezone_title $timezone
      aMember $am_version $trial
      Zend Framework $zend_version
      PHP $phpversion
      OS $os
      MySQL $mysql
      $dsn
      $cacheBackend_title $cacheBackend
      $root_title $root
      $cron_last_run_title $cron_last_run
      $modules_title $modules
      $plugins_title $plugins
      CUT; ob_start(); phpinfo(1|4|8|16|32); $phpInfo = ob_get_clean(); $phpStyles = <<(.*)<\/body>/s', $phpInfo, $matches); $phpInfo = $matches[1]; $content = sprintf('%s

      PHP Info


      %s
      ', $phpStyles, $amInfo, $phpInfo); $this->view->assign('content', $content); $this->view->display("admin/layout.phtml"); } }PK\&Rzz.default/controllers/AdminRestoreController.phpnu[getDi()->modules->getEnabled())) throw new Am_Exception_AccessDenied(___('Online backup is disabled if you have CC payment plugins enabled. Use offline backup instead')); } public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_BACKUP_RESTORE); } function indexAction() { $url = $this->escape($this->getUrl(null, 'restore')); ob_start(); echo '

      ' . ___('To restore the aMember database please pick a previously saved aMember Pro backup.') . '

      ' . ___('WARNING! ALL YOUR CURRENT AMEMBER TABLES AND RECORDS WILL BE REPLACED WITH THE CONTENTS OF THE BACKUP!') . '

      '; $this->view->title = ___('Restore Database from Backup'); $this->view->content = ob_get_clean(); $this->view->display('admin/layout.phtml'); } function restoreAction() { check_demo(); if (!$this->_request->isPost()) throw new Am_Exception_InputError('Only POST requests allowed here'); $db = $this->getDi()->db; $f = fopen($_FILES['file']['tmp_name'], 'r'); if (!$f) throw new Am_Exception_InputError('Can not open uploaded file'); $first_line = trim(fgets($f)); $second_line = trim(fgets($f)); if (!$first_line || !$second_line) throw new Am_Exception_InputError('Uploaded file has wrong format or empty'); $this->view->assign('backup_header', "$first_line
      $second_line"); if (!preg_match('/^### aMember Pro .+? database backup/', $first_line)) throw new Am_Exception_InputError(___('Uploaded file is not valid aMember Pro backup')); $query = null; while ($query || !feof($f)) { if ($query && (substr($query, -1) == ';')) { $db->query($query); $query = null; } if ($line = fgets($f)) $query .= "\r\n" . trim($line); } fclose($f); $this->getDi()->adminLogTable->log("Restored from $first_line"); $this->displayRestoreOk(); } function displayRestoreOk() { ob_start(); $this->view->title = ___('Restored Successfully'); echo '
      ' . ___('aMember database has been successfully restored from backup.') . '

      ' . ___('Backup file header') . "

      {$this->view->backup_header}
      
      "; $this->view->content = ob_get_clean(); $this->view->display('admin/layout.phtml'); } }PK\Q}}/default/controllers/AdminCategoryController.phpnu[view->isAjax = $this->isAjax(); if (!$this->isAjax()) { $this->view->title = $this->getTitle(); } $this->view->note = $this->getNote(); $this->view->nodes = $this->getTable()->getTree(); $this->view->tmpl = $this->getTable()->createRecord(); $this->view->display('admin/category.phtml'); } function saveAction() { $id = $this->getInt('id'); if ($id) { $c = $this->getTable()->load($id); } else { $c = $this->getTable()->createRecord(); } $c->title = $this->getParam('title'); $c->description = $this->getParam('description'); if (!is_null($code = $this->getParam('code'))) $c->code = $code; $c->parent_id = $this->getInt('parent_id'); $c->sort_order = $this->getInt('sort_order'); $c->save(); return $this->ajaxResponse($c->toArray() + array('id' => $c->pk())); } function delAction() { $id = $this->getInt('id'); if (!$id) throw new Am_Exception_InputError(___('Wrong id')); $c = $this->getTable()->load($id); $this->getTable()->moveNodes($c->pk(), $c->parent_id); $c->delete(); echo 'OK'; } function optionsAction() { return Am_Controller::ajaxResponse($this->getTable()->getOptions()); } protected function getNote() { return ''; } }PK\gee.default/controllers/AdminCouponsController.phpnu[record = $record; parent::__construct($id); } function init() { $this->setAttribute('enctype', 'multipart/form-data'); $this->addDataSource(new HTML_QuickForm2_DataSource_Array(array( '_count' => 1, 'use_count' => 10, 'discount' => 10, 'discount_type' => '%', 'user_use_count' => 1, '_code_len' => 8, '_source' => 3, '_code' => strtoupper(Am_Di::getInstance()->security->randomString(8)) ))); $this->addInteger('use_count') ->setLabel(___("Coupons Usage Count\n". 'how many times single coupon can be used')); $discountGroup = $this->addGroup() ->setLabel(___('Discount')); $discountGroup->setSeparator(' '); $discountGroup->addText('discount', array('size' => 5)); $discountGroup->addSelect('discount_type') ->loadOptions(array( Coupon::DISCOUNT_PERCENT => '%', Coupon::DISCOUNT_NUMBER => Am_Currency::getDefault() )); $this->addTextarea('comment', array('class' => 'el-wide')) ->setLabel(___("Comment\nfor admin reference")); if (!$this->record->isLoaded()) { $source = $this->addFieldset('source') ->setLabel(___('Coupon Codes')); $source->addAdvRadio('_source') ->setId('coupon-source') ->loadOptions(array( AdminCouponsController::SOURCE_INPUT => ___('Single Coupon Code'), AdminCouponsController::SOURCE_GENERATE => ___('Generate Batch of Random Coupon Codes (You will be able to alter codes later if you want)'), AdminCouponsController::SOURCE_FILE => ___('Import Pre-Defined List of Coupon Codes from CSV File (One coupon code per line)') )); $source->addText('_code', array('rel' => 'source-input')) ->setLabel(___('Coupon Code')); $source->addInteger('_count', array('rel' => 'source-generate')) ->setLabel(___("Coupons Count\nhow many coupons need to be generated")) ->addRule('gt', ___('Should be greater than 0'), 0); $source->addInteger('_code_len', array('rel' => 'source-generate')) ->setLabel(___("Code Length\ngenerated coupon code length\nbetween 4 and 32")) ->addRule('gt', ___('Should be greater than %d', 3), 3) ->addRule('lt', ___('Should be less then %d', 33), 33); $source->addFile('file[]', array('class' => 'styled', 'rel' => 'source-file')) ->setLabel(___('File')); $s_generate = AdminCouponsController::SOURCE_GENERATE; $s_file = AdminCouponsController::SOURCE_FILE; $s_input = AdminCouponsController::SOURCE_INPUT; $this->addScript() ->setScript(<<addAdvFieldset(null, array('id'=>'coupon-batch')) ->setLabel(___('Advanced Settings')); $fs->addInteger('user_use_count') ->setLabel(___("User Coupon Usage Count\nhow many times a coupon code can be used by customer")); $dateGroup = $fs->addGroup() ->setLabel(___("Dates\ndate range when coupon can be used")); $dateGroup->setSeparator(' '); $dateGroup->addCheckbox('_date-enable', array('class'=>'enable_date')); $dateGroup->addDate('begin_date', array('placeholder' => ___('Begin Date'))); $dateGroup->addHtml() ->setHtml('—'); $dateGroup->addDate('expire_date', array('placeholder' => ___('End Date'))); $fs->addAdvCheckbox('is_recurring') ->setLabel(___("Apply to recurring?\n". "apply coupon discount to recurring rebills?")); $fs->addAdvCheckbox('is_disabled') ->setLabel(___("Is Disabled?\n". "If you disable this coupons batch, it will ". "not be available for new purchases. ". "Existing invoices are not affected." )); $product_categories = array(); foreach (Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions() as $id => $title) { $product_categories['CATEGORY-'. $id] = $title; } $fs->addMagicSelect('product_ids', array('class' => 'am-combobox-fixed')) ->loadOptions(array( ___('Products') => Am_Di::getInstance()->productTable->getOptions(), ___('Product Categories') => $product_categories)) ->setLabel(___("Products\n". "coupons can be used with selected products only. " . "if nothing selected, coupon can be used with any product")); $jsCode = <<addScript('script')->setScript($jsCode); $require_options = $prevent_options = array(); foreach (Am_Di::getInstance()->productTable->getOptions() as $id => $title) { $title = Am_Html::escape($title); $require_options['ACTIVE-'. $id] = ___('ACTIVE %s', $title); $require_options['EXPIRED-'.$id] = ___('EXPIRED %s', $title); $prevent_options['ACTIVE-'. $id] = ___('ACTIVE %s', $title); $prevent_options['EXPIRED-'.$id] = ___('EXPIRED %s', $title); } $require_group_options = $prevent_group_options = array(); foreach (Am_Di::getInstance()->productCategoryTable->getAdminSelectOptions() as $id => $title) { $title = Am_Html::escape($title); $require_group_options['CATEGORY-ACTIVE-'. $id] = ___('ACTIVE category %s', '"'.$title.'"'); $require_group_options['CATEGORY-EXPIRED-'.$id] = ___('EXPIRED category %s', '"'.$title.'"'); $prevent_group_options['CATEGORY-ACTIVE-'. $id] = ___('ACTIVE category %s', '"'.$title.'"'); $prevent_group_options['CATEGORY-EXPIRED-'.$id] = ___('EXPIRED category %s', '"'.$title.'"'); } if (count($require_group_options)) { $rOptions = array( ___('Products') => $require_options, ___('Product Categories') => $require_group_options ); $pOptions = array( ___('Products') => $prevent_options, ___('Product Categories') => $prevent_group_options ); } else { $rOptions = $require_options; $pOptions = $prevent_options; } $fs->addMagicSelect('require_product', array('class' => 'am-combobox-fixed')) ->setLabel(___("To use coupon from this batch user must have an\n". "when user uses coupon, it will be checked " . "that user has one from the following subscriptions")) ->loadOptions($rOptions); $fs->addMagicSelect('prevent_if_product', array('class' => 'am-combobox-fixed')) ->setLabel(___("Disallow use of coupon from this batch if user has\n". "when user uses coupon, it will be checked " . "that he has no any from the following subscriptions")) ->loadOptions($pOptions); } } class Am_Grid_Filter_Coupon extends Am_Grid_Filter_Abstract { public function getTitle() { return ' '; } protected function applyFilter() { if ($this->isFiltered()) { $q = $this->grid->getDataSource(); /* @var $q Am_Query */ $q->leftJoin('?_coupon', 'cc') ->addWhere('cc.code=?', $this->vars['filter']); } } public function renderInputs() { return $this->renderInputText(array( 'placeholder' => ___('Coupon Code') )); } } class AdminCouponsController extends Am_Mvc_Controller_Grid { const SOURCE_GENERATE = 1; const SOURCE_FILE = 2; const SOURCE_INPUT = 3; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission('grid_coupon'); } public function createGrid() { $ds = new Am_Query($this->getDi()->couponBatchTable); $ds->addField('COUNT(c.coupon_id) AS coupons_count'); $ds->addField('SUM(c.used_count) AS used_count'); $ds->addField('c.code AS code'); $ds->leftJoin('?_coupon', 'c', 't.batch_id = c.batch_id'); $ds->setOrder('batch_id', 'desc'); $grid = new Am_Grid_Editable('_coupon', ___('Coupons Batches'), $ds, $this->_request, $this->view); $grid->setRecordTitle(array($this, 'getRecordTitle')); $grid->setEventId('gridCouponBatch'); $grid->addField('batch_id', '#', true, '', null, '1%'); $grid->addField(new Am_Grid_Field_Date('begin_date', ___('Begin Date')))->setFormatDate(); $grid->addField(new Am_Grid_Field_Date('expire_date', ___('Expire Date')))->setFormatDate(); $grid->addField(new Am_Grid_Field_IsDisabled()); $grid->addField('is_recurring', ___('Recurring'), true, 'center', null, '1%'); $grid->addField('discount', ___('Discount'), true, '', array($this, 'renderDiscount'), '5%'); $grid->addField('product_ids', ___('Products'), false, '', array($this, 'renderProducts'), '25%'); $grid->addField('comment', ___('Comment'), true, '', null, '15%'); $grid->addField('used_count', ___('Used'), true, 'center', array($this, 'renderUsedCount'), '5%'); $grid->addField('coupons_count', ___('Coupons'), true, 'center', null, '5%') ->setRenderFunction(array($this, 'renderCoupons')); $grid->setForm(array($this, 'createForm')); $grid->actionGet('edit')->setTarget('_top'); $grid->actionAdd(new Am_Grid_Action_Url('view', ___('View Coupons'), 'javascript:amOpenCoupons(__ID__)')) ->setAttribute("class", "coupons-link"); $url = $this->getDi()->url('admin-coupons/export/id/__ID__',null,false); $grid->actionAdd(new Am_Grid_Action_Url('export', ___('Export'), $url))->setTarget('_top'); $grid->actionAdd(new Am_Grid_Action_LiveEdit('comment')); $grid->actionAdd(new Am_Grid_Action_LiveCheckbox('is_recurring')); $grid->setFormValueCallback('product_ids', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->setFormValueCallback('require_product', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->setFormValueCallback('prevent_if_product', array('RECORD', 'unserializeList'), array('RECORD', 'serializeList')); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_SAVE, array($this, 'beforeSave')); $grid->addCallback(Am_Grid_Editable::CB_AFTER_INSERT, array($this, 'afterInsert')); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, function(& $out, $grid) { $out .= << jQuery(function(){ jQuery("input[name=_coupon_filter]").autocomplete({ minLength: 2, source: amUrl("/admin-coupons/autocomplete") }); }); CUT; }); $grid->setFilter(new Am_Grid_Filter_Coupon); return $grid; } public function getRecordTitle(CouponBatch $batch = null) { return $batch ? sprintf('%s (#%d - %s)', ___('Coupon Batch'), $batch->pk(), ($batch->comment ? $batch->comment : $batch->discount . ($batch->discount_type == 'percent' ? '%' : '$') . ($batch->begin_date ? ', ' . amDate($batch->begin_date) . '-' . amDate($batch->expire_date) : ''))) : ___('Coupon Batch'); } public function init() { parent::init(); $this->view->placeholder('after-content')->append(''); $couponsTitle = ___('Coupons'); $this->view->headScript()->appendScript(<<%s', $record->pk(), $record->pk(), ($record->coupons_count == 1 ? $record->code : $record->coupons_count)); return sprintf('%s', $content); } function renderDiscount($record) { return sprintf("%s", $record->discount_type == Coupon::DISCOUNT_PERCENT ? $record->discount . ' %' : Am_Currency::render($record->discount)); } function renderUsedCount($record) { return sprintf("%d/%d", $record->used_count, $record->use_count * $record->coupons_count ); } function renderProducts($record) { /* @var $record CouponBatch */ $product_ids = $record->getOnlyApplicableProductIds(); $category_ids = $record->getOnlyApplicableCategoryIds(); $res = array(); if ($product_ids) { $titles = $this->getDi()->productTable->getProductTitles($product_ids); $titles = implode(', ', $titles); $res[] = sprintf("%s: %s", ___('Products'), $titles); } if ($category_ids) { $options = $this->getDi()->productCategoryTable->getAdminSelectOptions(); $titles = array(); foreach ($category_ids as $id) { $titles[] = $options[$id]; } $titles = implode(', ', $titles); $res[] = sprintf("%s: %s", ___('Product Categories'), $titles); } if (!$product_ids && !$category_ids) { $res[] = sprintf('%s', ___('All')); } return sprintf('%s', implode('; ', $res)); } function createForm() { return new Am_Form_Admin_CouponBatch(get_class($this), $this->grid->getRecord()); } function beforeSave(& $values) { if (!isset($values['_date-enable'])) { $values['begin_date'] = $values['expire_date'] = null; } } public function afterInsert(array & $values, CouponBatch $record) { switch ($values['_source']) { case self::SOURCE_INPUT: $c = $this->getDi()->couponRecord; $c->code = $values['_code']; $c->batch_id = $record->pk(); $c->save(); break; case self::SOURCE_GENERATE : $record->generateCoupons((int)$values['_count'], (int)$values['_code_len'], (int)$values['_code_len']); break; case self::SOURCE_FILE : $upload = new Am_Upload($this->getDi()); $upload->setTemp(3600); if (!$upload->processSubmit('file')) { throw new Am_Exception_InputError('File was not uploaded'); } /* @var $file Upload */ list($file) = $upload->getUploads(); $f = fopen($file->getFullPath(), 'r'); while ($row = fgetcsv($f)) { $coupon = $this->getDi()->couponRecord; $coupon->code = $row[0]; $coupon->batch_id = $record->pk(); try { $coupon->insert(); } catch (Exception $e) {} } fclose($f); break; default : throw new Am_Exception_InternalError(sprintf('Unknown Coupon Code Source [%s]', $values['_source'])); } } public function autocompleteAction() { $term = '%' . $this->getParam('term') . '%'; $q = new Am_Query($this->getDi()->couponTable); $q->addWhere('code LIKE ?', $term); $qq = $q->query(0, 10); $ret = array(); $options = $this->getDi()->couponBatchTable->getOptions(); while ($r = $this->getDi()->db->fetchRow($qq)) { $ret[] = array( 'label' => $r['code'] . ' - ' . $options[$r['batch_id']], 'value' => $r['code'] ); } if ($q->getFoundRows() > 10) { $ret[] = array( 'label' => ___("... %d more rows found ...", $q->getFoundRows() - 10), 'value' => null, ); } $this->_response->ajaxResponse($ret); } public function detailAction() { $id = (int)$this->getParam('id'); if (!$id) throw new Am_Exception_InputError('Empty id passed to ' . __METHOD__); $ds = new Am_Query($this->getDi()->couponTable); $ds->leftJoin('?_user', 'u', 't.user_id=u.user_id'); $ds->addField('u.login', 'u_login'); $ds->addWhere('batch_id=?d', $id); $grid = new Am_Grid_Editable('_detail', ___('Coupons'), $ds, $this->_request, $this->view); $grid->setRecordTitle(___('Coupon')); $grid->setPermissionId('grid_coupon'); $grid->setEventId('gridCoupon'); $grid->actionsClear(); $grid->actionAdd(new Am_Grid_Action_Insert)->setTarget(null); $grid->addField('code', ___('Code'), true, null); $grid->addField(new Am_Grid_Field_Expandable('used_count', ___('Used For'), false)) ->setGetFunction(array($this, 'getUsedCount')) ->setPlaceholder(array($this, 'getPlaceholder')) ->setSafeHtml(true); $grid->addField('user_id', ___('User')) ->setGetFunction(array($this, 'getUser')); $grid->setFilter(new Am_Grid_Filter_Text(" ", array('code' => 'LIKE'), array('placeholder' => ___('Coupon Code')))); $grid->actionAdd(new Am_Grid_Action_LiveEdit('code')); $grid->actionAdd(new Am_Grid_Action_LiveEdit('user_id', ___('Click to Assign'))) ->setInitCallback('l = function(){this.autocomplete({ minLength: 2, source: amUrl("/admin-users/autocomplete") });}') ->getDecorator()->setInputTemplate(sprintf('', ___('Type Username or E-Mail'))); $grid->isAjax(false); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, array($this, 'couponRenderContent')); $grid->addCallback(Am_Grid_Editable::CB_BEFORE_INSERT, function(& $vars, $r, $g) { $r->batch_id = $g->getCompleteRequest()->getParam('id'); }); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_TABLE, function(& $out, $grid) { $batch = $grid->getDi()->couponBatchTable->load($id = $grid->getCompleteRequest()->getParam('id')); $_ = $grid->getDi()->db->selectRow("SELECT COUNT(coupon_id) AS cnt, SUM(used_count) AS used_cnt " . "FROM ?_coupon WHERE batch_id=?", $id); extract($_); $usage = json_encode(sprintf("%d/%d", $used_cnt, $batch->use_count * $cnt)); $out .= << jQuery(function(){ jQuery("#batch-$id-cnt").empty().append($cnt); jQuery("#batch-$id-usage").empty().append($usage); }); CUT; }); $grid->setForm(array($this, 'createCouponForm')); $response = $grid->run(); $response->sendHeaders(); $response->sendResponse(); } public function createCouponForm() { $di = $this->getDi(); $form = new Am_Form_Admin; $c = $form->addText('code') ->setLabel(___('Coupon Code')); $c->addRule('required'); $c->addRule('callback', ___('Coupon with such code is already exits'), function($c) use ($di) { return !$di->couponTable->findFirstByCode($c); }); return $form; } public function couponRenderContent(& $out) { $out = sprintf('
      %s
      ', ___('You can assign some coupon codes to specific user. Only this user will be able to use this coupon.')) . $out; } public function getUser($obj) { return $obj->user_id ? $obj->u_login : ''; } public function getUsedCount($obj) { $invoices = Am_Di::getInstance()->invoiceTable->findByCouponId($obj->coupon_id); if (!$invoices) return ''; $ret = array(); $out = ''; $wrap = '' . ___('Transactions with this coupon:') . '' . '
      ' . '' . '%s
      ' . ___('User') . '' . ___('Invoice') . '' . ___('Date/Time') . '' . ___('Receipt#') . '' . ___('Amount') . '' . ___('Discount') . '
      '; $tpl = '%s (%s)%d/%s%s%s%s%s'; foreach ($invoices as $invoice) { if ($invoice->getStatus() == Invoice::PENDING) continue; $payments = $this->getDi()->invoicePaymentTable->findBy(array( 'invoice_id' => $invoice->invoice_id, 'discount' => '<>0'), null, null, "invoice_payment_id"); foreach ($payments as $payment) { $user = Am_Di::getInstance()->userTable->load($payment->user_id); $ret[] = sprintf($tpl, $this->getDi()->view->userUrl($user->pk()), $this->getDi()->view->escape($user->login), $this->getDi()->view->escape($user->getName()), $this->getDi()->url("admin-user-payments/index/user_id/{$invoice->user_id}#invoice-{$invoice->pk()}",null,false), $invoice->pk(), $this->getDi()->view->escape($invoice->public_id), amDatetime($payment->dattm), $this->getDi()->view->escape($payment->receipt_id), $this->getDi()->view->escape(Am_Currency::render($payment->amount)), $this->getDi()->view->escape(Am_Currency::render($payment->discount)) ); } //100% discount if(!$payments) { try{ $user = Am_Di::getInstance()->userTable->load($invoice->user_id); $ret[] = sprintf($tpl, $this->getDi()->view->userUrl($user->pk()), $this->getDi()->view->escape($user->login), $this->getDi()->view->escape($user->getName()), $this->getDi()->url("admin-user-payments/index/user_id/{$invoice->user_id}#invoice-{$invoice->pk()}",null,false), $invoice->pk(), $invoice->public_id, amDatetime($invoice->tm_started), '–', $this->getDi()->view->escape(Am_Currency::render(0)), ___('100% discount')); } catch(Am_Exception_Db_NotFound $e) { $this->getDi()->errorLogTable->logException($e); } } } $out .= implode("\n", $ret); return $out ? sprintf($wrap, $out) : $out; } public function getPlaceholder($val, $obj) { return ___('Coupon used for %d transactions', $obj->used_count); } public function exportAction() { if (!($id = $this->getInt('id'))) throw new Am_Exception_InputError("Empty id passed to " . __METHOD__); $out = ''; foreach($this->getDi()->couponTable->findBy(array('batch_id' => $id)) as $c) $out .= $c->code."\r\n"; $dat = sqlDate('now'); $this->_helper->sendFile->sendData($out, 'text/csv', "amember_coupons-$id-$dat.csv"); } }PK\iY11'default/controllers/AdminController.phpnu[getDi()->store->get('db_version'); if (empty($db_version)) { $this->getDi()->store->set('db_version', AM_VERSION); } elseif ($db_version != AM_VERSION) { $this->_response->redirectLocation($this->getDi()->url('admin-upgrade-db',null,false)); } parent::preDispatch(); } function getDefaultWidgets() { return array( new Am_Widget('activity', ___('Recent Activity'), array($this, 'renderWidgetActivity'), Am_Widget::TARGET_ANY, array($this, 'createWidgetActivityConfigForm'), 'grid_payment'), new Am_Widget('users', ___('Last Users List'), array($this, 'renderWidgetUsers'), Am_Widget::TARGET_ANY, array($this, 'createWidgetUsersConfigForm'), 'grid_u'), new Am_Widget('user_logins', ___('Last User Logins List'), array($this, 'renderWidgetUserLogins'), Am_Widget::TARGET_ANY, array($this, 'createWidgetUserLoginsConfigForm'), 'grid_u'), new Am_Widget('payments', ___('Last Payments List'), array($this, 'renderWidgetPayments'), Am_Widget::TARGET_ANY, array($this, 'createWidgetPaymentsConfigForm'), 'grid_payment'), new Am_Widget('prefunds', ___('Last Refunds List'), array($this, 'renderWidgetRefunds'), Am_Widget::TARGET_ANY, array($this, 'createWidgetRefundsConfigForm'), 'grid_payment'), new Am_Widget('report-users', ___('Users Report'), array($this, 'renderWidgetReportUsers'), Am_Widget::TARGET_ANY, null, Am_Auth_Admin::PERM_REPORT), new Am_Widget('user-note', ___('Last User Notes'), array($this, 'renderWidgetUserNote'), Am_Widget::TARGET_ANY, array($this, 'createWidgetUserNoteConfigForm'), 'grid_un'), new Am_Widget('sales', ___('Sales Statistic'), array($this, 'renderWidgetSales'), Am_Widget::TARGET_ANY, array($this, 'createWidgetSalesConfigForm'), Am_Auth_Admin::PERM_REPORT), new Am_Widget('recurring-revenue', ___('Scheduled Recurring Revenue'), array($this, 'renderWidgetRecurringRevenue'), Am_Widget::TARGET_ANY, null, Am_Auth_Admin::PERM_REPORT), new Am_Widget('revenue-goal', ___('Revenue Goal'), array($this, 'renderWidgetRevenueGoal'), Am_Widget::TARGET_ANY, array($this, 'createWidgetRevenueGoalConfigForm'), Am_Auth_Admin::PERM_REPORT), new Am_Widget('invoices', ___('Last Invoices List'), array($this, 'renderWidgetInvoices'), Am_Widget::TARGET_ANY, array($this, 'createWidgetInvoicesConfigForm'), Am_Auth_Admin::PERM_REPORT), new Am_Widget('quick-start', ___('Quick Start'), array($this, 'renderWidgetQucikStart'), array(Am_Widget::TARGET_TOP)) ); } function getSavedReportWidgets() { $res = array (); foreach ($this->getDi()->savedReportTable->findByAdminId($this->getDi()->authAdmin->getUser()->pk()) as $report) { $res[] = new Am_Widget('saved-report-' . $report->pk(), $report->title, array($this, 'renderWidgetReport'), Am_Widget::TARGET_ANY, array($this, 'createWidgetReportConfigForm'), Am_Auth_Admin::PERM_REPORT, array('savedReport' => $report)); } return $res; } function getAvailableWidgets() { $event = new Am_Event(Am_Event::LOAD_ADMIN_DASHBOARD_WIDGETS); $this->getDi()->hook->call($event); $widgets = array(); foreach (array_merge($this->getDefaultWidgets(), $this->getSavedReportWidgets(), $event->getReturn()) as $widget) { $widgets[$widget->getId()] = $widget; } return $widgets; } /** * Retrieve widget by id * * @param string $id * @return Am_Widget */ function getWidget($id) { $availableWidgets = $this->getAvailableWidgets(); return isset($availableWidgets[$id]) ? $availableWidgets[$id] : null; } function customizeDashboardAction() { $widgets = $this->getAvailableWidgets(); foreach ($widgets as $k => $widget) { if (!$widget->hasPermission($this->getDi()->authAdmin->getUser())) { unset($widgets[$k]); } } $this->view->widgets = $widgets; $this->view->config = $this->getWidgetConfig(); $this->view->pref = $this->getPref(); $this->view->display('admin/customize.phtml'); } function getWidgetConfigFormAction() { $id = $this->getRequest()->getParam('id'); $widget = $this->getWidget($id); if (!$widget) throw new Am_Exception_InputError(___('Unknown Widget with Id [%s]', $id)); if (!$widget->hasConfigForm()) throw new Am_Exception_InputError(___('Widget with Id [%s] has not config form', $id)); $form = $widget->getConfigForm(); $config = $this->getWidgetConfig($widget->getId()); if ($config) { $form->setDataSources(array(new HTML_QuickForm2_DataSource_Array($config))); } echo $form; } protected function getPref() { $pref_default = array( 'top' => array('quick-start'), 'bottom' => array(), 'main' => array('users', 'payments'), 'aside' => array('sales', 'activity', 'report-users', 'user-note') ); $pref = $this->getDi()->authAdmin->getUser()->getPref(Admin::PREF_DASHBOARD_WIDGETS); return is_null($pref) ? $pref_default : $pref; } protected function getWidgetConfig($widget_id = null) { $config = $this->getDi()->authAdmin->getUser()->getPref(Admin::PREF_DASHBOARD_WIDGETS_CONFIG); if (is_null($widget_id)) return $config; return isset($config[$widget_id]) ? $config[$widget_id] : null; } function saveDashboardAction() { if ($this->getRequest()->isPost()) { $this->getDi()->authAdmin->getUser() ->setPref(Admin::PREF_DASHBOARD_WIDGETS, $this->getRequest()->getParam('pref', array())); } } function saveDashboardConfigAction() { if ($this->getRequest()->isPost()) { /* @var $widget Am_Widget */ $widget = $this->getWidget($this->getRequest()->getParam('id')); /* @var $form Am_Form */ $form = $widget->getConfigForm(); if (!$form) throw new Am_Exception_InputError(___('Can not save config for dashboard widget without config form [%s]', $this->getRequest()->getParam('id'))); $form->setDataSources(array($this->getRequest())); $config = $this->getDi()->authAdmin->getUser()->getPref(Admin::PREF_DASHBOARD_WIDGETS_CONFIG, array()); if ($form->validate()) { $vars = $form->getValue(); unset($vars['id']); $config[$widget->getId()] = $vars; $this->getDi()->authAdmin->getUser()->setPref(Admin::PREF_DASHBOARD_WIDGETS_CONFIG, $config); $html = $widget->render($this->view, $config[$widget->getId()]); $this->_response->ajaxResponse(array( 'status' => 'OK', 'html' => $html, 'id' => $widget->getId() )); } else { $this->_response->ajaxResponse(array( 'status' => 'ERROR', 'html' => (string)$form, 'id' => $widget->getId() )); } } } function renderWidgetQucikStart(Am_View $view, $config = null) { return $view->render('admin/widget/quick-start.phtml'); } function createWidgetUserNoteConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Notes to display')) ->setValue(5); return $form; } function renderWidgetUserNote(Am_View $view, $config = null) { $view->num = is_null($config) ? 5 : $config['num']; return $view->render('admin/widget/user-note.phtml'); } public function renderWidgetReport(Am_View $view, $config=null, $invokeArgs = array()) { class_exists('Am_Report_Standard', true); $view->enableReports(); /* @var $savedReport SavedReport */ $savedReport = $invokeArgs['savedReport']; $request = new Am_Mvc_Request(unserialize($savedReport->request)); $r = Am_Report_Abstract::createById($savedReport->report_id); $r->applyConfigForm($request); $result = $r->getReport(); $result->setTitle($savedReport->title); $type = is_null($config) ? 'graph-line' : $config['type']; $wrap = '

      %s

      %s
      '; switch ($type) { case 'graph-line' : $output = new Am_Report_Graph_Line($result); $output->setSize('100%', 250); break; case 'graph-bar' : $output = new Am_Report_Graph_Bar($result); $output->setSize('100%', 250); break; case 'table' : $output = new Am_Report_Table($result); $wrap = '

      %s

      %s
      '; break; default : throw new Am_Exception_InputError(___('Unknown report display type [%s]', $type)); } return sprintf($wrap, $savedReport->title, $savedReport->report_id, $output->render()); } public function createWidgetReportConfigForm() { $form = new Am_Form_Admin(); $form->addSelect('type') ->setLabel(___('Display Type')) ->setValue('graph-line') ->loadOptions(array( 'graph-line' => ___('Graph Line'), 'graph-bar' => ___('Graph Bar'), 'table' => ___('Table') )); return $form; } public function renderWidgetUsers(Am_View $view, $config=null) { $view->num = is_null($config) ? 5 : $config['num']; return $view->render('admin/widget/users.phtml'); } public function createWidgetUsersConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Users to display')) ->setValue(5); return $form; } public function renderWidgetUserLogins(Am_View $view, $config=null) { $view->num = is_null($config) ? 5 : $config['num']; return $view->render('admin/widget/user-logins.phtml'); } public function createWidgetUserLoginsConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Users to display')) ->setValue(5); return $form; } public function renderWidgetPayments(Am_View $view, $config=null) { $view->num = is_null($config) ? 5 : $config['num']; return $view->render('admin/widget/payments.phtml'); } public function renderWidgetActivity(Am_View $view, $config = null) { $interval = is_null($config) ? Am_Interval::PERIOD_THIS_WEEK_FROM_SUN : $config['interval']; $limit = min(50, is_null($config) ? 10 : $config['limit']); $events = is_null($config) ? array() : $config['events']; list($start, $stop) = $this->getDi()->interval->getStartStop($interval); $timeline = array(); $di = $this->getDi(); $events_def = array( 'payment' => array( 'date_field' => 'dattm', 'get_list' => function($limit, $start) use ($di) { return $di->invoicePaymentTable->selectLast($limit, $start); }), 'refund' => array( 'date_field' => 'dattm', 'get_list' => function($limit, $start) use ($di) { return $di->invoiceRefundTable->selectLast($limit, $start); }), 'signin' => array( 'date_field' => 'last_login', 'get_list' => function($limit, $start) use ($di) { return $di->userTable->findBy(array('last_login' => ">$start"), 0, $limit, 'last_login DESC'); }), 'signup' => array( 'date_field' => 'added', 'get_list' => function($limit, $start) use ($di) { return $di->userTable->selectLast($limit, $start); }), 'download' => array( 'date_field' => 'dattm', 'get_list' => function($limit, $start) use ($di) { return $di->fileDownloadTable->selectLast($limit, $start); }), 'user_note' => array( 'date_field' => 'dattm', 'get_list' => function($limit, $start) use ($di) { return $di->userNoteTable->selectLast($limit, $start); }), ); if (!$events) { $events = array_keys($events_def); } $data = array(); foreach ($events as $event_id) { if (isset($events_def[$event_id])) { $data[$event_id] = $events_def[$event_id]['get_list']($limit, $start); } } foreach ($data as $id => $rows) { foreach ($rows as $row) { $row->event_type = $id; $row->event_date_field = $events_def[$id]['date_field']; $timeline[sqlTime($row->{$events_def[$id]['date_field']}) . '-' . $row->pk()] = $row; } } krsort($timeline, SORT_STRING); $timeline = array_slice($timeline, 0, $limit); $view->assign('timeline', $timeline); return $view->render('admin/widget/activity.phtml'); } public function renderWidgetRefunds(Am_View $view, $config=null) { $view->num = is_null($config) ? 5 : $config['num']; return $view->render('admin/widget/refunds.phtml'); } public function renderWidgetInvoices(Am_View $view, $config=null) { $view->num = is_null($config) ? 5 : $config['num']; $view->statuses = $config['statuses']; return $view->render('admin/widget/invoices.phtml'); } public function createWidgetPaymentsConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Payments to display')) ->setValue(5); return $form; } public function createWidgetRefundsConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Refunds to display')) ->setValue(5); return $form; } public function createWidgetInvoicesConfigForm() { $form = new Am_Form_Admin(); $form->addInteger('num') ->setLabel(___('Number of Invoices to display')) ->setValue(5); $form->addMagicselect('statuses') ->setLabel(___('Show invoices with selected statuses') . "\n" . ___('leave it empty in case if you want to show all invoices')) ->loadOptions(Invoice::$statusText); return $form; } public function renderWidgetReportUsers(Am_View $view) { $view->enableReports(); $view->report = $this->getReportUsers(); return $view->render('admin/widget/report-users.phtml'); } public function renderWidgetWarnings(Am_View $view) { $this->view->warnings = AM_APPLICATION_ENV == 'demo' ? array() : $this->getWarnings(); $this->view->notice = $this->getNotice(); return $view->render('admin/widget/warnings.phtml'); } protected function getReportUsers() { class_exists('Am_Report_Standard', true); $res = $this->getDi()->db->select("SELECT status as ARRAY_KEY, COUNT(*) as `count` FROM ?_user GROUP BY status"); for ($i = 0; $i <= 2; $i++) $res[$i]['count'] = (int) @$res[$i]['count']; $active_paid = $this->getDi()->db->selectCell(" SELECT COUNT(DISTINCT p.user_id) AS active FROM ?_invoice_payment p INNER JOIN ?_user u USING (user_id) WHERE u.status = 1"); $active_free = $res[1]['count'] - $active_paid; $result = new Am_Report_Result; $result->setTitle(___('Users Breakdown')); $result->addPoint(new Am_Report_Point(0, ___('Pending')))->addValue(0, (int) $res[0]['count']); $result->addPoint(new Am_Report_Point(1, ___('Active')))->addValue(0, (int) $active_paid); $result->addPoint(new Am_Report_Point(4, ___('Active (free)')))->addValue(0, (int) $active_free); $result->addPoint(new Am_Report_Point(2, ___('Expired')))->addValue(0, (int) $res[2]['count']); $result->addLine(new Am_Report_Line(0, ___('# of users'))); $output = new Am_Report_Graph_Bar($result); $output->setSize('100%', 250); return $output; } public function renderWidgetSales(Am_View $view, $config = null) { $intervals = is_null($config) ? array(Am_Interval::PERIOD_TODAY, Am_Interval::PERIOD_THIS_WEEK_FROM_SUN) : (array)$config['interval']; $out = ''; foreach ($intervals as $interval) { list($start, $stop) = $this->getDi()->interval->getStartStop($interval); $view->start = $start; $view->stop = $stop; $view->reportTitle = $this->getDi()->interval->getTitle($interval); $view->controller = $this; $out .= $view->render('admin/widget/sales.phtml'); } return $out; } //MRR is all of your recurring revenue normalized in to a monthly amount public function renderWidgetRecurringRevenue(Am_View $view, $config = null) { $view->amount = Am_Currency::render( $this->getDi()->db->selectCell(<<= ? AND EXISTS (SELECT * FROM ?_invoice_payment ip WHERE ip.invoice_id=i.invoice_id) CUT , Invoice::RECURRING_ACTIVE, $this->getDi()->sqlDate)); return $view->render('admin/widget/recurring-revenue.phtml'); } public function renderWidgetRevenueGoal(Am_View $view, $config = null) { $interval = is_null($config) ? Am_Interval::PERIOD_THIS_MONTH : $config['interval']; list($start, $stop) = $this->getDi()->interval->getStartStop($interval); $s = new DateTime($start); $e = new DateTime($stop); $n = new DateTime(sqlTime('now')); $diff = $e->diff($s); $days_total = $diff->days + 1; $diff_current = $n->diff($s); $days_current = $diff_current->days + 1; $amount = $this->getDi()->db->selectCell("SELECT SUM(amount/base_currency_multi) AS amt " . " FROM ?_invoice_payment WHERE dattm BETWEEN ? AND ?", $start, $stop); $refund_amount = $this->getDi()->db->selectCell("SELECT SUM(amount/base_currency_multi) AS amt " . " FROM ?_invoice_refund WHERE dattm BETWEEN ? AND ?", $start, $stop); $view->amount = max(0, $amount - $refund_amount); $view->goal = isset($config['goal']) ? $config['goal'] : 10000; $view->ontarget = ($view->goal/$days_total) <= ($view->amount/$days_current); $width = (100 * $view->amount) / $view->goal; $view->width = min(100, round($width)); $goal_target = $days_current * ($view->goal/$days_total); $width_target = (100 * $goal_target) / $view->goal; $view->width_target = min(100, round($width_target)); $view->diff = $view->amount - $goal_target; $view->forecast = $days_total * ($view->amount/$days_current); $view->reportTitle = $this->getDi()->interval->getTitle($interval); return $view->render('admin/widget/revenue-goal.phtml'); } public function createWidgetRevenueGoalConfigForm() { $form = new Am_Form_Admin(); $form->addSelect('interval', null, array('options' => array( Am_Interval::PERIOD_TODAY => ___('Today'), Am_Interval::PERIOD_THIS_WEEK_FROM_SUN => ___('This Week (Sun-Sat)'), Am_Interval::PERIOD_THIS_WEEK_FROM_MON => ___('This Week (Mon-Sun)'), Am_Interval::PERIOD_THIS_MONTH => ___('This Month'), Am_Interval::PERIOD_THIS_QUARTER => ___('This Quarter'), Am_Interval::PERIOD_THIS_YEAR => ___('This Year') )))->setLabel(___('Period'))->setValue(Am_Interval::PERIOD_THIS_MONTH); $g = $form->addGroup(); $g->setSeparator(' '); $g->setLabel(___('Revenue Goal')); $g->addText('goal', array('size' => 8, 'placeholder' => '10000')); $g->addHtml() ->setHtml(Am_Currency::getDefault()); return $form; } public function createWidgetActivityConfigForm() { $form = new Am_Form_Admin(); $form->addMagicSelect('events') ->setLabel(___("Events\n" . "to inclulde to widget, leave it " . "empty to include all events")) ->loadOptions(array( 'payment' => ___('Payment'), 'refund' => ___('Refund'), 'signin' => ___('Sign In'), 'signup' => ___('Sign Up'), 'download' => ___('File Download'), 'user_note' => ___('User Notes') )); $form->addSelect('interval', null, array('options' => array( Am_Interval::PERIOD_TODAY => ___('Today'), Am_Interval::PERIOD_LAST_7_DAYS => ___('Last 7 Days'), Am_Interval::PERIOD_LAST_14_DAYS => ___('Last 14 Days'), Am_Interval::PERIOD_THIS_WEEK_FROM_SUN => ___('This Week (Sun-Sat)'), Am_Interval::PERIOD_THIS_WEEK_FROM_MON => ___('This Week (Mon-Sun)'), Am_Interval::PERIOD_THIS_MONTH => ___('This Month'), Am_Interval::PERIOD_THIS_QUARTER => ___('This Quarter'), Am_Interval::PERIOD_THIS_YEAR => ___('This Year') )))->setLabel(___('Period'))->setValue(Am_Interval::PERIOD_THIS_WEEK_FROM_SUN); $form->addText('limit', array('size' => 3, 'placeholder' => '10')) ->setLabel(___('Maximum number of events')) ->addRule('lte', ___('Should be less then %d', 50), 50); return $form; } public function createWidgetSalesConfigForm() { $form = new Am_Form_Admin(); $form->addSortableMagicSelect('interval', null, array('options' => $this->getDi()->interval->getOptions())) ->setLabel(___('Period')) ->setValue(array(Am_Interval::PERIOD_TODAY)); return $form; } function getSalesStats($start, $stop) { $row = $this->getDi()->db->selectRow(" SELECT COUNT(*) AS cnt, ROUND(SUM(amount / base_currency_multi), 2) AS total FROM ?_invoice_payment WHERE dattm BETWEEN ? AND ?", sqlTime(strtotime($start)), sqlTime(strtotime($stop))); return array((int) $row['cnt'], moneyRound($row['total'])); } function getRefundsStats($start, $stop) { $row = $this->getDi()->db->selectRow(" SELECT COUNT(*) AS cnt, ROUND(SUM(amount / base_currency_multi), 2) AS total FROM ?_invoice_refund WHERE dattm BETWEEN ? AND ?", sqlTime(strtotime($start)), sqlTime(strtotime($stop))); return array((int) $row['cnt'], moneyRound($row['total'])); } function getCancelsStats($start, $stop) { return $this->getDi()->db->selectCell(" SELECT COUNT(*) FROM ?_invoice WHERE tm_cancelled BETWEEN ? AND ?", sqlTime(strtotime($start)), sqlTime(strtotime($stop))); } function getPlannedRebills($start, $stop) { $row = $this->getDi()->db->selectRow(" SELECT COUNT(*) AS cnt, ROUND(SUM(second_total / base_currency_multi), 2) AS total FROM ?_invoice WHERE rebill_date BETWEEN DATE(?) AND DATE(?) AND tm_cancelled IS NULL", sqlTime(strtotime($start)), sqlTime(strtotime($stop))); return array((int) $row['cnt'], moneyRound($row['total'])); } function getSignupsCount($start, $stop) { return $this->getDi()->db->selectCell(" SELECT COUNT(*) AS cnt FROM ?_user WHERE added BETWEEN ? AND ?", sqlTime(strtotime($start)), sqlTime(strtotime($stop))); } function getErrorLogCount() { $time = $this->getDi()->time; $tm = date('Y-m-d H:i:s', $time - 24 * 3600); return $this->getDi()->db->selectCell( "SELECT COUNT(*) FROM ?_error_log WHERE dattm BETWEEN ? AND ?", $tm, $this->getDi()->sqlDateTime); } function getAccessLogCount() { $tm = date('Y-m-d H:i:s', $this->getDi()->time - 24 * 3600); return $this->getDi()->db->selectCell( "SELECT COUNT(log_id) FROM ?_access_log WHERE dattm BETWEEN ? AND ?", $tm, $this->getDi()->sqlDateTime); } function getWarnings() { $warn = array(); $ext = array('pdo', 'pdo_mysql', 'openssl', 'mbstring'); foreach ($ext as $e) { if (!extension_loaded($e)) $warn[] = "aMember require $e extension to be installed in PHP. Please contact your hosting support and ask to enable this extension for PHP on your server (installation instructions)."; } $setupUrl = $this->getDi()->url('admin-setup'); if (!$this->getDi()->config->get('maintenance')) { $t = Am_Cron::getLastRun(); $diff = time() - $t; $tt = $t ? (___('at ') . amDatetime($t)) : ___('NEVER (oops! no records that it has been running at all!)'); if (($diff > 24 * 3600) && (AM_APPLICATION_ENV != 'demo')) $warn[] = ___('Cron job has been running last time %s, it is more than 24 hours before. Most possible external cron job has been set incorrectly. It may cause very serious problems with the script. You can find info how to set up cron job for your installation here.', $tt); } if (!$this->getDi()->productTable->count()) { $productsUrl = $this->getDi()->url('admin-products'); $warn[] = ___('You have not added any products, your signup forms will not work until you add at least one product'); } if ($this->getDi()->config->get('email_queue_enabled') && !$this->getDi()->config->get('use_cron')) { $url = $this->getDi()->url('admin-setup/advanced'); $warn[] = ___('%sEnable%s and %sconfigure%s external cron if you are using E-Mail Throttle Queue', '', '', '', ''); } if ($this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_email_template WHERE name in (?a)", array('pending_to_user', 'pending_to_admin', 'expire', 'autoresponder')) && !$this->getDi()->config->get('use_cron') && (AM_APPLICATION_ENV != 'demo')) { $url = $this->getDi()->url('admin-setup/advanced'); $warn[] = ___('%sEnable%s and %sconfigure%s external cron if you are using Periodic E-Mails (Autoresponder/Expiration/Pending Notifications)', '', '', '', ''); } // load all plugins try { foreach ($this->getDi()->plugins as $m) $m->loadEnabled(); } catch (Exception $e) { //nop } $event = $this->getDi()->hook->call(Am_Event::ADMIN_WARNINGS); return array_merge($warn, $event->getReturn()); } function getNotice() { $warn = array(); // Check for not approved users. if($this->getDi()->config->get('manually_approve')) { $na_users = $this->getDi()->db->selectCell('select count(*) from ?_user where is_approved<1'); if($na_users) { $url = $this->getDi()->url('admin-users',array('_u_search[field-is_approved][val]'=>0)); $warn[] = sprintf( ___('Number of users who require approval: %d. %sClick here%s to review these users.'), $na_users, '', '' ); } } // Check for not approved invoices. if($this->getDi()->config->get('manually_approve_invoice')) { $na_invoices = $this->getDi()->db->selectCell('select count(*) from ?_invoice where is_confirmed<1'); if($na_invoices) { $url = $this->getDi()->url('default/admin-payments/p/not-approved/index'); $warn[] = sprintf( ___('Number of invoices which require approval: %d. %sClick here%s to review these invoices.'), $na_invoices, '', '' ); } } // load all plugins try { foreach ($this->getDi()->plugins as $m) $m->loadEnabled(); } catch (Exception $e) { //nop } $event = $this->getDi()->hook->call(Am_Event::ADMIN_NOTICE); return array_merge($warn, $event->getReturn()); } function hasPermissions($perm, $priv = null) { return $this->getDi()->authAdmin->getUser()->hasPermission($perm); } function disableQuickstartAction() { $pref = $this->getPref(); foreach ($pref['top'] as $k => $w) { if ($w == 'quick-start') unset($pref['top'][$k]); } $this->getDi()->authAdmin->getUser()->setPref(Admin::PREF_DASHBOARD_WIDGETS, $pref); return $this->indexAction(); } function getWidgetsByTarget() { $widgets = array( 'top' => array(), 'bottom' => array(), 'main' => array(), 'aside' => array() ); $pref = $this->getPref(); $availableWidgets = $this->getAvailableWidgets(); foreach ($pref as $target => $enabledWidgets) { foreach ($enabledWidgets as $id) { if (isset($availableWidgets[$id]) && $availableWidgets[$id]->hasPermission($this->getDi()->authAdmin->getUser())) { $widgets[$target][] = $availableWidgets[$id]; } } } return $widgets; } function indexAction() { $this->view->enableReports(); $this->view->widgets = $this->getMyWidgets(); $this->view->display('admin/index.phtml'); } function getMyWidgets() { $widgets = $this->getWidgetsByTarget(); array_unshift($widgets['top'], new Am_Widget('warnings', ___('Warnings'), array($this, 'renderWidgetWarnings'), array('top'))); return $widgets; } function widgetAction(){ Zend_Session::writeClose(); $id = $this->getFiltered('id'); $widgets = $this->getMyWidgets(); list(,$target,$index) = explode('-', $id); if(!strlen($target) && !strlen($index) && !isset($widgets[$target][$index])) echo ___('Unable to load widget: %s', $id); $widget = $widgets[$target][$index]; $config = $this->getWidgetConfig(); echo $widget->render($this->view, isset($config[$widget->getId()]) ? $config[$widget->getId()] : null); } }PK\y}}0default/controllers/AdminUpgradeDbController.phpnu[isSuper(); } function indexAction() { $this->getDi()->db->setLogger(false); $t = new Am_View; set_time_limit(0); ini_set('memory_limit', AM_HEAVY_MEMORY_LIMIT); $this->db_version = $this->getDi()->store->get('db_version'); if (defined('AM_DEBUG')) ob_start(); ?> aMember Database Upgrade

      aMember Database Upgrade


      fixNotUniqueRecordInRebillLog(); $this->fixNotUniquePathInPages(); $this->getDi()->app->dbSync(true); $this->checkInvoiceItemTotals(); $this->convertTax(); $this->convertAutoresponderPrefix(); $this->enableSkipIndexPage(); $this->manuallyApproveInvoices(); $this->addCountryCodes(); $this->fillResourceAccessSort(); $this->upgradeFlowPlayerKey(); $this->fixCryptSavedPass(); $this->updateStateInfo(); $this->fixCustomFieldSortTableName(); $this->normalizeProductSortOrder(); $this->fixPagePath(); $this->setupDefaultProtcetionForCustomFields(); $this->populateInvoicePublicId(); $this->populateCouponCode(); $this->convert0toNull(); $this->fixLogoutRedirectSettings(); $this->fixUserStatusTable(); $this->populateAffAddedField(); $this->convertFreeWithoutAccessFoldersToLinks(); $this->setDefaultProfileForm(); $this->hideSignupForms(); $this->disableUserNotesPlugin(); $this->disableForcePasswordCachangePlugin(); $this->enableUseCoupons(); $this->pupulateRefundAmount(); $this->enableAffKeywords(); $this->enableRecurringForExpireEmailTemplates(); $this->initFormSortOrder(); $this->enableAllowCancel(); $this->fixDateFormat(); $this->updateBrowseUsersField(); $this->convertCustomVats(); $this->handlePdfConfig(); $this->moveCurrencyToBp(); $this->convertCCRecords(); $this->getDi()->hook->call(new Am_Event(Am_Event::DB_UPGRADE, array('version' => $this->db_version))); $version = AM_VERSION; $year = date('Y'); $copyright = << aMember Pro™ $version by aMember.com © 2002–$year CGI-Central.Net
      CUT; echo "
      Upgrade finished successfully. Go to aMember Admin CP.
      $copyright "; } function fixNotUniqueRecordInRebillLog() { //to set unique index (invoice_id,rebill_date) if (version_compare($this->db_version, '4.2.15') < 0) { $db = $this->getDi()->db; try { //to handle situation when ?_cc_rebill table does not exists $db->query('CREATE TEMPORARY TABLE ?_cc_rebill_temp ( cc_rebill_id int not null, tm_added datetime not null, paysys_id varchar(64), invoice_id int, rebill_date date, status smallint, status_tm datetime, status_msg varchar(255), UNIQUE INDEX(invoice_id, rebill_date))'); $db->query(' INSERT IGNORE INTO ?_cc_rebill_temp SELECT * FROM ?_cc_rebill '); $db->query("TRUNCATE ?_cc_rebill"); $db->query(' INSERT INTO ?_cc_rebill SELECT * FROM ?_cc_rebill_temp '); $db->query("DROP TABLE ?_cc_rebill_temp"); } catch (Exception $e) { } } } function fillResourceAccessSort() { $this->getDi()->resourceAccessTable->syncSortOrder(); } function manuallyApproveInvoices(){ if((version_compare($this->db_version, '4.2.4') <0) || ((version_compare(AM_VERSION, '4.2.7')<=0) && !$this->getDi()->config->get('manually_approve_invoice')) ) { echo "Manually approve old invoices..."; @ob_end_flush(); $this->getDi()->db->query("update ?_invoice set is_confirmed=1"); echo "Done
      \n"; } } function checkInvoiceItemTotals() { if (version_compare($this->db_version, '4.1.8') < 0) { echo "Update invoice_item.total columns..."; @ob_end_flush(); $this->getDi()->db->query(" UPDATE ?_invoice_item SET first_total = first_price*qty - first_discount + first_shipping + first_tax, second_total = second_price*qty - second_discount + second_shipping + second_tax WHERE ((first_total IS NULL OR first_total = 0) AND first_price > 0) OR ((second_total IS NULL OR second_total = 0) AND second_price > 0) "); echo "Done
      \n"; } } function convertTax() { if (version_compare($this->db_version, '4.2.0') < 0) { echo "Move product.no_tax -> product.tax columns..."; @ob_end_flush(); try { $this->getDi()->db->query(" UPDATE ?_product SET tax_group = IF(IFNULL(no_tax, 0) = 0, 0, 1) "); // $this->getDi()->db->query("ALTER TABLE ?_product DROP no_tax"); } catch (Am_Exception_Db $e) { } echo "Move invoice_item.no_tax -> invoice_item.tax_group columns..."; @ob_end_flush(); try { $this->getDi()->db->query(" UPDATE ?_invoice_item SET tax_group = IF(IFNULL(no_tax, 0) = 0, 0, 1) "); // $this->getDi()->db->query("ALTER TABLE ?_invoice_item DROP no_tax"); } catch (Am_Exception_Db $e) { } echo "Done
      \n"; echo "Migrate tax settings..."; if ($this->getDi()->config->get('use_tax')) { $config = $this->getDi()->config; $config->read(); switch ($this->getDi()->config->get('tax_type')) { case 1: $config->set('plugins.tax', array('global-tax')); $config->set('tax.global-tax.rate', $config->get('tax_value')); break; case 2: $config->set('plugins.tax', array('regional')); $config->set('tax.regional.taxes', $config->get('regional_taxes')); break; } $arr = $config->getArray(); unset($arr['tax_type']); unset($arr['regional_taxes']); unset($arr['tax_value']); unset($arr['use_tax']); $config->setArray($arr); $config->save(); } echo "Done
      \n"; } } function convertAutoresponderPrefix() { if (version_compare($this->db_version, '4.2.0') < 0) { echo "Convert Autoresponder Prefix From [emailtemplate] to [email-messages]"; @ob_end_flush(); try { $rows = $this->getDi()->db->query(" SELECT * FROM ?_email_template WHERE name IN ('autoresponder', 'expire') AND attachments IS NOT NULL "); $upload_ids = array(); foreach ($rows as $row) { $upload_ids = array_merge($upload_ids, explode(',', $row['attachments'])); } if (count($upload_ids)) { $templates = array(); foreach ($upload_ids as $id) { $rows = $this->getDi()->db->query(" SELECT * FROM ?_email_template WHERE name NOT IN ('autoresponder', 'expire') AND (attachments=? OR attachments LIKE ? OR attachments LIKE ? OR attachments LIKE ?)", $id, '%,'.$id, $id.',%', '%,'.$id.',%' ); $templates = array_merge($templates, $rows); } if (count($templates)) { $names = array(); foreach ($templates as $tpl) { $names[] = sprintf('%s [%s]', $tpl['name'], $tpl['lang']); } echo sprintf(' Please reupload attachments for the following templates: %s
      ', implode(', ', $names)); } $this->getDi()->db->query("UPDATE ?_upload SET prefix=? WHERE upload_id IN (?a)", 'email-messages', $upload_ids); } } catch (Am_Exception_Db $e) { } echo "Done
      \n"; } } function checkResourceAccessEmailTemplates(){ if (version_compare($this->db_version, '4.1.14') < 0) { echo "Update resource access table ..."; @ob_end_flush(); $this->getDi()->db->query(" UPDATE ?_resource_access SET start_days = (SELECT day FROM ?_email_template WHERE email_template_id=resource_id), stop_days = (SELECT day FROM ?_email_template WHERE email_template_id=resource_id) WHERE resource_type = 'emailtemplate' AND fn='free' and start_days IS NULL "); echo "Done
      \n"; } } function enableSkipIndexPage() { if (version_compare($this->db_version, '4.1.16') < 0) { echo "Enable skip_index_page option..."; if (ob_get_level()) ob_end_flush(); $str = $this->getDi()->db->selectCell("SELECT config FROM ?_config WHERE name = ?", 'default'); $config = unserialize($str); if (!isset($config['skip_index_page'])) { $config['skip_index_page'] = 1; $this->getDi()->db->selectCol("UPDATE ?_config SET config=? WHERE name = ?", serialize($config), 'default'); } echo "Done
      \n"; } } function addCountryCodes() { if (version_compare($this->db_version, '4.2.10') < 0) { echo "Add country codes..."; if (ob_get_level()) ob_end_flush(); $query = file_get_contents($this->getDi()->root_dir . '/setup/sql-country.sql'); $query = str_replace('@DB_MYSQL_PREFIX@', '?_', $query); $this->getDi()->db->query($query); echo "Done
      \n"; } } function upgradeFlowPlayerKey() { if (version_compare($this->db_version, '4.2.16') < 0) { echo "Update Flowplayer License Key..."; if (ob_get_level()) ob_end_flush(); $request = new Am_HttpRequest('https://www.amember.com/fplicense.php', Am_HttpRequest::METHOD_POST); $request->addPostParameter('root_url', $this->getDi()->config->get('root_url')); try { $response = $request->send(); } catch (Exception $e) { echo "request failed " . $e->getMessage() . "\n
      "; return; } if ($response->getStatus() == 200) { $body = $response->getBody(); $res = json_decode($body, true); if ($res['status'] == 'OK' && $res['license']) { Am_Config::saveValue('flowplayer_license', $res['license']); } } echo "Done
      \n"; } } function fixCryptSavedPass() { if (version_compare($this->db_version, '4.2.16') < 0) { echo "Fix crypt saved pass..."; if (ob_get_level()) ob_end_flush(); $this->getDi()->db->query("UPDATE ?_saved_pass SET salt=pass WHERE format=?", 'crypt'); echo "Done
      \n"; } } function updateStateInfo() { if (version_compare($this->db_version, '4.2.16') < 0) { echo "Update State Info..."; if (ob_get_level()) ob_end_flush(); $query = file_get_contents($this->getDi()->root_dir . '/setup/sql-state.sql'); $query = str_replace('@DB_MYSQL_PREFIX@', '?_', $query); $this->getDi()->db->query($query); echo "Done
      \n"; } } function fixCustomFieldSortTableName() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Rename custom_fields_sort to custom_field_sort..."; if (ob_get_level()) ob_end_flush(); try { //actually we move data from old table to new one here to leave user preference if (!$this->getDi()->db->selectCell("SELECT COUNT(*) FROM ?_custom_field_sort")) { $this->getDi()->db->query("SET @i = 0"); $this->getDi()->db->query("INSERT INTO ?_custom_field_sort (custom_field_table, custom_field_name, sort_order) SELECT custom_field_table, custom_field_name, (@i:=@i+1) FROM ?_custom_fields_sort ORDER BY sort_order"); } } catch (Exception $e) { //nop, handle situsation for upgrade from version where ?_custom_fields_sort is not exists yet } echo "Done
      \n"; } } function normalizeProductSortOrder() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Normalize sort order for products..."; if (ob_get_level()) ob_end_flush(); $this->getDi()->db->query("SET @i = 0"); $this->getDi()->db->query("UPDATE ?_product SET sort_order=(@i:=@i+1) ORDER BY sort_order"); echo "Done
      \n"; } } function fixNotUniquePathInPages() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Fix Not Unique Path in Pages..."; if (ob_get_level()) ob_end_flush(); $this->getDi()->db->query("UPDATE ?_page SET path = page_id WHERE path=''"); echo "Done
      \n"; } } function fixPagePath() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Fix Page Path..."; if (ob_get_level()) ob_end_flush(); $this->getDi()->db->query("UPDATE ?_page SET path = NULL WHERE path=page_id"); echo "Done
      \n"; } } function setupDefaultProtcetionForCustomFields() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Setup default protection for custom fields..."; foreach($this->getDi()->userTable->customFields()->getAll() as $field) { if (isset($field->from_config) && $field->from_config) $this->getDi()->resourceAccessTable->setAccess(amstrtoint($field->name), Am_CustomField::ACCESS_TYPE, array( ResourceAccess::FN_FREE_WITHOUT_LOGIN => array( json_encode(array( 'start' => null, 'stop' => null, 'text' => ___('Free Access without log-in') ))) )); } echo "Done
      \n"; } } function populateInvoicePublicId() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Populate Invoice Public Id (Denormalization)..."; foreach (array('?_access', '?_invoice_item', '?_invoice_payment', '?_invoice_refund') as $table) { $this->getDi()->db->query("UPDATE $table t SET invoice_public_id = (SELECT public_id FROM ?_invoice i WHERE i.invoice_id=t.invoice_id) WHERE t.invoice_id IS NOT NULL"); } echo "Done
      \n"; } } function populateCouponCode() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Populate Coupon Code (Denormalization)..."; $this->getDi()->db->query("UPDATE ?_invoice t SET coupon_code = (SELECT code FROM ?_coupon c WHERE c.coupon_id=t.coupon_id) WHERE t.coupon_id IS NOT NULL"); echo "Done
      \n"; } } function convert0toNull() { if (version_compare($this->db_version, '4.2.20') < 0) { echo "Convert 0 to NULL..."; $this->getDi()->db->query("UPDATE ?_access SET invoice_id=NULL WHERE invoice_id=0"); $this->getDi()->db->query("UPDATE ?_access SET invoice_payment_id=NULL WHERE invoice_payment_id=0"); $this->getDi()->db->query("UPDATE ?_access SET invoice_item_id=NULL WHERE invoice_item_id=0"); $this->getDi()->db->query("UPDATE ?_access SET transaction_id=NULL WHERE transaction_id=''"); echo "Done
      \n"; } } function fixLogoutRedirectSettings() { if (version_compare($this->db_version, '4.2.20') < 0) { if (!$this->getDi()->config->get('protect.php_include.redirect_logout') && $this->getDi()->config->get('protect.php_include.redirect')) { Am_Config::saveValue('protect.php_include.redirect_logout', 'url'); $this->getDi()->config->read(); } } } function fixUserStatusTable() { if (version_compare($this->db_version, '4.3.3') < 0) { echo "Fix ?_user_status table..."; $this->getDi()->db->query("DELETE FROM ?_user_status WHERE user_id NOT IN (SELECT user_id FROM ?_user)"); echo "Done
      \n"; } } function populateAffAddedField() { if (version_compare($this->db_version, '4.3.3') < 0) { echo "Populate aff_added field..."; $this->getDi()->db->query("UPDATE ?_user SET aff_added=added WHERE aff_id>0 AND aff_added IS NULL"); echo "Done
      \n"; } } function convertFreeWithoutAccessFoldersToLinks() { if (version_compare($this->db_version, '4.3.4') < 0) { echo "Converst Free Without Access Folders to Links..."; foreach($this->getDi()->resourceAccessTable->findBy(array( 'fn' => ResourceAccess::FN_FREE_WITHOUT_LOGIN, 'resource_type' => ResourceAccess::FOLDER )) as $rec) { try { $folder = $this->getDi()->folderTable->load($rec->resource_id); $link = $this->getDi()->linkRecord; foreach (array('title', 'desc', 'url', 'hide') as $prop) { $link->{$prop} = $folder->{$prop}; } $link->save(); $link->setAccess(array( ResourceAccess::FN_FREE => array( 0 => array( 'start' => null, 'stop' => null ) ) )); $sort = $folder->getSortOrder(); $folder->delete(); $this->unprotectFolder($folder); $link->setSortOrder($sort); } catch (Exception $e) {} } echo "Done
      \n"; } } function setDefaultProfileForm() { if (version_compare($this->db_version, '4.6.4') < 0) { echo "Set Default Profile Form..."; if (!$this->getDi()->savedFormTable->getDefault(SavedForm::D_PROFILE)) { $id = $this->getDi()->db->selectCell('SELECT saved_form_id FROM ?_saved_form WHERE type=? LIMIT 1', 'profile'); $this->getDi()->savedFormTable->setDefault(SavedForm::D_PROFILE, $id); } echo "Done
      \n"; } } public function hideSignupForms() { if (version_compare($this->db_version, '4.7.0') < 0) { echo "Hide Signup Forms from Menu..."; $form = $this->getDi()->savedFormTable->getDefault(SavedForm::D_MEMBER); $this->getDi()->db->query('UPDATE ?_saved_form SET hide=1 WHERE type=? AND saved_form_id<>?', SavedForm::T_SIGNUP, $form->pk()); echo "Done
      \n"; } } public function disableUserNotesPlugin() { if (version_compare($this->db_version, '4.7.3') < 0) { //echo "Disable User Notes plugin (This feature is incorporated to core)..."; $plugins = $this->getDi()->config->get('plugins.misc'); if ($plugins) foreach ($plugins as $k => $pl) { if ($pl == 'user-note') { unset($plugins[$k]); Am_Config::saveValue('plugins.misc', $plugins); break; } } //echo "Done
      \n"; } } public function disableForcePasswordCachangePlugin() { if (version_compare($this->db_version, '4.7.3') < 0) { //echo "Disable Force Password Change plugin (This feature is incorporated to core)..."; $plugins = $this->getDi()->config->get('plugins.misc'); if ($plugins) foreach ($plugins as $k => $pl) { if ($pl == 'force-password-change') { Am_Config::saveValue('force_change_password', 1); Am_Config::saveValue('force_change_password_period', $this->getDi()->config->get('misc.force-password-change.period')); unset($plugins[$k]); Am_Config::saveValue('plugins.misc', $plugins); break; } } //echo "Done
      \n"; } } public function enableUseCoupons() { if (version_compare($this->db_version, '4.7.3') < 0) { echo "Enable use of coupons in Shopping Cart..."; Am_Config::saveValue('cart.use_coupons', 1); echo "Done
      \n"; } } public function pupulateRefundAmount() { if (version_compare($this->db_version, '4.7.3') < 0) { echo "Populate Refund Amount..."; $this->getDi()->db->query("INSERT INTO ?_invoice_payment (invoice_payment_id, refund_dattm, refund_amount) (SELECT invoice_payment_id, MIN(dattm), SUM(amount) FROM ?_invoice_refund WHERE invoice_payment_id > 0 GROUP BY invoice_payment_id) ON DUPLICATE KEY UPDATE refund_dattm = VALUES(refund_dattm), refund_amount = VALUES(refund_amount);"); echo "Done
      \n"; } } public function enableAffKeywords() { if (version_compare($this->db_version, '4.7.3') < 0) { echo "Enable Keywords support in Affiliate Module..."; Am_Config::saveValue('aff.keywords', 1); echo "Done
      \n"; } } public function enableRecurringForExpireEmailTemplates() { if (version_compare($this->db_version, '4.7.3') < 0) { echo "Enable Recurring Option for Expire Email Templates..."; $this->getDi()->db->query("UPDATE ?_email_template SET recurring=1 WHERE name=?", EmailTemplate::EXPIRE); echo "Done
      \n"; } } function initFormSortOrder() { if (version_compare($this->db_version, '5.0.1') < 0) { echo "Init sort order for saved forms..."; if (ob_get_level()) ob_end_flush(); $this->getDi()->db->query("SET @i = 0"); $this->getDi()->db->query("UPDATE ?_saved_form SET sort_order=(@i:=@i+1) ORDER BY `type`='signup' DESC"); echo "Done
      \n"; } } function enableAllowCancel() { if (version_compare($this->db_version, '5.0.5') <= 0) { echo "Enable allow_cancel option..."; if (ob_get_level()) ob_end_flush(); Am_Config::saveValue('allow_cancel', 1); echo "Done
      \n"; } } function fixDateFormat() { if (version_compare($this->db_version, '5.0.7') <= 0) { echo "Fix date_format and time_format..."; if (ob_get_level()) ob_end_flush(); Am_Config::saveValue('date_format', null); Am_Config::saveValue('time_format', null); echo "Done
      \n"; } } function updateBrowseUsersField() { if (version_compare($this->db_version, '5.1.7') < 0) { echo "Update Browse Users fields..."; $update = array('name', 'payments_count', 'payments_sum', 'products', 'ugroup', 'expire'); if (ob_get_level()) ob_end_flush(); foreach($this->getDi()->adminTable->findBy() as $admin) { if(@count($pref = $admin->getPref('grid_setup_u'))) { foreach($pref as $k => $v) { if(in_array($v, $update)) $pref[$k] = '_' . $v; } $admin->setPref('grid_setup_u', $pref); } } echo "Done
      \n"; } } public function handlePdfConfig() { if (version_compare($this->db_version, '5.1.8') <= 0) { echo "Normalize PDF Invoice options..."; if ($this->getDi()->config->get('send_pdf_invoice')) { Am_Config::saveValue('pdf_invoice_sent_user', 1); Am_Config::saveValue('pdf_invoice_sent_admin', 1); Am_Config::saveValue('pdf_invoice_link', 1); } echo "Done
      \n"; } } public function convertCCRecords() { if ((version_compare($this->db_version, '5.1.8') <= 0) && $this->getDi()->modules->isEnabled('cc')) { $this->error(sprintf("Default encryption method was changed. You must re-encrypt database. Please run this tool\n
      ", $this->getUrl('admin-convert', 'index', 'cc'))); } } function moveCurrencyToBp() { echo "Move Currency to Billing Plans..."; //idempotent operation $this->getDi()->db->query(<<\n"; } public function unprotectFolder(Folder $folder) { $htaccess_path = $folder->path . '/.htaccess'; if (!is_dir($folder->path)) { $this->error('Could not open folder [%s] to remove .htaccess from it. Do it manually', $folder->path); return; } $content = file_get_contents($htaccess_path); if (strlen($content) && !preg_match('/^\s*\#+\sAMEMBER START.+AMEMBER FINISH\s#+\s*/s', $content)) { $this->error('File [%s] contains not only aMember code - remove it manually to unprotect folder', $htaccess_path); return; } if (!unlink($folder->path . '/.htaccess')) $this->error('File [%s] cannot be deleted - remove it manually to unprotect folder', $htaccess_path); } public function convertCustomVats() { $nodata = 'a:29:{s:2:"AT";s:0:"";s:2:"BE";s:0:"";s:2:"BG";s:0:"";s:2:"CY";s:0:"";s:2:"HR";s:0:"";s:2:"CZ";s:0:"";s:2:"DE";s:0:"";s:2:"DK";s:0:"";s:2:"EE";s:0:"";s:2:"GR";s:0:"";s:2:"ES";s:0:"";s:2:"FI";s:0:"";s:2:"FR";s:0:"";s:2:"GB";s:0:"";s:2:"HU";s:0:"";s:2:"IE";s:0:"";s:2:"IM";s:0:"";s:2:"IT";s:0:"";s:2:"LT";s:0:"";s:2:"LU";s:0:"";s:2:"LV";s:0:"";s:2:"MT";s:0:"";s:2:"NL";s:0:"";s:2:"PL";s:0:"";s:2:"PT";s:0:"";s:2:"RO";s:0:"";s:2:"SE";s:0:"";s:2:"SK";s:0:"";s:2:"SI";s:0:"";}'; $i = 1; if ($records = $this->getDi()->db->select("SELECT * FROM ?_data WHERE `key` = 'vat_eu_rate'")) { $groups = $this->getConfig('tax.vat2015.tax_groups', array()); $index = array(); foreach ($groups as $id => $title) { $index[md5(serialize($this->getConfig("tax.vat2015.$id")))] = $id; } foreach ($records as $r) { if ($r['blob'] == $nodata) continue; $k = md5($r['blob']); if (isset($index[$k])) { $tax_group = $index[$k]; } else { $d = unserialize($r['blob']); $groups[$_ = uniqid()] = 'Reduced Tax Group '. $i++; $index[md5($r['blob'])] = $_; Am_Config::saveValue("tax.vat2015.$_", $d); $tax_group = $_; } if ($p = $this->getDi()->productTable->load($r['id'], false)) { $p->tax_rate_group = $tax_group; $p->save(); } } foreach ($groups as $id => $title) { Am_Config::saveValue('tax.vat2015.tax_groups.' . $id, $title); } $this->getDi()->db->query("DELETE FROM ?_data WHERE `key` = 'vat_eu_rate'"); } } function error($msg) { echo sprintf('%s
      ', $msg); } } PK\o>2<<1default/controllers/AdminDirbrowserController.phpnu[hasPermission("grid_content"); } /* * Does not allow to list directories upper than CHROOT * list CHROOT dir if tried to list dir outside of CHROOT * should be without trailing slash * * @example /home/user/htdocs */ protected $chroot; public function init() { parent::init(); try { $options = $this->getDi()->getParameter('dirbrowser'); if (!empty($options['chroot'])) { $this->chroot = $options['chroot']; } } catch (Exception $e) {} } public function indexAction() { $dirOrig = $this->getRequest()->getParam('dir', $this->getDi()->root_dir); $dirOrig = is_dir($dirOrig) ? $dirOrig : $this->getDi()->root_dir; $selected = $this->getRequest()->getParam('selected', false); $dir = ($selected) ? dirname($dirOrig) : $dirOrig; $dir = realpath($dir); if (!is_dir($dir)) { $dir = $this->getDi()->root_dir; } if (!$this->checkChRoot($dir)) { $dir = $this->chroot; } $dirList = $this->getDirList($dir); if ($selected) { foreach ($dirList as $k => $dirDescription) { if ($dirDescription['path'] == $dirOrig) { $dirList[$k]['selected'] = true; break; } } } $currentDir = $this->getCurrentDir($dir); $prevDir = $this->getPrevDir($dir); $result = array( 'dirList' => $dirList, 'currentDir' => $currentDir, 'prevDir' => $prevDir, 'separator' => DIRECTORY_SEPARATOR ); echo json_encode($result); } protected function checkChRoot($dir) { if (!is_null($this->chroot) && strpos($dir, $this->chroot)!==0) { return false; } else { return true; } } protected function getCurrentDir($dir) { $result = array(); $dirParts = explode(DIRECTORY_SEPARATOR, $dir); $path = array(); foreach ($dirParts as $part) { $path[]= $part; $part_path = implode(DIRECTORY_SEPARATOR, $path); $dir = array ( 'name' => $part, 'path' => ($this->checkChRoot($part_path) ? $part_path : null ) ); $result[] = $dir; } return $result; } protected function getPrevDir($dir) { $prevDir = null; $prevDirPath = dirname($dir); //root of file system if ($prevDirPath == $dir) return null; $dirParts = explode(DIRECTORY_SEPARATOR, $prevDirPath); $prevDirName = end($dirParts); if (is_dir( $prevDirPath ) ) { $prevDir = array ( 'name' => $prevDirName, 'path' => ($this->checkChRoot($prevDirPath) ? $prevDirPath : null) ); } return $prevDir; } protected function getDirList($dir) { $result = array(); $dirName = $dir; $dirHandler = opendir($dirName); while(false !== ($fn = readdir($dirHandler))) { if (is_dir($dirName . DIRECTORY_SEPARATOR . $fn) && !in_array($fn, array('..', '.'))) { $result[] = $this->getDirRecord($dirName, $fn); } } closedir($dirHandler); usort($result, function($a, $b) {return strcmp($a["name"], $b["name"]);}); return $result; } protected function getDirRecord($dirName, $fn) { $stat = stat($dirName . DIRECTORY_SEPARATOR . $fn); return array( 'name' => $fn, 'path' => $dirName . DIRECTORY_SEPARATOR . $fn, 'url' => $this->guessUrl($dirName . DIRECTORY_SEPARATOR . $fn), 'perm' => $this->formatPermissions($stat['mode']), 'created' => $this->formatDate($stat['ctime']), 'selected' => false ); } public function guessUrl($dir) { $documentRootFixed = str_replace('/', DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT']); //FirePHP::getInstance(true)->log($documentRootFixed , 'DOCUMENT ROOT'); //FirePHP::getInstance(true)->log($dir , 'dir'); //check if it is possible to calculate url if (strpos($dir, $documentRootFixed) !== 0) return false; $rootUrlMeta = parse_url(ROOT_URL); //combine url return sprintf('%s://%s%s/%s', $rootUrlMeta['scheme'], $rootUrlMeta['host'], (isset($rootUrlMeta['port']) ? ':' . $rootUrlMeta['port'] : ''), trim(str_replace(DIRECTORY_SEPARATOR, '/', str_replace($documentRootFixed, '', $dir)), '/')); } protected function formatPermissions($p) { $res = ''; $res .= ($p & 256) ? 'r' : '-'; $res .= ($p & 128) ? 'w' : '-'; $res .= ($p & 64) ? 'x' : '-'; $res .= ' '; $res .= ($p & 32) ? 'r' : '-'; $res .= ($p & 16) ? 'w' : '-'; $res .= ($p & 8) ? 'x' : '-'; $res .= ' '; $res .= ($p & 4) ? 'r' : '-'; $res .= ($p & 2) ? 'w' : '-'; $res .= ($p & 1) ? 'x' : '-'; return $res; } protected function formatDate($tm) { return amDate($tm); } } PK\'/default/controllers/AdminVatGroupController.phpnu[hasPermission(Am_Auth_Admin::PERM_SETUP); } function indexAction() { $plugin = $this->getPlugin(); $form = new Am_Form_Admin; $form->addText('name', array('class' => 'el-wide')) ->setLabel(___("Tax Group Name\n" . 'for your reference')) ->addRule('required'); $label_cancel = Am_Html::escape(___('Cancel')); $url_cancel = $this->getDi()->url("admin-setup/".$plugin->getId()); $g = $form->addGroup(); $g->setSeparator(' '); $g->addSubmit('save', array('value'=>___('Save'))); $g->addHtml() ->setHtml(<<$label_cancel CUT ); if ($form->isSubmitted() && $form->validate()) { $v = $form->getValue(); $tax_groups = $plugin->getConfig('tax_groups', array()); do { $id = uniqid(); } while (isset($tax_groups[$id])); Am_Config::saveValue("tax.{$plugin->getId()}.tax_groups.$id", $v['name']); Am_Mvc_Response::redirectLocation($this->getDi()->url("admin-setup/{$plugin->getId()}#tax-rate-group-$id",false)); } else { $this->view->title = ___('New Tax Group'); $this->view->content = (string) $form; $this->view->display('admin/layout.phtml'); } } function deleteAction() { $plugin = $this->getPlugin(); if (($id = $this->getParam('id')) && $id != 'rate') { $tax_groups = $this->getConfig("tax.{$plugin->getId()}.tax_groups"); unset($tax_groups[$id]); Am_Config::saveValue("tax.{$plugin->getId()}.tax_groups", $tax_groups); Am_Config::saveValue("tax.{$plugin->getId()}.$id", null); $this->getDi()->db->query(<<getDi()->url("admin-setup/{$plugin->getId()}",false)); } function editAction() { $plugin = $this->getPlugin(); if (($id = $this->getParam('id')) && $id != 'rate') { $tax_groups = $plugin->getConfig('tax_groups'); $form = new Am_Form_Admin; $form->addText('name', array('class' => 'el-wide')) ->setLabel(___("Tax Group Name\n" . 'for your reference')) ->addRule('required'); $form->addHidden('id') ->setValue($id); $label_cancel = Am_Html::escape(___('Cancel')); $url_cancel = $this->getDi()->url("admin-setup/{$plugin->getId()}#tax-rate-group-$id"); $g = $form->addGroup(); $g->setSeparator(' '); $g->addSubmit('save', array('value'=>___('Save'))); $g->addHtml() ->setHtml(<<$label_cancel CUT ); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'name' => $tax_groups[$id] ))); if ($form->isSubmitted() && $form->validate()) { $v = $form->getValue(); Am_Config::saveValue("tax.{$plugin->getId()}.tax_groups." . $v['id'], $v['name']); Am_Mvc_Response::redirectLocation($this->getDi()->url("admin-setup/{$plugin->getId()}#tax-rate-group-{$v['id']}",false)); } else { $this->view->title = ___('New Tax Group'); $this->view->content = (string) $form; $this->view->display('admin/layout.phtml'); } } else { throw new Am_Exception_InputError; } } function getPlugin() { list($pl) = $this->getDi()->plugins_tax->getAllEnabled(); return $pl; } }PK\l%  'default/controllers/MediaController.phpnu[getDi()->config->get('video_player', 'Flowplayer').'Params'; if(!method_exists($this, $method)) throw Am_Exception_InternalError(sprintf('Method %s is not defined.', $method)); return call_user_func(array($this, $method), $media); } function getPlayerConfig(ResourceAbstractFile $media) { $localConfig = array(); if (!$media->config) { } elseif (substr($media->config, 0,6) == 'preset') { $presets = unserialize($this->getDi()->store->getBlob('flowplayer-presets')); $localConfig = $presets[$media->config]['config']; } else { $localConfig = unserialize($media->config); } $config = array_merge($this->getDi()->config->get('flowplayer', array()), $localConfig); return $config; } function getMedia() { if (!$this->media) { $this->id = $this->_request->getInt('id'); if (!$this->id) throw new Am_Exception_InputError("Wrong URL - no media id passed"); $this->media = $this->getDi()->videoTable->load($this->id, false); if (!$this->media) throw new Am_Exception_InputError("This media has been removed"); } return $this->media; } function dAction() { $id = $this->_request->get('id'); $this->validateSignedLink($id); $id = intval($id); $media = $this->getDi()->videoTable->load($id); set_time_limit(600); while (@ob_end_clean()); Zend_Session::writeClose(); if ($path = $media->getFullPath()) { $this->_helper->sendFile($path, $media->getMime()); } else $this->_response->redirectLocation($media->getProtectedUrl($this->getDi()->config->get('storage.s3.expire', 15) * 60)); } function pAction() { $media = $this->getMedia(); $view = $this->view; $view->meta_title = $media->meta_title ? $media->meta_title : $media->title; if ($media->meta_keywords) $view->headMeta()->setName('keywords', $media->meta_keywords); if ($media->meta_description) $view->headMeta()->setName('description', $media->meta_description); if ($media->meta_robots) $view->headMeta()->setName('robots', $media->meta_robots); $view->title = $this->getMedia()->title; $view->content = '"; $view->display($media->tpl ? $media->tpl : 'layout.phtml'); } function getSignedLink(ResourceAbstract $media) { $rel = $media->pk() . '-' . ($this->getDi()->time + 3600 * 24); return $this->getDi()->url( $this->type . '/d/id/' . $rel . '-' . $this->getDi()->security->siteHash('am-' . $this->type . '-' . $rel, 10), false, $this->getRequest()->isSecure() ? true : 2); } function validateSignedLink($id) { @list($rec_id, $time, $hash) = explode('-', $id, 3); if ($rec_id <= 0) throw new Am_Exception_InputError('Wrong media id#'); if ($time < Am_Di::getInstance()->time) throw new Am_Exception_InputError('Media Link Expired'); if ($hash != $this->getDi()->security->siteHash("am-" . $this->type . "-$rec_id-$time", 10)) throw new Am_Exception_InputError('Media Link Error - Wrong Sign'); } function renderJs() { if(!$this->getDi()->auth->getUserId()) $this->getDi()->auth->checkExternalLogin($this->getRequest()); $media = $this->getMedia(); $config = $this->getPlayerConfig($media); $params = $this->getPlayerParams($media); $this->view->id = $this->id; $this->view->type = $this->type; $this->view->width = $this->_request->getInt('width', isset($params['width']) ? $params['width'] : 520); $this->view->height = $this->_request->getInt('height', isset($params['height']) ? $params['height'] : 330); unset($params['width']); unset($params['height']); $guestAccess = false; $guestAccess = $media->hasAccess(null); if (!$this->getDi()->auth->getUserId() && !$guestAccess) { try { if ($media->mime == 'audio/mpeg') throw new Exception; //skip it for audio files $m = $this->getDi()->videoTable->load($this->getDi()->config->get('video_non_member')); $media = $m; $this->view->media = $this->getSignedLink($m); $this->view->mime = $m->mime; } catch (Exception $e) { $this->view->error = ___("You must be logged-in to open this media"); $this->view->link = $this->getDi()->url("login",null,false); } } elseif (!$guestAccess && !$media->hasAccess($this->getDi()->user)) { try { if ($media->mime == 'audio/mpeg') throw new Exception; //skip it for audio files $m = $this->getDi()->videoTable->load($this->getDi()->config->get('video_not_proper_level')); $media = $m; $this->view->media = $this->getSignedLink($m); $this->view->mime = $m->mime; } catch (Exception $e) { $this->view->error = ___("Your subscription does not allow access to this media"); if(!empty($media->no_access_url)) $this->view->link = $media->no_access_url; else $this->view->link = $this->getDi()->url('no-access/content', array('id'=>$media->pk(),'type'=> $media->getTable()->getName(true))); } } else { $this->view->media = $this->getSignedLink($media); $this->view->mime = $media->mime; } if ($poster_id = $media->poster_id ?: (isset($config['poster_id']) ? $config['poster_id'] : "")) { $poster = $this->getDi()->uploadTable->load($poster_id, false); $this->view->poster = $poster ? $this->getDi()->url('upload/get/' . preg_replace('/^\./', '', $poster->path),null,false) : ''; } else { $this->view->poster = ''; } unset($params['poster_id']); $this->view->playerParams = $params; $this->view->isSecure = $this->getRequest()->isSecure(); return $this->view->render('_media.'. strtolower($this->getDi()->config->get('video_player', 'flowplayer')).'.phtml'); } function jsAction() { $this->_response->setHeader('Content-type', 'text/javascript'); $this->getMedia(); echo $this->renderJs(); } }PK\7A}}9default/controllers/AdminResourceCategoriesController.phpnu[getDi()->resourceCategoryTable; } protected function getTitle() { return ___('Content Categories'); } } PK\U'default/controllers/IndexController.phpnu[getDi()->config->get('index_page'); if ($index_page == -1) { $this->_response->redirectLocation($this->getDi()->url('login',null,false)); } if(!$this->getDi()->auth->getUserId()) $this->getDi()->auth->checkExternalLogin($this->getRequest()); if($this->getDi()->auth->getUserId() && $this->getDi()->config->get('skip_index_page')) $this->_response->redirectLocation($this->getDi()->url('member',null,false)); try { $p = $this->getDi()->pageTable->load($index_page); echo $p->render($this->view, $this->getDi()->auth->getUserId() ? $this->getDi()->auth->getUser() : null); } catch (Exception $e) { $this->view->display("index.phtml"); } } } PK\X2&default/controllers/CronController.phpnu[db_drupal = $db; $this->paysys_id = $paysys_id; } function process(User $user, array $payments) { $this->user = $user; foreach ($payments as $p) { $this->payments[$p['pid']] = $p; } $this->groupByInvoice(); $this->beforeWork(); return $this->doWork(); } function beforeWork() { } abstract function doWork(); static function factory($paysys_id, DbSimple_Interface $db) { $class = 'InvoiceCreator_' . ucfirst(toCamelCase($paysys_id)); if (class_exists($class, false)) return new $class($paysys_id, $db); else throw new Exception(sprintf('Unknown Payment System [%s]', $paysys_id)); } protected function _translateProduct($pid) { static $cache = array(); if (empty($cache)) { $cache = Am_Di::getInstance()->db->selectCol(" SELECT `value` as ARRAY_KEY, `id` FROM ?_data WHERE `table`='product' AND `key`='dms:id'"); } return @$cache[$pid]; } } class InvoiceCreator_Standard extends InvoiceCreator_Abstract { function doWork() { $user = $this->user; foreach ($this->groups as $oid => $list) { // Create new invoice; $invoice = $this->getDi()->invoiceRecord; $invoice->user_id = $this->user->pk(); foreach ($this->db_drupal->selectPage($total, "select pid, qty from ?_ms_order_products op left join ?_ms_products_plans p on op.id = p.sku where oid=?", $oid) as $row) { $invoice->add($product = $this->getDi()->productTable->findFirstByData('dms:id', $row['pid']), $row['qty']); } $invoice->calculate(); $invoice->tm_added = date('Y-m-d H:i:s', $list[0]['order_created']); $invoice->tm_started = date('Y-m-d H:i:s', $list[0]['created']); $invoice->public_id = $list[0]['order_key']; switch ($list[0]['gateway']) { case "ms_paypal_wps" : $invoice->paysys_id = 'paypal'; break; default : $invoice->paysys_id = 'free'; } switch ($list[0]['order_status']) { case 'completed': $invoice->status = Invoice::PAID; break; case 'active' : $invoice->status = Invoice::RECURRING_ACTIVE; break; case 'cancelled' : $invoice->status = Invoice::RECURRING_CANCELLED; $invoice->tm_cancelled = date('Y-m-d H:i:s', $list[0]['order_modified']); break; default : $invoice->status = Invoice::PENDING; break; } $invoice->data()->set('dms:id', $oid); $invoice->insert(); foreach ($list as $rec) { switch ($rec['type']) { case 'cart' : case 'rec_signup' : case 'rec_payment' : if ($rec['amount'] > 0) { // Add payment record; $payment = $this->getDi()->invoicePaymentRecord; $payment->amount = $rec['amount']; $payment->currency = $rec['currency']; $payment->dattm = date('Y-m-d H:i:s', $rec['created']); $payment->invoice_id = $invoice->pk(); $payment->paysys_id = $invoice->paysys_id; $payment->receipt_id = $rec['transaction']; $payment->transaction_id = sprintf('import-%s', $payment->receipt_id); $payment->user_id = $user->pk(); $payment->insert(); } else { $payment = null; } // Insert Access; $access = $this->getDi()->accessRecord; $access->user_id = $user->pk(); $access->setDisableHooks(); $access->begin_date = date('Y-m-d', $rec['created']); $p = new Am_Period($invoice->first_period); $access->expire_date = $p->addTo($access->begin_date); $access->invoice_id = $invoice->pk(); if (!is_null($payment)) $access->invoice_payment_id = $payment->pk(); $access->product_id = $product->pk(); $access->insert(); break; case 'refund' : $refund = $this->getDi()->invoiceRefundRecord; $refund->invoice_id = $invoice->pk(); $refund->user_id = $user->pk(); $refund->paysys_id = $invoice->paysys_id; $refund->receipt_id = $refund->transaction_id = $rec['transaction']; $refund->dattm = date('Y-m-d H:i:s', $rec['created']); $refund->currency = $rec['currency']; $refund->amount = $rec['amount']; $refund->insert(); break; } } } $this->user->checkSubscriptions(); } public function groupByInvoice() { foreach ($this->payments as $p) { $this->groups[$p['oid']][] = $p; } } } abstract class Am_Import_Abstract extends Am_BatchProcessor { /** @var DbSimple_Mypdo */ protected $db_drupal; protected $options = array(); /** @var Zend_Session_Namespace */ protected $session; public function __construct(DbSimple_Interface $db_drupal, array $options = array()) { $this->db_drupal = $db_drupal; $this->options = $options; $this->session = new Zend_Session_Namespace(get_class($this)); parent::__construct(array($this, 'doWork')); $this->init(); } public function init() { } public function run(&$context) { $ret = parent::run($context); if ($ret) $this->session->unsetAll(); return $ret; } /** @return Am_Di */ public function getDi() { return Am_Di::getInstance(); } abstract public function doWork(& $context); } class Am_Import_Product3 extends Am_Import_Abstract { public function doWork(&$context) { $importedProducts = $this->getDi()->db->selectCol("SELECT `value` FROM ?_data WHERE `table`='product' AND `key`='dms:id'"); $q = $this->db_drupal->queryResultOnly("SELECT * FROM ?_ms_products_plans"); while ($r = $this->db_drupal->fetchRow($q)) { if (in_array($r['pid'], $importedProducts)) continue; $rs = unserialize($r['recurring_schedule']); $r['data'] = unserialize($r['data']); $context++; $p = $this->getDi()->productRecord; $p->title = $r['name']; $p->description = $r['description']; $p->sort_order = $r['weight']; $p->data()->set('dms:id', $r['pid']); $p->insert(); $bp = $p->createBillingPlan(); $bp->title = 'default'; if ($r['cart_type'] == 'recurring') { $bp->first_price = $rs['has_trial'] ? $rs['trial_amount'] : $rs['main_amount']; $bp->first_period = $rs['has_trial'] ? strtolower($rs['trial_length'] . $rs['trial_unit']) : strtolower($rs['main_length'] . $rs['main_unit']); $bp->second_price = $rs['main_amount']; $bp->second_period = strtolower($rs['main_length'] . $rs['main_unit']); $bp->rebill_times = $rs['total_occurrences'] ? $rs['total_occurrences'] : IProduct::RECURRING_REBILLS; } else { // not recurring $bp->first_price = $rs['main_amount']; $bp->first_period = $rs['main_length'] ? $rs['main_length'] . strtolower($rs['main_unit']) : Am_Period::MAX_SQL_DATE; $bp->rebill_times = 0; } $bp->insert(); } return true; } } class Am_Import_User3 extends Am_Import_Abstract { function doWork(& $context) { //$crypt = $this->getDi()->crypt; $maxImported = (int) $this->getDi()->db->selectCell("SELECT `value` FROM ?_data WHERE `table`='user' AND `key`='dms:id' ORDER BY `id` DESC LIMIT 1"); $count = @$this->options['count']; if ($count) $count -= $context; if ($count < 0) return true; $q = $this->db_drupal->queryResultOnly("SELECT * FROM ?_users WHERE uid > ?d ORDER BY uid {LIMIT ?d} ", $maxImported, $count ? $count : DBSIMPLE_SKIP); while ($r = $this->db_drupal->fetchRow($q)) { if (!$this->checkLimits()) return; $u = $this->getDi()->userRecord; $u->email = $r['mail']; $u->added = date('Y-m-d H:i:s', $r['created']); $u->login = $r['name']; $u->is_approved = 1; $u->data()->set('dms:id', $r['uid']); $u->data()->set('signup_email_sent', 1); // do not send signup email second time $u->data()->set(Am_Protect_Databased::USER_NEED_SETPASS, 1); $u->generatePassword(); try { $u->insert(); $savedPass = $this->getDi()->savedPassRecord; $savedPass->user_id = $u->pk(); $savedPass->format = 'drupal'; $savedPass->pass = $r['pass']; $savedPass->salt = null; $savedPass->save(); $this->insertPayments($r['uid'], $u); $context++; } catch (Am_Exception_Db_NotUnique $e) { echo "Could not import user: " . $e->getMessage() . "
      \n"; } } return true; } function insertPayments($id, User $u) { $payments = $this->db_drupal->select(" select p.*, o.created as order_created, o.order_key as order_key, o.status as order_status, o.modified as order_modified from ?_ms_payments p left join ?_ms_orders o using(oid) where o.uid = ? order by p.pid desc", $id); $payments = $payments ? $payments : array(); //to add access if exists InvoiceCreator_Abstract::factory('standard', $this->db_drupal)->process($u, $payments); } } class AdminImportDrupalMsController extends Am_Mvc_Controller { /** @var Am_Form_Admin */ protected $dbForm; /** @var DbSimple_Mypdo */ protected $db_drupal; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Auth_Admin::PERM_SUPER_USER); } function indexAction() { Am_Mail::setDefaultTransport(new Am_Mail_Transport_Null()); if ($this->_request->get('start')) { $this->getSession()->drupal_db = null; $this->getSession()->drupal_import = null; } elseif ($this->_request->get('import_settings')) { $this->getSession()->drupal_import = null; } if (!$this->getSession()->drupal_db) return $this->askDbSettings(); $this->db_drupal = Am_Db::connect($this->getSession()->drupal_db); if (!$this->getSession()->drupal_import) return $this->askImportSettings(); // disable ALL hooks $this->getDi()->hook = new Am_Hook($this->getDi()); $done = $this->_request->getInt('done', 0); $importSettings = $this->getSession()->drupal_import; $import = $this->_request->getFiltered('i', $importSettings['import']); $class = "Am_Import_" . ucfirst($import) . "3"; $importer = new $class($this->db_drupal, (array) @$importSettings[$import]); if ($importer->run($done) === true) { $this->view->title = ucfirst($import) . " Import Finished"; $this->view->content = "$done records imported from Drupal Membership Script"; $this->view->content .= "

      Continue to import other information"; $this->view->content .= "

      Do not forget to >Rebuild Db after all import operations are done."; $this->view->display('admin/layout.phtml'); $this->getSession()->drupal_import = null; } else { $this->redirectHtml($this->getDi()->url("admin-import-drupal-ms",array('done'=>$done,'i'=>$import),false), "$done records imported"); } } function askImportSettings() { $this->form = $this->createImportForm($defaults); $this->form->addDataSource($this->_request); if (!$this->form->isSubmitted()) $this->form->addDataSource(new HTML_QuickForm2_DataSource_Array($defaults)); if ($this->form->isSubmitted() && $this->form->validate()) { $val = $this->form->getValue(); if (@$val['import']) { $this->getSession()->drupal_import = array( 'import' => $val['import'], 'user' => @$val['user'], ); $this->_redirect('admin-import-drupal-ms'); return; } } $this->view->title = "Import Drupal Membership Script Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } function createImportForm(& $defaults) { $form = new Am_Form_Admin; /** count imported */ $imported_products = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='product' AND `key`='dms:id'"); $total = $this->db_drupal->selectCell("SELECT COUNT(*) FROM ?_ms_products_plans"); if ($imported_products >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_products of $total)"); } else { $cb = $form->addRadio('import', array('value' => 'product')); } $cb->setLabel('Import Products'); if ($imported_products) { $imported_users = $this->getDi()->db->selectCell("SELECT COUNT(id) FROM ?_data WHERE `table`='user' AND `key`='dms:id'"); $total = $this->db_drupal->selectCell("SELECT COUNT(*) FROM ?_users"); if ($imported_users >= $total) { $cb = $form->addStatic()->setContent("Imported ($imported_users)"); } else { $cb = $form->addGroup(); if ($imported_users) $cb->addStatic()->setContent("partially imported ($imported_users of $total total)

      "); $cb->addRadio('import', array('value' => 'user')); $cb->addStatic()->setContent('

      # of users (keep empty to import all) '); $cb->addInteger('user[count]'); } $cb->setLabel('Import User and Payment Records'); } $form->addSaveButton('Run'); $defaults = array( //'user' => array('start' => 5), ); return $form; } function askDbSettings() { $this->form = $this->createMysqlForm(); if ($this->form->isSubmitted() && $this->form->validate()) { $this->getSession()->drupal_db = $this->form->getValue(); $this->_redirect('admin-import-drupal-ms'); } else { $this->view->title = "Import Drupal Membership Script Information"; $this->view->content = (string) $this->form; $this->view->display('admin/layout.phtml'); } } /** @return Am_Form_Admin */ function createMysqlForm() { $form = new Am_Form_Admin; $el = $form->addText('host')->setLabel('Drupal MySQL Hostname'); $el->addRule('required', 'This field is required'); $form->addText('user')->setLabel('Drupal MySQL Username') ->addRule('required', 'This field is required'); $form->addPassword('pass')->setLabel('Drupal MySQL Password'); $form->addText('db')->setLabel('Drupal MySQL Database Name') ->addRule('required', 'This field is required'); $form->addText('prefix')->setLabel('Drupal Tables Prefix'); $dbConfig = $this->getDi()->getParameter('db'); $form->addDataSource(new HTML_QuickForm2_DataSource_Array(array( 'host' => $dbConfig['mysql']['host'], 'user' => $dbConfig['mysql']['user'], 'prefix' => '', ))); $el->addRule('callback2', '-', array($this, 'validateDbConnect')); $form->addSubmit(null, array('value' => 'Continue...')); return $form; } function validateDbConnect() { $config = $this->form->getValue(); try { $db = Am_Db::connect($config); if (!$db) return "Check database settings - could not connect to database"; $db->query("SELECT * FROM ?_ms_orders LIMIT 1"); } catch (Exception $e) { return "Check database settings - " . $e->getMessage(); } } }PK\r 'altijd', ' from ' => 'van', ' to ' => 'tot', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" kan alleen besteld worden in combinatie met deze product(en)/abonnement(en): %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" kan alleen worden besteld wanneer je verlopen abonnement(en) hebt voor deze producten: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" kan niet worden besteld want je hebt al een actief(e) abonnement(en) voor: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" kan niet worden besteld want je hebt een verlopen abonnement(en) voor: %s', '%d-th day' => '%d-e dag', '%s MySQL Hostname' => '%s MySQL Hostnaam', '%s MySQL Password' => '%s MySQL Wachtwoord', '%s MySQL Username' => '%s MySQL Gebruikersnaam', '%s database and tables prefix' => '%s prefix voor database en tabellen', 'API Authentication Information' => 'API Authenticatie-informatie', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Accepteer Rechtstreekse Betalingen betalingen verwerken op betaalsysteem (zonder eerst voor aMember aan te melden)', 'Access' => 'Toegang', 'Access Denied' => 'Toegang Geweigerd', 'Access Log' => 'Toegangslogboek', 'Access Permissions' => 'Toegangpermissies', 'Actions' => 'Acties', 'Active' => 'Actief', 'Active Resources' => 'Actieve Bronnen', 'Active Subscriptions' => 'Actieve Abonnementen', 'Active Users' => 'Active Gebruikers', 'Active subusers' => 'Actieve subgebruikers', 'Add "Like" button' => 'Toevoegen "Like" button', 'Add New Notification Rule' => 'Voeg een nieuwe kennisgevingsregel toe', 'Add User' => 'Gebruiker Toevoegen', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Ken beloningspunten toe aan doorverwijzende affiliate voor dit product (extra in te stellen op aMember CP -> Setup -> Beloningspunten)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Ken beloningspunten toe aan gebruikers die dit product kopen (extra in te stellen op aMember CP -> Setup -> Beloningspunten)', 'Add to Basket' => 'Toevoegen aan mandje', 'Add/Renew Subscription' => 'Abonnement Toevoegen/Vernieuwen', 'Added' => 'Toegevoegd', 'Additional Fields' => 'Extra Velden', 'Address Info' => 'Adresinformatie', 'Address Information' => 'Adresinformatie', 'Admin' => 'Beheerder', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Beheer Groepen aMember zal nooit de %s accounts bewerken die toegewezen zijn aan de volgende groepen. Dit beschermt %s accounts tegen elke aMember activiteit', 'Admin Username' => 'Beheerder Gebruikersnaam', 'Administrator' => 'Beheerder', 'Advanced' => 'Geavanceerd', 'Advanced Search' => 'Geavanceerd Zoeken', 'Advertise our website to your friends and earn money' => 'Adverteer onze website bij je vrienden en verdien geld', 'Affiliate' => 'Affiliate', 'Affiliate Agreement' => 'Affiliate-overeenkomst', 'Affiliate Clicks' => 'Affliateklikken', 'Affiliate Id#' => 'Affiliate ID#', 'Affiliate Info' => 'Affiliate-informatie', 'Affiliate Payout - Paypal E-Mail address' => 'Affiliate-uitbetaling - Paypay e-mailadres', 'Affiliate Payout Type' => 'Affiliate betaalwijze', 'Affiliate Program' => 'Affliateprogramma', 'Affiliate Sales' => 'Affiliateverkopen', 'Affiliate Signup Form' => 'Affiliate aanmeldformulier', 'Affiliate info' => 'Affiliate-informatie', 'Affiliate stats' => 'Affiliatestatistieken', 'Affiliates' => 'Affiliates', 'All' => 'Alle', 'All %s records on this page are selected' => 'Alle %s velden op deze pagina zijn gekozen', 'All Affiliates' => 'Alle Affiliates', 'All Time' => 'Alles', 'All Users' => 'Alle Gebruikers', 'All records' => 'Alle velden', 'Amazon S3 storage is not configured' => 'Amazon S3 storage is niet geconfigureerd', 'Amount' => 'Bedrag', 'An Error has occurred' => 'Een fout heeft plaatsgevonden', 'An account with the same email [%s] is already exists.' => 'Een account met hetzelfde e-mail [%s] bestaat reeds.', 'An account with the same email already exists.' => 'Een account met hetzelfde e-mailadres bestaat al.', 'An error occurred while handling your payment.' => 'Er is een fout opgetreden tijdens de behandeling van je betaling.', 'An internal error happened in the script, please contact webmaster for details' => 'In het script heeft een interne fout plaatsgevonden, neem s.v.p. contact op met de beheerder voor details.', 'Any Product' => 'Ieder Product', 'Any product' => 'Elk product', 'Api Key' => 'Api Sleutel', 'Apply' => 'Toepassen', 'Apply Filter' => 'Toepassen Filter', 'Assigned to usergroup' => 'Toegewezen aan gebruikersgroep', 'Attachments' => 'Bijlagen', 'Authentication' => 'Authenticatie', 'Authentication problem, please contact website administrator' => 'Authenticatie probleem, neem contact op met de website beheerder', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Gebruikers automatisch aanmelden voor lijst als deze eenmaal voor hen beschikbaar komt', 'Available Bricks (drag to left to add)' => 'Beschikbare Bouwstenen (naar links slepen om toe te voegen)', 'Available Credits' => 'Beschikbaar Krediet', 'Awaiting Admin Response' => 'Wachtend op Beheerders Respons', 'Awaiting User Response' => 'Wachtend op Gebruikers Respons', 'Aweber Application' => 'Aweber Applicatie', 'Back' => 'Terug', 'Bank Code' => 'Bankcode', 'Bank Identification' => 'Bank identificatie', 'Bank Name' => 'Bank naam', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Verbannen Groepen aMember zal nooit de %s accounts bewerken die toegewezen zijn aan de volgende groepen. Dit beschermt %s accounts tegen elke aMember activiteit', 'Banners and Links' => 'Banners en links', 'Banners and Text Links' => 'Beheer banners en text links', 'Begin Date' => 'Begindatum', 'Both Affiliate and member' => 'Zowel affiliate als gebruiker', 'CC Demo' => 'CC Demonstratie', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF beschermfout - formulier moet binnen %d minuten na vertoning verzonden worden, herhaal nogmaals', 'Can view/edit customer Credit Card information and rebills' => 'Kan creditcard informatie en perodieke betalingen van de klant zien/bewerken', 'Cancel' => 'Annuleer', 'Cancel Subscription' => 'Annuleer Abonnement', 'Cancelled' => 'Geannuleerd', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Kan de GRATIS betaalplugin niet gebruiken met het product dat meer dan 0.0 kost', 'Cannot validate VAT Id, please try again' => 'Kan BTW-Id niet bevestigen, probeer opnieuw', 'Category' => 'Categorie', 'Change' => 'Veranderen', 'Change Password' => 'Wachtwoord Wijzigen', 'Change Password/Edit Profile' => 'Wachtwoord wijzigen / Profiel bewerken', 'Change Subscription' => 'Abonnement wijzigen', 'Change Username' => 'Verander Gebruikersnaam', 'Change payout info' => 'Wijzig uitbetaalinformatie', 'Checkout' => 'Betalen', 'Checkout error: ' => 'Fout bij betalen:', 'Choose a Password must be %d or more characters' => 'Kies een wachtwoord moet bestaan uit meer dan %d karakters', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Kies een gebruikersnaam dient te bestaan uit meer dan %d karakters en mag alleen letters, getallen en underscores bevatten', 'City' => 'Plaats', 'Click "Continue" to pay this order using stored credit card %s' => 'Klik "Doorgaan" om deze bestelling te betalen m.b.v. opgeslagen creditcard %s', 'Click button to continue' => 'Klik op de knop om door te gaan', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Klik hier als je niet langer wilt wachten (of als je browser je niet automatisch doorstuurd).', 'Click to Edit' => 'Klik om bij te werken', 'Clicks' => 'Klikken', 'Clicks/Sales Statistics' => 'Affiliateklikken / verkoopstatistieken', 'Close' => 'Sluiten', 'Close Ticket' => 'Ticket Sluiten', 'Closed' => 'Gesloten', 'Code' => 'Code', 'Comment' => 'Commentaar', 'Comment for admin reference' => 'Commentaar voor beheersdoeleinden', 'Commission' => 'Provisie', 'Commissions' => 'Provisie', 'Configuration' => 'Configuratie', 'Configured Tax Values' => 'Geconfigureerde Belastingwaarden', 'Confirm New Password' => 'Bevestiging nieuw wachtwoord', 'Confirm Password' => 'Bevestig je wachtwoord', 'Confirm Payment' => 'Bevestig betaling', 'Confirm Your E-Mail Address' => 'Bevestig Je E-mailadres', 'Confirm Your Password' => 'Bevestig je wachtwoord', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Bevestigingslink is verzonden naar je e-mailadres. Controleer je mailbox. Als je binnen 5 minuten geen e-mail hebt ontvangen, controleer dan ook de \'Spam\' map - ons bericht zou per ongeluk voor spam aangezien kunnen zijn.', 'Content' => 'Inhoud', 'Continue' => 'Doorgaan', 'Conversation' => 'Conversatie', 'Copy of' => 'Kopie van', 'Count of signups' => 'Aantal aanmeldingen', 'Count of user signups' => 'Aantal gebruikers aanmeldingen', 'Country' => 'Land', 'Coupon' => 'Kortingscode', 'Coupon Code' => 'Couponcode', 'Coupon Discount' => 'Kortingsbon', 'Coupon code disabled' => 'Coupon code uitgeschakeld', 'Coupon code expired' => 'Coupon code is verlopen', 'Coupon is not yet active' => 'Coupon is nog niet geldig', 'Coupon usage limit exceeded' => 'Gebruikslimiet coupon verlopen', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'aMember Gebruikers Aanmaken Door Eis stilzwijgend klanten aanmaken in aMember als gebruiker probeert in te loggen op aMember met dezelfde gebruikersnaam en wachtwoord als voor %s', 'Credit Card Code' => 'Creditcard code', 'Credit Card Info' => 'Creditcard info', 'Credit Card Number' => 'creditcardnummer', 'Credit Card Rebills' => 'Periodieke betalingen via creditcard', 'Credit Cards' => 'Creditcards', 'Credits' => 'Credits', 'Currency' => 'Valuta', 'Currency Exchange Rates' => 'Wisselkoersen', 'Current password entered incorrectly, please try again' => 'Huidige wachtwoord onjuist ingevoerd, probeer het nogmaals', 'Custom Commission' => 'Aangepaste provisie', 'Customer account has been automatically locked.' => 'Gebruikersaccount is automatisch vergrendeld.', 'Customize' => 'Aanpassen', 'DONE' => 'KLAAR', 'Dashboard' => 'Dashboard', 'Data Integrity Code' => 'Data Integriteit Code', 'Date' => 'Datum', 'Date and time of payment: %s' => 'Datum en tijd van betaling: %s', 'Date must be in format %s' => 'Datum moet zijn in de vorm %s', 'Date/Time' => 'Datum/Tijd', 'Date: ' => 'Datum:', 'Day' => 'Dag', 'Days' => 'Dagen', 'Deactivate Student' => 'Deactiveer Student', 'Deactivate User' => 'Gebruiker uitschakelen', 'Debit Card Number' => 'Debitcardnummer', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Standaard Niveau standaard niveau - gebruiker wordt gereset naar dit toegangsniveau als er geen actieve abonnementen bestaan (bijvoorbeeld: alle abonnementen zijn verlopen)', 'Delete' => 'Verwijderen', 'Delete %s' => 'Verwijderen %s', 'Delivery Time' => 'Levertijd', 'Description' => 'Omschrijving', 'Digits only please' => 'Alleen getallen s.v.p.', 'Disable online VAT Id Validation' => 'Uitschakelen online BTW-Id Bevestiging', 'Disabled' => 'Uitgeschakeld', 'Discard' => 'Negeren', 'Discount' => 'Korting', 'Display Type' => 'Type Afbeelding', 'Display in 2 rows' => 'Vertoon in 2 rijen', 'Do Import' => 'Import Uitvoeren', 'Do not add to Login Form' => 'Niet toevoegen aan Loginformulier', 'Do not add to Signup Form' => 'Niet toevoegen aan Aanmeldformulier', 'Do you really want to %s %s %s records' => 'Doorgaan met het %s van %s %ssrecord(s)?', 'Do you really want to %s?' => 'Weet je zeker dat je %s?', 'Do you really want to cancel subscription?' => 'Weet je zeker dat je je abonnement wilt annuleren?', 'Do you really want to delete record?' => 'Weet je zeker dat je dit record wil verwijderen?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Wilt je je echt afmelden voor %s periodieke berichten?', 'Done' => 'Klaar', 'Donee name' => 'Naam van de ontvanger', 'Download' => 'Download', 'Download limit exceeded for this file' => 'Download limiet overschreden voor dit bestand', 'Downloaded on your own server' => 'Gedownload van je eigen server', 'E-Mail' => 'E-mail', 'E-Mail Address' => 'E-mailadres', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'E-mailadres en E-mailadres Ter Bevestiging zijn verschillend. Vul deze opnieuw in.', 'E-Mail Format' => 'E-mailformaat', 'E-Mail Messages' => 'E-mailberichten', 'E-Mail Verification' => 'E-mailverificatie', 'EU VAT' => 'EU Belasting', 'EU VAT ID: ' => 'EU BTW-ID:', 'EU VAT Id (optional)' => 'EU BTW-Id (optioneel)', 'Edit' => 'Bewerken', 'Edit %s' => '%s Bewerken', 'Edit Brick Labels' => 'Labels Bewerken', 'Edit Categories' => 'Categorieën Bewerken', 'Edit E-Mail Template' => 'Bewerk E-mailsjabloon', 'Email' => 'E-mail', 'Email Subject' => 'E-mailonderwerp', 'Email [%s] is not valid' => 'E-mail [%s] is ongeldig', 'Email admin regarding account sharing' => 'E-mail beheerder betreffende het delen van account', 'Email user regarding account sharing' => 'E-mail gebruiker betreffende het delen van account', 'Empty response from Sagepay server' => 'Lege respons van Sagepay server', 'Enabled Modules' => 'Ingeschakelde Modules', 'End' => 'Einde', 'End Date' => 'Einddatum', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => 'Veel plezier met je lidmaatschap. Klik %shier%s voor toegang tot je ledenpagina.', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Veel plezier met je lidmaatschap. Klik hier om in te loggen %sLogin%s', 'Enter coupon code' => 'Invoeren couponcode', 'Enter gift voucher code' => 'Invoeren cadeauboncode', 'Error 404 - Not Found' => 'Fout 404 - Niet Gevonden', 'Error : upload folder [%s] does not exists' => 'Error : uploadmap [%s] bestaat niet', 'Error from Storage Engine' => 'Fout van opslagmotor', 'Error happened during payment process. ' => 'Fout opgetreden tijdens betaalproces', 'Error happened during transaction handling. Please contact website administrator' => 'Fout plaatsgevonden tijdens de transactieverwerking. Neem contact op met de websitebeheerder', 'European (A4)' => 'Europees (A4)', 'Exact' => 'Exact', 'Expire Date' => 'Vervaldatum', 'Expired' => 'Verlopen', 'Expired Users' => 'Verlopen Gebruikers', 'Expires' => 'Verloopt', 'Export' => 'Exporteren', 'Export Format' => 'Export Formaat', 'FaceBook App ID' => 'FaceBook App ID', 'FaceBook Application' => 'Facebook Applicatie', 'Facebook App Secret' => 'Facebook App Secret', 'Features' => 'Kenmerken', 'Field' => 'Veld', 'Field Type' => 'Veldtype', 'Field Updated' => 'Veld bijgewerkt', 'Fields To Display' => 'Te Vertonen Velden ', 'Fields To Export' => 'Te Exporteren Velden', 'Fieldset' => 'Veldset', 'Fieldset title' => 'Veldset titel', 'File' => 'Bestand', 'File Downloads' => 'Bestanden Downloads', 'File Storage' => 'Bestandsopslag', 'File should contain CSV list of user records for import in the following format:
      %s' => 'Bestand zou CSV lijst met gebruikersrecords moeten bevatten om in het volgende formaat te importeren:
      %s', 'Filename' => 'Bestandsnaam', 'Files' => 'Bestanden', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'Bestanden opgeslagen bij Amazon S3. (waarschuwing: Je buckets dienen in de naam géén hoofdletters te bevatten)', 'Files uploaded via aMember web interface' => 'Bestanden geupload via aMember web interface', 'Filter' => 'Filter', 'First & Last Name' => 'Voor- en achternaam', 'First Name' => 'Voornaam', 'Folder %s (%s)' => 'Map %s (%s)', 'Folders' => 'Mappen', 'Form Page Break' => 'Formulier Pagina-einde', 'Free' => 'Gratis', 'Free Access' => 'Gratis toegang', 'Free Access without log-in' => 'Gratis toegang zonder inloggen', 'From' => 'Van', 'GST (Inclusive Tax)' => 'GST (inclusief belasting)', 'Get Password' => 'Wachtwoord Opvragen', 'Gift Voucher' => 'Cadeaubon', 'Gift Vouchers' => 'Cadeaubon', 'Global Commission' => 'Algemene Provisie', 'Global Tax' => 'Belasting Wereldwijd', 'Groups' => 'Groepen', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'Groepen Prioriteit je kunt groepen slepen en neerzetten om ze te sorteren. als er meerdere groepen beschikbaar zijn voor een gebruiker, dan zal aMember groepen als "eerste" kiezen die hoger in deze lijst staan.', 'HTML Code that will be displayed' => 'HTML code die zal worden vertoond', 'HTML Message' => 'HTML Bericht', 'HTML text' => 'HTML tekst', 'Having Active Subscription To:' => 'Heeft Actief Abonnement Op:', 'Having Expired Subscription To:' => 'Heeft Verlopen Abonnement Op:', 'Helpdesk' => 'Helpdesk', 'Hide do not display this item link in members area' => 'Verbergen vertoon dit itemlink niet in lidmaatschapgedeelte', 'Hosted at Activecampaing\'s server' => 'Gehost bij ActiveCampaign\'s server', 'Housenumber' => 'Huisnummer', 'IP Address' => 'IP Adres', 'If you already have an account on our website, please %slog in%s to continue' => 'Heb je voor onze website al een account, dan graag eerst %sinloggen%s alvorens verder te gaan.', 'If you are a registered member, please %slogin%s' => 'Ben je een geregistreerde gebruiker, dan kun je hier %sinloggen%s', 'If you are not registered yet, please %ssignup%s' => 'Ben je nog geen geregistreerde gebruiker, dan graag eerst %saanmelden%s', 'Income Report - payments minus refunds' => 'Inkomstenrapportage - betalingen vermindert met teruggaves', 'Incorrect Parent Affiliate ID' => 'Onjuist Parent Affiliate ID', 'Insert comment into email' => 'Opmerking in de e-mail voegen', 'Integer Value' => 'Geheel getal waarde', 'Integer value required' => 'Geheel getal vereist', 'Integration' => 'Integratie', 'Integrations' => 'Integraties', 'Internal Error' => 'Interne Fout', 'Invalid Account Number' => 'Ongeldig rekeningnummer', 'Invalid Credit Card Number' => 'Ongeldig creditcardnummer', 'Invalid Debit Card Number' => 'Ongeldig Debitcardnummer', 'Invalid Expiration Date - Month' => 'Ongeldige vervaldatum - veld maand', 'Invalid Expiration Date - Year' => 'Ongeldige vervaldatum - veld jaar', 'Invalid Issue Number' => 'Ongeldig uitgiftenummer', 'Invalid Routing Number' => 'Ongeldig Routingnummer', 'Invalid VAT Id, please try again' => 'Ongeldige BTW-Id, probeer opnieuw', 'Invoice' => 'Factuur', 'Invoice Number: ' => 'Factuurnummer:', 'Invoice not found' => 'Factuur niet gevonden', 'Is Gift Voucher?' => 'Is het een cadeaubon?', 'Is Locked' => 'Is Geblokkeerd', 'Is Paid?' => 'Is Betaald?', 'Is Send At Later Date?' => 'Is het een \'verstuur op later moment\'?', 'Is Disabled?' => 'Is Uitgeschakeld?', 'Item' => 'Item', 'Label' => 'Label', 'Language' => 'Taal', 'Last 14 Days' => 'Afgelopen 14 dagen', 'Last 30 Days' => 'Laatste 30 dagen', 'Last 7 Days' => 'Afgelopen 7 dagen', 'Last Business Week (Mon-Fri)' => 'Afgelopen arbeidsweek (ma-vr)', 'Last Messages in Helpdesk' => 'Laatste berichten in helpdesk', 'Last Month' => 'Vorige maand', 'Last Name' => 'Achternaam', 'Last Week (Mon-Sun)' => 'Verleden week (ma-zo)', 'Last Week (Sun-Sat)' => 'Verleden week (zo-za)', 'Leads' => 'Leads', 'License Key' => 'Licentiesleutel', 'Lifetime' => 'Levensduur', 'Like Url' => 'Like Url', 'Link' => 'Link', 'Links' => 'Links', 'Live Edit %s' => 'Nu bewerken %s', 'Loading' => 'Laden...', 'Log In' => 'Inloggen', 'Log all API Requests' => 'Leg alle API verzoeken vast', 'Login' => 'Login', 'Login as User' => 'Login als Gebruiker', 'Logout' => 'Uitloggen', 'Lost Password Sending Error' => 'Fout tijdens Versturen Zoekgeraakt Wachtwoord', 'Lost Password Sent' => 'Zoekgeraakt wachtwoord verzonden', 'Lost password?' => 'Wachtwoord vergeten', 'Mail Queue' => 'Mail Wachtrij', 'Make Payment' => 'Nu Betalen', 'Make a Donation' => 'Doe een donatie', 'Make donation recurring' => 'Maak donatie terugkerend', 'Manage Newsletters' => 'Beheren Nieuwsbrieven', 'Marketing Materials' => 'Marketingmaterialen', 'Members Directory' => 'Ledenmap', 'Members Directory [%s] does not exists' => 'Ledenmap [%s] bestaat niet', 'Membership Type' => 'Abonnementtype', 'Merchant Key' => 'Merchant Key', 'Merchant Secret' => 'Merchant Secret', 'Message' => 'Bericht', 'Message can not be empty' => 'Bericht kan niet leeg zijn', 'Moip Payment' => 'Moip Betaling', 'Month' => 'Maand', 'Months' => 'Maanden', 'Multiplier' => 'Factor', 'My Country' => 'Mijn Land', 'NEVER' => 'NOOIT', 'Name' => 'Naam', 'Never' => 'Nooit', 'New' => 'Nieuw', 'New %s' => 'Nieuwe %s', 'New Password' => 'Nieuw Wachtwoord', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Nieuw wachtwoord je kunt hier een nieuw wachtwoord kiezen of deze ongewijzigd laten (het dient te bestaan uit minstens %d karakters)', 'Newsletter' => 'Nieuwsbrief', 'Newsletter Subscriptions' => 'Nieuwsbrief Abonnementen', 'Next' => 'Volgende', 'No' => 'Nee', 'No commissions on this date' => 'Geen provisies op deze datum', 'No coupons found with such coupon code' => 'Geen coupons gevonden met deze coupon code', 'No gift vouchers found with such code' => 'Geen cadeaubonnen gevonden met een dergelijke code', 'No items in this section' => 'Geen items in deze sectie', 'No items selected for purchase' => 'Er zijn geen producten gekozen om te kopen', 'No records found' => 'Geen resultaten gevonden', 'No, cancel' => 'Nee, annuleer', 'No, keep me subscribed' => 'Nee, ik wil ingeschreven blijven', 'No, please keep me subscribed' => 'Nee, ik wil abonnee blijven', 'Not Approved Affiliates' => 'Niet goedgekeurde Affiliates', 'Not Selected' => 'Niet geselecteerd', 'Not assigned to usergroup' => 'Niet toegewezen aan gebruikersgroep', 'Not registered yet?' => 'Nog niet geregistreerd?', 'Number of Messages to display' => 'Aantal weer te geven berichten ', 'Numeric Value' => 'Numerieke waarde', 'Numeric value required' => 'Numerieke waarde vereist', 'Offline Payment' => 'Offline Betaling', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'Is de plugin configuratie op deze pagina eenmaal voltooid, denk eraan een record op de %saMember CP -> Protected Content -> Integrations%s pagina toe te voegen', 'Only Affiliate %s(rarely used)%s' => 'Alleen affiliate %s(zelden gebruikt)%s', 'Order reference: %s' => 'Order referentie: %s', 'Other' => 'Anders', 'Our system will try to charge your card again on %s' => 'Ons systeem zal proberen je kaart opnieuw te belasten op %s', 'Pages' => 'Pagina\'s', 'Password' => 'Wachtwoord', 'Password and Password Confirmation are different. Please reenter both' => 'Wachtwoord en Bevestiging Wachtwoord zijn verschillend. Vul beide opnieuw in.', 'Password must contain at least %d letters or digits' => 'Wachtwoord moet minstens %d letters of getallen bevatten', 'Passwords do not match' => 'Wachtwoorden komen niet overeen', 'Path to %s' => 'Pad naar %s', 'Path to %s Folder' => 'Pad naar de map %s', 'Payanyway plugin does not support recurring billing!' => 'Payanywayplugin ondersteunt geen terugkerende betaling!', 'Payment' => 'Betaling', 'Payment Error' => 'Betaalfout', 'Payment Failed' => 'Betaling Mislukt', 'Payment Info' => 'Betaalinfo', 'Payment System' => 'Betaalsysteem', 'Payment System Description' => 'Betaalsysteem Omschrijving', 'Payment System Title' => 'Betaalsysteem Titel', 'Payment error: ' => 'Betaalfout:', 'Payment failed' => 'Betaling mislukt', 'Payment info' => 'Betaalinfo', 'Payment is already processed, please go to %sMembership page%s' => 'Betaling is al verwerkt, ga s.v.p. naar de %slidmaatschappagina%s', 'Payments' => 'Betaling', 'Payments History' => 'Betaalhistorie', 'Payments by New vs Existing members' => 'Betalingen van Nieuwe vergelijken met Bestaande gebruikers ', 'Payments by payment system breakdown' => 'Betalingen gesorteerd op betaalsysteem', 'Payments by products breakdown' => 'Betalingen gesorteerd op producten', 'Payments from existing customers' => 'Betalingen van bestaande klanten', 'Payments from new customers' => 'Betalingen van nieuwe klanten', 'Payments total' => 'Totaal aan betalingen', 'Payout Method' => 'Uitbetaalwijze', 'Payouts' => 'Uitbetalingen', 'Pending' => 'Hangende', 'Pending Invoices' => 'Hangende Facturen', 'Pending subusers' => 'Hangende subgebruikers', 'Period' => 'Periode', 'Period must be in interval 1-24 months' => 'Periode moet een interval hebben van 1-24 maanden', 'Period must be in interval 1-5 years' => 'Periode moet een interval hebben van 1-5 jaar', 'Period must be in interval 1-90 days' => 'Periode moet een interval hebben van 1-90 dagen', 'Personal Content' => 'Persoonlijke Inhoud', 'Phone' => 'Telefoon', 'Phone Number' => 'Telefoonnummer', 'Plain-Text Message' => 'Platte tekst', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => '%sLogin%s op je bestaande account.%sAls je nog geen betaling hebt afgerond, dan kun je dat doen na in te loggen.', 'Please Select' => 'Kies s.v.p.', 'Please agree to Affiliate Agreement' => 'Ga s.v.p. akkoord met de affiliate-overeenkomst', 'Please agree to User Agreement' => 'Ga akkoord met de gebruiksvoorwaarden', 'Please choose' => 'Kies s.v.p.', 'Please choose a Credit Card Type' => 'Kies s.v.p. een type creditcard', 'Please choose a membership type' => 'Kies een abonnementtype', 'Please choose a payment system' => 'Kies s.v.p. een betaalwijze', 'Please choose state' => 'Selecteer een provincie/staat', 'Please enter %s' => 'S.v.p. invoeren %s', 'Please enter Account Number' => 'Voer s.v.p. je rekeningnummer in', 'Please enter City' => 'Plaatsnaam invullen s.v.p.', 'Please enter Country' => 'Land invullen s.v.p.', 'Please enter Credit Card Code' => 'S.v.p. de creditcard-code invullen', 'Please enter Credit Card Number' => 'Voer s.v.p. een creditcardnummer in', 'Please enter Debit Card Number' => 'Voer s.v.p. Debitcardnummer in', 'Please enter Password' => 'Wachtwoord invullen s.v.p.', 'Please enter Routing Number' => 'Voer s.v.p. een Routingnummer in', 'Please enter State' => 'Provincie/Staat invullen s.v.p.', 'Please enter Street Address' => 'Straatnaam invullen s.v.p.', 'Please enter ZIP code' => 'Postcode invullen s.v.p.', 'Please enter a valid e-mail address' => 'Vul een geldig e-mailadres in', 'Please enter correct amount' => 'Voer s.v.p. een correct bedrag in ', 'Please enter coupon code' => 'Vul s.v.p. een couponcode in', 'Please enter credit card holder first name' => 'Vul s.v.p. de voornaam van de kaarthouder in', 'Please enter credit card holder last name' => 'Vul s.v.p. de achternaam van de kaarthouder in', 'Please enter credit card holder name' => 'Vul s.v.p. de naam van de kaarthouder in', 'Please enter debit card holder first name' => 'Voer s.v.p. debitcardhouder\'s voornaam in', 'Please enter debit card holder last name' => 'Voer .s.v.p. debitcardhouder\'s achternaam in', 'Please enter debit card holder name' => 'Voer s.v.p. debitcardhouder\'s naam in', 'Please enter first name' => 'Voer s.v.p. je voornaam in', 'Please enter gift voucher code' => 'Voer s.v.p. de cadeauboncode in', 'Please enter housenumber' => 'Huisnummer invullen s.v.p.', 'Please enter phone number' => 'Telefoonnummer invullen s.v.p.', 'Please enter valid Email' => 'S.v.p. een geldig e-mailadres invullen.', 'Please enter valid Username. It must contain at least %d characters' => 'Vul een geldige gebruikersnaam in. Het dient uit minstens %d karakters te bestaan.', 'Please enter your First Name' => 'S.v.p. je voornaam invullen. ', 'Please enter your Last Name' => 'S.v.p. je achternaam invullen.', 'Please enter your current password for validation' => 'Vul je huidige wachtwoord in ter bevestiging', 'Please enter your last name' => 'Voer s.v.p. je achternaam in', 'Please enter your name' => 'Voer s.v.p. je naam in', 'Please login' => 'Inloggen s.v.p.', 'Please select' => 'Selecteer', 'Please select an item...' => 'S.v.p. een item selecteren...', 'Please select payment system for payment' => 'Kies een betaalwijze', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Gebruik s.v.p. het formulier: %sAbonnement Toevoegen/Verlengen%s (via bovenstaande knop), om te bestellen of het abonnement te verlengen.', 'Please wait %d seconds before next login attempt' => 'Wacht %d seconden alvorens opnieuw te proberen om in te loggen', 'Plugin' => 'Plugin', 'Plugin List Id' => 'Plugin Lijst Id', 'PostAffiliatePro Parent Affiliate ID' => 'PostAffiliatePro Parent Affiliate ID', 'PostAffiliatePro Referral ID' => 'PostAffiliatePro Doorverwijs ID', 'Prev' => 'Vorige', 'Preview' => 'Voorvertoning', 'Price' => 'Prijs', 'Processing your Transaction' => 'Verwerken van je transactie', 'Processing your product upgrade' => 'Verwerken van je productuitbreiding', 'Product' => 'Product', 'Product %s is incompatible with product %s. Reason: %s' => 'Product %s is onverenigbaar met product %s. Reden: %s', 'Product Categories' => 'Productcategorieën', 'Product Title' => 'Producttitel', 'Product upgrade finished successfully' => 'Productuitbreiding succesvol afgerond', 'Product(s) to display' => 'Producten te vertonen', 'Products' => 'Producten', 'Products keep empty to report all products' => 'Producten Leeg houden om alle producten te rapporteren', 'Profile' => 'Bewerk Profiel', 'Profile update transaction failed' => 'Transactie mislukt van bijwerken profiel', 'Protected Content [%s-%d]' => 'Beschermde Inhoud [%s-%d]', 'Purchased Credits' => 'Aangekocht Krediet', 'Qty' => 'Aantal', 'Quantity' => 'Eenheid', 'Quick Order' => 'Snel bestelllen', 'Quickpay parameters' => 'Quickpay parameters', 'Re-Open Ticket' => 'Heropen Ticket', 'Read-only' => 'Alleen-lezen', 'Real Path' => 'Werkelijk pad', 'Record' => 'Record', 'Record Type' => 'Recordtype', 'Record [%s] not found' => 'Record [%s] niet gevonden', 'Records that match all these conditions' => 'Records die aan al deze voorwaarden voldoen', 'Recurring' => 'Terugkerend', 'Redirect to NetDebit booking form.' => 'Doorsturen naar NetDebit boekingsformulier', 'Reference number is:' => 'Referentienummer is:', 'Referer' => 'Doorverwijzer', 'Referred Affiliate' => 'Doorverwijzende affiliate', 'Refresh' => 'Verschonen', 'Refresh 3-rd party lists' => 'Verschoon lijsten van derden', 'Refund' => 'Terugbetaling', 'Refund Amount' => 'Bedrag Terugbetalen', 'Refunded' => 'Terugbetaald', 'Regional Tax' => 'Belasting Regionaal', 'Register' => 'Registeren', 'Remote API Permissions' => 'Remote API Rechten', 'Remove' => 'Verwijderen', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Verwijder Gebruikers wanneer gebruikersgegevens van aMember worden verwijderd moeten de gerelateerde gegevens worden verwijderd van %s', 'Remove user' => 'Verwijder gebruiker', 'Reply' => 'Beantwoorden', 'Required' => 'Vereist', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Opnieuw proberen bij storing als de periodieke betaling mislukt is, kan aMember het na enige dagen herhalen en het lidmaatschap voor die periode verlengen. Vul het aantal dagen in waarna opnieuw getracht wordt te betalen', 'Return' => 'Terug', 'Return and try again' => 'Keer terug en probeer opnieuw', 'Review/Pay Commissions' => 'Bekijk/Betaal Affiliateprovisie', 'Reward Points' => 'Beloningspunten', 'Reward Points Configuration' => 'Beloningspunten Configuratie', 'Run Report' => 'Uitvoeren Rapportage', 'Running %s' => 'Verwerken %s', 'Save' => 'Opslaan', 'Save Profile' => 'Profiel Opslaan', 'Search' => 'Zoeken', 'Search Products' => 'Zoek producten', 'Security code is invalid' => 'Beveiligingscode is ongeldig', 'Select a condition to add into search' => 'Selecteer een voorwaarde om toe te voegen in de zoekopdracht', 'Select all %s records matching your search' => 'Kies alle %s records die voldoen aan jouw zoekopdracht', 'Send' => 'Versturen', 'Send Cancel Notifications to User' => 'Verstuur Annuleringskennisgeving aan Gebruiker', 'Send Voucher To' => 'Verstuur tegoedbon aan', 'Session expired, please enter username and password again' => 'Sessie verlopen, voer s.v.p. gebruikersnaam en wachtwoord opnieuw in', 'Settings' => 'Instellingen', 'Shipping' => 'Verzending', 'Shipping Options' => 'Verzendmogelijkheden', 'Shopping Cart' => 'Winkelwagen', 'Shopping Cart Module. No data input' => 'Winkelwagen Module. Geen data invoer', 'Shopping Cart Module. No product id input' => 'Winkelwagen Module. Geen product ID invoer', 'Sign-up' => 'Aanmelden', 'Signature' => 'Handtekening', 'Signup Form' => 'Aanmeldformulier', 'Signup here' => 'Klik hier om je aan te melden', 'Signup/payment functions are disabled for this user account' => 'Aanmeld- / betaalfuncties zijn uitgeschakeld voor dit gebruikersaccount', 'Simple Search Users' => 'Eenvoudig Gebruikers Zoeken', 'Site Title' => 'Titel van de site', 'Skip First Line' => 'Eerste regel overslaan', 'Snippets' => 'Fragmenten', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Excuses, het is niet mogelijk deze betaalwijze te kiezen. Kies s.v.p. een andere betaalwijze', 'Sorry, seems you have used wrong link' => 'Sorry, het lijkt erop dat je de verkeerde link hebt gebruikt.', 'Source Code — Copy/Paste Into Your Website' => 'Broncode — Knip en plak deze naar je website', 'Standard' => 'Standaard', 'Start' => 'Aanvang', 'Start Date' => 'Startdatum', 'State' => 'Provincie/Staat', 'Status' => 'Status', 'Street' => 'Straat', 'Street (Second Line)' => 'Adres (tweede regel)', 'Street Address' => 'Straat', 'Street Address (Second Line)' => 'Adres (tweede regel)', 'SubUsers Count (keep zero for non-reseller products)' => 'Aantal Subgebruikers (gebruik nul voor niet-wederverkoper producten)', 'SubUsers Product (keep empty for non-reseller products)' => 'Subgebruikers Product (leeglaten voor niet-wederverkoper producten)', 'Subject' => 'Onderwerp', 'Subject can not be empty' => 'Onderwerp kan niet leeg zijn', 'Submit' => 'Verstuur', 'Subscribe And Pay' => 'Aanmelden en Betalen', 'Subscribe all available users' => 'Alle beschikbare gebruikers aanmelden', 'Subscribe to Site Newsletters' => 'Aanmelden voor Site Nieuwsbrieven', 'Subscribed To Newsletters' => 'Ingeschreven voor de Nieuwsbrief', 'Subscribers' => 'Abonnees', 'Subscription Terms' => 'Abonnementsvoorwaarden', 'Subscription/Product Title' => 'Abonnement / Product Titel', 'Subtotal' => 'Subtotaal', 'Subusers' => 'Subgebruikers', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => 'Geslaagd: %d (%0.2f %s) Mislukt: %d (%0.2f %s)', 'Such affiliate ID exist' => 'Dergelijk affiliate ID bestaat al', 'Support Us!' => 'Ondersteun ons!', 'Target URL' => 'Bestemmings-URL', 'Tax' => 'BTW', 'Tax Amount' => 'BTW Bedrag', 'Tax Id' => 'Belasting ID', 'Tax Rate for example 18.5 (no percent sign)' => 'Belastingtarief bijvoorbeeld 18.5 (geen procentteken)', 'Tax Title' => 'Belasting Titel', 'Tax Value' => 'Belastingwaarde', 'Terms' => 'Voorwaarden', 'Test Mode' => 'Test Modus', 'Test Settings' => 'Testgegevens', 'Thank you for Signing up' => 'Dank je wel voor je aanmelding', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Bedankt! Je betaling is HANGENDE en in behandeling. Wij zullen je abonnement bijwerken zodra je betaling is voltooid. Blijf beschikbaar gedurende dit proces. Het kan 12 tot 24 uur duren. Je ontvangt een email over de ontvangst van uw betaling.', 'The database has encountered a problem, please try again later.' => 'De database heeft een probleem ondervonden, probeer het later nog eens.', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'Het bestand is verwijderd van schijf of is beschadigd. Upload het opnieuw s.v.p.', 'The following words are reserved : %s' => 'De volgende woorden zijn gereserveerd: %s', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'Het bericht dat je wachtwoord bevat is reeds verstuurd naar je inbox. Gelieve 180 minuten te wachten alvoren het opnieuw te proberen.', 'The password should be at least %d characters long' => 'Je wachtwoord dient minstens %d karakters te hebben', 'The user name or password is incorrect' => 'De gebruikersnaam of wachtwoord is onjuist', 'There are no confirmed payments for your account' => 'Er zijn geen bevestigde betalingen voor je account', 'There are no form available for affiliate signup.' => 'Er is geen formulier beschikbaar voor affiliate-aanmelding.', 'There are no products available for purchase. Please come back later.' => 'Er zijn geen producten beschikbaar voor verkoop. Kom later nog eens terug.', 'This %s is blocked. Please contact site support to find out why' => 'Deze %s wordt geblokkeerd. Neem contact op met site support om te vragen waarom', 'This Month' => 'Deze maand', 'This Week (Mon-Sun)' => 'Deze week (ma-zo)', 'This Week (Sun-Sat)' => 'Deze week (zo-za)', 'This coupon belongs to another customer' => 'Deze coupon baan behoort aan andere gebruiker', 'This field is required' => 'Dit veld is vereist', 'This is a required field' => 'Dit is een verplicht veld', 'This page will be automatically refreshed within %s' => 'Deze pagina zal automatisch verschoond worden binnen %s', 'This payment system could not handle payments in [%s] currency' => 'Dit betaalsysteem was niet in staat betalingen in [%s] valuta te verwerken', 'This payment system could not handle zero-total invoices' => 'Dit betaalsysteem was niet in staat nul-totaal facturen te verwerken', 'Thresehold Date' => 'Drempeldatum', 'Ticket' => 'Ticket', 'Ticket has been submited' => 'Ticket is verzonden', 'Tickets' => 'Tickets', 'Title' => 'Titel', 'To' => 'Aan', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Om velden aan het formulier toe te voegen, verplaats het item van \'Beschikbare Bouwstenen\' naar \'Formulier Bouwstenen\'. Om velden te verwijderen, verplaats het veld terug naar \'Beschikbare Bouwstenen\'. Om een formulier van meerdere pagina\'s te maken, plaats een \'Pagina Scheiding\' item op de plek waar je de pagina wilt splitsen.', 'Today' => 'Vandaag', 'Total' => 'Totaal', 'Try again' => 'Probeer opnieuw', 'Type' => 'Type', 'USA (Letter)' => 'VS (Letter)', 'Unable to cancel subscription: ' => 'Niet in staat abonnement te annuleren:', 'Unable to delete this file as it is used for:' => 'Niet mogelijk om dit bestand te verwijderen omdat het gebruikt wordt voor:', 'Unenroll Student' => 'Uitschrijven Student', 'Unit Price' => 'Stukprijs', 'Unknown period unit: %s' => 'Onbekende periode eenheid: %s', 'Unsubscribe' => 'Afmelden', 'Unsubscribe from all e-mail messages' => 'Afmelden voor alle e-mailberichten', 'Unsubscribed' => 'Afgemeld', 'Unsubscription Confirmation' => 'Bevestiging Afmelding', 'Update' => 'Bijwerken', 'Update Credit Card Info' => 'Pas creditcardgegevens aan', 'Update Debit Card Info' => 'Bijwerken Debitcard informatie', 'Updated' => 'Bijgewerkt', 'Upgrade Subscription' => 'Upgrade Abonnement', 'Upload files using FTP client to [%s]' => 'Uploaden van bestanden met behulp van FTP-client om [%s]', 'Use Database Connection other than configured for aMember' => 'Gebruik Database Connectie anders dan geconfigureerd voor aMember', 'Use Reward Points' => 'Beloningspunten gebruiken', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Gebruik andere MySQL Db gebruik zelfbepaalde host, gebruiker, wachtwoord voor %s databaseconnectie Gewoonlijk kun je dit onaangevinkt laten', 'Used' => 'Gebruikt', 'Useful Links' => 'Handige Links', 'User' => 'Gebruiker', 'User Agreement' => 'Gebruiksvoorwaarden', 'User Groups' => 'Gebruikersgroepen', 'User Info' => 'Gebruikersinformatie', 'User Search' => 'Gebruikers Zoeken', 'User is locked' => 'Gebruiker is geblokkeerd', 'User is not approved' => 'Gebruiker is niet goedgekeurd', 'User must provide' => 'Gebruiker dient te geven', 'Username' => 'Gebruikersnaam', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Gebruikersnaam je kunt hier een nieuwe gebruikersnaam kiezen of deze ongewijzigd laten Gebruikersnaam moet langer of gelijk zijn aan %d karakters en mag alleen kleine letters, getallen en underscores bevatten', 'Username %s is already taken. Please choose another username' => 'Gebruikersnaam %s is bezet. Kies een andere gebruikersnaam.', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'Gebruikersnaam [%s] bevat ongeldige karakters - gebruik s.v.p. cijfers en letters', 'Username [%s] is already taken. Please choose another username' => 'Gebruikersnaam [%s] is reeds vergeven. Kies s.v.p. een andere gebruikersnaam', 'Username contains invalid characters - please use digits, letters or spaces' => 'Gebruikersnaam bevat ongeldige karakters - gebruik s.v.p. cijfers, letters en spaties', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Gebruikersnaam bevat ongeldige karakters - gebruik s.v.p. cijfers en letters', 'Username/Email' => 'E-mailadres of gebruikersnaam ', 'Users subscribed to Newsletter Threads #' => 'Gebruikers geabonneerd op de nieuwsbrief discussies #', 'VAT Id' => 'BTW-Id', 'Validate E-Mail Address by sending e-mail message with code' => 'Valideerd e-mailadres door het verzenden van een e-mailbericht met code', 'Validation' => 'Bevestiging', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'Een e-mail ter verificatie is verzonden naar je adres. E-mail zal gewijzigd worden in je account na bevestiging', 'Version of script' => 'Scriptversie', 'Video' => 'Video', 'View Basket' => 'Bekijk mandje', 'Visit %sorder page%s to order additional subscriptions' => 'Bezoek %sbestelpagina%s om aanvullende abonnementen te bestellen', 'Voucher is not yet active' => 'Tegoedbon is nog niet actief', 'Week' => 'Week', 'Wrong code or code expired - please start signup process again' => 'Verkeerde code of verlopen code - start het aanmeld proces opnieuw', 'Wrong link - no id passed' => 'Verkeerde link - geen id doorgegeven', 'Wrong parameters, error #1253' => 'Verkeerde parameters, fout #1253', 'Wrong password' => 'Verkeerd wachtwoord', 'Wrong verification code' => 'Verkeerde verficatiecode', 'Wrongly signed URL, please contact site admin' => 'Onjuist ondertekende URL, neem contact op met site admin', 'Year' => 'Jaar', 'Years' => 'Jaren', 'Yes' => 'Ja', 'Yes, I want to cancel subscription' => 'Ja, ik wil mijn abonnement annuleren', 'Yes, continue' => 'Ja, ga verder', 'Yes, unsubscribe' => 'Ja, afmelden', 'Yesterday' => 'Gisteren', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Je bent ingelogd als %s. %sUitloggen%s om als nieuwe gebruiker aan te melden.', 'You have %s%d ticket(s)%s that require your attention' => 'Je hebt %s%d tickets%s die je aandacht vragen', 'You have no access to %s' => 'Je hebt geen toegang tot %s', 'You have no active subscriptions' => 'Je hebt geen actieve abonnementen.', 'You have no enough permissions for this operation' => 'Je hebt niet genoeg rechten voor deze bewerking', 'You have no items in your basket - please add something to your basket before checkout' => 'Je hebt niets in je winkelmandje - plaats s.v.p. eerst iets in je mandje alvorens te betalen', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'Je hebt te veel subgebruikers toegewezen aan dit account. Je kunt kiezen om %d gebruikers van je account te verwijderen', 'You must be authorized to access this area' => 'Je moet geauthoriseerd zijn om toegang te hebben tot dit gedeelte', 'You must be logged-in to open this media' => 'Je moet ingelogd zijn om deze media te openen', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Je moet aMember CP -> Setup -> Advanced -> Sessie-opslag op \'Standaard PHP sessies\' zetten. Dit is noodzakelijk om Single Login mogelijk te maken tussen aMember en SilverStrype', 'Your 9 digit ABA Routing Number' => 'Je 9-cijferig ABA Routingnummer', 'Your Account Removal' => 'Je account verwijderen', 'Your Bank Account Number' => 'Je bankrekeningnummer', 'Your Basket' => 'Jouw winkelwagen', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Je huidige wachtwoord als je je wachtwoord wilt wijzigen, vul dan hier s.v.p. je huidige wachtwoord in ter bevestiging', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Je e-mailadres een e-mail zal ter bevestiging naar dit adres worden gestuurd', 'Your General Affiliate Link' => 'Je Algemene Affiliatelink', 'Your Membership Information' => 'Je Lidmaatschapinformatie', 'Your Payment is PENDING & Under Process' => 'Je betaling is HANGENDE en in behandeling', 'Your Personal Downloads' => 'Je Persoonlijke Downloads', 'Your Reseller Packages' => 'Je Wederverkoper Pakketten', 'Your account has been automatically locked.' => 'Je account is automatisch vergrendeld.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Je account is nog niet goedgekeurd. Je wordt per e-mail op de hoogte gebracht wanneer een sitebeheerder je account beoordeelt en toegang verleent.', 'Your password is too long' => 'Je wachtwoord is te lang', 'Your payment has been successfully processed.' => 'Je betaling is met succes verwerkt.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Je betaling is nog niet bevestigd door het betaalsysteem. Het kan enkele minuten duren voordat bevestiging van betaling is ontvangen.', 'Your profile has been updated successfully' => 'Je profiel is succesvol bijgewerkt', 'Your subject is too verbose' => 'Je onderwerp bevat te veel woorden', 'Your subscription does not allow access to this media' => 'Je abonnement staat geen toegang toe tot deze media', 'Your subscription has been successfully processed.' => 'Je abonnement is met succes verwerkt.', 'ZIP' => 'Postcode', 'ZIP Code' => 'Postcode', 'Zip' => 'Postcode', '[Select country]' => '[Kies Land]', '[Select state]' => '[Selecteer provincie/staat]', '_default_locale' => 'nl_NL', 'accepts all major credit cards' => 'accepteer alle belangrijke creditcards', 'admin' => 'Beheerder', 'affiliate program commissions' => 'Affiliateprogramma provisie', 'after completing order, voucher will be sent to specified address' => 'na afronding van de bestelling, zal de tegoedbon verzonden worden naar het gespecificeerde adres', 'ago' => 'geleden', 'banned' => 'Geblokkeerd', 'check box to use points and get discount' => 'aanvinken om punten te gebruiken en korting te krijgen', 'check it if you want to gift subscription on this product' => 'aanvinken als je \'abonnement cadeau doen\' voor dit product', 'commission found by next rules' => 'provisie gevonden via de volgende regels', 'day' => 'dag', 'days' => 'dagen', 'different currency products' => 'producten met verschillende valutas', 'different rebill times subscriptions' => 'abonnementen met verschillend aantal terugkerende betalingen', 'different the first period subscriptions' => 'abonnementen met verschillende eerste termijn', 'different the second period subscriptions' => 'abonnementen met verschillende tweede termijn', 'email' => 'e-mail', 'email will contain this sentence' => 'e-mail zal deze zin bevatten', 'expiration' => 'vervallen', 'expires' => 'vervalt', 'filtered' => 'gefilterd', 'for affiliate commission payouts' => 'voor affiliateprovisie uitbetalingen', 'for example: 1111-2222-3333-4444' => 'bijvoorbeeld: 1111-2222-3333-4444', 'generate' => 'genereer', 'hrs' => 'uren', 'iDEAL betaling' => 'iDEAL betaling', 'if not specified, voucher will be sent to your email' => 'indien niet gespecificeerd, dan zal de tegoedbon per e-mail naar je verzonden worden', 'ip' => 'ip', 'just now' => 'zojuist', 'link' => 'link', 'login' => 'Inloggen', 'min' => 'min', 'month' => 'maand', 'months' => 'maanden', 'more than' => 'meer dan', 'no records' => 'geen records', 'number of affiliate program clicks' => 'aantal affiliateprogramma klikken', 'of products' => 'van producten', 'on %d-th day' => 'op %d-e dag', 'only First Name' => 'alleen voornaam', 'only Last Name' => 'alleen achternaam', 'or' => 'of', 'pay using credit card or PayPal' => 'Betaal met creditcard of Paypal', 'pay using wire transfer or by sending offline check' => 'betalen met overschrijving of door het sturen van offline cheque', 'protected area' => 'Afgeschermd gedeelte', 'return' => 'terug', 'seconds' => 'seconden', 'start' => 'start', 'upgrade' => 'opwaarderen', 'use 4111-1111-1111-1111 for successful transaction' => 'gebruik 4111-1111-1111-1111 voor een geslaagde transactie', 'year' => 'jaar', 'years' => 'jaren', 'you have %d reward points collected' => 'je hebt %d beloningspunten verzameld', ); PK\fc:default/language/user/sv.phpnu['_');PK\Tdefault/language/user/ja.phpnu[ '永久に', ' from ' => '~から', ' to ' => '~に', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" はこれらの商品とのみ同時に購入することができます: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" はこれらの失効した購読商品をお持ちの場合のみ購入することができます: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" は %sを既に購読されているため購入することができません。', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" は %s購読が失効されているため購入することができません。', '%d-Tier Affiliates Commission ' => '%dアフィリエイトコミッション率 ', '%s MySQL Hostname' => '%s MySQL ホスト名', '%s MySQL Password' => '%s MySQL パスワード', '%s MySQL Username' => '%s MySQL ユーザー名', '%s database and tables prefix' => '%sのデータベースとテーブル接頭語', 'API Authentication Information' => 'API認証情報', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => '直接払いに応じる 決済システム側での支払いを処理する (最初にaMemberに登録せずに)', 'Access Denied' => 'アクセスが拒否されました', 'Access Log' => 'アクセスログ', 'Access Permissions' => 'アクセス許可', 'Actions' => 'アクション', 'Active' => 'アクティブ', 'Active Resources' => 'アクティブリソース', 'Active Subscriptions' => 'アクティブな購読', 'Active Users' => 'アクティブユーザー', 'Active subusers' => 'アクティブサブユーザー', 'Add "Like" button' => '”いいね”ボタンを追加する', 'Add New Notification Rule' => '新しい通知ルールを追加する', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'この商品の購入に対してポイントを紹介アフィリエイトに付与する (aMember CP -> Setup -> Reward Pointsにて設定が可能です)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'この商品の購入に対してポイントをユーザーに付与する (aMember CP -> Setup -> Reward Pointsにて設定が可能です)', 'Add to Basket' => '買い物かごに入れる', 'Add/Renew Subscription' => '追加/変更', 'Address Info' => '住所情報', 'Address Information' => '住所情報', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => '管理者グループ aMemberは次のグループに割り当てられた%sのアカウントに関係しません。 他のaMemberのアクティビティが%sのアカウントから保護されます。', 'Administrator' => '管理人', 'Advertise our website to your friends and earn money' => 'あなたの家族や友人に当社のウェブサイトを紹介し、お金を稼ぐ', 'Affiliate Agreement' => 'アフィリエイト規約', 'Affiliate Clicks' => 'アフィリエイトクリック', 'Affiliate Info' => 'アフィリエイト情報', 'Affiliate Payout - Paypal E-Mail address' => 'アフィリエイトの支払い - ペイパルメールアドレス', 'Affiliate Payout Type' => 'アフィリエイト支払いタイプ', 'Affiliate Program' => 'アフィリエイトプログラム', 'Affiliate Sales' => 'アフィリエイト売り上げ', 'Affiliate Signup Form' => 'アフィリエイト登録フォーム', 'Affiliate info' => 'アフィリエイト情報', 'Affiliate stats' => 'アフィリエイトステータス', 'Affiliates' => 'アフィリエイト', 'All' => '全て', 'All %s records on this page are selected' => 'このページにある全ての%sの記録が選択されました', 'All Affiliates' => '全てのアフィリエイト', 'All Time' => '全期間', 'All Users' => '全てのユーザー', 'All records' => '全ての記録', 'Amazon S3 storage is not configured' => 'Amazon S3が設定されていません', 'Amount' => '総額', 'An account with the same email [%s] is already exists.' => 'このEメールアドレス[%s]はすでに使用済みです', 'An account with the same email already exists.' => 'このEメールアドレスはすでに使用済みです', 'An internal error happened in the script, please contact webmaster for details' => '内部エラーがスクリプト内にて発生しました。内容につきましてはウェブマスターにお問い合わせ下さい', 'Any Product' => 'どの商品でも', 'Any product' => '商品', 'Apply' => '実行する', 'Apply Filter' => 'フィルターを利用する', 'Assigned to usergroup' => 'ユーザーグループに割り当てる', 'Attachments' => '添付', 'Authentication' => '認証', 'Authentication problem, please contact website administrator' => '問題が発生しました。サイト管理者に問い合わせ下さい', 'Auto-Subscribe users to list once it becomes accessible for them' => '自動購読ユーザーをアクセスが可能になり次第リストする', 'Available Bricks (drag to left to add)' => '使用可能なブリック(左にドラッグし追加する)', 'Available Credits' => '使用可能なクレジット', 'Awaiting Admin Response' => '管理人の返事を待っています', 'Awaiting User Response' => 'ユーザーの返事を待っています', 'Aweber Application' => 'aweberアプリ', 'Back' => '戻る', 'Bank Code' => '銀行コード', 'Bank Identification' => '銀行識別番号', 'Bank Name' => '銀行名', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => '禁止されたグループ aMemberは次のグループに割り当てられた%sのアカウントに関係しません。 他のaMemberのアクティビティが%sのアカウントから保護されます。', 'Banners and Links' => 'バナー&リンク', 'Banners and Text Links' => 'バナー&テキストリンクの管理', 'Both Affiliate and member' => 'アフィリエイト&メンバー', 'CC Demo' => 'コールセンターのデモンストレーション', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF保護エラー - %d以内にフォームを再度送信して下さい', 'Can view/edit customer Credit Card information and rebills' => 'お客様のクレジットカード情報と自動引き落としを確認/変更することができます', 'Cancel' => 'キャンセル', 'Cancel Subscription' => '購読をキャンセルする', 'Cancelled' => 'キャンセルされました', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => '0.0以上する商品に無料支払いプラグインを使用できません。', 'Cannot validate VAT Id, please try again' => '付加価値税IDが認証できません、再度入力してください', 'Category' => 'カテゴリー', 'Change' => '変更する', 'Change Password' => 'パスワードを変更する', 'Change Password/Edit Profile' => 'パスワードを変更する/プロフィールを編集する', 'Change Subscription' => '購読を変更する', 'Change Username' => 'ユーザー名を変更する', 'Change payout info' => '支払情報の変更', 'Checkout' => 'チェックアウト', 'Checkout error: ' => 'チェックアウトエラー', 'Choose a Password must be %d or more characters' => 'パスワードを選択する。%d以上の文字が必要です。', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'ユーザー名を選択下さい。ユーザー名を入力下さい。最低%d字が必要です。 ', 'City' => '市町村', 'Click "Continue" to pay this order using stored credit card %s' => '既に登録されている%sクレジットカードにてお支払いの場合、続行をクリックして下さい。', 'Click button to continue' => 'クリックして続ける', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'ページが変更されない、又は今すぐ移動したい場合はここをクリックしてください', 'Click to Edit' => 'クリックして編集する', 'Clicks' => 'クリック', 'Clicks/Sales Statistics' => 'アフィリエイトクリック&売り上げの統計', 'Close' => '完了する', 'Close Ticket' => 'チケットを完了する', 'Closed' => '完了済み', 'Code' => 'コード', 'Comment' => 'コメント', 'Configured Tax Values' => '税金の値を設定する', 'Confirm New Password' => '新パスワードを登録', 'Confirm Password' => 'パスワードを確認する', 'Confirm Payment' => '支払いを確認する', 'Confirm Your E-Mail Address' => 'Eメールアドレスを再入力', 'Confirm Your Password' => 'パスワードを確認する', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'リンクをEメールアドレスに送信されました。メール受信箱をご確認下さい。5分以内に確認メールが届かない場合は迷惑メールもご確認下さい。', 'Content' => '内容', 'Continue' => '続ける', 'Conversation' => '会話', 'Count of signups' => '登録数', 'Count of user signups' => 'ユーザー登録数', 'Country' => '国', 'Coupon' => 'クーポン', 'Coupon Discount' => 'クーポン割引', 'Coupon code disabled' => 'クーポンコードが無効です', 'Coupon code expired' => 'このクーポンはすでに失効しました', 'Coupon is not yet active' => 'このクーポンは現在使用できません', 'Coupon usage limit exceeded' => 'このクーポンは無効です', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'デマンドでaMemberユーザーを作成する ユーザーが%sと同じユーザー名とパスワードでaMemberにログインしようとした場合、自動的にaMemberに顧客を作成する', 'Credit Card Code' => 'セキュリティーコード', 'Credit Card Info' => 'クレジットカード情報', 'Credit Card Number' => 'クレジットカード番号', 'Credit Card Rebills' => 'クレジットカードの自動引き落とし', 'Credit Cards' => 'クレジットカード', 'Credits' => '残高', 'Current password entered incorrectly, please try again' => 'パスワードが間違っています。再入力下さい', 'Custom Commission' => 'カスタムコミッション', 'Customer account has been automatically locked.' => '顧客アカウントが自動的にロックされました', 'Customize' => 'カスタマイズ', 'DONE' => '完了', 'Data Integrity Code' => 'データインテグリティコード', 'Date' => '日付', 'Date and time of payment: %s' => 'お支払い日時: %s', 'Date must be in format %s' => 'データは%sのフォーマットでなければなりません', 'Date: ' => '日付:', 'Day' => '日', 'Days' => '日付', 'Deactivate Student' => '生徒のアカウントを停止する', 'Deactivate User' => 'ユーザーを停止する', 'Debit Card Number' => 'デビットカード番号', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'デフォルトレベル デフォルトレベル - アクティブな購読がない場合、ユーザーはこのアクセスレベルにリセットされます。 (例:全ての購読が期限切れになった場合)', 'Delete' => '削除', 'Delete %s' => '%sを削除', 'Delivery Time' => '配送時間', 'Description' => '説明', 'Digits only please' => '数字のみ使用下さい', 'Disable online VAT Id Validation' => 'オンライン付加価値税ID認証を無効にする', 'Discard' => '破棄する', 'Discount' => '割引', 'Display in 2 rows' => '二列で表示する', 'Do Import' => 'インポートする', 'Do not add to Login Form' => 'ログインフォームに追加しない', 'Do not add to Signup Form' => '登録フォームに追加しない', 'Do you really want to %s %s %s records' => '%s %s %sの記録がいりますか?', 'Do you really want to %s?' => '本当に%sをしますか?', 'Do you really want to cancel subscription?' => '本当に購読の解除をしますか?', 'Do you really want to delete record?' => '本当に削除されますか?', 'Do you really want to unsubscribe from %s periodical messages?' => '%sの定期メッセージからの購読を解除しますか?', 'Done' => '完了', 'Donee name' => '受贈者名', 'Download limit exceeded for this file' => 'ダウンロード制限回数に達しました。', 'Downloaded on your own server' => 'あなたのサーバーにダウンロードする', 'E-Mail' => 'Eメール', 'E-Mail Address' => 'Eメールアドレス', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => '最初のEメールアドレスと再入力されたアドレスが正しくありません', 'E-Mail Format' => 'Eメールフォーマット', 'E-Mail Verification' => 'Eメール確認', 'EU VAT ID: ' => 'EU付加価値税ID:', 'EU VAT Id (optional)' => 'EU付加価値税ID (オプション)', 'Edit' => '編集', 'Edit %s' => '%sを編集', 'Edit Brick Labels' => 'ブリックラベルを編集する', 'Edit E-Mail Template' => 'Eメールテンプレートを編集する', 'Email [%s] is not valid' => 'Eメールアドレス[%s]が正しくありません', 'Empty response from Sagepay server' => 'Sagepayサーバーからの反応を空にする', 'Enabled Modules' => 'モジュールを有効化する', 'End' => '終わり', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => '会員得点をお楽しみ下さい。%sこちら%sをクリックして会員エリアにアクセスして下さい', 'Enjoy your membership. To Login please click here %sLogin%s' => '会員特典をお楽しみ下さい。ログインするには%sログイン%sをクリックして下さい。', 'Enter coupon code' => 'クーポンコードを入力', 'Enter gift voucher code' => 'ギフトクーポンコードを入力する', 'Error 404 - Not Found' => 'エラー404 - 見つかりません', 'Error : upload folder [%s] does not exists' => 'エラー:アップロードフォルダー [%s]が存在しません', 'Error from Storage Engine' => 'ストレージエンジンにエラーが発生しました', 'Error happened during payment process. ' => '支払いのプロセス中にエラーが発生しました', 'Error happened during transaction handling. Please contact website administrator' => '処理中にエラーが発生しました。サイトにお問い合わせください', 'Exact' => '正確な', 'Expired Users' => '無効のユーザー', 'Export' => 'エクスポート', 'Export Format' => 'エクスポートフォーマット', 'FaceBook App ID' => 'FacebookアプリID', 'FaceBook Application' => 'Facebookアプリ', 'Facebook App Secret' => 'Facebookアプリ秘密の合言葉', 'Features' => '機能', 'Field Updated' => 'フィールドが更新されました', 'Fields To Display' => '表示するフィールド', 'Fields To Export' => 'エクスポートするフィールド', 'Fieldset' => 'フィールドセット', 'Fieldset title' => 'フィールドセット名', 'File' => 'ファイル', 'File Downloads' => 'ファイルダウンロード', 'File Storage' => 'ファイルストレージ', 'File should contain CSV list of user records for import in the following format:
      %s' => '記載のフォーマットでインポートするにはファイルにユーザー記録が記載されたCSVファイルが含まれている必要があります %s', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'Amazon S3にあるファイル。(注意:あなたのbucketsにある名前に英字の大文字を含まないで下さい)', 'Files uploaded via aMember web interface' => 'aMemberウェブインターフェイスを使いファイルをアップロードする', 'Filter' => 'フィルター', 'First & Last Name' => '名前', 'First Name' => 'ファーストネーム(名)', 'Folder %s (%s)' => 'フォルダー %s (%s)', 'Form Page Break' => 'ページの区切りから', 'Free' => '無料', 'Free Access' => 'フリーアクセス', 'Free Access without log-in' => 'ログインなしに無料でアクセスできます', 'From' => 'から', 'GST (Inclusive Tax)' => '物品サービス税(税込み)', 'Get Password' => 'パスワードを取得する', 'Gift Voucher' => 'ギフトクーポン', 'Gift Vouchers' => 'ギフトクーポン', 'Global Commission' => '全体のコミッション', 'Global Tax' => '税金合計', 'Groups' => 'グループ', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'グループ優先度 グループをドラッグ&ドロップすることによって整理することができます。 複数のグループがあった場合、aMenberはリスト最上部のリストを第一リストとして選びます', 'HTML Code that will be displayed' => '表示されるHTMLコード', 'HTML Message' => 'HTML メッセージ', 'HTML text' => 'HTMLテキスト', 'Having Active Subscription To:' => '有効な購読:', 'Having Expired Subscription To:' => '有効期限切れの購読:', 'Helpdesk' => 'ヘルプデスク', 'Hosted at Activecampaing\'s server' => 'Activecampaingのサーバーでホストする', 'Housenumber' => '丁目', 'If you already have an account on our website, please %slog in%s to continue' => 'すでにアカウントをお持ちの場合は%sログイン%sして続けてください', 'If you are a registered member, please %slogin%s' => 'メンバー登録がお済の場合は%sログイン%sして下さい', 'If you are not registered yet, please %ssignup%s' => '登録がまだの場合は、%sご登録%s下さい', 'Income Report - payments minus refunds' => '収入レポート - 支払いから返金を引いた値', 'Incorrect Parent Affiliate ID' => 'アフィリエイト元IDが間違っています', 'Insert comment into email' => 'メールにコメントを入れる', 'Integer value required' => '整数値が必要です', 'Integration' => '統合', 'Internal Error' => 'エラー', 'Invalid Account Number' => '口座番号が無効です', 'Invalid Credit Card Number' => 'クレジットカード番号が無効です', 'Invalid Debit Card Number' => 'デビットカード番号が正しくありません', 'Invalid Expiration Date - Month' => '有効期限が無効です 日―月', 'Invalid Expiration Date - Year' => '有効期限が無効です 日―年', 'Invalid Issue Number' => 'カード発行番号が無効です', 'Invalid Routing Number' => '銀行支店番号が無効です。', 'Invalid VAT Id, please try again' => '付加価値税IDが間違っています、再度入力して下さい', 'Invoice' => '請求書', 'Invoice Number: ' => '請求書番号:', 'Invoice not found' => '請求書はありません', 'Is Gift Voucher?' => 'ギフトクーポンは?', 'Is Send At Later Date?' => '後日に送信しますか?', 'Is Disabled?' => ' は無効化されていますか?', 'Item' => '商品', 'Label' => 'ラベル', 'Language' => '言語', 'Last 14 Days' => '過去14日間', 'Last 30 Days' => '過去30日間', 'Last 7 Days' => '過去7日間', 'Last Business Week (Mon-Fri)' => '前の営業週(月―金)', 'Last Messages in Helpdesk' => 'ヘルプデスクでの最後のメッセージ', 'Last Month' => '先月', 'Last Name' => 'ラストネーム(氏)', 'Last Week (Mon-Sun)' => '先週(月曜―日曜)', 'Last Week (Sun-Sat)' => '先週(日曜―土曜)', 'Lifetime' => '生涯', 'Like Url' => 'いいね URL', 'Link' => 'リンク', 'Live Edit %s' => '%sのライブエディット', 'Log all API Requests' => '全てのAPIの要求を記録する', 'Login' => 'ログイン', 'Logout' => 'ログアウト', 'Lost Password Sending Error' => 'パスワードを紛失、エラー', 'Lost Password Sent' => 'パスワードが送信されました', 'Lost password?' => 'パスワードをお忘れの方', 'Make Payment' => '支払う', 'Make a Donation' => '寄付する', 'Make donation recurring' => '自動で寄付するようにする', 'Manage Newsletters' => 'ニュースレターを管理する', 'Marketing Materials' => 'マーケティング材料', 'Members Directory' => '会員一覧', 'Members Directory [%s] does not exists' => '会員一覧[%s]は存在しません', 'Membership Type' => 'メンバータイプ', 'Merchant Key' => 'マーチャントキー', 'Merchant Secret' => 'マーチャント暗号', 'Message' => 'メッセージ', 'Message can not be empty' => 'メッセージを入力して下さい', 'Moip Payment' => 'Moipペイメント', 'Month' => '月', 'Months' => '月', 'Multiplier' => '乗数', 'My Country' => '私の国', 'NEVER' => '二度としない', 'Name' => '名前', 'New' => '新しい', 'New %s' => '新しい%s', 'New Password' => '新パスワード', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => '新パスワード 新しいパスワードを%d字以上のアルファベットで入力', 'Newsletter' => 'ニュースレター', 'Newsletter Subscriptions' => '購読ニュースレター', 'Next' => '次', 'No' => 'いいえ', 'No commissions on this date' => 'この日のコミッションはありません', 'No coupons found with such coupon code' => '存在しないクーポンコードです', 'No gift vouchers found with such code' => 'ギフトクーポンコードが間違っています', 'No items in this section' => 'アイテムはありません', 'No items selected for purchase' => 'アイテムが選択されていません', 'No records found' => '記録がありません', 'No, cancel' => 'いいえ。キャンセルします。', 'No, keep me subscribed' => 'いいえ、購読を継続して下さい', 'No, please keep me subscribed' => 'いいえ、購読を継続する', 'Not Approved Affiliates' => 'アフィリエイトが承認されていません', 'Not Selected' => '選択されていません', 'Not assigned to usergroup' => 'ユーザーグループに割り当てられていません', 'Not registered yet?' => '登録済みですか?', 'Number of Messages to display' => 'メッセージの表示数', 'Numeric value required' => '数値が必要です', 'Offline Payment' => 'オフラインでの支払い', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'このページ上のプラグインの設定が完了後、記録を%saMember CP -> Protect Content -> Integrations%s ページに忘れず追加して下さい', 'Only Affiliate %s(rarely used)%s' => 'アフィリエイトのみ%s(ほとんど使われていない)%s', 'Order reference: %s' => 'ご注文番号: %s', 'Other' => '他', 'Our system will try to charge your card again on %s' => ' %s 日に再度引き落としを行います', 'Password' => 'パスワード', 'Password and Password Confirmation are different. Please reenter both' => 'パスワードが一致しません。', 'Password must contain at least %d letters or digits' => 'パスワードを最低%d字の数字又はアルファベットが必要です。', 'Passwords do not match' => 'パスワードが正しくありません', 'Path to %s' => '%sへのパス', 'Path to %s Folder' => '%sフォルダへのパス', 'Payanyway plugin does not support recurring billing!' => 'Payanywayは自動請求システムに対応していません', 'Payment' => '支払', 'Payment Error' => '支払エラー', 'Payment Failed' => '支払いに失敗しました', 'Payment Info' => '支払情報', 'Payment System' => '支払システム', 'Payment System Description' => '決済システム説明', 'Payment System Title' => '決済システム名', 'Payment error: ' => '支払いエラー:', 'Payment failed' => '支払いが失敗しました', 'Payment info' => '支払情報', 'Payment is already processed, please go to %sMembership page%s' => '支払が完了しました、%sメンバーページ%sをご確認ください', 'Payments' => '支払', 'Payments History' => '支払履歴', 'Payments by New vs Existing members' => '新しい顧客対すでに存在する顧客による報酬', 'Payments by payment system breakdown' => '決済システム別の報酬', 'Payments by products breakdown' => '商品別の報酬', 'Payments from existing customers' => 'すでに存在する顧客からの支払', 'Payments from new customers' => '新しい顧客の支払', 'Payments total' => '支払合計', 'Pending' => '保留中', 'Pending subusers' => '保留中のサブユーザー', 'Period' => '期間', 'Period must be in interval 1-24 months' => '1-24ヶ月の期間にしてください', 'Period must be in interval 1-5 years' => '1-5年の期間にしてください', 'Period must be in interval 1-90 days' => '1-90日の期間にしてください', 'Personal Content' => '個人向け商品', 'Phone' => '電話番号', 'Phone Number' => '電話番号', 'Plain-Text Message' => 'プレーンテキストメッセージ', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => '現在お持ちのアカウントへ%sログイン%sして下さい。%s支払いが完了していません、ログイン後支払いを完了させて下さい', 'Please Select' => '選択して下さい', 'Please agree to Affiliate Agreement' => 'アフィリエイト規約に同意する', 'Please agree to User Agreement' => '同意するをクリックください', 'Please choose' => '選択してください', 'Please choose a Credit Card Type' => 'クレジットカードの種類を選択してください', 'Please choose a membership type' => 'メンバータイプを選択してください', 'Please choose a payment system' => '決済システムを選択下さい', 'Please choose state' => '都道府県を選択下さい', 'Please enter %s' => '%sを入力下さい', 'Please enter Account Number' => '銀行口座番号を入力して下さい', 'Please enter City' => '市町村を入力下さい', 'Please enter Country' => '国名を入力下さい', 'Please enter Credit Card Code' => 'セキュリティーコードを入力してください', 'Please enter Credit Card Number' => 'クレジットカード番号を入力してください', 'Please enter Debit Card Number' => 'デビッドカード番号を入力下さい', 'Please enter Password' => 'パスワードを入力してください', 'Please enter Routing Number' => '銀行支店番号を入力して下さい。', 'Please enter State' => '都道府県を入力下さい', 'Please enter Street Address' => '番地を入力下さい', 'Please enter ZIP code' => '郵便番号を入力下さい', 'Please enter a valid e-mail address' => '正しいEメールアドレスを入力してください', 'Please enter correct amount' => '再入力ください', 'Please enter coupon code' => 'クーポンコードを入力してください', 'Please enter credit card holder first name' => 'クレジットカード名義人の名を入力してください', 'Please enter credit card holder last name' => 'クレジットカード名義人の苗字を入力してください', 'Please enter credit card holder name' => 'クレジットカード名義人の氏名を入力してください', 'Please enter debit card holder first name' => 'デビットカードに登録のファーストネーム(名)を入力下さい。', 'Please enter debit card holder last name' => 'デビットカードに登録のラストネーム(氏)を入力下さい。', 'Please enter debit card holder name' => 'デビットカードに登録された名前を入力下さい', 'Please enter first name' => 'ファーストネーム(名)を入力して下さい', 'Please enter gift voucher code' => 'ギフトクーポンコードを入力してください', 'Please enter housenumber' => '丁目を入力下さい', 'Please enter phone number' => '電話番号を入力下さい', 'Please enter valid Email' => 'Eメールアドレスが正しくありません', 'Please enter valid Username. It must contain at least %d characters' => 'ユーザー名を入力下さい。最低%d字が必要です。 ', 'Please enter your First Name' => 'ファーストネーム(名)を記入下さい', 'Please enter your Last Name' => 'ラストネーム(氏)を記入下さい', 'Please enter your current password for validation' => '確認のために現在のパスワードを入力して下さい', 'Please enter your last name' => 'ラストネーム(氏)を入力して下さい', 'Please enter your name' => '氏名を入力して下さい', 'Please login' => 'ログインしてください', 'Please select' => '選択してください', 'Please select an item...' => '商品を選択して下さい', 'Please select payment system for payment' => '支払方法を選択してください', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => '%s追加/%sからの購読の更新を使用して下さい購読の更新または注文', 'Please wait %d seconds before next login attempt' => '%d後再度ログインしてください', 'Plugin' => 'プラグイン', 'Plugin List Id' => 'プラグインリストID', 'PostAffiliatePro Parent Affiliate ID' => 'PostAffiliateProアフィリエイト元ID', 'PostAffiliatePro Referral ID' => 'PostAffiliatePro紹介ID', 'Prev' => '戻る', 'Price' => '価格', 'Processing your Transaction' => '決済の処理中です', 'Processing your product upgrade' => '商品のアップグレード中です。', 'Product' => '商品', 'Product %s is incompatible with product %s. Reason: %s' => '商品 %s は商品 %s に対応していません。理由 %s', 'Product upgrade finished successfully' => '商品のアップグレードが完了しました。', 'Product(s) to display' => '商品の表示', 'Products' => '商品', 'Products keep empty to report all products' => '商品 全商品をレポートするために空にする', 'Profile' => 'プロフィールを編集する', 'Profile update transaction failed' => 'お客様情報更新に失敗しました。', 'Protected Content [%s-%d]' => '保護された内容 [%s-%d]', 'Purchased Credits' => '購入済みクレジット', 'Qty' => '数量', 'Quantity' => '数量', 'Quick Order' => 'クイックオーダー', 'Quickpay parameters' => 'Quickpayパラメーター', 'Re-Open Ticket' => '再度チケットをオープンする', 'Read-only' => '読み取り専用', 'Real Path' => '絶対パス', 'Record' => '記録', 'Record [%s] not found' => '記録[%s]は存在しません', 'Records that match all these conditions' => '全ての条件にマッチした記録', 'Redirect to NetDebit booking form.' => 'NetDebit bookingフォームにリダイレクトする', 'Reference number is:' => '参照番号は:', 'Referred Affiliate' => 'アフィリエイト紹介', 'Refresh' => '更新する', 'Refresh 3-rd party lists' => '第三者リストを更新する', 'Regional Tax' => '地方税', 'Register' => '登録', 'Remote API Permissions' => 'リモートAPIの許可', 'Remove' => '削除する', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'ユーザーを削除する aMemberからユーザー記録を削除すると、それに関連した情報も%sから削除されます', 'Remove user' => 'ユーザーを削除する', 'Reply' => '返信する', 'Required' => '必要', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => '自動請求が失敗した場合もう一度繰り返してください。 aMemberはお客様の購読期間を繰り返し入力された日数分延長することができます。', 'Return' => '戻る', 'Return and try again' => '再度入力してください', 'Review/Pay Commissions' => 'アフィリエイトコミッションの確認&支払い', 'Reward Points' => 'ポイント', 'Reward Points Configuration' => 'ポイント設定', 'Run Report' => 'レポートを実行する', 'Running %s' => '%sの実行中です', 'Save' => '保存', 'Save Profile' => 'プロファイルを保存する', 'Search' => '検索', 'Search Products' => '商品を検索', 'Security code is invalid' => 'セキュリティーコードが無効です', 'Select a condition to add into search' => '検索に追加する条件を選択して下さい', 'Select all %s records matching your search' => '検索にマッチした全ての%sの記録を選択する', 'Send Voucher To' => 'にクーポンを送る', 'Session expired, please enter username and password again' => '有効セッションが切れました。再度ユーザー名とパスワードを入力してください', 'Settings' => '設定', 'Shipping' => '送料', 'Shipping Options' => '配送手段', 'Shopping Cart' => 'ショッピングカート', 'Shopping Cart Module. No data input' => 'ショッピングカートモジュールにデータ入力されていません', 'Shopping Cart Module. No product id input' => 'ショッピングカートモジュールに商品IDが入力されていません', 'Sign-up' => '登録', 'Signature' => '署名', 'Signup Form' => '登録フォーム', 'Signup here' => 'ここから登録する', 'Signup/payment functions are disabled for this user account' => 'このユーザーに対して登録/支払い機能が停止しています', 'Simple Search Users' => '簡易ユーザー検索', 'Snippets' => '抜粋', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'この注文に選択の支払方法は使用できません。その他の支払方法を選択下さい', 'Sorry, seems you have used wrong link' => '申し訳ございません、無効なリンクを使用されています', 'Source Code — Copy/Paste Into Your Website' => 'ソースコード — をあなたのウェブサイトにコピー/貼り付け', 'Standard' => '標準', 'Start' => '始まり', 'State' => '都道府県', 'Street' => '番地', 'Street (Second Line)' => '番地(2行目)', 'Street Address' => '番地', 'Street Address (Second Line)' => '番地(アパート名・部屋番号)', 'SubUsers Count (keep zero for non-reseller products)' => 'サブユーザー数 (再販商品に対して0にして下さい)', 'SubUsers Product (keep empty for non-reseller products)' => 'サブユーザー商品 (再販商品に対して空にして下さい)', 'Subject' => '件名', 'Subject can not be empty' => '件名を入力して下さい', 'Submit' => '提出する', 'Subscribe And Pay' => '購読して支払う', 'Subscribe all available users' => 'すべてのユーザーを購読する', 'Subscribe to Site Newsletters' => 'サイトニュースレターを購読する', 'Subscribed To Newsletters' => 'ニュースレターを購読する', 'Subscribers' => '購読者', 'Subscription Terms' => '購読規約', 'Subscription/Product Title' => '購読/商品名', 'Subtotal' => '小計', 'Subusers' => 'サブユーザー', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => '成功: %d (%0.2f %s) 失敗: %d (%0.2f %s)', 'Such affiliate ID exist' => 'アフィリエイトIDが存在しません', 'Support Us!' => '支援をお願いします。', 'Target URL' => 'ターゲットURL', 'Tax' => '税金', 'Tax Amount' => '税金', 'Tax Rate for example 18.5 (no percent sign)' => '税率 例 18.5(パーセントサインなし)', 'Tax Title' => '税金名', 'Tax Value' => '税金値', 'Terms' => '条件', 'Test Mode' => 'テストモード', 'Test Settings' => 'テスト設定', 'Thank you for Signing up' => 'ご登録ありがとうございました', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'ありがとうございます。支払いが完了後、購読を更新いたします。約12~24時間が支払いの完了にかかりますので、もうしばらくお待ちください。支払いが完了後メールにてお知らせいたします。', 'The database has encountered a problem, please try again later.' => 'データベースに問題が発生しました。時間をおいて再度試行して下さい', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'ファイルがディスクから削除された、または破損しています。もう一度アップロードして下さい', 'The following words are reserved : %s' => 'これらの言葉は既に登録されています: %s', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'パスワードが含まれたメッセージが送信されました。180分お待ちの上確認下さい。', 'The password should be at least %d characters long' => 'パスワードは最低%d字必要です', 'The user name or password is incorrect' => 'ユーザー名またはパスワードが正しくありません', 'There are no confirmed payments for your account' => '支払はありません', 'There are no form available for affiliate signup.' => 'アフィリエイト登録フォームは現在ありません', 'There are no products available for purchase. Please come back later.' => '購入できる商品がありません。時間が経ってからお試しください。', 'This %s is blocked. Please contact site support to find out why' => '%sブロックされています。サポートに問い合わせ下さい', 'This Month' => '今月', 'This Week (Mon-Sun)' => '今週(月曜―日曜)', 'This Week (Sun-Sat)' => '今週(日曜―土曜)', 'This coupon belongs to another customer' => 'このクーポンは無効です', 'This is a required field' => '必須', 'This page will be automatically refreshed within %s' => 'このページは自動的に更新されます%s', 'This payment system could not handle payments in [%s] currency' => 'この決済システムは[%s]の通貨を取り扱っておりません', 'This payment system could not handle zero-total invoices' => '合計が0のため支払いが出来ません', 'Ticket' => 'チケット', 'Ticket has been submited' => 'チケットが提出されました', 'Tickets' => 'チケット', 'Title' => 'タイトル', 'To' => 'へ', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'フォームにフィールドを追加するにはアイテムを"使用可能なブリック"から"フォームブリック"に動かしてください。フィールドを削除するには"使用可能なブリック"に戻してください。フォームを複数ページにするには"ページの区切り"をページの区切りたい場所に追加して下さい。', 'Today' => '今日', 'Total' => '合計', 'Try again' => '再度入力してください', 'Unable to cancel subscription: ' => '購読のキャンセルができません', 'Unable to delete this file as it is used for:' => 'このファイルは使用中のため削除できません', 'Unenroll Student' => '生徒を退会させる', 'Unit Price' => '価格', 'Unknown period unit: %s' => 'までの不明な期間: %s', 'Unsubscribe' => '購読をやめる', 'Unsubscribe from all e-mail messages' => 'すべてのEメールからの購読を解除する', 'Unsubscription Confirmation' => '購読キャンセルの完了', 'Update' => 'アップデート', 'Update Credit Card Info' => 'クレジットカード情報をアップデートする', 'Update Debit Card Info' => 'デビットカード情報を更新する', 'Upgrade Subscription' => '購読を更新する', 'Upload files using FTP client to [%s]' => 'FTPクライアントを使ってファイルを [%s]にアップロードする', 'Use Database Connection other than configured for aMember' => 'aMember以外のデータベースコネクションを使用する', 'Use Reward Points' => 'ポイントを使用する', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => '別のMySQL Dbを使用する %sデータベースコネクションのカスタムホスト、ユーザー、パスワードを使用する。通常はチェックする必要はありません。', 'Used' => '使用済み', 'Useful Links' => '便利なリンク', 'User Agreement' => 'ユーザー同意', 'User Info' => 'ユーザー情報', 'User Search' => 'ユーザー検索', 'User must provide' => 'ユーザーは提供する必要があります', 'Username' => 'ユーザ名', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'ユーザー名 新しいユーザー名に変更または現在のユーザー名を保持することができます。 ユーザー名は最低%d字が必要です。 ', 'Username %s is already taken. Please choose another username' => 'このユーザー名%sはすでに使用済みです。別のユーザー名を使用下さい', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'ユーザー名[%s]に使用できない文字が含まれています。数字とアルファベットのみ使用できます', 'Username [%s] is already taken. Please choose another username' => 'このユーザー名[%s]はすでに使用済みです。別のユーザー名を使用下さい', 'Username contains invalid characters - please use digits, letters or spaces' => 'ユーザーネームに無効の文字が含まれています。数字、アルファベット、スペースのみをして入力ください', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'ユーザーネームに無効の文字が含まれています。数字又はアルファベットのみを入力してください', 'Username/Email' => 'Eメールアドレス又はユーザー名', 'Users subscribed to Newsletter Threads #' => 'ニュースレタースレッド#を購読しているユーザー', 'VAT Id' => '付加価値税ID', 'Validate E-Mail Address by sending e-mail message with code' => 'コード付きのメッセージを送信し、Eメールアドレスを認証する', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'メールアドレスに確認メールが送信されました。確認された後Eメールが変更されます。', 'Version of script' => 'スクリプトのバーション', 'View Basket' => '買い物カゴを確認', 'Visit %sorder page%s to order additional subscriptions' => '%s注文ページ%sにて購読の追加を注文してください', 'Voucher is not yet active' => 'クーポンはまだ有効ではありません。', 'Week' => '週', 'Wrong code or code expired - please start signup process again' => 'コードを正しくありません。再度登録してください', 'Wrong link - no id passed' => 'リンクが違います - IDが間違っています', 'Wrong parameters, error #1253' => 'エラー#1253', 'Wrong password' => 'パスワードが正しくありません', 'Wrong verification code' => 'コードが間違っています。', 'Wrongly signed URL, please contact site admin' => 'URLが間違っています。管理者に問い合わせ下さい', 'Year' => '年', 'Years' => '年', 'Yes, I want to cancel subscription' => 'はい、購読の解除をします', 'Yes, continue' => 'はい。続けます。', 'Yes, unsubscribe' => 'はい、解除します', 'Yesterday' => '昨日', 'You have %s%d ticket(s)%s that require your attention' => '重要な%s%d チケット%sがあります', 'You have no access to %s' => '%sへのアクセスはできません', 'You have no active subscriptions' => '購読中の商品がありません', 'You have no enough permissions for this operation' => 'このオペレーションに対しての十分な権限がありません', 'You have no items in your basket - please add something to your basket before checkout' => '買い物カゴが空です。チェックアウトするには商品を入れてください', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'このアカウントに対してサブユーザー数が多すぎます。%dユーザーを選び、アカウントから削除することができます。', 'You must be authorized to access this area' => 'このエリアにアクセスするには承認が必要です', 'You must be logged-in to open this media' => 'ログインしてください', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'aMember CP -> Setup -> Advanced -> Session Storageの順で標準PSPセッションを設定してください。 この設定はaMemberとSilverStrype間での一回のログインを有効化させるのに必要です。', 'Your 9 digit ABA Routing Number' => '銀行支店番号', 'Your Account Removal' => 'アカウントの削除', 'Your Bank Account Number' => '銀行口座番号', 'Your Basket' => '買い物カゴ', 'Your Current Password if you are changing password, please enter your current password for validation' => 'パスワード 現在のパスワードを入力下さい', 'Your E-Mail Address a confirmation email will be sent to you at this address' => '確認メールがご記入いただいたEメールアドレスに送信されます。', 'Your General Affiliate Link' => 'あなたの標準アフィリエイトリンク', 'Your Membership Information' => 'メンバー情報', 'Your Payment is PENDING & Under Process' => 'あなたの支払いは保留・実行中です。', 'Your Personal Downloads' => 'あなたのダウンロード', 'Your Reseller Packages' => 'あなたの再販パッケージ', 'Your account has been automatically locked.' => 'アカウントが自動的にロックされました。', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'アカウントがまだ承認されていません。承認後、確認メールが送信されます。', 'Your password is too long' => 'パスワードが長すぎます', 'Your payment has been successfully processed.' => 'お支払いが完了いたしました', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => '支払システムはまだ認証されていません。確認作業に数分かかることがあります。', 'Your profile has been updated successfully' => 'プロフィールが更新されました', 'Your subject is too verbose' => '件名', 'Your subscription does not allow access to this media' => 'このメディアにアクセスできません', 'Your subscription has been successfully processed.' => '購読処理が完了いたしました', 'ZIP' => '郵便番号', 'ZIP Code' => '郵便番号', 'Zip' => 'Zip', '[Select country]' => '【国を選択】', '[Select state]' => '【都道府県を選択】', '_default_locale' => 'en_US', 'accepts all major credit cards' => 'すべてのクレジットカードに対応する', 'admin' => '管理者', 'affiliate program commissions' => 'アフィリエイトプログラムコミッション', 'after completing order, voucher will be sent to specified address' => '購入の完了後、特定のアドレスにクーポンが送信されます。', 'ago' => '前', 'banned' => '禁止されています', 'check box to use points and get discount' => 'boxをチェックしてポイントを使用してください', 'check it if you want to gift subscription on this product' => 'この商品に対して購読のプレゼントがほしいかチェックする', 'commission found by next rules' => '次の基準により見つかったコミッション', 'day' => '日', 'days' => '日', 'different currency products' => '通貨が違います', 'different rebill times subscriptions' => '購読更新時期が違います', 'different the first period subscriptions' => '最初の購読期間と違います', 'different the second period subscriptions' => '二回目の購読期間と違います', 'email' => 'Eメール', 'email will contain this sentence' => 'メールにこちらの文章が追加されます', 'expiration' => '有効期限', 'expires' => '有効期限', 'filtered' => 'フィルターされた', 'for affiliate commission payouts' => 'アフィリエイトコミッションの支払いのために', 'for example: 1111-2222-3333-4444' => '例: 1111-2222-3333-4444', 'hrs' => '時', 'iDEAL betaling' => 'iDEAL betaling', 'if not specified, voucher will be sent to your email' => '特に特定されない場合、あなたのメールアドレスにクーポンが送信されます', 'ip' => 'ip', 'just now' => '今現在', 'link' => 'リンク', 'login' => 'ログイン', 'min' => '分', 'month' => '月', 'months' => '月', 'more than' => 'よりも', 'no records' => '記録がありません', 'number of affiliate program clicks' => 'アフィリエイトクリック数', 'of products' => 'の商品', 'on %d-th day' => '%d-th の日に', 'only First Name' => 'ファーストネーム(名)のみ', 'only Last Name' => 'ラストネーム(氏)のみ', 'pay using credit card or PayPal' => 'クレジットカードまたはペイパルで支払う', 'pay using wire transfer or by sending offline check' => '振込みまたは小切手を使って支払う', 'protected area' => '保護されたエリア', 'return' => '戻る', 'seconds' => '秒', 'start' => '始める', 'upgrade' => '更新', 'use 4111-1111-1111-1111 for successful transaction' => '4111-1111-1111-1111の形で入力して下さい。', 'year' => '年', 'years' => '年', 'you have %d reward points collected' => '%dポイントを獲得しました', ); PK\ϤPKsKsdefault/language/user/es.phpnu[ '"%s" solamente se puede solicitar junto con estos productos o esta/s suscripción/es: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" solamente se puede solicitar si tiene una o varias suscripciones vencidas para estos productos: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" no se puede solicitar, ya que tiene una/s suscripción/es activa/s: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" no se puede solicitar, ya que tiene una o varias suscripciones vencidas: %s', '%d-th day' => 'Día %d', '%s database and tables prefix' => '%s base de datos y tablas por defecto', 'Access' => 'Accesos', 'Access Denied' => 'Acceso denagado', 'Access Log' => 'Registro de acceso', 'Access Permissions' => 'Permisos de Acceso', 'Actions' => 'Acciones', 'Active' => 'Activo', 'Active Users' => 'Usuarios activos', 'Add User' => 'Añadir usuario', 'Add to Basket' => 'Añadir a la cesta de la compra', 'Add/Renew Subscription' => 'Añadir/Renovar suscripción', 'Added' => 'Añadido', 'Additional Fields' => 'Campos Adicionales', 'Address Info' => 'Información acerca de la dirección', 'Address Information' => 'Información de la dirección', 'Admin' => 'Administrador', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupos de administradores Un miembro nunca toca las cuentas %s asignado a los siguientes grupos. Esto protege %s las cuentas en contra de cualquier actividad del miembro', 'Admin Username' => 'Usuario Administrador', 'Administrator' => 'Administrador', 'Advanced' => 'Avanzado', 'Advanced Search' => 'Búsqueda avanzada', 'Advertise our website to your friends and earn money' => 'Publicite nuestro sitio web a sus amigos y gane dinero', 'Affiliate' => 'Afiliado', 'Affiliate Info' => 'Información de afiliado', 'Affiliate Payout Type' => 'Tipo de pago afiliado', 'Affiliate Program' => 'Programa de afiliado', 'Affiliate Signup Form' => 'Formulario de registro de afiliado', 'Affiliate info' => 'Información de afiliado', 'Affiliate stats' => 'Estadísticas de afiliado', 'Affiliates' => 'Afiliados', 'All' => 'Todos', 'All %s records on this page are selected' => 'Todos %s los registros en esta páginas están seleccionados', 'All Affiliates' => 'Todos los afiliados', 'All Users' => 'Todos los usuarios', 'All records' => 'Todos los registros', 'Amount' => 'Cantidad', 'An Error has occurred' => 'Ha ocurrido un error', 'An account with the same email already exists.' => 'Ya existe una cuenta con la misma dirección de correo electrónico', 'An error occurred while handling your payment.' => 'Ha ocurrido un error mientras se procesaba su pago.', 'An internal error happened in the script, please contact webmaster for details' => 'Ocurrió un error interno en la secuencia, por favor, póngase en contacto con el administrador del sitio web para más detalles', 'Any Product' => 'Cualquier Producto', 'Any product' => 'Cualquier producto', 'Apply' => 'Aplicar', 'Apply Filter' => 'Aplicar filtro', 'Attachments' => 'Archivos adjuntos', 'Authentication' => 'Autenticación', 'Authentication problem, please contact website administrator' => 'Problema de autentificación, por favor contacta con el administrador de la página web', 'Available Bricks (drag to left to add)' => 'Bloques disponibles (arrastrar a la izquierda para añadir)', 'Awaiting Admin Response' => 'Esperando respuesta del administrador', 'Awaiting User Response' => 'Esperando la respuesta del usuario', 'Back' => 'Volver', 'Bank Identification' => 'Identificación del banco', 'Bank Name' => 'Nombre del banco', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupos restringidos un miembro nunca toca %s cuentas asignadas a los siguientes grupos. Esto protege %s cuentas en contra de cualquier inactividad de un miembro', 'Banners and Links' => 'Carteles y vínculos', 'Banners and Text Links' => 'Administrar carteles y enlaces de textos', 'Begin Date' => 'Fecha de comienzo', 'Both Affiliate and member' => 'Tanto afiliado como miembro', 'CC Demo' => 'Demostración CC', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF error de protección- el formulario debe ser enviado dentro de %d minutos después de la visualización, por favor repítelo', 'Can view/edit customer Credit Card information and rebills' => 'Puede ver / editar la información de facturación y de la tarjeta de crédito del cliente', 'Cancel' => 'Cancelar', 'Cancel Subscription' => 'Cancelar suscripción', 'Cancelled' => 'Cancelada', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'No se puede utilizar el "plugin" de pago gratuito con un producto que cuesta más de 0', 'Category' => 'Categoría', 'Change' => 'Cambiar', 'Change Password' => 'Cambiar contraseña', 'Change Password/Edit Profile' => 'Cambiar contraseña / Editar perfil', 'Change Subscription' => 'Cambiar suscripción', 'Change Username' => 'Cambiar nombre de usuario', 'Change payout info' => 'Cambiar la información de pagos', 'Checkout' => 'Comprar', 'Checkout error: ' => 'Error en el pago:', 'Choose a Password must be %d or more characters' => 'Selecciona un contraseña debe de ser %d o más caracteres', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Seleccionar un nombre de usuario Este debe de ser %d o más caracteres de largo puede solo contener letras, números y guiones bajos', 'City' => 'Ciudad', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Haz clic aquí si no quieres esperar más ( o si tu navegador no te redirige automáticamente)', 'Clicks' => 'Clics', 'Clicks/Sales Statistics' => 'Clics de afiliado / Estadísticas de venta', 'Close' => 'Cerrar', 'Close Ticket' => 'Entrada cerrada', 'Closed' => 'Cerrado', 'Code' => 'Código', 'Comment' => 'Comentario', 'Comment for admin reference' => 'Comentario para la referencia del administrador', 'Commission' => 'Comisión', 'Commissions' => 'Comisiones', 'Configuration' => 'Configuración', 'Configured Tax Values' => 'Configurados los valores de impuestos', 'Confirm' => 'Confirmar', 'Confirm New Password' => 'Confirmar nueva contraseña', 'Confirm Password' => 'Confirmar contraseña', 'Confirm Payment' => 'Confirmar pago', 'Confirm Your Password' => 'Confirma tu contraseña', 'Continue' => 'Continuar', 'Conversation' => 'Conversación', 'Country' => 'País', 'Coupon' => 'Cupón', 'Coupon Discount' => 'Cupón de descuento', 'Coupon code disabled' => 'Código de cupón invalidado', 'Coupon code expired' => 'El código del cupón ya expiró', 'Coupon is not yet active' => 'El cupón aún no está activo', 'Coupon usage limit exceeded' => 'Límite de uso de cupones excedido', 'Credit Card Code' => 'Código de la tarjeta de crédito', 'Credit Card Info' => 'Información de la tarjeta de crédito', 'Credit Card Number' => 'Número de la tarjeta de crédito', 'Credit Card Rebills' => 'Facturas de la tarjeta de crédito', 'Credit Cards' => 'Tarjetas de crédito', 'Currency' => 'Divisa', 'Currency Exchange Rates' => 'Tipo Cambio de Divisa', 'Current password entered incorrectly, please try again' => 'La contraseña actual introducida es incorrecta. por favor, inténtalo de nuevo', 'Custom Commission' => 'Comisión personalizada', 'DONE' => 'HECHO', 'Dashboard' => 'Panel de control', 'Date' => 'Fecha', 'Date and time of payment: %s' => 'Fecha y hora del pago: %s', 'Date must be in format %s' => 'La fecha debe de estar en este formato %s', 'Date/Time' => 'Fecha/Hora', 'Day' => 'Día', 'Days' => 'Días', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Nivel predeterminado nivel por defecto - el usuario vuelve a este nivel de acceso si no hay suscripciones activas existentes (por ejemplo, todas las suscripciones caducadas)', 'Delete' => 'Eliminar', 'Delete %s' => 'Eliminar %s', 'Description' => 'Descripción', 'Disabled' => 'Deshabilitado', 'Discard' => 'Descartar', 'Discount' => 'Descuento', 'Display Type' => 'Mostrar tipo', 'Do you really want to %s %s %s records' => '¿Realmente quieres %s %s %s registros?', 'Do you really want to %s?' => '¿Realmente quieres %s?', 'Do you really want to cancel subscription?' => '¿Realmente quiere cancelar su suscripción?', 'Do you really want to delete record?' => '¿Realmente quieres eliminar el registro?', 'Done' => 'Terminado', 'E-Mail' => 'Dirección de correo electrónico', 'E-Mail Address' => 'Dirección de correo electrónico', 'E-Mail Format' => 'Formato de correo electrónico', 'E-Mail Messages' => 'Mensajes Correo Electrónico', 'E-Mail Verification' => 'Verificación del correo electrónico', 'Edit' => 'Editar', 'Edit %s' => 'Editar %s', 'Edit Brick Labels' => 'Editar etiquetas de los bloques', 'Edit E-Mail Template' => 'Editar plantilla de correo electrónico', 'Email' => 'Dirección de correo electrónico', 'Email Subject' => 'Asunto de Correo', 'Enabled Modules' => 'Módulos habilitados', 'End' => 'Finalizar', 'End Date' => 'Fecha de fin', 'Error 404 - Not Found' => 'Error 404, no encontrado', 'Expire Date' => 'Fecha de expiración', 'Expired' => 'Caducado', 'Expired Users' => 'Usuarios caducados', 'Export' => 'Exportar', 'Export Format' => 'Exportar formato', 'Field' => 'Campo', 'Field Type' => 'Tipo de Campo', 'Field Updated' => 'Campo actualizado', 'Fields To Export' => 'Campos para exportar', 'File' => 'Archivo', 'Filename' => 'Nombre de archivo', 'Files' => 'Archivos', 'Filter' => 'Filtrar', 'First & Last Name' => 'Nombre y apellido', 'First Name' => 'Nombre', 'Folders' => 'Carpetas', 'Form Page Break' => 'Modo salto de página', 'Free' => 'Gratis', 'Free Access' => 'Acceso gratuito', 'From' => 'Desde', 'Get Password' => 'Recuperar contraseña', 'HTML Message' => 'Mensaje HTML', 'Having Active Subscription To:' => 'Teniendo suscripciones activas a:', 'Having Expired Subscription To:' => 'Habiendo expirado la suscripción a:', 'Helpdesk' => 'Soporte Técnico', 'Housenumber' => 'Número de la casa', 'IP Address' => 'Dirección IP', 'If you already have an account on our website, please %slog in%s to continue' => 'Si eres un usuario registrado, por favor %s ingresa%s', 'Integer Value' => 'Valor entero', 'Integer value required' => 'Requiere un valor entero', 'Integrations' => 'Integraciones', 'Invalid Credit Card Number' => 'Número de tarjeta de crédito erróneo', 'Invalid Expiration Date - Month' => 'Fecha (o mes) de expiración inválida', 'Invalid Expiration Date - Year' => 'Fecha (o año) de expiración inválida', 'Invalid Issue Number' => 'Número de emisión inválido', 'Invite Code' => 'Código de invitación', 'Invoice' => 'Factura', 'Invoice not found' => 'Factura no encontrada', 'Is Locked' => 'Está bloqueado', 'Is Paid?' => '¿Está pagado?', 'Item' => 'Objeto', 'Language' => 'Idioma', 'Last Name' => 'Apellido', 'Leads' => 'Clientes Potenciales', 'License Key' => 'Clave de Licencia', 'Lifetime' => 'Vida', 'Link' => 'Enlace', 'Links' => 'Enlaces', 'Live Edit %s' => 'Editar historial %s', 'Log In' => 'Conectarse', 'Login' => 'Iniciar sesión', 'Logout' => 'Cerrar sesión', 'Lost Password Sending Error' => 'Error al enviarle su contraseña perdida', 'Lost Password Sent' => 'Se le ha enviado su contraseña perdida', 'Lost password?' => 'Contraseña perdida', 'Mail Queue' => 'Cola de correo', 'Make Payment' => 'Realizar el pago', 'Manage Newsletters' => 'Gestionar boletines', 'Marketing Materials' => 'Materiales de "marketing"', 'Membership Type' => 'Tipo de membresía', 'Message' => 'Mensaje', 'Message can not be empty' => 'El mensaje no puede estar vacío', 'Month' => 'Mes', 'Months' => 'Meses', 'Multiplier' => 'Multiplicador', 'Name' => 'Nombre', 'Never' => 'Nunca', 'New' => 'Nuevo', 'New Password' => 'Nueva contraseña', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Nueva contraseña Puedes seleccionar una nueva contraseña aquí o mantenerla sin cambios debe de ser %d o más caracteres', 'Newsletter' => 'Boletín', 'Newsletter Subscriptions' => 'Suscripciones a boletines', 'Next' => 'Siguiente', 'No' => 'No', 'No commissions on this date' => 'Sin comisiones en esta fecha', 'No coupons found with such coupon code' => 'No se encontraron cupones con ese código', 'No items selected for purchase' => 'No se han seleccionado objetos para comprar', 'No records found' => 'No se encontraron registros', 'No, cancel' => 'No, cancelar', 'No, please keep me subscribed' => 'No, por favor, quiero seguir suscrito', 'Not Selected' => 'No seleccionado', 'Not registered yet?' => '¿Aún no se ha registrado?', 'Numeric Value' => 'Valor numérico', 'Numeric value required' => 'Requiere un valor numérico', 'Offline Payment' => 'Pago en modo desconectado', 'Order reference: %s' => 'Referencia de pedido: %s', 'Pages' => 'Páginas', 'Password' => 'Contraseña', 'Password and Password Confirmation are different. Please reenter both' => 'La contraseña y la confirmación de la contraseña son diferentes. Por favor, reintroduce ambos', 'Password must contain at least %d letters or digits' => 'La contraseña debe contener al menos %d letras o dígitos', 'Passwords do not match' => 'Las contraseñas no coinciden', 'Path to %s' => 'Camino a %s', 'Path to %s Folder' => 'Ruta a %s Carpeta', 'Payment Error' => 'Error en el pago', 'Payment Failed' => 'Pago fallido', 'Payment System' => 'Sistema de pago', 'Payment System Description' => 'Descripción del sistema de pago', 'Payment System Title' => 'Nombre del sistema de pago', 'Payment error: ' => 'Error en el pago', 'Payment failed' => 'Pago fallido', 'Payments' => 'Pagos', 'Payments History' => 'Historial de pagos', 'Payout Method' => 'Método de Pago', 'Payouts' => 'Pagos', 'Pending' => 'Pendientes', 'Period must be in interval 1-24 months' => 'El periodo debe ser entre 1 y 24 meses', 'Period must be in interval 1-5 years' => 'El periodo debe ser entre 1 y 5 años', 'Period must be in interval 1-90 days' => 'El periodo debe ser de 1 a 90 días', 'Phone' => 'Teléfono', 'Plain-Text Message' => 'Mensajes de texto plano', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Por favor, %sentra%s a tu cuenta ya existente. %s Si no has completado el pago, podrás completarlo después de entrar', 'Please Select' => 'Por favor, selecciona', 'Please agree to User Agreement' => 'Por favor, acepta el acuerdo de condiciones del usuario', 'Please choose' => 'Por favor, elija', 'Please choose a Credit Card Type' => 'Por favor, seleccione un tipo de tarjeta de crédito', 'Please choose a membership type' => 'Por favor elige un tipo de membresía', 'Please choose a payment system' => 'Por favor, selecciona una forma de pago', 'Please choose state' => 'Por favor, seleccione su estado', 'Please enter %s' => 'Por favor, introduce %s', 'Please enter City' => 'Por favor, introduzca su ciudad', 'Please enter Country' => 'Por favor, introduzca su país', 'Please enter Credit Card Code' => 'Por favor, introduzca el código de la tarjeta de crédito', 'Please enter Credit Card Number' => 'Por favor, introduzca el número de la tarjeta de crédito', 'Please enter Password' => 'Por favor, introduce la contraseña', 'Please enter State' => 'Por favor, introduzca su Estado', 'Please enter Street Address' => 'Por favor, introduzca su dirección postal', 'Please enter ZIP code' => 'Por favor, introduzca su código postal', 'Please enter a valid e-mail address' => 'Por favor, introduzca un correo electrónico válido', 'Please enter credit card holder first name' => 'Por favor, introduzca el nombre del titular de la tarjeta', 'Please enter credit card holder last name' => 'Por favor, introduzca los apellidos del titular de la tarjeta', 'Please enter credit card holder name' => 'Por favor, inserte el nombre del titular de la tarjeta', 'Please enter housenumber' => 'Por favor, introduzca el número de la casa', 'Please enter phone number' => 'Por favor, introduzca el número de teléfono', 'Please enter valid Email' => 'Por favor, introduce un correo electrónico válido', 'Please enter valid Username. It must contain at least %d characters' => 'Por favor, introduce un nombre de usuario valido. Este debe de contener al menos %d caracteres', 'Please enter your First Name' => 'Por favor, introduce tu nombre', 'Please enter your Last Name' => 'Por favor, introduce tu apellido', 'Please enter your current password for validation' => 'Por favor, introduce tu contraseña actual para la validación', 'Please login' => 'Por favor, inicie sesión', 'Please select an item...' => 'Por favor, selecciona un elemento...', 'Please select payment system for payment' => 'Por favor, seleccione un método para pagar', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Por favor, utilice el formulario de añadir/renovar suscripción para pedir o renovar una suscripción.', 'Please wait %d seconds before next login attempt' => 'Por favor espera %d segundos antes del siguiente intento de entrada', 'Plugin' => 'Plugin', 'Prev' => 'Anterior', 'Preview' => 'Previsualizar', 'Price' => 'Precio', 'Product' => 'Producto', 'Product Categories' => 'Categorías de Productos', 'Product(s) to display' => 'Producto(s) para visualizar', 'Products' => 'Productos', 'Profile' => 'Editar perfil', 'Qty' => 'Cantidad', 'Quantity' => 'Cantidad', 'Quick Order' => 'Pedido rápido', 'Re-Open Ticket' => 'Reabrir entrada', 'Record' => 'Registrar', 'Records that match all these conditions' => 'Registros que cumplen todas estas condiciones', 'Recurring' => 'Recurrente', 'Reference number is:' => 'El número de referencia es:', 'Referer' => 'Referencia', 'Referred Affiliate' => 'Afiliado', 'Refresh' => 'Refrescar', 'Refund' => 'Reembolsar', 'Refunded' => 'Reembolsado', 'Register' => 'Registrarse', 'Remove' => 'Eliminar', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Eliminar usuarios cuando un registro de usuario es eliminado por un miembro debe el registro relacionado ser eliminado de %s', 'Reply' => 'Responder', 'Return' => 'Volver', 'Return and try again' => 'Volver e intentarlo de nuevo', 'Review/Pay Commissions' => 'Revisar o pagar comisión de afiliado', 'Run Report' => 'Crear informe', 'Running %s' => 'Ejecutando %s', 'Save' => 'Guardar', 'Save Profile' => 'Guardar perfil', 'Search' => 'Búsqueda', 'Search Products' => 'Buscar productos', 'Security code is invalid' => 'El código de seguridad no es válido', 'Select a condition to add into search' => 'Seleccionar una condición y añadirla a la búsqueda', 'Select all %s records matching your search' => 'Selecciona todos %s registros correspondientes a tu busqueda', 'Send' => 'Enviar', 'Session expired, please enter username and password again' => 'Sesión caducada, por favor entra el usuario y la contraseña de nuevo', 'Shipping' => 'Envío', 'Shopping Cart' => 'Carro de la compra', 'Sign-up' => 'Regístrate', 'Signup Form' => 'Formulario de registro', 'Signup here' => 'Regístrese aquí', 'Simple Search Users' => 'Búsqueda simple de usuarios', 'Site Title' => 'Título de la página', 'Skip First Line' => 'Saltar Primera Línea', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Lo sentimos, no es posible utilizar este método de pago para este pedido. Por favor, seleccione otro sistema de pago', 'Sorry, seems you have used wrong link' => 'Lo sentimos, parece que ha utilizado un enlace incorrecto', 'Source Code — Copy/Paste Into Your Website' => 'Código fuente — copie y pegue en su sitio web', 'Start' => 'Comenzar', 'Start Date' => 'Fecha de inicio', 'State' => 'Estado', 'Status' => 'Estado', 'Street' => 'Calle', 'Street Address' => 'Dirección postal', 'Subject' => 'Tema', 'Subject can not be empty' => 'El tema no puede estar vacío', 'Subscribe to Site Newsletters' => 'suscribirse a boletines del sitio', 'Subscribers' => 'Subscriptores', 'Subscription Terms' => 'Condiciones de suscripción', 'Subscription/Product Title' => 'Suscripción / Título del producto', 'Subtotal' => 'Total parcial', 'Target URL' => 'URL de destino', 'Tax' => 'Impuesto', 'Tax Amount' => 'Importe del impuesto', 'Tax Value' => 'Valor de impuesto', 'Terms' => 'Condiciones', 'Test Settings' => 'Configuración de la prueba', 'Thank you for Signing up' => 'Gracias por registrarte', 'The database has encountered a problem, please try again later.' => 'La base de datos ha detectado un problema, por favor, inténtalo de nuevo más tarde', 'The password should be at least %d characters long' => 'La contraseña debe tener, al menos, %d caracteres', 'There are no confirmed payments for your account' => 'No hay pagos confirmados para tu cuenta', 'This %s is blocked. Please contact site support to find out why' => 'Este %s se encuentra bloqueado. Por favor, póngase en contacto con el soporte técnico del sitio web para más detalles', 'This coupon belongs to another customer' => 'Este cupón pertenece a otro cliente', 'This field is required' => 'Este campo es obligatorio', 'This is a required field' => 'Este es un campo necesario', 'This page will be automatically refreshed within %s' => 'Esta página se actualiza automáticamente dentro de %s', 'This payment system could not handle payments in [%s] currency' => 'Este sistema de pago no pudo procesar pagos en [%s] moneda', 'This payment system could not handle zero-total invoices' => 'Este sistema de pago no pudo procesar facturas de importe cero', 'Thresehold Date' => 'Fecha Umbral', 'Ticket' => 'Entrada', 'Ticket has been submited' => 'La entrada ha sido registrada', 'Tickets' => 'Entradas', 'Title' => 'Título', 'To' => 'Para', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Para agregar campos en el formulario, mueve la selección desde "Bloques disponibles" a "Forma de los bloques". Para eliminar los campos, muévelos de vuelta a "Bloques disponibles". Para hacer un formulario de varias páginas, inserta "Separador de páginas" en el lugar donde quieras que la página sea extendida.', 'Total' => 'Total', 'Try again' => 'Inténtelo de nuevo', 'Type' => 'Tipo', 'Unsubscribe from all e-mail messages' => 'Cancelar la suscripción de todos los correos electrónicos', 'Unsubscription Confirmation' => 'Confirmar cancelar suscripción', 'Update' => 'Actualizar', 'Update Credit Card Info' => 'Actualizar información de la tarjeta de crédito', 'Updated' => 'Actualizado', 'Upgrade Subscription' => 'Actualizar suscripción', 'Use Database Connection other than configured for aMember' => 'El uso de la conexión a la base de datos distinta que la configurada por un miembro', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Usar otra MySQL base de datos Uso de un alojamiento personalizado, usuario, contraseña %s de la conexión a la base de datos usualmente puedes dejar esta opción sin marcar', 'Useful Links' => 'Enlaces útiles', 'User' => 'Usuario', 'User Agreement' => 'Acuerdo del usuario', 'User Groups' => 'Grupos de usuarios', 'User Info' => 'Información del usuario', 'User Search' => 'Buscar usuario', 'Username' => 'Nombre de usuario', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Nombre de usuario Puedes elegir un nuevo nombre de usuario aquí o mantenerlo sin cambios. El nombre de usuario debe ser %d o más caracteres de longitud y puede solo contener letras minúsculas, números y guión bajo', 'Username %s is already taken. Please choose another username' => 'El nombre de usuario %s ya está en uso. Por favor, elige otro nombre de usuario', 'Username contains invalid characters - please use digits, letters or spaces' => 'El nombre de usuario contiene caracteres no válidos; por favor, utilice dígitos, letras o espacios', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'El nombre de usuario contiene caracteres no válidos; por favor, utilice dígitos y letras', 'Username/Email' => 'Dirección de correo electrónico o nombre de usuario', 'Users subscribed to Newsletter Threads #' => 'Usuarios suscritos a los hilos de los boletines de noticias #', 'Validate E-Mail Address by sending e-mail message with code' => 'Validar la dirección de correo electrónico enviando un mensaje de correo con el código', 'Validation' => 'Validación', 'View Basket' => 'Ver cesta de la compra', 'Visit %sorder page%s to order additional subscriptions' => 'Visita %s página de pedido%s para pedir suscripciones adicionales', 'Week' => 'Semana', 'Wrong code or code expired - please start signup process again' => 'Código erroneo o código expirado- por favor, empieza de nuevo el proceso de registro', 'Wrong parameters, error #1253' => 'Parámetros erróneos, error #1253', 'Wrong password' => 'Contraseña Incorrecta', 'Wrong verification code' => 'Código de verificación incorrecto', 'Wrongly signed URL, please contact site admin' => 'URL incorrecta; por favor, póngase en contacto con el administrador del sitio web', 'Year' => 'Año', 'Years' => 'Años', 'Yes, I want to cancel subscription' => 'Sí, quiero cancelar mi suscripción', 'Yes, continue' => 'Si, continuar', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Has ingresado como %s. %sSalir%s para registrarte como nuevo usuario', 'You have no access to %s' => 'No tienes acceso a %s', 'You have no active subscriptions' => 'Usted no cuenta con ninguna suscripción activa', 'You have no items in your basket - please add something to your basket before checkout' => 'No hay ningún objeto en su cesta de la compra, por favor, añada algo a su cesta antes de proceder con el pago', 'Your Basket' => 'Su cesta de la compra', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Tu contraseña actual Si estás cambiando la contraseña, por favor introduce tu contraseña actual para la validación', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Tu correo de confirmación un correo electrónico de confirmación te será enviado a esta dirección', 'Your Membership Information' => 'Información de tu membresía', 'Your Subscriptions' => 'Sus suscripciones', 'Your password is too long' => 'Su contraseña es demasiado larga', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Tu pago aún no está confirmado por el sistema de pagos. Puede tardar varios minutos para obtener la confirmación del pago.', 'Your subject is too verbose' => 'Tu tema es demasiado extenso', 'ZIP' => 'Código postal', 'ZIP Code' => 'Código postal', 'Zip' => 'Código postal', '[Select country]' => '[Seleccione país]', '[Select state]' => '[Seleccione estado]', '_default_locale' => 'inglés_US', 'admin' => 'Administrador', 'ago' => 'antes', 'banned' => 'bloqueado', 'commission found by next rules' => 'comisión establecida por las siguientes reglas', 'days' => 'días', 'email' => 'correo electrónico', 'filtered' => 'filtrado', 'for example: 1111-2222-3333-4444' => 'por ejemplo: 1111-2222-3333-4444', 'generate' => 'generar', 'hrs' => 'hrs.', 'ip' => 'ip', 'just now' => 'en este momento', 'login' => 'iniciar sesión', 'min' => 'min.', 'no records' => 'no hay entradas', 'of products' => 'de los productos', 'on %d-th day' => 'el día %d', 'or' => 'o', 'pay using wire transfer or by sending offline check' => 'pague mediante transferencia bancaria o enviando un cheque electrónico', 'return' => 'volver', 'seconds' => 'segundos', 'use 4111-1111-1111-1111 for successful transaction' => 'utilice 4111-1111-1111-1111 para una transacción con éxito', ); PK\Tibodefault/language/user/en.phpnu['_'); PK\|7ddefault/language/user/tr.phpnu[ '%d. gün', 'Active' => 'Aktif', 'Add User' => 'Kullanıcı Ekle', 'Added' => 'Eklendi', 'Additional Fields' => 'Ek Alanlar', 'Admin' => 'Yönetici', 'Admin Username' => 'Yönetici Kullanıcı Adı', 'Advanced' => 'Gelişmiş', 'Advanced Search' => 'Gelişmiş Arama', 'Affiliate' => 'Affiliate', 'Affiliate Info' => 'Affiliate Bilgisi', 'Affiliate Payout Type' => 'Affiliate Ödeme Şekli', 'Affiliate Program' => 'Affiliate Programı', 'Affiliate Signup Form' => 'Affiliate Kayıt Formu', 'Affiliates' => 'Affiliateler', 'All' => 'Hepsi', 'Amount' => 'Miktar', 'Banners and Text Links' => 'Banner ve Text Linkleri Yönet', 'Begin Date' => 'Başlangıç Tarihi', 'Both Affiliate and member' => 'Hem Affiliate hem üye', 'Clicks/Sales Statistics' => 'Affiliate Tıklama/Satış İstatistikleri', 'Code' => 'Kodu', 'Comment for admin reference' => 'Yorum yönetici kaydı için', 'Commission' => 'Komisyon', 'Commissions' => 'Komisyonlar', 'Configuration' => 'Yapılandırma', 'Configured Tax Values' => 'Yapılandırılmış Vergi Değerleri', 'Content' => 'İçerik', 'Continue' => 'Devam Et', 'Currency' => 'Döviz', 'Currency Exchange Rates' => 'Döviz Kurları', 'Dashboard' => 'Gösterge Tablosu', 'Date/Time' => 'Tarih/Saat', 'Disabled' => 'Devre Dışı', 'Display Type' => 'Görüntüleme Şekli', 'Done' => 'Bitti', 'E-Mail Messages' => 'Email mesajları', 'Email' => 'Email', 'Email Subject' => 'Email Konusu', 'End Date' => 'Bitiş Tarihi', 'European (A4)' => 'Avrupa (A4)', 'Expire Date' => 'Sona Eriş Tarihi', 'Expired' => 'Bitmiş', 'Expires' => 'Sona Eriş', 'Field' => 'Alan', 'Field Type' => 'Alan Tipi', 'File' => 'Dosya', 'Filename' => 'Dosya Adı', 'Files' => 'Dosyalar', 'First Name' => 'Ad', 'Folders' => 'Dizinler', 'From' => 'Kimden', 'Hide do not display this item link in members area' => 'Gizle üye alanında bu maddeyi gösterme', 'IP Address' => 'IP Adresi', 'Integer Value' => 'Tamsayı Değer', 'Integrations' => 'Birleştirmeler', 'Is Locked' => 'Kilitli', 'Is Paid?' => 'Ödendi mi?', 'Last Name' => 'Soyad', 'Leads' => 'Bağlantılar', 'License Key' => 'Lisans Anahtarı', 'Links' => 'Linkler', 'Log In' => 'Giriş Yap', 'Mail Queue' => 'Email Sırası', 'Never' => 'Asla', 'No' => 'Hayır', 'Not Selected' => 'Seçili Değil', 'Numeric Value' => 'Rakamsal Değer', 'Only Affiliate %s(rarely used)%s' => 'Sadece Affiliate %s(nadiren kullanılır)%s', 'Pages' => 'Sayfalar', 'Payout Method' => 'Ödeme Şekli', 'Payouts' => 'Ödemeler', 'Pending' => 'Karara Bağlanmamış', 'Pending Invoices' => 'İşlemdeki Faturalar', 'Please select an item...' => 'Lütfen bir kalem seçin...', 'Plugin' => 'Eklenti', 'Preview' => 'Önizleme', 'Product Categories' => 'Ürün Kategorileri', 'Recurring' => 'Tekrar Eden', 'Referer' => 'Yönlendiren', 'Refund' => 'Geri Öde', 'Refund Amount' => 'Geri Ödeme Miktarı', 'Refunded' => 'Geri Ödendi', 'Remove' => 'Kaldır', 'Review/Pay Commissions' => 'Affiliate Komisyonunu Gözden Geçir/Öde', 'Save' => 'Kaydet', 'Send' => 'Gönder', 'Site Title' => 'Site İsmi', 'Skip First Line' => 'İlk Satırı Atla', 'Start Date' => 'Başlangıç Tarihi', 'Tax Value' => 'Vergi Değeri', 'This field is required' => 'Bu alan gereklidir', 'Thresehold Date' => 'Eşik Tarihi', 'To' => 'Kime', 'Type' => 'Tip', 'USA (Letter)' => 'ABD (Mektup)', 'User Groups' => 'Kullanıcı Grupları', 'Validation' => 'Onaylama', 'Wrong password' => 'Yanlış Şifre', 'Zip' => 'Posta kodu', 'expires' => 'geçerliliğini yitirir', 'generate' => 'oluştur', 'or' => 'ya da', ); PK\ˆqdefault/language/user/el.phpnu[ 'για πάντα', ' from ' => 'από', ' to ' => 'προς', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" μπορεί να παραγγελθεί μόνο σε συνδυασμό με τα παρακάτω προϊόντα/συνδρομές: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" μπορεί να παραγγελθεί μόνο αν έχετε ληγμένη συνδρομή των παρακάτω προϊόντων: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" δεν μπορεί να παραγγελθεί γιατί έχετε ενεργή συνδρομή από: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" δεν μπορεί να παραγγελθεί γιατί έχετε ληγμένη συνδρομή από: %s', '%d access records...' => '%d προσβάσιμες εγγραφές...', '%s Configuration' => '%s Παραμετροποίηση', '%s database and tables prefix' => '%s βάση δεδομένων και πρόθεμα πινάκων', '%s records on this page are selected. You can choose group operation in the select box below or %scancel%s' => '%s εγγραφές στη σελίδα είναι επιλεγμένες. Μπορείτε να επιλέξετε διεργασία από τις επιλογές παρακάτω, ή %sακύρωση%s', '%s, you\'ve successfully logged in to Facebook.' => '%s, έχετε συνδεθεί επιτυχώς μέσω Facebook.', '(must match your credit card statement delivery address)' => '(πρέπει να συμφωνεί με την διεύθυνση αποστολής των ειδοποιητηρίων)', '2-Tier Default Commission' => 'Εξ ορισμού προμήθεια για το 2ο επίπεδο', 'Access' => 'Πρόσβαση', 'Access Denied' => 'Απαγορεύεται η είσοδος', 'Access Log' => 'Καταγραφέας Πρόσβασης', 'Access Permissions' => 'Αδειες πρόσβασης', 'Access allowed for all Users' => 'Η πρόσβαση επιτρέπεται σε όλα τα Μέλη', 'Access allowed for all Users and Guests' => 'Η πρόσβαση επιτρέπεται σε όλα τα Μέλη και τους Επισκέπτες', 'Actions' => 'Ενέργειες', 'Active Users' => 'Ενεργά Μέλη', 'Add "Like" button' => 'Προσθήκη "Μου Αρέσει"', 'Add to Basket' => 'Αγοράστε το', 'Add/Renew Subscription' => 'Προσθήκη/Ανανέωση Συνδρομής', 'Address Info' => 'Διεύθυνση', 'Address Information' => 'Διεύθυνση', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Ομάδες Διαχειριστών aMember ποτέ δεν θα πειράξει %s λογαριασμούς που ανήκουν στις παρακάτω ομάδες. Αυτό προστατεύει τους %s λογαριασμούς από οποιαδήποτε λάθος', 'Administrator' => 'Διαχειριστής', 'Advertise our website to your friends and earn money' => 'Διαφημίστε μας στους φίλους σας και κερδίστε χρήματα', 'Affiliate Clicks' => 'Εμφανίσεις Διαφημιστή', 'Clicks/Sales Statistics' => 'Στατιστικά Εμφανίσεων/Πωλήσεων', 'Affiliate Info' => 'Στοιχεία Διαφημιστή', 'Affiliate Payout Type' => 'Τρόπος Πληρωμής Διαφημιστή', 'Affiliate Program' => 'Πρόγραμμα Διαφημιστών', 'Affiliate Sales' => 'Πωλήσεις Διαφημιστών', 'Affiliate Signup Form' => 'Εγγραφή Διαφημιστή', 'Affiliate info' => 'Στοιχεία Διαφημιστή', 'Affiliate stats' => 'Στατιστικά Διαφημιστή', 'Affiliates' => 'Διαφημιστές', 'All %s records on this page are selected' => 'Ολες οι %s εγγραφές στη σελίδα είναι επιλεγμένες', 'All Affiliates' => 'Ολους τους Διαφημιστές', 'All Guests' => 'Ολους τους Επισκέπτες', 'All Users' => 'Ολα τα Μέλη', 'All Users and Guests' => 'Ολα τα Μέλη και Επισκέπτες', 'All records' => 'Ολες οι εγγραφές', 'Amount' => 'Ποσό', 'An Error has occurred' => 'Παρουσιάστηκε λάθος στη διαδικασία', 'An account with the same email already exists.' => 'Υπάρχει ήδη ενεργός λογαριασμός με αυτή την email διεύθυνση', 'An error occurred while handling your payment.' => 'Κάποιο λάθος παρουσιάστηκε στη διαδικασία πληρωμής', 'An internal error happened in the script, please contact webmaster for details' => 'Υπήρξε λάθος συστήματος. Παρακαλούμε επικοινωνείστε με τον Διαχειριστή', 'Any Product' => 'Οποιοδήποτε προϊόν', 'Any product' => 'Οποιοδήποτε προϊόν', 'Apply' => 'Εφαρμογή', 'Apply Filter' => 'Καταχώρηση κριτηρίων', 'Attachments' => 'Επισυναπτόμενα', 'Authentication' => 'Επικύρωση', 'Authentication problem, please contact website administrator' => 'Λάθος στη πιστοποίηση των στοιχείων. Παρακαλούμε επικοινωνείστε με τον Διαχειριστή', 'Available Bricks (drag to left to add)' => 'Διαθέσιμα στοιχεία (σύρτε προς τα αριστερά για να τα προσθέσετε)', 'Awaiting Admin Response' => 'Σε αναμονή απάντησης απο τον Διαχειριστή', 'Awaiting User Response' => 'Σε αναμονή απάντησης από τον Πελάτη', 'Back' => 'Επιστροφή', 'Back to shopping cart' => 'Επιστροφή στο κατάστημα', 'Bank Identification' => 'Στοιχεία Τραπέζης', 'Bank Name' => 'Ονομα Τράπεζας', 'Bank Phone' => 'Τηλέφωνο Τράπεζας', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Ομάδα αποβλημένων (Banned) aMember ποτέ δεν θα πειράξει %s λογαριασμούς που ανήκουν στις παρακάτω ομάδες. Αυτό προστατεύει τους %s λογαριασμούς από οποιαδήποτε λάθος,', 'Banners and Links' => 'Banners και Links', 'Billing International Province' => 'Νομός', 'Both Affiliate and member' => 'Ταυτόχρονα Διαφημιστής και Μέλος', 'Browse Guests Subscribers' => 'Λίστα Συνδρομητών (Επισκέπτες)', 'CC Demo' => 'Επίδειξη πληρωμής με κάρτα', 'COUPONS' => 'ΕΚΠΤΩΤΙΚΑ ΚΟΥΠΟΝΙΑ', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'Λάθος προστασίας CSRF. Η φόρμα πρέπει να υποβληθεί μέσα σε %d λεπτά απο την εμφάνιση της. Ξαναπροσπαθήστε.', 'Can open and answer helpdesk tickets' => 'Μπορείτε να καταχωρήσετε ή να απαντήσετε σε προβήματα', 'Can view/edit customer Credit Card information and rebills' => 'Επιτρέπεται να δεί/διορθώσει στοιχεία Πιστωτικών καρτών του Πελάτη και επαναλαμβανόμενες πληρωμές', 'Cancel' => 'Ακύρωση', 'Cancel Subscription' => 'Ακύρωση Συνδρομής', 'Cancel all Subscriptions' => 'Ακύρωση όλων των συνδρομών', 'Cancelled' => 'Ακυρώθηκε', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Δεν μπορείτε να χρησιμοποιήσετε τον Δωρεάν τρόπος πληρωμής με προϊόν που κοστίζει περισσότερο από 0', 'Card Expire' => 'Ημερομηνία Λήξης', 'Card Issue #' => 'Εκδότης κάρτας', 'Card Start Date' => 'Ημερομηνία Εναρξης', 'Cardholder Name' => 'Ονοματεπώνυμο κατόχου', 'Category' => 'Κατηγορία', 'Change' => 'Αλλαγή', 'Change Password' => 'Αλλαγή κωδικού πρόσβασης', 'Change Password error' => 'Λάθος στην διαδικασία αλλαγής κωδικού', 'Change Password/Edit Profile' => 'Αλλαγή Κωδικού/Στοιχείων', 'Change Subscription' => 'Αλλαγή συνδρομής', 'Change Username' => 'Αλλαγή Ονόματος Χρήστη', 'Change payout info' => 'Αλλαγή στοιχείων πληρωμής', 'Checkout' => 'Πληρωμή', 'Checkout error: ' => 'Λάθος Πληρωμής:', 'Choose Action' => 'Επιλέξτε ενέργεια', 'Choose Newsletters' => 'Επιλέξτε Ενημερωτικά', 'Choose Payment System' => 'Επιλέξτε τρόπο πληρωμής', 'Choose a Password must be %d or more characters' => 'Επιλέξτε κωδικό πρόσβασης πρέπει να είναι τουλάχιστον %d χαρακτήρες', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Επιλέξτε ένα Ονομα χρήστη θα πρέπει να είναι %d ή περισσότεροι χαρακτήρες μπορεί να περιλαμβάνει μόνο γράμματα, αριθμούς και κάτω παύλες', 'Choose another payment processor and try again' => 'Επιλέξτε άλλο τρόπο πληρωμής και ξαναπροσπαθήστε', 'City' => 'Πόλη', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Πατήστε εδώ αν δεν θέλετε να περιμένετε, ή αν η ανακατεύθυνση δεν λειτουργεί', 'ClickBank' => 'ClickBank', 'Clicks' => 'Εμφανίσεις', 'Close' => 'Κλείσιμο', 'Close Ticket' => 'Κλείσιμο υπόθεσης', 'Closed' => 'Κλειστή', 'Comment' => 'Σχόλιο', 'Commission earned' => 'Προμήθεια', 'Company Name' => 'Ονομα Εταιρείας', 'Confirm' => 'Επιβεβαίωση', 'Confirm New Password' => 'Επιβεβαίωση νέου κωδικού', 'Confirm Password' => 'Επιβεβαίωση κωδικού', 'Confirm Payment' => 'Επιβεβαίωση Πληρωμής', 'Confirm Your Password' => 'Επιβεβαίωση κωδικού', 'Confirmation Code' => 'Κωδικός επιβεβαίωσης', 'Confirmation sent' => 'Η επιβεβαίωση στάλθηκε', 'Connect with Facebook' => 'Συνδεθείτε μέσω Facebook', 'Continue' => 'Συνέχεια', 'Conversation' => 'Συνομιλία', 'Country' => 'Χώρα', 'Coupon' => 'Εκπτωτικό κουπόνι', 'Coupon Discount' => 'Εκπτωτικό κουπόνι', 'Coupon code disabled' => 'Ο εκπτωτικός κωδικός ακυρώθηκε', 'Coupon code expired' => 'Ο εκπτωτικός κωδικός έληξε', 'Coupon is not yet active' => 'Ο εκπτωτικός κωδικός δεν έχει ακόμη ενεργοποιηθεί', 'Coupon usage limit exceeded' => 'Το όριο χρήσης του εκπτωτικού κωδικού έχει ήδη κλείσει', 'Credit Card Code' => 'Κωδικός Ασφαλείας κάρτας', 'Credit Card Info' => 'Στοιχεία Κάρτας', 'Credit Card Number' => 'Αριθμός κάρτας', 'Credit Card Rebills' => 'Επαναλαμβανόμενες Πληρωμές', 'Credit Card Type' => 'Τύπος Πιστωτικής Κάρτας', 'Credit Cards' => 'Πιστωτικές Κάρτες', 'Current password entered incorrectly, please try again' => 'Δώσατε λάθος τον τωρινό σας κωδικό. Ξαναπροσπαθήστε', 'Custom Commission' => 'Ειδική Προμήθεια', 'DONE' => 'ΕΓΙΝΕ', 'Date' => 'Ημερομηνία', 'Date and time of payment: %s' => 'Ημερομηνία και Ωρα πληρωμής: %s', 'Date must be in format %s' => 'Ημερομηνία πρέπει να είναι σε μορφή %s', 'Day' => 'Ημέρα', 'Days' => 'Ημέρες', 'Default Commission' => 'Εξ ορισμού προμήθεια', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Εξ ορισμού επίπεδο χρήστη εξ ορισμού επίπεδι - ο χρήστης θα επανέλθει σαυτό το επίπεδο αν δεν υπάρχει ενεργή συνδρομή (άν δηλαδή η συνδρομή του δεν ανανεωθεί)', 'Delete' => 'Διαγραφή', 'Delete %s' => 'Διαγραφή %s', 'Description' => 'Περιγραφή', 'Discard' => 'Απόρριψη', 'Discount' => 'Εκπτωση', 'Do not add to Login Form' => 'Να μη προστεθεί στη φόρμα Εισόδου', 'Do not add to Signup Form' => 'Να μη προστεθεί στη φόρμα Εγγραφής', 'Do you really want to %s %s %s records' => 'Θέλετε πράγματι να %s %s %s εγγραφές;', 'Do you really want to %s?' => 'Θέλετε πραγματικά να %s;', 'Do you really want to cancel subscription?' => 'Είστε σίγουρος(-η) ότι θέλετε να ακυρώσετε τη συνδρομή σας;', 'Do you really want to delete record?' => 'Θέλετε πράγματι να διαγράψετε την εγγραφή;', 'E-Mail' => 'Email διεύθυνση', 'E-Mail Address' => 'Email διεύθυνση', 'Username/Email' => 'Email διεύθυνση ή Ονομα χρήστη', 'E-Mail Format' => 'Τύπος Email', 'E-Mail Verification' => 'Επιβεβαίωση Email', 'Edit' => 'Διόρθωση', 'Edit %s' => 'Διόρθωση %s', 'Edit Brick Labels' => 'Αλλαγή τίτλων στοιχείων', 'Edit E-Mail Template' => 'Επεξεργασία Πρωτύπου Email', 'Edit Profile' => 'Διόρθωση στοιχείων', 'Either click on the confirmation link in the e-mail message or enter confirmation code here' => 'Πατήστε στο link επιβεβαίωσης ή δώστε τον κωδικό επιβεβαίωσης', 'End' => 'Λήξη', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Απολαύστε την εγγραφή σας. Για να μπείτε στο σύστημα, %sπατήστε εδώ%s', 'Enter Confirmation Code' => 'Δώστε τον κωδικό επιβεβαίωσης', 'Enter Coupon Code:' => 'Εκπτωτικό κουπόνι:', 'Enter Verification Text please type text from image' => 'Δώστε τον κώδικό επιβεβαίωσης παρακαλούμε γράψτες το κείμενο της εικόνας', 'Enter coupon code (optional)' => 'Δώστε κωδικό για το εκπτωτικό κουπόνι (προαιρετικό)', 'Enter your Username/Email' => 'Δώστε το Email ή το Ονομα χρήστη', 'Error 404 - Not Found' => 'Λάθος 404 - Δεν βρέθηκε', 'Expired Users' => 'Ανενεργά Μέλη', 'Export' => 'Εξαγωγή', 'Export Format' => 'Τύπος Εξαγωγής', 'FaceBook App ID' => 'α/α (id) Εφαρμογής Facebook', 'FaceBook Application' => 'Εφαρμογή Facebook', 'Facebook App Secret' => 'Κωδικός Εφαρμογής Facebook', 'Features' => 'Χαρακτηριστικά', 'Field Updated' => 'Το πεδίο ενημερώθηκε', 'Fields To Export' => 'Στοιχεία για Εξαγωγή', 'Filter' => 'Κριτήριο', 'Filter by String' => 'Αναζήτηση λέξεων', 'First & Last Name' => 'Ονοματεπώνυμο', 'Form Bricks' => 'Στοιχεία φόρμας', 'Form Page Break' => 'Αλλαγή σελίδας φόρμας', 'Free' => 'Δωρεάν', 'Free Access' => 'Δωρεάν Πρόσβαση', 'Get Password' => 'Αποστολή κωδικού', 'Get affiliate banners and links' => 'Banners και Links Διαφημιστή', 'Guests having subscription to newsletters %s' => 'Επισκέπτες που είναι συνδρομητές στο ενημερωτικό %s', 'HTML Message' => 'Εμπλουτισμένο κείμενο', 'Having Active Subscription To:' => 'Με ενεργή συνδρομής σε:', 'Having Expired Subscription To:' => 'Με ληγμένη συνδρομή σε:', 'Helpdesk' => 'Εξυπηρέτηση Πελατών', 'Housenumber' => 'Αριθμός', 'I Agree' => 'Συμφωνώ', 'If that is your account, please go to %syour membership page%s to login into your subscription.' => 'Εαν είναι δικός σας λογαριασμός, τότε πηγαίνετε στη %sσελίδα μελών%s για να δώστε τα στοιχεία εισόδου.', 'If you already have an account on our website, please %slog in%s to continue' => 'Αν είστε εγγεγραμμένο Μέλος, τότε κάντε %sLogin%s', 'If you are a registered member, please %slogin%s' => 'Εαν είστε εγγεγραμμένο Μέλος, παρακαλούμε κάντε %sLogin%s', 'If you are not registered yet, please %ssignup%s' => 'Εαν δεν είστε Μέλος, τότε %sγίνετε τώρα%s', 'Income Report - payments minus refunds' => 'Κατάσταση Εσόδων - Πληρωμές μείον Επιστροφές', 'Integer value required' => 'Μόνο ακέραιος αριθμός είναι αποδεκτός', 'Invalid Credit Card Number' => 'Λάθος Αριθμός κάρτας', 'Invalid Expiration Date - Month' => 'Λάθος Μήνας λήξης', 'Invalid Expiration Date - Year' => 'Λάθος Ετος λήξης', 'Invalid Issue Number' => 'Λάθος αριθμός Εκδοτη', 'Invite Code' => 'Κώδικας πρόσκλησης', 'Invite code is required' => 'Ο κώδικας πρόσκλησης είναι υποχρεωτικό στοιχείο', 'Invoice' => 'Τιμολόγιο', 'Invoice not found' => 'Το Τιμολόγιο δεν βρέθηκε', 'Is Affiliate?' => 'Είναι Διαφημιστής;', 'Item' => 'Προϊόν', 'Language' => 'Γλώσσα', 'Lifetime' => 'Εφ όρου ζωής', 'Like Url' => 'Link στο Μου αρέσει', 'Link' => 'Link', 'Live Edit %s' => 'Ενεργή διόρθωση %s', 'Logged in as %s' => 'Είσοδος σαν %s', 'Login' => 'Είσοδος', 'Login using Facebook' => 'Είσοδος μέσω Facebook', 'Logout' => 'Εξοδος', 'Lost Password Sending Error' => 'Λάθος στην αποστολή κωδικού', 'Lost Password Sent' => 'Η επιβεβαίωση αλλαγής κωδικού στάλθηκε', 'Lost password?' => 'Υπενθύμιση κωδικού', 'Main Page' => 'Κεντρική Σελίδα', 'Make Payment' => 'Πληρωμή', 'Banners and Text Links' => 'Διαχείριση Banners και Links', 'Manage Newsletters' => 'Διαχείριση Συνδρομών', 'Marketing Materials' => 'Βοηθήματα Πωλήσεων', 'Member Login' => 'Είσοδος Μέλους', 'Membership Type' => 'Τύπος Συνδρομής', 'Message' => 'Μήνυμα', 'Message Count' => 'Αριθμός Μηνυμάτων', 'Message can not be empty' => 'Το μήνυμα είναι υποχρεωτικό στοιχείο', 'Month' => 'Μήνας', 'Months' => 'Μήνες', 'Multiplier' => 'Πολλαπλασιαστής', 'Name' => 'Ονομα', 'New' => 'Νέο', 'New %s' => 'Νέα %s', 'New Password' => 'Νέος κωδικός εισόδου', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Νέος κωδικός πρόσβασης μπορείτε να επιλέξετε νέο κωδικό ή να κρατήσετε τον υπάρχοντα πρέπει να είναι τουλάχιστον %d χαρακτήρες', 'New guest subscribe confirmation has been e-mailed to you' => 'Η επιβεβαίωση συνδρομής σας στάλθηκε με email', 'Newsletter' => 'Ενημερωτικό μήνυμα', 'Newsletter Subscribe' => 'Εγγραφή σε Ενημερωτικά Μηνύματα', 'Newsletter Subscriptions' => 'Συνδρομές σε ενημερωτικά μηνύματα', 'Next' => 'Επόμενο', 'No' => 'Οχι', 'No Banners and Links added by admin yet' => 'Προς το παρόν ο Διαχειριστής δεν έχει διαθέσιμα Banners και Links', 'No commissions on this date' => 'Καμμιά προμήθεια σαυτή την ημερομηνία', 'No coupons found with such coupon code' => 'Δεν βρέθηκε κάποιο εκπτωτικό κουπόνι με αυτό τον αριθμό', 'No items selected for purchase' => 'Δεν επιλέξατε κάποιο προϊόν για αγορά', 'No records found' => 'Δεν υπάρχουν στοιχεία', 'No, cancel' => 'ΟΧΙ, λάθος', 'No, please keep me subscribed' => 'ΟΧΙ, κρατήστε σε ισχύ τη συνδρομή μου', 'Not Selected' => 'Δεν Επιλέχθηκε', 'Not registered yet?' => 'Δεν είστε Μέλος;', 'Now please login to your account on our site to complete the link.' => 'Τώρα κάντε Login στο site μας για να οριστικοποιήσετε τον δεσμό.', 'Numeric value required' => 'Μόνο αριθμός είναι αποδεκτός', 'Offline Payment' => 'Πληρωμή εκτός συστήματος (Oflline)', 'Only Affiliate %s(rarely used)%s' => 'Μόνο Διαφημιστής %s(rarely used)%s', 'Order reference: %s' => 'Κωδικός παραγγελίας: %s', 'PDF Invoice' => 'PDF Τιμολόγιο', 'Password' => 'Κωδικός', 'Password and Password Confirmation are different. Please reenter both' => 'Οι δύο κωδικοί δεν συμφωνούν μεταξύ τους. Παρακαλούμε ξαναγράψτε και τους δύο', 'Password must contain at least %d letters or digits' => 'Ο κωδικός πρέπει να αποτελείται από τουλάχιστος %d γράμματα ή αριθμούς', 'Passwords do not match' => 'Οι κωδικοί δεν συμφωνούν μεταξύ τους', 'Path to %s' => 'Διαδρομή για %s', 'Path to %s Folder' => 'Διαδρομή για τον φάκελλο %s', 'Payment Error' => 'Λάθος πληρωμής', 'Payment Failed' => 'Αποτυχημένη πληρωμή', 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when he chooses to pay using this payment system you can use the following tags: %s - Invoice Id %s - Invoice Total' => 'Πληροφορίες πληρωμής για τον Πελάτη μπορείτε να χρησιμοποιήσετε HTML κώδικα εδώ, ο οποίος θα εμφανιστεί στον πελάτη, αν επιλέξει αυτό τον τρόπο πληρωμής μπορείτε να χρησιμοποιήσετε: %s - Αριθμός Τιμολογίου %s - Πληρωτέο ποσό', 'Payment System' => 'Τρόπος Πληρωμής', 'Payment System Description' => 'Περιγραφή τρόπου πληρωμής', 'Payment System Title' => 'Τίτλος τρόπου πληρωμής', 'Payment error: ' => 'Λάθος πληρωμής:', 'Payment failed' => 'Η πληρωμή απέτυχε', 'Payment is already processed, please go to %sMembership page%s' => 'Η πληρωμή πραγματοποιήθηκε, παρακαλώ πηγαίνετε στη %sMembership page%s', 'Payments' => 'Πληρωμές', 'Payments History' => 'Ιστορικό Πληρωμών', 'Period must be in interval 1-24 months' => 'Η χρονική περίοδος πρέπει να είναι μεταξύ 1-24 μήνες', 'Period must be in interval 1-5 years' => 'Η χρονική περίοδος πρέπει να είναι μεταξύ 1-5 έτη', 'Period must be in interval 1-90 days' => 'Η χρονική περίοδος πρέπει να είναι μεταξύ 1-90 ημέρες', 'Phone' => 'Τηλέφωνο', 'Plain-Text Message' => 'Απλό κείμενο', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Παρακαλούμε %sεισέλθετε%s στον ενεργό σας λογαριασμό. %sΑν δεν ολοκληρώσατε την πληρωμή σας, μπορείτε να το κάνετε αργότερα', 'Please Select' => 'Παρακαλώ επιλέξτε', 'Please agree to User Agreement' => 'Πρέπει να συμφωνείσετε με τους Ορους Μέλους', 'Please check your email - verification email message has been just emailed to you. Once you receive this message, read this and follow instructions in this email to complete your subscription.' => 'Το μήνυμα για την επαλήθευση της ηλεκτρονικής σας διεύθυνσης στάλθηκε με επιτυχία. Μόλις το παραλάβετε, διαβάστε προσεχτικά τη διαδικασία που χρειάζεται να ακολουθήσετε προκειμένου να οριστικοποιήσετε την εγγραφή σας.', 'Please check your mailbox' => 'Παρακαλούμε ελέγξτε τα εισερχόμενα σας', 'Please choose' => 'Επιλογή', 'Please choose a Credit Card Type' => 'Παρακαλώ επιλέξτε τύπο πιστωτικής κάρτας', 'Please choose a membership type' => 'Επιλέξτε τύπο συνδρομής', 'Please choose a payment system' => 'Παρακαλώ επιλέξτε τρόπο πληρωμής', 'Please choose state' => 'Επιλογή Νομού', 'Please enter %s' => 'Παρακαλώ εισάγετε %s', 'Please enter City' => 'Πόλη Διαμονής', 'Please enter Country' => 'Χώρα διαμονής', 'Please enter Credit Card Code' => 'Παρακαλώ δώστε τον κωδικό ασφαλείας', 'Please enter Credit Card Number' => 'Παρακαλώ δώστε τον αριθμό της κάρτας σας', 'Please enter Password' => 'Παρακαλώ δώστε νέο κωδικό', 'Please enter State' => 'Επιλέξτε Πολιτεία', 'Please enter Street Address' => 'Δώστε το όνομα της Οδού', 'Please enter ZIP code' => 'Ταχυδρομικός κώδικας', 'Please enter a valid e-mail address' => 'Παρακαλώ εισάγετε μια αποδεκτή email διεύθυνση', 'Please enter credit card holder first name' => 'Ονομα κατόχου της κάρτας', 'Please enter credit card holder last name' => 'Επώνυμο κατόχου της κάρτας', 'Please enter credit card holder name' => 'Ονοματεπώνυμο κατόχου της κάρτας', 'Please enter housenumber' => 'Δώστε τον αριθμό της κατοικίας', 'Please enter phone number' => 'Τηλέφωνο επικοινωνίας', 'Please enter username and password' => 'Δώστε το όνομα χρήστη και τον κωδικό εισόδου', 'Please enter valid Email' => 'Παρακαλώ εισάγετε ενα αποδεκτό Email', 'Please enter valid Login Name. It must contain at least %d characters' => 'Παρακαλώ δώστε ενα αποδεκτό ψευδώνυμο. Πρέπει να περιέχει τουλάχιστον %d χαρακτήρες', 'Please enter valid Username. It must contain at least %d characters' => 'Παρακαλώ δώστε ενα αποδεκτό όνομα χρήστη. Πρέπει να αποτελείται απο τουλάχιστον %d χαρακτήρες', 'Please enter your First Name' => 'Δώστε το Ονομα σας', 'Please enter your Last Name' => 'Δώστε το Επώνυμο σας', 'Please enter your current password for validation' => 'Για επιβεβαίωση παρακαλούμε δώστε τον τωρινό σας κωδικό', 'Please login' => 'Είσοδος Μέλους', 'Please select a different log-in name' => 'Παρακαλώ επιλέξτε κάποιο άλλο ψευδώνυμο', 'Please select payment system for payment' => 'Επιλέξτε τρόπο πληρωμής', 'Please use %sAdd/Renew subscription%s form' => 'Χρησιμοποιήστε τη φόρμα %sΠροσθήκη/Ανανέωση Συνδρομής%s', 'Please wait %d seconds before next login attempt' => 'Παρακαλούμε περιμένετε %d δευτερόλεπτα πριν την επόμενη προσπάθεια', 'Plugin [%s] is not configured' => 'Το πρόσθετο [%s] δεν έχει μορφοποιηθεί', 'Powered by %saMember Pro%s membership software' => 'Πνευματικά διακαιώματα %saMember Pro%s', 'Prev' => 'Προηγ', 'Price' => 'Τιμή', 'Product' => 'Προϊόν', 'Product(s) to display' => 'Προϊόντα για εμφάνιση', 'Products' => 'Προϊόντα', 'Protection' => 'Προστασία', 'Qty' => 'Τεμ', 'Quantity' => 'Ποσότητα', 'Quick Order' => 'Γρήγορη Παραγγελία', 'Re-Open Ticket' => 'Ανοιγμα εκ νέου', 'Record' => 'Εγγραφή', 'Records that match all these conditions' => 'Εγγραφές που πληρούν όλα τα κριτήρια', 'Reference number is:' => 'Αριθμός πρωτοκόλου', 'Referred Affiliate' => 'Διαφημιστής που τον σύστησε', 'Refresh' => 'Ανανέωση', 'Register' => 'Εγγραφή', 'Remember my password?' => 'Αποθήκευση κωδικού', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Διαγραφή Μελών αν ένα μέλος διαγραφεί απο το aMember τότε να διαγραφεί και από %s', 'Reply' => 'Απάντηση', 'Require Address Info' => 'Υποχρεωτικά στοιχεία διεύθυνσης', 'Restricted' => 'Απαγορευμένο', 'Restricted Access' => 'Απαγόρευση πρόσβασης', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Επανάληψη σε περίπτωση αποτυχίας Εαν μια επαναλαμβανόμενη πληρωμή αποτύχει aMember μπορεί να ξαναπροσπαθήσει μετά απο μερικές μέρες, και επεκτείνει την συνδρομή του πελάτη για αυτές τις ημέρες δώστε τον αριθμό των ημερών για επανάληψη της προσπάθειας', 'Return' => 'Επιστροφή', 'Return and try again' => 'Επιστροφή και ξαναπροσπαθήστε', 'Return to log-in page' => 'Επιστροφή στη σελίδα εισόδου', 'Review your affiliate statistics' => 'Στατιστικά στοιχεία Διαφημιστή', 'Review/Pay Commissions' => 'Εμφάνιση/Πληρωμή προμηθειών', 'Run Report' => 'Δημιουργία Λίστας', 'Running %s' => 'Πραγματοποίηση %s', 'Save' => 'Καταχώρηση', 'Save Profile' => 'Καταχώρηση στοιχείων', 'Search' => 'Αναζήτηση', 'Search Products' => 'Αναζήτηση Προϊόντος', 'Security code is expired' => 'Ο κωδικός ασφαλείας έχει λήξει', 'Security code is invalid' => 'Ο κωδικός ασφαλείας είναι μη αποδεκτός', 'Select a condition to add into search' => 'Επιλέξτε ενα κριτήριο να να προσθέσετε στην αναζήτηση', 'Select all %s records matching your search' => 'Επιλογή όλων των %s εγγραφών που πληρούν τα κριτήρια', 'Select card expiration date - month and year' => 'Επιλέξτε Ημέρα-Μήνα-Ετος Λήξης', 'Session expired, please enter username and password again' => 'Τέλος χρόνου, παρακαλούμε ξαναδώστε τα στοιχεία σας', 'Shipping' => 'Μεταφορικά', 'Shopping Cart' => 'Κατάστημα', 'Sign-up' => 'Εγγραφή', 'Sign-up - email verification' => 'Επαλήθευση εγγραφής με email', 'Signup Form' => 'Φόρμα Εγγραφής', 'Signup here' => 'Εγγραφή Μέλους', 'Simple Search Users' => 'Απλή αναζήτηση στα Μέλη', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Λυπούμαστε αλλά δεν μπορείτε να χρησιμοποιήσετε τον επιλεγμένο τρόπο πληρωμής για τη συγκεκριμένη παραγγελία', 'Sorry, seems you have used wrong link' => 'Λυπούμαστε αλλά φαίνεται ότι χρησιμοποιήσατε λάθος link', 'Source Code — Copy/Paste Into Your Website' => 'Πηγαίος κώδικας — Αντιγραφή/Επικόληση στην ιστοσελίδα σας', 'Start' => 'Εναρξη', 'State' => 'Πολιτεία', 'Status' => 'Κατάσταση', 'Street' => 'Οδός', 'Street Address' => 'Οδός', 'Subject' => 'Θέμα', 'Subject can not be empty' => 'Το θέμα είναι υποχρεωτικό στοιχείο', 'Subscribe' => 'Εγγραφή', 'Subscribe to Site Newsletters' => 'γραφτείτε-στα-ενημερωτικά-μας-μηνύματα', 'Subscribed To Newsletters (including guests)' => 'Συνδρομητές σε ενημερωτικά (συμπεριλαμβανομένων των Επιστεπτών)', 'Subscribers' => 'Συνδρομητές', 'Subscription Terms' => 'Οροι Συνδρομής', 'Subscription confirmed' => 'Η συνδρομή επιβεβαιώθηκε', 'Subscription/Product Title' => 'Τίτλος Συνδρομής/Προϊόντος', 'Subtotal' => 'Μερικό σύνολο', 'Target URL' => 'URL Προορισμού', 'Tax' => 'Φόρος', 'Tax Amount' => 'Ποσό Φόρου', 'Terms' => 'Οροι', 'Test Settings' => 'Επαλήθευση Στοιχείων', 'Text has been entered incorrectly' => 'Το κείμενο που γράψατε είναι λάθος', 'Thank you' => 'Ευχαριστούμε', 'Thank you for Signing up' => 'Σας ευχαριστούμε για την εγγραφή σας', 'The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).' => 'Ο κωδικός ασφαλείας είναι ένας αριθμός αποτελούμενος απο 3 ή 4 ψηφία και συνήθως βρίσκεται στο πίσω μέρος της κάρτας (ή στο μπρός μέρος για την American Express).', 'The database has encountered a problem, please try again later.' => 'Λάθος στη βάση δεδομένων. Παρακαλούμε προσπαθήστε πάλι αργότερα', 'The information you have entered is incorrect' => 'Τα στοιχεία που δώσατε είναι λάθος', 'The password should be at least %d characters long' => 'Ο κωδικός πρέπει να αποτελείται από τουλάχιστον %d χαρακτήρες', 'There are no confirmed payments for your account' => 'Δεν υπάρχουν πληρωμές στο λογαριασμό σας', 'This %s is blocked. Please contact site support to find out why' => 'Το %s είναι απαγορευμένο. Επικοινωνείστε με τον Διαχειριστή', 'This coupon belongs to another customer' => 'Ο εκπτωτικός κωδικός που δώσατε, ανήκει σε άλλο μέλος', 'This is a required field' => 'Υποχρεωτικό στοιχείο', 'This page will be automatically refreshed within %s' => 'Η σελίδα θα ανανεωθεί αυτόματα σε %s', 'This payment system could not handle payments in [%s] currency' => 'Δεν επιτρέπεται να χρησιμοποιηθεί σε πληρωμής σε νόμισμα [%s]', 'This payment system could not handle zero-total invoices' => 'Δεν επιτρέπεται να χρησιμοποιηθεί σε τιμολόγια μηδενικής αξίας', 'Ticket' => 'Υπόθεση', 'Ticket has been submited' => 'Το πρόβλημα σας καταχωρήθηκε', 'Ticket#' => 'Υπόθεση#', 'Tickets' => 'Υποθέσεις', 'Title' => 'Τίτλος', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Για να προσθέσετε στοιχεία στη φόρμα, επιλέξτε απο τα \'Διαθέσιμα Στοιχεία\' στο \'Στοιχεία Φόρμας\'. Για να τα διαγράψετε σύρτε τα πάλι πίσω στα \'Διαθέσιμα Στοιχεία\'. Για να κάνετε τη φόρμα πολλαπλών σελίδων εισάγετε τον \'Διαχωριστή Σελίδων\' στο σημείο που θέλετε να γίνει αλλαγή σελίδας', 'Total' => 'Σύνολο', 'Try again' => 'Ξαναπροσπαθήστε', 'Unknown period unit: %s' => 'Αγνωστος τύπος χρονικής περιόδου: %s', 'Unsubscribe from all e-mail messages' => 'Διαγραφή από όλα τα ενημερωτικά μηνύματα', 'Unsubscription Confirmation' => 'Επιβεβαίωση διαγραφής', 'Untick checkbox to cancel subscription' => 'Απενεργοποιήστε την επιλογή για να ακυρώσετε την συνδρομή', 'Update' => 'Ενημέρωση', 'Update Credit Card Info' => 'Ενημέρωση στοιχείων Πιστωτικής Κάρτας', 'Update your commissions payout info' => 'Ενημέρωση στοιχείων πληρωμής', 'Updated' => 'Ενημέρωση', 'Upgrade Subscription' => 'Αναβάθμιση Συνδρομής', 'Use Database Connection other than configured for aMember' => 'Χρησιμοποίηση σύνδεσης βάσης δεδομένων άλλης απο αυτής του aMember', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Χρησιμοποίηση άλλης βάσης MySQL Δώστε το όνομα εξυπηρετητή, χρήστη, κωδικού για την σύνδεση %sΣυνήθως μπορείτε να το αφήσετε ατσεκάριστο', 'User' => 'Μέλος', 'User Agreement' => 'Οροι Συμφωνίας Μέλους', 'User Info' => 'Στοιχεία Μέλους', 'User Search' => 'Αναζήτηση Μέλους', 'User is not found in database' => 'Ο χρήστης δεν βρέθηκε', 'Username' => 'Ψευδώνυμο', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Ονομα χρήστη μπορείτε να επιλέξετε ένα νέο όνομα, ή να κρατήσετε αυτό που έχετε Το όνομα χρήστη πρέπει να είναι τουλάχιστον %d χαρακτήρες και μπορεί να περιλαμβάνει μόνο μικρά γράμματα, αριθμούς και κάτω παύλες', 'Username %s has been taken by another user' => 'Το ψευδώνυμο %s που διαλέξατε, χρησιμοποιείται ήδη από άλλο χρήστη', 'Username %s is already taken. Please choose another username' => 'Το όνομα χρήστη %s χρησιμοποιείται ήδη από κάποιον άλλον. Παρακαλούμε επιλέξτε κάτι διαφορετικό', 'Username [%s] does not exist in database' => 'Χρήστης με ψευδώνυμο [%s] δεν υπάρχει στο σύστημα', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Το ψευδώνυμο περιέχει απαράδεκτους χαρακτήρες. Χρησιμοποιήστε μόνο αριθμούς και γράμματα', 'Username contains invalid characters - please use digits, letters or spaces' => 'Το ψευδώνυμο περιέχει απαράδεκτους χαρακτήρες. Χρησιμοποιήστε μόνο αριθμούς, γράμματα και κενά διαστήματα', 'Users subscribed to Newsletter Threads #' => 'Μέλη που είναι συνδρομητές στο ενημερωτικό #', 'Validate E-Mail Address by sending e-mail message with code' => 'Επαλήθευση email διεύθυνσης με αποστολή μηνύματος με τον κωδικό επιβεβαίωσης', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'Μήνυμα επιβεβαίωσης ηλεκτρονικής διεύθυνσης στάλθηκε με επιτυχία. Η ηλεκτρονική σας διεύθυνση θα αλλάξει αμέσως μετά την επιβεβαίωση', 'View Basket' => 'Εμφάνιση Παραγγελίας', 'Visit %sorder page%s to order additional subscriptions' => 'Επισκεφτείτε στη σελίδα %sπαραγγελιών%s για να προσθέσετε νέα προϊόντα', 'Week' => 'Εβδομάδα', 'Wrong Upgrade Path selected' => 'Επιλέξατε λάθος path αναβάθμισης', 'Wrong code entered or confirmation link expired' => 'Λάθος κωδικός ή το Link έχει λήξει', 'Wrong code or code expired - please start signup process again' => 'Λάθος κωδικός, ή ο κωδικός έληξε. Παρακαλούμε αρχίστε την εγγραφή από την αρχή', 'Wrong parameters, error #1253' => 'Λάθος παράμμετροι, κωδικός λάθους #1253', 'Wrong verification code' => 'Λάθος κωδικός επιβεβαίωσης', 'Wrongly signed URL, please contact site admin' => 'Λάθος στό URL εγγραφής, παρακαλούμε επικοινωνήστε με τον Διαχειριστή', 'Year' => 'Ετος', 'Years' => 'Ετη', 'Yes, I want to cancel subscription' => 'ΝΑΙ, θέλω να ακυρώσω τη συνδρομή μου', 'Yes, continue' => 'ΝΑΙ, συνεχίστε', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Είστε στο σύστημα σαν %s. %sΕξέλθετε%s για να εγγραφείτε σαν νέο Μέλος.', 'You can select more than one item - keep "Ctrl" key pressed' => 'Μπορείτε να κάνετε πολλαπλή επιλογή κρατώντας πατημένο το πλήκτρο Ctrl', 'You have no access to %s' => 'Δεν έχετε πρόσβαση στο %s', 'You have no active subscriptions' => 'Δεν έχετε καμμιά ενεργή συνδρομή', 'You have no enough permissions for this operation' => 'Δεν έχετε την απαραίτητη άδεια γιαυτή την εργασία', 'You have no items in your basket - please add something to your basket before checkout' => 'Η παραγγελία σας είναι άδεια. Παρακαλώ προσθέστε κάποιο προϊόν πριν πάτε στο ταμείο', 'You have not verified your e-mail address, so login is not%sallowed. Please check your mailbox for e-mail verification message and%sclick link to be verified. If you have not receive verification message,%splease click %sthis link%s and we will resend you verification message.' => 'Δεν έχετε επιβεβαιώσει την ηλεκτρονική σας διεύθυνση, γιαυτό και η είσοδος στη περιοχή μελών δεν%sεπιτρέπεται. Παρακαλούμε ελέγξτε την ηλεκτρονική σας αλληλογραφία για να βρείτε το μήνυμα σχετικά με την επιβεβαίωση και %sπατήστε το link για να επιβεβαιώσετε την εγγραφή σας. Εαν δεν βρείτε τέτοιο μήνυμα, τότε %sπατήστε%sαυτό το link%s για να σας το ξαναστείλουμε.', 'You must be authorized to access this area' => 'Πρέπει να κάνετε πιστοποίηση στοιχείων για να εισέλθετε σαυτή την περιοχή', 'You will be redirected to protected area' => 'Ανακατευθύνεστε σε προστατευόμενη περιοχή', 'You will only have to do this once. If you don\'t have an account with us, please %ssignup%s' => 'Αυτό θα γίνει μόνο μια φορά. Αν δέν έχετε λογαριασμό με εμάς, %sδημιουργήστε%s ένα τώρα', 'Your Active Subscriptions' => 'Ενεργές Συνδρομές', 'Your Basket' => 'Το καλάθι σας', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Ο τωρινός σας κωδικός αν αλλάζετε τον κωδικό σας, παρακαλούμε δώστε τον τωρινό σας κωδικό για επιβεβαίωση', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Η Email διεύθυνση σας ενα επιβεβαιωτικό μήνυμα θα σταλεί σε αυτή τη διεύθυνση', 'Your Membership Information' => 'Πληροφορίες Μέλους', 'Your Subscriptions' => 'Οι Συνδρομές σου', 'Your e-mail address was not found in database' => 'Το Email σας δεν βρέθηκε στη βάση δεδομένων', 'Your email address has been changed' => 'Η ηλεκτρονική σας διεύθυνση άλλαξε με επιτυχία', 'Your message is too verbose' => 'Το μήνυμα σας είναι υπερβολικά μεγάλο', 'Your password has been e-mailed to you' => 'Ο κωδικός σας στάλθηκε με επιτυχία', 'Your password is too long' => 'Ο κωδικός σας έχει υπερβολικά πολλούς χαρακτήρες', 'Your payment has been succesfully processed.' => 'Η πληρωμή σας πραγματοποιήθηκε με επιτυχία', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Η πληρωμή σας δεν επιβεβαιώθηκε ακόμη. Μπορεί να χρειαστεί να περιμένετε αρκετά λεπτά της ώρας μέχρι να οριστικοποιηθεί', 'Your subject is too verbose' => 'Το θέμα σας είναι υπερβολικά μακρύ', 'Your subscription has been succesfully processed.' => 'Η συνδρομή σας ενεργοποιήθηκε με επιτυχία', 'ZIP' => 'ΤαχΚωδ', 'ZIP Code' => 'ΤαχΚωδ', '[Select country]' => '[Επιλέξτε Χώρα]', '[Select state]' => '[Επιλέξτε Πολιτεία]', '_default_locale' => 'el', 'admin' => 'Διαχειριστής', 'affiliate program commissions' => 'Προμήθειες Διαφημιστικού Προγράμματος', 'ago' => 'πριν', 'banned' => 'αποβλημένοι', 'cardholder first and last name, exactly as%son the card' => 'Ονοματεπώνυμο κατόχου, ακριβώς όπως εμφανίζεται %s στη κάρτα ', 'commission found by next rules' => 'προμήθεια που υπόκειται στους παρακάτω όρους', 'customer / affiliate status' => 'κατάσταση Πελάτη/Διαφημιστή', 'customer service phone number listed on back of your credit card' => 'αριθμός τηλεφώνου του τμήματος εξυπηρέτησης πελατών της τράπεζας', 'days' => 'ημέρες', 'displaying records %d-%d from %d' => 'εμφάνιση εγγραφών %d-%d επι συνόλου %d', 'email' => 'email', 'expiration' => 'λήξη', 'filtered' => 'με κριτήρια', 'for example: 1111-2222-3333-4444' => 'παράδειγμα: 1111-2222-3333-4444', 'for international provinces outside of US & Canada include the province name here' => 'Για χώρες εκτός ΗΠΑ και Καναδά, δώστε το νομό διαμονής', 'hrs' => 'ώρες', 'ip' => 'ip', 'is required for Maestro/Solo/Switch credit cards only' => 'μόνο για τις κάρτες τύπου Maestro/Solo/Switch', 'just now' => 'μόλις τώρα', 'login' => 'Είσοδος', 'min' => 'λεπτά', 'name of the bank which issued the credit card' => 'ονομα της εκδότριας τράπεζας', 'no records' => 'καμμία εγγραφή', 'number of affiliate program clicks' => 'αριθμός εμφανίσεων απο το διαφημιστικό πρόγραμμα', 'of products' => 'απο προϊόντα', 'on %d-th day' => 'την %d-η μέρα', 'pay using credit card or PayPal' => 'πληρωμή μέσω PayPal ή πιστωτικής κάρτας', 'pay using wire transfer or by sending offline check' => 'πληρωμή μέσω τραπεζικού εμβάσματος ή Επιταγής', 'please select one' => 'Παρακαλώ επιλέξτε ένα', 'return' => 'επιστροφή', 'seconds' => 'δευτερόλεπτα', 'start' => 'εναρξη', 'the company name associated with the%sbilling address for the transaction' => 'Ονομα Εταιρείας σύμφωνη με την%sδιεύθυνση πληρωμής ', 'to order or renew subscription.' => 'για να ανανεώσετε τη συνδρομή', 'use 4111-1111-1111-1111 for successful transaction' => 'Δώστε 4111-1111-1111-1111 για επιτυχημένη πληρωμή', ); PK\Qslldefault/language/user/fr.phpnu[ '"%s" ne peut être commandé que avec ces produits/abonnements: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" ne peut être commandé si votre abonnement a expiré pour ces produits: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" ne peut être commandé parce que les abonnements à %s sont actifs .', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" ne peut être commandé parce que les abonnements à %s ont expiré.', '%d-th day' => '%d-è jour', '%s database and tables prefix' => 'Base de données %s et préfixes de tables', 'Access' => 'Accès', 'Access Denied' => 'Accès refusé', 'Access Log' => 'Enregistrement des accès', 'Access Permissions' => 'Permissions d\'accès', 'Actions' => 'Actions', 'Active' => 'Actif', 'Active Users' => 'Utilisateurs actifs', 'Add User' => 'Ajouter utilisateur', 'Add to Basket' => 'Ajouter au panier', 'Add/Renew Subscription' => 'Ajouter/renouveler un abonnement', 'Added' => 'Ajouté', 'Additional Fields' => 'Champs additionnels', 'Address Info' => 'Information adresse', 'Address Information' => 'Informations d\'adresse', 'Admin' => 'Admin', 'Admin Username' => 'Nom d\'utilisateur Admin', 'Administrator' => 'Administrateur', 'Advanced' => 'Avancé', 'Advanced Search' => 'Recherche avancée', 'Advertise our website to your friends and earn money' => 'Parlez de notre site à vos amis et gagnez de l\'argent', 'Affiliate' => 'Affillié', 'Affiliate Info' => 'Informations de l\'affilié', 'Affiliate Payout Type' => 'Type de paiement affilié', 'Affiliate Program' => 'Programme affilié', 'Affiliate Signup Form' => 'Formulaire d\'inscription affilié', 'Affiliate info' => 'information de la filiale', 'Affiliate stats' => 'Statistiques de filiale', 'Affiliates' => 'Affilié', 'All' => 'Tout', 'All Affiliates' => 'Tous les affiliés', 'All Users' => 'Tous les utilisateurs', 'All records' => 'Tous les enregistrements', 'Amount' => 'Montant', 'An Error has occurred' => 'Une erreur est survenue', 'An account with the same email already exists.' => 'Un compte avec la même adresse email existe déjà.', 'An error occurred while handling your payment.' => 'Une erreur est survenue à votre paiement', 'An internal error happened in the script, please contact webmaster for details' => 'Une erreur interne est survenue dans ce script. Contactez le webmaster', 'Any Product' => 'N\'importe quel Produit', 'Any product' => 'N\'importe quel produit', 'Apply' => 'Appliquer', 'Apply Filter' => 'Appliquer le filtre', 'Attachments' => 'Pièces jointes', 'Authentication' => 'Authentication', 'Authentication problem, please contact website administrator' => 'Problème d\'authentification, contactez l\'administrateur du site', 'Available Bricks (drag to left to add)' => 'Briques disponibles (faites glisser vers la gauche pour ajouter)', 'Awaiting Admin Response' => 'En attente de la réponse de l\'administrateur', 'Awaiting User Response' => 'En attente de la réponse de l\'utilisateur', 'Back' => 'Retour', 'Bank Identification' => 'Identifiant de la banque', 'Bank Name' => 'Nom de la banque', 'Banners and Links' => 'Bannières et liens', 'Banners and Text Links' => 'Gérer les bannières et liens texte', 'Begin Date' => 'Date de démarrage', 'Both Affiliate and member' => 'Affilié et membre', 'CC Demo' => 'Démo CC', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'Erreur de protection CSRF - le formulaire doit être à nouveau soumis moins de %d minutes après affichage, veuillez recommencer', 'Can view/edit customer Credit Card information and rebills' => 'Possibilité de voir/éditer les informations de carte de crédit clients et de refacturer', 'Cancel' => 'Annuler', 'Cancel Subscription' => 'Annuler l\'abonnement', 'Cancelled' => 'annulé', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Vous ne pouvez pas utiliser le plugin de paiement FREE pour un produit qui coûte plus de 0.0', 'Category' => 'Catégorie', 'Change' => 'Changer', 'Change Password' => 'Changez le mot de passe', 'Change Password/Edit Profile' => 'Changez votre mot de passe/Éditer votre profil', 'Change Subscription' => 'Changer l\'abonnement', 'Change Username' => 'Changer le nom d\'utilisateur', 'Change payout info' => 'Changez les informations de paiement', 'Checkout' => 'Facturation', 'Checkout error: ' => 'Erreur de facturation', 'Choose a Password must be %d or more characters' => 'Choisissez un mot de passe il doit contenir %d caractères ou plus', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Choisissez un nom d\'utilisateur il doit contenir %d caractères ou plus ne peut contenir que des lettres, chiffres et underscores', 'City' => 'Ville', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Cliquez ici si vous ne voulez pas attendre plus longtemps (ou si votre navigateur ne vous redirige pas automatiquement)', 'Clicks' => 'Clics', 'Clicks/Sales Statistics' => 'Clics affiliés/Statistiques de vente', 'Close' => 'Fermer', 'Close Ticket' => 'Fermer un ticket', 'Closed' => 'Fermé', 'Code' => 'Code', 'Comment' => 'Commentaire', 'Comment for admin reference' => 'Commentaire pour référence administrateur', 'Commission' => 'Commission', 'Commissions' => 'Commissions', 'Configuration' => 'Configuration', 'Configured Tax Values' => 'Configurer les valeurs taxe', 'Confirm' => 'Confirmer', 'Confirm New Password' => 'Confirmez le nouveau mot de passe', 'Confirm Password' => 'Confirmez le mot de passe', 'Confirm Payment' => 'Confirmer le paiement', 'Confirm Your Password' => 'Confirmez votre mot de passe', 'Continue' => 'Continuer', 'Conversation' => 'Conversation', 'Country' => 'Pays', 'Coupon' => 'Coupon', 'Coupon Discount' => 'Coupon de réduction', 'Coupon code disabled' => 'Code coupon désactivé', 'Coupon code expired' => 'Code coupon expiré', 'Coupon is not yet active' => 'Le coupon n\'est pas encore actif', 'Coupon usage limit exceeded' => 'Limite d\'utilisation du coupon dépassée', 'Credit Card Code' => 'Code de carte de crédit', 'Credit Card Info' => 'Informations de carte de crédit', 'Credit Card Number' => 'Numéro de carte de crédit', 'Credit Card Rebills' => 'Refacturations de la carte de crédit', 'Credit Cards' => 'Cartes de crédit', 'Currency' => 'Monnaie', 'Currency Exchange Rates' => 'Taux de change', 'Current password entered incorrectly, please try again' => 'Le mot de passe actuel n\'a pas été saisi correctement, veuillez réessayer', 'Custom Commission' => 'Commission client', 'DONE' => 'FAIT', 'Dashboard' => 'Tableau de bord', 'Date' => 'Date', 'Date and time of payment: %s' => 'Date et heure de paiement: %s', 'Date must be in format %s' => 'La date doit être en format %s', 'Date/Time' => 'Date/heure', 'Day' => 'Jour', 'Days' => 'Jours', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Niveau par défaut Niveau par défaut - utilisateur réinitialisé à ce niveau d\'accès si aucun abonnement n\'existe (par exemple, tous les abonnements ont expiré)', 'Delete' => 'Supprimer', 'Delete %s' => 'Supprimer %s', 'Description' => 'Description', 'Disabled' => 'Désactivé', 'Discard' => 'Annuler', 'Discount' => 'réduction', 'Display Type' => 'Type d\'affichage', 'Do you really want to %s %s %s records' => 'Souhaitez-vous réellement %s %s %s les enregistrements ?', 'Do you really want to %s?' => 'Voulez-vous vraiment %s?', 'Do you really want to cancel subscription?' => 'Voulez-vous réellement annuler votre abonnement?', 'Do you really want to delete record?' => 'Souhaitez-vous réellement effacer l\'enregistrement ?', 'Done' => 'Effectué', 'E-Mail' => 'Email', 'E-Mail Address' => 'Adresse email', 'E-Mail Format' => 'Format d\'email', 'E-Mail Messages' => 'Messages E-Mail', 'E-Mail Verification' => 'Vérification de l\'email', 'Edit' => 'Éditer', 'Edit %s' => 'Modifier %s', 'Edit Brick Labels' => 'Modifier les noms des briques', 'Edit E-Mail Template' => 'Éditer le modèle d\'email', 'Email' => 'Email', 'Email Subject' => 'Sujet de l\'Email', 'Enabled Modules' => 'Modules activés', 'End' => 'Fin', 'End Date' => 'Date de fin', 'Error 404 - Not Found' => 'Erreur 404 - non trouvé', 'Expire Date' => 'Date d\'expiration', 'Expired' => 'Expiré', 'Expired Users' => 'Utilisateurs expirés', 'Export' => 'Exporter', 'Export Format' => 'Format de l\'exportation', 'Field' => 'Champ', 'Field Type' => 'Type de champ', 'Field Updated' => 'Champ mis à jour', 'Fields To Export' => 'Champs à exporter', 'File' => 'Fichier', 'Filename' => 'Nom du fichier', 'Files' => 'Fichiers', 'Filter' => 'Filtrez', 'First & Last Name' => 'Prénom et nom de famille', 'First Name' => 'Prénom', 'Folders' => 'Dossiers', 'Form Page Break' => 'Former une séparation de page', 'Free' => 'Vide', 'Free Access' => 'Accès libre', 'From' => 'Depuis', 'Get Password' => 'Trouvez un mot de passe', 'HTML Message' => 'Message HTML', 'Having Active Subscription To:' => 'Avoir un abonnement actif à :', 'Having Expired Subscription To:' => 'Avoir un abonnement expiré à :', 'Helpdesk' => 'Bureau d\'aide', 'Housenumber' => 'Numéro de maison', 'IP Address' => 'Adresse IP', 'Integer Value' => 'Valeur entière', 'Integer value required' => 'Valeur entière requise', 'Integrations' => 'Intégrations', 'Invalid Credit Card Number' => 'Numéro de carte de crédit invalide', 'Invalid Expiration Date - Month' => 'Date d\'expiration invalide - mois', 'Invalid Expiration Date - Year' => 'Date d\'expiration invalide - année', 'Invalid Issue Number' => 'Numéro de problème invalide', 'Invite Code' => 'Code d\'invitation', 'Invoice' => 'Facture', 'Invoice not found' => 'Facture introuvable', 'Is Locked' => 'Est verrouillé', 'Is Paid?' => 'est payé ?', 'Item' => 'Objet', 'Language' => 'Langue', 'Last Name' => 'Nom', 'Leads' => 'Prospects', 'License Key' => 'Numéro de licence', 'Lifetime' => 'Vie', 'Link' => 'Lien', 'Links' => 'Liens', 'Live Edit %s' => 'Modification en direct %s', 'Log In' => 'Connexion', 'Login' => 'Se connecter', 'Logout' => 'Se déconnecter', 'Lost Password Sending Error' => 'Erreur d\'envoi du mot de passe perdu', 'Lost Password Sent' => 'Mot de passe perdu envoyé', 'Lost password?' => 'Mot de passe perdu', 'Mail Queue' => 'Mails en attente', 'Make Payment' => 'Faire un paiement', 'Manage Newsletters' => 'Gérer les lettres d\'informations', 'Marketing Materials' => 'Matériaux marketing', 'Membership Type' => 'Type d\'abonnement', 'Message' => 'Message', 'Message can not be empty' => 'Le message ne peut pas être vide', 'Month' => 'Mois', 'Months' => 'Mois', 'Multiplier' => 'Multiplicateur', 'Name' => 'Nom', 'Never' => 'Jamais', 'New' => 'Nouveau', 'New %s' => 'Nouveau %s', 'New Password' => 'Nouveau mot de passe', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Nouveau mot de passe vous pouvez choisir un nouveau mot de passe, ou conserver le même il doit contenir %d caractères ou plus', 'Newsletter' => 'Lettre d\'information', 'Newsletter Subscriptions' => 'Inscriptions newsletter', 'Next' => 'Suivant', 'No' => 'Non', 'No commissions on this date' => 'Aucune commission à ce jour', 'No coupons found with such coupon code' => 'Aucun coupon trouvé avec ce code', 'No items selected for purchase' => 'Aucun objet sélectionné pour achat', 'No records found' => 'Aucun dossier trouvé', 'No, cancel' => 'No, annuler', 'No, please keep me subscribed' => 'Non, je veux être encore inscrit', 'Not Selected' => 'Non sélectionné', 'Not registered yet?' => 'Pas encore enregistré', 'Numeric Value' => 'Valeur Numérique', 'Numeric value required' => 'Valeur numérique requise', 'Offline Payment' => 'Paiement hors ligne', 'Only Affiliate %s(rarely used)%s' => 'Affilier seulement %s (rarement utilisé) %s', 'Order reference: %s' => 'Référence de commande: %s', 'Pages' => 'Pages', 'Password' => 'Mot de passe', 'Password and Password Confirmation are different. Please reenter both' => 'Le mot de passe et la confirmation du mot de passe sont différents. Veuillez saisir à nouveau les deux', 'Password must contain at least %d letters or digits' => 'Le mot de passe doit contenir au moins %d lettres ou chiffres', 'Passwords do not match' => 'Les mots de passe ne correspondent pas', 'Path to %s' => 'Chemin vers %s', 'Path to %s Folder' => 'Chemin vers le dossier %s', 'Payment Error' => 'Erreur de paiement', 'Payment Failed' => 'Échec du paiement', 'Payment System' => 'Système de paiement', 'Payment System Description' => 'Description du système de paiement', 'Payment System Title' => 'Titre du système de paiement', 'Payment error: ' => 'Erreur de paiement', 'Payment failed' => 'Échec du paiement', 'Payments' => 'Paiements', 'Payments History' => 'Historique de paiement', 'Payout Method' => 'Méthode de paiement', 'Payouts' => 'Paiements', 'Pending' => 'En attente', 'Period must be in interval 1-24 months' => 'Les périodes doivent être entre 1 et 24 mois', 'Period must be in interval 1-5 years' => 'Les périodes doivent être entre 1 et 5 ans.', 'Period must be in interval 1-90 days' => 'Les périodes doivent être entre 1 et 90 jours', 'Phone' => 'Numéro de téléphone', 'Plain-Text Message' => 'Message en texte', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Veuillez %s vous connecter %s à votre compte existant. %s Si vous n\'avez pas effectué le paiement, vous pourrez le compléter après la connexion', 'Please Select' => 'Veuillez sélectionner', 'Please agree to User Agreement' => 'Veuillez accepter l\'Accord utilisateur', 'Please choose' => 'Veuillez choisir', 'Please choose a Credit Card Type' => 'Veuillez choisir un type de carte de crédit', 'Please choose a membership type' => 'Veuillez choisir un type d\'abonnement', 'Please choose a payment system' => 'Veuillez choisir un système de paiement', 'Please choose state' => 'Choisir l\'état', 'Please enter %s' => 'Veuillez saisir %s', 'Please enter City' => 'Entrez le nom de la ville', 'Please enter Country' => 'Entrez le pays', 'Please enter Credit Card Code' => 'Veuillez entre le code de carte de crédit', 'Please enter Credit Card Number' => 'Entrez votre numéro de carte de crédit', 'Please enter Password' => 'Veuillez saisir le mot de passe', 'Please enter State' => 'Entrez l\'état', 'Please enter Street Address' => 'Entrez le nom de la rue', 'Please enter ZIP code' => 'Entrez le code postal', 'Please enter a valid e-mail address' => 'Entrez une adresse email valide', 'Please enter credit card holder first name' => 'Entrez le prénom du propriétaire de la carte', 'Please enter credit card holder last name' => 'Veuillez entrer le nom de famille du propriétaire de la carte', 'Please enter credit card holder name' => 'Entrez le nom du propriétaire de la carte', 'Please enter housenumber' => 'Entrez le numéro de maison', 'Please enter phone number' => 'Entrez un numéro de téléphone', 'Please enter valid Email' => 'Veuillez saisir une adresse email valide', 'Please enter valid Username. It must contain at least %d characters' => 'Veuillez saisir un nom d\'utilisateur valide. Il doit contenir au moins %d caractères.', 'Please enter your First Name' => 'Veuillez saisir votre prénom', 'Please enter your Last Name' => 'Veuillez saisir votre nom de famille', 'Please enter your current password for validation' => 'Veuillez saisir votre mot de passe actuel pour valider', 'Please login' => 'Veuillez vous connecter', 'Please select an item...' => 'Veuillez choisir une proposition...', 'Please select payment system for payment' => 'Sélectionner le système de paiement', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Utiliser le %sformulaire d\'ajout/renouvellement%s d\'inscription pour commander ou renouveler l\'inscription', 'Please wait %d seconds before next login attempt' => 'Attendez %d secondes avec de vous connecter à nouveau', 'Plugin' => 'Plugin', 'Prev' => 'Préc', 'Preview' => 'Prévisualisation', 'Price' => 'Prix', 'Product' => 'Produit', 'Product Categories' => 'Catégories produit', 'Product(s) to display' => 'Produit(s) à afficher', 'Products' => 'Produits', 'Profile' => 'Éditer le profil', 'Qty' => 'Qté', 'Quantity' => 'Quantité', 'Quick Order' => 'Commande rapide', 'Re-Open Ticket' => 'Réouvrir un ticket', 'Record' => 'Enregistrement', 'Records that match all these conditions' => 'Enregistrements qui correspondent à toutes ces conditions', 'Recurring' => 'Récurrent', 'Reference number is:' => 'Le numéro de référence est', 'Referer' => 'Référant', 'Referred Affiliate' => 'Filiale', 'Refresh' => 'Rafraîchir', 'Refund' => 'Rembourser', 'Refunded' => 'Remboursé', 'Register' => 'S\'enregistrer', 'Remove' => 'Supprimer', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Supprimer des utilisateurs lorsque les enregistrements d\'un utilisateur sont supprimés l\'enregistrement lié doit être supprimé de %s', 'Reply' => 'Répondre', 'Return' => 'Retour', 'Return and try again' => 'Retourner et réessayer', 'Review/Pay Commissions' => 'Revoir/Commission affiliée', 'Run Report' => 'Lancer le rapport', 'Running %s' => 'Exécution de %s', 'Save' => 'Enregistrer', 'Save Profile' => 'Profil enregistré', 'Search' => 'Rechercher', 'Search Products' => 'Chercher les produits', 'Security code is invalid' => 'Le code sécurité est invalide', 'Select a condition to add into search' => 'Sélectionnez une condition à ajouter à la recherche', 'Send' => 'Envoyer', 'Session expired, please enter username and password again' => 'Session expirée, entrez le nom d\'utilisateur et mot de passe à nouveau', 'Shipping' => 'Expédition', 'Shopping Cart' => 'Panier', 'Sign-up' => 'Se connecter', 'Signup Form' => 'Formulaire d\'inscription', 'Signup here' => 'Connectez-vous ici', 'Simple Search Users' => 'Recherche d\'utilisateurs simple', 'Site Title' => 'Titre du site', 'Skip First Line' => 'Sauter la première ligne', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Désolé, il est impossible d\'utiliser cette méthode de paiement pour cette commande. Veuillez choisir une autre méthode de paiement.', 'Sorry, seems you have used wrong link' => 'Désolé, il semblerait que vous ayez utilisé le mauvais lien', 'Source Code — Copy/Paste Into Your Website' => 'Code source — copier/coller sur votre site', 'Start' => 'Début', 'Start Date' => 'Date de début', 'State' => 'État', 'Status' => 'Statut', 'Street' => 'Rue', 'Street Address' => 'Rue', 'Subject' => 'Sujet', 'Subject can not be empty' => 'Les sujets ne peuvent pas être vide', 'Subscribe to Site Newsletters' => 'S\'abonner aux newsletters du site', 'Subscribers' => 'Abonnés', 'Subscription Terms' => 'Conditions d\'abonnement', 'Subscription/Product Title' => 'Titre d\'abonnement/produit', 'Subtotal' => 'Sous-total', 'Target URL' => 'URL cible', 'Tax' => 'Taxe', 'Tax Amount' => 'Taxe', 'Tax Value' => 'Valeur de taxe', 'Terms' => 'Conditions', 'Test Settings' => 'Options de test', 'Thank you for Signing up' => 'Merci de vous être enregistré', 'The database has encountered a problem, please try again later.' => 'La base de données a rencontré un problème, recommencez plus tard.', 'The password should be at least %d characters long' => 'Le mot de passe doit être plus long que %d caractères.', 'There are no confirmed payments for your account' => 'Il n\'y a pas de paiement confirmé pour votre compte', 'This %s is blocked. Please contact site support to find out why' => 'Le %s est bloqué. Veuillez contacter le support du site pour découvrir pourquoi', 'This coupon belongs to another customer' => 'Ce coupon appartient à un autre client', 'This field is required' => 'Ce champ est requis', 'This is a required field' => 'Ceci est un champ requis', 'This page will be automatically refreshed within %s' => 'Cette page va être automatiquement rafraîchie dans %s', 'This payment system could not handle payments in [%s] currency' => 'Ce système de paiement ne peut pas manipuler la devise [%s]', 'This payment system could not handle zero-total invoices' => 'Ce système de paiement ne peut pas manipuler les factures avec un total de zéro.', 'Thresehold Date' => 'Date limite', 'Ticket' => 'Ticket', 'Ticket has been submited' => 'Le ticket a été soumis', 'Tickets' => 'Tickets', 'Title' => 'Titre', 'To' => 'à', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Pour ajouter des champs au formulaires, déplacer des éléments de \'Briques disponibles\' à \'Former briques\'. Pour supprimer des champs, redéplacez-les vers \'Briques disponibles\'. Pour que le formulaire fasse plusieurs pages, insérez l\'élément \'PageSeparator\' à l\'endroit où vous voulez que les pages soient partagées.', 'Total' => 'Total', 'Try again' => 'Réessayer', 'Type' => 'Type', 'Unknown period unit: %s' => 'Unité de période inconnue: %s', 'Unsubscribe from all e-mail messages' => 'Se désinscrire de tous les emails', 'Unsubscription Confirmation' => 'Confirmation de la désinscription', 'Update' => 'Mise à jour', 'Update Credit Card Info' => 'Mise à jour des informations de carte de crédit', 'Updated' => 'Mis à jour', 'Upgrade Subscription' => 'Mettre à jour l\'abonnement', 'Use Database Connection other than configured for aMember' => 'Utiliser la connexion à la base de données autrement que configurée pour un membre', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Utiliser une autre base de données MySQL utiliser un hôte personnalisé, un utilisateur et mot de passe pour la connexion à la base de données %s. Vous pouvez généralement laisser ceci décoché', 'Useful Links' => 'Liens utiles', 'User' => 'Utilisateur', 'User Agreement' => 'Accord utilisateur', 'User Groups' => 'Groupes d\'utilisateurs', 'User Info' => 'Informations de l\'utilisateur', 'User Search' => 'Recherche d\'utilisateur', 'Username' => 'Nom d\'utilisateur', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Nom d\'utilisateur vous pouvez choisir un nouveau nom d\'utilisateur, ou conserver le même. Le nom d\'utilisateur doit contenir %d caractères ou plus et ne peut contenir que des lettres minuscules, chiffres et underscores', 'Username %s is already taken. Please choose another username' => 'Le nom d\'utilisateur %s est déjà pris. Veuillez choisir un autre nom d\'utilisateur', 'Username contains invalid characters - please use digits, letters or spaces' => 'Le nom d\'utilisateur contient des caractères invalides - utilisez des chiffres, lettres ou espaces', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Le nom d\'utilisateur contient des caractères invalides - utilisez des nombres et des lettres', 'Username/Email' => 'Adresse mail ou nom d\'utilisateur', 'Users subscribed to Newsletter Threads #' => 'Utilisateurs abonnés aux sujets # de la lettre d\'informations', 'Validate E-Mail Address by sending e-mail message with code' => 'Valider l\'adresse email en envoyant un email avec un code', 'Validation' => 'Validation', 'View Basket' => 'Voir le panier', 'Week' => 'Semaine', 'Wrong code or code expired - please start signup process again' => 'Code incorrect ou expiré - veuillez recommencer votre inscription', 'Wrong parameters, error #1253' => 'Paramètres erronés, erreur #1253', 'Wrong password' => 'Mot de passe erroné', 'Wrong verification code' => 'Code vérification erroné', 'Wrongly signed URL, please contact site admin' => 'URL mal signée, contactez l\'administrateur du site', 'Year' => 'Année', 'Years' => 'Années', 'Yes, I want to cancel subscription' => 'Oui je veux annuler l\'abonnement', 'Yes, continue' => 'Oui, continuer', 'You have no access to %s' => 'Vous n\'avez pas accès à %s', 'You have no active subscriptions' => 'Vous n\'avez pas d\'abonnement actif', 'You have no items in your basket - please add something to your basket before checkout' => 'Vous n\'avez aucun article dans votre panier - merci d\'ajouter quelque chose à votre panier avant la facturation', 'Your Basket' => 'Votre panier', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Votre mot de passe actuel si vous changez de mot de passe, veuillez entrer votre mot de passe actuel pour valider', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Votre adresse email un email de confirmation vous sera envoyé à cette adresse', 'Your Membership Information' => 'Vos informations de membre', 'Your Subscriptions' => 'Vos abonnements', 'Your password is too long' => 'Votre mot de passe est trop long', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Votre paiement n\'a pas encore été confirmé par le système de paiement. Cela pourra prenrde encore plusieurs minutes.', 'Your subject is too verbose' => 'Votre sujet est trop long', 'ZIP' => 'Code postal', 'ZIP Code' => 'Code postal', 'Zip' => 'Code postal', '[Select country]' => '[Sélectionner pays]', '[Select state]' => '[Sélectionner l\'état]', '_default_locale' => '_default_locale', 'admin' => 'administrateur', 'ago' => 'il y a', 'banned' => 'banni', 'commission found by next rules' => 'commission établie selon les règles suivantes', 'days' => 'jours', 'email' => 'email', 'filtered' => 'filtré', 'for example: 1111-2222-3333-4444' => 'par exemple: 1111-2222-333-4444', 'generate' => 'générer', 'hrs' => 'heures', 'ip' => 'ip', 'just now' => 'il y a un instant', 'login' => 'nom d\'utilisateur$', 'min' => 'min', 'no records' => 'aucun enregistrement', 'of products' => 'de produits', 'on %d-th day' => 'le %d-ième jour', 'or' => 'ou', 'pay using wire transfer or by sending offline check' => 'payer en utilisant un virement bancaire ou en envoyant un chèque', 'return' => 'retour', 'seconds' => 'secondes', 'use 4111-1111-1111-1111 for successful transaction' => 'utiliser 4111-1111-1111-1111 pour une transaction effectuée avec succès', ); PK\;oodefault/language/user/pt.phpnu[ 'para sempre', ' from ' => 'de', ' to ' => 'para', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" pode ser comprado apenas dentro desta inscrição: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" pode ser comprado se você tiver inscrições(ção) expirada(s) para estes produtos: %s ', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" não pode ser comprado por que você tem inscrição ativa em: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" não pode ser comprado por que você tem inscrição expirada em: %s', '%s database and tables prefix' => '%s base de dados e prefixo de tabelas', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Aceita Pagamentos Diretos trabalha com pagamentos feito no lado do sistema de pagamento (sem assinar o aMember primeiro)', 'Access' => 'Acessar', 'Access Denied' => 'Acesso Negado', 'Access Log' => 'Log de acesso', 'Access Permissions' => 'Permissão de Acesso', 'Actions' => 'Ações', 'Active Users' => 'Usuários Ativos', 'Add "Like" button' => 'Adicine botão "Curtir"', 'Add to Basket' => 'Adiciona na cesta', 'Add/Renew Subscription' => 'Adiciona/Reneva Assinatura', 'Address Info' => 'Endereço', 'Address Information' => 'Endereço', 'Admin' => 'admin', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupo de Administradores aMember nunca toca %s em suas contas atribuidas para os seguintes grupos. Estes projetos %s contas contra qualquer aMember atividade', 'Administrator' => 'Administrador', 'Advertise our website to your friends and earn money' => 'Anuncie nosso website para seus amigos e ganhe dinheiro', 'Affiliate Clicks' => 'Cliques dos afiliados', 'Affiliate Info' => 'Informação de Afiliado', 'Affiliate Payout Type' => 'Tipo de Prêmio para Afiliado', 'Affiliate Program' => 'Programa de Afiliado', 'Affiliate Sales' => 'Vendas de Afiliados(as)', 'Affiliate Signup Form' => 'Formulário de Inscrição de Afiliado', 'Affiliate info' => 'Informação de Afiliado', 'Affiliate stats' => 'Estatísticas de Afiliado(a)', 'Affiliates' => 'Afiliados', 'All %s records on this page are selected' => 'All %s registro(s) nesta página está(ão) selecionado(s)', 'All Affiliates' => 'Todos os Afiliados', 'All Users' => 'Todos os Usuários', 'All records' => 'Todos os Registros', 'Amount' => 'Total', 'An Error has occurred' => 'Ocorreu um erro', 'An account with the same email already exists.' => 'Já existe uma conta com o mesmo email.', 'An error occurred while handling your payment.' => 'Ocorreu um erro enquanto processávamos seu pagamento. ', 'An internal error happened in the script, please contact webmaster for details' => 'Ocorreu um um erro interno no script, por favor contate o suporte do site', 'Any Product' => 'Qualquer Produto', 'Any product' => 'Qualquer Produto', 'Apply' => 'Aplicar', 'Apply Filter' => 'Aplicar filtro', 'Attachments' => 'Anexos', 'Authentication' => 'Autenticação', 'Authentication problem, please contact website administrator' => 'Problema de autenticação, por favor contate o administrador do site', 'Available Bricks (drag to left to add)' => 'Bricks disponíveis (arraste para a esquerda para adicionar)', 'Awaiting Admin Response' => 'Aguardando Resposta do Administrador', 'Awaiting User Response' => 'Aguardando resposta do usuário', 'Back' => 'Voltar', 'Bank Identification' => 'Identificação do banco', 'Bank Name' => 'Nome do banco', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupo de Banidos aMember nunca toca %s contas atribuido aos seguintes grupos. Este protege %s contas contra qualquer atividade do aMember', 'Banners and Links' => 'Banners e Links', 'Banners and Text Links' => 'Gerencie Banners e Links de texto', 'Both Affiliate and member' => 'Ambos Afiliado e Membro', 'CC Demo' => 'CC Demo', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF erro de proteção - formulário deve ser submetido dentro de %d minutos depois de apresentado, por favor repita', 'Can view/edit customer Credit Card information and rebills' => 'Pode visualizar/editar Informação de Cartão de Crédito do cliente e cobrança', 'Cancel' => 'Cancelar', 'Cancel Subscription' => 'Cancelar inscrição', 'Cancelled' => 'Cancelado', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Não pode usar o plugin de pagamento GRÁTIS com o produto que custa mais de R$ 0,0', 'Category' => 'Categoria', 'Change' => 'Mudar', 'Change Password' => 'Muda Senha', 'Change Password/Edit Profile' => 'Mudar Senha/Editar Perfil', 'Change Subscription' => 'Mudar Assinatura', 'Change Username' => 'Mude Nome de Usuário (username)', 'Change payout info' => 'Troca informação de prêmio', 'Checkout' => 'Caixa', 'Checkout error: ' => 'Erro no checkout:', 'Choose a Password must be %d or more characters' => 'Escolha uma Senha deve ser %d ou mais caracteres', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Escolha um Nome de Usuário deve ter %d ou mais caracteres de tamanho deve conter somente letras, números ou underline', 'City' => 'Cidade', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Clique aqui se não deseja mais esperar (ou se seu brower não redirecioná-lo automaticamente).', 'Click to Edit' => 'Clique para Editar', 'Clicks' => 'Cliques', 'Clicks/Sales Statistics' => 'Afiliado(a) Cliques/Vendas Estatísticas', 'Close' => 'Fechar', 'Close Ticket' => 'Fechar Ticket', 'Closed' => 'Fechado', 'Comment' => 'Comentar', 'Confirm' => 'Confirme', 'Confirm New Password' => 'Confirme sua nova senha', 'Confirm Password' => 'Confirme Senha', 'Confirm Payment' => 'Confirme Pagamento', 'Confirm Your Password' => 'Confirme sua Senha', 'Continue' => 'Continue', 'Conversation' => 'Conversão', 'Country' => 'País', 'Coupon' => 'Cupom', 'Coupon Discount' => 'Cupom de Desconto', 'Coupon code disabled' => 'Código de cupom desabilitado', 'Coupon code expired' => 'Código do cupom expirou', 'Coupon is not yet active' => 'Cupom ainda não está ativo', 'Coupon usage limit exceeded' => 'Limite de uso do cupom excedido', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Cria usuário por Demanda silecionamente cria cliente no sistema se usuário tentar logar/acessar o sistema com o mesmo usuário e senha como para %s', 'Credit Card Code' => 'Código de Segurança do Cartão de Crédito', 'Credit Card Info' => 'Informação de Cartão de Crédito', 'Credit Card Number' => 'Número do Cartão de Crédito', 'Credit Card Rebills' => 'Cobrança Cartão de Crédito ', 'Credit Cards' => 'Cartões de Crédito', 'Current password entered incorrectly, please try again' => 'A senha atual inserida está incorreta, por favor entre novamente', 'Custom Commission' => 'Comissão Customizada', 'DONE' => 'FEITO', 'Date' => 'Data', 'Date and time of payment: %s' => 'Data e hora do pagamento: %s', 'Date must be in format %s' => 'Data deve estar neste formato %s', 'Day' => 'Dia', 'Days' => 'Dias', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Nível Padrão nível padrão - usuário redefine para este nível de acesso Se não existe nenhuma assinatura ativa (por exemplo, todas os assinantes expirados)', 'Delete' => 'Apagar', 'Delete %s' => 'Apagado(s) %s', 'Description' => 'Descrição', 'Discard' => 'Descartar', 'Discount' => 'Desconto', 'Do not add to Login Form' => 'Não adicione ao formulário de login', 'Do not add to Signup Form' => 'Não adicione ao formulário de inscrição', 'Do you really want to %s %s %s records' => 'Você realmente quer para %s %s %s registros', 'Do you really want to %s?' => 'Você realmente deseja %s', 'Do you really want to cancel subscription?' => 'Você realmente deseja cancelar esta inscrição?', 'Do you really want to delete record?' => 'Você realmente deseja apagar este registro?', 'E-Mail' => 'E-mail', 'E-Mail Address' => 'Endereço de E-mail', 'E-Mail Format' => 'Formato de E-mail', 'E-Mail Verification' => 'Verificação de E-mail', 'Edit' => 'Editar', 'Edit %s' => 'Ecitar %s', 'Edit Brick Labels' => 'Editar o Rótudo do Brick', 'Edit E-Mail Template' => 'Editar Modelo de E-mail ', 'End' => 'Final', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Aprecie sua filiação. Para Entrar por favor clique em %sLogin%s', 'Error 404 - Not Found' => 'Erro 404 - Não encontrado', 'Error happened during transaction handling. Please contact website administrator' => 'Ocorreu um erro durante a transação. Por favor contacte o administrador do site ou nosso suporte', 'Expired Users' => 'Usuários Expirados', 'Export' => 'Exportar', 'Export Format' => 'Exportar Formato', 'FaceBook App ID' => 'Número da Aplicação no Facebook (App ID)', 'FaceBook Application' => 'Aplicação do Facebook', 'Facebook App Secret' => 'Facebook App Secret', 'Features' => 'Características', 'Field Updated' => 'Campo Atualizado', 'Fields To Export' => 'Campos para Exportar', 'Filter' => 'Filtrar', 'First & Last Name' => 'Nome e Sobrenome ', 'Folder %s (%s)' => 'Pasta %s (%s)', 'Form Page Break' => 'Form Page Break', 'Free' => 'Grátis', 'Free Access' => 'Acesso livre', 'Get Password' => 'Conseguir senha', 'HTML Message' => 'Mensagem HTML', 'Having Active Subscription To:' => 'Tendo Ativa a Inscrição Para:', 'Having Expired Subscription To:' => 'Tendo Expirado a Inscrição Para:', 'Helpdesk' => 'Suporte', 'Housenumber' => 'número da residência/complemento', 'If you already have an account on our website, please %slog in%s to continue' => 'Se você é um membro registrado, por favor faça %slogin%s', 'If you are a registered member, please %slogin%s' => 'Se você é membro registrado, por favor %sfaça login aqui%s', 'If you are not registered yet, please %ssignup%s' => 'Se você ainda não é registrado, por favor %sregistre-se aqui%s', 'Income Report - payments minus refunds' => 'Relatório de Ganhos - Pagamentos menos reembolso', 'Integer value required' => 'Valor inteiro é obrigatório', 'Internal Error' => 'Erro Interno', 'Invalid Credit Card Number' => 'Número de Cartão de Crédito inválido', 'Invalid Expiration Date - Month' => 'Data de Expiração Inválida - Mês', 'Invalid Expiration Date - Year' => 'Data de Expiração Inválida - Ano', 'Invalid Issue Number' => 'Número do ticket inválido', 'Invite Code' => 'Código de Convite', 'Invoice' => 'Fatura', 'Invoice not found' => 'Fatura não encontrada', 'Item' => 'Item', 'Language' => 'Língua', 'Lifetime' => 'Vida toda', 'Like Url' => 'Curtir Url', 'Link' => 'Link', 'Live Edit %s' => 'Edição ao vido %s', 'Login' => 'login', 'Logout' => 'Sair', 'Lost Password Sending Error' => 'Erro no envio da Senha Perdida ', 'Lost Password Sent' => 'Senha Perdida Enviada', 'Lost password?' => 'Senha perdida', 'Make Payment' => 'Faça o Pagamento', 'Manage Newsletters' => 'Gerenciar Newsletter', 'Marketing Materials' => 'Materiais de Marketing', 'Membership Type' => 'Tipo de Assinatura/Plano', 'Message' => 'Mensagem', 'Message can not be empty' => 'Mesagem não pode ser vazia', 'Month' => 'Mês', 'Months' => 'Meses', 'Multiplier' => 'Multiplicador', 'Name' => 'Nome', 'New' => 'Novo', 'New %s' => 'Novas %s', 'New Password' => 'Nova Senha', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Nova senha você pode escolher uma nova senha aqui ou mantê-la como está deve ser %d ou mais de caracteres', 'Newsletter' => 'Newsletter', 'Newsletter Subscriptions' => 'Assinatura de Newsletter', 'Next' => 'Próximo', 'No' => 'Não', 'No commissions on this date' => 'Sem comissão nesta data', 'No coupons found with such coupon code' => 'Nenhum cupom foi encontrado com o código informado', 'No items selected for purchase' => 'Nenhum item selecionado para compra', 'No records found' => 'Nenhum Registro Encontrado', 'No, cancel' => 'Não, cancele', 'No, please keep me subscribed' => 'Não, por favor mantenha-me inscrito', 'Not Selected' => 'Não-Selecionado', 'Not registered yet?' => 'Ainda não é registrado?', 'Numeric value required' => 'Valor numérico é obrigatório', 'Offline Payment' => 'Pagamento Offline', 'Only Affiliate %s(rarely used)%s' => 'Somente Afiliado %s(raramente usado)%s', 'Order reference: %s' => 'Referência de compra: %s', 'Password' => 'Senha', 'Password and Password Confirmation are different. Please reenter both' => 'Senha e Confirmação de Senha são diferentes. Por favor entre novamente com os dados', 'Password must contain at least %d letters or digits' => 'Senha deve conter pelo menos %d letras ou dígitos', 'Passwords do not match' => 'Senhas não são iguais', 'Path to %s' => 'Caminho para %s', 'Path to %s Folder' => 'Caminho para %s Pasta', 'Payment Error' => 'Erro no Pagamento', 'Payment Failed' => 'Falha no Pagamento', 'Payment System' => 'Sistema de Pagamento ', 'Payment System Description' => 'Descrição do Sistema de Pagamento', 'Payment System Title' => 'Título do Sistema de Pagamento', 'Payment error: ' => 'Erro no Pagamento:', 'Payment failed' => 'Falha no Pagamento', 'Payment is already processed, please go to %sMembership page%s' => 'Pagamento já está processado, por favor vá para %sMembership page%s', 'Payments' => 'Pagamentos', 'Payments History' => 'Histórico de pagamentos', 'Period must be in interval 1-24 months' => 'Período deve ser no intervado de 1-24 meses', 'Period must be in interval 1-5 years' => 'Período deve ser no intervado de 1-5 anos', 'Period must be in interval 1-90 days' => 'Período deve ser no intervado de 1-90 dias', 'Phone' => 'Fone', 'Plain-Text Message' => 'Mesagem de Texto', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Por favor %sacesse%s sua conta já existente. %sSe você ainda não completou o pagamento, você poderá completá-lo após o seu login', 'Please Select' => 'Por favor Selecione', 'Please agree to User Agreement' => 'Por favor, você deve concordar com o Contrato de Usuário', 'Please choose' => 'Por favor escolha', 'Please choose a Credit Card Type' => 'Por favor escolhar o Tipo de Cartão de Crédito', 'Please choose a membership type' => 'Por favor, escolha o tipo de assinatura', 'Please choose a payment system' => 'Por favor escolha um sistema de pagamento', 'Please choose state' => 'Por favor escolha um Estado', 'Please enter %s' => 'Por favor entre %s', 'Please enter City' => 'Por favor entre com a Cidade', 'Please enter Country' => 'Por favor entre com o seu País', 'Please enter Credit Card Code' => 'Por favor entre o Código do seu Cartão de Crédito', 'Please enter Credit Card Number' => 'Por favor entre com o número do Cartão de Crédito', 'Please enter Password' => 'Por favor entre com a sua Senha', 'Please enter State' => 'Por favor entre com o nome do Estado', 'Please enter Street Address' => 'Por favor entre com o seu endereço', 'Please enter ZIP code' => 'Por favor entre com o CEP', 'Please enter a valid e-mail address' => 'Por favor entre com um email válido', 'Please enter credit card holder first name' => 'Por favor entre com o primeiro nome do usuário do cartão', 'Please enter credit card holder last name' => 'Por favor entre com o sobrenome do usuário do cartão', 'Please enter credit card holder name' => 'Por favor entre com o nome do usuário do cartão', 'Please enter housenumber' => 'Por favor entre com o número da residência/complemento', 'Please enter phone number' => 'Por favor entre com o Fone', 'Please enter valid Email' => 'Por favor valide seu E-mail', 'Please enter valid Username. It must contain at least %d characters' => 'Por favor use um nome de usuário válido. Deve conter pelo menos %d caracteres', 'Please enter your First Name' => 'Por favor entre com o seu Primeiro Nome', 'Please enter your Last Name' => 'Por favor entre com o seu sobrenome', 'Please enter your current password for validation' => 'Por favor entre com a sua senha atual para validação', 'Please login' => 'Por favor acesse', 'Please select payment system for payment' => 'Por favor selecione o sistema de pagamento para realizar o seu pagamento', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Por favor use %sAdicionar/Renovar inscrição%s de para comprar ou renovar inscrição.', 'Please wait %d seconds before next login attempt' => 'Por favor aguarde %d segundos antes de tentar logar/acessar novamente', 'Prev' => 'Anterior', 'Price' => 'Preço', 'Product' => 'Produto', 'Product(s) to display' => 'Produto(s) para apresentar', 'Products' => 'Produtos', 'Profile' => 'Editar Perfil', 'Qty' => 'Qtde', 'Quantity' => 'Quantidade', 'Quick Order' => 'Ordem Expressa', 'Re-Open Ticket' => 'Re-abrir Ticket', 'Record' => 'Registro', 'Records that match all these conditions' => 'Registros que coincidem com todas essas condições', 'Reference number is:' => 'Número de referência é:', 'Referred Affiliate' => 'Afiliado Indicado', 'Refresh' => 'Recarregar', 'Register' => 'Registrador', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Remover Usuários quando um registro de usuário é removido do aMember o arquivo relacionado deve ser removido do %s ', 'Reply' => 'Responder', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Falha se o pagamento recorrente falhou, aMember pode repetir este pagamento depois de vários dias, e prorrogar inscrição de clientes pelo mesmo período entre com o número de dias para repetir a tentativa de cobrança', 'Return' => 'Retornar', 'Return and try again' => 'Volte e tente novamente', 'Review/Pay Commissions' => 'Revise/Pague Comissão de Afiliado(a)', 'Run Report' => 'Gerar Relatório', 'Running %s' => 'Gerando %s', 'Save' => 'Salvar', 'Save Profile' => 'Salvar Perfil', 'Search' => 'Busca', 'Search Products' => 'Busca Produtos', 'Security code is invalid' => 'Código de segurança é inválido', 'Select a condition to add into search' => 'Selecione uma condição para adicionar na busca', 'Select all %s records matching your search' => 'Selecione todos %s registros juntando sua busca', 'Session expired, please enter username and password again' => 'Sessão expirada, por favor entre o seu login e senha novamente ', 'Shipping' => 'Frete', 'Shopping Cart' => 'Carrinho de Compras', 'Sign-up' => 'Entre', 'Signup Form' => 'Formulário de Inscrição', 'Signup here' => 'Cadastre-se aqui', 'Simple Search Users' => 'Busca Simples de Usuários', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Desculpa, é impossível utilizar este método de pagamento para esta compra. Por favor, selecione outro método de pagamento', 'Sorry, seems you have used wrong link' => 'Desculpa, parece que você utilizou um link errado', 'Source Code — Copy/Paste Into Your Website' => 'Código fonte — Copie/Cole No seu Site', 'Start' => 'começo', 'State' => 'Estado', 'Status' => 'Status', 'Street' => 'Rua', 'Street Address' => 'Rua', 'Subject' => 'Assunto', 'Subject can not be empty' => 'Assunto não pode ser vazio', 'Subscribe to Site Newsletters' => 'Assinar newsletter do site', 'Subscribers' => 'Assinantes', 'Subscription Terms' => 'Termos da assinatura', 'Subscription/Product Title' => 'Assinatura/Título do Produto', 'Subtotal' => 'Subtotal', 'Target URL' => 'URL alvo', 'Tax' => 'Taxa', 'Tax Amount' => 'Valor do imposto', 'Terms' => 'Termos', 'Test Settings' => 'Test as Configurações', 'Thank you for Signing up' => 'Obrigado por se cadastrar', 'The database has encountered a problem, please try again later.' => 'O banco de dados encontrou um problema, por favor tente novamente mais tarde.', 'The password should be at least %d characters long' => ' A senha deveria ter pelo menos %d caracteres de tamanho ', 'The user name or password is incorrect' => 'O usuário/login ou sua senha está incorreto', 'There are no confirmed payments for your account' => 'Não há pagamentos confirmados para sua conta', 'This %s is blocked. Please contact site support to find out why' => 'Este %s está bloqueado. Por favor contate o suporte do site para descobrir o motivo', 'This coupon belongs to another customer' => 'Este cupom pertence a outro usuário', 'This is a required field' => 'Este é um campo obrigatório', 'This page will be automatically refreshed within %s' => 'Esta página será automaticamente recarregada dentro de: %s', 'This payment system could not handle payments in [%s] currency' => 'Este sistema de pagamento não pode suportar pagamentos em [%s] moeda(s)', 'This payment system could not handle zero-total invoices' => 'Este sistema de pagamento não pode trabalhar com total-zero na fatura', 'Ticket' => 'Ticket', 'Ticket has been submited' => 'Ticket foi encaminhado', 'Tickets' => 'Tickets', 'Title' => 'Título', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Para adicionar campos no formulário, mova o item de \'Bricks disponíveis\' para \'Block de Formulário\' Para remover campos, mova de volta para \'Bricks disponíveis\'. Para fazer formulário de múltiplas páginas, insira o item \'Separador de Página\' no local onde você deseja a página dividida', 'Total' => 'Total', 'Try again' => 'Tente novamente', 'Unknown period unit: %s' => 'Unidade de período desconhecido: %s', 'Unsubscribe from all e-mail messages' => 'Descadastrar de todas as mensagens de e-mails', 'Unsubscription Confirmation' => 'Confirmação de Descadastramento ', 'Update' => 'Atualizar', 'Update Credit Card Info' => 'Atualiza Informação de Cartão de Crédito ', 'Updated' => 'Atualizado', 'Upgrade Subscription' => 'Fazer upgrade de inscrição', 'Use Database Connection other than configured for aMember' => 'Utilize outra conexão de banco de dados que configurada no sistema', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Use outro MySQL Db use host, user, senha para %s connexão de base de dados Normalmente você pode deixar este item sem selecionar', 'User' => 'Usuário', 'User Agreement' => 'Contrato de Usuário', 'User Info' => 'Informação do Usuário', 'User Search' => 'Busca Usuário', 'Username' => 'Login', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Username (Nome de usuário) você pode escolher um novo username aqui e mantê-lo sem mudar. Username deve ter %d ou mais caracteres de tamanho e deve conter apenas letras minúsculas, números e/ou underline ', 'Username contains invalid characters - please use digits, letters or spaces' => 'Username contem caracteres inválidos - por favor use números , letras ou espaços apenas', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Username/Login contem caracteres inválidos - por favor use números e letras', 'Username/Email' => 'Seu e-mail ou seu Username', 'Users subscribed to Newsletter Threads #' => 'Usuários inscritos na Newsletter Tópicos #', 'Validate E-Mail Address by sending e-mail message with code' => 'Valide seu endereço de e-mail enviando a mensagem de email com o código', 'View Basket' => 'Ver Cesta', 'Visit %sorder page%s to order additional subscriptions' => 'Visite a %spágina de compra%s para adquirir outras inscrições/serviços', 'Week' => 'Semana', 'Wrong code or code expired - please start signup process again' => 'Código errado or código expirado - por favor inicie o processo de inscrição novamente', 'Wrong parameters, error #1253' => 'Parâmetros errados, erro #1253', 'Wrong verification code' => 'Código de Verificação Inválido', 'Wrongly signed URL, please contact site admin' => 'URL assinada de forma errada, por favor contacte o administrador do site', 'Year' => 'Ano', 'Years' => 'Anos', 'Yes, I want to cancel subscription' => 'Sim, quero cancelar esta inscrição', 'Yes, continue' => 'Sim, continue', 'You have no access to %s' => 'Você não tem acesso a %s', 'You have no active subscriptions' => 'Você não tem inscrição ativa', 'You have no enough permissions for this operation' => 'Você não tem permissão suficiente para esta operação', 'You have no items in your basket - please add something to your basket before checkout' => 'Você não possui nenhum item na sua ceta - por favor adicione algo na sua cesta antes de ir para o caixa', 'You must be authorized to access this area' => 'Você deve estar autorizado para acessar esta área', 'Your Basket' => 'Sua Cesta', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Sua senha atual se você está mudando a sua senha, por favor entre com a sua senha atual para validação', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Seu endereço de E-mail uma confirmação de email será enviada para você através deste e-mail', 'Your Membership Information' => 'Informações da sua Filiação (Membership) ', 'Your Subscriptions' => 'Suas inscrições', 'Your password is too long' => 'Sua senha é muito longa', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Seu pagamento ainda não esta confirmdo pelo sistema de pagamento. Este processo pode levar alguns minutos. ', 'Your subject is too verbose' => 'Assunto contem mais palavras que o necessário', 'ZIP' => 'CEP', 'ZIP Code' => 'CEP', '[Select country]' => '[Selecione país]', '[Select state]' => '[Selecione estado]', '_default_locale' => 'pt_BR', 'admin' => 'admin', 'affiliate program commissions' => 'programa de comissões de afiliado(a)', 'ago' => 'atrás', 'banned' => 'banido', 'commission found by next rules' => 'comissão encontrada pelas próximas regras', 'days' => 'Dias', 'email' => 'email', 'expiration' => 'expiração', 'filtered' => 'Filtrado', 'for example: 1111-2222-3333-4444' => 'por exemplo: 1111-2222-3333-4444', 'hrs' => 'hs', 'ip' => 'ip', 'just now' => 'agora', 'login' => 'login', 'min' => 'min', 'no records' => 'sem registros', 'number of affiliate program clicks' => 'número de cliques programa de afiliados', 'of products' => 'de produtos', 'on %d-th day' => 'no %d dia', 'pay using credit card or PayPal' => 'pague usando cartão de crédito ou PayPal', 'pay using wire transfer or by sending offline check' => 'pague utilizando transferência ou enviando um cheque', 'return' => 'Retornar', 'seconds' => 'segundos', 'start' => 'começo', 'use 4111-1111-1111-1111 for successful transaction' => 'use 4111-1111-1111-1111 para uma transação bem sucedida', ); PK\u,u,default/language/user/hr.phpnu[ 'Dodaj/Obnovi pretplatu', 'Address Info' => 'Adresa - Podaci', 'Advertise our website to your friends and earn money' => 'Reklamirajte našu web stranicu prijateljima i zaradite novac', 'Affiliate Info' => 'Affiliate info', 'Affiliate Payout Type' => 'Vrsta Affiliate isplate', 'Affiliate info' => 'Affiliate info', 'Affiliate stats' => 'Affiliate statistika', 'Affiliates' => 'Affiliate partneri', 'Amount' => 'Iznos', 'An Error has occurred' => 'Dogodila se Greška', 'An account with the same email already exists.' => 'Jedan račun sa istom email adresom već postoji.', 'An error occurred while handling your payment.' => 'Dogodila se greška za vrijeme vašeg plaćanja.', 'Back' => 'Natrag', 'Bank Identification' => 'Identifikacija banke', 'Bank Name' => 'Naziv banke', 'Cancel' => 'Otkazujem', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Ne možete koristiti plugin za BESPLATNO plaćanje sa proizvodom koji košta više od 0.0', 'Change' => 'Promijeni', 'Change Password' => 'Promjena lozinke', 'Change Password/Edit Profile' => 'Promijeni lozinku/Editiraj profil', 'Change payout info' => 'Promijenite podatke za isplatu', 'City' => 'Grad', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Kliknite ovdje ako ne želite duže čekati (ali ako vas vaš preglednik neće automatski preusmjeriti).', 'Close' => 'Zatvori', 'Confirm Password' => 'Potvrdi lozinku', 'Continue' => '#-#-#-#-# hr.po #-#-#-#-# Nastavi #-#-#-#-# hr.po #-#-#-#-# Nastavi #-#-#-#-# hr.po #-#-#-#-# Nastavi #-#-#-#-# hr.po #-#-#-#-# Nastaviti', 'Country' => 'Država', 'Coupon Discount' => 'Kupon popust', 'Credit Card Code' => 'Kod Kreditne kartice', 'Credit Card Info' => 'Podaci o Kreditnoj kartici', 'Credit Card Number' => '#-#-#-#-# hr.po #-#-#-#-# Broj Kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Broj kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Broj kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Broj kreditne kartice', 'Date' => 'Datum', 'Date and time of payment: %s' => 'Datum i vrijeme plaćanja: %s', 'Do you really want to cancel subscription?' => 'Da li stvarno želite otkazati pretplatu?', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Uživajte u članstvu. Za ulaz kliknite na %sPrijava%s', 'First & Last Name' => 'Ime & Prezime', 'Get Password' => 'Uzmi lozinku', 'Housenumber' => 'Kućni broj', 'If you already have an account on our website, please %slog in%s to continue' => 'Ako ste registriran član, molimo %slogin%s', 'If you are a registered member, please %slogin%s' => 'Ako ste registriran član, molimo %slogin%s', 'If you are not registered yet, please %ssignup%s' => 'Ako još niste registrirani, molimo %ssignup%s', 'Internal Error' => 'Interna greška', 'Invalid Credit Card Number' => '#-#-#-#-# hr.po #-#-#-#-# Nevažeći broj Kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Nevažeći broj kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Nevažeći broj kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Nevažeći broj kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Nevažeći broj kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Nevažeći broj kreditne kartice', 'Invalid Expiration Date - Month' => '#-#-#-#-# hr.po #-#-#-#-# Nevažeći datum - mjesec isticanja #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - mjesec #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - mjesec #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - mjesec #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - mjesec #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - mjesec', 'Invalid Expiration Date - Year' => '#-#-#-#-# hr.po #-#-#-#-# Nevažeći datum - godina isticanja #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - godina #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - godina #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - godina #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - godina #-#-#-#-# hr.po #-#-#-#-# Nevažeći datum isteka - godina', 'Invoice' => 'Izdati račun', 'Language' => 'Jezik', 'Logout' => 'Odjava', 'Lost Password Sending Error' => 'Greška prilikom slanja izgubljene lozinke', 'Lost Password Sent' => 'Izgubljena Lozinka je poslana', 'Lost password?' => 'Izgubljena lozinka', 'Membership Type' => 'Vrsta članstva', 'Message' => 'Poruka', 'Name' => 'Ime i Prezime', 'New Password' => 'Nova lozinka', 'Newsletter Subscriptions' => 'Newsletter pretplate', 'Next' => 'Slijedeće', 'No, please keep me subscribed' => 'Ne, molim da me zadržite prijavljenog', 'Not registered yet?' => 'Niste još registrirani?', 'Offline Payment' => 'Offline plaćanje', 'Password' => 'Lozinka', 'Password and Password Confirmation are different. Please reenter both' => 'Lozinka i Potvrda lozinke se razlikuju. Molimo da ponovo unesete oboje', 'Password must contain at least %d letters or digits' => 'Lozinka mora sadržavati najmanje %d znakova ili brojki', 'Payment Error' => 'Greška prilikom plaćanja', 'Payment Failed' => 'Plaćanje nije uspjelo', 'Payment System' => '#-#-#-#-# hr.po #-#-#-#-# Sistem za plaćanje #-#-#-#-# hr.po #-#-#-#-# Sistem plaćanja #-#-#-#-# hr.po #-#-#-#-# Sistem plaćanja #-#-#-#-# hr.po #-#-#-#-# Sistem plaćanja', 'Payment failed' => 'Plaćanje nije uspjelo', 'Payment is already processed, please go to %sMembership page%s' => 'Plaćanje je već procesirano, molimo da odete na %sČlansku stranicu%s', 'Period must be in interval 1-24 months' => 'Razdoblje treba biti u intervalu od 1-24 mjeseci', 'Period must be in interval 1-5 years' => 'Razdoblje treba biti u intervalu od 1-5 godina', 'Period must be in interval 1-90 days' => 'Razdoblje treba biti u intervalu od 1-90 dana', 'Phone' => 'Telefon', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Molimo da se %sprijavite%s u vaš postojeći račun.%sAko još nemate dovršeno plaćanje, bit ćete u mogućnosti dovršiti ga nakon prijave', 'Please choose a Credit Card Type' => 'Molimo da odaberete vrstu Kreditne kartice', 'Please choose a membership type' => 'Molimo da izaberete vrstu članstva', 'Please choose a payment system' => 'Molimo da izaberete sistem plaćanja', 'Please choose state' => 'Molimo da unesete regiju-državu', 'Please enter City' => 'Molimo da unesete Grad', 'Please enter Country' => 'Molimo da unesete Državu', 'Please enter Credit Card Code' => '#-#-#-#-# hr.po #-#-#-#-# Molimo da unesete kod Kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete kod kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete kod kreditne kartice #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete kod kreditne kartice', 'Please enter Credit Card Number' => 'Molimo da unesete broj Kreditne kartice', 'Please enter Password' => 'Molimo da unesete Lozinku', 'Please enter State' => 'Molimo da unesete Regiju / državu', 'Please enter Street Address' => 'Molimo da unesete Ulicu', 'Please enter ZIP code' => '#-#-#-#-# hr.po #-#-#-#-# Molimo da unesete Poštanski broj / zip #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete poštanski broj / zip code #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete poštanski broj / zip code #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete Poštanski broj / zip code #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete Poštanski broj / zip code #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete Poštanski broj / zip code #-#-#-#-# hr.po #-#-#-#-# Molimo da unesete Poštanski broj / zip code', 'Please enter credit card holder first name' => 'Molimo da unesete ime vlasnika Kreditne kartice', 'Please enter credit card holder last name' => 'Molimo da unesete prezime vlasnika Kreditne kartice', 'Please enter credit card holder name' => 'Molimo da unesete ime vlasnika Kreditne kartice', 'Please enter housenumber' => 'Molimo da unesete kućni broj', 'Please enter phone number' => 'Molimo da unesete telefonski broj', 'Please enter valid Email' => 'Molimo da unesete ispravan email', 'Please enter your First Name' => 'Molimo da unesete svoje Ime', 'Please enter your Last Name' => 'Molimo da unesete svoje Prezime', 'Please login' => '#-#-#-#-# hr.po #-#-#-#-# Molimo da se logirate #-#-#-#-# hr.po #-#-#-#-# Molim prijavu', 'Please select payment system for payment' => 'Molimo da odaberete sistem plaćanja za plaćanje', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Molimo da koristite formular %sDodaj/Obnovi pretplatu%s da biste se pretplatili ili obnovili pretplatu.', 'Price' => 'Cijena', 'Product' => 'Proizvod', 'Profile' => 'Editiraj Profil', 'Return and try again' => 'Vratite se i pokušajte ponovo', 'Save' => 'Spremi', 'Save Profile' => 'Spremi Profil', 'Session expired, please enter username and password again' => 'Povezanost je istekla, molimo da unesete korisničko ime i lozinku ponovo', 'Sign-up' => '#-#-#-#-# hr.po #-#-#-#-# Registracija #-#-#-#-# hr.po #-#-#-#-# Prijava', 'Signup here' => 'Registrirajte se ovdje', 'State' => '#-#-#-#-# hr.po #-#-#-#-# Regija / država #-#-#-#-# hr.po #-#-#-#-# Regija / država #-#-#-#-# hr.po #-#-#-#-# Regija / država #-#-#-#-# hr.po #-#-#-#-# Regija / država #-#-#-#-# hr.po #-#-#-#-# Regija / država #-#-#-#-# hr.po #-#-#-#-# Regija #-#-#-#-# hr.po #-#-#-#-# Regija-država #-#-#-#-# hr.po #-#-#-#-# Regija-država', 'Street' => 'Ulica', 'Street Address' => 'Ulica', 'Subject' => 'Predmet', 'Subscribe to Site Newsletters' => 'Prijavite se na naš Newsletter', 'Subscription/Product Title' => '#-#-#-#-# hr.po #-#-#-#-# Naslov Pretplate/Proizvoda #-#-#-#-# hr.po #-#-#-#-# Naslov pretplate/Proizvoda', 'Subtotal' => 'Ukupno', 'Tax Amount' => 'Iznos poreza', 'Thank you for Signing up' => 'Zahvaljujemo na registraciji', 'Total' => '#-#-#-#-# hr.po #-#-#-#-# Ukupno #-#-#-#-# hr.po #-#-#-#-# Sveukupno #-#-#-#-# hr.po #-#-#-#-# Sveukupno', 'Try again' => 'Pokušajte ponovo', 'Unknown period unit: %s' => 'Nepoznata jedinica razdoblja: %s', 'Unsubscribe from all e-mail messages' => 'Odjava od svih email poruka', 'Unsubscription Confirmation' => 'Potvrda odjave', 'User Agreement' => 'Ugovor o korištenju', 'Username' => 'Korisničko ime', 'Username contains invalid characters - please use digits, letters or spaces' => 'Korisničko ime sadrži nedozvoljene znakove - molimo da koristite brojke, slova ili prazna mjesta', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Korisničko ime sadrži nedozvoljene znakove - molimo da koristite brojke i slova', 'Wrongly signed URL, please contact site admin' => 'Pogrešno naznačen URL, molimo da kontaktirate administratora stranice', 'You have no active subscriptions' => 'Vi nemate aktivnih pretplata', 'Your Membership Information' => 'Vaši članski podaci', 'Your Subscriptions' => 'Vaše pretplate', 'ZIP' => 'Poštanski broj / zip', '[Select country]' => '[Odaberite državu]', '[Select state]' => '[Odaberite regiju]', '_default_locale' => 'hr_HR', 'for example: 1111-2222-3333-4444' => 'na primjer: 1111-2222-3333-4444', ); PK\1N ``default/language/user/zh.phpnu[ '"%s" 只能随这些产品订购:%s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" 只能在这些产品过期后订购: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" 无法被订购因为您有激活的订购: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" 无法被订购因为您有过期的订购: %s', '%d-th day' => '第%d天', '%s database and tables prefix' => '%s 数据库和表前缀', 'Access' => '进入', 'Access Denied' => '拒绝进入', 'Access Log' => '进入记录', 'Access Permissions' => '进入允许', 'Actions' => '行为', 'Active' => '有效的', 'Active Users' => '活跃用户', 'Add User' => '增加用户', 'Add to Basket' => '增加到篮子', 'Add/Renew Subscription' => '增加/续订订阅', 'Added' => '已增加', 'Additional Fields' => '其他栏', 'Address Info' => '地址信息', 'Address Information' => '地址信息', 'Admin' => '管理员', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => '管理员群组 aMember 从不触摸%s账户 分配到下列群组。这保护 %s账户不受aMember 活动影响', 'Admin Username' => '管理员用户名', 'Administrator' => '管理员', 'Advanced' => '高级', 'Advanced Search' => '高级搜索', 'Advertise our website to your friends and earn money' => '向朋友推销我们的网站赚钱', 'Affiliate' => '分销', 'Affiliate Info' => '分销信息', 'Affiliate Payout Type' => '分销支付类型', 'Affiliate Program' => '分销计划', 'Affiliate Signup Form' => '分销注册表格', 'Affiliate info' => '分销商信息', 'Affiliate stats' => '分销统计', 'Affiliates' => '分销商', 'All' => '全部', 'All %s records on this page are selected' => '所有%s记录被选中', 'All Affiliates' => '所有分销', 'All Users' => '所有用户', 'All records' => '所有记录', 'Amount' => '数量', 'An account with the same email already exists.' => '此邮件账户已经存在', 'An internal error happened in the script, please contact webmaster for details' => '脚本内部错误发生,请联系管理员', 'Any Product' => '任何产品', 'Any product' => '任何产品', 'Apply' => '应用', 'Apply Filter' => '使用过滤', 'Attachments' => '附件', 'Authentication' => '认证', 'Authentication problem, please contact website administrator' => '验证问题,请联系网站管理员', 'Available Bricks (drag to left to add)' => '可用的组件(拖动到左侧添加)', 'Awaiting Admin Response' => '等待管理员回复', 'Awaiting User Response' => '等待用户回复', 'Back' => '返回', 'Bank Identification' => '银行用户名', 'Bank Name' => '银行名', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => '屏蔽群组 aMember 从不触摸%s账户 分配到下列群组。这保护 %s账户不受aMember活动的影响', 'Banners and Links' => '条幅广告和链接', 'Banners and Text Links' => '管理条幅广告和文字链接', 'Begin Date' => '开始日期', 'Both Affiliate and member' => '分销商和会员', 'CC Demo' => 'CC演示', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF 保护错误-表格必须在显示%d分钟内提交,请重复', 'Can view/edit customer Credit Card information and rebills' => '可以浏览/编辑 客户信用卡信息和再次支付', 'Cancel' => '取消', 'Cancel Subscription' => '取消订阅', 'Cancelled' => '已取消', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => '不能使用免费支付插件给价值超过0.0的产品', 'Category' => '目录', 'Change' => '更改', 'Change Password' => '更改密码', 'Change Password/Edit Profile' => '更改密码/编辑个人资料', 'Change Subscription' => '更改订阅', 'Change Username' => '更改用户名', 'Change payout info' => '更改支付信息', 'Checkout' => '支付', 'Checkout error: ' => '支付错误', 'Choose a Password must be %d or more characters' => '选择密码 必须%d或更多字符', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => '选择用户名 必须是%d或更多个字符长度 可以只包含字母、数字,和下划线', 'City' => '城市', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => '如果您不想再等下去请点击这里(或者如果您的浏览器不能自动跳转)', 'Clicks' => '点击', 'Clicks/Sales Statistics' => '分销点击/销售统计', 'Close' => '关闭', 'Close Ticket' => '关闭问题', 'Closed' => '关闭', 'Code' => '代码', 'Comment' => '评论', 'Comment for admin reference' => '评论 供管理员参考', 'Commission' => '佣金', 'Commissions' => '佣金', 'Configuration' => '配置', 'Configured Tax Values' => '配置的税值', 'Confirm' => '确认', 'Confirm New Password' => '确认新密码', 'Confirm Password' => '确认密码', 'Confirm Payment' => '确认支付', 'Confirm Your Password' => '确认密码', 'Continue' => '继续', 'Conversation' => '对话', 'Country' => '国家', 'Coupon' => '优惠券', 'Coupon Discount' => '折扣优惠券', 'Coupon code disabled' => '优惠代码禁用', 'Coupon code expired' => '优惠代码过期', 'Coupon is not yet active' => '优惠券未激活', 'Coupon usage limit exceeded' => '超出优惠使用限制', 'Credit Card Code' => '信用卡代码', 'Credit Card Info' => '信用卡信息', 'Credit Card Number' => '信用卡号码', 'Credit Card Rebills' => '信用卡再次支付', 'Credit Cards' => '信用卡', 'Currency' => '货币', 'Currency Exchange Rates' => '货币汇率', 'Current password entered incorrectly, please try again' => '当前密码输入不正确,请重试', 'Custom Commission' => '定制佣金', 'DONE' => '完成', 'Dashboard' => '控制台', 'Date' => '日期', 'Date and time of payment: %s' => '支付日期和时间:%s', 'Date must be in format %s' => '日期必须是%s格式', 'Date/Time' => '日期/时间', 'Day' => '日', 'Days' => '日', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => '默认级别 默认级别-用户重置到这个进入级别 如果无有效订阅 (例如所有订阅过期)', 'Delete' => '删除', 'Delete %s' => '删除%s', 'Description' => '描述', 'Disabled' => '禁用', 'Discard' => '丢弃', 'Discount' => '折扣', 'Display Type' => '显示类型', 'Do you really want to %s %s %s records' => '您真的想%s %s %s 记录', 'Do you really want to %s?' => '您真的想%s?', 'Do you really want to cancel subscription?' => '您真的要取消订阅?', 'Do you really want to delete record?' => '您真的想删除记录吗?', 'Done' => '完成', 'E-Mail' => '电子邮件', 'E-Mail Address' => '电子邮件地址', 'E-Mail Format' => '电子邮件格式', 'E-Mail Messages' => '电子邮件消息', 'E-Mail Verification' => '电子邮件验证', 'Edit' => '编辑', 'Edit %s' => '编辑%s', 'Edit Brick Labels' => '编辑组件标签', 'Edit E-Mail Template' => '编辑电子邮件模板', 'Email' => '电子邮件', 'Email Subject' => '电子邮件主题', 'Enabled Modules' => '启用的模块', 'End' => '结束', 'End Date' => '结束日期', 'Enjoy your membership. To Login please click here %sLogin%s' => '请享受您的会员资格。要登录请点这里%s登录%s', 'Error 404 - Not Found' => '404错误-未找到', 'Expire Date' => '过期日期', 'Expired' => '已过期', 'Expired Users' => '过期用户', 'Export' => '导出', 'Export Format' => '导出格式', 'Field' => '栏', 'Field Type' => '栏类型', 'Field Updated' => '更新的栏', 'Fields To Export' => '导出的栏', 'File' => '文件', 'Filename' => '文件名', 'Files' => '文件', 'Filter' => '过滤', 'First & Last Name' => '名和姓', 'First Name' => '名', 'Folders' => '文件夹', 'Form Page Break' => '表格分页', 'Free' => '免费', 'Free Access' => '免费进入', 'From' => '从', 'Get Password' => '获取密码', 'HTML Message' => 'HTML消息', 'Having Active Subscription To:' => '拥有有效订阅:', 'Having Expired Subscription To:' => '拥有过期订阅:', 'Helpdesk' => '帮助', 'Housenumber' => '门牌号码', 'IP Address' => 'IP 地址', 'If you already have an account on our website, please %slog in%s to continue' => '如果您是注册会员,请%s登录%s', 'If you are a registered member, please %slogin%s' => '如果您是注册会员,请%s登录%s', 'If you are not registered yet, please %ssignup%s' => '如果您还没有注册,请%s注册%s', 'Integer Value' => '整数值', 'Integer value required' => '必须是整数值', 'Integrations' => '整合', 'Invalid Credit Card Number' => '无效的信用卡号码', 'Invalid Expiration Date - Month' => '无效的到期日期-月份', 'Invalid Expiration Date - Year' => '无效的到期日期-年份', 'Invalid Issue Number' => '无效发行如期', 'Invite Code' => '邀请代码', 'Invoice' => '发票', 'Invoice not found' => '发票未找到', 'Is Locked' => '被锁定', 'Is Paid?' => '支付了吗?', 'Item' => '物品', 'Language' => '语言', 'Last Name' => '姓', 'Leads' => '线', 'License Key' => '许可证密钥', 'Lifetime' => '终生', 'Link' => '链接', 'Links' => '链接', 'Live Edit %s' => '在线编辑%s', 'Log In' => '登录', 'Login' => '登录', 'Logout' => '注销', 'Lost Password Sending Error' => '丢失密码发送错误', 'Lost Password Sent' => '丢失密码发送', 'Lost password?' => '密码丢失', 'Mail Queue' => '邮件队列', 'Make Payment' => '支付', 'Manage Newsletters' => '管理通讯', 'Marketing Materials' => '销售材料', 'Membership Type' => '会员类型', 'Message' => '消息', 'Message can not be empty' => '消息不能为空', 'Month' => '月', 'Months' => '月', 'Multiplier' => '乘数', 'Name' => '名字', 'Never' => '从未', 'New' => '新的', 'New %s' => '新的%s', 'New Password' => '新密码', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => '新密码 您可选择新密码或保持不变 必须%d或更多字符', 'Newsletter' => '通讯', 'Newsletter Subscriptions' => '订阅通讯', 'Next' => '下一步', 'No' => '否', 'No commissions on this date' => '在此日期无佣金', 'No coupons found with such coupon code' => '无此代码优惠券', 'No items selected for purchase' => '购买物品未选中', 'No records found' => '记录未找到', 'No, cancel' => '不,取消', 'No, please keep me subscribed' => '不,请让我订阅', 'Not Selected' => '未选中', 'Not registered yet?' => '尚未注册?', 'Numeric Value' => '数字值', 'Numeric value required' => '必须是数字值', 'Offline Payment' => '离线付款', 'Only Affiliate %s(rarely used)%s' => '仅分销%s(很少使用)%s', 'Order reference: %s' => '订购参考:%s', 'Pages' => '页面', 'Password' => '密码', 'Password and Password Confirmation are different. Please reenter both' => '密码和确认密码不同。请重新输入', 'Password must contain at least %d letters or digits' => '密码须包含至少 %d 个字母或位数', 'Passwords do not match' => '密码不匹配', 'Path to %s' => '到%s的路径', 'Path to %s Folder' => '到%s文件夹的路径', 'Payment Error' => '付款错误', 'Payment Failed' => '付款失败', 'Payment System' => '支付系统', 'Payment System Description' => '支付系统描述', 'Payment System Title' => '支付系统标题', 'Payment error: ' => '支付错误:', 'Payment failed' => '支付失败', 'Payment is already processed, please go to %sMembership page%s' => '支付已处理,请到%s会员页面%s', 'Payments' => '支付', 'Payments History' => '支付历史', 'Payout Method' => '取款方法', 'Payouts' => '取款', 'Pending' => '待批', 'Period must be in interval 1-24 months' => '时期必须间隔1-24个月', 'Period must be in interval 1-5 years' => '时期必须间隔1-5年', 'Period must be in interval 1-90 days' => '时期必须间隔1-90天', 'Phone' => '电话', 'Plain-Text Message' => '纯文本消息', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => '请%s登录%s已有账户。%s如果您还没有完成支付,您可以在登录之后完成。', 'Please Select' => '请选择', 'Please agree to User Agreement' => '请同意用户协议', 'Please choose' => '请选择', 'Please choose a Credit Card Type' => '请选择信用卡类型', 'Please choose a membership type' => '请选择会员类型', 'Please choose a payment system' => '请选择支付系统', 'Please choose state' => '请选择省份', 'Please enter %s' => '请输入%s', 'Please enter City' => '请输入城市', 'Please enter Country' => '请输入国家', 'Please enter Credit Card Code' => '请输入信用卡代码', 'Please enter Credit Card Number' => '请输入信用卡号码', 'Please enter Password' => '请输入密码', 'Please enter State' => '请输入省份', 'Please enter Street Address' => '请输入街道地址', 'Please enter ZIP code' => '请输入邮政编码', 'Please enter a valid e-mail address' => '请输入有效电子邮件地址', 'Please enter credit card holder first name' => '请输入信用卡持有人名', 'Please enter credit card holder last name' => '请输入信用卡持有人姓', 'Please enter credit card holder name' => '请输入信用卡持有人姓名', 'Please enter housenumber' => '请输入门牌号', 'Please enter phone number' => '请输入电话号码', 'Please enter valid Email' => '请输入有效的电子邮件', 'Please enter valid Username. It must contain at least %d characters' => '请输入有效用户名。必须包含至少%d字符', 'Please enter your First Name' => '请输入您的名', 'Please enter your Last Name' => '请输入您的姓', 'Please enter your current password for validation' => '请输入您的当前密码进行验证', 'Please login' => '请登录', 'Please select an item...' => '请选择物品……', 'Please select payment system for payment' => '请选择支付系统', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => '请用%s增加/续订订阅%s的表格订购或续订订阅。', 'Please wait %d seconds before next login attempt' => '请等待%d秒再重新登录', 'Plugin' => ' 插件', 'Prev' => '前面', 'Preview' => '预览', 'Price' => '价格', 'Product' => '产品', 'Product Categories' => '产品目录', 'Product(s) to display' => '显示产品', 'Products' => '产品', 'Profile' => '编辑个人资料', 'Qty' => '数量', 'Quantity' => '数量', 'Quick Order' => '快速订单', 'Re-Open Ticket' => '重开问题', 'Record' => '记录', 'Records that match all these conditions' => '匹配所有条件的记录', 'Recurring' => '周期性订购', 'Reference number is:' => '参考号码是:', 'Referer' => '推荐人', 'Referred Affiliate' => '推荐分销', 'Refresh' => '更新', 'Refund' => '退款', 'Refunded' => '已退款', 'Register' => '注册', 'Remove' => '移除', 'Remove Users when user record removed from aMember must the related record be removed from %s' => '移除用户 当用户记录被从aMember移除 相关记录必须被从%s移除', 'Reply' => '回复', 'Return' => '返回', 'Return and try again' => '返回,然后重试', 'Review/Pay Commissions' => '浏览/支付分销佣金', 'Run Report' => '运行报告', 'Running %s' => '进行%s', 'Save' => '保存', 'Save Profile' => '保存个人资料', 'Search' => '搜索', 'Search Products' => '搜素产品', 'Security code is invalid' => '安全代码无效', 'Select a condition to add into search' => '选择条件增加到搜索', 'Select all %s records matching your search' => '选择所有%s记录匹配您的搜索', 'Send' => '发送', 'Session expired, please enter username and password again' => '操作超时,请再次输入用户名和密码', 'Shipping' => '运送', 'Shopping Cart' => '购物车', 'Sign-up' => '注册', 'Signup Form' => '注册表格', 'Signup here' => '在这里注册', 'Simple Search Users' => '简单搜索用户', 'Site Title' => '网站标题', 'Skip First Line' => '跳过第一线', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => '抱歉,此订购不能使用此支付方式。请选择其他支付方式', 'Sorry, seems you have used wrong link' => '抱歉,您使用了错误链接', 'Source Code — Copy/Paste Into Your Website' => '源代码&mdash;复制/粘帖到您的网站', 'Start' => '开始', 'Start Date' => '开始日期', 'State' => '省份', 'Status' => '状态', 'Street' => '街道', 'Street Address' => '街道地址', 'Subject' => '主题', 'Subject can not be empty' => '主题不能为空', 'Subscribe to Site Newsletters' => '订阅网站通讯', 'Subscribers' => '订阅者', 'Subscription Terms' => '订阅条款', 'Subscription/Product Title' => '订阅/产品名称', 'Subtotal' => '小计', 'Target URL' => '目标链接', 'Tax' => '税', 'Tax Amount' => '税额', 'Tax Value' => '税值', 'Terms' => '条款', 'Test Settings' => '试用设置', 'Thank you for Signing up' => '感谢您注册', 'The database has encountered a problem, please try again later.' => '数据库出现问题,请过后重试。', 'The password should be at least %d characters long' => '密码应至少%d个字符长度', 'There are no confirmed payments for your account' => '您的账户无确认的支付', 'This %s is blocked. Please contact site support to find out why' => '%s被屏蔽。请联系网站管理员查明原因', 'This coupon belongs to another customer' => '此优惠券是其他客户的', 'This field is required' => '此栏必填', 'This is a required field' => '必填栏', 'This page will be automatically refreshed within %s' => '此页面将在%s自动刷新', 'This payment system could not handle payments in [%s] currency' => '此支付系统无法处理[%s]货币支付', 'This payment system could not handle zero-total invoices' => '支付系统无法处理0发票', 'Thresehold Date' => '开始日期', 'Ticket' => '问题', 'Ticket has been submited' => '问题已经被提交', 'Tickets' => '问题', 'Title' => '标题', 'To' => '到', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => '给表格增加栏,把物品从“可用组件”移动到“表格组件”。 移动栏,把它移回"可用组件"。 要让表格有多页面,插入“页面分割”到您希望分割的地方。', 'Total' => '总计', 'Try again' => '再试一次', 'Type' => '类型', 'Unknown period unit: %s' => '未知期限单位: %s', 'Unsubscribe from all e-mail messages' => '发送邮件退订所有刊物', 'Unsubscription Confirmation' => '取消订阅确认', 'Update' => '更新', 'Update Credit Card Info' => '更新信用卡信息', 'Updated' => '已更新', 'Upgrade Subscription' => '更新订阅', 'Use Database Connection other than configured for aMember' => '使用数据库连接而不是aMember配置', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => '使用其他MySQL数据库 使用定制空间、用户、密码给%s数据库连接 通常您可以不选这项', 'Useful Links' => '友情链接', 'User' => '用户', 'User Agreement' => '用户协议', 'User Groups' => '用户群组', 'User Info' => '用户信息', 'User Search' => '用户搜索', 'Username' => '用户名', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => '用户名 您可选择新用户名或保持不变 用户名必须%d或更多字符长度并 只包含小写字母、数字和下划线', 'Username %s is already taken. Please choose another username' => '用户名%s已经被使用。请选择其他用户名', 'Username contains invalid characters - please use digits, letters or spaces' => '用户名中包含无效字符-请使用数字、字母或空格', 'Username contains invalid characters - please use digits, letters, dash and underscore' => '用户名中包含无效字符-请使用数字和字母', 'Username/Email' => '电子邮件地址或用户名', 'Users subscribed to Newsletter Threads #' => '订阅通讯#的用户', 'Validate E-Mail Address by sending e-mail message with code' => '通过发送含代码的电邮验证电子邮件地址', 'Validation' => '验证', 'View Basket' => '查看篮子', 'Visit %sorder page%s to order additional subscriptions' => '访问%sorder page%s订购其他订阅', 'Week' => '周', 'Wrong code or code expired - please start signup process again' => '错误代码或代码过期-请再次开始注册过程', 'Wrong parameters, error #1253' => '错误参数,错误#1253', 'Wrong password' => '错误密码', 'Wrong verification code' => '错误验证代码', 'Wrongly signed URL, please contact site admin' => '错误的链接,请联络网站管理员', 'Year' => '年', 'Years' => '年', 'Yes, I want to cancel subscription' => '是对,我想取消订阅', 'Yes, continue' => '是的,继续', 'You are logged-in as %s. %sLogout%s to signup as new user.' => '您作为%s登录。%s注销%s注册新用户。', 'You have no access to %s' => '您无权进入%s', 'You have no active subscriptions' => '您没有有效的订阅', 'You have no items in your basket - please add something to your basket before checkout' => '您的篮子里没有物品-请在结帐前给篮子增加些东西', 'Your Basket' => '您的篮子', 'Your Current Password if you are changing password, please enter your current password for validation' => '您当前密码 如果您要更改密码,请 输入当前密码进行验证', 'Your E-Mail Address a confirmation email will be sent to you at this address' => '您的电子邮件地址 确认电子邮件将被发送 到您的电子邮件地址', 'Your Membership Information' => '您的会员资料', 'Your Subscriptions' => '您的订阅', 'Your password is too long' => '您的密码太长了', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => '您的支付还未被支付系统确认。可能需要几分钟才能确认。', 'Your subject is too verbose' => '您的主题太繁琐', 'ZIP' => '邮编', 'ZIP Code' => '邮编', 'Zip' => '邮编', '[Select country]' => '[选择国家]', '[Select state]' => '[选择省]', '_default_locale' => '英文', 'admin' => '管理员', 'ago' => '之前', 'banned' => '屏蔽的', 'commission found by next rules' => '根据下一规则寻找的佣金', 'days' => '日', 'email' => '电子邮件', 'filtered' => '过滤的', 'for example: 1111-2222-3333-4444' => '例如: 1111-2222-3333-4444', 'generate' => '生成', 'hrs' => '小时', 'ip' => 'IP地址', 'just now' => '刚才', 'login' => '登录', 'min' => '分', 'no records' => '无记录', 'of products' => '商品的', 'on %d-th day' => '在第 %d 天', 'or' => '或', 'pay using wire transfer or by sending offline check' => '电汇支付或发送支票', 'return' => '返回', 'seconds' => '秒', 'use 4111-1111-1111-1111 for successful transaction' => '使用4111-1111-1111-1111成功交易', ); PK\ZFdefault/language/user/de.phpnu[ 'dauerhaft', ' from ' => 'von', ' to ' => 'nach', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" kann zusammen mit diesen Produkten / Abo (s) nur angeordnet werden: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" kann nur angeordnet werden, wenn Sie Abonnement (s) für diese Produkte sind abgelaufen sein: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" kann nicht bestellt, weil Sie aktive Abonnement (s) zu haben sein: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" kann nicht bestellt, weil Sie Abonnement (s) abgelaufen zu sein: %s', '%d-Tier Affiliates Commission ' => '%d-Stufen Partnerprovision ', '%d-th day' => '%d-ter Tag', '%s MySQL Hostname' => '%s MySQL-Hostname', '%s MySQL Password' => '%s MySQL-Passwort', '%s MySQL Username' => '%s MySQL-Benutzername', '%s database and tables prefix' => '%s-Datenbank und Tabellen-Präfix', 'API Authentication Information' => 'API-Authentifizierungs-Info', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Akzeptiere Direktzahlung Zahlungen verarbeiten, die seitens des Zahlungssystems gemacht wurden (ohne vorherige Registrierung bei aMember)', 'Access' => 'Zugriff', 'Access Denied' => 'Zugriff verweigert', 'Access Log' => 'Zugangsprotokoll', 'Access Permissions' => 'Zugriffsberechtigungen', 'Actions' => 'Aktionen', 'Active' => 'Aktiv', 'Active Resources' => 'Aktive Ressourcen', 'Active Subscriptions' => 'Aktive Abonnements', 'Active Users' => 'Aktive Benutzer', 'Active subusers' => 'Aktive Subnutzer', 'Add "Like" button' => '"Like"-Button hinzufügen', 'Add New Notification Rule' => 'Neue Benachrichtigungs-Regel festlegen', 'Add User' => 'Benutzer hinzufügen', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Füge dem Partner Reward-Punkte beim Kauf dieses Produkts hinzu (zusätzliche zu Konfiguration unter aMember CP -> Einrichtung -> Reward-Punkte)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Füge dem Benutzer Reward-Punkte beim Kauf dieses Produkts hinzu (zusätzliche zu Konfiguration unter aMember CP -> Einrichtung -> Reward-Punkte)', 'Add to Basket' => 'In den Warenkorb hinzufügen', 'Add/Renew Subscription' => 'Abonnement hinzufügen/erneuern', 'Added' => 'Hinzugefügt', 'Additional Fields' => 'Zusätzliche Felder', 'Address Info' => 'Adressen-Info', 'Address Information' => 'Adresse Information', 'Admin' => 'Administrator', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Administrator Gruppen aMember nie berührt %s-Konten zugeordnet zu den folgenden Gruppen. Dies schützt %s Accounts gegen jegliche aMember Aktivität', 'Admin Username' => 'Der Benutzername des Administrators', 'Administrator' => 'Administrator', 'Advanced' => 'Fortschrittlich', 'Advanced Search' => 'Erweiterte Suche', 'Advertise our website to your friends and earn money' => 'Machen Sie unsere Webseiten bei Freunden bekannt und verdienen Sie dabei Geld', 'Affiliate' => 'Geschäftspartner', 'Affiliate Agreement' => 'Partner-Vereinbarung', 'Affiliate Clicks' => 'Partner-Klicks', 'Affiliate Id#' => 'Partner-ID-Nr.', 'Affiliate Info' => 'Partner Iinformation', 'Affiliate Payout - Paypal E-Mail address' => 'Partner-Auszahlung - Paypal Mail-Adresse', 'Affiliate Payout Type' => 'Partner-Auszahlungstyp', 'Affiliate Program' => 'Partnerprogramm', 'Affiliate Sales' => 'Partner-Verkäufe', 'Affiliate Signup Form' => 'Partner Anmeldeformular', 'Affiliate info' => 'Partner-Information', 'Affiliate stats' => 'Partnerstatistik', 'Affiliates' => 'Partner', 'All' => 'Alle', 'All %s records on this page are selected' => 'Alle %s Einträge auf dieser Seite sind ausgewählt', 'All Affiliates' => 'Alle Partner', 'All Time' => 'Alle', 'All Users' => 'Alle Benutzer', 'All records' => 'Alle Datensätze', 'Amazon S3 storage is not configured' => 'Amazon S§-Speicher nicht konfiguriert', 'Amount' => 'Betrag', 'An Error has occurred' => 'Ein Fehler ist aufgetreten', 'An account with the same email [%s] is already exists.' => 'Ein Konto mit der selben Mailadresse [%s] existiert bereits.', 'An account with the same email already exists.' => 'Ein Konto mit derselben E-Mail existiert schon.', 'An error occurred while handling your payment.' => 'Fehler während des Zahlungsvorgangs.', 'An internal error happened in the script, please contact webmaster for details' => 'Ein interner Fehler im Skript passiert, kontaktieren Sie bitte webmaster für Details', 'Any Product' => 'Jedes Produkt', 'Any product' => 'Jedes Produkt', 'Api Key' => 'Api Key', 'Apply' => 'anwenden', 'Apply Filter' => 'Filter anwenden', 'Assigned to usergroup' => 'Benutzergruppe zugeordnet', 'Attachments' => 'Anhänge', 'Authentication' => 'Authentication', 'Authentication problem, please contact website administrator' => 'Authentikation Problem, kontaktieren Sie bitte Website Administrator', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Melde Nutzer automatisch in Liste an, sobald er auf diese zugreifen kann', 'Available Bricks (drag to left to add)' => 'Erhältliche Bausteine (ziehen, um mehr hinzuzufügen)', 'Available Credits' => 'Verfügbare Credits', 'Awaiting Admin Response' => 'Warten auf Administratoraktion', 'Awaiting User Response' => 'Warten auf Benutzeraktion', 'Aweber Application' => 'Aweber Anwendung', 'Back' => 'Zurück', 'Bank Code' => 'Bankleitzahl', 'Bank Identification' => 'Bank Identifikation', 'Bank Name' => 'Name der Bank', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Gesperrte Gruppen aMember nie berührt %s-Konten zugeordnet zu den folgenden Gruppen. Dies schützt %s Accounts gegen jegliche aMember Aktivität', 'Banners and Links' => 'Banner und Links', 'Banners and Text Links' => 'Verwalten Sie Banner und Textlinks', 'Begin Date' => 'Anfangsdatum', 'Both Affiliate and member' => 'Beide Partner und Mitglied', 'CC Demo' => 'Die Zahlung ist fehlgeschlagen', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF Schutz Fehler - Form in %d Minuten nach der Anzeige einzureichen, wiederholen Sie bitte', 'Can view/edit customer Credit Card information and rebills' => 'Kann Kreditkarteninformationen von Kunden und erneuten Zahlungen sehen / bearbeiten', 'Cancel' => 'Abbrechen', 'Cancel Subscription' => 'Abonnement kündigen', 'Cancelled' => 'Gekündigt', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Kann nicht das KOSTENLOSE Zahlungs-Plugin mit einem Produkt benutzen, das mehr als 0.0 kostet', 'Cannot validate VAT Id, please try again' => 'USt.-Nr. kann nicht überprüft werden, bitte erneut versuchen', 'Category' => 'Kategorie', 'Change' => 'Ändern', 'Change Password' => 'Passwort ändern', 'Change Password/Edit Profile' => 'Passwort ändern/Profil ändern', 'Change Subscription' => 'Abonnement ändern', 'Change Username' => 'Benutzername ändern', 'Change payout info' => 'Änderung der Auszahl-Information', 'Check Payable To' => 'Scheck zahlbar an', 'Checkout' => 'Checkout', 'Checkout error: ' => 'Checkout-Fehler:', 'Choose a Password must be %d or more characters' => 'Wählen Sie ein Passwort muss %d oder mehr Zeichen sein', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Wählen Sie einen Benutzername es muss %d oder mehr Zeichen lang sein darf nur aus Buchstaben, Zahlen und Unterstrichen bestehen', 'City' => 'Ort', 'Click "Continue" to pay this order using stored credit card %s' => 'Klicken Sie "Fortfahren", um die Bestellung mit hinterlegten Kreditkarteninformationen abzuschließen %s', 'Click button to continue' => 'Zum Fortfahren Button klicken', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Klicken Sie hier, wenn Sie nicht länger warten wollen (oder der Browser Sie nicht automatisch weiterleitet).', 'Click to Edit' => 'Zum Bearbeiten klicken', 'Clicks' => 'Clicks', 'Clicks/Sales Statistics' => 'Partner Clicks/Verkaufsstatistik', 'Close' => 'Schließen', 'Close Ticket' => 'Ticket schließen', 'Closed' => 'Geschlossen', 'Code' => 'Der Code', 'Comment' => 'Kommentar', 'Comment for admin reference' => 'Kommentar für Admnistrator Referenz', 'Commission' => 'Kommission', 'Commissions' => 'Kommissionen', 'Configuration' => 'Konfiguration', 'Configured Tax Values' => 'Konfigurierter Steuerwert', 'Confirm' => 'Bestätigen', 'Confirm New Password' => 'Bestätigen Sie neues Passwort', 'Confirm Password' => 'Passwort bestätigen', 'Confirm Payment' => 'Bestätigung der Bezahlung', 'Confirm Your E-Mail Address' => 'Bestätigen Sie Ihre Mailadresse', 'Confirm Your Password' => 'Bestätigen Sie Ihr Passwort', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Bestätigungs-Link wurde Ihnen per Mail gescht. Bitte überprüfen Sie Ihren Posteingang. Sollten Sie innerhalb von 5 Minuten keine Mail erhalten haben, überprüfen Sie bitte Ihren \'Spam\'-Ordner - unsere Nachricht könnte fälschlicherweise als Spam eingeordnet worden sein.', 'Content' => 'Inhalt', 'Continue' => 'Weiter', 'Conversation' => 'Gespräch', 'Copy of' => 'Kopie von', 'Count of signups' => 'Anzahl Registrierungen', 'Count of user signups' => 'Anzahl Benutzerregistrierungen', 'Country' => 'Land', 'Coupon' => 'Coupon', 'Coupon Code' => 'Couponcode', 'Coupon Discount' => 'Coupon-Discount', 'Coupon code disabled' => 'Coupon-Code deaktiviert', 'Coupon code expired' => 'Coupon-Code abgelaufen', 'Coupon is not yet active' => 'Coupon ist noch nicht aktiv', 'Coupon usage limit exceeded' => 'Coupon Nutzung überschritten', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'aMember-Nutzer auf Anfrage erzeugen erzeuge Kunden in aMember stillschweigend, wenn Benutzer sich in aMember mit demselben Benutzernamen und Passwort, wie für [%s] einzologgen', 'Credit Card Code' => 'Kreditkarten-Code', 'Credit Card Info' => 'Kreditkarten-Info', 'Credit Card Number' => 'Kreditkartennummer', 'Credit Card Rebills' => 'Credit Card erneute Zahlungen', 'Credit Cards' => 'Kreditkarten', 'Credits' => 'Credits', 'Currency' => 'Währung', 'Currency Exchange Rates' => 'Wechselkurse', 'Current password entered incorrectly, please try again' => 'Aktuelles Kennwort falsch eingegeben, bitte versuchen Sie es erneut', 'Custom Commission' => 'Benutzerdefinierte Kommission', 'Customer account has been automatically locked.' => 'Kundenkonto wurde automatisch gesperrt.', 'Customize' => 'Bearbeiten', 'DONE' => 'ERLEDIGT', 'Dashboard' => 'Instrumententafel', 'Data Integrity Code' => 'Datenrichtlinie', 'Date' => 'Datum', 'Date and time of payment: %s' => 'Datum und Zeit der Zahlung: %s', 'Date must be in format %s' => 'Das Datum muss im Format %s werden', 'Date/Time' => 'Datum/Zeit', 'Date: ' => 'Datum:', 'Day' => 'Tag', 'Days' => 'Tage', 'Deactivate Student' => 'Teilnehmer deaktivieren', 'Deactivate User' => 'Benutzer deaktivieren', 'Debit Card Number' => 'Kontonummer', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Standard-Ebene Standard-Ebene - Benutzer wieder auf diese Zugriffsebene wenn keine aktiven Abonnements vorhanden sind (zum Beispiel alle Abonnements abgelaufen)', 'Delete' => 'Löschen', 'Delete %s' => 'Löschen Sie %s', 'Delivery Time' => 'Zustellzeit', 'Description' => 'Beschreibung', 'Digits only please' => 'Bitte nur Ziffern', 'Disable online VAT Id Validation' => 'Deaktiviere Online-Überprüfung der USt.-Nr.', 'Disabled' => 'Deaktiviert', 'Discard' => 'Ablegen', 'Discount' => 'Rabatt', 'Display' => 'Anzeigen', 'Display Type' => 'Display-Typ', 'Display in 2 rows' => 'Anzeige in 2 Spalten', 'Do Import' => 'Importieren', 'Do not add to Login Form' => 'Bitte nicht zum Login-Formular hinzufügen', 'Do not add to Signup Form' => 'Bitte nicht zum Registrierungsformular hinzufügen', 'Do you really want to %s %s %s records' => 'Wollen Sie wirklich %s %s %s Einträge', 'Do you really want to %s?' => 'Wollen Sie wirklich %s?', 'Do you really want to cancel subscription?' => 'Möchten Sie das Abonnement wirklich kündigen?', 'Do you really want to delete record?' => 'Wollen Sie wirklich Datensatz löschen?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Wollen Sie sich wirklich von %s regelmäßigen Nachrichten abmelden?', 'Done' => 'Erledigt', 'Donee name' => 'Empfänger-Name', 'Download' => 'Download', 'Download limit exceeded for this file' => 'Download-Limit für diese Datei erreicht', 'Downloaded on your own server' => 'Auf eigenen Server heruntergeladen', 'E-Mail' => 'E-Mail', 'E-Mail Address' => 'E-Mail-Adresse', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'Mailadresse und -bestätigung stimmen nicht überein. Bitte geben Sie beide erneut ein', 'E-Mail Format' => 'E-Mail-Format', 'E-Mail Messages' => 'E-Mail-Nachrichten', 'E-Mail Verification' => 'E-Mail Verifikation', 'EU VAT' => 'EU USt', 'EU VAT ID: ' => 'EU-USt.-Nr.:', 'EU VAT Id (optional)' => 'EU-USt.-Nr. (optional)', 'Edit' => 'Bearbeiten', 'Edit %s' => 'Bearbeiten %s', 'Edit Brick Labels' => 'Baustein Markierung bearbeiten', 'Edit Categories' => 'Kategorien bearbeiten', 'Edit E-Mail Template' => 'Bearbeiten von E-Mail-Vorlage', 'Email' => 'E-Mail', 'Email Address' => 'E-Mail-Adresse', 'Email Subject' => 'Email Betreff', 'Email [%s] is not valid' => 'E-Mail [%s] ist ungültig', 'Email admin regarding account sharing' => 'Admin per Mail über Account-Sharing informieren', 'Email user regarding account sharing' => 'Nutzer per Mail über Account-Sharing informieren', 'Empty response from Sagepay server' => 'Sagepay-Server liefert leere Antwort', 'Enabled Modules' => 'Aktivierte Module', 'End' => 'Beenden', 'End Date' => 'Endzeit', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => 'Genießen Sie Ihre Mitgliedschaft. Bitte klicken Sie %shier%s, um Zugriff auf den Mitgliedsbereich zu erhalten.', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Viel Freude an der Mitgliedschaft! Zum Anmelden hier klicken %sAnmeldung%s', 'Enter coupon code' => 'Coupon-Code eingeben', 'Enter gift voucher code' => 'Geschenkgutschein-Code eingeben', 'Error 404 - Not Found' => 'Fehler 404 - Nicht gefunden', 'Error : upload folder [%s] does not exists' => 'Fehler: Upload-Ordner [%s] existiert nicht', 'Error from Storage Engine' => 'Fehler von Speicher-Engine', 'Error happened during payment process. ' => 'Fehler beim Bezahlvorgang aufgetreten', 'Error happened during transaction handling. Please contact website administrator' => 'Bei der Transaktionsverarbeitung ist ein Fehler aufgetreten. Bitte kontaktieren Sie den Website-Administrator', 'European (A4)' => 'Europa (A4)', 'Exact' => 'Pünktlich', 'Expire Date' => 'Verfalldatum', 'Expired' => 'Abgelaufen', 'Expired Users' => 'Abgelaufene Benutzer', 'Expires' => 'Läuft ab', 'Export' => 'Export', 'Export Format' => 'Export Format', 'FaceBook App ID' => 'FaceBook App ID', 'FaceBook Application' => 'FaceBook Anwendung', 'Facebook App Secret' => 'FaceBook App Secret', 'Features' => 'Features', 'Field' => 'Feld', 'Field Type' => 'Feldtyp', 'Field Updated' => 'Feld aktualisiert', 'Fields To Display' => 'Anzeigefelder', 'Fields To Export' => 'Zu exportierenden Felder', 'Fieldset' => 'Eingabefelder', 'Fieldset title' => 'Bezeichnung Eingabefelder', 'File' => 'Datei', 'File Downloads' => 'Datei-Downloads', 'File Storage' => 'Dateispeicher', 'File should contain CSV list of user records for import in the following format:
      %s' => 'Datei sollte CSV-Liste von Nutzerdaten zum Inport im folgenden Format enthalten:
      %s', 'Filename' => 'Dateiname', 'Files' => 'Dateien', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'Dateien befinden sich im Amazon S3-Speicher. (Warnung: Ihre Buckets sollten keine Großbuchstaben im Namen haben)', 'Files uploaded via aMember web interface' => 'Dateien via aMember Web-Interface hochgeladen', 'Filter' => 'Filter', 'First & Last Name' => 'Vorname und Nachname', 'First Name' => 'Der Vorname', 'Folder %s (%s)' => 'Ordner %s (%s)', 'Folders' => 'Ordner', 'Form Page Break' => 'Formular Seitenumbruch', 'Free' => 'Frei', 'Free Access' => 'Freier Zugang', 'Free Access without log-in' => 'Freier Zugriff ohne Login', 'Free Signup' => 'Kostenlose Einschreibung', 'From' => 'Von', 'GST (Inclusive Tax)' => 'Mehrwertsteuer', 'Get Password' => 'Passwort erhalten', 'Gift Voucher' => 'Geschenkgutschein', 'Gift Vouchers' => 'Geschenkgutscheins', 'Global Commission' => 'Globale Provision', 'Global Tax' => 'Allgemeine Steuer', 'Groups' => 'Gruppen', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'Gruppen-Priorität Ziehen Sie Gruppen hier rein, um sie zu ordnen. Sollten mehrere Gruppen für einen Benutzer verfügbar sein wird aMember die Gruppen wählen, die weiter oben in der Liste stehen, als "Primär"', 'HTML Code that will be displayed' => 'Angezeigter HTML-Code', 'HTML Message' => 'HTML-Nachricht', 'HTML text' => 'HTML-Text', 'Having Active Subscription To:' => 'Mit aktivem Abonnement an:', 'Having Expired Subscription To:' => 'Nach abgelaufener Abonnements an:', 'Helpdesk' => 'Helpdesk', 'Hide do not display this item link in members area' => 'Ausblenden Link zu diesem Artikel im Mitgliederbereich ausblenden', 'Hosted at Activecampaing\'s server' => 'Auf Activecampaign-Server gehosted', 'Housenumber' => 'Hausnummer', 'IP Address' => 'IP-Adresse', 'If you already have an account on our website, please %slog in%s to continue' => 'Falls Sie bereits ein Konto besitzen, bitte %sanmelden%s', 'If you are a registered member, please %slogin%s' => 'Falls Sie registriertes Mitglied sind, bitte %sanmelden%s', 'If you are not registered yet, please %ssignup%s' => 'Falls Sie noch nicht registriert sind, bitte %seinschreiben%s', 'Income Report - payments minus refunds' => 'Einkommens-Bericht - Zahlungen abzüglich Rückforderungen', 'Incorrect Parent Affiliate ID' => 'Falsche Parent-Partner-ID', 'Insert comment into email' => 'Kommentar in Mail einfügen', 'Integer Value' => 'Integer Wert', 'Integer value required' => 'Integer-Wert erforderlich', 'Integration' => 'Integration', 'Integrations' => 'Integrationen', 'Internal Error' => 'Interner Fehler', 'Invalid Account Number' => 'Ungültige Kontonummer', 'Invalid Credit Card Number' => 'ungültige Kreditkartennummer', 'Invalid Debit Card Number' => 'Ungültige Kontonummer', 'Invalid Expiration Date - Month' => 'Ungültiges Ablaufdatum - Monat', 'Invalid Expiration Date - Year' => 'Ungültiges Ablaufdatum - Jahr', 'Invalid Issue Number' => 'Ungültige Ausgabe Nummer', 'Invalid Routing Number' => 'Ungültige ABA-Nummer', 'Invalid VAT Id, please try again' => 'Ungültige USt.-Nr., bitte erneut versuchen', 'Invite Code' => 'Einladungscode', 'Invoice' => 'Rechnung', 'Invoice Number: ' => 'Rechnungsnummer:', 'Invoice not found' => 'Rechnung nicht gefunden', 'Is Gift Voucher?' => 'Ist Geschenkgutschein?', 'Is Locked' => 'Ist gesperrt', 'Is Paid?' => 'Ist bezahlt?', 'Is Send At Later Date?' => 'Wird später versandt?', 'Is Disabled?' => 'Ist deaktiviert?', 'Item' => 'Artikel', 'Label' => 'Label', 'Language' => 'Sprache', 'Last 14 Days' => 'Letzte 14 Tage', 'Last 30 Days' => 'Letzte 30 Tage', 'Last 7 Days' => 'Letzte 7 Tage', 'Last Business Week (Mon-Fri)' => 'Letzte Geschäftswoche (Mo-Fr)', 'Last Messages in Helpdesk' => 'Letzte Nachrichten im Helpdesk', 'Last Month' => 'Letzter Monat', 'Last Name' => 'Der Nachname', 'Last Week (Mon-Sun)' => 'Letzte Woche (Mo-So)', 'Last Week (Sun-Sat)' => 'Letzte Woche (So-Sa)', 'Leads' => 'Kundenkontakte', 'License Key' => 'Lizenzschlüssel', 'Lifetime' => 'Lebensdauer', 'Like Url' => 'Like-URL', 'Link' => 'Link', 'Links' => 'Links', 'Live Edit %s' => 'Live Bearbeitung Live Edit %s', 'Loading' => 'Lädt', 'Log In' => 'Anmelden', 'Log all API Requests' => 'Alle API-Anfragen loggen', 'Login' => 'Anmelden', 'Login as User' => 'Login als Benutzer', 'Logout' => 'Abmelden', 'Lost Password Sending Error' => 'Fehler beim Senden des vergessenen Passworts', 'Lost Password Sent' => 'Vergessenes Passwort verschickt', 'Lost password?' => 'Vergessenes Passwort', 'Mail Queue' => 'Mail Reihe', 'Make Payment' => 'Zahlung', 'Make a Donation' => 'Spenden Sie!', 'Make donation recurring' => 'regelmäßig Spenden', 'Manage Newsletters' => 'Newsletters verwalten', 'Marketing Materials' => 'Marketing-Materialien', 'Members Directory' => 'Mitgliederverzeichnis', 'Members Directory [%s] does not exists' => 'Mitgliederverzeichnis [%s] existiert nicht', 'Membership Type' => 'Mitgliedschafts-Typ', 'Merchant Key' => 'Verkäuferschlüssel', 'Merchant Secret' => 'Verkäufer-Passphrase', 'Message' => 'Nachricht', 'Message can not be empty' => 'Nachricht darf nicht leer sein', 'Moip Payment' => 'MoIP (Money over IP) Zahlung', 'Month' => 'Monat', 'Months' => 'Monate', 'Multiplier' => 'Multiplikator', 'My Country' => 'Mein Land', 'NEVER' => 'NIE', 'Name' => 'Name', 'Never' => 'Niemals', 'New' => 'Neu', 'New %s' => 'Neu %s', 'New Password' => 'Neues Passwort', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Neues Passwort Sie können hier Ihr neues Passwort wählen, oder halten Sie es unverändert muss %d oder mehr Zeichen sein', 'Newsletter' => 'Newsletter', 'Newsletter Subscriptions' => 'Newsletter Abonnements', 'Next' => 'Weiter', 'No' => 'Nein', 'No commissions on this date' => 'Keine Provisionen an diesem Tag', 'No coupons found with such coupon code' => 'Keine Gutscheine mit einem solchen Gutschein-Code gefunden', 'No gift vouchers found with such code' => 'Keine Geschenkgutscheine mit diesem Code gefunden', 'No items in this section' => 'Keine Artikel in diesem Bereich', 'No items selected for purchase' => 'Keine Artikel zum Kauf ausgewählt', 'No records found' => 'Keine Datensätze gefunden', 'No, cancel' => 'Nein, abbrechen', 'No, keep me subscribed' => 'Nein, angemeldet bleiben', 'No, please keep me subscribed' => 'Nein, bitte Abonnement beibehalten', 'Not Approved Affiliates' => 'Nicht-freigegebene Partner', 'Not Selected' => 'Nicht ausgewählt', 'Not assigned to usergroup' => 'Benutzergruppe nicht zugeordnet', 'Not registered yet?' => 'Noch nicht registriert?', 'Number of Messages to display' => 'Anzahl der anzuzeigenden Nachrichten', 'Numeric Value' => 'Numerischer Wert', 'Numeric value required' => 'v', 'Offline Payment' => 'Offline Zahlung', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'Sobald die Plugin-Einrichtung auf dieser Seite abgeschlossen ist, vergessen Sie nicht einen Eintrag unter %saMember CP -> Inhalt schützen -> Integrationen%s vorzunehmen', 'Only Affiliate %s(rarely used)%s' => 'Nur Partnerprogramm %s(selten verwendet)%s', 'Order reference: %s' => 'Bestell-Hinweis: %s', 'Other' => 'Andere', 'Our system will try to charge your card again on %s' => 'Unser System wird wieder versuchen Ihre Karte am %s zu belasten', 'Pages' => 'Seiten', 'Password' => 'Passwort', 'Password and Password Confirmation are different. Please reenter both' => 'Passwort und Passwortbestätigung sind unterschiedlich. Bitte beide nochmals eingeben', 'Password must contain at least %d letters or digits' => 'Passwort muss mindestens %d Buchstaben oder Ziffern lang sein', 'Passwords do not match' => 'Passwörter stimmen nicht überein', 'Path to %s' => 'Pfad an %s', 'Path to %s Folder' => 'Pfad an %s Mappe', 'Payanyway plugin does not support recurring billing!' => 'Payanyway-Plugin unterstützt keine wiederkehrenden Zahlungen!', 'Payment' => 'Zahlung', 'Payment Confirmation' => 'Zahlungsbestätigung', 'Payment Error' => 'Zahlungsfehler', 'Payment Failed' => 'Zahlung fehlgeschlagen', 'Payment Info' => 'Zahlungsinformation', 'Payment System' => 'Zahlungssystem', 'Payment System Description' => 'Zahlungssystem Beschreibung', 'Payment System Title' => 'Zahlungssystem Titel', 'Payment error: ' => 'Zahlungsfehler:', 'Payment failed' => 'Die Zahlung ist fehlgeschlagen', 'Payment info' => 'Zahlungsinformation', 'Payment is already processed, please go to %sMembership page%s' => 'Zahlung wurde schon bearbeitet, bitte gehen Sie zur %sMitgliedsseite%s', 'Payments' => 'Zahlungen', 'Payments History' => 'Zahlungen Geschichte', 'Payments by New vs Existing members' => 'Zahlungen für Neue vs. bereits existierende Mitglieder', 'Payments by payment system breakdown' => 'Zahlungen je Zahlungssystem', 'Payments by products breakdown' => 'Zahlungen je Produkt', 'Payments from existing customers' => 'Zahlungen bereits existierender Kunden', 'Payments from new customers' => 'Zahlungen neuer Kunden', 'Payments total' => 'Zahlungen gesamt', 'Payout Method' => 'Zahlungsmethode', 'Payouts' => 'Auszahlungen', 'Pending' => 'Anstehend', 'Pending Invoices' => 'Ausstehende Rechnungen', 'Pending subusers' => 'Ausstehende Subnutzer', 'Period' => 'Periode', 'Period must be in interval 1-24 months' => 'Zeitraum muss ein Intervall haben von 1-24 Monaten', 'Period must be in interval 1-5 years' => 'Zeitraum muss ein Intervall haben von 1-5 Jahren', 'Period must be in interval 1-90 days' => 'Zeitraum muss ein Intervall haben von 1-90 Tagen', 'Personal Content' => 'Perönlicher Inhalt', 'Phone' => 'Telefon', 'Phone Number' => 'Telefonnummer', 'Plain-Text Message' => 'Einfache Text-Nachricht', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Bitte %sanmelden%s zu bestehendem Konto.%sWenn Sie die Zahlung nicht vollendet haben, werden Sie das nach der Anmeldung machen können', 'Please Select' => 'Bitte wählen', 'Please agree to Affiliate Agreement' => 'Bitte lesen Sie die Partner Vereinbarung', 'Please agree to User Agreement' => 'Bitte stimmen Sie Nutzungsvereinbarung zu ', 'Please choose' => 'Bitte wählen Sie', 'Please choose a Credit Card Type' => 'Bitte wählen Sie einen Kreditkartentyp', 'Please choose a membership type' => 'Bitte wählen Sie einen Mitgliedschaftstyp', 'Please choose a payment system' => 'Bitte wählen Sie ein Zahlungssystem', 'Please choose state' => 'Bitte wählen: US-Bundesstaat', 'Please enter %s' => 'Bitte geben Sie %s ein', 'Please enter Account Number' => 'Bitte geben Sie Ihre Kontonummer ein', 'Please enter City' => 'Bitte Ort eingeben', 'Please enter Country' => 'Bitte Land eingeben', 'Please enter Credit Card Code' => 'Bitte eingeben: Kreditkarten-Code', 'Please enter Credit Card Number' => 'Bitte eingeben: Kreditkartennummer', 'Please enter Debit Card Number' => 'Bitte geben Sie die Kontonummer ein', 'Please enter Password' => 'Bitte Passwort eingeben', 'Please enter Routing Number' => 'Bitte geben Sie Ihre ABA-Nummer ein', 'Please enter State' => 'Bitte US-Bundesstaat eingeben', 'Please enter Street Address' => 'Bitte Straße eingeben', 'Please enter ZIP code' => 'Bitte geben Sie die PLZ ein', 'Please enter a valid e-mail address' => 'Bitte geben Sie eine gültige E-Mail-Adresse ein', 'Please enter correct amount' => 'Bitte geben Sie einen korrekten Betrag an', 'Please enter coupon code' => 'Gutschein-Code erneut eingeben', 'Please enter credit card holder first name' => 'Bitte eingeben: Kreditkartenbesitzer Vorname', 'Please enter credit card holder last name' => 'Bitte eingeben: Kreditkartenbesitzer Nachname', 'Please enter credit card holder name' => 'Bitte eingeben: Name des Kreditkartenbesitzers', 'Please enter debit card holder first name' => 'Bitte geben Sie den Vornamen des Kontoinhabers an', 'Please enter debit card holder last name' => 'Bitte geben Sie den Nachnamen des Kontoinhabers an', 'Please enter debit card holder name' => 'Bitte geben Sie den Kontoinhaber an', 'Please enter first name' => 'Bitte geben Sie Ihren Vornamen ein', 'Please enter gift voucher code' => 'Bitte geben Sie einen Geschenkgutschein-Code ein', 'Please enter housenumber' => 'Bitte eingeben: Hausnummer', 'Please enter phone number' => 'Bitte eingeben: Telefonnummer', 'Please enter valid Email' => 'Bitte gültige E-Mail wählen', 'Please enter valid Username. It must contain at least %d characters' => 'Bitte geben Sie eine gültige Benutzername ein. Es muss mindestens %d Zeichen sein', 'Please enter your First Name' => 'Bitte geben Sie Ihren Vornamen ein', 'Please enter your Last Name' => 'Bitte geben Sie Ihren Nachnamen ein', 'Please enter your current password for validation' => 'Bitte geben Sie Ihr aktuelles Passwort für die Validierung ein', 'Please enter your last name' => 'Bitte geben SIe Ihren Nachnamen ein', 'Please enter your name' => 'Bitte geben Sie Ihren Namen ein', 'Please login' => 'Bitte anmelden', 'Please select' => 'Bitte auswählen', 'Please select an item...' => 'Bitte wählen Sie einen Artikel ...', 'Please select payment system for payment' => 'Bitte Zahlungssystem für Zahlung wählen', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Bitte benutzen Sie das Formular %sAbonnements hinzufügen/erneuern,%s um ein Abonnement hinzuzufügen oder zu erneuern.', 'Please wait %d seconds before next login attempt' => 'Bitte warten %d Sekunden vor dem nächsten Login-Versuch', 'Plugin' => 'Das Plugin', 'Plugin List Id' => 'Plugin-Listen-ID', 'PostAffiliatePro Parent Affiliate ID' => 'PostAffiliatPro Parent-Partner-ID', 'PostAffiliatePro Referral ID' => 'PostAffiliatePro Referral-ID', 'Prev' => 'Zurück', 'Preview' => 'Vorschau', 'Price' => 'Preis', 'Processing your Transaction' => 'Transaktion wird bearbeitet', 'Processing your product upgrade' => 'Produkt-Upgrade wird bearbeitet', 'Product' => 'Produkt', 'Product %s is incompatible with product %s. Reason: %s' => 'Produkt %s ist nicht mit Produkt %s kompatibel. Grund: %s', 'Product Categories' => 'Produktkategorien', 'Product Title' => 'Produktname', 'Product upgrade finished successfully' => 'Produkt-Upgrade erfolgreich abgeschlossen', 'Product(s) to display' => 'Produkt (e) zur Anzeige', 'Products' => 'Products', 'Products keep empty to report all products' => 'Produkte frei lassen, um alle Produkte zu erfassen', 'Profile' => 'Profil ändern', 'Profile update transaction failed' => 'Profilaktualisierung fehlgeschlagen', 'Protected Content [%s-%d]' => 'Geschützter Inhalt [%s-%d]', 'Purchased Credits' => 'Erworbene Credits', 'Qty' => 'Menge', 'Quantity' => 'Menge', 'Quick Order' => 'Schnelle Bestellung', 'Quickpay parameters' => 'Quickpay-Parameter', 'Re-Open Ticket' => 'Ticket Wiederöffnen', 'Read-only' => 'Nur-Lesen', 'Real Path' => 'Tatsächlicher Pfad', 'Record' => 'Verzeichnis', 'Record Type' => 'Datensatztyp', 'Record [%s] not found' => 'Datensatz [%s] nicht gefunden', 'Records that match all these conditions' => 'Datensätze, die alle diese Bedingungen erfüllen', 'Recurring' => 'Wiederkehrend', 'Redirect to NetDebit booking form.' => 'Weiterleitung zum NetDebit Buchungsformular.', 'Reference number is:' => 'Referenz-Nummer lautet:', 'Referer' => 'Referrer ', 'Referred Affiliate' => 'Verbundener Partner', 'Refresh' => 'Auffrischen', 'Refresh 3-rd party lists' => 'Drittanbieter-Listen aktualisieren', 'Refund' => 'Rückzahlung', 'Refund Amount' => 'Erstattungsbetrag', 'Refunded' => 'Zurückgezahlt', 'Regional Tax' => 'Regionale Steuer', 'Register' => 'Registrieren', 'Remote API Permissions' => 'Remote-API', 'Remove' => 'Entfernen', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Benutzer entfernen wenn der Benutzer Datensatz aus aMember entferntmüssen die zugehörigen Datensatz aus %s entfernt werden', 'Remove user' => 'Benutzer entfernen', 'Reply' => 'Antworten', 'Required' => 'Erforderlich', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Wiederholen Bei Fehler wenn die wiederkehrenden Zahlungen ist gescheitert, aMember kann es nach mehreren Tagen wiederholen, und erweitern Kunde Abonnement für diesen Zeitraum Geben Sie Anzahl der Tage bis zur Abrechnung Versuch wiederholen', 'Return' => 'Zurück', 'Return and try again' => 'Gehen Sie zurück und versuchen Sie es nochmals', 'Review/Pay Commissions' => 'Nachprüfung/ Zahlungs Partner-Kommission', 'Reward Points' => 'Reward-Punkte', 'Reward Points Configuration' => 'Reward-Punkte-Konfiguration', 'Run Report' => 'Bericht ausführen', 'Running %s' => 'Laufen %s', 'Save' => 'Speichern', 'Save Profile' => 'Profil speichern', 'Search' => 'Suchen', 'Search Products' => 'Produkte suchen', 'Security code is invalid' => 'Sicherheitscode ist ungültig', 'Select a condition to add into search' => 'Wählen Sie eine Bedingung in Suche hinzufügen', 'Select all %s records matching your search' => 'Wählen Sie alle %s Datensätze die Ihrer Suche entsprechen', 'Send' => 'Senden', 'Send Cancel Notifications to User' => 'Kündigungsbestätigung an Benutzer', 'Send Voucher To' => 'Gutschein senden an', 'Session expired, please enter username and password again' => 'Sitzung abgelaufen, bitte nochmals Benutzername und Passwort eingeben', 'Settings' => 'Einstellungen', 'Shipping' => 'Versand', 'Shipping Options' => 'Versandoptionen', 'Shopping Cart' => 'Warenkorb', 'Shopping Cart Module. No data input' => 'Warenkorb-Modul. Keine Dateneingabe', 'Shopping Cart Module. No product id input' => 'Warenkorb-Modul. Keine Produkt-ID-Eingabe', 'Sign-up' => 'Registrieren', 'Signature' => 'Signatur', 'Signup Form' => 'Anmeldeformular', 'Signup here' => 'Hier anmelden', 'Signup/payment functions are disabled for this user account' => 'Registrierungs-/Zahlungsfunktionen für dieses Konto deaktiviert', 'Simple Search Users' => 'Einfache Suche der Benutzer', 'Site Title' => 'Titel der Seite', 'Skip First Line' => 'Die erste Linie auslassen', 'Snippets' => 'Snippets', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Leider ist es unmöglich, diese Zahlungsmethode für Ihre Bestellung zu verwenden. Bitte wählen Sie eine andere Zahlungsmethode', 'Sorry, seems you have used wrong link' => 'Entschuldigung, Sie haben einen falschen Link benutzt', 'Source Code — Copy/Paste Into Your Website' => 'Primärkode — Kopieren / Einfügen in Ihre Webseite', 'Standard' => 'Standard', 'Start' => 'Start', 'Start Date' => 'Anfangsdatum', 'State' => 'US-Bundesstaat', 'Status' => 'Status', 'Street' => 'Straße', 'Street (Second Line)' => 'Straße und Hausnummer', 'Street Address' => 'Straße', 'Street Address (Second Line)' => 'Straßenanschrift', 'SubUsers Count (keep zero for non-reseller products)' => 'SubUser-Anzahl (auf Null lassen für Nicht-Wiederverkäuferprodukte)', 'SubUsers Product (keep empty for non-reseller products)' => 'SubUser-Produkt (leer lassen für Nicht-Wiederverkäuferprodukte)', 'Subject' => 'Betreff', 'Subject can not be empty' => 'Betreff darf nicht leer sein', 'Submit' => 'Abschicken', 'Subscribe And Pay' => 'Abonnieren und bezahlen', 'Subscribe all available users' => 'Alle verfügbaren Nutzer abonnieren', 'Subscribe to Site Newsletters' => 'Newsletters für diese Webseiten abonnieren', 'Subscribed To Newsletters' => 'Newsletter abonniert', 'Subscribers' => 'Abonnenten', 'Subscription Terms' => 'Abonnement AGB', 'Subscription/Product Title' => 'Abonnement-/Produkt-Titel', 'Subtotal' => 'Nettopreis', 'Subusers' => 'Subnutzer', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => 'Erfolgreich: %d (%0.2f %s) Fehlgeschlagen: %d (%0.2f %s)', 'Such affiliate ID exist' => 'Diese Partner-ID existiert', 'Support Us!' => 'Unterstützen Sie uns!', 'TOTAL' => 'GESAMT', 'Target URL' => 'Ziel-URL', 'Tax' => 'Steur', 'Tax Amount' => 'Betrag Steuer', 'Tax Id' => 'Steuernummer', 'Tax Rate for example 18.5 (no percent sign)' => 'Steuersatz beispielsweise 18.5 (ohne Prozentzeichen)', 'Tax Title' => 'Steuertitel', 'Tax Value' => 'Der Steuerwert', 'Terms' => 'Bedingungen', 'Test Mode' => 'Testbetrieb', 'Test Settings' => 'Einstellungen testen', 'Thank you for Signing up' => 'Danke für die Einschreibung', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Vielen Dank! Ihre Zahlung ist AUSSTEHEND & wird bearbeitet. Wir werden Ihr Abonnement aktualisieren, sobald die Zahlung abgeschlossen ist. Bitte gedulden Sie sich währenddessen. Voraussichtliche Dauer ist 12 bis 24 Stunden. Sie werden eine Benachrichtigung per Mail über den Zahlungserhalt bekommen.', 'The database has encountered a problem, please try again later.' => 'Die Datenbank hat ein Problem festgestellt, versuchen Sie es später erneut.', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'Die Datei wurde entfernt oder ist beschädigt. Bitte versuchen Sie es erneut.', 'The following words are reserved : %s' => 'Die folgenden Wörter sind reserviert: %s', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'Die Nachricht, die Ihr Passwort enthält, wurde bereits an Sie gesendet. Bitte warten Sie 180 Minuten für einen erneuten Versuch', 'The password should be at least %d characters long' => 'Das Passwort sollte mindestens %d Zeichen lang sein', 'The user name or password is incorrect' => 'Benutzername oder Passwort falsch', 'There are no confirmed payments for your account' => 'Es gibt keine bestätigten Zahlungen für Ihr Konto', 'There are no form available for affiliate signup.' => 'Es ist kein Formular für Parnet-Registrierung verfügbar.', 'There are no products available for purchase. Please come back later.' => 'Es sind keine Produkte zum Kauf verfügbar. Bitte kommen Sie später wieder.', 'This %s is blocked. Please contact site support to find out why' => 'Diese %s ist gesperrt. Bitte kontaktieren Sie Unterstützung vor Ort, um herauszufinden, warum', 'This Month' => 'Dieser Monat', 'This Week (Mon-Sun)' => 'Diese Woche (Mo-So)', 'This Week (Sun-Sat)' => 'Diese Woche (So-Sa)', 'This coupon belongs to another customer' => 'Dieser Coupon gehört zu einem anderen Kunden', 'This field is required' => 'Dieses Feld ist erforderlich', 'This is a required field' => 'Dies ist ein Pflichtfeld', 'This page will be automatically refreshed within %s' => 'Diese Seite wird automatisch in %s aktualisiert werden', 'This payment system could not handle payments in [%s] currency' => 'Dieses Zahlungssystem konnte damit nicht Zahlungen in [%s] Währung bearbeiten', 'This payment system could not handle zero-total invoices' => 'Dieses Zahlungssystem konnte damit nicht Null-total Rechnungen bearbeiten', 'Thresehold Date' => 'Datum des Schwellwerts', 'Ticket' => 'Ticket', 'Ticket has been submited' => 'Ticket wurde eingesetzt', 'Tickets' => 'Tickets', 'Title' => 'Titel', 'To' => 'An', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Um Felder in das Formular einzufügen, verschieben Sie Element aus \'Verfügbare Bausteine\' auf \'Formulare Bausteine\'. So entfernen Sie Felder, bringen Sie ihn wieder zu "Verfügbare Bausteine \'. Zur Bildung multi-page, legen Sie \'PageSeparator\' Artikel in den Ort ein, wo Sie wollen, um aufgeteilt werden können.', 'Today' => 'Heute', 'Total' => 'Gesamt', 'Transactions' => 'Transaktionen', 'Try again' => 'Nochmals versuchen', 'Type' => 'Typ', 'USA (Letter)' => 'USA (Brief)', 'Unable to cancel subscription: ' => 'Beenden des Abonnements nicht möglich', 'Unable to delete this file as it is used for:' => 'Löschen der Datei nicht möglich, da in Benutzung:', 'Unenroll Student' => 'Teilnehmer abmelden', 'Unit Price' => 'EInzelpreis', 'Unknown period unit: %s' => 'Unbekannte Zeitraum-Einheit: %s', 'Unsubscribe' => 'Abbestellen', 'Unsubscribe from all e-mail messages' => 'Alle E-Mail-Nachrichten abbestellen', 'Unsubscribed' => 'Abbestellt', 'Unsubscription Confirmation' => 'Bestätigung der Abbestellung', 'Update' => 'Aktualisierung', 'Update Credit Card Info' => 'Kreditkarte aktualisieren ', 'Update Debit Card Info' => 'Lastschriftinformationen aktualisieren', 'Updated' => 'Aktualisiert', 'Upgrade Subscription' => 'Abonnement aktualisieren', 'Upload files using FTP client to [%s]' => 'Lade Dateien per FTP nach [%s] hoch', 'Use Database Connection other than configured for aMember' => 'Verwenden Sie Datenbakverbindung anders als aMember konfiguriert', 'Use Reward Points' => 'Reward-Punkte nutzen', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Verwenden Sie eine andere MySQL Db benutzerdefinierte Host, Benutzer, Passwort für %s Datenbankverbindung Normalerweise können Sie dieses Kontrollkästchen nicht markieren', 'Used' => 'Benutzt', 'Useful Links' => 'Nützliche Links', 'User' => 'Benutzer', 'User Agreement' => 'Nutzungsvereinbarung', 'User Groups' => 'Benutzergruppen', 'User Info' => 'Benutzer Information', 'User Search' => 'Benutzer suchen', 'User is locked' => 'Benutzer ist gesperrt', 'User is not approved' => 'Benutzer ist nicht freigegeben', 'User must provide' => 'Benutzer muss folgendes angeben', 'Username' => 'Benutzername', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Benutzername Sie können neue Benutzernamen hier wählen oder halten Sie es unverändert. Der Benutzername muss %d oder mehr Zeichen lang sein', 'Username %s is already taken. Please choose another username' => 'Benutzername %s ist bereits vergeben. Bitte wählen Sie einen anderen Benutzernamen', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'Benutzername [%s] enthält unzulässige Zeichen - Bitte Ziffern und Buchstaben benutzen', 'Username [%s] is already taken. Please choose another username' => 'Benutzname [%s] ist bereits vergeben. Bitte wählen Sie einen Anderen.', 'Username contains invalid characters - please use digits, letters or spaces' => 'Benutzername enthält ungültige Zeichen - bitte Ziffern, Buchstaben oder Leerzeichen verwenden', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'enthält ungültige Zeichen - bitte Ziffern oder Buchstaben verwenden', 'Username/Email' => 'E-Mail-Adresse oder Benutzername', 'Users subscribed to Newsletter Threads #' => 'Benutzer abonniert Newsletter Threads #', 'VAT Id' => 'Ust.-Nr.', 'Validate E-Mail Address by sending e-mail message with code' => 'Bestätigen Sie die E-Mail-Adresse per E-Mail-Nachricht mit Code', 'Validation' => 'Bestätigung', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'Bestätigung wurde an Ihr Mail-Adresse geschickt. E-Mail wird in Ihrem Account nach Bestätigung geändert', 'Version of script' => 'Skript-Version', 'Video' => 'Video', 'View Basket' => 'Warenkorb anzeigen', 'Visit %sorder page%s to order additional subscriptions' => 'Besuchen %sSie um Seite%s, um zusätzliche Abos bestellen', 'Voucher is not yet active' => 'Gutschein ist nicht aktiviert', 'Week' => 'Woche', 'Wrong code or code expired - please start signup process again' => 'Falscher Code oder Code - please starten Anmeldevorgang wieder', 'Wrong link - no id passed' => 'Falscher Link - keine ID übergeben', 'Wrong parameters, error #1253' => 'Falscher Parameter, Fehlermeldung # 1253', 'Wrong password' => 'Falsches Passwort', 'Wrong verification code' => 'Falsche Verifizierungscode', 'Wrongly signed URL, please contact site admin' => 'Falsche signed URL, bitte Webseiten Administrator kontaktieren', 'Year' => 'Jahr', 'Years' => 'Jahre', 'Yes' => 'Ja', 'Yes, I want to cancel subscription' => 'Ja, ich möchte Abonnement kündigen', 'Yes, continue' => 'Ja, fortsetzen', 'Yes, unsubscribe' => 'Ja, abmelden', 'Yesterday' => 'Gestern', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'You are logged-in as %s. %sLogout%s to signup as new user.', 'You have %s%d ticket(s)%s that require your attention' => 'Sie haben %s%d Tickets%s, die Ihre Aufmerksamkeit erfordern', 'You have no access to %s' => 'Sie haben keinen Zugrif an %s', 'You have no active subscriptions' => 'Sie haben keine aktiven Abonnements', 'You have no enough permissions for this operation' => 'Sie haben keine ausreichenden Berechtigungen für diese Aktion', 'You have no items in your basket - please add something to your basket before checkout' => 'Sie haben keine Artikel im Warenkorb - fügen Sie bitte etwas zu Ihrem Warenkorb vor der Kasse', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'Sie haben diesem Account zu viele Subnutzer zugewiesen. Entfernen Sie %d Nutzer von Ihrem Account', 'You must be authorized to access this area' => 'Sie sind nicht berechtigt diesen Bereich zu betreten', 'You must be logged-in to open this media' => 'Sie müssen eingeloggt sein, um dieses Medium zu öffnen', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Sie müssen aMember CP -> Einrichtung -> Erweitert -> Sitzungsspeicher auf \'Standard-PHP-Sitzungen\' ändern. Notwendig, um Single-Login zwischen aMember und SilverStrype zu aktivieren', 'Your 9 digit ABA Routing Number' => 'Ihre 9-stellige ABA-Nummer ein', 'Your Account Removal' => 'Ihre Account-Löschung', 'Your Bank Account Number' => 'Ihre Kontonummer', 'Your Basket' => 'Ihr Warenkorb', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Ihr aktuelles Passwort Wenn Sie beim Ändern des Kennworts sind, bitte Geben Sie Ihr aktuelles Passwort für die Validierung ein', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Ihre E-Mail-Adresse eine Bestätigung per E-Mail gesendet an dieser Adresse', 'Your General Affiliate Link' => 'Dein allgemeiner Partner-Link', 'Your Membership Information' => 'Ihre Mitgliedschafts-Information', 'Your Payment is PENDING & Under Process' => 'Ihre Zahlung ist AUSSTEHEND & wird bearbeitet', 'Your Personal Downloads' => 'Ihre persönlichen Downloads', 'Your Reseller Packages' => 'Ihre Wiederverkäuferpakete', 'Your Subscriptions' => 'Ihre Abonnements', 'Your account has been automatically locked.' => 'Ihr Account wurde automatisch gesperrt.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Ihr Konto wurde noch nicht freigegeben. Sie werden per Mail benachrichtige, sobald ein Administrator Ihren Account überprüft und aktiviert hat.', 'Your password is too long' => 'Ihr Passwort ist zu lang', 'Your payment has been successfully processed.' => 'Ihre Zahlung wurde erfolgreich verarbeitet.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Ihre Zahlung ist noch nicht vom Zahlungssystem bestätigt. Es kann einige Minuten dauern, um eine Bestätigung der Zahlung erhalten.', 'Your profile has been updated successfully' => 'Ihr Profil wurde erfolgreich aktualisiert', 'Your subject is too verbose' => 'Ihr Motiv ist zu wortreich', 'Your subscription does not allow access to this media' => 'Ihr Abonnement erlaubt keine Zugriff auf dieses Medium', 'Your subscription has been successfully processed.' => 'Ihr Abonnement wurde erfolgreich verarbeitet.', 'ZIP' => 'PLZ', 'ZIP Code' => 'Postleitzahl', 'Zip' => 'Die Postleitzahl ', '[Select country]' => '[Wahlen Sie Land vor]', '[Select state]' => '[Wahlen Sie Zustand vor]', '_default_locale' => 'de_DE', 'accepts all major credit cards' => 'akzeptiert alle gängigen Kreditkarten', 'admin' => 'Administrator', 'affiliate program commissions' => 'Partnerprogramm-Provisionen', 'after completing order, voucher will be sent to specified address' => 'nach Abschluss der Bestellung, wird Gutschein an angegebene Adresse geschickt', 'ago' => 'vor', 'banned' => 'verboten', 'check box to use points and get discount' => 'Auswählen, um Punkte zu nutzen und Ermäßigungen zu erhalten', 'check it if you want to gift subscription on this product' => 'Auswählen, wenn Abonnement zu diesem Produkt geschenkt wird', 'commission found by next rules' => 'Kommission bis zum nächsten Regeln gefunden', 'day' => 'Tag', 'days' => 'Tage', 'different currency products' => 'Produktwährung verschieden', 'different rebill times subscriptions' => 'verschiedene Rechnungsstellungs-Zeiten für Abonnements', 'different the first period subscriptions' => 'verschieden vom erstmaligen Abonnement', 'different the second period subscriptions' => 'verschieden von Folgezeitraum des Abonnements', 'email' => 'E-Mail', 'email will contain this sentence' => 'Mail wird diesen Satz beinhalten', 'expiration' => 'Ablauf', 'expires' => 'läuft ab', 'filtered' => 'gefiltert', 'for affiliate commission payouts' => 'für Auszahlung Partner-Provision', 'for example: 1111-2222-3333-4444' => 'z.B.: 1111-2222-3333-4444', 'free' => 'kostenlos', 'generate' => 'Erzeugen', 'hrs' => 'Stunden', 'iDEAL betaling' => 'iDEAL betaling', 'if not specified, voucher will be sent to your email' => 'wenn nicht angegeben, wird Gutschein an Ihre Adresse geschickt', 'ip' => 'ip', 'just now' => 'Jetzt gleich', 'link' => 'Link', 'login' => 'Login', 'min' => 'Minuten', 'month' => 'Monat', 'months' => 'Monate', 'more than' => 'mehr als', 'no records' => 'keine Datensätze', 'number of affiliate program clicks' => 'Anzahl Partnerprogramm-Klicks', 'of products' => 'von Produkten', 'on %d-th day' => 'auf %d-ten Tag', 'only First Name' => 'nur Vorname', 'only Last Name' => 'nur Nachname', 'or' => 'oder', 'pay using credit card or PayPal' => 'per Kreditkarte oder PayPal zahlen', 'pay using wire transfer or by sending offline check' => 'Zahlung per Überweisung oder per offline Check', 'protected area' => 'Geschützter Bereich', 'return' => 'Zurückkehren', 'seconds' => 'Sekunden', 'start' => 'Beginn', 'upgrade' => 'Upgrade', 'use 4111-1111-1111-1111 for successful transaction' => 'Verwendung 4111-1111-1111-1111 für eine erfolgreiche Transaktion', 'year' => 'Jahr', 'years' => 'Jahre', 'you have %d reward points collected' => 'Sie haben %d Reward-Punkte gesammelt', ); PK\]>qqdefault/language/user/ru.phpnu[ 'навсегда', ' from ' => 'из', ' to ' => 'кому', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" может быть куплен только со следующими товарами/подписками: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" может быть куплен только если у вас есть завершенная подписка на эти продукты: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" не может быть куплен, так как у вас уже есть активная подписка на: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" не может быть куплен, так как у вас есть завершенная подписка на: %s', '%d-Tier Affiliates Commission ' => '%d-Уровень партнеркой комиссии ', '%s MySQL Hostname' => '%s MySQL название хоста', '%s MySQL Password' => '%s MySQL пароль', '%s MySQL Username' => '%s MySQL имя пользователя', '%s database and tables prefix' => '%s префикс базы данных и таблицы', ', for %d installments' => ', %d раз', ', then ' => ', затем ', '-- Please select --' => '-- Выбирите --', 'API Authentication Information' => 'информация о API аутентификации', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Принять прямой платеж провести платеж выполненый на стороне платежной системы (без регистрации в aMember)', 'Access' => 'Доступ', 'Access Denied' => 'Доступ закрыт', 'Access Log' => 'Лог доступа', 'Access Permissions' => 'Права доступа', 'Actions' => 'Действия', 'Active' => 'Активный', 'Active Resources' => 'Активные ресурсы', 'Active Subscriptions' => 'Активные подписки', 'Active Users' => 'Активные пользователи', 'Active subusers' => 'Активные подпользователи', 'Add' => 'Добавить', 'Add "Like" button' => 'Добавить кнопку "Нравиться"', 'Add Attachments' => 'Прикрепить Файл', 'Add Membership' => 'Добавить подписку', 'Add New Notification Rule' => 'Добавить новое правило уведомления', 'Add User' => 'Добавить клиента', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Добавить призовые очки соотнесенному партнеру после покупки продукта (дополнительно настраивается в aMember панель управления -> Установка -> Призовые очки)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Добавить призовые очки пользователю после покупки продукта (дополнительно настраивается в aMember панель управления -> Установка -> Призовые очки', 'Add to Basket' => 'Добавить в корзину', 'Add user to these groups' => 'Добавить клиента в эту группу', 'Add/Renew Subscription' => 'Добавить/Обновить подписку', 'Added' => 'Добавлен', 'Additional Fields' => 'Дополнительные поля', 'Address Info' => 'Адрес', 'Address Info (must match your credit card statement delivery address)' => 'Адрес (должен совпадать с адресом доставки счетов по кредитной карте)', 'Address Information' => 'Адрес', 'Admin' => 'Администратор', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Группы адмистратора aMember никогда не изменяет %s аккаунты состоящие в этой группе. Это защищает %s аккаунты от любой aMember активности ', 'Admin Username' => 'Имя пользователя администратора', 'Administrator' => 'Администратор', 'Admins' => 'Администраторы', 'Advanced' => 'Дополнительно', 'Advanced Search' => 'Расширенный поиск', 'Advertise our website to your friends and earn money' => 'Рекламируйте наш сайт среди своих друзей и зарабатывайте деньги', 'Affiliate' => 'Партнер', 'Affiliate Affiliate Link' => 'Партнерская ссылка партнера', 'Affiliate Agreement' => 'Партнерские соглашения', 'Affiliate Clicks' => 'Партнерские клики', 'Affiliate Clicks for' => 'Партнерские клики', 'Affiliate Id#' => 'Id партнера', 'Affiliate Info' => 'Партнерская информация', 'Affiliate Payout - Paypal E-Mail address' => 'Партнерские выплаты - E-Mail адрес Paypal', 'Affiliate Payout Type' => 'Способ выплат комиссионных', 'Affiliate Program' => 'Партнерская программа', 'Affiliate Sales' => 'Продажи партнера', 'Affiliate Signup Form' => 'Форма регистрации партнера', 'Affiliate Source' => 'Основание партнерства', 'Affiliate info' => 'Партнерская программа', 'Affiliate link with Custom Landing Page' => 'Партнерская ссылка с заданной целевой страницей', 'Affiliate stats' => 'Статистика партнерской программы', 'Affiliates' => 'Партнеры', 'All' => 'Все', 'All %s records on this page are selected' => 'Выбраны все %s записи на этой странице', 'All Affiliates' => 'Все партнеры', 'All Categories' => 'Все Категории', 'All Time' => 'Все время', 'All Users' => 'Все пользователи', 'All records' => 'Все записи', 'Already in Basket' => 'Уже в корзине', 'Always' => 'Всегда', 'Amazon S3 storage is not configured' => 'Amazon S3 хранилище не сконфигурировано', 'Amount' => 'Сумма', 'An Error has occurred' => 'Произошла ошибка', 'An account with the same email [%s] is already exists.' => 'Аккаунт с таким email [%s] уже используется', 'An account with the same email already exists.' => 'Аккаунт с таким адресом электронной почты уже создан', 'An error occurred while handling your payment.' => 'Произошла ошибка во время обработки платежа.', 'An internal error happened in the script, please contact webmaster for details' => 'В программе произошла внутренняя ошибка, пожалуйста обратитесь к вебмастеру за деталями', 'Any Product' => 'Любой продукт', 'Any product' => 'Любой продукт', 'Api Key' => 'Api ключ', 'Apply' => 'Применить', 'Apply Coupon (optional)' => 'Приминить купон (не обязательно)', 'Apply Filter' => 'Применить фильтр', 'Assigned by Administrator %s at %s' => 'Назначен администратором %s в %s', 'Assigned by COOKIE at %s' => 'Назначен на основании COOKIE в %s', 'Assigned by Coupon %s at %s' => 'Назначен на основании купона %s в %s', 'Assigned by IP %s at %s' => 'Назначен на основании IP %s в %s', 'Assigned by Invoice %s at %s' => 'Назначен на основании заказа %s в %s', 'Assigned to usergroup' => 'Состоит в пользовательской группе', 'Attach File' => 'Прикрепить файл', 'Attachments' => 'Вложения', 'Authentication' => 'Идентификация', 'Authentication problem, please contact website administrator' => 'Проблема авторизации, пожалуйста свяжитесь с администратором', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Автоматически добавлять пользователей в лист после того как он становиться доступным ', 'Available Bricks (drag to left to add)' => 'Доступные блоки (перенесите налево для добавления)', 'Available Credits' => 'Доступные кредиты', 'Awaiting Admin Response' => 'Ожидает ответа администратора', 'Awaiting User Response' => 'Ожидает ответа пользователя', 'Aweber Application' => 'Приложение Aweber', 'Back' => 'Назад', 'Back to shopping' => 'Вернутся к выбору товара', 'Bank Account Number Up to 20 digits' => 'Номер банковского счета до 20 цифр', 'Bank Account Type please select one' => 'Тип банковского счета пожалуйста, выберите один', 'Bank Code' => 'Код банка', 'Bank Identification' => 'Идентификация банка', 'Bank Name' => 'Название', 'Bank Name name of the bank which issued the credit card' => 'Название банка название банка, выдавшего кредитную карту', 'Bank Phone customer service phone number listed on back of your credit card' => 'Телефон банка номер телефона обслуживания клиентов можно найти на обратной стороне вашей кредитной карты', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Забаненые группы aMember никогда не изменяет %s аккаунты состоящие в следующих группах. Это защищает %s аккаунты от любой aMember активности', 'Banners and Links' => 'Получить баннеры и ссылки', 'Banners and Text Links' => 'Управление баннерами и ссылками', 'Begin Date' => 'Дата начала', 'Both Affiliate and member' => 'И партнер, и пользователь', 'CC Demo' => 'Демонтрация ипользования кредитной карты', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF защита - форма должна быть отправлена в течении %d минут, повторите', 'Campaign' => 'Кампания', 'Can view/edit customer Credit Card information and rebills' => 'Может смотреть/редактировать информацию о кредитных картах', 'Cancel' => 'Завершить', 'Cancel Subscription' => 'Отказаться от подписки', 'Cancelled' => 'Отменен', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Нельзя использовать бесплатную подписку для продукта, стоимость которого больше 0.0', 'Cannot validate VAT Id, please try again' => 'Не могу проверить VAT Id, пожалуйста попытайтесь снова', 'Card Expire Select card expiration date - month and year' => 'Карты истекает выбирите дату срока действия карты - месяц и год', 'Card Issue # is required for Maestro/Solo/Switch credit cards only' => 'Карта выпуск # требуется только для кредитных карт Maestro/Solo/Switch', 'Card Start Date is required for Maestro/Solo/Switch credit cards only' => 'Дата начала карты требуется только для кредитных карт Maestro/Solo/Switch', 'Cardholder Name cardholder first and last name, exactly as on the card' => 'Имя владельца карточки имя и фамилия, точно так, как на карте', 'Categories' => 'Категории', 'Category' => 'Категория', 'Category [%s] not found' => 'Категория [%s] не найдена', 'Category of question' => 'Категория вопроса', 'Change' => 'Изминить', 'Change Category' => 'Сменить Категорию', 'Change Owner' => 'Сменить Владельца', 'Change Password' => 'Смена пароля', 'Change Password/Edit Profile' => 'Изменить пароль/Редактировать личные данные', 'Change Subscription' => 'Изменить подписки', 'Change Username' => 'Изменить имя пользователя', 'Change Your Password' => 'Изменить пароль', 'Change payout info' => 'Изменить платёжную информацию', 'Changes in User Profile' => 'Изменения в профиле', 'Checkout' => 'Купить', 'Checkout error: ' => 'Ошибка обработки заказа:', 'Choose New Password must be %d or more characters' => 'Выбирите новый пароль должен содержать %d или более символов', 'Choose a Password must be %d or more characters' => 'Выберите пароль должен быть не менее %d символов', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Выберите имя пользователя должно быть не менее %d символов длиной и может содержать буквы, цифры и подчеркивание', 'City' => 'Город', 'City ' => 'Город', 'Click "Continue" to pay this order using stored credit card %s' => 'Нажмите "Continue" для оплаты этого заказа с помощью хранимой кредитной карты %s', 'Click button to continue' => 'Нажать на кнопку для продолжение', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Нажмите здесь, если не хотите ждать (или если Ваш броузер не перенаправил Вас автоматически).', 'Click to Assign' => 'назначить', 'Click to Edit' => 'Нажмите для редактирования', 'Clicks' => 'Переходы', 'Clicks/Sales Statistics' => 'Статистика переходов/продаж по партнерской программе', 'Close' => 'Закрыть', 'Close This Ticket After Response' => 'Закрыть После Ответа', 'Close Ticket' => 'Закрыть Запрос', 'Close Ticket(s)' => 'Закрыть Обращение(я)', 'Closed' => 'Закрыто', 'Code' => 'Код', 'Comment' => 'Комментарий', 'Comment for admin reference' => 'Комментарий для справки администратора', 'Commission' => 'Комиссия', 'Commission Rules' => 'Правила начисления комиссии', 'Commissions' => 'Комиссии', 'Company Name the company name associated with the billing address for the transaction' => 'Название компании название компании, связанное с адресом для выставления счетов для транзакции', 'Complete Payment' => 'Завершить платеж', 'Condition' => 'Условие', 'Conditions/Commissions' => 'Условия/Комиссии', 'Configuration' => 'Настройки', 'Configured Tax Values' => 'Настроенные значение налога', 'Confirm E-Mail Address second field will be displayed to enter email address twice' => 'Подтверждать E-Mail адрес еще одно поле будет показано для того чтобы ввести адрес дважды', 'Confirm New Password' => 'Подтвердить новый пароль', 'Confirm Password' => 'Подтвердите пароль', 'Confirm Payment' => 'Подтвердить платеж', 'Confirm Your E-Mail Address' => 'Утвердить ваш E-Mail', 'Confirm Your Password' => 'Подтвердите ваш пароль', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Ссылка утверждения была отправлена на ваш e-mail. Пожалуйста проверьте ваш почтовый ящик. Если вы не получили e-mail в течение пяти минут, пожалуйста проверьте папку со спамом - наши сообщения могут быть рассмотрены по ошибке как спам.', 'Content' => 'Содержание', 'Content Categories' => 'Категории', 'Content Categories these categories will be shown in user\'s menu if user has access to resources in this category. You can uses these categories to organize your content by pages' => 'Категории ссылки на эти категории будут добавлены в меню в разделе клиента в том случае если клиент имеет доступ к содержимуму категории. Вы можете использовать их чтобы организовать ваши материалы', 'Continue' => 'Продолжить', 'Continue Shopping' => 'Продолжить выбор', 'Conversation' => 'Переписка', 'Copy of' => 'Копия', 'Count' => 'Количество', 'Count of Messages' => 'Количество сообщений', 'Count of product purchase' => 'Количество покупок', 'Count of signups' => 'Количество регистраций', 'Count of user signups' => 'Количество регистраций новых пользователей', 'Country' => 'Страна', 'Country Title' => 'Название страны', 'Coupon' => 'Купон', 'Coupon Code' => 'Код купона', 'Coupon Discount' => 'Скидка', 'Coupon can be used only if you have active subscription for these products: %s' => 'Купон может быть использован только если у вас есть активная подписка на один из следующих продктов: %s', 'Coupon can be used only if you have expired subscription(s) for these products: %s' => 'Купон может быть использован только если у вас есть истекшая подписка на один из следующих продуктов: %s', 'Coupon cannot be used because you have active subscription(s) to: %s' => 'Купон не может быть использован так как у вас есть активная подписка на один из следующих продуктов: %s', 'Coupon cannot be used because you have expired subscription(s) to: %s' => 'Купон не может быть использован так как у вас есть истекшая подписка на один из следующих продуктов: %s', 'Coupon code disabled' => 'Купон не действует', 'Coupon code expired' => 'Купон уже не действует', 'Coupon is not yet active' => 'Купон пока не активен', 'Coupon usage limit exceeded' => 'Купон уже использован', 'Coupons Batch' => 'Серия купонов', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Добавлять пользователя aMember по требованию незаметно создавая пользователя в aMember если пользователь пытается войти в aMember c тем же именем пользователя и паролем как %s', 'Created' => 'Создан', 'Credit Card Code' => 'Код кредитной карты', 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards)' => 'Код кредитной карты «Код карты» это трех - или четырехзначный код, который напечатан на задней части кредитных карт (или на передний части для карт American Express)', 'Credit Card Info' => 'Информация о Кредитной Карте', 'Credit Card Number' => 'Номер кредитной карты', 'Credit Card Number for example: 1111-2222-3333-4444' => 'Номер кредитной карты на пример: 1111-2222-3333-4444', 'Credit Card Rebills' => 'Повторно выставленные счета', 'Credit Card Type please select one' => 'Тип кредитной карты выберите один из вариантов', 'Credit Cards' => 'Кредитные карты', 'Credits' => 'Кредиты', 'Currency' => 'Валюта', 'Currency Exchange Rates' => 'Курсы валют', 'Current password entered incorrectly, please try again' => 'Пароль введен неправильно, попробуйте снова', 'Custom Commission' => 'Специальная комиссия', 'Customer account has been automatically locked.' => 'Аккаунт покупателя был автоматически закрыт.', 'Customize' => 'Настроить', 'DONE' => 'ГОТОВО', 'Dashboard' => 'Информация', 'Data Integrity Code' => 'Код данных интегрирования', 'Date' => 'Дата', 'Date and time of payment: %s' => 'Дата и время оплаты: %s', 'Date must be in format %s' => 'Дата должна быть в формате %s', 'Date/Time' => 'Дата/Время', 'Date: ' => 'Дата:', 'Day' => 'День', 'Days' => 'Дни', 'Deactivate Student' => 'Деактивировать студента', 'Deactivate User' => 'Деактивировать пользователя', 'Debit Card Number' => 'Номер дебитовой карты ', 'Default' => 'По умолчанию', 'Default Avatar' => 'Аватар по умолчанию', 'Default Coupon Batch placeholder %coupon% will be replaced with coupon code from this batch' => 'Серия купонов по умолчанию %coupon% будет заменен на код купона из этй серии', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Уровень по умолчанию уровень по умолчанию - пользователь устанавливается на этот уровнь доступа если нет активных подписок', 'Delete' => 'Удалить', 'Delete %s' => 'Удалить %s', 'Delivery Time' => 'Время доставки', 'Description' => 'Описание', 'Did\'t Use Any Coupon' => 'Не использован купон', 'Did\'t Use Coupon from Batch: %s' => 'Не использован купон из серии: %s', 'Did\'t Use Coupon with Code: %s' => 'Не использован купон с кодом: %s', 'Digits only please' => 'Только цифры', 'Disable online VAT Id Validation' => 'Отключить валидацию Id VAT в режиме онлайн', 'Disabled' => 'Выключено', 'Discard' => 'Отвергнуть', 'Discount' => 'Скидка', 'Display All Products' => 'Показывать все продукты', 'Display It Anyway' => 'Все равно показать его', 'Display Type' => 'Тип отображения', 'Display in 2 rows' => 'Показать в два ряда', 'Disregard' => 'Проигнорировать', 'Do Import' => 'Импортировать', 'Do not add to Login Form' => 'Не добавлять в форму входа', 'Do not add to Signup Form' => 'Не добавлять в регистрационную форму', 'Do not create coupon for affiliate' => 'Не создавать купон для партнера', 'Do you really want to %s %s %s records' => 'Вы действительно хотите %s %s %s записи', 'Do you really want to %s?' => 'Действительно хотите %s?', 'Do you really want to cancel subscription?' => 'Вы действительно хотите завершить подписку?', 'Do you really want to delete record?' => 'Вы действительно хотите удалить запись?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Вы действительно хотите отписаться от %s периодических сообщений?', 'Do you really want to void commission?' => 'Вы действительно хотите отозвать коммисию?', 'Does not Ask Current Password user will not need to enter his current password to change it' => 'Не спрашивать текущий пароль клиенту не надо будет вводить свой текущий пароль чтобы поменять его', 'Does not Confirm Password second field will not be displayed to enter password twice' => 'Не подтверждать пароль не показывать второго поля для того чтобы вести пароль дважды', 'Does not allow to Copy&Paste to confirmation field' => 'Не разрешать копировать текст в поле подтверждения', 'Done' => 'Сделано', 'Donee name' => 'Имя дарополучателя', 'Download' => 'Скачать', 'Download limit exceeded for this file' => 'Лимит закачек превышен для данного файла', 'Downloaded on your own server' => 'Скачено на вашем собственном сервере', 'Drag&Drop rows to change display order. You may want to temporary change setting \'%sRecords per Page (for grids)%s\' to some big value so all records were on one page and you can arrange all items.' => 'Перетаскивыйте (Drag&Drop) строчки для того чтобы поменять порядок. Вы можете временно поменять колличество %sЗаписей на странице (для таблиц)%s на кокое либо большее значение для того чтобы все записи были на одной странице и вы могли упорядочить их', 'E-Mail Address' => 'Адрес электронной почты', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'E-Mail и E-Mail утверждения различаются. Пожалуйста заново введите оба', 'E-Mail Format' => 'Формат E-Mail ', 'E-Mail Messages' => 'E-Mail Сообщения', 'E-Mail Verification' => 'Проверка адреса электронной почты', 'EU VAT' => 'EU VAT', 'EU VAT ID: ' => 'EU VAT ID:', 'EU VAT Id (optional)' => 'EU VAT Id (не обязательно)', 'Edit' => 'Редактировать', 'Edit %s' => 'Редактировать %s', 'Edit Brick Labels' => 'Править метку блока', 'Edit Categories' => 'Изменить категории', 'Edit E-Mail Template' => 'Редактировать шаблоны писем', 'Edit Your Cart' => 'Редактировать вашу корзину', 'Email' => 'Email', 'Email Subject' => 'Тема письма', 'Email [%s] is not valid' => 'Email [%s] не утвержден', 'Email admin regarding account sharing' => 'Отправить Email администратору относительно совместного использования', 'Email user regarding account sharing' => 'Отправить Email пользователю относительно совместного использования', 'Empty response from Sagepay server' => 'Пустой ответ от сервера Sagepay', 'Enable Debug Mode' => 'Включить режим отладки', 'Enabled Modules' => 'Модули', 'End' => 'Конец', 'End Date' => 'Дата окончания', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => 'Наслаждайтесь вашей подпиской. Пожалуйста нажмите %sздесь%s для перехода в личный кабинет.', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Спасибо за подписку. Пожалуйста, перейдите по ссылке для входа %sВход%s', 'Enter coupon code' => 'Введите код купона', 'Enter gift voucher code' => 'Вставить код подарочного ваучера', 'Error' => 'Ошибка', 'Error 404 - Not Found' => 'Ошибка 404 - не найдено', 'Error : upload folder [%s] does not exists' => 'Ошибка: папка закачек [%s] не существует', 'Error Message' => 'Сообщение об ошибке', 'Error from Storage Engine' => 'Ошибка механизма хранения ', 'Error happened during payment process. ' => 'В процессе оплаты произошла ошибка.', 'Error happened during transaction handling. Please contact website administrator' => 'Произошла ошибка при прохождение тразакции. Пожалуйста свяжитесь с администрацией сайта', 'European (A4)' => 'Европейский (A4)', 'Exact' => 'Точный', 'Expire Date' => 'Дата истечения', 'Expired' => 'Подписка истекла', 'Expired Users' => 'Неактивные пользователи', 'Expires' => 'Истекает', 'Export' => 'Экспорт', 'Export Format' => 'Формат экпорта', 'FaceBook App ID' => 'FaceBook App ID ', 'FaceBook Application' => 'FaceBook приложение', 'Facebook App Secret' => 'Facebook App секретная фраза', 'Features' => 'Компоненты', 'Field' => 'Поле', 'Field Type' => 'Тип поля', 'Field Updated' => 'Значение сохранено', 'Fields To Display' => 'Отображаемые поля', 'Fields To Export' => 'Поля на экспорт', 'Fieldset' => 'Шапка', 'Fieldset title' => 'Название шапки', 'File' => 'Файл', 'File Downloads' => 'Скачивания файла', 'File Storage' => 'Хранилище файлов', 'File should contain CSV list of user records for import in the following format:
      %s' => 'Файл должен содержать CSV лист пользовательких записей для импорта в следующий формат:
      %s', 'Filename' => 'Имя файла', 'Files' => 'Файлы', 'Files keep empty to report all files' => 'Файлы оставье пустым чтобы показать отчет по всем файлам', 'Files List' => 'Список файлов', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'Файлы размещены на Amazon S3 хранилище. (Внимание: ваши бакеты не должны содержать символов в верхнем регистре)', 'Files uploaded via aMember web interface' => 'Файлы закаченные через веб интерфейс aMember', 'Filter' => 'Фильтр', 'First & Last Name' => 'Имя и фамилия', 'First Name' => 'Имя', 'First Payment' => 'Первый платеж', 'Folder %s (%s)' => 'Папка %s (%s)', 'Folders' => 'Папки', 'Free' => 'Бесплатно', 'Free Access' => 'Свободный доступ', 'Free Access without log-in' => 'Свободный доступ без входа в систему', 'Free Signup' => 'Бесплатная регистрация', 'From' => 'От', 'GST (Inclusive Tax)' => 'GST (включительно налог)', 'Get Link' => 'Получить ссылку', 'Get Password' => 'Получить пароль', 'Gift Voucher' => 'Подарить ваучер', 'Gift Vouchers' => 'подарочные сертификаты', 'Global Commission' => 'Общая комиссия', 'Global Tax' => 'Общий налог', 'Groups' => 'Группы', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'Приоритеты групп вы можете премещять группы тем самым сортируя их если для пользователя доступны несколько групп aMember выберет группу с высшим приоритетом', 'HTML Code that will be displayed' => 'HTML код который будет показан', 'HTML Message' => 'HTML сообщение', 'HTML text' => 'HTML текст', 'Having Active Subscription To:' => 'Есть активная подписка на:', 'Having Expired Subscription To:' => 'Есть истекшая подписка на:', 'Helpdesk' => 'Служба поддержки', 'Hide do not display this item link in members area' => 'Скрыть не показывать этот элемент в области пользователя', 'Hosted at Activecampaing\'s server' => 'Размещено на сервере Activecampaing\'s ', 'Housenumber' => 'Номер дома', 'IP Address' => 'Адрес IP', 'If you already have an account on our website, please %slog in%s to continue' => 'Если вы зарегистрированный пользователь, пожалуйста %sвойдите%s', 'If you are a registered member, please %slogin%s' => 'Если вы уже зарегистрированы, вы можете %sвойти%s', 'If you are not registered yet, please %ssignup%s' => 'Если нет, добро пожаловать на страницу %sрегистрации%s', 'Income' => 'Доход', 'Income Report - payments minus refunds' => 'Отчет о доходе - платежи за вычетом возвратов', 'Incorrect Parent Affiliate ID' => 'Некорректный родительский ID партнера', 'Insert comment into email' => 'Вставить комментарий в email', 'Integer Value' => 'Целое число', 'Integer value required' => 'Целое число обязательно', 'Integration' => 'Интеграция', 'Integrations' => 'Интеграции', 'Internal Error' => 'Внутренняя ошибка', 'Invalid Account Number' => 'Неправильный номер аккаунта', 'Invalid Bank Account Number' => 'Неверный номер банковского счета', 'Invalid Credit Card Number' => 'Неверный номер кредитной карты', 'Invalid Debit Card Number' => 'Неверный номер дебитовой карты', 'Invalid Expiration Date - Month' => 'Неверная дата окончания срока действия карты - месяц', 'Invalid Expiration Date - Year' => 'Неверная дата окончания срока действия карты - год', 'Invalid Issue Number' => 'Неправильный номер выпуска', 'Invalid Routing Number' => 'Неправильный номер маршрутизации', 'Invalid VAT Id, please try again' => 'Неверный VAT Id, пожалуйста попытайтесь снова', 'Invoice' => 'Счет', 'Invoice Number: ' => 'Номер счета:', 'Invoice Text' => 'Счет', 'Invoice not found' => 'Счет не найден', 'Invoices/Access' => 'Счета/Доступ', 'Is Affiliate? customer / affiliate status' => 'Партнер? клиент/партнер статус', 'Is Gift Voucher?' => 'Подарочный ваучер?', 'Is Locked' => 'Заблокирован?', 'Is Paid?' => 'Выплачено?', 'Is Send At Later Date?' => 'Если отправлено по поздней дате?', 'Is Disabled?' => 'Отключен?', 'It is last message that will be shown to user before account removal, you can place some special offer here.' => 'это последнее сообщение, которое увидит клиент перед удалением его учетной записи, вы можете поместить каое либо специальное предложение здесь чтобы удержать клиента.', 'Item' => 'Продукт', 'Keywords' => 'Кампании', 'Label' => 'Метка', 'Language' => 'Язык', 'Last 14 Days' => 'Последние 14 дней', 'Last 30 Days' => 'Последние 30 дней', 'Last 7 Days' => 'Последние семь дней', 'Last Business Week (Mon-Fri)' => 'Последняя бизнес неделя (Понедельник - Пятница)', 'Last Messages in Helpdesk' => 'Последние сообщения в Helpdesk', 'Last Month' => 'Последний месяц', 'Last Name' => 'Фамилия', 'Last Signin' => 'Последний вход', 'Last Week (Mon-Sun)' => 'Последняя неделя (Понедельник - Суббота)', 'Last Week (Sun-Sat)' => 'Последняя неделя (Воскресенье - Суббота)', 'Leads' => 'Регистрации', 'License Key' => 'Лицензионный ключ', 'Lifetime' => 'Пожизненно', 'Like Url' => 'как Url', 'Limit' => 'Лимит', 'Link' => 'Ссылка', 'Links' => 'Ссылки', 'Live Edit %s' => 'Редактирование в реальном времени %s', 'Loading' => 'Загрузка', 'Log In' => 'Вход', 'Log all API Requests' => 'Вести лог всех API запросов', 'Login' => 'Войти', 'Login as User' => 'Войти как пользователь', 'Logout' => 'Выход', 'Lost Password Sending Error' => 'Ошибка отправки пароля', 'Lost Password Sent' => 'Пароль отправлен', 'Lost password?' => 'Потеряли пароль', 'Mail Queue' => 'Очередь писем', 'Make Payment' => 'Сделать платеж', 'Make a Donation' => 'Сделать пожертвование', 'Make donation recurring' => 'Сделать пожертвование повторяющимся', 'Manage Newsletters' => 'Управление информационной рассылкой', 'Marketing Materials' => 'Рекламные материалы', 'Members Directory' => 'Список пользователей', 'Members Directory [%s] does not exists' => 'Членкий раздел [%s] не существует', 'Membership Type' => 'Тип подписки', 'Merchant Key' => 'Ключ продавца', 'Merchant Secret' => 'Секретная фраза продавца', 'Message' => 'Сообщение', 'Message It is last message that will be shown to user before account removal, you can place some special offer here.' => 'Сообщение это последнее сообщение, которое увидит клиент перед удалением его учетной записи, вы можете поместить каое либо специальное предложение здесь чтобы удержать клиента.', 'Message can not be empty' => 'Сообщение должно быть введено', 'Month' => 'Месяц', 'Months' => 'Месяцы', 'Multiplier' => 'Множитель', 'My Country' => 'Моя страница', 'My Tickets' => 'Мои обращения', 'NEVER' => 'НИКОГДА', 'Name' => 'Имя', 'Never' => 'Никогда', 'New' => 'Новый', 'New %s' => 'Новый %s', 'New Password' => 'Новый пароль', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Новый пароль вы можете выбрать новый пароль или оставьте это поле пустым должен быть не менее %d символов', 'Newsletter Subscriptions' => 'Информационные подписки', 'Newsletters' => 'Рассылки', 'Next' => 'Далее', 'Next Rebill' => 'Следующий платеж', 'No' => 'Нет', 'No commissions on this date' => 'Нет комиссий на указанную дату', 'No coupons found with such coupon code' => 'Не найдены купоны с такими кодами', 'No files uploaded' => 'Файлы не были загружены', 'No gift vouchers found with such code' => 'Не найдено ни одного подарочного ваучера с таким кодом', 'No items in this section' => 'Нет позиций в этой секции', 'No items selected for purchase' => 'Ничего не выбрано для покупки', 'No records found' => 'Записи не найдены', 'No result found' => 'Ни чего не найдено', 'No, cancel' => 'Нет, отменить', 'No, keep me subscribed' => 'Нет, сохранить подписку', 'No, please keep me subscribed' => 'Нет, пожалуйста, оставьте мою подписку', 'Not Affiliate' => 'Не партнер', 'Not Approved Affiliates' => 'Не утвержденные партнеры', 'Not Selected' => 'Не выбрано', 'Not assigned to usergroup' => 'Не состоит в пользовательской группе', 'Not registered yet?' => 'Еще не зарегистрированы?', 'Notes' => 'Примечания', 'Number of Messages to display' => 'Количество отображаемых сообщений', 'Number of cancel on each billing cycle' => 'Количество отмен на каждом платежном цикле', 'Numeric Value' => 'Число', 'Numeric value required' => 'Числовое значение обязательно', 'Offline Payment' => 'Автономный платеж', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'После завершения конфигурирования страницы, не забудьте добавить запись на странице %saMember панель управления -> Защищенный контент -> Интеграции %s ', 'Online' => 'Онлайн', 'Only Affiliate %s(rarely used)%s' => 'Только партнер %s(редко используется)%s', 'Only Affiliate, not a member' => 'Только партнер, не клиент', 'Only Billing Plans selected below' => 'Только платежные планы выбранные ниже', 'Only Products selected below' => 'Только продукты выбранные ниже', 'Order reference: %s' => 'Ссылка на заказ: %s', 'Other' => 'Другие', 'Our system will try to charge your card again on %s' => 'Наша система будет пытаться снять деньги с Вашей кредитной карты %s', 'Owner' => 'Владелец', 'Page Title' => 'Заголовок страницы', 'Pages' => 'Страницы', 'Paper Format' => 'Формат листа', 'Password' => 'Пароль', 'Password and Password Confirmation are different. Please reenter both' => 'Пароль и подтверждение различаются. Введите заново', 'Password must contain at least %d letters or digits' => 'Пароль должен содержать минимум %d букв или цифр', 'Password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars' => 'Пароль должен иметь по крайней мере 2 прописные буквы, 2 числа и 2 специальных символа', 'Passwords do not match' => 'Пароли не совпадают', 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this product to do it' => 'Путь будет использоваться для создания удобного URL-адреса, в случае, если вы оставить его пустым aMember будет использовать идентификатор этого продукта для него', 'Path should be unique across all products' => 'Путь должен быть уникальным для всех продуктов', 'Path to %s' => 'Путь к %s', 'Path to %s Folder' => 'Путь к %s папке', 'Pay' => 'Оплатить', 'Payanyway plugin does not support recurring billing!' => 'Payanyway плагин не поддерживает повторяющиеся платежи!', 'Payment' => 'Платежи', 'Payment Confirmation' => 'Подтверждение оплаты', 'Payment Error' => 'Ошибка платежа', 'Payment Failed' => 'Платёж не выполнен', 'Payment History' => 'Истоия платежей', 'Payment Info' => 'Информация о платеже', 'Payment Link' => 'Платежная ссылка', 'Payment System' => 'Платёжная система', 'Payment System Description' => 'Описание платежной системы', 'Payment System Title' => 'Название платежной системы', 'Payment error: ' => 'Ошибка платежа:', 'Payment failed' => 'Платеж не обработан', 'Payment info' => 'Информация о платеже', 'Payment is already processed, please go to %sMembership page%s' => 'Платеж уже был обработан, пожалуйста, перейдите на %sПользовательскую страницу%s', 'Payments' => 'Платежи', 'Payments Amount' => 'Сумма Платежей', 'Payments History' => 'История платежей', 'Payments by New vs Existing members' => 'Платежи новых и уже существующих пользователей', 'Payments by payment system breakdown' => 'Платежи с разбивкой по платежным системам', 'Payments by products breakdown' => 'Платежи с разбивкой по продуктам', 'Payments from existing customers' => 'Платежи от уже существующих пользователей', 'Payments from new customers' => 'Платежи от новых пользователей', 'Payments total' => 'Сумма платежей', 'Payments vs Refunds' => 'Платежи/Возвраты', 'Payout Date' => 'Дата выплаты', 'Payout Method' => 'Способ выплат', 'Payout Method Title' => 'Название метода вывода', 'Payouts' => 'Выплаты', 'Paysystem (optional)' => 'Платежная система (не обязательно)', 'Pending' => 'Рассматривается', 'Pending Invoices' => 'Рассматриваемые заказы', 'Pending subusers' => 'Подпользователи находящиеся на рассмотрение', 'Period' => 'Период', 'Period must be in interval 1-24 months' => 'Период должен быть в интервале 1-24 месяцев', 'Period must be in interval 1-5 years' => 'Период должен быть в интервале 1-5 лет', 'Period must be in interval 1-90 days' => 'Период должен быть в интервале 1-90 дней', 'Permalink' => 'Ссылка', 'Personal Content' => 'Личный контент', 'Phone' => 'Телефон', 'Phone Number' => 'Номер телефона', 'Plain-Text Message' => 'Простое текстовое сообщение', 'Plain-Text Password' => 'Пароль в открытом виде', 'Please %sdefine payout method%s to get commission in our affiliate program.' => '%sВыберите способ вывода%s ваших комиссионных в нашей партнерской программе', 'Please %senable at least one payout method%s since you use affiliate module' => 'Вам необходимо %sвключить по крайней мере один способ выплат%s для вашей партнерской программы', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Пожалуйста %sвойдите%s в ваш аккаунт. %sЕсли вы не завершили платеж, у вас будет возможность завершить его после входа', 'Please Enter URL of Your Landing Page' => 'Пожалуйста, введите URL-адрес целевой страницы', 'Please Select' => 'Пожалуйста выберите', 'Please agree to Affiliate Agreement' => 'Пожалуйста согласитесь с партнерской программой', 'Please agree to User Agreement' => 'Пожалуйста подтвердите, что вы согласны с правилами', 'Please choose' => 'Пожалуйста выберите', 'Please choose a Credit Card Type' => 'Пожалуйста, выберите тип кредитной карты', 'Please choose a membership type' => 'Пожалуйста выберите тип подписки', 'Please choose a payment system' => 'Пожалуйста выберите платежную систему', 'Please choose state' => 'Пожалуйста, введите название штата (области)', 'Please enter %s' => 'Пожалуйста введите %s', 'Please enter Account Number' => 'Пожалуйста введите номер аккаунта', 'Please enter City' => 'Введите город', 'Please enter Country' => 'Введите страну', 'Please enter Credit Card Code' => 'Пожалуйста, введите код кредитной карты', 'Please enter Credit Card Number' => 'Пожалуйста, введите номер кредитной карты', 'Please enter Debit Card Number' => 'Пожалуйста введите номер дебитовой карты', 'Please enter Password' => 'Пожалуйста введите пароль', 'Please enter Routing Number' => 'Пожалуйста введите номер маршрутизации', 'Please enter State' => 'Выберите штат', 'Please enter Street Address' => 'Введите адрес', 'Please enter ZIP code' => 'Введите почтовый индекс', 'Please enter a valid e-mail address' => 'Пожалуйста, введите корректный E-Mail адрес', 'Please enter correct amount' => 'Пожалуйста введите корректную сумму ', 'Please enter coupon code' => 'Пожалуйста введите номер купона', 'Please enter credit card holder first and last name' => 'Введите имя и фамалию владельца кредитной карты', 'Please enter credit card holder first name' => 'Пожалуйста, введите имя владельца кредитной карты', 'Please enter credit card holder last name' => 'Пожалуйста, введите фамилию владельца кредитной карты', 'Please enter credit card holder name' => 'Пожалуйста, введите имя владельца кредитной карты', 'Please enter debit card holder first name' => 'Пожалуйста введите имя держателя дебитовой карты', 'Please enter debit card holder last name' => 'Пожалуйста введите фамилию держателя дебитовой карты', 'Please enter debit card holder name' => 'Пожалуйста введите имя держателя дебитовой карты ', 'Please enter first name' => 'Пожалуйста введите фамилию', 'Please enter gift voucher code' => 'Пожалуйста введите код подарочного ваучера', 'Please enter housenumber' => 'Пожалуйста, введите номер дома', 'Please enter phone number' => 'Пожалуйста, введите номер телефона', 'Please enter valid Email' => 'Пожалуйста введите правильный адрес электронной почты', 'Please enter valid Username. It must contain at least %d characters' => 'Введите корректное имя пользователя - оно должно содержать не менее %d символов', 'Please enter your First Name' => 'Введите имя', 'Please enter your Last Name' => 'Введите фамилию', 'Please enter your current password for validation' => 'Пожалуйста введите ваш пароль для проверки', 'Please enter your last name' => 'Пожалуйста введите имя', 'Please enter your name' => 'Пожалуйста введите ваше имя', 'Please login' => 'Пожалуйста войдите', 'Please note: it is impossible to restore your current account after deleting but you still can signup again as new user.' => 'Обратите внимание: востановить вашу учетную запись будет невозможно но вы сможете зарегистрироваться как новый пользователь.', 'Please select' => 'Пожалуйста выберете', 'Please select an item...' => 'Пожалуйста выберите элемент...', 'Please select payment system for payment' => 'Пожалуйста, выберите систему оплаты для платежа', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Пожалуйста, используйте форму %sДобавить/Обновить подписку%s чтобы заказать или обновить подписку.', 'Please wait %d seconds before next login attempt' => 'Пожалуйста подождите %d секунд перед следующей попыткой входа', 'Plugin' => 'Плагин', 'Plugin List Id' => 'List Id плагина', 'PostAffiliatePro Parent Affiliate ID' => 'PostAffiliatePro родительский ID партнера', 'PostAffiliatePro Referral ID' => 'PostAffiliatePro ID реферала', 'Prev' => 'Предыдущий', 'Preview' => 'Предпросмотр', 'Price' => 'Цена', 'Priority' => 'Приоритет', 'Proceed to Checkout' => 'Перейти к оформлению', 'Processing your Transaction' => 'Прохождение вашей транзакции', 'Processing your product upgrade' => 'Выполнение улучшения вашего продукта', 'Product' => 'Продукт', 'Product %s is incompatible with product %s. Reason: %s' => 'Продукт %s не совместим с продуктом %s. Причина: %s', 'Product Categories' => 'Категории продуктов', 'Product Description displayed on the shopping cart page' => 'Описание продукта отображается на страницах эл. магазина', 'Product Gategories' => 'Категории продуктов', 'Product Title' => 'Название продукта', 'Product categories keep empty to report all categories' => 'Категории продуктов оставьте пустым для того чтобы показать отчет по всем категориям', 'Product upgrade finished successfully' => 'Обновление продукта успешно оконченно', 'Product(s)' => 'Продукт(ы)', 'Product(s) Title' => 'Название продукта(ов)', 'Product(s) to display' => 'Показывать продукт(ы)', 'Products' => 'Продукты', 'Products keep empty to report all products' => 'Продукты оставьте пустым для отчета по всем продуктам', 'Products from selected Categories' => 'Продукты из выбранной категории', 'Products not found. Click %shere%s to continue shopping.' => 'Продукт не найден. Перейдите %sпо ссылки%s чтобы ознакомится с ассортиментом', 'Profile' => 'Личные данные', 'Profile update transaction failed' => 'Неудачная транзакция обновления профиля', 'Protected Content [%s-%d]' => 'Защищенное содержимое [%s-%d]', 'Purchased Credits' => 'Купленные кредиты', 'Qty' => 'Количество', 'Quantity' => 'Количество', 'Quick Filter' => 'Быстрый поиск', 'Quick Order' => 'Оформить покупку', 'Quickpay parameters' => 'параметры Quickpay', 'Random Questions' => 'Случайны вопрос', 'Re-Open Ticket' => 'Открыть Запрос', 'Read-only' => 'Только для чтения', 'Real Path' => 'Реальный путь', 'Reason' => 'Причина', 'Record' => 'Запись', 'Record Type' => 'Тип записи', 'Record [%s] not found' => 'Запись [%s] не существует', 'Records Per Page' => 'Записей на странице', 'Records that match all these conditions' => 'Записи которые отвечают всем условиям', 'Recurring' => 'Повторные платежи', 'Redirect to NetDebit booking form.' => 'Партнеркие клики', 'Reference number is:' => 'Номер запроса:', 'Referer' => 'Ссылка', 'Referred Affiliate' => 'Партнер', 'Refresh' => 'Обновить', 'Refresh 3-rd party lists' => 'Обновить список рассылок (плагины)', 'Refund' => 'Возврат', 'Refund Amount' => 'Вернуть сумму', 'Refunded' => 'Возвращено', 'Regional Tax' => 'Местный налог', 'Register' => 'Регистрация', 'Remote API Permissions' => 'Права доступа к API', 'Remove' => 'Удалить', 'Remove It From Signup Form' => 'Убрать его с формы регистрации', 'Remove My Account' => 'Удалить учетную запись', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Удалить пользователей когда учетная запись пользователя удалена из aMember должна ли связанная запись удаляться из %s', 'Remove user' => 'Удалить пользователя', 'Reply' => 'Ответить', 'Report' => 'Отчет', 'Required' => 'Обязательно', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Повторить в случае неудачи если повторная выплата была неудачной, aMember может выполнить попытку через несколько дней, и продлить пользователькую подписку на этот период ввести количество дней для повторной попытки', 'Return' => 'Вернуться', 'Return and try again' => 'Вернитесь и попробуйте ещё раз', 'Review/Pay Commissions' => 'Комиссии по партнерской программе', 'Reward Points' => 'Призовые очки', 'Reward Points Configuration' => 'Конфигурация призовых баллов', 'Run Report' => 'Запустить отчет', 'Running %s' => 'Обрабатываем %s', 'Sales' => 'Продажи', 'Save' => 'Сохранить', 'Save Profile' => 'Сохранить Данные', 'Search' => 'Поиск', 'Search Products' => 'Искать продукты', 'Search Results' => 'Результаты поиска', 'Second and Subsequent Payments' => 'Второй и последующие платежи', 'Security code is invalid' => 'Секретный код введен неправильно', 'Select a condition to add into search' => 'Выбрать условие для поиска', 'Select all %s records matching your search' => 'Выбрать все %s записи из результатов поиска', 'Send' => 'Отправить', 'Send Cancel Notifications to User' => 'Отправить пользователю уведомление об отмене', 'Send Message' => 'Отправить Сообщение', 'Send Voucher To' => 'Отправить ваучер', 'Session expired, please enter username and password again' => 'Сессия устарела, пожалуйста введите имя пользователя и пароль снова', 'Settings' => 'Настройки', 'Shipping' => 'Доставка', 'Shipping Options' => 'Варианты доставки', 'Shopping Cart' => 'Электронный магазин', 'Shopping Cart Module. No data input' => 'Модуль корзины. Нет входных данных.', 'Shopping Cart Module. No product id input' => 'Модуль корзины. Нет входного ID продукта (product id)', 'Shopping Cart Signup' => 'Регистрация в электронном магазине', 'Sign-up' => 'Подписка', 'Signature' => 'Сигнатура', 'Signup Form' => 'Регистрация', 'Signup here' => 'Зарегистрируйтесь здесь', 'Signup/payment functions are disabled for this user account' => 'Функции Зарегистрироваться/Заплатить не доступны для данного пользователя', 'Simple Search Users' => 'Простой поиск пользователей', 'Site Title' => 'Название сайта', 'Skip First Line' => 'Пропустить первую строчку', 'Snippets' => 'Шаблоны', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Извините, невозможно использовать этот способ оплаты для этого заказа. Пожалуйста выберите другой', 'Sorry, seems you have used wrong link' => 'Извините, кажется вы воспользовались неправильной ссылкой', 'Source Code — Copy/Paste Into Your Website' => 'Исходный код — Копировать/Вставить на Ваш сайт', 'Standard' => 'Стандартный', 'Start' => 'Старт', 'Start Date' => 'Дата старта', 'State' => 'Штат', 'State Title' => 'Название региона', 'Statistics' => 'Статистика', 'Status' => 'Статус', 'Status of your subscription has been changed.' => 'Статус вашей подписки был изменен', 'Street' => 'Улица', 'Street (Second Line)' => 'Название улицы (вторая строка)', 'Street Address' => 'Название улицы', 'Street Address (Second Line)' => 'Название улицы (вторая строка)', 'SubUsers Count (keep zero for non-reseller products)' => 'Количество подпользователей (установите в ноль для не реселлерских продуктов)', 'SubUsers Product (keep empty for non-reseller products)' => 'Продукт подпользователя (оставьте пустым для не реселлерских продуктов)', 'Subject' => 'Тема', 'Subject can not be empty' => 'Тема должна быть введена', 'Subject or Ticket#' => 'Тема или Номер Обращения', 'Submit' => 'Отправить', 'Submit New Ticket' => 'Отправить Запрос', 'Subscribe And Pay' => 'Подписаться и Оплатить', 'Subscribe all available users' => 'Подписать всех доступных пользователей', 'Subscribe to Site Newsletters' => 'Подписаться на новостную рассылку сайта', 'Subscribed To Newsletters' => 'Подписан на Newsletters', 'Subscribers' => 'Подписчики', 'Subscription Terms' => 'Параметры подписки', 'Subscription expired, please contact your reseller to upgrade subscription' => 'Срок действия подписки истек, обратитесь к вашему торговому посреднику для обновления подписки', 'Subscription/Product Title' => 'Название Подписки/Продукта', 'Subtotal' => 'Итого', 'Subusers' => 'Подпользователи', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => 'Успешно: %d (%0.2f %s) Неудачно: %d (%0.2f %s)', 'Such affiliate ID exist' => 'Такой ID партнера сущестует', 'Support' => 'Помощь', 'Support Us!' => 'Поддержите нас!', 'Take' => 'Взять', 'Target URL' => 'URL назначения', 'Tax' => 'Налог', 'Tax Amount' => 'Сумма налога', 'Tax Id' => 'Id налога', 'Tax Rate for example 18.5 (no percent sign)' => 'Размер налога для примера 18.5(без знака процента)', 'Tax Title' => 'Название налога', 'Tax Value' => 'Размер налога', 'Terms' => 'Условия', 'Test Mode' => 'Тестовый режим', 'Test Settings' => 'Тестовые настройки', 'Thank you for Signing up' => 'Спасибо за подписку', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Спасибо! Ваш платеж обрабатывается и находится на рассмотрение. Мы обновим подписку сразу же, как платеж будет завершен. Пожалуйста, оставайтесь настроеными в течение этого процесса. Это может занять от 12 до 24 часов. Вы получите Email уведомление с информацией о платеже.', 'The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).' => '«Код карты» - это трех - или четырех значный защитный код, который напечатан на задней части кредитных карт (или на передней части для карт American Express).', 'The coupon entered is not valid with any product(s) being purchased. No discount will be applied' => 'Введенный купон не дает ни какой скидки на выбранные продукты', 'The database has encountered a problem, please try again later.' => 'Возникла проблема с базой данных, попробуйте снова чуть позже', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'Файл был удален с диска или поврежден. Пожалуйста закачайте файл заново.', 'The following words are reserved : %s' => 'Следующие слова зарезервированы: %s', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'Сообщение содержащие ваш пароль уже отправленно на вашу входящюю почту', 'The password should be at least %d characters long' => 'Пароль должен быть как минимум %d символов длиной', 'The user name or password is incorrect' => 'Имя пользователя или пароль неправильный', 'There are no confirmed payments for your account' => 'Нет утвержденных платежей для вашего аккаунта', 'There are no form available for affiliate signup.' => 'Нет подходящей формы регистрации партнера', 'There are no products available for purchase. Please come back later.' => 'Нет доступных продуктов для скачивания. Пожалуйста вернитеcь позднее', 'This %s is blocked. Please contact site support to find out why' => 'Этот %s заблокирован. Обратитесь к администратору сайта для выяснения причин', 'This Coupon Code is already being used, please select another one' => 'Это код уже используется для другого купона, код купона должен быть уникальным', 'This Month' => 'Этот месяц', 'This Week (Mon-Sun)' => 'Эта неделя (Понедельник - Воскресенье)', 'This Week (Sun-Sat)' => 'Эта неделя (Воскресенье - Суббота)', 'This coupon belongs to another customer' => 'Купон принадлежит другому пользователю', 'This customer is a reseller' => 'Этот клиент является реселлером', 'This field is a requried field' => 'Это поле обязательно для заполнения', 'This field is required' => 'Это поле обязательное', 'This is a required field' => 'Это - обязательное поле', 'This page will be automatically refreshed within %s' => 'Страница автоматически обновиться через %s', 'This payment system could not handle payments in [%s] currency' => 'Эта платежная система не принимает валюту [%s]', 'This payment system could not handle zero-total invoices' => 'Эта платежная система не может обрабатывать бесплатные подписки', 'Thresehold Date' => 'Дата отсечения', 'Ticket' => 'Запрос', 'Ticket has been submited' => 'Запрос добавлен', 'Tickets' => 'Запросы', 'Title' => 'Заголовок', 'To' => 'До', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Для добавления полей в форму, перенесите элементы из \'Доступные блоки\' в \'Блоки формы\'. Для удаления полей, переместите их обратно в \'Доступные блоки\'. Для того что бы сделать форму многостраничной, вставьте элемент \'PageSeparator\' в область, которая будет содержать несколько страниц.', 'Today' => 'Сегодня ', 'Total' => 'Итого', 'Total Amount of Payment' => 'Общая сумма платежей', 'Try again' => 'Попробуйте ещё раз', 'Type' => 'Тип', 'Type Username or E-Mail' => 'Имя пользователя или e-mail', 'USA (Letter)' => 'США (Letter)', 'Unable to cancel subscription: ' => 'Невозможно отменить подиску:', 'Unable to delete this file as it is used for:' => 'Невозможно удалить этот файл так как он ипользуется для:', 'Unassign Affiliate' => 'Убрать закрепленного партнера', 'Underscore is not allowed for username' => 'Нельзя использовать подчеркивание в имени пользователя', 'Unenroll Student' => 'Отписать студента', 'Unique Clicks' => 'Уникальные переходы', 'Unit Price' => 'Единая цена', 'Unknown period unit: %s' => 'Неизвестная единица измерения периода: %s', 'Unlimited' => 'не ограниченно', 'Unsubscribe' => 'Отписан', 'Unsubscribe from all e-mail messages' => 'Отказаться от всех email рассылок', 'Unsubscribed' => 'Отписан', 'Unsubscription Confirmation' => 'Подтверждение отказа от подписки', 'Update' => 'Обновить', 'Update Credit Card Info' => 'Обновить информацию о кредитной карте', 'Update Debit Card Info' => 'Обновить информацию о дебитовой карте', 'Update Password' => 'Изменить пароль', 'Updated' => 'Обновлено', 'Upgrade Subscription' => 'Сменить подписку', 'Upload files using FTP client to [%s]' => 'Закачивайте файлы используя FTP клиент в [%s]', 'Uploaded Files' => 'Загруженные файлы', 'Use Database Connection other than configured for aMember' => 'Использовать отличное от сконфигурированного в aMember, соединение с базой данных', 'Use Reward Points' => 'Ипользовать призовые очки', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Ипользовать другую базу данных MySQL Ипользовать индивидуальный хост, пользователь, пароль для %s соединения. Вы можете пропустить это.', 'Used' => 'Ипользовано', 'Used Any Coupon' => 'Использован любой купон', 'Used Coupon from Batch: %s' => 'Использован купон из серии: %s', 'Used Coupon with Code: %s' => 'Использован купон с кодом: %s', 'Useful Links' => 'Полезные ссылки', 'User' => 'Клиент', 'User %s is already working on this ticket.' => 'Пользователь %s уже работает над этим запросом.', 'User %s not found' => 'Клиент %s не найден', 'User Affiliate Link' => 'Партнерская ссылка пользователя', 'User Agreement' => 'Соглашение', 'User Groups' => 'Группы пользователей', 'User Info' => 'Информация о пользователе', 'User Search' => 'Поиск пользователя', 'User is locked' => 'Пользователь заблокирован', 'User is not approved' => 'Пользователь не утвержден', 'User must provide' => 'Пользователь должен предоставить', 'Username' => 'Имя пользователя', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Имя пользователя вы можете выбрать новое имя пользователя или оставить его неизмененным. Имя пользователя должно содержать минимум %d символов в длину и может состоять из букв, чисел и подчеркиваний', 'Username %s is already taken. Please choose another username' => 'Имя пользователя %s уже используется. Выберите другое имя', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'Имя пользователя [%s] содержит недопустимые символы - пожалуйста используйте цифры и буквы', 'Username [%s] is already taken. Please choose another username' => 'Имя пользователя [%s] уже используется. Пожалуйста выберите другое имя.', 'Username and password can not be the same' => 'Имя пользователя и пароль не могут быть одинаковыми', 'Username contains invalid characters - please use digits, letters or spaces' => 'Имя пользователя содержит недопустимые символы - пожалуйста, используйте цифры, буквы или пробелы', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Имя пользователя содержит недопустимые символы - пожалуйста, используйте цифры и буквы', 'Username/Email' => 'Введите адрес электронной почты или имя пользователя', 'Users subscribed to Newsletter Threads #' => 'Пользователи подписанные на темы Newsletter #', 'Validate E-Mail Address by sending e-mail message with code' => 'Проверить адрес электронной почты отправкой письма с кодом', 'Validation' => 'Проверка', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'Подтверждающее письмо отправлено на ваш адрес. Адрес электронной почты в вашем аккаунте будет изменен после верификации.', 'Version of script' => 'Версия скрипта', 'Video' => 'Видео', 'View Basket' => 'Посмотреть корзину', 'Visit %sorder page%s to order additional subscriptions' => 'Посетите %sстраницу подписки%s чтобы купить дополнительную подписку', 'Void' => 'Аннулировать', 'Voucher is not yet active' => 'Ваучер еще не активен', 'We ask you to update your password periodically for security reason.' => 'Мы просим вас менять пароль иногда по соображениям безопасности.', 'Week' => 'Неделя', 'Write your comment...' => 'Напишите ваш комментарий...', 'Write your reply...' => 'Напишите ваш ответ...', 'Wrong code or code expired - please start signup process again' => 'Неправильный или устаревший код - попробуйте снова', 'Wrong link - no id passed' => 'Неправильная ссылка - идентификационный номер не передан ', 'Wrong parameters, error #1253' => 'Неправильные параметры', 'Wrong password' => 'Неправильный пароль', 'Wrong verification code' => 'Неправильный код проверки', 'Wrongly signed URL, please contact site admin' => 'Неверный URL, пожалуйста, свяжитесь с администратором сайта', 'Year' => 'Год', 'Years' => 'Года', 'Yes' => 'Да', 'Yes, I want to cancel subscription' => 'Да, я отказываюсь от подписки', 'Yes, I want to remove my account with all associated info on this site' => 'Да, я хочу удалить мою учетную запись со всей информацией привязанной к ней', 'Yes, continue' => 'Да, продолжить', 'Yes, unsubscribe' => 'Да, отписаться', 'Yesterday' => 'Вчера', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Вы вошли как %s. %sВыйдите%s чтобы зарегистрироваться под другим именем', 'You can remove your account in our system.' => 'Вы можете удалить вашу учетную запись', 'You have %d items in shopping cart' => 'У вас есть %d продукт(ов) в корзине', 'You have %d items in your Basket' => 'У вас есть %d продукт(ов) в корзине', 'You have %s%d ticket(s)%s that require your attention' => 'У вас есть %s%d запросов%s, которые требуют вашего внимания', 'You have no access to %s' => 'У вас нет доступа к %s', 'You have no active subscriptions' => 'У Вас нет активных подписок', 'You have no enough permissions for this operation' => 'У вас недостаточно разрешений для выполнения операции', 'You have no items in shopping cart' => 'Ваша корзина пуста', 'You have no items in your basket - please add something to your basket before checkout' => 'Ваша корзина пуста - пожалуйста добавьте что-нибудь', 'You have no subscription' => 'У вас нет подписок', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'У вас слишком много подпользователей закрепленных за этим аккаунтом. Вы можете выбрать %d пользователей для удаления из вашего аккаунта ', 'You must be authorized to access this area' => 'Вы должны быть авторизованны для доступа к данной области', 'You must be logged-in to open this media' => 'Вы должны осуществить вход в систему для доступа к данному носителю среды', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Вы должны установить aMember панель управления -> Уcтановка -> Расширенные -> Механизм хранения сессий в \'Стандартная сессия PHP\'. Это необходимо для включения логирования пользователей между aMember и SilverStrype', 'Your 9 digit ABA Routing Number' => 'Ваш 9-ти значный ABA Routing номер', 'Your Account Removal' => 'Ваш аккаунт удален', 'Your Bank Account Number' => 'Номер вашего банковского аккаунта', 'Your Bank Account Number Up to 20 digits' => 'Номер вашего банковского счета до 20 цифр', 'Your Basket' => 'Ваша Корзина', 'Your Current Password' => 'Ваш пароль', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Ваш текущий пароль если вы меняете пароль, нужно ввести имеющийся пароль для проверки в это поле', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Ваш адрес электронной почты письмо с подтверждением будет отправлено вам на этот адрес', 'Your General Affiliate Link' => 'Ваша партнерская ссылка', 'Your Membership Information' => 'Ваша пользовательская информация', 'Your Message' => 'Ваше сообщение', 'Your Name your first and last name' => 'Ваше имя ваше имя и фамилия', 'Your Password' => 'Ваш пароль', 'Your Payment is PENDING & Under Process' => 'Ваш платеж обрабатывается и находится на рассмотрение', 'Your Personal Downloads' => 'Ваши персональные файлы', 'Your Reseller Packages' => 'Пакеты вашего реселлера', 'Your account has been automatically locked.' => 'Ваш аккаунт был автоматически заблокирован.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Ваш аккаунт еще не утвержден. Вы получите уведомительное письмо когда администратор сайта рассмотрит ваш аккаунт и откроет доступ', 'Your answer is wrong' => 'Ваш ответ не верен', 'Your cart is empty. Click %shere%s to continue shopping.' => 'Ваша корзина пуста. Перейдите %sпо ссылки%s чтобы ознакомится с ассортиментом', 'Your password is too long' => 'Ваш пароль слишком длинный', 'Your payment has been successfully processed.' => 'Ваш платеж был успешно обработан.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Ваш платеж еще не подтвержден платежной системой. Это может занять до нескольких минут', 'Your profile has been updated successfully' => 'Ваш профиль был успешно обновлен', 'Your subject is too verbose' => 'Тема слишком длинная', 'Your subscription does not allow access to this media' => 'Ваша подписка не предоставляет доступ к данному носителю информации', 'Your subscription has been successfully processed.' => 'Ваша подписка успешно обработана.', 'ZIP' => 'Индекс', 'ZIP Code' => 'Почтовый индекс', '[Select country]' => '[Выберите страну]', '[Select state]' => '[Выберите штат (регион)]', '_default_locale' => 'ru_RU', 'accepts all major credit cards' => 'принимает большинство известных кредитных карт', 'admin' => 'администратор', 'affiliate <-> user relation is expired (%saccording your settings%s User-Affiliate Relation Lifetime is %d day(s)), no commissions will be added for new payments' => 'связь партнер <-> клиент истекла (%sв соответствии с вашими настройками%s Клиент-Партнер время связи - %d день(ей)), комиссионные для новых платежей не будут добавляться', 'affiliate program commissions' => 'комиссия партнерской программы', 'after completing order, voucher will be sent to specified address' => 'после завершения заказа, ваучер будет отправлен на указанный адрес', 'ago' => 'назад', 'all requests will be added to %sLogs%s, useful if something is going wrong' => 'все запросы будут добавлены в %sЛог%s может быть полезно в случае возникновения каких либо проблем', 'any product' => 'любой продукт', 'banned' => 'забанен', 'begins' => 'начинается', 'check box to use points and get discount' => 'Кнопка-флажок для использования призовых очков и получения дисконта', 'check it if you want to gift subscription on this product' => 'проверте, если хотите подраить подписку на этот продукт', 'commission found by next rules' => 'комиссия найдена по следующим правилам', 'configure' => 'настроить', 'count of paid invoices by signup form' => 'количество оплаченных счетов на форму регистрации', 'day' => 'день', 'days' => 'дней', 'different currency products' => 'валюты продуктов не совпадают', 'different rebill times subscriptions' => 'Время повторного платежа подписок не совпадает ', 'different the first period subscriptions' => 'Первичный период подписок не совпадает', 'different the second period subscriptions' => 'Время вторичного платежа не совпадает', 'email' => 'адрес электронной почты', 'email will contain this sentence' => 'email будет содержать это предложение', 'expiration' => 'окончание срока', 'expires' => 'истекает', 'filtered' => 'отфильтровано', 'for affiliate commission payouts' => 'для выплаты партнерской комиссии', 'for example: 1111-2222-3333-4444' => 'например: 1111-2222-3333-4444', 'for example: 1111222233334444' => 'например: 1111222233334444', 'free' => 'бесплатно', 'generate' => 'сгенерировать', 'hrs' => 'часов', 'iDEAL betaling' => 'iDEAL оплата', 'if not specified, voucher will be sent to your email' => 'есле не указан, ваучер будет отправлен на ваш email адрес', 'ip' => 'ip-адрес', 'just now' => 'сейчас', 'labels' => 'тексты', 'lines skipped' => 'строк скрыто', 'link' => 'ссылка', 'login' => 'имя пользоватля', 'min' => 'минут', 'month' => 'месяц', 'months' => 'месяцы', 'more than' => 'больше чем', 'no records' => 'нет записей', 'number of active users per product' => 'количество активных пользователей по продуктам', 'number of affiliate program clicks' => 'Количество кликов партнерских программ', 'number of users per region' => 'колличество клиентов по регионам', 'of products' => 'на продукты', 'on %d-th day' => 'в %d-ый день', 'only First Name' => 'только имя', 'only Last Name' => 'только фамилия', 'or' => 'или', 'pay using credit card or PayPal' => 'оплатить используя кредитную карту или PayPal', 'pay using wire transfer or by sending offline check' => 'оплатить используя банковский перевод или чек', 'protected area' => 'Защищенная зона', 'reset' => 'сбросить', 'return' => 'вернуться', 'seconds' => 'секунд', 'start' => 'старт', 'this field is required' => 'это поле обязательно для заполнения', 'upgrade' => 'улучшение', 'use 4111-1111-1111-1111 for successful transaction' => 'используйте 4111-1111-1111-1111 для проведения успешной транзакции', 'year' => 'год', 'years' => 'годы', 'you can upload your filese here' => 'вы можете загрузить ваш файл', 'you have %d reward points collected' => 'Вы собрали %d призовых очков', ); PK\P4ťťdefault/language/user/he.phpnu[ 'לתמיד', ' from ' => 'מ', ' to ' => 'ל', '"%s" can be ordered along with these products/subscripton(s) only: %s' => 'ניתן להזמין את המוצר "%s" עם המינויים %s בלבד', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => 'ניתן להזמין את המוצר "%s" רק עבור מינויים %s שפג תוקפם ', '"%s" cannot be ordered because you have active subscription(s) to: %s' => 'המוצר "%s" לא ניתן להזמנה מכיוון שיש לך %s פעילים', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => 'לא ניתן להזמין "%s" מכיוון שהמינוי שלך ל %s פג תוקף', '%d-th day' => 'היום ה %d', '%s database and tables prefix' => '%s בסיס נתונים וקידומת', 'API Authentication Information' => 'API פרטי אימות', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'קבל תשלומים ישירים', 'Access' => 'גישה', 'Access Denied' => 'גישה נדחתה', 'Access Log' => 'יומן גישה', 'Access Permissions' => 'הרשאות גישה', 'Actions' => 'פעולות', 'Active' => 'פעיל', 'Active Resources' => 'משאבים פעילים', 'Active Subscriptions' => 'מנויי משנה פעילים', 'Active Users' => 'משתמשים פעילים', 'Active subusers' => 'משתמשי משנה פעילים', 'Add "Like" button' => 'הוסף כפתור "לייק"', 'Add New Notification Rule' => 'הוסף כלל הודעה חדשה', 'Add User' => 'הוסף משתמש', 'Add to Basket' => 'הוסף לסל', 'Add/Renew Subscription' => 'הוסף/ חדש מינויי', 'Added' => 'נוספו', 'Additional Fields' => 'שדות נוספים', 'Address Info' => 'כתובת', 'Address Information' => 'פרטי כתובת', 'Admin' => 'מנהל', 'Admin Username' => 'שם מנהל', 'Administrator' => 'מנהל', 'Advanced' => 'מתקדם', 'Advanced Search' => 'חיפוש מורחב', 'Advertise our website to your friends and earn money' => 'פרסם את אתרנו לחבריך והרווח כסף', 'Affiliate' => 'תכנית שותפים', 'Affiliate Clicks' => 'קליקים תכנית שותפים', 'Affiliate Id#' => 'מספר זיהוי תכנית שותפים', 'Affiliate Info' => 'פרטי תכנית שותפים', 'Affiliate Payout - Paypal E-Mail address' => 'תשלום שותף- כתובת PAYPAL', 'Affiliate Payout Type' => 'סוג תשלום', 'Affiliate Program' => 'תכנית שותפים', 'Affiliate Sales' => 'מכירות תכנית שותפים', 'Affiliate Signup Form' => 'טופס הרשמה תכנית שותפים', 'Affiliate info' => 'מידע אודות תכנית השותפים', 'Affiliate stats' => 'סטטיסטיקת שותף', 'Affiliates' => 'שותפים', 'All' => 'הכל', 'All %s records on this page are selected' => 'כל %s הרשומות בעמוד זה נבחרו', 'All Affiliates' => 'כל תכניות השותפים', 'All Time' => 'כל הזמן', 'All Users' => 'כל המשתמשים', 'All records' => 'כל הרשומות', 'Amazon S3 storage is not configured' => 'Amazon S3 לא מוגדר', 'Amount' => 'סכום', 'An Error has occurred' => 'שגיאה התרחשה', 'An account with the same email already exists.' => 'חשבון עם כתובת מייל זאת קיים', 'An error occurred while handling your payment.' => 'שגיאה התרחשה בתהליך התשלום', 'An internal error happened in the script, please contact webmaster for details' => 'שגיאה פנימית התחרשה ,אנא פנה למנהל האתר', 'Any Product' => 'מוצר כללי', 'Any product' => 'הוסף מוצר', 'Apply' => 'ליישם', 'Apply Filter' => 'הפעל מסנן', 'Attachments' => 'קבצים מצורפים', 'Authentication' => 'הזדהות', 'Authentication problem, please contact website administrator' => 'בעיית הזדהות, אנא צור קשר עם מנהל האתר', 'Auto-Subscribe users to list once it becomes accessible for them' => 'רישום אוטומט לרשימת משתמשים', 'Available Bricks (drag to left to add)' => 'לבנים זמינים (גרור שמאלה להוספה)', 'Available Credits' => 'קרדיטים זמינים', 'Awaiting Admin Response' => 'ממתין לתגובת מנהל', 'Awaiting User Response' => 'ממתין לתגובת משתמש', 'Back' => 'חזור', 'Bank Identification' => 'זיהוי בנק', 'Bank Name' => 'שם הבנק', 'Banners and Links' => 'באנרים וקישורים', 'Banners and Text Links' => 'ניהול באנרים וקישורי טקסט', 'Begin Date' => 'תאריך התחלה', 'Both Affiliate and member' => 'שניהם שותפים וחבר', 'CC Demo' => 'CC Demo', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'הטופס חייב להשלח תוך %d דקות לאחר הצגה, אנא מלא שוב', 'Can view/edit customer Credit Card information and rebills' => 'יכול להציג / לערוך את כרטיסי האשראי של הלקוחות', 'Cancel' => 'בטל', 'Cancel Subscription' => 'ביטול מנוי', 'Cancelled' => 'בוטל', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'לא ניתן להשתמש בתוסף תשלום חינם עם המוצר שעלותו יותר מ 0.0', 'Cannot validate VAT Id, please try again' => 'לא ניתן לאמת קוד זיהוי מעמ, אנא נסה שוב', 'Category' => 'קטגוריה', 'Change' => 'שנה', 'Change Password' => 'שנה סיסמא', 'Change Password/Edit Profile' => 'שנה סיסמא/ ערוך פרופיל', 'Change Username' => 'שינוי שם משתמש', 'Change payout info' => 'שנה את פרטי תשלום', 'Checkout' => 'רכוש', 'Checkout error: ' => 'שגיאת יציאה', 'Choose a Password must be %d or more characters' => 'בחר סיסמא חייב להכיל לפחות %d תווים', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'בחר שם משתמש מינימום %d תווים יכול להכיל רק אותיות, מספרים וקו תחתי', 'City' => 'עיר', 'Click button to continue' => 'לחץ על הכפתור על מנת להמשיך', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'לחץ כאן אם אין ברצונך לחכות עוד(או שהדפדפן אינו מעביר אותך אוטומטית)', 'Click to Edit' => 'לחץ לעריכה', 'Clicks' => 'קליקים', 'Clicks/Sales Statistics' => ' סטטיסטיקת קליקים/מכירות', 'Close' => 'סגור', 'Close Ticket' => 'סגור קריאת שירות', 'Closed' => 'נסגר', 'Code' => 'קוד', 'Comment' => 'תגובה', 'Comment for admin reference' => 'הערה', 'Commission' => 'עמלה', 'Commissions' => 'עמלות', 'Configuration' => 'הגדרות', 'Configured Tax Values' => 'הגדר ערכי מס', 'Confirm New Password' => 'הכנס שנית סיסמא חדשה', 'Confirm Password' => 'אשר סיסמא', 'Confirm Payment' => 'אשר תשלום', 'Confirm Your E-Mail Address' => 'אמת את כתובת הדואל שלך', 'Confirm Your Password' => 'הכנס שנית סיסמא', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'קישור אישור נשלח לכתובת דואר האלקטרוני שלך. אנא בדוק את תיבת הדואר שלך. אם לא קבל הודעת דואר אלקטרוני תוך 5 דקות, בדוק בתיקייה \'דואר הזבל\' ', 'Content' => 'תוכן', 'Continue' => 'המשך', 'Conversation' => 'שיחה', 'Copy of' => 'העתק של', 'Count of signups' => 'מספר הנרשמים', 'Count of user signups' => 'מספר המשתמשים שנרשמו', 'Country' => 'מדינה', 'Coupon' => 'קופון', 'Coupon Code' => 'קוד קופון', 'Coupon Discount' => 'הנחת קופון', 'Coupon code disabled' => 'קופון בוטל', 'Coupon code expired' => 'הקופון פג תוקף', 'Coupon is not yet active' => 'הקופון עדיין לא הופעל', 'Coupon usage limit exceeded' => 'מגבלת השימוש בקופון חרגה', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'צירת משתמשי aMember על ידי ביקוש שקט ליצור לקוח בaMember אם משתמש מנסה להתחבר לaMember עם באותו שם משתמש וסיסמא כעבור%s', 'Credit Card Code' => '3 ספרות בגב כרטיס האשראי', 'Credit Card Info' => 'נתוני כרטיס אשראי', 'Credit Card Number' => 'מספר כרטיס אשראי', 'Credit Card Rebills' => 'חיוב נוסף כרטיס אשראי', 'Credit Cards' => 'כרטיסי אשראי', 'Currency' => 'מטבע', 'Currency Exchange Rates' => 'שער חליפין של מטבע', 'Current password entered incorrectly, please try again' => 'הסיסמא הנוכחית אינה תואמת, אנא נסה שוב', 'Custom Commission' => 'עמלה מותאמת אישית', 'Customer account has been automatically locked.' => 'חשבון לקוחות ננעל באופן אוטומטי.', 'Customize' => 'התאם אישית', 'DONE' => 'בוצע', 'Dashboard' => 'לוח מחוונים', 'Data Integrity Code' => 'קוד תקינות הנתונים', 'Date' => 'תאריך', 'Date and time of payment: %s' => 'תאריך וזמן התשלום: %s', 'Date must be in format %s' => 'תאריך חייב להיות בפורמט של %s', 'Date/Time' => 'תאריך / זמן', 'Date: ' => 'תאריך:', 'Day' => 'יום', 'Days' => 'ימים', 'Deactivate Student' => 'בטל סטודנט', 'Deactivate User' => 'בטל משתמש', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'רמת ברירת מחדל רמת ברירת מחדל- משתמשים מאופסים לרמת גישה זאת במידה ואין אף מינויי אפשרי', 'Delete' => 'מחק', 'Delete %s' => 'מחק %s', 'Description' => 'תאור', 'Disable online VAT Id Validation' => 'בטל אימות קוד זיהוי מע"מ מקוון', 'Disabled' => 'מבוטל', 'Discard' => 'בטל', 'Discount' => 'הנחה', 'Display Type' => 'צורת הצגה', 'Display in 2 rows' => 'הצג ב -2 שורות', 'Do not add to Login Form' => 'אל תוסיף לעמוד הכניסה', 'Do not add to Signup Form' => 'אל תוסיף לעמוד ההרשמה', 'Do you really want to %s %s %s records' => 'האם אתה בטוח שברצונך %s %s %s שדות', 'Do you really want to %s?' => 'האם אתה באמת רוצה %s ?', 'Do you really want to cancel subscription?' => 'אתה בטוח שברצונך לבטל את המנוי?', 'Do you really want to delete record?' => 'האם אתה בטוח שברצונך למחוק רשומה?', 'Do you really want to unsubscribe from %s periodical messages?' => 'אתה בטוח שברצונך להסיר הודעות מ %s ?', 'Done' => 'בוצע', 'Download' => 'הורדה', 'Download limit exceeded for this file' => 'מכסת ההורדה לקובץ זה הגיעה לסופה', 'Downloaded on your own server' => 'הורד בשרת שלך', 'E-Mail' => 'מייל', 'E-Mail Address' => 'כתובת מייל', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'כתובת דואר אלקטרוני ואישור כתובת דואר אלקטרוני שונות. הזן מחדש שניהם', 'E-Mail Format' => 'פורמט הודעת דואל', 'E-Mail Messages' => 'הודעות מייל', 'E-Mail Verification' => 'אימות מייל', 'EU VAT' => 'מעמ', 'EU VAT ID: ' => 'קוד זיהוי מעמ אירופאי', 'EU VAT Id (optional)' => 'קוד זיהוי מעמ אירופאי (אופציונלי)', 'Edit' => 'ערוך', 'Edit %s' => 'ערוך %s', 'Edit Brick Labels' => 'ערוך תויות', 'Edit E-Mail Template' => 'עריכת תבנית דואר אלקטרוני', 'Email' => 'מייל', 'Email Subject' => 'נושא', 'Email admin regarding account sharing' => 'יידע מנהל בנוגע לשיתוף חשבונות', 'Email user regarding account sharing' => 'שלח הודעת דואל ללקוח בנוגע לשיתוף חשבונות', 'Empty response from Sagepay server' => 'תגובה ריקה משרת Sagepay', 'Enabled Modules' => 'מודולים מופעלים', 'End' => 'סיום', 'End Date' => 'תאריך סיום', 'Enjoy your membership. To Login please click here %sLogin%s' => 'להכנס אנא לחץ כאן %sכניסה%s ', 'Enter coupon code' => 'הכנס קופון', 'Error 404 - Not Found' => 'שגיאה 404- דף לא נמצא', 'Error : upload folder [%s] does not exists' => 'שגיאה: הספריה [%s] לא קיימת', 'Error happened during transaction handling. Please contact website administrator' => 'שגיאה התרחשה במהלך טיפול עסקה. אנא צור קשר עם מנהל אתר', 'European (A4)' => 'אירופאי', 'Exact' => 'מדויק', 'Expire Date' => 'תאריך פקיעה', 'Expired' => 'פקיעה', 'Expired Users' => 'משתמשים שפגו תוקף', 'Expires' => 'פקיעה', 'Export' => 'ייצא', 'Export Format' => 'פורמט ייצוא', 'FaceBook App ID' => 'FaceBook App ID', 'FaceBook Application' => 'יישום פייסבוק', 'Facebook App Secret' => 'Facebook App Secret', 'Features' => 'תכונות', 'Field' => 'שדה', 'Field Type' => 'סוג השדה', 'Field Updated' => 'שדות עודכנו', 'Fields To Display' => 'שדות להצגה', 'Fieldset' => 'קבוצת שדות', 'Fieldset title' => 'כותרת קבוצת שדות', 'File' => 'קובץ', 'File Downloads' => 'הורדת קבצים', 'File Storage' => 'אחסון קבצים', 'Filename' => 'שם קובץ', 'Files' => 'קבצים', 'Files uploaded via aMember web interface' => 'קבצים שהועלו באמצעות ממשק האינטרנט aMember', 'Filter' => 'סנן', 'First & Last Name' => 'שם מלא', 'First Name' => 'שם פרטי', 'Folder %s (%s)' => 'ספריה %s (%s)', 'Folders' => 'תקיות', 'Form Page Break' => 'מעבר עמוד טופס', 'Free' => 'חינם', 'Free Access' => 'גישה חופשית', 'From' => 'מ', 'Get Password' => 'קבל סיסמא', 'Global Tax' => 'מס גלובלי', 'Groups' => 'קבוצות', 'HTML Code that will be displayed' => 'קוד HTML שיוצג', 'HTML Message' => 'הודעת HTML', 'HTML text' => 'טקסט HTML', 'Having Active Subscription To:' => 'יש מנוי פעיל ל:', 'Having Expired Subscription To:' => 'יש מינויי פג תוקף ל:', 'Helpdesk' => 'מרכז התמיכה', 'Hide do not display this item link in members area' => 'הסתר לא להציג קישור פריט זה באזור חברים', 'Hosted at Activecampaing\'s server' => 'מאוחסן אצל Activecampaing\'s ', 'Housenumber' => 'מספר בית', 'IP Address' => 'כתובת IP', 'If you already have an account on our website, please %slog in%s to continue' => 'אם יש ברשותך חשבון באתרנו אנא %sהכנס%s על מנת להמשיך', 'If you are a registered member, please %slogin%s' => 'במידה והינך משתמש רשום, אנא בצע%sכניסה%s', 'If you are not registered yet, please %ssignup%s' => 'אם אינך משתמש רשום אנא %sהרשם%s', 'Income Report - payments minus refunds' => 'דוח הכנסות- תשלומים פחות זיכויים', 'Incorrect Parent Affiliate ID' => 'קוד זיהוי שגוי', 'Integer Value' => 'ערך מספר שלם', 'Integer value required' => 'ערך מספרי שלם נדרש', 'Integration' => 'השתלבות', 'Integrations' => 'אינטגרציות', 'Internal Error' => 'שגיאה פנימית', 'Invalid Credit Card Number' => 'מספר אשראי לא חוקי', 'Invalid Expiration Date - Month' => 'תוקף לא חוקי', 'Invalid Expiration Date - Year' => 'תוקף לא חוקי', 'Invalid Issue Number' => 'מספר ההנפקה לא חוקי', 'Invalid VAT Id, please try again' => 'קוד זיהוי מעם שגוי, נסה שוב', 'Invoice' => 'חשבונית', 'Invoice Number: ' => 'מספר חשבונית', 'Invoice not found' => 'חשבונית לא נמצאה', 'Is Locked' => 'נעול', 'Is Paid?' => 'בוצע תשלום?', 'Is Disabled?' => '  מבוטל?', 'Item' => 'פריט', 'Label' => 'תוית', 'Language' => 'שפה', 'Last 14 Days' => '14 ימים אחרונים', 'Last 30 Days' => '30 ימים אחרונים', 'Last 7 Days' => '7 ימים אחרונים', 'Last Business Week (Mon-Fri)' => 'שבוע העסקים האחרון', 'Last Messages in Helpdesk' => 'הודעה אחרונה במרכז התמיכה', 'Last Month' => 'חודש שעבר', 'Last Name' => 'שם משפחה', 'Last Week (Mon-Sun)' => 'שבוע שעבר (שני עד ראשון)', 'Last Week (Sun-Sat)' => 'שבוע שעבר (ראשון עד שבת)', 'Leads' => 'לידים', 'License Key' => 'מפתח רישיון', 'Lifetime' => 'זמן חיים', 'Like Url' => 'כתובת "לייק"', 'Link' => 'קישור', 'Links' => 'קישורים', 'Live Edit %s' => '%s עורך בזמן אמת', 'Loading' => 'טוען', 'Log In' => 'כנס', 'Log all API Requests' => 'רשום את כל בקשות API', 'Login' => 'כניסה', 'Login as User' => 'כנס כמשתמש', 'Logout' => 'התנתק', 'Lost Password Sending Error' => 'שגיאה בשליחת סיסמא', 'Lost Password Sent' => 'סיסמא שאבדה נשלחה', 'Lost password?' => 'שכחתי סיסמא', 'Mail Queue' => 'תור מייל', 'Make Payment' => 'בצע תשלום', 'Manage Newsletters' => 'נהל עלון', 'Marketing Materials' => 'תכנים שיווקים', 'Membership Type' => 'סוג חברות', 'Merchant Key' => 'מפתח סוחר', 'Merchant Secret' => 'Merchant Secret', 'Message' => 'הודעה', 'Message can not be empty' => 'הודעה לא יכולה להשאר ריקה', 'Month' => 'חודש', 'Months' => 'חודשים', 'Multiplier' => 'גורם', 'My Country' => 'הארץ שלי', 'Name' => 'שם', 'Never' => 'אף פעם', 'New' => 'חדש', 'New %s' => '%s חדש', 'New Password' => 'סיסמא חדשה', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'סיסמא חדשה ניתן לבחור סיסמא חדשה או להשאיר ללא שינוי, סיסמא חייבת להכיל לפחות %d תווים', 'Newsletter' => 'עלון', 'Newsletter Subscriptions' => 'מינויי עלון', 'Next' => 'הבא', 'No' => 'לא', 'No commissions on this date' => 'אין עמלות לתאריך הנבחר', 'No coupons found with such coupon code' => 'לא נמצאו קופונים זמינים', 'No items selected for purchase' => 'לא נבחר פריט לרכישה', 'No records found' => 'לא נמצאו רשומות', 'No, cancel' => 'לא, בטל', 'No, keep me subscribed' => 'לא, השאר אותי רשום', 'No, please keep me subscribed' => 'לא, השאר אותי מנוי', 'Not Approved Affiliates' => 'תכנית שותפים לא מאושרת', 'Not Selected' => 'לא נבחר', 'Not registered yet?' => 'לא רשום עדיין?', 'Number of Messages to display' => 'מספר הודעות להצגה', 'Numeric Value' => 'ערך נומרי', 'Numeric value required' => 'ערך נומרי נדרש', 'Offline Payment' => 'תשלום לא מקוון', 'Only Affiliate %s(rarely used)%s' => 'רק שותף %sשימוש נדיר%s', 'Order reference: %s' => 'הפנית הזמנה : %s', 'Other' => 'אחר', 'Pages' => 'עמודים', 'Password' => 'סיסמא', 'Password and Password Confirmation are different. Please reenter both' => 'סיסמאות לא תואמות , אנא הכנס שוב', 'Password must contain at least %d letters or digits' => 'סיסמא חייבת להכיל לפחות %d אותיות או מספרים', 'Passwords do not match' => 'סיסמאות לא תואמות', 'Path to %s' => 'נתיב ל %s', 'Path to %s Folder' => 'נתיב ל %s ספריה', 'Payanyway plugin does not support recurring billing!' => 'התוסף Payanyway לא תומך בתשלום מחזורי', 'Payment' => 'תשלום', 'Payment Error' => 'שגיאה בתשלום', 'Payment Failed' => 'תשלום נכשל', 'Payment System' => 'מערכת תשלום', 'Payment System Description' => 'תיאור מערכת תשלומים', 'Payment System Title' => 'כותרת מערכת תשלומים', 'Payment error: ' => 'שגיאת תשלום', 'Payment failed' => 'תשלום נכשל', 'Payment is already processed, please go to %sMembership page%s' => 'התשלום בוצע כבר, אנא בקר %sבדף מינויים%s', 'Payments' => 'תשלומים', 'Payments History' => 'היסטוריית תשלומים', 'Payments by New vs Existing members' => 'פירוט תשלומים על ידי השוואת לקוחות חדשים כנגד ישנים', 'Payments by payment system breakdown' => 'תשלומים על ידי התמוטטות מערכת תשלומים', 'Payments by products breakdown' => 'תשלומים על ידי פירוט מוצרים', 'Payments from existing customers' => 'תשלומים מלקוחות קימים', 'Payments from new customers' => 'תשלומים מלקוחות חדשים', 'Payments total' => 'תשלומים כולל', 'Payout Method' => 'שיטת תשלום', 'Payouts' => 'תשלומים', 'Pending' => 'בהמתנה', 'Pending Invoices' => 'חשבוניות בהמתנה', 'Pending subusers' => 'משתמשי משנה בהמתנה', 'Period' => 'תקופה', 'Period must be in interval 1-24 months' => 'תקופה חייבת להיות בין 1-24 חודשים', 'Period must be in interval 1-5 years' => 'תקופה חייבת להיות בין 1 -15 שנים', 'Period must be in interval 1-90 days' => 'תקופה חייבת להיות בין 1-90 יום', 'Personal Content' => 'פרטים אישיים', 'Phone' => 'טלפון', 'Phone Number' => 'מספר טלפון', 'Plain-Text Message' => 'הודעת טקסט', 'Please Select' => 'אנא בחר', 'Please agree to User Agreement' => 'אנה לחץ אני מסכים', 'Please choose' => 'אנא בחר', 'Please choose a Credit Card Type' => 'אנא בחר סוג כרטיס אשראי', 'Please choose a membership type' => 'אנא בחר סוג חברות', 'Please choose a payment system' => 'אנא בחר שיטת תשלום', 'Please choose state' => 'אנא בחר מדינה', 'Please enter %s' => 'אנא הכנס %s', 'Please enter City' => 'אנא הכנס עיר', 'Please enter Country' => 'אנא הכנס מדינה', 'Please enter Credit Card Code' => 'אנא הכנס 3 ספרות בגב כרטיס האשראי', 'Please enter Credit Card Number' => 'אנא הכנס מספר כרטיס אשראי', 'Please enter Password' => 'אנא הכנס סיסמא', 'Please enter State' => 'אנא הכנס מדינה', 'Please enter Street Address' => 'אנא הכנס שם רחוב', 'Please enter ZIP code' => 'אנא הכנס מיקוד', 'Please enter a valid e-mail address' => 'אנא הכנס כתובת דואל תקנית', 'Please enter coupon code' => 'אנא הכנס קופון', 'Please enter credit card holder first name' => 'הכנס שם פרטי של מחזיק האשראי', 'Please enter credit card holder last name' => 'הכנס שם משפחה של מחזיק האשראי', 'Please enter credit card holder name' => 'אנא הכנס שם בעל כרטיס האשראי', 'Please enter housenumber' => 'אנא הכנס מספר בית', 'Please enter phone number' => 'אנא הכנס מספר טלפון', 'Please enter valid Email' => 'אנא הכנס כתובת מייל חוקית', 'Please enter valid Username. It must contain at least %d characters' => 'אנא הכנס שם משתמש חוקי, חייב להכיל לפחות %d תווים', 'Please enter your First Name' => 'אנא הכנס את שמך הפרטי', 'Please enter your Last Name' => 'אנא הכנס את שם המשפחה', 'Please enter your current password for validation' => 'אנא הכנס את סיסמתך הנוכחית לצורך זיהוי', 'Please login' => 'אנא הכנס', 'Please select' => 'אנא בחר', 'Please select an item...' => 'אנא בחר פריט ...', 'Please select payment system for payment' => 'אנא בחר שיטת תשלום', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'אנא השתמש %sבטופס חידוש/הוספת מינוי%s להזמין או לחדש מינוי', 'Please wait %d seconds before next login attempt' => 'אנא המתן %d שניות לפני הכניסה הבאה', 'Plugin' => 'תוסף', 'Plugin List Id' => 'קוד זיהוי רשימת תוספים', 'PostAffiliatePro Parent Affiliate ID' => 'קוד זיהוי PostAffiliatePro ', 'PostAffiliatePro Referral ID' => 'קוד מפנה PostAffiliatePro ', 'Prev' => 'קודם', 'Preview' => 'תצוגה מקדימה', 'Price' => 'מחיר', 'Processing your Transaction' => 'מעבד את העסקה', 'Product' => 'מוצר', 'Product Categories' => 'קטגוריות מוצרים', 'Product Title' => 'כותרת מוצר', 'Product(s) to display' => 'מוצרים להצגה', 'Products' => 'מוצרים', 'Products keep empty to report all products' => 'מוצרים השאר רק לדווח כל המוצרים', 'Profile' => 'ערוך פרופיל', 'Profile update transaction failed' => ' עדכון פרופיל נכשל', 'Purchased Credits' => 'קרדיטים נרכשו', 'Qty' => 'כמות', 'Quantity' => 'כמות', 'Quick Order' => 'הזמנה מהירה', 'Re-Open Ticket' => 'פתח מחדש קריאת שרות', 'Read-only' => 'קריאה בלבד', 'Record' => 'רשומה', 'Records that match all these conditions' => 'רשומות התואמות את כל התנאים', 'Recurring' => 'מחזורי', 'Reference number is:' => 'מספר סימוכין:', 'Referer' => 'מפנה', 'Referred Affiliate' => 'שותף מפנה', 'Refresh' => 'רענן', 'Refresh 3-rd party lists' => 'רענן רשימת צד 3', 'Refund' => 'זכה', 'Refund Amount' => 'סכום לזיכוי', 'Refunded' => 'זוכה', 'Regional Tax' => 'מס מקורי', 'Register' => 'הרשם', 'Remove' => 'הסר', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'הסר משתמשים כאשר רשומה נמחקת מבסיס הנתונים, הרשומה מוסרת גם מ %s', 'Remove user' => 'הסר משתמש', 'Reply' => 'השב', 'Required' => 'נחוץ', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'נסה שוב בכישלון אם החיוב החוזר נכשל, aMember יכול לחזור על זה אחרי כמה ימים, ולהאריך את המנוי של לקוח לתקופה הזן את מספר ימים לחזור על ניסיון חיוב', 'Return' => 'החזר', 'Return and try again' => 'חזור ונסה שנית', 'Review/Pay Commissions' => 'סקור/שלם עמלת שותפים', 'Run Report' => 'הרץ דוח', 'Running %s' => 'מריץ %s', 'Save' => 'שמור', 'Save Profile' => 'שמור פרופיל', 'Search' => 'חפש', 'Search Products' => 'חפש מוצר', 'Security code is invalid' => 'קוד אבטחה לא חוקי', 'Select a condition to add into search' => 'בחר תנאי להוספת החיפוש', 'Select all %s records matching your search' => 'בחר את כל %s הרשומות המתאימות לחיפוש', 'Send' => 'שלח', 'Send Cancel Notifications to User' => 'שלח התראת ביטול ללקוח', 'Session expired, please enter username and password again' => 'התוקף פג, אנא הכנס שם משתמש וסיסמא בשנית', 'Settings' => 'הגדרות', 'Shipping' => 'משלוח', 'Shopping Cart' => 'עגלת קניות', 'Sign-up' => 'הרשם', 'Signup Form' => 'טופס הרשמה', 'Signup here' => 'הרשם כאן', 'Signup/payment functions are disabled for this user account' => 'אופציית כניסה / תשלום מושבתות עבור חשבון משתמש זה', 'Simple Search Users' => 'חיפוש משתמשים פשוט', 'Skip First Line' => 'דלג שורה הראשונה', 'Snippets' => 'קטעים', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'לא ניתן להשתמש במערכת תשלום זאת להזמנה זאת, אנא נסה מערכת ערכת', 'Sorry, seems you have used wrong link' => 'ככל הנראה השתמשת בקישור שגוי', 'Standard' => 'סטנדרט', 'Start' => 'התחלה', 'Start Date' => 'תאריך התחלה', 'State' => 'מדינה', 'Status' => 'סטטוס', 'Street' => 'רחוב', 'Street Address' => 'שם רחוב', 'SubUsers Count (keep zero for non-reseller products)' => 'מספר משתמשי משנה', 'SubUsers Product (keep empty for non-reseller products)' => 'מוצרי משתמשי משנה', 'Subject' => 'נושא', 'Subject can not be empty' => 'נושא לא יכול להשאר ריק', 'Subscribe to Site Newsletters' => 'הרשם לעלון האתר', 'Subscribed To Newsletters' => 'הרשם לעלון', 'Subscribers' => 'מנויים', 'Subscription Terms' => 'תנאי מנוי', 'Subscription/Product Title' => 'כותרת מנוי/מוצר', 'Subtotal' => 'סכום ביניים', 'Subusers' => 'משתמשי משנה', 'Such affiliate ID exist' => 'תכנית שותפים לא קיימת', 'Target URL' => 'כתובת יעד', 'Tax' => 'מס', 'Tax Amount' => 'סכום מס', 'Tax Id' => 'זיהוי מס', 'Tax Rate for example 18.5 (no percent sign)' => 'שיעור מס לדוגמא 18.6', 'Tax Title' => 'כותרת מס', 'Tax Value' => 'ערך מס', 'Terms' => 'תנאים', 'Test Mode' => 'מצב בדיקה', 'Test Settings' => 'בדוק הגדרות', 'Thank you for Signing up' => 'תודה לך על ההרשמה', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'תודה! התשלום בהמתנה & מעובד. ברגע שהתשלום יסתיים נעדכן את חשבונך ודואל אישור ישלח ', 'The database has encountered a problem, please try again later.' => 'האתר נתקל בבעיה, אנא נסה שוב מאוחר יותר.', 'The password should be at least %d characters long' => 'הסיסמא צריכה להכיל לפחות %d תווים', 'The user name or password is incorrect' => 'שם המשתמש או סיסמא שגויים', 'There are no confirmed payments for your account' => 'אין תשלומים מאושרים לחשבונך', 'There are no form available for affiliate signup.' => 'אין טפסים זמינים עבור הרשמה לתכנית השותפים', 'There are no products available for purchase. Please come back later.' => 'אין מוצרים למכירה כרגע, אנא נסה שוב מאוחר יותר', 'This Month' => 'חודש זה', 'This Week (Mon-Sun)' => 'שבוע זה (שני עד ראשון)', 'This Week (Sun-Sat)' => 'שבוע זה(ראשון עד שבת)', 'This coupon belongs to another customer' => 'קופון זה שייך ללקוח אחר', 'This field is required' => 'השדה הכרחי', 'This is a required field' => 'זהו שדה חובה', 'This page will be automatically refreshed within %s' => 'דף זה ירוענן אוטומטי בתוך %s', 'This payment system could not handle payments in [%s] currency' => 'מערכת התשלומים הנל לא יכולה לקבל תשלומים במטבע [%s] ', 'This payment system could not handle zero-total invoices' => 'מערכת תשלומים זאת לא יכולה לקבל חשבוניות על סכום 0', 'Thresehold Date' => 'Thresehold תאריך', 'Ticket' => 'קריאת שרות', 'Ticket has been submited' => 'קריאת שרות הוכנסה', 'Tickets' => 'קריאת שרות', 'Title' => 'כותרת', 'To' => 'ל', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'להוספת שדות לטופס, הזה פריטים מ\'פריטים אפשרים\' לפריטי טופס', 'Today' => 'היום', 'Total' => 'סכום כולל', 'Try again' => 'נסה שוב', 'Type' => 'סוג', 'USA (Letter)' => 'ארהב', 'Unable to delete this file as it is used for:' => 'לא ניתן למחוק קובץ זה, משמש עבור:', 'Unenroll Student' => 'ביטול הרשמת הסטודנט', 'Unknown period unit: %s' => 'יחידת מחזור %s אינה מוכרת', 'Unsubscribe from all e-mail messages' => 'הסר הרשמה מכל הודעות הדואל', 'Unsubscribed' => 'הסר מהמנוי', 'Unsubscription Confirmation' => 'אישור ביטול מנוי', 'Update' => 'עדכן', 'Update Credit Card Info' => 'עדכן פרטי אשראי', 'Updated' => 'עודכן', 'Upgrade Subscription' => 'שדרוג מנוי', 'Upload files using FTP client to [%s]' => 'העלאת קבצים באמצעות תוכנת FTP ל [%s]', 'Use Database Connection other than configured for aMember' => 'השתמש בבסיס נתונים בנוסף ל aMember', 'Useful Links' => 'קישורים שימושים', 'User' => 'משתמש', 'User Agreement' => 'הסכם משתמש', 'User Groups' => 'קבוצות משתמשים', 'User Info' => 'פרטי משתמש', 'User Search' => 'חיפוש משתמש', 'User is locked' => 'המשתמש נעול', 'User is not approved' => 'המשתמש לא מאושר', 'User must provide' => 'משתמש חייב לספק', 'Username' => 'שם משתמש', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'שם משתמש אפשר לבחור שם משתמש חדש או להשאיר ללא שינוי חייב להכיל לפחות %d תווים', 'Username %s is already taken. Please choose another username' => 'שם משתמש %s תפוס, בחר שם משתמש אחר', 'Username contains invalid characters - please use digits, letters or spaces' => 'שם משתמש מכיל תווים לא חוקיים', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'שם משתמש מכיל תווים לא חוקיים, אנא הכנס ספרות ואותיות בלבד', 'Username/Email' => 'כתובת מייל או שם משתמש', 'Users subscribed to Newsletter Threads #' => 'מספר מנויים לעלון', 'VAT Id' => 'זיהוי מעמ', 'Validate E-Mail Address by sending e-mail message with code' => 'אימות כתובת אימייל על ידי שליחת הודעת דואר אלקטרוני עם קוד', 'Validation' => 'אמות', 'Version of script' => 'גרסאת סקריפט', 'Video' => 'ווידאו', 'View Basket' => 'צפה בסל הקניות', 'Visit %sorder page%s to order additional subscriptions' => 'עבור %sלדף הזמנות%s על מנת להזמין מוצר חדש', 'Week' => 'שבוע', 'Wrong code or code expired - please start signup process again' => ' קוד שגוי או פג תוקפו - התחל תהליך הרשמה שוב', 'Wrong link - no id passed' => 'קישור שגוי - זיהוי לא עבר', 'Wrong parameters, error #1253' => 'פרמטרים לא נכונים, שגיאה #1253', 'Wrong password' => 'סיסמא שגויה', 'Wrong verification code' => 'קוד אימות שגוי', 'Wrongly signed URL, please contact site admin' => 'כתובת שגויה , אנא פנה למנהל האתר', 'Year' => 'שנה', 'Years' => 'שנים', 'Yes' => 'כן', 'Yes, I want to cancel subscription' => 'כן, אני רוצה לבטל', 'Yes, continue' => 'כן, המשך', 'Yes, unsubscribe' => 'כן, הסר', 'Yesterday' => 'אתמול', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'אתה מחובר כ%s. %sהתנתק%s על מנת להרשם עם חשבון חדש', 'You have no access to %s' => 'אין לך גישה ל %s', 'You have no active subscriptions' => 'אין מוצרים זמינים', 'You have no enough permissions for this operation' => 'אין לך מספיק הרשאות לפעולה זו', 'You have no items in your basket - please add something to your basket before checkout' => 'אין לך מוצרים בסל הקניות, אנא הוסף מוצרים ', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'ישנם יותר מדי משתמשי משנה בחשבון זה, באפשרותך להסיר משתמשים %d מחשבונך', 'You must be authorized to access this area' => 'אתה חייב להיות מורשה לגשת לאזור זה', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype', 'Your Basket' => 'סל הקניות שלך', 'Your Current Password if you are changing password, please enter your current password for validation' => 'הסיסמא הנוכחית שלך במידה והינך משנה סיסמא, וודא שהיא חוקית', 'Your Membership Information' => 'פרטי המנוי שלך', 'Your Payment is PENDING & Under Process' => 'התשלום בתהליך', 'Your Personal Downloads' => 'ההורדות האישיות שלך', 'Your Reseller Packages' => 'חבלית המפיץ שלך', 'Your account has been automatically locked.' => 'החשבון שלך ננעל באופן אוטומטי.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'החשבון שלך עדין לא אושר, התראה תשלח לדואל שלך לאחר שהמנהל יאשר', 'Your password is too long' => 'הסיסמא ארוכה מדי', 'Your payment has been successfully processed.' => 'התשלום שלך אושר', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'התשלום שלך עדיין לא אושר על ידי המערכת, אנא נסה שוב בעוד כמספר דקות', 'Your subject is too verbose' => 'הנושא שלך הוא יותר מדי מפורט', 'Your subscription has been successfully processed.' => 'המינוי שלך עובד בהצלחה', 'ZIP' => 'מיקוד', 'ZIP Code' => 'מיקוד', 'Zip' => 'מיקוד', '[Select country]' => '[בחדר מדינה]', '[Select state]' => 'בחר מדינה', '_default_locale' => 'en_US', 'admin' => 'מנהל', 'affiliate program commissions' => 'עמלות תכנית שותפים', 'ago' => 'לפני', 'banned' => 'מנודה', 'commission found by next rules' => 'עמלות על פי הכללים הבאים', 'days' => 'ימים', 'email' => 'מייל', 'expiration' => 'פקיעה', 'expires' => 'תפוגה', 'filtered' => 'סוננו', 'for affiliate commission payouts' => 'תשלום עמלה לשותף', 'for example: 1111-2222-3333-4444' => 'לדוגמא 1111-2222-3333-4444', 'generate' => 'יצר', 'hrs' => 'שעות', 'ip' => 'IP', 'just now' => 'רק לעכשיו', 'link' => 'קישור', 'login' => 'כניסה', 'min' => 'דקות', 'month' => 'חודשים', 'more than' => 'יותר מ', 'no records' => 'אין רשומות', 'number of affiliate program clicks' => 'מספר קליקים לתכנית שותפים', 'of products' => 'של מוצרים', 'on %d-th day' => 'ביום ה %d', 'only First Name' => 'רק שם פרטי', 'only Last Name' => 'רק שם משפחה', 'or' => 'או', 'pay using credit card or PayPal' => 'שלם באמצעות כרטיס אשראי או PAYPAL', 'pay using wire transfer or by sending offline check' => 'תשלום באמצעות העברה בנקאית או על ידי משלוח המחאה ', 'protected area' => 'אזור מוגן', 'return' => 'החזר', 'seconds' => 'שניות', 'start' => 'התחלה', 'use 4111-1111-1111-1111 for successful transaction' => 'use 4111-1111-1111-1111 for successful transaction', ); PK\_>>!default/language/user/default.phpnu[Expired' => ' / Expired', ' Setup' => ' Setup', ' forever ' => ' forever ', ' from ' => ' from ', ' to ' => ' to ', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" can be ordered along with these products/subscripton(s) only: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" can only be ordered if you have expired subscription(s) for these products: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" cannot be ordered because you have active subscription(s) to: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" cannot be ordered because you have expired subscription(s) to: %s', '#' => '#', '$CONFIG[instanceid] value from ownCloud Config file' => '$CONFIG[instanceid] value from ownCloud Config file', '$CONFIG[passwordsalt] value from ownCloud Config file' => '$CONFIG[passwordsalt] value from ownCloud Config file', '%d access records…' => '%d access records…', '%d item(s) - %s' => '%d item(s) - %s', '%d items processed, %d users is unsubscribed. %sBack%s' => '%d items processed, %d users is unsubscribed. %sBack%s', '%d-Tier Affiliates Commission ' => '%d-Tier Affiliates Commission ', '%d-th day' => '%d-th day', '%s Additional Settings' => '%s Additional Settings', '%s Database name and Tables Prefix' => '%s Database name and Tables Prefix', '%s Integration Settings' => '%s Integration Settings', '%s MySQL Hostname' => '%s MySQL Hostname', '%s MySQL Password' => '%s MySQL Password', '%s MySQL Username' => '%s MySQL Username', '%s database and tables prefix' => '%s database and tables prefix', '%s records on this page are selected. You can choose group operation in the select box below or %scancel%s' => '%s records on this page are selected. You can choose group operation in the select box below or %scancel%s', '%sEnable%s and %sconfigure%s external cron if you are using credit card payment plugins' => '%sEnable%s and %sconfigure%s external cron if you are using credit card payment plugins', ', for %d installments' => ', for %d installments', ', then ' => ', then ', '-- Home --' => '-- Home --', '-- Please select --' => '-- Please select --', '2Factor (Authy.com)' => '2Factor (Authy.com)', '2Factor (Duosecurity.com)' => '2Factor (Duosecurity.com)', '2Factor Authentication' => '2Factor Authentication', '5-10 lowercase alphanumeriv characters' => '5-10 lowercase alphanumeriv characters', 'A duplicate transaction has been submitted. Please wait 2 minutes before next attempt' => 'A duplicate transaction has been submitted. Please wait 2 minutes before next attempt', 'A/B Signup' => 'A/B Signup', 'A/B Signup Form' => 'A/B Signup Form', 'A/B Signup Theme Pending' => 'A/B Signup Theme Pending', 'A/B Signup Theme Purchases' => 'A/B Signup Theme Purchases', 'A/B Signup Theme Visitors' => 'A/B Signup Theme Visitors', 'ABA Routing Number 9 digits' => 'ABA Routing Number 9 digits', 'API Authentication Information' => 'API Authentication Information', 'API Key' => 'API Key', 'API Key Get it from your SnappyCheckout Account Admin -> Settings -> API' => 'API Key Get it from your SnappyCheckout Account Admin -> Settings -> API', 'API Keyyour private API key' => 'API Keyyour private API key', 'API Token' => 'API Token', 'API hostname' => 'API hostname', 'Above Form' => 'Above Form', 'Above Form (Header)' => 'Above Form (Header)', 'Accept' => 'Accept', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)', 'Access' => 'Access', 'Access send email only if user has active subscription to these products. Leave it empty to send to all users' => 'Access send email only if user has active subscription to these products. Leave it empty to send to all users', 'Access Code will be included into URL to make it unique' => 'Access Code will be included into URL to make it unique', 'Access Denied' => 'Access Denied', 'Access Log' => 'Access Log', 'Access Permissions' => 'Access Permissions', 'Access mode' => 'Access mode', 'Account Alerts' => 'Account Alerts', 'Account Details' => 'Account Details', 'Account Holder first and last name' => 'Account Holder first and last name', 'Account Information' => 'Account Information', 'Account Name' => 'Account Name', 'Account Notifications' => 'Account Notifications', 'Account Number / IBAN' => 'Account Number / IBAN', 'Account holder name' => 'Account holder name', 'Account number' => 'Account number', 'Action on Simultaneous Login Attempt' => 'Action on Simultaneous Login Attempt', 'Actions' => 'Actions', 'Activate' => 'Activate', 'Activation' => 'Activation', 'Active' => 'Active', 'Active Resources' => 'Active Resources', 'Active Subscriptions' => 'Active Subscriptions', 'Active Users' => 'Active Users', 'Active Users by Period' => 'Active Users by Period', 'Active Users by Products' => 'Active Users by Products', 'Active subusers' => 'Active subusers', 'Add' => 'Add', 'Add "Like" button' => 'Add "Like" button', 'Add Access depends on current user\'s groups in ' => 'Add Access depends on current user\'s groups in ', 'Add Affiliate Points' => 'Add Affiliate Points', 'Add Attachments' => 'Add Attachments', 'Add Category Filter to Popup' => 'Add Category Filter to Popup', 'Add Coupon Code to Affiliates' => 'Add Coupon Code to Affiliates', 'Add Membership' => 'Add Membership', 'Add New Notification Rule' => 'Add New Notification Rule', 'Add Result for Previous Period' => 'Add Result for Previous Period', 'Add Result for Same Period in Previous Year' => 'Add Result for Same Period in Previous Year', 'Add Subscription Before Payment (HIDDEN)' => 'Add Subscription Before Payment (HIDDEN)', 'Add Subscription to the following products right after signup form has been submitted, subscription will be added only for new users' => 'Add Subscription to the following products right after signup form has been submitted, subscription will be added only for new users', 'Add Tax' => 'Add Tax', 'Add User' => 'Add User', 'Add User Stamp this option applicalable only to PDF files' => 'Add User Stamp this option applicalable only to PDF files', 'Add VAT Rates Group' => 'Add VAT Rates Group', 'Add VAT to all B2B payments Normally aMember will not add VAT to invoice if customer located in another country and specified valid VAT ID With that setting enabled, VAT will be applied in this situation too.' => 'Add VAT to all B2B payments Normally aMember will not add VAT to invoice if customer located in another country and specified valid VAT ID With that setting enabled, VAT will be applied in this situation too.', 'Add Widget With Uploaded Files To User Dashboard' => 'Add Widget With Uploaded Files To User Dashboard', 'Add an \'empty\' option to select box to do not choose any products' => 'Add an \'empty\' option to select box to do not choose any products', 'Add free access to a product if user signup from Facebook' => 'Add free access to a product if user signup from Facebook', 'Add hyperlink for Logo' => 'Add hyperlink for Logo', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)', 'Add the following product(s) on Expiration' => 'Add the following product(s) on Expiration', 'Add the following product(s) on Signup' => 'Add the following product(s) on Signup', 'Add to Basket' => 'Add to Basket', 'Add user to these groups' => 'Add user to these groups', 'Add/Renew Subscription' => 'Add/Renew Subscription', 'Added' => 'Added', 'Added During Import' => 'Added During Import', 'Added between dates:' => 'Added between dates:', 'Added during user creation by demand from plugin [%s]' => 'Added during user creation by demand from plugin [%s]', 'Additional Action' => 'Additional Action', 'Additional Fields' => 'Additional Fields', 'Address Details' => 'Address Details', 'Address Info' => 'Address Info', 'Address Info (must match your credit card statement delivery address)' => 'Address Info (must match your credit card statement delivery address)', 'Address Info (must match your debit card statement delivery address)' => 'Address Info (must match your debit card statement delivery address)', 'Address Information' => 'Address Information', 'Admin' => 'Admin', 'Admin E-Mail' => 'Admin E-Mail', 'Admin E-Mail Address' => 'Admin E-Mail Address', 'Admin First Name' => 'Admin First Name', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity', 'Admin Last Name' => 'Admin Last Name', 'Admin Username' => 'Admin Username', 'Administrator' => 'Administrator', 'Admins' => 'Admins', 'AdobeConnect' => 'AdobeConnect', 'Advanced' => 'Advanced', 'Advanced Search' => 'Advanced Search', 'Advertise our website to your friends and earn money' => 'Advertise our website to your friends and earn money', 'Affiliate' => 'Affiliate', 'Affiliate whenever coupons from this batch is used, commission will always be credited to this affiliate. This is true even when another affiliate is permanently tagged to the customer. For sales where the coupon is NOT used, the original (previous) affiliate will continue receiving commissions. If the customer has no affiliate, this affiliate will permanently be tagged to the customer, and will receive credit for future sales.' => 'Affiliate whenever coupons from this batch is used, commission will always be credited to this affiliate. This is true even when another affiliate is permanently tagged to the customer. For sales where the coupon is NOT used, the original (previous) affiliate will continue receiving commissions. If the customer has no affiliate, this affiliate will permanently be tagged to the customer, and will receive credit for future sales.', 'Affiliate Affiliate Link' => 'Affiliate Affiliate Link', 'Affiliate Agreement' => 'Affiliate Agreement', 'Affiliate BACS - Account holder name' => 'Affiliate BACS - Account holder name', 'Affiliate BACS - Account number' => 'Affiliate BACS - Account number', 'Affiliate BACS - Bank name' => 'Affiliate BACS - Bank name', 'Affiliate BACS - Sort code' => 'Affiliate BACS - Sort code', 'Affiliate Bonus Link' => 'Affiliate Bonus Link', 'Affiliate Check - City' => 'Affiliate Check - City', 'Affiliate Check - Country' => 'Affiliate Check - Country', 'Affiliate Check - Payable To' => 'Affiliate Check - Payable To', 'Affiliate Check - State' => 'Affiliate Check - State', 'Affiliate Check - Street Address' => 'Affiliate Check - Street Address', 'Affiliate Check - ZIP Code' => 'Affiliate Check - ZIP Code', 'Affiliate Chexx - Account Holder Name' => 'Affiliate Chexx - Account Holder Name', 'Affiliate Chexx - BIC' => 'Affiliate Chexx - BIC', 'Affiliate Chexx - IBAN' => 'Affiliate Chexx - IBAN', 'Affiliate Chexx - Payment Routing Number' => 'Affiliate Chexx - Payment Routing Number', 'Affiliate Clicks' => 'Affiliate Clicks', 'Affiliate Clicks for' => 'Affiliate Clicks for', 'Affiliate Coupons' => 'Affiliate Coupons', 'Affiliate Group IN (%s)' => 'Affiliate Group IN (%s)', 'Affiliate Id#' => 'Affiliate Id#', 'Affiliate Info' => 'Affiliate Info', 'Affiliate Keywords' => 'Affiliate Keywords', 'Affiliate Leads' => 'Affiliate Leads', 'Affiliate Link' => 'Affiliate Link', 'Affiliate Manager this user always will be assigned as 2-tier affiliate for all affiliates' => 'Affiliate Manager this user always will be assigned as 2-tier affiliate for all affiliates', 'Affiliate Payout - Bitcoin Wallet' => 'Affiliate Payout - Bitcoin Wallet', 'Affiliate Payout - Okpay Wallet ID' => 'Affiliate Payout - Okpay Wallet ID', 'Affiliate Payout - Pagseguro E-Mail address' => 'Affiliate Payout - Pagseguro E-Mail address', 'Affiliate Payout - Paypal E-Mail address' => 'Affiliate Payout - Paypal E-Mail address', 'Affiliate Payout - Propay E-Mail address' => 'Affiliate Payout - Propay E-Mail address', 'Affiliate Payout - Skrill Account ID' => 'Affiliate Payout - Skrill Account ID', 'Affiliate Payout - WM purse' => 'Affiliate Payout - WM purse', 'Affiliate Payout Amount by User' => 'Affiliate Payout Amount by User', 'Affiliate Payout Type' => 'Affiliate Payout Type', 'Affiliate Payouts' => 'Affiliate Payouts', 'Affiliate Program' => 'Affiliate Program', 'Affiliate Sales' => 'Affiliate Sales', 'Affiliate Sales Number' => 'Affiliate Sales Number', 'Affiliate Signup Form' => 'Affiliate Signup Form', 'Affiliate Source' => 'Affiliate Source', 'Affiliate Tier' => 'Affiliate Tier', 'Affiliate commission to %s' => 'Affiliate commission to %s', 'Affiliate commission up to %s' => 'Affiliate commission up to %s', 'Affiliate generated %d item sales last %d days' => 'Affiliate generated %d item sales last %d days', 'Affiliate generated %d sales last %d days' => 'Affiliate generated %d sales last %d days', 'Affiliate generated %d%s in commissions last %d days' => 'Affiliate generated %d%s in commissions last %d days', 'Affiliate has Products IN (%s)' => 'Affiliate has Products IN (%s)', 'Affiliate has Products from Category IN (%s)' => 'Affiliate has Products from Category IN (%s)', 'Affiliate info' => 'Affiliate info', 'Affiliate link with Custom Landing Page' => 'Affiliate link with Custom Landing Page', 'Affiliate points' => 'Affiliate points', 'Affiliate points current' => 'Affiliate points current', 'Affiliate points total' => 'Affiliate points total', 'Affiliate stats' => 'Affiliate stats', 'Affiliates' => 'Affiliates', 'After Purchase Display this content on thank you page You can use %invoice.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.' => 'After Purchase Display this content on thank you page You can use %invoice.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.', 'After Purchase Redirect User to this URL instead of thanks page You can use %root_url%, %root_surl%, %invoice.%, %product.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.' => 'After Purchase Redirect User to this URL instead of thanks page You can use %root_url%, %root_surl%, %invoice.%, %product.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.', 'After first payment has been completed' => 'After first payment has been completed', 'After the user has been added' => 'After the user has been added', 'Agreement text' => 'Agreement text', 'All' => 'All', 'All %s records on this page are selected' => 'All %s records on this page are selected', 'All Affiliates' => 'All Affiliates', 'All Categories' => 'All Categories', 'All Clicks' => 'All Clicks', 'All Downloads History Report' => 'All Downloads History Report', 'All Files' => 'All Files', 'All Time' => 'All Time', 'All Users' => 'All Users', 'All achieved affiliate points' => 'All achieved affiliate points', 'All records' => 'All records', 'All/Unique Clicks' => 'All/Unique Clicks', 'Allow Affiliate to redirect Referrers to any url' => 'Allow Affiliate to redirect Referrers to any url', 'Allow Instant Commission functionality for all affiliates By default instant commissions will be enabled only if you enable this in affiliate profile' => 'Allow Instant Commission functionality for all affiliates By default instant commissions will be enabled only if you enable this in affiliate profile', 'Allow Login via IP Address' => 'Allow Login via IP Address', 'Allow payment if anonymous proxy Whether IP address is %sAnonymous Proxy%s (anonymous proxy = very high risk)' => 'Allow payment if anonymous proxy Whether IP address is %sAnonymous Proxy%s (anonymous proxy = very high risk)', 'Allow payment if country not matched Whether country of IP address matches billing address country (mismatch = higher risk)' => 'Allow payment if country not matched Whether country of IP address matches billing address country (mismatch = higher risk)', 'Allow payment if free e-mail Whether e-mail is from free e-mail provider (free e-mail = higher risk)' => 'Allow payment if free e-mail Whether e-mail is from free e-mail provider (free e-mail = higher risk)', 'Allow payment if high risk countries Whether IP address or billing address country is in Egypt, Ghana, Indonesia, Lebanon, Macedonia, Morocco, Nigeria, Pakistan, Romania, Serbia and Montenegro, Ukraine, or Vietnam' => 'Allow payment if high risk countries Whether IP address or billing address country is in Egypt, Ghana, Indonesia, Lebanon, Macedonia, Morocco, Nigeria, Pakistan, Romania, Serbia and Montenegro, Ukraine, or Vietnam', 'Allow to Search Directory by the following Fields' => 'Allow to Search Directory by the following Fields', 'Allow to export Leads' => 'Allow to export Leads', 'Allow to filter Leads' => 'Allow to filter Leads', 'Allowed Phone Types The TNI service is able to categorize customer inputted US and Canadian phone numbers into %seight different phone types%s such as fixed land line, mobile, VoIP, and invalid phone numbers' => 'Allowed Phone Types The TNI service is able to categorize customer inputted US and Canadian phone numbers into %seight different phone types%s such as fixed land line, mobile, VoIP, and invalid phone numbers', 'Already in Basket' => 'Already in Basket', 'Alternate' => 'Alternate', 'Always' => 'Always', 'Amazon S3 storage is not configured' => 'Amazon S3 storage is not configured', 'Amount' => 'Amount', 'Amount Paid' => 'Amount Paid', 'An Error has occurred' => 'An Error has occurred', 'An account with the same email [%s] is already exists.' => 'An account with the same email [%s] is already exists.', 'An account with the same email already exists.' => 'An account with the same email already exists.', 'An error occurred while cancellation request' => 'An error occurred while cancellation request', 'An error occurred while handling your payment or you cancelled it.' => 'An error occurred while handling your payment or you cancelled it.', 'An error occurred while handling your payment.' => 'An error occurred while handling your payment.', 'An internal error happened in the script, please contact webmaster for details' => 'An internal error happened in the script, please contact webmaster for details', 'Anti Spam' => 'Anti Spam', 'Anti Spam check failed' => 'Anti Spam check failed', 'Any' => 'Any', 'Any Product' => 'Any Product', 'Any product' => 'Any product', 'Api Key' => 'Api Key', 'Application' => 'Application', 'Apply' => 'Apply', 'Apply Coupon (optional)' => 'Apply Coupon (optional)', 'Apply Filter' => 'Apply Filter', 'Apply to recurring? apply coupon discount to recurring rebills' => 'Apply to recurring? apply coupon discount to recurring rebills', 'As Is' => 'As Is', 'Assign Group' => 'Assign Group', 'Assign JACL Group' => 'Assign JACL Group', 'Assign JomSocial Group' => 'Assign JomSocial Group', 'Assign User Groups (HIDDEN)' => 'Assign User Groups (HIDDEN)', 'Assign this Ticket to yourself' => 'Assign this Ticket to yourself', 'Assigned by Administrator %s at %s' => 'Assigned by Administrator %s at %s', 'Assigned by COOKIE at %s' => 'Assigned by COOKIE at %s', 'Assigned by Coupon %s at %s' => 'Assigned by Coupon %s at %s', 'Assigned by IP %s at %s' => 'Assigned by IP %s at %s', 'Assigned by Invoice %s at %s' => 'Assigned by Invoice %s at %s', 'Assigned to usergroup' => 'Assigned to usergroup', 'Attach File' => 'Attach File', 'Attachments' => 'Attachments', 'Authentication' => 'Authentication', 'Authentication problem, please contact website administrator' => 'Authentication problem, please contact website administrator', 'Authorize.NET eCheck' => 'Authorize.NET eCheck', 'Authy Token' => 'Authy Token', 'Auto Login Link' => 'Auto Login Link', 'Auto-Responder' => 'Auto-Responder', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Auto-Subscribe users to list once it becomes accessible for them', 'Auto-generated Template Settings' => 'Auto-generated Template Settings', 'Available Bricks (drag to left to add)' => 'Available Bricks (drag to left to add)', 'Available Credits' => 'Available Credits', 'Avatar' => 'Avatar', 'Avatar Size width×height' => 'Avatar Size width×height', 'Average Lifetime Value' => 'Average Lifetime Value', 'Average Lifetime Value (Cohort Analysis)' => 'Average Lifetime Value (Cohort Analysis)', 'Avoid using standard layout you have to design entire page in the \'Offer Text\' field' => 'Avoid using standard layout you have to design entire page in the \'Offer Text\' field', 'Awaiting Admin Response' => 'Awaiting Admin Response', 'Awaiting User Response' => 'Awaiting User Response', 'Aweber Application' => 'Aweber Application', 'BACS' => 'BACS', 'BIC' => 'BIC', 'Back' => 'Back', 'Back to shopping' => 'Back to shopping', 'Bad URL, enter the correct OpenGate URL' => 'Bad URL, enter the correct OpenGate URL', 'Balance' => 'Balance', 'Bank Account Name name associated with the bank account' => 'Bank Account Name name associated with the bank account', 'Bank Account Number' => 'Bank Account Number', 'Bank Account Number Up to 20 digits' => 'Bank Account Number Up to 20 digits', 'Bank Account Type please select one' => 'Bank Account Type please select one', 'Bank Code' => 'Bank Code', 'Bank Details' => 'Bank Details', 'Bank Identification' => 'Bank Identification', 'Bank Name' => 'Bank Name', 'Bank Name name of the bank which issued the credit card' => 'Bank Name name of the bank which issued the credit card', 'Bank Phone customer service phone number listed on back of your credit card' => 'Bank Phone customer service phone number listed on back of your credit card', 'Bank code / BIC' => 'Bank code / BIC', 'Bank name' => 'Bank name', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity', 'Banners and Links' => 'Banners and Links', 'Banners and Text Links' => 'Banners and Text Links', 'Batch for Affiliate Coupons new coupons for affiliate will be generated in this batch' => 'Batch for Affiliate Coupons new coupons for affiliate will be generated in this batch', 'Begin' => 'Begin', 'Begin Date' => 'Begin Date', 'Below Form' => 'Below Form', 'Below Form (Footer)' => 'Below Form (Footer)', 'Between Dates' => 'Between Dates', 'Billing Address' => 'Billing Address', 'Billing Address must match your credit card statement delivery address' => 'Billing Address must match your credit card statement delivery address', 'Billing International Province for international provinces outside of US & Canada include the province name here' => 'Billing International Province for international provinces outside of US & Canada include the province name here', 'Billing Name Billing Address First and Last name' => 'Billing Name Billing Address First and Last name', 'Billing Plan' => 'Billing Plan', 'Billing Plan(s) to display' => 'Billing Plan(s) to display', 'Bonus' => 'Bonus', 'Bonuses' => 'Bonuses', 'Both Affiliate and member' => 'Both Affiliate and member', 'Bounces' => 'Bounces', 'Branch Sort Code' => 'Branch Sort Code', 'Brick Position' => 'Brick Position', 'Browse Events' => 'Browse Events', 'Bruteforce Notification' => 'Bruteforce Notification', 'Bulk Actions' => 'Bulk Actions', 'Bundle Discount' => 'Bundle Discount', 'Button Title' => 'Button Title', 'CC Demo' => 'CC Demo', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat', 'CSS Selector for conteiner' => 'CSS Selector for conteiner', 'CSV File was not specified' => 'CSV File was not specified', 'Campaign' => 'Campaign', 'Can Operate with Notifications' => 'Can Operate with Notifications', 'Can Operate with OTO' => 'Can Operate with OTO', 'Can add/edit/delete Milestones' => 'Can add/edit/delete Milestones', 'Can manage software licenses' => 'Can manage software licenses', 'Can manage software licensing schemes' => 'Can manage software licensing schemes', 'Can manage webhooks' => 'Can manage webhooks', 'Can not handle this billing terms' => 'Can not handle this billing terms', 'Can not handle this billing terms: first_period != second_period' => 'Can not handle this billing terms: first_period != second_period', 'Can not handle this billing terms: first_total is zero' => 'Can not handle this billing terms: first_total is zero', 'Can not handle this billing terms: not in possible periods' => 'Can not handle this billing terms: not in possible periods', 'Can not handle this billing terms: rebill time must be forever' => 'Can not handle this billing terms: rebill time must be forever', 'Can view/edit customer Credit Card information and rebills' => 'Can view/edit customer Credit Card information and rebills', 'Can\'t obtaint OAuth2 token' => 'Can\'t obtaint OAuth2 token', 'Cancel' => 'Cancel', 'Cancel Feedback' => 'Cancel Feedback', 'Cancel Subscription' => 'Cancel Subscription', 'Cancelation Reason' => 'Cancelation Reason', 'Cancellation Feedback' => 'Cancellation Feedback', 'Cancellation Reason' => 'Cancellation Reason', 'Cancellation Reasons' => 'Cancellation Reasons', 'Cancelled' => 'Cancelled', 'Cannot connect to database. Check hostname, username and password settings' => 'Cannot connect to database. Check hostname, username and password settings', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Cannot use FREE payment plugin with a product which cost more than 0.0', 'Cannot validate VAT Id, please try again' => 'Cannot validate VAT Id, please try again', 'Card Amount' => 'Card Amount', 'Card Expire Card expiration date - month and year' => 'Card Expire Card expiration date - month and year', 'Card Expire Month and Year' => 'Card Expire Month and Year', 'Card Expire Select card expiration date - month and year' => 'Card Expire Select card expiration date - month and year', 'Card Expires' => 'Card Expires', 'Card Issue # is required for Maestro/Solo/Switch credit cards only' => 'Card Issue # is required for Maestro/Solo/Switch credit cards only', 'Card Start Date is required for Maestro/Solo/Switch credit cards only' => 'Card Start Date is required for Maestro/Solo/Switch credit cards only', 'Card code is either invalid or alredy used' => 'Card code is either invalid or alredy used', 'Cardholder Name cardholder first and last name, exactly as on the card' => 'Cardholder Name cardholder first and last name, exactly as on the card', 'Catalog Prices Include Tax' => 'Catalog Prices Include Tax', 'Categories' => 'Categories', 'Category' => 'Category', 'Category [%s] not found' => 'Category [%s] not found', 'Category of question' => 'Category of question', 'Center' => 'Center', 'Change' => 'Change', 'Change Category' => 'Change Category', 'Change Manager' => 'Change Manager', 'Change Owner' => 'Change Owner', 'Change Password' => 'Change Password', 'Change Password/Edit Profile' => 'Change Password/Edit Profile', 'Change Subscription' => 'Change Subscription', 'Change Title' => 'Change Title', 'Change Username' => 'Change Username', 'Change Your Password' => 'Change Your Password', 'Change payout info' => 'Change payout info', 'Changes in User Profile' => 'Changes in User Profile', 'Check Payable To' => 'Check Payable To', 'Checkboxes (multiple products can be selected)' => 'Checkboxes (multiple products can be selected)', 'Checkboxes for Selected Lists' => 'Checkboxes for Selected Lists', 'Checked' => 'Checked', 'Checkout' => 'Checkout', 'Checkout Secret Key at paddle.com' => 'Checkout Secret Key at paddle.com', 'Checkout error: ' => 'Checkout error: ', 'Checkout payment' => 'Checkout payment', 'Chexx' => 'Chexx', 'Choose New Password must be %d or more characters' => 'Choose New Password must be %d or more characters', 'Choose a Password must be %d or more characters' => 'Choose a Password must be %d or more characters', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores', 'Choose admins to include to roster You can choose same admin several times to balance tickets accordingly' => 'Choose admins to include to roster You can choose same admin several times to balance tickets accordingly', 'Choose another payment processor or try again with the same.' => 'Choose another payment processor or try again with the same.', 'Choose date Period to rebuild' => 'Choose date Period to rebuild', 'Choose products to include into test invoice' => 'Choose products to include into test invoice', 'Churn Rate' => 'Churn Rate', 'City' => 'City', 'City ' => 'City ', 'Clear Pending Invoices' => 'Clear Pending Invoices', 'Click "Continue" to pay this order using stored credit card %s' => 'Click "Continue" to pay this order using stored credit card %s', 'Click Here if you have already sent Bitcoins' => 'Click Here if you have already sent Bitcoins', 'Click Url' => 'Click Url', 'Click button to continue' => 'Click button to continue', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).', 'Click to Assign' => 'Click to Assign', 'Click to Edit' => 'Click to Edit', 'ClickBank is the retailer of products on this site. CLICKBANK® is a registered trademark of Click Sales, Inc., a Delaware corporation located at 917 S. Lusk Street, Suite 200, Boise Idaho, 83706, USA and used by permission. ClickBank\'s role as retailer does not constitute an endorsement, approval or review of these products or any claim, statement or opinion used in promotion of these products.' => 'ClickBank is the retailer of products on this site. CLICKBANK® is a registered trademark of Click Sales, Inc., a Delaware corporation located at 917 S. Lusk Street, Suite 200, Boise Idaho, 83706, USA and used by permission. ClickBank\'s role as retailer does not constitute an endorsement, approval or review of these products or any claim, statement or opinion used in promotion of these products.', 'Clicks' => 'Clicks', 'Clicks (All)' => 'Clicks (All)', 'Clicks (Unique)' => 'Clicks (Unique)', 'Clicks/Sales Statistics' => 'Clicks/Sales Statistics', 'Close' => 'Close', 'Close This Ticket After Response' => 'Close This Ticket After Response', 'Close Ticket' => 'Close Ticket', 'Close Ticket(s)' => 'Close Ticket(s)', 'Closed' => 'Closed', 'Code' => 'Code', 'Code is invalid' => 'Code is invalid', 'Comment' => 'Comment', 'Comment for admin reference' => 'Comment for admin reference', 'Comment for your reference' => 'Comment for your reference', 'Comment will be shown above table with users' => 'Comment will be shown above table with users', 'Comments? (Optional)' => 'Comments? (Optional)', 'Commission' => 'Commission', 'Commission Earned' => 'Commission Earned', 'Commission Rules' => 'Commission Rules', 'Commissions' => 'Commissions', 'Company Logo for Invoice it must be png/jpeg/tiff file' => 'Company Logo for Invoice it must be png/jpeg/tiff file', 'Company Name the company name associated with the billing address for the transaction' => 'Company Name the company name associated with the billing address for the transaction', 'Complete Payment' => 'Complete Payment', 'Completed' => 'Completed', 'Condition' => 'Condition', 'Conditional' => 'Conditional', 'Conditions After actual payment aMember will check user invoice and in case of it contains one of defined product or product from defined product category this OTO will be shown for him instead of ordinary thank you page. In case of you use OTO (Downsell) condition it will be matched if user click NO link in defined offer and this OTO will be shown for user' => 'Conditions After actual payment aMember will check user invoice and in case of it contains one of defined product or product from defined product category this OTO will be shown for him instead of ordinary thank you page. In case of you use OTO (Downsell) condition it will be matched if user click NO link in defined offer and this OTO will be shown for user', 'Conditions/Commissions' => 'Conditions/Commissions', 'Configuration' => 'Configuration', 'Configured Tax Values' => 'Configured Tax Values', 'Confirm' => 'Confirm', 'Confirm Billing Country' => 'Confirm Billing Country', 'Confirm E-Mail Address second field will be displayed to enter email address twice' => 'Confirm E-Mail Address second field will be displayed to enter email address twice', 'Confirm New Password' => 'Confirm New Password', 'Confirm Password' => 'Confirm Password', 'Confirm Payment' => 'Confirm Payment', 'Confirm Your E-Mail Address' => 'Confirm Your E-Mail Address', 'Confirm Your Password' => 'Confirm Your Password', 'Confirm download' => 'Confirm download', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.', 'Consider only initial purchase disregard subsequent recurring payments' => 'Consider only initial purchase disregard subsequent recurring payments', 'Content' => 'Content', 'Content You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.' => 'Content You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.', 'Content Categories' => 'Content Categories', 'Content Categories these categories will be shown in user\'s menu if user has access to resources in this category. You can uses these categories to organize your content by pages' => 'Content Categories these categories will be shown in user\'s menu if user has access to resources in this category. You can uses these categories to organize your content by pages', 'Continue' => 'Continue', 'Continue Shopping' => 'Continue Shopping', 'Conversation' => 'Conversation', 'Copy of' => 'Copy of', 'Corrective Invoice Number: ' => 'Corrective Invoice Number: ', 'Count' => 'Count', 'Count Free item to match discount?' => 'Count Free item to match discount?', 'Count conversion for these products only' => 'Count conversion for these products only', 'Count of Messages' => 'Count of Messages', 'Count of Pending Invoices' => 'Count of Pending Invoices', 'Count of User Messages in Helpdesk' => 'Count of User Messages in Helpdesk', 'Count of product purchase' => 'Count of product purchase', 'Count of signups' => 'Count of signups', 'Count of user signups' => 'Count of user signups', 'Country' => 'Country', 'Country Title' => 'Country Title', 'Coupon' => 'Coupon', 'Coupon Batch' => 'Coupon Batch', 'Coupon Batch create coupons in this batch as invite codes' => 'Coupon Batch create coupons in this batch as invite codes', 'Coupon Code' => 'Coupon Code', 'Coupon Discount' => 'Coupon Discount', 'Coupon can be used only if you have active subscription for these products: %s' => 'Coupon can be used only if you have active subscription for these products: %s', 'Coupon can be used only if you have expired subscription(s) for these products: %s' => 'Coupon can be used only if you have expired subscription(s) for these products: %s', 'Coupon cannot be used because you have active subscription(s) to: %s' => 'Coupon cannot be used because you have active subscription(s) to: %s', 'Coupon cannot be used because you have expired subscription(s) to: %s' => 'Coupon cannot be used because you have expired subscription(s) to: %s', 'Coupon code disabled' => 'Coupon code disabled', 'Coupon code expired' => 'Coupon code expired', 'Coupon is not yet active' => 'Coupon is not yet active', 'Coupon usage limit exceeded' => 'Coupon usage limit exceeded', 'Coupons one coupon per line' => 'Coupons one coupon per line', 'Coupons Batch' => 'Coupons Batch', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s', 'Created' => 'Created', 'Credit Card Code' => 'Credit Card Code', 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards)' => 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards)', 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).' => 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).', 'Credit Card Info' => 'Credit Card Info', 'Credit Card Number' => 'Credit Card Number', 'Credit Card Number for example: 1111-2222-3333-4444' => 'Credit Card Number for example: 1111-2222-3333-4444', 'Credit Card Rebills' => 'Credit Card Rebills', 'Credit Card Type please select one' => 'Credit Card Type please select one', 'Credit Cards' => 'Credit Cards', 'Credits' => 'Credits', 'Credits Balance' => 'Credits Balance', 'Credits History' => 'Credits History', 'Credits spent by products breakdown' => 'Credits spent by products breakdown', 'Currency' => 'Currency', 'Currency which currencies to fetch' => 'Currency which currencies to fetch', 'Currency you can choose from list of currencies supported by paysystems' => 'Currency you can choose from list of currencies supported by paysystems', 'Currency Code' => 'Currency Code', 'Currency Exchange Rates' => 'Currency Exchange Rates', 'Current Credit Card Info' => 'Current Credit Card Info', 'Current affiliate points' => 'Current affiliate points', 'Current password entered incorrectly, please try again' => 'Current password entered incorrectly, please try again', 'Custom Bold Font for Invoice (optional) Useful for invoices with non-Latin symbols when there is a problem with displaying such symbols in the PDF invoice.Please upload .ttf file only.' => 'Custom Bold Font for Invoice (optional) Useful for invoices with non-Latin symbols when there is a problem with displaying such symbols in the PDF invoice.Please upload .ttf file only.', 'Custom Commission' => 'Custom Commission', 'Custom Element' => 'Custom Element', 'Custom Font for Invoice (optional) Useful for invoices with non-Latin symbols when there is a problem with displaying such symbols in the PDF invoice. Please upload .ttf file only.' => 'Custom Font for Invoice (optional) Useful for invoices with non-Latin symbols when there is a problem with displaying such symbols in the PDF invoice. Please upload .ttf file only.', 'Custom PDF Template for Invoice (optional)' => 'Custom PDF Template for Invoice (optional)', 'Custom Template Settings' => 'Custom Template Settings', 'Customer account has been automatically locked.' => 'Customer account has been automatically locked.', 'Customize' => 'Customize', 'DONE' => 'DONE', 'Dashboard' => 'Dashboard', 'Data Integrity Code' => 'Data Integrity Code', 'Database name or prefix is wrong - could not find table [%s] with fields [%s] inside database [%s]:' => 'Database name or prefix is wrong - could not find table [%s] with fields [%s] inside database [%s]:', 'Date' => 'Date', 'Date and time of payment: %s' => 'Date and time of payment: %s', 'Date must be in format %s' => 'Date must be in format %s', 'Date of First Collection' => 'Date of First Collection', 'Date/Time' => 'Date/Time', 'Date: ' => 'Date: ', 'Dates date range when notification is shown' => 'Dates date range when notification is shown', 'Day' => 'Day', 'Day of Notification Sending' => 'Day of Notification Sending', 'Days' => 'Days', 'Deactivate Student' => 'Deactivate Student', 'Deactivate User' => 'Deactivate User', 'Debit Card Number' => 'Debit Card Number', 'Decline all transactions Plugin will decline all payment attempts' => 'Decline all transactions Plugin will decline all payment attempts', 'Decrease Affiliate Points' => 'Decrease Affiliate Points', 'Default' => 'Default', 'Default Avatar' => 'Default Avatar', 'Default Coupon Batch placeholder %coupon% will be replaced with coupon code from this batch' => 'Default Coupon Batch placeholder %coupon% will be replaced with coupon code from this batch', 'Default Home Folder' => 'Default Home Folder', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)', 'Default Level users created by demand will have access to the sele (for example all subscriptions expired)' => 'Default Level users created by demand will have access to the sele (for example all subscriptions expired)', 'Default Order By' => 'Default Order By', 'Default Product' => 'Default Product', 'Default Product access to this product will be added if customer has not any other active subscription and vise versa access to this product will be removed if customer signup to any other product' => 'Default Product access to this product will be added if customer has not any other active subscription and vise versa access to this product will be removed if customer signup to any other product', 'Default Value for this field hidden field will be populated with this value' => 'Default Value for this field hidden field will be populated with this value', 'Default amount of donation' => 'Default amount of donation', 'Default unchecked Leave unchecked if you want newsletter default to be checked' => 'Default unchecked Leave unchecked if you want newsletter default to be checked', 'Define Custom Html Message' => 'Define Custom Html Message', 'Delete' => 'Delete', 'Delete %s' => 'Delete %s', 'Delete This VAT Rates Group' => 'Delete This VAT Rates Group', 'Delete User Account' => 'Delete User Account', 'Delete other session when user try to login from new one' => 'Delete other session when user try to login from new one', 'Delivery Time' => 'Delivery Time', 'Description' => 'Description', 'Detail Page Fields link to details page will be displayed if any fields are selected here' => 'Detail Page Fields link to details page will be displayed if any fields are selected here', 'Detail Page Template alternative template for detail page' => 'Detail Page Template alternative template for detail page', 'Device' => 'Device', 'Did\'t Use Any Coupon' => 'Did\'t Use Any Coupon', 'Did\'t Use Coupon from Batch: %s' => 'Did\'t Use Coupon from Batch: %s', 'Did\'t Use Coupon with Code: %s' => 'Did\'t Use Coupon with Code: %s', 'Digits only please' => 'Digits only please', 'Dime Sale: First Price Ceiling' => 'Dime Sale: First Price Ceiling', 'Dime Sale: First Price Increment' => 'Dime Sale: First Price Increment', 'Dime Sale: Next Price Level' => 'Dime Sale: Next Price Level', 'Dime Sale: Number' => 'Dime Sale: Number', 'Dime Sale: Second Price Ceiling' => 'Dime Sale: Second Price Ceiling', 'Dime Sale: Second Price Increment' => 'Dime Sale: Second Price Increment', 'Dime Sale: Start Date' => 'Dime Sale: Start Date', 'Dime Sale: Type' => 'Dime Sale: Type', 'Direct Debit Reference: %s' => 'Direct Debit Reference: %s', 'Direct Debits are not available in your country (%s)' => 'Direct Debits are not available in your country (%s)', 'DirectOne Merchant ID your directone 9-digit merchant id' => 'DirectOne Merchant ID your directone 9-digit merchant id', 'DirectOne Password it is special password which can be set via the Settings page of the Members section on the DirectOne website' => 'DirectOne Password it is special password which can be set via the Settings page of the Members section on the DirectOne website', 'Directory Access' => 'Directory Access', 'Disable' => 'Disable', 'Disable Ability to Update Profile in case of user logged in via IP' => 'Disable Ability to Update Profile in case of user logged in via IP', 'Disable Single Login Session Protection' => 'Disable Single Login Session Protection', 'Disable login via IP if this box is checked, login via IP will not work for your account' => 'Disable login via IP if this box is checked, login via IP will not work for your account', 'Disable online VAT Id Validation' => 'Disable online VAT Id Validation', 'Disabled' => 'Disabled', 'Discard' => 'Discard', 'Discount' => 'Discount', 'Discount this discount will be applied to total of invoice. In case of discount is more than total - discount will be ignored. if user use coupon with purchase - max discount will be used' => 'Discount this discount will be applied to total of invoice. In case of discount is more than total - discount will be ignored. if user use coupon with purchase - max discount will be used', 'Discount Rule' => 'Discount Rule', 'Display' => 'Display', 'Display All Affiliate Coupons' => 'Display All Affiliate Coupons', 'Display All Products' => 'Display All Products', 'Display It Anyway' => 'Display It Anyway', 'Display Link Invite a Friend in Active Resources block' => 'Display Link Invite a Friend in Active Resources block', 'Display Link Invite a Friend in Useful Links block' => 'Display Link Invite a Friend in Useful Links block', 'Display List of Invited Users in customer account' => 'Display List of Invited Users in customer account', 'Display Products in Popup' => 'Display Products in Popup', 'Display Separate Block on customer dashboard' => 'Display Separate Block on customer dashboard', 'Display Separate Invoice for Refunds Setting affect aMember Control Panel only. User will see regular invoice which includes refund information inside' => 'Display Separate Invoice for Refunds Setting affect aMember Control Panel only. User will see regular invoice which includes refund information inside', 'Display Type' => 'Display Type', 'Display in 2 rows' => 'Display in 2 rows', 'Display name publicly as' => 'Display name publicly as', 'Display new Terms only active users of leave empty to show for all users' => 'Display new Terms only active users of leave empty to show for all users', 'Disregard' => 'Disregard', 'Do Import' => 'Do Import', 'Do not Include Subscription Terms to PDF Invoice' => 'Do not Include Subscription Terms to PDF Invoice', 'Do not add to Login Form' => 'Do not add to Login Form', 'Do not add to Signup Form' => 'Do not add to Signup Form', 'Do not check Access Permissions for this field on this form (show it without any conditions)' => 'Do not check Access Permissions for this field on this form (show it without any conditions)', 'Do not create coupon for affiliate' => 'Do not create coupon for affiliate', 'Do not require to fill in these fields' => 'Do not require to fill in these fields', 'Do not show \'Credits Balance\' link at Useful Links' => 'Do not show \'Credits Balance\' link at Useful Links', 'Do not show \'Credits History\' tab at User Menu' => 'Do not show \'Credits History\' tab at User Menu', 'Do you really want to %s %s %s records' => 'Do you really want to %s %s %s records', 'Do you really want to %s?' => 'Do you really want to %s?', 'Do you really want to cancel subscription?' => 'Do you really want to cancel subscription?', 'Do you really want to delete record?' => 'Do you really want to delete record?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Do you really want to unsubscribe from %s periodical messages?', 'Do you really want to void commission?' => 'Do you really want to void commission?', 'Does not Ask Current Password user will not need to enter his current password to change it' => 'Does not Ask Current Password user will not need to enter his current password to change it', 'Does not Confirm Password second field will not be displayed to enter password twice' => 'Does not Confirm Password second field will not be displayed to enter password twice', 'Does not allow to Copy&Paste to confirmation field' => 'Does not allow to Copy&Paste to confirmation field', 'Does not allow to close notification' => 'Does not allow to close notification', 'Does not show Agreement Text display only tick box' => 'Does not show Agreement Text display only tick box', 'Donation Amount %s' => 'Donation Amount %s', 'Donation Product Product which will be added to user\'s account' => 'Donation Product Product which will be added to user\'s account', 'Done' => 'Done', 'Donee' => 'Donee', 'Donee name' => 'Donee name', 'Donee\'s Invoice' => 'Donee\'s Invoice', 'Download' => 'Download', 'Download Files (.zip)' => 'Download Files (.zip)', 'Download Invoices (.pdf)' => 'Download Invoices (.pdf)', 'Download Invoices As Single File (.pdf)' => 'Download Invoices As Single File (.pdf)', 'Download Report (CSV File)' => 'Download Report (CSV File)', 'Download Transaction (CSV File)' => 'Download Transaction (CSV File)', 'Download limit exceeded for this file' => 'Download limit exceeded for this file', 'Downloaded on your own server' => 'Downloaded on your own server', 'Downloads' => 'Downloads', 'Downloads History' => 'Downloads History', 'Downloads History Report per File' => 'Downloads History Report per File', 'Downloads History Report per User' => 'Downloads History Report per User', 'Downloads by files breakdown' => 'Downloads by files breakdown', 'Drag&Drop rows to change display order. You may want to temporary change setting \'%sRecords per Page (for grids)%s\' to some big value so all records were on one page and you can arrange all items.' => 'Drag&Drop rows to change display order. You may want to temporary change setting \'%sRecords per Page (for grids)%s\' to some big value so all records were on one page and you can arrange all items.', 'Drop Me' => 'Drop Me', 'E-Mail' => 'E-Mail', 'E-Mail Address' => 'E-Mail Address', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both', 'E-Mail Format' => 'E-Mail Format', 'E-Mail Messages' => 'E-Mail Messages', 'E-Mail Notification by Category' => 'E-Mail Notification by Category', 'E-Mail Verification' => 'E-Mail Verification', 'EU VAT' => 'EU VAT', 'EU VAT ID: ' => 'EU VAT ID: ', 'EU VAT Id (optional)' => 'EU VAT Id (optional)', 'EU VAT Report' => 'EU VAT Report', 'Echeck' => 'Echeck', 'Edit' => 'Edit', 'Edit %s' => 'Edit %s', 'Edit Brick Labels' => 'Edit Brick Labels', 'Edit Categories' => 'Edit Categories', 'Edit E-Mail Template' => 'Edit E-Mail Template', 'Edit Profile Form' => 'Edit Profile Form', 'Edit Your Cart' => 'Edit Your Cart', 'Electronically Supplied Service Enable if ALL your products are electronic services.' => 'Electronically Supplied Service Enable if ALL your products are electronic services.', 'Electronically Supplied Service Enable if your product is an electronic service.' => 'Electronically Supplied Service Enable if your product is an electronic service.', 'Email' => 'Email', 'Email Address' => 'Email Address', 'Email Confirmation URL' => 'Email Confirmation URL', 'Email Link' => 'Email Link', 'Email Placeholder' => 'Email Placeholder', 'Email Subject' => 'Email Subject', 'Email Template For Donee' => 'Email Template For Donee', 'Email Template For Grantor' => 'Email Template For Grantor', 'Email [%s] is not valid' => 'Email [%s] is not valid', 'Email admin regarding account sharing' => 'Email admin regarding account sharing', 'Email change confirmation' => 'Email change confirmation', 'Email user regarding account sharing' => 'Email user regarding account sharing', 'Emotional' => 'Emotional', 'Empty response from Sagepay server' => 'Empty response from Sagepay server', 'Enable' => 'Enable', 'Enable Debug Mode' => 'Enable Debug Mode', 'Enable Dime Sale' => 'Enable Dime Sale', 'Enable Gift Option By Default' => 'Enable Gift Option By Default', 'Enable Instant Commissions' => 'Enable Instant Commissions', 'Enable Location Validation aMember will require two peices of location evidence before an invoice is created. Invoice that fials validation will be blocked and user will receive warning.' => 'Enable Location Validation aMember will require two peices of location evidence before an invoice is created. Invoice that fials validation will be blocked and user will receive warning.', 'Enable PDF Invoice attach invoice file (.pdf) to Payment Receipt email' => 'Enable PDF Invoice attach invoice file (.pdf) to Payment Receipt email', 'Enable Receipts Emails' => 'Enable Receipts Emails', 'Enable Self-Validation If validation failed, user will be able to confirm current location manually ' => 'Enable Self-Validation If validation failed, user will be able to confirm current location manually ', 'Enable double opt-in' => 'Enable double opt-in', 'Enable for Admins' => 'Enable for Admins', 'Enable for Users' => 'Enable for Users', 'Enabled' => 'Enabled', 'Enabled Modules' => 'Enabled Modules', 'Encrypt/Decrypt secret key' => 'Encrypt/Decrypt secret key', 'End' => 'End', 'End Date' => 'End Date', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => 'Enjoy your membership. Please click %shere%s to access your member\'s area.', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Enjoy your membership. To Login please click here %sLogin%s', 'Enter ID generated by software' => 'Enter ID generated by software', 'Enter coupon code' => 'Enter coupon code', 'Enter gift voucher code' => 'Enter gift voucher code', 'Enter username of existing user' => 'Enter username of existing user', 'Error' => 'Error', 'Error 404 - Not Found' => 'Error 404 - Not Found', 'Error : upload folder [%s] does not exists' => 'Error : upload folder [%s] does not exists', 'Error Message' => 'Error Message', 'Error from Storage Engine' => 'Error from Storage Engine', 'Error happened during payment process' => 'Error happened during payment process', 'Error happened during payment process. ' => 'Error happened during payment process. ', 'Error happened during transaction handling. Please contact website administrator' => 'Error happened during transaction handling. Please contact website administrator', 'European (A4)' => 'European (A4)', 'Evidence' => 'Evidence', 'Exact' => 'Exact', 'Exclude from Directory if this box is checked, user will not be displayed in public members directory' => 'Exclude from Directory if this box is checked, user will not be displayed in public members directory', 'Exclude from Directory if this box is checked, you will not be displayed in public members directory' => 'Exclude from Directory if this box is checked, you will not be displayed in public members directory', 'Exclude the following categories from Filter' => 'Exclude the following categories from Filter', 'Expiration Date' => 'Expiration Date', 'Expiration E-Mail' => 'Expiration E-Mail', 'Expire' => 'Expire', 'Expire Date' => 'Expire Date', 'Expire Product Title' => 'Expire Product Title', 'Expire the following product(s) on Expiration' => 'Expire the following product(s) on Expiration', 'Expire the following product(s) on Signup' => 'Expire the following product(s) on Signup', 'Expired' => 'Expired', 'Expired List User will be added to this list immediately when his subscription expires' => 'Expired List User will be added to this list immediately when his subscription expires', 'Expired Users' => 'Expired Users', 'Expires' => 'Expires', 'Export' => 'Export', 'Export Format' => 'Export Format', 'Export Presets' => 'Export Presets', 'External Coupon' => 'External Coupon', 'External Coupon: %s' => 'External Coupon: %s', 'FAQ' => 'FAQ', 'FaceBook App ID' => 'FaceBook App ID', 'FaceBook Application' => 'FaceBook Application', 'Facebook App Secret' => 'Facebook App Secret', 'Facebook SDK was not loaded. Got an error: %s' => 'Facebook SDK was not loaded. Got an error: %s', 'Failed' => 'Failed', 'Fallback paysystems if invoice was started with %s and user canceled payment process OR payment was failed. By default all enabled paysystems will be listed' => 'Fallback paysystems if invoice was started with %s and user canceled payment process OR payment was failed. By default all enabled paysystems will be listed', 'Features' => 'Features', 'Field' => 'Field', 'Field Revisions' => 'Field Revisions', 'Field Type' => 'Field Type', 'Field Updated' => 'Field Updated', 'Fields' => 'Fields', 'Fields To Display' => 'Fields To Display', 'Fields To Export' => 'Fields To Export', 'Fields delimited by' => 'Fields delimited by', 'Fields to Display in Grid' => 'Fields to Display in Grid', 'Fields to track' => 'Fields to track', 'Fieldset' => 'Fieldset', 'Fieldset title' => 'Fieldset title', 'File' => 'File', 'File Downloads' => 'File Downloads', 'File Storage' => 'File Storage', 'File Upload' => 'File Upload', 'File should contain CSV list of user records for import in the following format:
      %s' => 'File should contain CSV list of user records for import in the following format:
      %s', 'File-Upload: browse uploaded files' => 'File-Upload: browse uploaded files', 'Filename' => 'Filename', 'Filename for Invoice %public_id% will be replaced with real public id of invoice, %receipt_id% will be replaced with payment receipt, also you can use the following placehoders %payment.date%, %user.name_f%, %user.name_l%' => 'Filename for Invoice %public_id% will be replaced with real public id of invoice, %receipt_id% will be replaced with payment receipt, also you can use the following placehoders %payment.date%, %user.name_f%, %user.name_l%', 'Files' => 'Files', 'Files keep empty to report all files' => 'Files keep empty to report all files', 'Files List' => 'Files List', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)', 'Files located on Selectel storage. ' => 'Files located on Selectel storage. ', 'Files uploaded via aMember web interface' => 'Files uploaded via aMember web interface', 'Files were uploaded! %sBack%s' => 'Files were uploaded! %sBack%s', 'Filter' => 'Filter', 'Filter Directory' => 'Filter Directory', 'Filter Leads' => 'Filter Leads', 'Filter Text' => 'Filter Text', 'Filter by Content or Link' => 'Filter by Content or Link', 'Filter by Username or Name or E-Mail Address#' => 'Filter by Username or Name or E-Mail Address#', 'First & Last Name' => 'First & Last Name', 'First Name' => 'First Name', 'First Payment' => 'First Payment', 'First Time Purchase of Product' => 'First Time Purchase of Product', 'First Time Purchase: %s' => 'First Time Purchase: %s', 'Flat Amount' => 'Flat Amount', 'Folder %s (%s)' => 'Folder %s (%s)', 'Folders' => 'Folders', 'Follow the link to activate the token' => 'Follow the link to activate the token', 'Follow the link to reset the token' => 'Follow the link to reset the token', 'Footer this content will be included to footer' => 'Footer this content will be included to footer', 'Force I Agree' => 'Force I Agree', 'Force User to Choose Some Product from this Brick' => 'Force User to Choose Some Product from this Brick', 'Forgot password?' => 'Forgot password?', 'Form Bricks (drag to right to remove)' => 'Form Bricks (drag to right to remove)', 'Form Page Break' => 'Form Page Break', 'Free' => 'Free', 'Free Access' => 'Free Access', 'Free Access without log-in' => 'Free Access without log-in', 'Free Signup' => 'Free Signup', 'From' => 'From', 'From Address' => 'From Address', 'Full Name' => 'Full Name', 'GST (Inclusive Tax)' => 'GST (Inclusive Tax)', 'Get Link' => 'Get Link', 'Get Password' => 'Get Password', 'Get Payment Link' => 'Get Payment Link', 'Get affiliate coupons' => 'Get affiliate coupons', 'GetClicky Site Id GetClicky Account -> Preferences -> Info' => 'GetClicky Site Id GetClicky Account -> Preferences -> Info', 'Gift Card' => 'Gift Card', 'Gift Card fill in gift card here if you have one' => 'Gift Card fill in gift card here if you have one', 'Gift Card (Purchase)' => 'Gift Card (Purchase)', 'Gift Card (Redeem)' => 'Gift Card (Redeem)', 'Gift Card Balance' => 'Gift Card Balance', 'Gift Card Period gift card should be used within this period after purchase' => 'Gift Card Period gift card should be used within this period after purchase', 'Gift Voucher' => 'Gift Voucher', 'Gift Voucher Donee' => 'Gift Voucher Donee', 'Gift Voucher Grantor' => 'Gift Voucher Grantor', 'Gift Voucher Period Of Validity After Creation' => 'Gift Voucher Period Of Validity After Creation', 'Gift Vouchers' => 'Gift Vouchers', 'Global Commission' => 'Global Commission', 'Global Limit of IP Addresses empty or 0 - without limit' => 'Global Limit of IP Addresses empty or 0 - without limit', 'Global Tax' => 'Global Tax', 'Go Back' => 'Go Back', 'Goal' => 'Goal', 'Grantor' => 'Grantor', 'Grantor\'s Invoice' => 'Grantor\'s Invoice', 'Group By' => 'Group By', 'Grouping' => 'Grouping', 'Groups' => 'Groups', 'Groups Limit' => 'Groups Limit', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"', 'HTML Code that will be displayed' => 'HTML Code that will be displayed', 'HTML Message' => 'HTML Message', 'HTML text' => 'HTML text', 'Has %s Affiliate Commission' => 'Has %s Affiliate Commission', 'Has Affiliate Commission' => 'Has Affiliate Commission', 'Has Not Used Payment System' => 'Has Not Used Payment System', 'Has Used Payment System' => 'Has Used Payment System', 'Has invoice canceled between dates' => 'Has invoice canceled between dates', 'Has invoice started between dates' => 'Has invoice started between dates', 'Has payment made between dates' => 'Has payment made between dates', 'Has pending invoice with products' => 'Has pending invoice with products', 'Has subscription between dates' => 'Has subscription between dates', 'Has subscription on date' => 'Has subscription on date', 'Has subscription that expire between dates' => 'Has subscription that expire between dates', 'Have a Coupon? Apply Here' => 'Have a Coupon? Apply Here', 'Have uploaded at least 1 file' => 'Have uploaded at least 1 file', 'Having Active Subscription To:' => 'Having Active Subscription To:', 'Having Expired Subscription To:' => 'Having Expired Subscription To:', 'Having active subscription to' => 'Having active subscription to', 'Having expired subscription to' => 'Having expired subscription to', 'Having no active subscription to' => 'Having no active subscription to', 'Header this content will be included to header' => 'Header this content will be included to header', 'Header Logo keep it empty for default value' => 'Header Logo keep it empty for default value', 'Help Desk Url it must be with https and without slash on the end, for example https://example.zendesk.com' => 'Help Desk Url it must be with https and without slash on the end, for example https://example.zendesk.com', 'Helpdesk' => 'Helpdesk', 'Helpdesk: Can operate with helpdesk tickets' => 'Helpdesk: Can operate with helpdesk tickets', 'Helpdesk: Categories' => 'Helpdesk: Categories', 'Helpdesk: FAQ' => 'Helpdesk: FAQ', 'Here you can assign user groups to products. To add new user groups %sclick here%s. ' => 'Here you can assign user groups to products. To add new user groups %sclick here%s. ', 'Hidden' => 'Hidden', 'Hide' => 'Hide', 'Hide do not display this item in members area' => 'Hide do not display this item in members area', 'Hide do not display this item link in members area' => 'Hide do not display this item link in members area', 'Hide Brick Title' => 'Hide Brick Title', 'Hide Invoice after XX days' => 'Hide Invoice after XX days', 'Hide Label' => 'Hide Label', 'Hide Payment Forms and History from SubUsers' => 'Hide Payment Forms and History from SubUsers', 'Hide Select if there is only one choice' => 'Hide Select if there is only one choice', 'History' => 'History', 'Hosted at Activecampaing\'s server' => 'Hosted at Activecampaing\'s server', 'Hours' => 'Hours', 'Housenumber' => 'Housenumber', 'How to calculate limits? Pages Limit and Groups Limit' => 'How to calculate limits? Pages Limit and Groups Limit', 'I confirm I\'m based in %s' => 'I confirm I\'m based in %s', 'I have read and agree to the Terms & Conditions' => 'I have read and agree to the Terms & Conditions', 'IBAN' => 'IBAN', 'ID used for placeholders in emails' => 'ID used for placeholders in emails', 'IF' => 'IF', 'INET-CASH payment wizard' => 'INET-CASH payment wizard', 'IP Address' => 'IP Address', 'IP Addresses' => 'IP Addresses', 'If product is not available because of require/disallow settings' => 'If product is not available because of require/disallow settings', 'If you already have an account on our website, please %slog in%s to continue' => 'If you already have an account on our website, please %slog in%s to continue', 'If you are a registered member, please %slogin%s' => 'If you are a registered member, please %slogin%s', 'If you are not registered yet, please %ssignup%s' => 'If you are not registered yet, please %ssignup%s', 'Import from CSV' => 'Import from CSV', 'In order to comply with EU VAT Rules we need you to confirm your billing country.' => 'In order to comply with EU VAT Rules we need you to confirm your billing country.', 'Include Access Periods to PDF Invoice' => 'Include Access Periods to PDF Invoice', 'Include only users who have active subscritpions to these products' => 'Include only users who have active subscritpions to these products', 'Include to Directory' => 'Include to Directory', 'Include to Directory matching users will be displayed in this members directory in case of empty all active users will be included' => 'Include to Directory matching users will be displayed in this members directory in case of empty all active users will be included', 'Income' => 'Income', 'Income Report - payments minus refunds' => 'Income Report - payments minus refunds', 'Incorrect Parent Affiliate ID' => 'Incorrect Parent Affiliate ID', 'Index Page Fields' => 'Index Page Fields', 'Initial Receipt# Number' => 'Initial Receipt# Number', 'Initial Receipt# Refund Number' => 'Initial Receipt# Refund Number', 'Input Type' => 'Input Type', 'Insert comment into email' => 'Insert comment into email', 'Instance ID' => 'Instance ID', 'Insufficient credits' => 'Insufficient credits', 'Integer Value' => 'Integer Value', 'Integer value required' => 'Integer value required', 'Integration' => 'Integration', 'Integration key' => 'Integration key', 'Integrations' => 'Integrations', 'Internal Error' => 'Internal Error', 'Invalid Account Number' => 'Invalid Account Number', 'Invalid Bank Account Number' => 'Invalid Bank Account Number', 'Invalid Bank Identifier Code' => 'Invalid Bank Identifier Code', 'Invalid Credit Card Number' => 'Invalid Credit Card Number', 'Invalid Debit Card Number' => 'Invalid Debit Card Number', 'Invalid EU VAT Id format' => 'Invalid EU VAT Id format', 'Invalid Emails' => 'Invalid Emails', 'Invalid Expiration Date - Month' => 'Invalid Expiration Date - Month', 'Invalid Expiration Date - Year' => 'Invalid Expiration Date - Year', 'Invalid Issue Number' => 'Invalid Issue Number', 'Invalid Product Code' => 'Invalid Product Code', 'Invalid Routing Number' => 'Invalid Routing Number', 'Invalid VAT Id, please try again' => 'Invalid VAT Id, please try again', 'Invite' => 'Invite', 'Invite Code' => 'Invite Code', 'Invite Email Message' => 'Invite Email Message', 'Invite a Friend' => 'Invite a Friend', 'Invited Users' => 'Invited Users', 'Invoice' => 'Invoice', 'Invoice #%s not found' => 'Invoice #%s not found', 'Invoice Approved' => 'Invoice Approved', 'Invoice Contact information included at top, use <br> for new line' => 'Invoice Contact information included at top, use <br> for new line', 'Invoice First Total' => 'Invoice First Total', 'Invoice Footer Note This text will be included at bottom to PDF Invoice. You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.' => 'Invoice Footer Note This text will be included at bottom to PDF Invoice. You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.', 'Invoice Internal ID#' => 'Invoice Internal ID#', 'Invoice Number: ' => 'Invoice Number: ', 'Invoice Public ID#' => 'Invoice Public ID#', 'Invoice Second Total' => 'Invoice Second Total', 'Invoice Summary' => 'Invoice Summary', 'Invoice Text' => 'Invoice Text', 'Invoice is expired' => 'Invoice is expired', 'Invoice not found' => 'Invoice not found', 'Invoice numbering' => 'Invoice numbering', 'Invoices/Access' => 'Invoices/Access', 'Is Affiliate? customer / affiliate status' => 'Is Affiliate? customer / affiliate status', 'Is Donation Required?' => 'Is Donation Required?', 'Is Gift Voucher?' => 'Is Gift Voucher?', 'Is Html?' => 'Is Html?', 'Is Locked' => 'Is Locked', 'Is Paid?' => 'Is Paid?', 'Is Send At Later Date?' => 'Is Send At Later Date?', 'Is Send Email to Grantor?' => 'Is Send Email to Grantor?', 'Is a Subuser:' => 'Is a Subuser:', 'Is Disabled?' => 'Is Disabled?', 'It is last message that will be shown to user before account removal, you can place some special offer here.' => 'It is last message that will be shown to user before account removal, you can place some special offer here.', 'It looks like you are not at home right now.' => 'It looks like you are not at home right now.', 'Item' => 'Item', 'JSON Web Token' => 'JSON Web Token', 'JavaScript Code it will be injected on signup form' => 'JavaScript Code it will be injected on signup form', 'Joint Venture Agreement' => 'Joint Venture Agreement', 'JunglePay payment' => 'JunglePay payment', 'Keep empty to use default value from field settings' => 'Keep empty to use default value from field settings', 'Key Secret' => 'Key Secret', 'Keyword' => 'Keyword', 'Keywords' => 'Keywords', 'Label' => 'Label', 'Language' => 'Language', 'Language Display this brick only for the following languages. Keep it empty to display for any language.' => 'Language Display this brick only for the following languages. Keep it empty to display for any language.', 'Last 14 Days' => 'Last 14 Days', 'Last 30 Days' => 'Last 30 Days', 'Last 6 Months' => 'Last 6 Months', 'Last 7 Days' => 'Last 7 Days', 'Last 90 Days' => 'Last 90 Days', 'Last Business Week (Mon-Fri)' => 'Last Business Week (Mon-Fri)', 'Last File Upload' => 'Last File Upload', 'Last Messages in Helpdesk' => 'Last Messages in Helpdesk', 'Last Month' => 'Last Month', 'Last Name' => 'Last Name', 'Last Quarter' => 'Last Quarter', 'Last Signin' => 'Last Signin', 'Last Used Login' => 'Last Used Login', 'Last Week (Mon-Sun)' => 'Last Week (Mon-Sun)', 'Last Week (Sun-Sat)' => 'Last Week (Sun-Sat)', 'Last Year' => 'Last Year', 'Layout' => 'Layout', 'Layout Width' => 'Layout Width', 'Leads' => 'Leads', 'Left' => 'Left', 'Legal Address Please enter the legal address of your organisation which will be included in the Direct Debit Guarantee statement' => 'Legal Address Please enter the legal address of your organisation which will be included in the Direct Debit Guarantee statement', 'Legal Name Please enter the legal name of your organisation which will be included in the Direct Debit Guarantee statement' => 'Legal Name Please enter the legal name of your organisation which will be included in the Direct Debit Guarantee statement', 'License Key' => 'License Key', 'License activation has been disabled' => 'License activation has been disabled', 'Licenses' => 'Licenses', 'Licensing Schemes' => 'Licensing Schemes', 'Lifetime' => 'Lifetime', 'Like Button Action' => 'Like Button Action', 'Like Button Layout' => 'Like Button Layout', 'Like Url' => 'Like Url', 'Limit' => 'Limit', 'Limit Access to Invite Feature leave it empty if there is not any restrictions' => 'Limit Access to Invite Feature leave it empty if there is not any restrictions', 'Limit Number of Display per User keep it empty for unlimited' => 'Limit Number of Display per User keep it empty for unlimited', 'Limit of IP Addresses' => 'Limit of IP Addresses', 'Limit of Simultaneous Active Sessions' => 'Limit of Simultaneous Active Sessions', 'Link' => 'Link', 'Link PayPal Account' => 'Link PayPal Account', 'Link Type' => 'Link Type', 'Link expired' => 'Link expired', 'Link is either expired or invalid' => 'Link is either expired or invalid', 'Linked PayPal Account' => 'Linked PayPal Account', 'Links' => 'Links', 'List Page Template alternative template for list page' => 'List Page Template alternative template for list page', 'List of E-Mail Address' => 'List of E-Mail Address', 'Lists All List will be displayed if none selected' => 'Lists All List will be displayed if none selected', 'Live Edit %s' => 'Live Edit %s', 'Loading' => 'Loading', 'Location validation failed.' => 'Location validation failed.', 'Lock User Account' => 'Lock User Account', 'Locked Group Whenever user is locked in aMember, plugin adds user to this group in %s Select any group with limited access which doesn\'t allow to login into %s Some scripts have special group for this situations: \'Unregistered\' or \'Guest\'' => 'Locked Group Whenever user is locked in aMember, plugin adds user to this group in %s Select any group with limited access which doesn\'t allow to login into %s Some scripts have special group for this situations: \'Unregistered\' or \'Guest\'', 'Log In' => 'Log In', 'Log Requests' => 'Log Requests', 'Log all API Requests' => 'Log all API Requests', 'Login' => 'Login', 'Login Button Size' => 'Login Button Size', 'Login Indicator' => 'Login Indicator', 'Login Monitor' => 'Login Monitor', 'Login Reminder' => 'Login Reminder', 'Login Reminder to User' => 'Login Reminder to User', 'Login as User' => 'Login as User', 'Login to your Account' => 'Login to your Account', 'Login via IP' => 'Login via IP', 'Logo Position' => 'Logo Position', 'Logo Width' => 'Logo Width', 'Logout' => 'Logout', 'Lost Password Sending Error' => 'Lost Password Sending Error', 'Lost Password Sent' => 'Lost Password Sent', 'Lost password?' => 'Lost password?', 'Low Stock Notification' => 'Low Stock Notification', 'Low Stock Notification to Admin' => 'Low Stock Notification to Admin', 'Low Stock Threshold' => 'Low Stock Threshold', 'MILESTONE PLUGIN: Goal \'%s\' completed!' => 'MILESTONE PLUGIN: Goal \'%s\' completed!', 'Mail Payment Admin' => 'Mail Payment Admin', 'Mail Queue' => 'Mail Queue', 'MailerLite API key API key can be obtained from Integrations page when you are logged into MailerLite application' => 'MailerLite API key API key can be obtained from Integrations page when you are logged into MailerLite application', 'Make Payment' => 'Make Payment', 'Make a Donation' => 'Make a Donation', 'Make donation recurring' => 'Make donation recurring', 'Make the first letters of first and last name Uppercase' => 'Make the first letters of first and last name Uppercase', 'Make this Brick Required Only in Case There is not any Required Brick on Page Above It' => 'Make this Brick Required Only in Case There is not any Required Brick on Page Above It', 'Make user who invite Affiliate' => 'Make user who invite Affiliate', 'Manage Newsletters' => 'Manage Newsletters', 'Manually Approve' => 'Manually Approve', 'Manually Approve Admin' => 'Manually Approve Admin', 'Manually Approve Invoice' => 'Manually Approve Invoice', 'Manually Approve Invoice Admin' => 'Manually Approve Invoice Admin', 'Marketing Materials' => 'Marketing Materials', 'Max' => 'Max', 'MaxMind Account' => 'MaxMind Account', 'MaxMind Credit Card Fraud Detection' => 'MaxMind Credit Card Fraud Detection', 'MaxMind License' => 'MaxMind License', 'MaxMind User ID' => 'MaxMind User ID', 'Maximum amount of donation' => 'Maximum amount of donation', 'Maxmind License Key %sObtain a Free or Premium license key%s' => 'Maxmind License Key %sObtain a Free or Premium license key%s', 'Member Record' => 'Member Record', 'Members Directory' => 'Members Directory', 'Members Directory [%s] does not exists' => 'Members Directory [%s] does not exists', 'Membership Type' => 'Membership Type', 'Merchant Key' => 'Merchant Key', 'Merchant Name to be shown in Checkout Form' => 'Merchant Name to be shown in Checkout Form', 'Merchant Secret' => 'Merchant Secret', 'Message' => 'Message', 'Message It is last message that will be shown to user before account removal, you can place some special offer here.' => 'Message It is last message that will be shown to user before account removal, you can place some special offer here.', 'Message This message will be shown on accept page. You can clarify situation for user here and provide link to new Agreement text. Placeholder %button% will be replaced with actual button.' => 'Message This message will be shown on accept page. You can clarify situation for user here and provide link to new Agreement text. Placeholder %button% will be replaced with actual button.', 'Message on cancel feedback page for customer' => 'Message on cancel feedback page for customer', 'Message Text' => 'Message Text', 'Message can not be empty' => 'Message can not be empty', 'Message has been sent successfully' => 'Message has been sent successfully', 'Message template when goal is completed' => 'Message template when goal is completed', 'Message template when goal is not reached' => 'Message template when goal is not reached', 'Meta Data' => 'Meta Data', 'Milestones' => 'Milestones', 'Min' => 'Min', 'Minimum Number of Items in invoice to apply discount' => 'Minimum Number of Items in invoice to apply discount', 'Minimum Payout include to report only affiliates with payout in qiven period more or equal to' => 'Minimum Payout include to report only affiliates with payout in qiven period more or equal to', 'Minimum amount of donation keep it empty if there is not any limit' => 'Minimum amount of donation keep it empty if there is not any limit', 'Misc' => 'Misc', 'Moip Payment' => 'Moip Payment', 'Month' => 'Month', 'Month (30 days)' => 'Month (30 days)', 'Months' => 'Months', 'Multiplier' => 'Multiplier', 'My Country' => 'My Country', 'My Tickets' => 'My Tickets', 'NEVER' => 'NEVER', 'Name' => 'Name', 'Name of Account Holder first and last name' => 'Name of Account Holder first and last name', 'Name of Friend' => 'Name of Friend', 'Never' => 'Never', 'Never subscribed to' => 'Never subscribed to', 'New' => 'New', 'New %s' => 'New %s', 'New Email' => 'New Email', 'New Password' => 'New Password', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'New Password you can choose new password here or keep it unchanged must be %d or more characters', 'New Signups are Disabled' => 'New Signups are Disabled', 'New Value' => 'New Value', 'Newsletter' => 'Newsletter', 'Newsletter Subscriptions' => 'Newsletter Subscriptions', 'Newsletters' => 'Newsletters', 'Next' => 'Next', 'Next Rebill' => 'Next Rebill', 'Nickname' => 'Nickname', 'No' => 'No', 'No Category' => 'No Category', 'No commissions on this date' => 'No commissions on this date', 'No coupons found with such coupon code' => 'No coupons found with such coupon code', 'No files uploaded' => 'No files uploaded', 'No gift vouchers found with such code' => 'No gift vouchers found with such code', 'No items in this section' => 'No items in this section', 'No items selected for purchase' => 'No items selected for purchase', 'No licenses assigned yet' => 'No licenses assigned yet', 'No payouts have been made to your account yet' => 'No payouts have been made to your account yet', 'No records found' => 'No records found', 'No records in this member directory yet' => 'No records in this member directory yet', 'No result found' => 'No result found', 'No, cancel' => 'No, cancel', 'No, is not a subuser' => 'No, is not a subuser', 'No, keep me subscribed' => 'No, keep me subscribed', 'No, please keep me subscribed' => 'No, please keep me subscribed', 'Nochex Merchant ID Your default merchant id is the email address you use with your Nochex account' => 'Nochex Merchant ID Your default merchant id is the email address you use with your Nochex account', 'None' => 'None', 'Normal' => 'Normal', 'Not Affiliate' => 'Not Affiliate', 'Not Approved Affiliates' => 'Not Approved Affiliates', 'Not Paid' => 'Not Paid', 'Not Recurring' => 'Not Recurring', 'Not Selected' => 'Not Selected', 'Not Send' => 'Not Send', 'Not Subscribed to Newsletter Lists' => 'Not Subscribed to Newsletter Lists', 'Not Used' => 'Not Used', 'Not assigned to usergroup' => 'Not assigned to usergroup', 'Not enough credits to debit' => 'Not enough credits to debit', 'Not registered yet?' => 'Not registered yet?', 'Notes' => 'Notes', 'Nothing, allow simultaneous login for same user from different computers' => 'Nothing, allow simultaneous login for same user from different computers', 'Notification' => 'Notification', 'Notification Message' => 'Notification Message', 'Notifications' => 'Notifications', 'Notify Admin about new user with risk score more then define threshold' => 'Notify Admin about new user with risk score more then define threshold', 'Notify Admin once user removed himself' => 'Notify Admin once user removed himself', 'Notify Admin after User Log in to His Account' => 'Notify Admin after User Log in to His Account', 'Notify Admin on Simultaneous Login' => 'Notify Admin on Simultaneous Login', 'Notify User about new file upload' => 'Notify User about new file upload', 'Notify User on Simultaneous Login' => 'Notify User on Simultaneous Login', 'Notify admin about new upload' => 'Notify admin about new upload', 'NuevoMailer installation URL' => 'NuevoMailer installation URL', 'Number Identification Enable %sTelephone Number Identification (TNI)%s service' => 'Number Identification Enable %sTelephone Number Identification (TNI)%s service', 'Number of Active Users by Date' => 'Number of Active Users by Date', 'Number of Affiliates' => 'Number of Affiliates', 'Number of Messages to display' => 'Number of Messages to display', 'Number of Users who Purchase product B after Product A' => 'Number of Users who Purchase product B after Product A', 'Number of cancel on each billing cycle' => 'Number of cancel on each billing cycle', 'Number of users who becomes inactive in given period' => 'Number of users who becomes inactive in given period', 'Numeric Value' => 'Numeric Value', 'Numeric value required' => 'Numeric value required', 'OAuth Secret' => 'OAuth Secret', 'OAuth client_id' => 'OAuth client_id', 'OK. Press \'Continue...\' to refresh Database name autocompletion database' => 'OK. Press \'Continue...\' to refresh Database name autocompletion database', 'OTO' => 'OTO', 'OTO (Downsell)' => 'OTO (Downsell)', 'Offer Page Settings' => 'Offer Page Settings', 'Offline Check' => 'Offline Check', 'Offline Payment' => 'Offline Payment', 'Offline bank account info' => 'Offline bank account info', 'Old Value' => 'Old Value', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Newsletters%s page' => 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Newsletters%s page', 'One Time Offer' => 'One Time Offer', 'Online' => 'Online', 'Online backup is disabled if you have CC payment plugins enabled. Use offline backup instead' => 'Online backup is disabled if you have CC payment plugins enabled. Use offline backup instead', 'Only Affiliate %s(rarely used)%s' => 'Only Affiliate %s(rarely used)%s', 'Only Affiliate, not a member' => 'Only Affiliate, not a member', 'Only Billing Plans selected below' => 'Only Billing Plans selected below', 'Only Products selected below' => 'Only Products selected below', 'Open Link in New Window' => 'Open Link in New Window', 'Optimize Mail Log' => 'Optimize Mail Log', 'Order Summary' => 'Order Summary', 'Order reference: %s' => 'Order reference: %s', 'Order with credits' => 'Order with credits', 'Other' => 'Other', 'Our system will try to charge your card again on %s' => 'Our system will try to charge your card again on %s', 'Out of Stock Notification' => 'Out of Stock Notification', 'Out of Stock Notification to Admin' => 'Out of Stock Notification to Admin', 'Owner' => 'Owner', 'PDF Invoice Unpaid' => 'PDF Invoice Unpaid', 'Page Title' => 'Page Title', 'Pages' => 'Pages', 'Pages Limit' => 'Pages Limit', 'Paid (Included to Payout)' => 'Paid (Included to Payout)', 'Paper Format' => 'Paper Format', 'Parent User' => 'Parent User', 'Parent User Info' => 'Parent User Info', 'Partially Used' => 'Partially Used', 'Partner' => 'Partner', 'Partner Share for First Payment calculated for first payment in each invoice' => 'Partner Share for First Payment calculated for first payment in each invoice', 'Partner Share for Rebills' => 'Partner Share for Rebills', 'Password' => 'Password', 'Password Change E-Mail' => 'Password Change E-Mail', 'Password Salt' => 'Password Salt', 'Password and Password Confirmation are different. Please reenter both' => 'Password and Password Confirmation are different. Please reenter both', 'Password must contain at least %d letters or digits' => 'Password must contain at least %d letters or digits', 'Password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars' => 'Password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars', 'Passwords do not match' => 'Passwords do not match', 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this product to do it' => 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this product to do it', 'Path should be unique across all products' => 'Path should be unique across all products', 'Path to %s' => 'Path to %s', 'Path to %s Folder' => 'Path to %s Folder', 'Path to Source Folder' => 'Path to Source Folder', 'Path to Target Folder' => 'Path to Target Folder', 'Pay' => 'Pay', 'Pay with Card' => 'Pay with Card', 'Pay with your Credit Card' => 'Pay with your Credit Card', 'PayForIt payment' => 'PayForIt payment', 'Payanyway plugin does not support recurring billing!' => 'Payanyway plugin does not support recurring billing!', 'Payment' => 'Payment', 'Payment Amount' => 'Payment Amount', 'Payment Canceled' => 'Payment Canceled', 'Payment Confirmation' => 'Payment Confirmation', 'Payment Currency' => 'Payment Currency', 'Payment E-mail' => 'Payment E-mail', 'Payment Error' => 'Payment Error', 'Payment Failed' => 'Payment Failed', 'Payment History' => 'Payment History', 'Payment Info' => 'Payment Info', 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when he chooses to pay using this payment system you can use the following tags: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total' => 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when he chooses to pay using this payment system you can use the following tags: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total', 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when they set up a direct debit using this payment system you can use the following tags: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total' => 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when they set up a direct debit using this payment system you can use the following tags: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total', 'Payment Link' => 'Payment Link', 'Payment Link to Complete Pending Invoice' => 'Payment Link to Complete Pending Invoice', 'Payment Method' => 'Payment Method', 'Payment Options if none selected, all enabled will be displayed' => 'Payment Options if none selected, all enabled will be displayed', 'Payment Receipt Id' => 'Payment Receipt Id', 'Payment Routing Number' => 'Payment Routing Number', 'Payment System' => 'Payment System', 'Payment System Description' => 'Payment System Description', 'Payment System Domain Leave default value if you are not sure' => 'Payment System Domain Leave default value if you are not sure', 'Payment System Title' => 'Payment System Title', 'Payment Type' => 'Payment Type', 'Payment error: ' => 'Payment error: ', 'Payment failed' => 'Payment failed', 'Payment info' => 'Payment info', 'Payment is already processed, please go to %sMembership page%s' => 'Payment is already processed, please go to %sMembership page%s', 'Payments' => 'Payments', 'Payments Amount' => 'Payments Amount', 'Payments History' => 'Payments History', 'Payments by New vs Existing members' => 'Payments by New vs Existing members', 'Payments by Used Coupon' => 'Payments by Used Coupon', 'Payments by payment system breakdown' => 'Payments by payment system breakdown', 'Payments by product categories breakdown' => 'Payments by product categories breakdown', 'Payments by products breakdown' => 'Payments by products breakdown', 'Payments from existing customers' => 'Payments from existing customers', 'Payments from new customers' => 'Payments from new customers', 'Payments total' => 'Payments total', 'Payments vs Refunds' => 'Payments vs Refunds', 'Payments/Access' => 'Payments/Access', 'Payout' => 'Payout', 'Payout Date' => 'Payout Date', 'Payout Method' => 'Payout Method', 'Payout Method Title' => 'Payout Method Title', 'Payouts' => 'Payouts', 'Paypal interface language en_US - english, de_DE - german, default is german' => 'Paypal interface language en_US - english, de_DE - german, default is german', 'Paysystem (optional)' => 'Paysystem (optional)', 'Paysystem IN (%s)' => 'Paysystem IN (%s)', 'Pending' => 'Pending', 'Pending Invoice Notifications to Admin' => 'Pending Invoice Notifications to Admin', 'Pending Invoice Notifications to User' => 'Pending Invoice Notifications to User', 'Pending Invoices' => 'Pending Invoices', 'Pending Invoices Block' => 'Pending Invoices Block', 'Pending List User will be added to this list immediately after signup' => 'Pending List User will be added to this list immediately after signup', 'Pending subusers' => 'Pending subusers', 'Percentage of users who convert from free to paid within given amount of days' => 'Percentage of users who convert from free to paid within given amount of days', 'Period' => 'Period', 'Period must be in interval 1-24 months' => 'Period must be in interval 1-24 months', 'Period must be in interval 1-5 years' => 'Period must be in interval 1-5 years', 'Period must be in interval 1-90 days' => 'Period must be in interval 1-90 days', 'Permalink' => 'Permalink', 'Personal Content' => 'Personal Content', 'Personal Content These files will be available for downloads only for this user on his dashboard' => 'Personal Content These files will be available for downloads only for this user on his dashboard', 'Personal Content: Upload File' => 'Personal Content: Upload File', 'Personal Folder' => 'Personal Folder', 'Phone' => 'Phone', 'Phone Number' => 'Phone Number', 'Plain-Text Message' => 'Plain-Text Message', 'Plain-Text Password' => 'Plain-Text Password', 'Please %sdefine payout method%s to get commission in our affiliate program.' => 'Please %sdefine payout method%s to get commission in our affiliate program.', 'Please %senable at least one payout method%s since you use affiliate module' => 'Please %senable at least one payout method%s since you use affiliate module', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login', 'Please Enter URL of Your Landing Page' => 'Please Enter URL of Your Landing Page', 'Please Select' => 'Please Select', 'Please agree to Affiliate Agreement' => 'Please agree to Affiliate Agreement', 'Please agree to User Agreement' => 'Please agree to User Agreement', 'Please answer above question' => 'Please answer above question', 'Please choose' => 'Please choose', 'Please choose Payment Method' => 'Please choose Payment Method', 'Please choose a Bank Account Type' => 'Please choose a Bank Account Type', 'Please choose a Credit Card Type' => 'Please choose a Credit Card Type', 'Please choose a membership type' => 'Please choose a membership type', 'Please choose a payment system' => 'Please choose a payment system', 'Please choose state' => 'Please choose state', 'Please confirm your billing address manually' => 'Please confirm your billing address manually', 'Please contact webmaster' => 'Please contact webmaster', 'Please enter %s' => 'Please enter %s', 'Please enter Account Number' => 'Please enter Account Number', 'Please enter Bank Account Name' => 'Please enter Bank Account Name', 'Please enter Bank Identifier Code' => 'Please enter Bank Identifier Code', 'Please enter Bank Name' => 'Please enter Bank Name', 'Please enter Branch Sort Code' => 'Please enter Branch Sort Code', 'Please enter City' => 'Please enter City', 'Please enter Country' => 'Please enter Country', 'Please enter Credit Card Code' => 'Please enter Credit Card Code', 'Please enter Credit Card Number' => 'Please enter Credit Card Number', 'Please enter Credit Card expiration date' => 'Please enter Credit Card expiration date', 'Please enter Debit Card Number' => 'Please enter Debit Card Number', 'Please enter EU VAT Id' => 'Please enter EU VAT Id', 'Please enter Password' => 'Please enter Password', 'Please enter Routing Number' => 'Please enter Routing Number', 'Please enter State' => 'Please enter State', 'Please enter Street Address' => 'Please enter Street Address', 'Please enter ZIP code' => 'Please enter ZIP code', 'Please enter a valid IP address' => 'Please enter a valid IP address', 'Please enter a valid URL' => 'Please enter a valid URL', 'Please enter a valid e-mail address' => 'Please enter a valid e-mail address', 'Please enter billing name' => 'Please enter billing name', 'Please enter cardholder name exactly as on card' => 'Please enter cardholder name exactly as on card', 'Please enter correct amount' => 'Please enter correct amount', 'Please enter coupon code' => 'Please enter coupon code', 'Please enter credit card holder first and last name' => 'Please enter credit card holder first and last name', 'Please enter credit card holder first name' => 'Please enter credit card holder first name', 'Please enter credit card holder last name' => 'Please enter credit card holder last name', 'Please enter credit card holder name' => 'Please enter credit card holder name', 'Please enter debit card holder first name' => 'Please enter debit card holder first name', 'Please enter debit card holder last name' => 'Please enter debit card holder last name', 'Please enter debit card holder name' => 'Please enter debit card holder name', 'Please enter first name' => 'Please enter first name', 'Please enter gift voucher code' => 'Please enter gift voucher code', 'Please enter housenumber' => 'Please enter housenumber', 'Please enter last name' => 'Please enter last name', 'Please enter name' => 'Please enter name', 'Please enter phone number' => 'Please enter phone number', 'Please enter valid Email' => 'Please enter valid Email', 'Please enter valid HTTPS url with "/api" at the end' => 'Please enter valid HTTPS url with "/api" at the end', 'Please enter valid Username. It must contain at least %d characters' => 'Please enter valid Username. It must contain at least %d characters', 'Please enter your First & Last Name' => 'Please enter your First & Last Name', 'Please enter your First Name' => 'Please enter your First Name', 'Please enter your Last Name' => 'Please enter your Last Name', 'Please enter your current password for validation' => 'Please enter your current password for validation', 'Please enter your last name' => 'Please enter your last name', 'Please enter your name' => 'Please enter your name', 'Please keep me subscribed' => 'Please keep me subscribed', 'Please login' => 'Please login', 'Please note: it is impossible to restore your current account after deleting but you still can signup again as new user.' => 'Please note: it is impossible to restore your current account after deleting but you still can signup again as new user.', 'Please save your settings before use preview link' => 'Please save your settings before use preview link', 'Please select' => 'Please select', 'Please select an item...' => 'Please select an item...', 'Please select card type' => 'Please select card type', 'Please select payment system for payment' => 'Please select payment system for payment', 'Please select the biller and click button to continue' => 'Please select the biller and click button to continue', 'Please specify donation amount' => 'Please specify donation amount', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Please use %sAdd/Renew subscription%s form to order or renew subscription.', 'Please wait %d seconds before next attempt' => 'Please wait %d seconds before next attempt', 'Please wait %d seconds before next login attempt' => 'Please wait %d seconds before next login attempt', 'Please wait while we process your order...' => 'Please wait while we process your order...', 'Plugin' => 'Plugin', 'Plugin List Id' => 'Plugin List Id', 'Plugin List Id value required' => 'Plugin List Id value required', 'Plugin [%s] is not configured yet. Please %scomplete configuration%s' => 'Plugin [%s] is not configured yet. Please %scomplete configuration%s', 'Position for HTML' => 'Position for HTML', 'Possible Gift Card Amount Range' => 'Possible Gift Card Amount Range', 'PostAffiliatePro Parent Affiliate ID' => 'PostAffiliatePro Parent Affiliate ID', 'PostAffiliatePro Referral ID' => 'PostAffiliatePro Referral ID', 'Postal Index' => 'Postal Index', 'Preset Name' => 'Preset Name', 'Presets' => 'Presets', 'Prev' => 'Prev', 'Preview' => 'Preview', 'Previous Period' => 'Previous Period', 'Previous Year' => 'Previous Year', 'Price' => 'Price', 'Priority' => 'Priority', 'Priority of discount First match discount with higher priority will be applied' => 'Priority of discount First match discount with higher priority will be applied', 'Proceed to Checkout' => 'Proceed to Checkout', 'Process %s' => 'Process %s', 'Process Payment Day' => 'Process Payment Day', 'Processing' => 'Processing', 'Processing your Invoice' => 'Processing your Invoice', 'Processing your Transaction' => 'Processing your Transaction', 'Processing your product upgrade' => 'Processing your product upgrade', 'Product' => 'Product', 'Product user should have active access to one of following products in order to personal folder was created' => 'Product user should have active access to one of following products in order to personal folder was created', 'Product %s is incompatible with product %s. Reason: %s' => 'Product %s is incompatible with product %s. Reason: %s', 'Product A' => 'Product A', 'Product B' => 'Product B', 'Product Categories' => 'Product Categories', 'Product Category IN (%s)' => 'Product Category IN (%s)', 'Product Category NOT IN (%s)' => 'Product Category NOT IN (%s)', 'Product Chaining Rules' => 'Product Chaining Rules', 'Product Code' => 'Product Code', 'Product Convertion' => 'Product Convertion', 'Product Description displayed on the shopping cart page' => 'Product Description displayed on the shopping cart page', 'Product Gategories' => 'Product Gategories', 'Product ID' => 'Product ID', 'Product ID at paddle.com' => 'Product ID at paddle.com', 'Product Password user should use this password on signup form in order to be able to purchase this product' => 'Product Password user should use this password on signup form in order to be able to purchase this product', 'Product Picture for shopping cart pages. Only jpg, png and gif formats allowed' => 'Product Picture for shopping cart pages. Only jpg, png and gif formats allowed', 'Product Required Fields' => 'Product Required Fields', 'Product Title' => 'Product Title', 'Product Title of the Latest Purchased Product' => 'Product Title of the Latest Purchased Product', 'Product Welcome E-mail' => 'Product Welcome E-mail', 'Product categories keep empty to report all categories' => 'Product categories keep empty to report all categories', 'Product upgrade finished successfully' => 'Product upgrade finished successfully', 'Product(s)' => 'Product(s)', 'Product(s) Title' => 'Product(s) Title', 'Product(s) to display' => 'Product(s) to display', 'Products' => 'Products', 'Products keep empty to report all products' => 'Products keep empty to report all products', 'Products leave it empty to include all products' => 'Products leave it empty to include all products', 'Products IN (%s)' => 'Products IN (%s)', 'Products NOT IN (%s)' => 'Products NOT IN (%s)', 'Products from selected Categories' => 'Products from selected Categories', 'Products in this Brick is Optional (Not Required)' => 'Products in this Brick is Optional (Not Required)', 'Products not found. Click %shere%s to continue shopping.' => 'Products not found. Click %shere%s to continue shopping.', 'Profile' => 'Edit Profile', 'Profile Changed' => 'Profile Changed', 'Profile update transaction failed' => 'Profile update transaction failed', 'Protected Content [%s-%d]' => 'Protected Content [%s-%d]', 'Public Key Please include -----BEGIN PUBLIC KEY-----' => 'Public Key Please include -----BEGIN PUBLIC KEY-----', 'Publish' => 'Publish', 'Publish Date set it if you want to grant lifetime acces to this item for users with active subscription on this date' => 'Publish Date set it if you want to grant lifetime acces to this item for users with active subscription on this date', 'Purchase' => 'Purchase', 'Purchased Credits' => 'Purchased Credits', 'Qty' => 'Qty', 'Quantity' => 'Quantity', 'Quarter' => 'Quarter', 'Quarter (90 days)' => 'Quarter (90 days)', 'Questions with possible answers one question per line question and answers should be separated by pipe, for example Question1?|Answer1|Answer2|Answer3 Question2?|Answer1|Answer2 register of answers does not matter' => 'Questions with possible answers one question per line question and answers should be separated by pipe, for example Question1?|Answer1|Answer2|Answer3 Question2?|Answer1|Answer2 register of answers does not matter', 'Queue' => 'Queue', 'Quick Filter' => 'Quick Filter', 'Quick Order' => 'Quick Order', 'Quickpay parameters' => 'Quickpay parameters', 'Radio-buttons (one product can be selected)' => 'Radio-buttons (one product can be selected)', 'Random Questions' => 'Random Questions', 'Re-Open Ticket' => 'Re-Open Ticket', 'Read All Notifications' => 'Read All Notifications', 'Read-only' => 'Read-only', 'Real Path' => 'Real Path', 'Reason' => 'Reason', 'Rebuild' => 'Rebuild', 'Rebuild Completed!' => 'Rebuild Completed!', 'Rebuild Invoice Database' => 'Rebuild Invoice Database', 'Rebuild Invoices. Please wait...' => 'Rebuild Invoices. Please wait...', 'Rebuild completed. %sReturn%s' => 'Rebuild completed. %sReturn%s', 'Rebuild...' => 'Rebuild...', 'Receipt# Number Prefix If you change prefix numbers will start over from 1 You can use %year% shortcode in invoice number. It will be replaced to actual year For example: INV-%year%-' => 'Receipt# Number Prefix If you change prefix numbers will start over from 1 You can use %year% shortcode in invoice number. It will be replaced to actual year For example: INV-%year%-', 'Recipient' => 'Recipient', 'Recipient Email' => 'Recipient Email', 'Recipient Name' => 'Recipient Name', 'Record' => 'Record', 'Record Date' => 'Record Date', 'Record Type' => 'Record Type', 'Record [%s] not found' => 'Record [%s] not found', 'Records Per Page' => 'Records Per Page', 'Records that match all these conditions' => 'Records that match all these conditions', 'Rectifies Invoice Number: ' => 'Rectifies Invoice Number: ', 'Recurring' => 'Recurring', 'Recurring? Product must be recurring as well, First & Second periods will be taken from product config' => 'Recurring? Product must be recurring as well, First & Second periods will be taken from product config', 'Redirect URL aMember will redirect user to this url after account removal, User will be redirected to aMember root url in case of this option is empty' => 'Redirect URL aMember will redirect user to this url after account removal, User will be redirected to aMember root url in case of this option is empty', 'Redirect URL aMember will redirect user to this url after user click Accept button. User will be redirected to aMember root url in case of this option is empty' => 'Redirect URL aMember will redirect user to this url after user click Accept button. User will be redirected to aMember root url in case of this option is empty', 'Redirect Url you can use user specific placeholders in url %user.*% eg.: %user.email%, %user.login% etc.' => 'Redirect Url you can use user specific placeholders in url %user.*% eg.: %user.email%, %user.login% etc.', 'Redirect to NetDebit booking form.' => 'Redirect to NetDebit booking form.', 'Reference' => 'Reference', 'Reference number is:' => 'Reference number is:', 'Referer' => 'Referer', 'Referred Affiliate' => 'Referred Affiliate', 'Referred By' => 'Referred By', 'Refresh' => 'Refresh', 'Refresh 3-rd party lists' => 'Refresh 3-rd party lists', 'Refund' => 'Refund', 'Refund Amount' => 'Refund Amount', 'Refund Failed' => 'Refund Failed', 'Refund Receipt# Prefix If you change prefix numbers will start over from 1You can use %year% shortcode in invoice number. It will be replaced to actual year For example: RFND-%year%-' => 'Refund Receipt# Prefix If you change prefix numbers will start over from 1You can use %year% shortcode in invoice number. It will be replaced to actual year For example: RFND-%year%-', 'Refunded' => 'Refunded', 'Refunds by Used Coupon' => 'Refunds by Used Coupon', 'Regional Tax' => 'Regional Tax', 'Register' => 'Register', 'Registered' => 'Registered', 'Registration E-Mail to Subusers' => 'Registration E-Mail to Subusers', 'Registration country and your IP address country doesn\'t match. ' => 'Registration country and your IP address country doesn\'t match. ', 'Registrations are not allowed. Please contact webmaster for details.' => 'Registrations are not allowed. Please contact webmaster for details.', 'Remaining quantity' => 'Remaining quantity', 'Remote API Permissions' => 'Remote API Permissions', 'Remove' => 'Remove', 'Remove It From Signup Form' => 'Remove It From Signup Form', 'Remove Label' => 'Remove Label', 'Remove Mode action after new invoice completed' => 'Remove Mode action after new invoice completed', 'Remove My Account' => 'Remove My Account', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Remove Users when user record removed from aMember must the related record be removed from %s', 'Remove all user\'s pending invoices' => 'Remove all user\'s pending invoices', 'Remove user' => 'Remove user', 'Remove user\'s pending invoices that has either same product or product from same category as completed invoice' => 'Remove user\'s pending invoices that has either same product or product from same category as completed invoice', 'Remove user\'s pending invoices that has same product as completed invoice' => 'Remove user\'s pending invoices that has same product as completed invoice', 'Reply' => 'Reply', 'Report' => 'Report', 'Report Period Take into Account only subscriptions that began in defined period, keep empty to use all subscriptions' => 'Report Period Take into Account only subscriptions that began in defined period, keep empty to use all subscriptions', 'Requested Type To be used if you have multiple plans in one account and wish to select type of query you wish to make. By default the service uses the highest level available' => 'Requested Type To be used if you have multiple plans in one account and wish to select type of query you wish to make. By default the service uses the highest level available', 'Require Behaviour' => 'Require Behaviour', 'Required' => 'Required', 'Required Referral Number to get Bonus Subscription' => 'Required Referral Number to get Bonus Subscription', 'Required User Fields user must fill in these fields in order to pucrhase product' => 'Required User Fields user must fill in these fields in order to pucrhase product', 'Required Value' => 'Required Value', 'Reseller can log-in as subuser' => 'Reseller can log-in as subuser', 'Reseller can manage the following subuser fields' => 'Reseller can manage the following subuser fields', 'Reseller cannot delete subuser accounts' => 'Reseller cannot delete subuser accounts', 'Reseller cannot edit subusers accounts after insertion' => 'Reseller cannot edit subusers accounts after insertion', 'Resellers can delete subusers' => 'Resellers can delete subusers', 'Resellers can delete subusers only when limit is over' => 'Resellers can delete subusers only when limit is over', 'Resellers cannot delete subusers' => 'Resellers cannot delete subusers', 'Resellers-only page' => 'Resellers-only page', 'Resend Postback enter list of URLs to resend incoming postback' => 'Resend Postback enter list of URLs to resend incoming postback', 'Reset' => 'Reset', 'Reset Accept Status for Active Users of leave empty to reset for all users' => 'Reset Accept Status for Active Users of leave empty to reset for all users', 'Reset Accept Status for Users' => 'Reset Accept Status for Users', 'Reset Filter' => 'Reset Filter', 'Responsive' => 'Responsive', 'Resume Subscription' => 'Resume Subscription', 'Retention Rate' => 'Retention Rate', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt', 'Return' => 'Return', 'Return and try again' => 'Return and try again', 'Review/Pay Commissions' => 'Review/Pay Commissions', 'Reward Points' => 'Reward Points', 'Reward Points Configuration' => 'Reward Points Configuration', 'Right' => 'Right', 'Risk Score' => 'Risk Score', 'Risk Score Overall %sRisk Score%s (decimal from 0 to 10) For orders that return a fraud score of 2.5 and above, it is recommended to hold for review, or require the validation with the Telephone Verification service ' => 'Risk Score Overall %sRisk Score%s (decimal from 0 to 10) For orders that return a fraud score of 2.5 and above, it is recommended to hold for review, or require the validation with the Telephone Verification service ', 'Robots instructions for search engines' => 'Robots instructions for search engines', 'Rolling Conversion' => 'Rolling Conversion', 'Rolling Days' => 'Rolling Days', 'Rows Count per Page at Credits History page empty - it uses global settings' => 'Rows Count per Page at Credits History page empty - it uses global settings', 'Run Report' => 'Run Report', 'Running %s' => 'Running %s', 'Sales' => 'Sales', 'Save' => 'Save', 'Save As Preset for future quick access' => 'Save As Preset for future quick access', 'Save Profile' => 'Save Profile', 'Search' => 'Search', 'Search Products' => 'Search Products', 'Search Results' => 'Search Results', 'Search by Card Code' => 'Search by Card Code', 'Search by Voucher Code' => 'Search by Voucher Code', 'Second and Subsequent Payments' => 'Second and Subsequent Payments', 'Secret Key' => 'Secret Key', 'Secret key' => 'Secret key', 'Secure Payment' => 'Secure Payment', 'Security Code' => 'Security Code', 'Security code is either invalid or expired' => 'Security code is either invalid or expired', 'Security code is invalid' => 'Security code is invalid', 'See details' => 'See details', 'Select Payment Method' => 'Select Payment Method', 'Select Search Criteria' => 'Select Search Criteria', 'Select a condition to add into search' => 'Select a condition to add into search', 'Select all %s records matching your search' => 'Select all %s records matching your search', 'Select by default' => 'Select by default', 'Select-box (one product can be selected)' => 'Select-box (one product can be selected)', 'Selected Users has not any associated files' => 'Selected Users has not any associated files', 'Selectel storage is not configured' => 'Selectel storage is not configured', 'Self-Service' => 'Self-Service', 'Self-Service Setup' => 'Self-Service Setup', 'Self-Service Store' => 'Self-Service Store', 'Selz payout' => 'Selz payout', 'Send' => 'Send', 'Send Cancel Notifications to Admin' => 'Send Cancel Notifications to Admin', 'Send Cancel Notifications to User' => 'Send Cancel Notifications to User', 'Send Date' => 'Send Date', 'Send Email MD5 Hash method bypasses all blacklists, normalisation and obfuscation bypass checks' => 'Send Email MD5 Hash method bypasses all blacklists, normalisation and obfuscation bypass checks', 'Send Email with Gift Code at later date' => 'Send Email with Gift Code at later date', 'Send Free Payment Admin' => 'Send Free Payment Admin', 'Send Gift Card to Purchaser' => 'Send Gift Card to Purchaser', 'Send Gift Card to Recipient' => 'Send Gift Card to Recipient', 'Send Message' => 'Send Message', 'Send Notification To User Email' => 'Send Notification To User Email', 'Send Notification after XX since Last Sign In' => 'Send Notification after XX since Last Sign In', 'Send Payment Admin' => 'Send Payment Admin', 'Send Payment Link' => 'Send Payment Link', 'Send Payment Link default email template' => 'Send Payment Link default email template', 'Send Payment Mail' => 'Send Payment Mail', 'Send Reminder to Admin if coupon batch is almost empty' => 'Send Reminder to Admin if coupon batch is almost empty', 'Send Reminder to User if he has not logged in to site for a long time' => 'Send Reminder to User if he has not logged in to site for a long time', 'Send Security Code' => 'Send Security Code', 'Send Signup Mail' => 'Send Signup Mail', 'Send Voucher To' => 'Send Voucher To', 'Send opt-in/out emails' => 'Send opt-in/out emails', 'Sender Name' => 'Sender Name', 'Sending' => 'Sending', 'Sent' => 'Sent', 'Sent above notification in case of batch has less than ... coupons' => 'Sent above notification in case of batch has less than ... coupons', 'Sepaone' => 'Sepaone', 'Sequential Receipt# Numbering aMember still creates unique id for invoices, but it will generate PDF receipts for each payment that will be available in the member area for customers' => 'Sequential Receipt# Numbering aMember still creates unique id for invoices, but it will generate PDF receipts for each payment that will be available in the member area for customers', 'Serial Numbers' => 'Serial Numbers', 'Session Timeout, min' => 'Session Timeout, min', 'Session expired, please enter username and password again' => 'Session expired, please enter username and password again', 'Set LInk Expiration' => 'Set LInk Expiration', 'Set Successfully' => 'Set Successfully', 'Settings' => 'Settings', 'Shipping' => 'Shipping', 'Shipping Address Information' => 'Shipping Address Information', 'Shipping Options' => 'Shipping Options', 'Shipwire Shipping Address Brick' => 'Shipwire Shipping Address Brick', 'Shop Id Unique Shop ID in the system' => 'Shop Id Unique Shop ID in the system', 'Shopping Cart' => 'Shopping Cart', 'Shopping Cart Module. No data input' => 'Shopping Cart Module. No data input', 'Shopping Cart Module. No product id input' => 'Shopping Cart Module. No product id input', 'Shopping Cart Signup' => 'Shopping Cart Signup', 'Show' => 'Show', 'Show Link only if customer has no subscription (optional)' => 'Show Link only if customer has no subscription (optional)', 'Show Tax even it is 0' => 'Show Tax even it is 0', 'Show error and do not allow to login until session timeout' => 'Show error and do not allow to login until session timeout', 'Show these fields' => 'Show these fields', 'Sign-up' => 'Sign-up', 'Signature' => 'Signature', 'Signup Form' => 'Signup Form', 'Signup here' => 'Signup here', 'Signup/payment functions are disabled for this user account' => 'Signup/payment functions are disabled for this user account', 'Simple Search Users' => 'Simple Search Users', 'Single Checkbox' => 'Single Checkbox', 'Single Login Session' => 'Single Login Session', 'Site Title' => 'Site Title', 'Skip First Line' => 'Skip First Line', 'Skrill E-Mail' => 'Skrill E-Mail', 'Sliiing Billers' => 'Sliiing Billers', 'Snippets' => 'Snippets', 'Software' => 'Software', 'Software Download' => 'Software Download', 'Software Downloads' => 'Software Downloads', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Sorry, it is impossible to use this payment method for this order. Please select another payment method', 'Sorry, license re-activation limit reached' => 'Sorry, license re-activation limit reached', 'Sorry, seems you have used wrong link' => 'Sorry, seems you have used wrong link', 'Sorry, we have not found an activation record to deactivate' => 'Sorry, we have not found an activation record to deactivate', 'Sorry, you have already reached limit of activations (%d active, %d allowed)' => 'Sorry, you have already reached limit of activations (%d active, %d allowed)', 'Sort code' => 'Sort code', 'Source Code — Copy/Paste Into Your Website' => 'Source Code — Copy/Paste Into Your Website', 'Spam Report' => 'Spam Report', 'Spam Reports' => 'Spam Reports', 'Spam threshold 0-255' => 'Spam threshold 0-255', 'Specific User' => 'Specific User', 'Specified folder is not writable - please chmod the folder to 777, so aMember can write .htaccess file for folder protection' => 'Specified folder is not writable - please chmod the folder to 777, so aMember can write .htaccess file for folder protection', 'Spent Amount' => 'Spent Amount', 'Standard' => 'Standard', 'Standard VAT Rates' => 'Standard VAT Rates', 'Standard VAT Rates, %' => 'Standard VAT Rates, %', 'Start' => 'Start', 'Start Date' => 'Start Date', 'State' => 'State', 'State Title' => 'State Title', 'Statistics' => 'Statistics', 'Status' => 'Status', 'Status of your subscription has been changed.' => 'Status of your subscription has been changed.', 'Stay signed in' => 'Stay signed in', 'Street' => 'Street', 'Street (Second Line)' => 'Street (Second Line)', 'Street Address' => 'Street Address', 'Street Address (Second Line)' => 'Street Address (Second Line)', 'Sub-Affiliates' => 'Sub-Affiliates', 'SubUsers Count (keep zero for non-reseller products)' => 'SubUsers Count (keep zero for non-reseller products)', 'SubUsers Product (keep empty for non-reseller products)' => 'SubUsers Product (keep empty for non-reseller products)', 'Subject' => 'Subject', 'Subject can not be empty' => 'Subject can not be empty', 'Subject or Ticket#' => 'Subject or Ticket#', 'Submit' => 'Submit', 'Submit Details' => 'Submit Details', 'Submit New Ticket' => 'Submit New Ticket', 'Subscribe And Pay' => 'Subscribe And Pay', 'Subscribe Now' => 'Subscribe Now', 'Subscribe all available users' => 'Subscribe all available users', 'Subscribe to Site Newsletters' => 'Subscribe to Site Newsletters', 'Subscribed To Newsletters' => 'Subscribed To Newsletters', 'Subscribed to Newsletter Lists' => 'Subscribed to Newsletter Lists', 'Subscribed to any of (including expired)' => 'Subscribed to any of (including expired)', 'Subscribers' => 'Subscribers', 'Subscription Limit' => 'Subscription Limit', 'Subscription Terms' => 'Subscription Terms', 'Subscription expired, please contact your reseller to upgrade subscription' => 'Subscription expired, please contact your reseller to upgrade subscription', 'Subscription limit' => 'Subscription limit', 'Subscription limit for each user' => 'Subscription limit for each user', 'Subscription/Product Title' => 'Subscription/Product Title', 'Subtotal' => 'Subtotal', 'Subuser e-mail address can be changed by site admin only' => 'Subuser e-mail address can be changed by site admin only', 'Subusers' => 'Subusers', 'Subusers Assigned To (reseller username or id#):' => 'Subusers Assigned To (reseller username or id#):', 'Subusers Assigned To [%s #%d]' => 'Subusers Assigned To [%s #%d]', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)', 'Successfull update' => 'Successfull update', 'Such affiliate ID exist' => 'Such affiliate ID exist', 'Sum all available limits' => 'Sum all available limits', 'Super Groups Plugin will not remove these groups from user\'s account. This is useful if you add additional group to user manually and this group is not linked to any product. If that additional group is not added to Super groups, it will be removed when plugin updates user account' => 'Super Groups Plugin will not remove these groups from user\'s account. This is useful if you add additional group to user manually and this group is not linked to any product. If that additional group is not added to Super groups, it will be removed when plugin updates user account', 'Super Groups aMember will not remove %s groups from user\'s account This is useful if you add additional group to user in %s manually and this group is not linked to any aMember product If that additional group is not added to Super groups, it will be removed when aMember updates user account' => 'Super Groups aMember will not remove %s groups from user\'s account This is useful if you add additional group to user in %s manually and this group is not linked to any aMember product If that additional group is not added to Super groups, it will be removed when aMember updates user account', 'Support' => 'Support', 'Support Us!' => 'Support Us!', 'Surrender' => 'Surrender', 'Switch default identity block with block with avatar' => 'Switch default identity block with block with avatar', 'THEN YOU RECEIVE' => 'THEN YOU RECEIVE', 'TOTAL' => 'TOTAL', 'Tags' => 'Tags', 'Tags comma separated list of tags' => 'Tags comma separated list of tags', 'Take' => 'Take', 'Target' => 'Target', 'Target By User' => 'Target By User', 'Target Folder URL' => 'Target Folder URL', 'Target URL' => 'Target URL', 'Tax' => 'Tax', 'Tax Amount' => 'Tax Amount', 'Tax Id' => 'Tax Id', 'Tax Rate' => 'Tax Rate', 'Tax Rate for example 18.5 (no percent sign)' => 'Tax Rate for example 18.5 (no percent sign)', 'Tax Report' => 'Tax Report', 'Tax Title' => 'Tax Title', 'Tax Value' => 'Tax Value', 'Tax by Customer Country' => 'Tax by Customer Country', 'Taxable Income' => 'Taxable Income', 'Taxable Subtotal' => 'Taxable Subtotal', 'Template' => 'Template', 'Terms' => 'Terms', 'Test Mode' => 'Test Mode', 'Test Mode Enabled The cents part of the amount you pass to DirectOne will determine the response code for the test script. For example, an amount of 100 ($1.00) with return a response of 00 which represents an approved transaction response. An amount of 151 ($1.51) will return a response of 51 which represents a declined transaction response.' => 'Test Mode Enabled The cents part of the amount you pass to DirectOne will determine the response code for the test script. For example, an amount of 100 ($1.00) with return a response of 00 which represents an approved transaction response. An amount of 151 ($1.51) will return a response of 51 which represents a declined transaction response.', 'Test Settings' => 'Test Settings', 'Text to Add to each PDF file This text will be included at bottom to PDF fileYou can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.' => 'Text to Add to each PDF file This text will be included at bottom to PDF fileYou can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.', 'Thank you for Signing up' => 'Thank you for Signing up', 'Thank you for your purchase. Your subscription will become active as soon as the payment has been verified.' => 'Thank you for your purchase. Your subscription will become active as soon as the payment has been verified.', 'Thank you! We sent invite code to your friend.' => 'Thank you! We sent invite code to your friend.', 'Thanks Success' => 'Thanks Success', 'Thanks for the payment request. It may take up to 48 hours....' => 'Thanks for the payment request. It may take up to 48 hours....', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.', 'The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).' => 'The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).', 'The coupon entered is not valid with any product(s) being purchased. No discount will be applied' => 'The coupon entered is not valid with any product(s) being purchased. No discount will be applied', 'The database has encountered a problem, please try again later.' => 'The database has encountered a problem, please try again later.', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'The file has been removed from disk or corrupted. Please re-upload it.', 'The following words are reserved : %s' => 'The following words are reserved : %s', 'The information you have entered is incorrect. Username [%s] does not exist in database' => 'The information you have entered is incorrect. Username [%s] does not exist in database', 'The maximum amount is %s' => 'The maximum amount is %s', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying', 'The minimum amount is %s' => 'The minimum amount is %s', 'The minimum donation amount is %s' => 'The minimum donation amount is %s', 'The password should be at least %d characters long' => 'The password should be at least %d characters long', 'The result is filtered.' => 'The result is filtered.', 'The user name or password is incorrect' => 'The user name or password is incorrect', 'There are %d pending subuser subscriptions. %sUpgrade your access%s' => 'There are %d pending subuser subscriptions. %sUpgrade your access%s', 'There are no confirmed payments for your account' => 'There are no confirmed payments for your account', 'There are no form available for affiliate signup.' => 'There are no form available for affiliate signup.', 'There are no products available for purchase. Please come back later.' => 'There are no products available for purchase. Please come back later.', 'There are no products available to order with credits' => 'There are no products available to order with credits', 'There is %d active login session for this user from following IP address(es): %s' => 'There is %d active login session for this user from following IP address(es): %s', 'There is issue with second factor Authentication' => 'There is issue with second factor Authentication', 'There is not such amount (%d) of product %s' => 'There is not such amount (%d) of product %s', 'There is not such amount (%d) of product %s you can purchase only %s items.' => 'There is not such amount (%d) of product %s you can purchase only %s items.', 'These details can be found on your cheque book, bank statement, or bank card' => 'These details can be found on your cheque book, bank statement, or bank card', 'This %s is blocked. Please contact site support to find out why' => 'This %s is blocked. Please contact site support to find out why', 'This Coupon Code is already being used, please select another one' => 'This Coupon Code is already being used, please select another one', 'This Month' => 'This Month', 'This Quarter' => 'This Quarter', 'This Week (Mon-Sun)' => 'This Week (Mon-Sun)', 'This Week (Sun-Sat)' => 'This Week (Sun-Sat)', 'This Year' => 'This Year', 'This coupon belongs to another customer' => 'This coupon belongs to another customer', 'This customer is a reseller' => 'This customer is a reseller', 'This customer is a subuser of' => 'This customer is a subuser of', 'This customer was invited by %s' => 'This customer was invited by %s', 'This field is a requried field' => 'This field is a requried field', 'This field is required' => 'This field is required', 'This is a required field' => 'This is a required field', 'This page will be automatically refreshed within %s' => 'This page will be automatically refreshed within %s', 'This payment system could not handle payments in [%s] currency' => 'This payment system could not handle payments in [%s] currency', 'This payment system could not handle recurring subscriptions' => 'This payment system could not handle recurring subscriptions', 'This payment system could not handle zero-total invoices' => 'This payment system could not handle zero-total invoices', 'This payment system doesn\'t support Trial Periods' => 'This payment system doesn\'t support Trial Periods', 'This paysystem can not work with multiple products in card' => 'This paysystem can not work with multiple products in card', 'This plugin can not handle recurring subscriptions with free trial' => 'This plugin can not handle recurring subscriptions with free trial', 'This report works only with radio and select fields. You have not such custom fields yet.' => 'This report works only with radio and select fields. You have not such custom fields yet.', 'Thresehold Date' => 'Thresehold Date', 'Threshold Date' => 'Threshold Date', 'Ticket' => 'Ticket', 'Ticket Roster' => 'Ticket Roster', 'Ticket has been submited' => 'Ticket has been submited', 'Tickets' => 'Tickets', 'Tier' => 'Tier', 'Title' => 'Title', 'Title Just for your reference' => 'Title Just for your reference', 'Title for link to Personal Folder in member area' => 'Title for link to Personal Folder in member area', 'To' => 'To', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.', 'To add new user groups %sClick here%s.' => 'To add new user groups %sClick here%s.', 'To assign groups to products %sClick here%s.' => 'To assign groups to products %sClick here%s.', 'Today' => 'Today', 'Token is empy in response object' => 'Token is empy in response object', 'Token value' => 'Token value', 'Too many Lost Password requests. Please wait 180 minutes for retrying' => 'Too many Lost Password requests. Please wait 180 minutes for retrying', 'Top Affiliate' => 'Top Affiliate', 'Top Affiliates by Points' => 'Top Affiliates by Points', 'Top Margin How much [pt] skip from top of template before start to output invoice 1 pt = 0.352777 mm' => 'Top Margin How much [pt] skip from top of template before start to output invoice 1 pt = 0.352777 mm', 'Total' => 'Total', 'Total Amount of Payment' => 'Total Amount of Payment', 'Total Price' => 'Total Price', 'Total Records: %s' => 'Total Records: %s', 'Track Only Initial Payment for recurring subscription aMember notify iDevAffiliate only about initial payment' => 'Track Only Initial Payment for recurring subscription aMember notify iDevAffiliate only about initial payment', 'Transaction aborted by user.' => 'Transaction aborted by user.', 'Transaction failed' => 'Transaction failed', 'Transaction reference: %s' => 'Transaction reference: %s', 'Transactions' => 'Transactions', 'Transactions History' => 'Transactions History', 'Try again' => 'Try again', 'Trying to load foreign subuser' => 'Trying to load foreign subuser', 'Two-Factor Authentication (%s)' => 'Two-Factor Authentication (%s)', 'Type' => 'Type', 'Type Username or E-Mail' => 'Type Username or E-Mail', 'Type a keyword to search in FAQ' => 'Type a keyword to search in FAQ', 'URL' => 'URL', 'USA (Letter)' => 'USA (Letter)', 'Unable to cancel subscription: ' => 'Unable to cancel subscription: ', 'Unable to delete this file as it is used for:' => 'Unable to delete this file as it is used for:', 'Unable to handle invoice, class: %s undefined' => 'Unable to handle invoice, class: %s undefined', 'Unassign Affiliate' => 'Unassign Affiliate', 'Unassign Partner' => 'Unassign Partner', 'Unassign this Ticket from yourself' => 'Unassign this Ticket from yourself', 'Unchecked' => 'Unchecked', 'Undefined' => 'Undefined', 'Underscore is not allowed for username' => 'Underscore is not allowed for username', 'Unenroll Student' => 'Unenroll Student', 'Unique Clicks' => 'Unique Clicks', 'Unit Price' => 'Unit Price', 'Unknown' => 'Unknown', 'Unknown period unit: %s' => 'Unknown period unit: %s', 'Unlimited' => 'Unlimited', 'Unsubscribe' => 'Unsubscribe', 'Unsubscribe by Existing Reports' => 'Unsubscribe by Existing Reports', 'Unsubscribe by Webhooks' => 'Unsubscribe by Webhooks', 'Unsubscribe customer from selected newsletter threads' => 'Unsubscribe customer from selected newsletter threads', 'Unsubscribe from all e-mail messages' => 'Unsubscribe from all e-mail messages', 'Unsubscribed' => 'Unsubscribed', 'Unsubscription Confirmation' => 'Unsubscription Confirmation', 'Update' => 'Update', 'Update Credit Card' => 'Update Credit Card', 'Update Credit Card Info' => 'Update Credit Card Info', 'Update Debit Card Info' => 'Update Debit Card Info', 'Update Echeck Info' => 'Update Echeck Info', 'Update Iban Info' => 'Update Iban Info', 'Update Password' => 'Update Password', 'Update eCheck Info' => 'Update eCheck Info', 'Update failed' => 'Update failed', 'Updated' => 'Updated', 'Upgrade Invoice' => 'Upgrade Invoice', 'Upgrade Status' => 'Upgrade Status', 'Upgrade Subscription' => 'Upgrade Subscription', 'Upgrades for "%s"' => 'Upgrades for "%s"', 'Upload Categories' => 'Upload Categories', 'Upload Category' => 'Upload Category', 'Upload File' => 'Upload File', 'Upload File to Active Users of' => 'Upload File to Active Users of', 'Upload files using FTP client to [%s]' => 'Upload files using FTP client to [%s]', 'Uploaded' => 'Uploaded', 'Uploaded File Category' => 'Uploaded File Category', 'Uploaded File Names' => 'Uploaded File Names', 'Uploaded Files' => 'Uploaded Files', 'Uploads' => 'Uploads', 'Use Custom Validation Settings otherwise Validation settings from field definition is used' => 'Use Custom Validation Settings otherwise Validation settings from field definition is used', 'Use Database Connection other than configured for aMember' => 'Use Database Connection other than configured for aMember', 'Use MaxMind Credit Card Fraud Detection' => 'Use MaxMind Credit Card Fraud Detection', 'Use Pre-Defined Template' => 'Use Pre-Defined Template', 'Use Reward Points' => 'Use Reward Points', 'Use SSL for Authenticated URLs enable this option if you use https for your site' => 'Use SSL for Authenticated URLs enable this option if you use https for your site', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked', 'Use another card' => 'Use another card', 'Use different profile form for subusers' => 'Use different profile form for subusers', 'Use maximum from available' => 'Use maximum from available', 'Use normal, non customized invoice' => 'Use normal, non customized invoice', 'Used' => 'Used', 'Used Any Coupon' => 'Used Any Coupon', 'Used Coupon' => 'Used Coupon', 'Used Coupon from Batch: %s' => 'Used Coupon from Batch: %s', 'Used Coupon with Code: %s' => 'Used Coupon with Code: %s', 'Useful Links' => 'Useful Links', 'User' => 'User', 'User %s' => 'User %s', 'User %s is already working on this ticket.' => 'User %s is already working on this ticket.', 'User %s not found' => 'User %s not found', 'User Affiliate Link' => 'User Affiliate Link', 'User Agreement' => 'User Agreement', 'User Base Fields' => 'User Base Fields', 'User City' => 'User City', 'User Country' => 'User Country', 'User Demographics' => 'User Demographics', 'User Distribution by Custom Field' => 'User Distribution by Custom Field', 'User First Name' => 'User First Name', 'User Group' => 'User Group', 'User Groups' => 'User Groups', 'User ID' => 'User ID', 'User Info' => 'User Info', 'User Internal ID#' => 'User Internal ID#', 'User Last Name' => 'User Last Name', 'User Personal Folder URL' => 'User Personal Folder URL', 'User Phone' => 'User Phone', 'User Search' => 'User Search', 'User State' => 'User State', 'User Status (0-pending, 1-active, 2-expired)' => 'User Status (0-pending, 1-active, 2-expired)', 'User Street' => 'User Street', 'User Street (Second Line)' => 'User Street (Second Line)', 'User Subscriptions Status' => 'User Subscriptions Status', 'User Unsubscribe Link' => 'User Unsubscribe Link', 'User ZIP' => 'User ZIP', 'User can Choose Product in any Brick of Such Type on Page but he Should Choose at least One Product still' => 'User can Choose Product in any Brick of Such Type on Page but he Should Choose at least One Product still', 'User can choose to make donation recurring' => 'User can choose to make donation recurring', 'User is locked' => 'User is locked', 'User is not approved' => 'User is not approved', 'User limit in FileRun is already reached' => 'User limit in FileRun is already reached', 'User must provide' => 'User must provide', 'User should have/had access in same month as publish date' => 'User should have/had access in same month as publish date', 'User should have/had acecss on publish date exactly' => 'User should have/had acecss on publish date exactly', 'Username' => 'Username', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore', 'Username %s is already taken. Please choose another username' => 'Username %s is already taken. Please choose another username', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore', 'Username [%s] is already taken. Please choose another username' => 'Username [%s] is already taken. Please choose another username', 'Username and password can not be the same' => 'Username and password can not be the same', 'Username contains invalid characters - please use digits, letters or spaces' => 'Username contains invalid characters - please use digits, letters or spaces', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Username contains invalid characters - please use digits, letters, dash and underscore', 'Username/Email' => 'Username/Email', 'Users Take into Account only user who sign up in defined period, keep empty to use all user' => 'Users Take into Account only user who sign up in defined period, keep empty to use all user', 'Users subscribed to Newsletter Threads #' => 'Users subscribed to Newsletter Threads #', 'VAT Id' => 'VAT Id', 'VAT Rates Group' => 'VAT Rates Group', 'VAT Settings are incorrect - no Vat Id configured' => 'VAT Settings are incorrect - no Vat Id configured', 'Validate E-Mail Address by sending e-mail message with code' => 'Validate E-Mail Address by sending e-mail message with code', 'Validate Location even if Invoice has no VAT Validate All New Invoices (even if invoice has no VAT) If unchecked, location will be validated only when user selects country inside EU and only if VAT should be applied to invoice. Free invoices won\'t be validated still' => 'Validate Location even if Invoice has no VAT Validate All New Invoices (even if invoice has no VAT) If unchecked, location will be validated only when user selects country inside EU and only if VAT should be applied to invoice. Free invoices won\'t be validated still', 'Validation' => 'Validation', 'Value' => 'Value', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation', 'Verify Email Profile' => 'Verify Email Profile', 'Verify Email Signup' => 'Verify Email Signup', 'Version' => 'Version', 'Version of script' => 'Version of script', 'Versions' => 'Versions', 'Video' => 'Video', 'View Basket' => 'View Basket', 'Visit %sorder page%s to order additional subscriptions' => 'Visit %sorder page%s to order additional subscriptions', 'Void' => 'Void', 'Void Amount' => 'Void Amount', 'Voucher Code Length' => 'Voucher Code Length', 'Voucher is already used' => 'Voucher is already used', 'Voucher is expired' => 'Voucher is expired', 'Voucher is not yet active' => 'Voucher is not yet active', 'Watchers' => 'Watchers', 'Watchers notify the following admins about new messages in this ticket' => 'Watchers notify the following admins about new messages in this ticket', 'We ask you to update your password periodically for security reason.' => 'We ask you to update your password periodically for security reason.', 'We review all affiliates manually, so your affiliate account status is pending. You will receive email when your account will be approved. Thank you for your patience.' => 'We review all affiliates manually, so your affiliate account status is pending. You will receive email when your account will be approved. Thank you for your patience.', 'We updated our Terms & Conditions. Please accept new one.' => 'We updated our Terms & Conditions. Please accept new one.', 'Webhooks' => 'Webhooks', 'Week' => 'Week', 'Weeks' => 'Weeks', 'Wepay does not support trial periods!' => 'Wepay does not support trial periods!', 'What to Display' => 'What to Display', 'What to Submit?' => 'What to Submit?', 'Who is paying the fee' => 'Who is paying the fee', 'Widget' => 'Widget', 'Write your comment...' => 'Write your comment...', 'Write your reply...' => 'Write your reply...', 'Wrong code or code expired - please start signup process again' => 'Wrong code or code expired - please start signup process again', 'Wrong columns count. Please use exact format for import file: %s' => 'Wrong columns count. Please use exact format for import file: %s', 'Wrong link - no id passed' => 'Wrong link - no id passed', 'Wrong parameters, error #1253' => 'Wrong parameters, error #1253', 'Wrong password' => 'Wrong password', 'Wrong path: not a folder: %s' => 'Wrong path: not a folder: %s', 'Wrong step' => 'Wrong step', 'Wrong value submitted' => 'Wrong value submitted', 'Wrong verification code' => 'Wrong verification code', 'Wrongly signed URL, please contact site admin' => 'Wrongly signed URL, please contact site admin', 'Year' => 'Year', 'Years' => 'Years', 'Yes' => 'Yes', 'Yes, I want to cancel subscription' => 'Yes, I want to cancel subscription', 'Yes, I want to remove my account with all associated info on this site' => 'Yes, I want to remove my account with all associated info on this site', 'Yes, continue' => 'Yes, continue', 'Yes, is a subuser' => 'Yes, is a subuser', 'Yes, unsubscribe' => 'Yes, unsubscribe', 'Yesterday' => 'Yesterday', 'You are going to download "%s" file. %s credit will be deducted from your balance. You have %s credits.' => 'You are going to download "%s" file. %s credit will be deducted from your balance. You have %s credits.', 'You are logged-in as' => 'You are logged-in as', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'You are logged-in as %s. %sLogout%s to signup as new user.', 'You are trying to access disabled module [%s]' => 'You are trying to access disabled module [%s]', 'You can assign some coupon codes to specific affiliate. Whenever coupon is used, commission will always be credited to this affiliate. This is true even when another affiliate is permanently tagged to the customer. For sales where the coupon is NOT used, the original (previous) affiliate will continue receiving commissions. If the customer has no affiliate, this affiliate will permanently be tagged to the customer, and will receive credit for future sales.' => 'You can assign some coupon codes to specific affiliate. Whenever coupon is used, commission will always be credited to this affiliate. This is true even when another affiliate is permanently tagged to the customer. For sales where the coupon is NOT used, the original (previous) affiliate will continue receiving commissions. If the customer has no affiliate, this affiliate will permanently be tagged to the customer, and will receive credit for future sales.', 'You can change Number of %sRecords per Page%s in section %sSetup/Configuration%s' => 'You can change Number of %sRecords per Page%s in section %sSetup/Configuration%s', 'You can find info regarding pdf invoice customization %shere%s' => 'You can find info regarding pdf invoice customization %shere%s', 'You can get this token from the Authy mobile app. Otherwise you should receive SMS with token.' => 'You can get this token from the Authy mobile app. Otherwise you should receive SMS with token.', 'You can not merge ordinary user with subuser and vice versa' => 'You can not merge ordinary user with subuser and vice versa', 'You can not merge subusers of different user' => 'You can not merge subusers of different user', 'You can not use your own email' => 'You can not use your own email', 'You can remove your account in our system.' => 'You can remove your account in our system.', 'You can\'t use your affiliate coupon code' => 'You can\'t use your affiliate coupon code', 'You don;t have permission to access this area' => 'You don;t have permission to access this area', 'You have %d items in shopping cart' => 'You have %d items in shopping cart', 'You have %d items in your Basket' => 'You have %d items in your Basket', 'You have %s credits (%sTransaction History%s)' => 'You have %s credits (%sTransaction History%s)', 'You have %s%d ticket(s)%s that require your attention' => 'You have %s%d ticket(s)%s that require your attention', 'You have no access to %s' => 'You have no access to %s', 'You have no active subscriptions' => 'You have no active subscriptions', 'You have no enough permissions for this operation' => 'You have no enough permissions for this operation', 'You have no items in shopping cart' => 'You have no items in shopping cart', 'You have no items in your basket - please add something to your basket before checkout' => 'You have no items in your basket - please add something to your basket before checkout', 'You have no saved credit card at OpenGateway' => 'You have no saved credit card at OpenGateway', 'You have no subscription' => 'You have no subscription', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'You have too many subusers assigned to this account. You may choose to remove %d users from your account', 'You must be authorized to access this area' => 'You must be authorized to access this area', 'You must be logged-in to open this media' => 'You must be logged-in to open this media', 'You must be logged-in to run this action' => 'You must be logged-in to run this action', 'You must be logged-in to use this function' => 'You must be logged-in to use this function', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype', 'Your 9 digit ABA Routing Number' => 'Your 9 digit ABA Routing Number', 'Your API Key' => 'Your API Key', 'Your Account Removal' => 'Your Account Removal', 'Your BIC Bank Identifier Code' => 'Your BIC Bank Identifier Code', 'Your Bank Account Number' => 'Your Bank Account Number', 'Your Bank Account Number Up to 20 digits' => 'Your Bank Account Number Up to 20 digits', 'Your Basket' => 'Your Basket', 'Your Cart' => 'Your Cart', 'Your Cellphone' => 'Your Cellphone', 'Your Credits Balance: ' => 'Your Credits Balance: ', 'Your Current Password' => 'Your Current Password', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Your Current Password if you are changing password, please enter your current password for validation', 'Your Custom Affiliate Link' => 'Your Custom Affiliate Link', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Your E-Mail Address a confirmation email will be sent to you at this address', 'Your General Affiliate Link' => 'Your General Affiliate Link', 'Your IBAN International Bank Account Number' => 'Your IBAN International Bank Account Number', 'Your Leads' => 'Your Leads', 'Your Membership Information' => 'Your Membership Information', 'Your Message' => 'Your Message', 'Your Message to Recipient included to email with Gift Card' => 'Your Message to Recipient included to email with Gift Card', 'Your Name your first and last name' => 'Your Name your first and last name', 'Your Password' => 'Your Password', 'Your Payment is PENDING & Under Process' => 'Your Payment is PENDING & Under Process', 'Your Personal Downloads' => 'Your Personal Downloads', 'Your Personal Uploads' => 'Your Personal Uploads', 'Your Reseller Packages' => 'Your Reseller Packages', 'Your Reseller Signup Form URL' => 'Your Reseller Signup Form URL', 'Your Subscriptions' => 'Your Subscriptions', 'Your Username' => 'Your Username', 'Your Zendesk Agent Email Address' => 'Your Zendesk Agent Email Address', 'Your account has been automatically locked.' => 'Your account has been automatically locked.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.', 'Your account require additional authentification factor' => 'Your account require additional authentification factor', 'Your answer is wrong' => 'Your answer is wrong', 'Your card details have been updated.' => 'Your card details have been updated.', 'Your cart is empty. Click %shere%s to continue shopping.' => 'Your cart is empty. Click %shere%s to continue shopping.', 'Your content on Amazon S3 should not be public. Please restrict public access to your files on Amazon S3 side and ensure you can not access it directly from Amazon S3. aMember use Access Key and Secret Key to generate links with authentication token for users to provide access them to your content on Amazon S3.' => 'Your content on Amazon S3 should not be public. Please restrict public access to your files on Amazon S3 side and ensure you can not access it directly from Amazon S3. aMember use Access Key and Secret Key to generate links with authentication token for users to provide access them to your content on Amazon S3.', 'Your credit card statement will show a charge from ClickBank or CLKBANK*COM' => 'Your credit card statement will show a charge from ClickBank or CLKBANK*COM', 'Your download will start shortly. Click %s this link %s if you don\'t want to wait any longer...' => 'Your download will start shortly. Click %s this link %s if you don\'t want to wait any longer...', 'Your password has been changed successfully. You can %slogin to your account%s with new password.' => 'Your password has been changed successfully. You can %slogin to your account%s with new password.', 'Your password has been e-mailed to you. Please check your mailbox' => 'Your password has been e-mailed to you. Please check your mailbox', 'Your password is too long' => 'Your password is too long', 'Your payment has been successfully processed.' => 'Your payment has been successfully processed.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.', 'Your profile has been updated successfully' => 'Your profile has been updated successfully', 'Your sales domain in justclick eg. username.justclick.ru' => 'Your sales domain in justclick eg. username.justclick.ru', 'Your subject is too verbose' => 'Your subject is too verbose', 'Your subscription does not allow access to this media' => 'Your subscription does not allow access to this media', 'Your subscription has been successfully processed.' => 'Your subscription has been successfully processed.', 'Your upgrade is being processed please wait' => 'Your upgrade is being processed please wait', 'ZIP' => 'ZIP', 'ZIP Code' => 'ZIP Code', 'Zip' => 'Zip', 'Zipcode' => 'Zipcode', '[Select country]' => '[Select country]', '[Select state]' => '[Select state]', '_default_locale' => 'en_US', 'aMember Payment Process' => 'aMember Payment Process', 'aMember Root URL' => 'aMember Root URL', 'accepts all major credit cards' => 'accepts all major credit cards', 'add access to selected product even if user choose 0 donation amount' => 'add access to selected product even if user choose 0 donation amount', 'added between %s and %s' => 'added between %s and %s', 'admin' => 'admin', 'affiliate <-> user relation is expired (%saccording your settings%s User-Affiliate Relation Lifetime is %d day(s)), no commissions will be added for new payments' => 'affiliate <-> user relation is expired (%saccording your settings%s User-Affiliate Relation Lifetime is %d day(s)), no commissions will be added for new payments', 'affiliate program commissions' => 'affiliate program commissions', 'after completing order, voucher will be sent to specified address' => 'after completing order, voucher will be sent to specified address', 'ago' => 'ago', 'all requests will be added to %sLogs%s, useful if something is going wrong' => 'all requests will be added to %sLogs%s, useful if something is going wrong', 'any product' => 'any product', 'as chosen on signup page' => 'as chosen on signup page', 'assigned to usergroups [%s]' => 'assigned to usergroups [%s]', 'back to full report' => 'back to full report', 'banned' => 'banned', 'begins' => 'begins', 'both First and Last Name' => 'both First and Last Name', 'both First and Last Name in Single Input' => 'both First and Last Name in Single Input', 'cancel' => 'cancel', 'card declined' => 'card declined', 'check box to use points and get discount' => 'check box to use points and get discount', 'check expired subscriptions too' => 'check expired subscriptions too', 'check future subscriptions too' => 'check future subscriptions too', 'check it if you want to gift subscription on this product' => 'check it if you want to gift subscription on this product', 'choose a version' => 'choose a version', 'click to see password' => 'click to see password', 'click to upload' => 'click to upload', 'commission found by next rules' => 'commission found by next rules', 'configure' => 'configure', 'count of all invoices by theme' => 'count of all invoices by theme', 'count of non invoices by theme' => 'count of non invoices by theme', 'count of paid invoices by signup form' => 'count of paid invoices by signup form', 'count of paid invoices by theme' => 'count of paid invoices by theme', 'day' => 'day', 'days' => 'days', 'delete' => 'delete', 'delivery confirmation' => 'delivery confirmation', 'different currency products' => 'different currency products', 'different rebill times subscriptions' => 'different rebill times subscriptions', 'different the first period subscriptions' => 'different the first period subscriptions', 'different the second period subscriptions' => 'different the second period subscriptions', 'disable' => 'disable', 'displaying records %s-%s from %s' => 'displaying records %s-%s from %s', 'download' => 'download', 'email' => 'email', 'email will contain this sentence' => 'email will contain this sentence', 'empty - use global setting if 0 - without limit' => 'empty - use global setting if 0 - without limit', 'expiration' => 'expiration', 'expires' => 'expires', 'filter' => 'filter', 'filtered' => 'filtered', 'for affiliate commission payouts' => 'for affiliate commission payouts', 'for example: 1111-2222-3333-4444' => 'for example: 1111-2222-3333-4444', 'for example: 1111222233334444' => 'for example: 1111222233334444', 'free' => 'free', 'generate' => 'generate', 'has all values selected' => 'has all values selected', 'has not used payment system %s' => 'has not used payment system %s', 'has used payment system %s' => 'has used payment system %s', 'have invoice for %s that canceled between %s and %s' => 'have invoice for %s that canceled between %s and %s', 'have invoice for %s that started between %s and %s' => 'have invoice for %s that started between %s and %s', 'have no active subscriptions to %s' => 'have no active subscriptions to %s', 'have payment for %s that made between %s and %s' => 'have payment for %s that made between %s and %s', 'have subscription for %s that expire between %s and %s' => 'have subscription for %s that expire between %s and %s', 'have subscription for %s between %s and %s' => 'have subscription for %s between %s and %s', 'have subscription for %s for date %s ' => 'have subscription for %s for date %s ', 'hide if logged-in' => 'hide if logged-in', 'hrs' => 'hrs', 'iDEAL betaling' => 'iDEAL betaling', 'if' => 'if', 'if applicable (product is recurring)' => 'if applicable (product is recurring)', 'if not specified, voucher will be sent to your email' => 'if not specified, voucher will be sent to your email', 'including pending records' => 'including pending records', 'increase price after every defined number of days/hours/sales' => 'increase price after every defined number of days/hours/sales', 'internal error, please repeat payment later' => 'internal error, please repeat payment later', 'ip' => 'ip', 'just now' => 'just now', 'labels' => 'labels', 'last signin between %s and %s' => 'last signin between %s and %s', 'limit amount of subscription for this product per user, keep empty if you do not want to limit amount of subscriptions' => 'limit amount of subscription for this product per user, keep empty if you do not want to limit amount of subscriptions', 'limit amount of subscription for this product, keep empty if you do not want to limit amount of subscriptions' => 'limit amount of subscription for this product, keep empty if you do not want to limit amount of subscriptions', 'lines skipped' => 'lines skipped', 'link' => 'link', 'login' => 'login', 'min' => 'min', 'month' => 'month', 'months' => 'months', 'more than' => 'more than', 'never signin' => 'never signin', 'next rebill' => 'next rebill', 'no records' => 'no records', 'not subscribed to newsletter lists #' => 'not subscribed to newsletter lists #', 'number of active users per product' => 'number of active users per product', 'number of affiliate program clicks' => 'number of affiliate program clicks', 'number of sales by affiliate' => 'number of sales by affiliate', 'number of users per region' => 'number of users per region', 'of products' => 'of products', 'on %d-th day' => 'on %d-th day', 'only First Name' => 'only First Name', 'only Last Name' => 'only Last Name', 'only files downloaded by registered users is taken to account' => 'only files downloaded by registered users is taken to account', 'or' => 'or', 'pay using credit card or PayPal' => 'pay using credit card or PayPal', 'pay using wire transfer or by sending offline check' => 'pay using wire transfer or by sending offline check', 'please select billing plan to add manual access to users added by demand' => 'please select billing plan to add manual access to users added by demand', 'preview' => 'preview', 'protected area' => 'protected area', 'reCAPTCHA Size' => 'reCAPTCHA Size', 'reCAPTCHA Theme' => 'reCAPTCHA Theme', 'records processed.' => 'records processed.', 'remaining' => 'remaining', 'report includes only user who did at least one payment' => 'report includes only user who did at least one payment', 'reset' => 'reset', 'return' => 'return', 'schedule change' => 'schedule change', 'seconds' => 'seconds', 'separated by commas for several address, eg: 12.12.12.12,23.23.23.23,34.34.34.34 separated by hyphen for rage address, eg: 123.123.123.1-123.123.123.100 IMPORTANT: Do not use leading zero in IP address segments. For example this IP is incorrect: 127.000.000.001' => 'separated by commas for several address, eg: 12.12.12.12,23.23.23.23,34.34.34.34 separated by hyphen for rage address, eg: 123.123.123.1-123.123.123.100 IMPORTANT: Do not use leading zero in IP address segments. For example this IP is incorrect: 127.000.000.001', 'signature required' => 'signature required', 'spent %s %s' => 'spent %s %s', 'start' => 'start', 'subscribed to newsletter lists #' => 'subscribed to newsletter lists #', 'super' => 'super', 'this field is required' => 'this field is required', 'to %s on %s' => 'to %s on %s', 'trackable' => 'trackable', 'type part of brick name to filter…' => 'type part of brick name to filter…', 'unsubscribe' => 'unsubscribe', 'upgrade' => 'upgrade', 'use 4111-1111-1111-1111 for successful transaction' => 'use 4111-1111-1111-1111 for successful transaction', 'use this coupon' => 'use this coupon', 'used coupon %s' => 'used coupon %s', 'username, e-mail or name contains string [%s]' => 'username, e-mail or name contains string [%s]', 'valid until %s' => 'valid until %s', 'what you entered when creating your account' => 'what you entered when creating your account', 'year' => 'year', 'years' => 'years', 'you can upload your filese here' => 'you can upload your filese here', 'you have %d reward points collected' => 'you have %d reward points collected', 'you were referred by %s' => 'you were referred by %s', ); PK\4HZdefault/language/user/pl.phpnu[ 'na zawsze', ' from ' => 'od', ' to ' => 'do', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" może być zamówione tylko z tymi produktami/subskrypcja(ami): %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" może być kupione tylko jak masz wygaśnietą subskrypcję dla tych produktów: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" nie możesz tego kupić bo masz aktywną subskrypcję do: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" nie może być kupione bo masz aktywną subskrypcję do: %s', '%d-Tier Affiliates Commission ' => '%d-powiązana Prowizja Partnerska ', '%d-th day' => '%d-ty dzień', '%s MySQL Hostname' => '%s nazwa hostingowa MySQL', '%s MySQL Password' => '%s Hasło MySQL', '%s MySQL Username' => '%s Nazwa Użytkownika MySQL', '%s database and tables prefix' => '%s prefiks bazy danych i tablic', 'API Authentication Information' => 'Informacja Autoryzacji API', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Przyjmij Bezpośrednią Płatność płanosc może by dokonana na stronie systemu płaniczego ( bez konieczności rejestracji jako użytkownik)', 'Access' => 'Dostęp', 'Access Denied' => 'Zablokowany Dostep', 'Access Log' => 'Raport dostępu', 'Access Permissions' => 'Zezwolenia dostępu', 'Actions' => 'Akcje', 'Active' => 'Aktywny', 'Active Resources' => 'Aktywne Zasoby', 'Active Subscriptions' => 'Aktywne Subskrypcje', 'Active Users' => 'Aktywny Użytkownik', 'Active subusers' => 'Aktywni podużytkownicy', 'Add "Like" button' => 'Dodaj "Lubie" przycisk', 'Add New Notification Rule' => 'Dodaj nową regułę powiadomień', 'Add User' => 'Dodaj Użytkownika', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Dodaj punkty lojalnościowe do poleconego partnera po zakupie tego produktu (dodatkowo do skonfigurowanych w aMember CP -> Ustawienia -> Punkty Lojalnościowe)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Dodaj punkty lojalnościowe do użytkownika po zakupie tego produktu (dodatkowo do skonfigurowanych w aMember CP -> Ustawienia -> Punkty Lojalnościowe)', 'Add to Basket' => 'Dodaj do koszyka', 'Add/Renew Subscription' => 'Dodaj/Usuń Subskrypcje', 'Added' => 'Dodano', 'Additional Fields' => 'Pola dodatkowe', 'Address Info' => 'Informacje o adresie', 'Address Information' => 'Informacje o Adresie', 'Admin' => 'Administrator', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupy Administratorów aMember nigdy nie dotyka %s kont przypisanych do danych grup. To zabezpiecza %s konta przed zmianami uzytkownikow aMember', 'Admin Username' => 'Nazwa Użytkownika Administratora', 'Administrator' => 'Administrator', 'Advanced' => 'Zaawansowane', 'Advanced Search' => 'Zaawansowane wyszukiwanie', 'Advertise our website to your friends and earn money' => 'Zareklamuj naszą strone i zarób dodatkowe pieniądze', 'Affiliate' => 'Partner', 'Affiliate Agreement' => 'Kontrakt Partnera', 'Affiliate Clicks' => 'Kliknnięcia na partnera', 'Affiliate Id#' => '#ID Partnera', 'Affiliate Info' => 'Informacje o partnerze', 'Affiliate Payout - Paypal E-Mail address' => 'Wypłata Partnera - adres E-Mail do Paypal', 'Affiliate Payout Type' => 'Rodzaj wyplaty partnera', 'Affiliate Program' => 'Program Partnerski', 'Affiliate Sales' => 'Sprzedaże Partnera', 'Affiliate Signup Form' => 'Formularz Rejestracji Partnera', 'Affiliate info' => 'Informacja partnera', 'Affiliate stats' => 'Statystyki partnera', 'Affiliates' => 'Partnerzy', 'All' => 'Wszystko', 'All %s records on this page are selected' => 'Wszyskie %s archiwa na danej stronie są wybrane', 'All Affiliates' => 'Wszyscy partnerzy', 'All Time' => 'Za każdym razem', 'All Users' => 'Wszyscy Użytkownicy', 'All records' => 'Wszystkie dane ', 'Amazon S3 storage is not configured' => 'Magazyn Amazon S3 jest nie ustawiony', 'Amount' => 'Kwota', 'An Error has occurred' => 'Wystapil blad', 'An account with the same email [%s] is already exists.' => 'Konto z tym samym email [%s] już istnieje', 'An account with the same email already exists.' => 'Konto z tym samym e-mailem już istnieje.', 'An error occurred while handling your payment.' => 'Wystapil blad tranzakcji twojej platnosci.', 'An internal error happened in the script, please contact webmaster for details' => 'Wystąpił bład ze skryptem, przosze sie skontaktować z adminem strony', 'Any Product' => 'Jakikolwiek Produkt', 'Any product' => 'jakikolwiek produkt', 'Api Key' => 'Klucz API', 'Apply' => 'Zastosuj', 'Apply Filter' => 'Użyj Filter ', 'Assigned to usergroup' => 'Przypisany do grupy użytkowników', 'Attachments' => 'Zalącznik', 'Authentication' => 'Autoryzacja', 'Authentication problem, please contact website administrator' => 'Problem z autoryzacja, prosze skontaktować się z adminem strony', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Automatycznie zapisz użytkownikow do listy jak już bedzie dostepna dla nich', 'Available Bricks (drag to left to add)' => 'Dostepne Cegiełki ( przesuń na prawo aby dodać )', 'Available Credits' => 'Dostępne Kredyty', 'Awaiting Admin Response' => 'Czekające na odpowiedź administratora', 'Awaiting User Response' => 'Czekające na odpowiedź użytkownika', 'Aweber Application' => 'Aplikacja Aweber', 'Back' => 'Wróć', 'Bank Code' => 'Kod Bankowy', 'Bank Identification' => 'Identyfikacja Banku', 'Bank Name' => 'Nazwa Banku', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Zakazane Grupy aMember nie dotyka %s kont przypisanych do następujacych grup. To zabezpiecza %s konta przed zmianami użytkowników aMember', 'Banners and Links' => 'Banery i linki', 'Banners and Text Links' => 'Organizuj Banery i Tekstowe Linki', 'Begin Date' => 'Data Rozpoczęcia', 'Both Affiliate and member' => 'Zarówno partner i członek', 'CC Demo' => 'Przyklad CC', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'błąd CSRF zabezpieczenia - forma musi być wysłana w ciągu %d minut od otwarcia, proszę spróbować ponownie', 'Can view/edit customer Credit Card information and rebills' => 'Zobacz/Zmień informacje o klienta Karcie Kredytowej i automatycznych płatnosci', 'Cancel' => 'Anuluj', 'Cancel Subscription' => 'Anuluj Subskrypcje', 'Cancelled' => 'Anulowano', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Nie można używać DARMOWEJ wtyczki płatności z produktem który kosztuje więcej niż 0.0', 'Cannot validate VAT Id, please try again' => 'Nie można rozpoznać numeru VAT, proszę spróbować ponownie', 'Category' => 'Kategoria', 'Change' => 'Zmień', 'Change Password' => 'Zmień Hasło', 'Change Password/Edit Profile' => 'Zmień Hasło/Profil', 'Change Subscription' => 'Zmień Subskrypcję', 'Change Username' => 'Zmień Użytkownika', 'Change payout info' => 'Zmień informacje o wypłacie', 'Checkout' => 'Przejdż do kasy', 'Checkout error: ' => 'Błąd przy zapłacie:', 'Choose a Password must be %d or more characters' => 'Wybierz Hasło musi zawierać %d lub więcej znaków', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Wybierz nazwę użytkownika musi mieć przynajmniej %d lub więcej znaków może zawierać tylko litery, cyfry i podkreślenia', 'City' => 'Miasto', 'Click "Continue" to pay this order using stored credit card %s' => 'Kliknij "Kontynuj" aby oplacić te zamowienie zachowaną kartą kredytową %s', 'Click button to continue' => 'Naciśnij na przycisk aby kontynuować', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Naciśnij tutaj jak nie chcesz dłużej czekać (lub twoja przeglądarka automatycznie Cię nie przekierowuje )', 'Click to Edit' => 'Naciśnij aby uaktualnić', 'Clicks' => 'Kliknięćia', 'Clicks/Sales Statistics' => 'Kliknięcia Partnerów/Statystyki Sprzedaży', 'Close' => 'Zamknij', 'Close Ticket' => 'Zamknij tą sprawę', 'Closed' => 'Zamknięte', 'Code' => 'Kod', 'Comment' => 'Komentarz', 'Comment for admin reference' => 'Komentarz do wiadomości admina', 'Commission' => 'Prowizja', 'Commissions' => 'Prowizje', 'Configuration' => 'Ustawienia', 'Configured Tax Values' => 'Oblicz Wartość Tax-u', 'Confirm New Password' => 'Potwierdź swoje Nowe Hasło', 'Confirm Password' => 'Potwierdż Hasło', 'Confirm Payment' => 'Potwierdż Płatność', 'Confirm Your E-Mail Address' => 'Potwierdź swój adres emailowy', 'Confirm Your Password' => 'Potwierdź swoje hasło', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Potwierdzająca wiadomość została wysłana na Twoje konto e-mailowe. Proszę sprawdzić swoja skrzynkę. Jesli nie otrzymasz wiadomości w przeciągu 5 minut, proszę sprawdzić folder \' Spam\'- nasza wiadomość może być tam umieszczona przez pomyłkę. ', 'Content' => 'Zawartość', 'Continue' => 'Kontynuj', 'Conversation' => 'Konwersacja', 'Copy of' => 'Kopia', 'Count of signups' => 'Ilość rejestracji', 'Count of user signups' => 'Ilość rejestracji użytkowników', 'Country' => 'Kraj', 'Coupon' => 'Zniżka', 'Coupon Code' => 'Kod Kuponu', 'Coupon Discount' => 'Kod Zniżkowy', 'Coupon code disabled' => 'Kod kuponu jest nieważny', 'Coupon code expired' => 'Kod kuponu juz wygasł', 'Coupon is not yet active' => 'Kupon jest jeszcze nie aktywny', 'Coupon usage limit exceeded' => 'Kupon zosytał juz wyczerpany', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Załóż koto aMember na rządanie automatycznie załóż konto w aMember jeżeli użytkownik próbuje zalogować sie do aMember używajac te same dane do konta ktore ma %s', 'Credit Card Code' => 'Kod z Karty Kredytowej', 'Credit Card Info' => 'Informacja Karty Kredytowej', 'Credit Card Number' => 'Numer Karty Kredytowej', 'Credit Card Rebills' => 'Automatyczne płatnosci Kartą Kredytową', 'Credit Cards' => 'Karta Kredytowa', 'Credits' => 'Kredyty', 'Currency' => 'Waluta', 'Currency Exchange Rates' => 'Kursy wymiany walut', 'Current password entered incorrectly, please try again' => 'Wprowadzone hasło jest niepoprawne , proszę spróbować jeszcze raz', 'Custom Commission' => 'Niestandardowa Prowizja', 'Customer account has been automatically locked.' => 'Konto klienta zostało automatycznie zablokowane.', 'Customize' => 'Dostosować', 'DONE' => 'Skończone', 'Dashboard' => 'Panel Administracyjny', 'Data Integrity Code' => 'Kod Integralność danych', 'Date' => 'Data', 'Date and time of payment: %s' => 'Dzień i czas płatnośći: %s', 'Date must be in format %s' => 'Data musi być w formacie %s', 'Date/Time' => 'Data/Czas', 'Date: ' => 'Data ', 'Day' => 'Dzień', 'Days' => 'Dni', 'Deactivate Student' => 'Dezaktywuj Studenta', 'Deactivate User' => 'Wyłącz Użytkownika', 'Debit Card Number' => 'Numer Karty Bankowej', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Podstawowy poziom podstawowy poziom - użytkownik jest przypisany do tego poziomu jezeli nie ma aktywnej subskrypcji (dla przykładu, wszyscy z wygaśniętymi subskrypcjami) ', 'Delete' => 'Usuń', 'Delete %s' => 'Usuń %s', 'Delivery Time' => 'Czas Dostawy', 'Description' => 'Opis', 'Digits only please' => 'Tylko cyfry proszę', 'Disable online VAT Id Validation' => 'Wyłącz intenetową ratyfikacę numeru VAT', 'Disabled' => 'Wyłączone', 'Discard' => 'Wyrzuć', 'Discount' => 'Zniżka', 'Display Type' => 'Typ Wyświetlacza', 'Display in 2 rows' => 'Wyświetl w dwóch rzędach', 'Do Import' => 'Wykonaj Import', 'Do not add to Login Form' => 'Nie dodawać do formy Logowania', 'Do not add to Signup Form' => 'Nie dodawać to formy Rejestracji', 'Do you really want to %s %s %s records' => 'Czy chcesz %s %s %s archiwa', 'Do you really want to %s?' => 'Czy chcesz żeby %s?', 'Do you really want to cancel subscription?' => 'Czy na pewno chcesz anulować subskrypcje?', 'Do you really want to delete record?' => 'Czy chcesz usunąć archiwa ?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Czy naprawde chcesz się wypisać z %s poradycznych wiadomości ?', 'Done' => 'Zakoncz', 'Donee name' => 'Nazwa odbiorcy', 'Download' => 'Pobierz', 'Download limit exceeded for this file' => 'Limit ściągania przekroczony dla tego pliku', 'Downloaded on your own server' => 'Sciągnięty na twój serwer', 'E-Mail' => 'E-Mail', 'E-Mail Address' => 'Adres E-Mail', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'Podany email rożni sie od emaila weryfikującego, Prosze wpisac je ponownie ', 'E-Mail Format' => 'Format E-maila', 'E-Mail Messages' => 'Wiadomości e-mail', 'E-Mail Verification' => 'Weryfikacja Emailem', 'EU VAT' => 'VAT EU', 'EU VAT ID: ' => 'EU VAT ID:', 'EU VAT Id (optional)' => 'EU VAT Id (opcjonalnie)', 'Edit' => 'Edytuj', 'Edit %s' => 'Edytuj %s', 'Edit Brick Labels' => 'Zmień nazwy cegiełek', 'Edit Categories' => 'Edytuj Kategorie', 'Edit E-Mail Template' => 'Zmień wyglad e-maila', 'Email' => 'E-mail', 'Email Subject' => 'Tytuł Emaila', 'Email [%s] is not valid' => 'Email [%s] jest nieprawidłowy', 'Email admin regarding account sharing' => 'Wyślij e-mail do administratora dotyczący współdzielenia konta', 'Email user regarding account sharing' => 'Wyślij e-mail do użytkownika dotyczący współdzielenia konta', 'Empty response from Sagepay server' => 'Brak odpowiedzi z serwera Sagepay', 'Enabled Modules' => 'Wlączone Moduły', 'End' => 'Koniec', 'End Date' => 'Data Końcowa', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => 'Witaj w członkostwie. Kliknij %stutaj%s aby uzyskać dostęp do twojej strefy użytkownika', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Witaj w nowy czlonkostwie, Aby się zalogować kliknij tutaj %sZaloguj się%s', 'Enter coupon code' => 'Wpisz kod zniżki', 'Enter gift voucher code' => 'Wprowadź kod kuponu podarunkowego', 'Error 404 - Not Found' => 'Błąd 404 - Nie Znaleziono', 'Error : upload folder [%s] does not exists' => 'Błąd : Wgrany folder [%s] nie istnieje', 'Error from Storage Engine' => 'Błąd Silnika Magazynu', 'Error happened during payment process. ' => 'Wystąpił błąd podczas przetwarzania płatności', 'Error happened during transaction handling. Please contact website administrator' => 'Wystąpił błąd podczas tranzakcji, Proszę skontaktować sie z Administratorem Strony', 'European (A4)' => 'Europejski (A4)', 'Exact' => 'Dokładnie', 'Expire Date' => 'Data Wygaśnięcia', 'Expired' => 'Przedawniony', 'Expired Users' => 'Nieaktywny Uzytkownik', 'Expires' => 'Wygasa', 'Export' => 'Wysyłanie', 'Export Format' => 'Format do Wysyłania', 'FaceBook App ID' => 'FaceBook App ID', 'FaceBook Application' => 'Aplikacja FaceBook', 'Facebook App Secret' => 'Facebook App Sekret', 'Features' => 'Opcje', 'Field' => 'Pole', 'Field Type' => 'Rodzaj Pola', 'Field Updated' => 'Pole Uaktualnione', 'Fields To Display' => 'Pola ktore będą wyświetlane', 'Fields To Export' => 'Pola do eksportowania', 'Fieldset' => 'Pola', 'Fieldset title' => 'Nazwa pola', 'File' => 'Plik', 'File Downloads' => 'Załadowany Plik', 'File Storage' => 'Magazyn Plików', 'File should contain CSV list of user records for import in the following format:
      %s' => 'Plik powinien zawierać listę rekordów użytkowników CSV do importu w następującym formacie:<br /> <strong>%s</strong>', 'Filename' => 'Nazwa pliku', 'Files' => 'Pliki', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'Pliki umieszczone w magazynie Amazon S3. (Ostrzeżenie: Twoje komory nie powinny zawierać dużych liter w nazwie)', 'Files uploaded via aMember web interface' => 'Pliki wgrane uzywając aMember www interfejs', 'Filter' => 'Filtruj', 'First & Last Name' => 'Imie i Nazwisko', 'First Name' => 'Imię', 'Folder %s (%s)' => 'Folder %s (%s)', 'Folders' => 'Foldery', 'Form Page Break' => 'z przerwy na stronie', 'Free' => 'Darmowy', 'Free Access' => 'Darmowy Dostęp', 'Free Access without log-in' => 'Darmowy dostęp bez logowania', 'From' => 'Z', 'GST (Inclusive Tax)' => 'GST (włączny podatek)', 'Get Password' => 'Pobierz Hasło', 'Gift Voucher' => 'Kupon Podarunkowy', 'Gift Vouchers' => 'Kupony Podarunkowe', 'Global Commission' => 'Główna prowizja', 'Global Tax' => 'Podatek Globalny', 'Groups' => 'Grupy', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'Priorytet Grup możesz przeciągnąć i upuścić grupy aby je posortować. jeśli jest kilka grup dostępnych dla użytkownika aMember wybierze grupy, które są wyżej na tej liście jako "Główne"', 'HTML Code that will be displayed' => 'kod HTML który bedzie wyświetlany', 'HTML Message' => 'Wiadomość HTML', 'HTML text' => 'tekst HTML', 'Having Active Subscription To:' => 'Mających aktywną subskrypcję do:', 'Having Expired Subscription To:' => 'Mających wygaśnietą subskrypcję do:', 'Helpdesk' => 'Dział Pomocy', 'Hide do not display this item link in members area' => 'Ukryj nie wyświetlaj linka do tej pozycji w strefie członkowskej', 'Hosted at Activecampaing\'s server' => 'Umieszczone na serwerze Aktywnej Kampani', 'Housenumber' => 'Numer Domu', 'IP Address' => 'Adres IP', 'If you already have an account on our website, please %slog in%s to continue' => 'jeżeli już posiadasz konto na naszej stronie, prosze sie %szalogować%s aby kontynuować', 'If you are a registered member, please %slogin%s' => 'Jeżeli jesteś zarejestrowanym użytkownikiem, prosze %szaloguj się%s', 'If you are not registered yet, please %ssignup%s' => 'Jeżeli nie jesteś jeszcze zarejestrowanym użytkownikiem, prosze %szarejestruj się%s', 'Income Report - payments minus refunds' => 'Raport dochodów - płatności minus zwroty', 'Incorrect Parent Affiliate ID' => 'Niepoprawny ID Partnera Głównego', 'Insert comment into email' => 'Wstaw komentarz do emaila', 'Integer Value' => 'Wartość całkowita', 'Integer value required' => 'Wymagana wartość liczby całkowitej', 'Integration' => 'Integracja', 'Integrations' => 'Integracje', 'Internal Error' => 'Błąd wewnętrzny', 'Invalid Account Number' => 'Numer konta jest niepoprawny', 'Invalid Credit Card Number' => 'Niepoprawny Numer Karty Kredytowej', 'Invalid Debit Card Number' => 'Niepoprawny Numer Karty Bankowej', 'Invalid Expiration Date - Month' => 'Nie Poprawna Data Ważności - Miesiąc', 'Invalid Expiration Date - Year' => 'Nie Poprawna Data Ważności - Rok', 'Invalid Issue Number' => 'Niepoprawny Numer Wydania', 'Invalid Routing Number' => 'Niepoprawny Numer Kierunkowy', 'Invalid VAT Id, please try again' => 'Niepoprawny numer VAT, spróbuj ponownie', 'Invoice' => 'Faktura', 'Invoice Number: ' => 'Numer Rachunku', 'Invoice not found' => 'Faktura nie znależona', 'Is Gift Voucher?' => 'Jest Kuponem Podarunkowym', 'Is Locked' => 'Jest zablokowane', 'Is Paid?' => 'czy zapłacono?', 'Is Send At Later Date?' => 'jest Wyślij W Późniejszym Terminie', 'Is Disabled?' => 'Czy&nbsp;Wylłączony?', 'Item' => 'Produkt', 'Label' => 'Etykieta', 'Language' => 'Język', 'Last 14 Days' => 'Ostatnie 14 Dni', 'Last 30 Days' => 'Ostatnie 30 Dni', 'Last 7 Days' => 'Ostanie 7 dni', 'Last Business Week (Mon-Fri)' => 'W ostatnim Pracowniczym Tygodniu ( Pon- Pi)', 'Last Messages in Helpdesk' => 'Ostatnie Wiadomości z Działu Pomocy', 'Last Month' => 'W Zeszłym Miesiącu', 'Last Name' => 'Nazwisko', 'Last Week (Mon-Sun)' => 'W ostatnim Tygodniu ( Pon- Nie)', 'Last Week (Sun-Sat)' => 'W ostatnim Tygodniu (Nie- So)', 'Leads' => 'Wskazówki', 'License Key' => 'Klucz Licencyjny', 'Lifetime' => 'Na Całe Życie', 'Like Url' => 'Lubie Url', 'Link' => 'Link', 'Links' => 'Linki', 'Live Edit %s' => 'Edycja na żywo %s', 'Loading' => 'Ładowanie', 'Log In' => 'Zaloguj Się', 'Log all API Requests' => 'Rejestruj wszystkie prośby API', 'Login' => 'Zaloguj Się', 'Login as User' => 'Zaloguj się jako użytkownik', 'Logout' => 'Wyloguj się', 'Lost Password Sending Error' => 'Bład w wysyłce zapomnianego hasła', 'Lost Password Sent' => 'Zapomniane hasło zostało wysłane', 'Lost password?' => 'Zapomnialem hasło', 'Mail Queue' => 'Kolejka Poczty', 'Make Payment' => 'Wykonaj Płatność', 'Make a Donation' => 'Donacja', 'Make donation recurring' => 'Ustaw darowiznę jako powtarzaną', 'Manage Newsletters' => 'Zarządzaj Biuletynami', 'Marketing Materials' => 'Materiał Marketingowy', 'Members Directory' => 'Katalog Członków', 'Members Directory [%s] does not exists' => 'Katalog Członków [%s] nie istnieje', 'Membership Type' => 'Rodzaj Członkostwa ', 'Merchant Key' => 'Klucz Sklepu', 'Merchant Secret' => 'Sekret Sklepu', 'Message' => 'Wiadomość', 'Message can not be empty' => 'Wiadomość nie może być pusta', 'Moip Payment' => 'Płatność Moip', 'Month' => 'Miesiac', 'Months' => 'Mieśiące', 'Multiplier' => 'Mnożnik', 'My Country' => 'Mój Kraj', 'NEVER' => 'NIGDY', 'Name' => 'Nazwa', 'Never' => 'Nigdy', 'New' => 'Nowy', 'New %s' => 'Nowy %s', 'New Password' => 'Nowe Hasło', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Nowe Hasło Możesz wybrać tutaj nowe hasło albo zatrzymać swoje dotychczasowe hasło musi mieć %d albo więcej znaków', 'Newsletter' => 'Biuletyn', 'Newsletter Subscriptions' => 'Biuletyny', 'Next' => 'Dalej', 'No' => 'Nie', 'No commissions on this date' => 'Brak prowizji od tej daty', 'No coupons found with such coupon code' => 'Nie znależono takiego kodu promocyjnego', 'No gift vouchers found with such code' => 'Nie odnaleziono kuponów podarunkowych z takim kodem', 'No items in this section' => 'Brak produktów w tej sekcji', 'No items selected for purchase' => 'Nie wybrano żadnych produktów', 'No records found' => 'Brak wpisów', 'No, cancel' => 'Nie, unieważnij', 'No, keep me subscribed' => 'Nie, zostaw mnie zaprenumerowanego', 'No, please keep me subscribed' => 'Nie, proszę zostawić mnie zarejestrowanego', 'Not Approved Affiliates' => 'Nie Zatwierdzeni Partnerzy', 'Not Selected' => 'Nie Wybrany', 'Not assigned to usergroup' => 'Nie przypisany do grupy użythkowników', 'Not registered yet?' => 'Jestes jeszcze nie zerejestrowany?', 'Number of Messages to display' => 'Ilość wyświetlanych wiadomości', 'Numeric Value' => 'Wartość numeryczna', 'Numeric value required' => 'Wymagana Wartość Numeryczna ', 'Offline Payment' => 'Płatność Niepodłączona', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'W momencie skonfigurowania wtyczki na tej stronie, nie zapomnij to dodać do ustawienia w %saMember CP -> Protect Content -> Integrations%s stronie', 'Only Affiliate %s(rarely used)%s' => 'Partner %s(żadko używany)%s ', 'Order reference: %s' => 'Referencje zamówienia: %s', 'Other' => 'Inne', 'Our system will try to charge your card again on %s' => 'System spróbuje ponownie pobrac opłatę z karty kredytowej dnia %s', 'Pages' => 'Strony', 'Password' => 'Hasło', 'Password and Password Confirmation are different. Please reenter both' => 'Twoje hasło i hasło weryfikujace róznią sie, Prosze wpisać je ponownie', 'Password must contain at least %d letters or digits' => 'Hasło musi miec przynajmniej %d liter lub cyfr', 'Passwords do not match' => 'Hasła nie są identyczne', 'Path to %s' => 'Ścieżka do %s', 'Path to %s Folder' => 'Ścieżka do %s Foldera', 'Payanyway plugin does not support recurring billing!' => 'Payanyway wtyczka nie obsługuje automatycznych płatności !', 'Payment' => 'Płatność', 'Payment Error' => 'Błąd Płatnosci', 'Payment Failed' => 'Płatność nie przeszła', 'Payment Info' => 'Informacja o płatności', 'Payment System' => 'System Płatniczy', 'Payment System Description' => 'Opis Systemu Płatności', 'Payment System Title' => 'Tytuł Systemu Płatności ', 'Payment error: ' => 'Bład przy dokonywaniu płatnosci', 'Payment failed' => 'Płatność nie przeszła', 'Payment info' => 'Informacja Płatności', 'Payment is already processed, please go to %sMembership page%s' => 'Płatność jest juz zapłacona, prosze przejść do %sMembership page%s', 'Payments' => 'Płatności', 'Payments History' => 'Historia Płatności', 'Payments by New vs Existing members' => 'Płatności nowych użytkowników w porównaniu z obecnymi', 'Payments by payment system breakdown' => 'Płatności pokategorowane systemami płatniczymi', 'Payments by products breakdown' => 'Płatność z wyszczególnioną lista produktów', 'Payments from existing customers' => 'Płatności od dotychczasowych klientów', 'Payments from new customers' => 'Płatności od nowych klientów', 'Payments total' => 'Podsumowanie płatności', 'Payout Method' => 'Metoda Wypłaty', 'Payouts' => 'Wypłaty', 'Pending' => 'w oczekiwaniu', 'Pending Invoices' => 'Faktury Oczekujące', 'Pending subusers' => 'Rozważani podużytkownicy', 'Period' => 'Okres', 'Period must be in interval 1-24 months' => 'Okres musi być w odstępach 1-24 miesięcznych', 'Period must be in interval 1-5 years' => 'Okres musi być w odstępach 1-5 letnich', 'Period must be in interval 1-90 days' => 'Okres musi być w odstepach 1-90 dni', 'Personal Content' => 'Prywatna Zawartość', 'Phone' => 'Telefon', 'Phone Number' => 'Numer Telefonu', 'Plain-Text Message' => 'Zwykła wiadomość tekstowa', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Prosze sie %slogin%s do twojego konta.%sjezeli nie oplaciles platnosci, bedziesz mogl dokonac platnosci po zalogowaniu', 'Please Select' => 'Proszę wybrać', 'Please agree to Affiliate Agreement' => 'Prosze zatwierdzić Kontrakt Partnera', 'Please agree to User Agreement' => 'Proszę wyrazić zgodę w miejscu dla Zgody Użytkownika', 'Please choose' => 'Proszę wybrać', 'Please choose a Credit Card Type' => 'Proszę wybrać Rodzaj Karty Kredytowej', 'Please choose a membership type' => 'Proszę wybrać rodzaj członkostwa', 'Please choose a payment system' => 'Proszę wybrać rodzaj płatności', 'Please choose state' => 'Prosze wybrać województwo', 'Please enter %s' => 'Proszę wprowadzić %s', 'Please enter Account Number' => 'Proszę wpisać numer konta', 'Please enter City' => 'Prosze wpisać nazwę Miasta', 'Please enter Country' => 'Prosze wpisać Kraj', 'Please enter Credit Card Code' => 'Proszę wprowadzić Kod z Karty Kredytowej', 'Please enter Credit Card Number' => 'Prosze wpisac Numer Karty Kredytowej', 'Please enter Debit Card Number' => 'Prosze wpisać Numer Karty Bankowej', 'Please enter Password' => 'Proszę wpisać Hasło', 'Please enter Routing Number' => 'Proszę wprowadzić Numer Kierunkowy', 'Please enter State' => 'Wpisz Stan', 'Please enter Street Address' => 'Proszę wprowadzic Nazwę Ulicy', 'Please enter ZIP code' => 'Prosze wpisać Kod Pocztowy', 'Please enter a valid e-mail address' => 'Proszę wprowadzić dokładny adres e-mailowy ', 'Please enter correct amount' => 'Proszę wprowadzić poprawną wartość', 'Please enter coupon code' => 'Proszę wpisać kod zniżkowy', 'Please enter credit card holder first name' => 'Prosze wprowadzić pierwszę imię właściciela karty kredytowej', 'Please enter credit card holder last name' => 'Prosze wprowadzić nazwisko właściciela karty kredytowej', 'Please enter credit card holder name' => 'Prosze wprowadzić nazwe właściciela karty kredytowej', 'Please enter debit card holder first name' => 'Wpisz Imię właściciela karty bankowej', 'Please enter debit card holder last name' => 'Wpisz Nazwisko wlaściciela karty bankowej', 'Please enter debit card holder name' => 'Wpisz Imię i Nazwisko właściciela karty bankowej', 'Please enter first name' => 'Proszę wpisać Imię', 'Please enter gift voucher code' => 'Proszę wprowadzić kod kuponu podarunkowego', 'Please enter housenumber' => 'Proszę wpisać Numer Domu', 'Please enter phone number' => 'Prosze wpisac Numer Telefonu', 'Please enter valid Email' => 'Proszę wpisać poprawny Email', 'Please enter valid Username. It must contain at least %d characters' => 'Prosze wpisać poprawnie Użytkownika. Musi mieć przynajmniej %d znaków', 'Please enter your First Name' => 'Prosze wpisac swoje Imię', 'Please enter your Last Name' => 'Prosze wpisać swoje Nazwisko', 'Please enter your current password for validation' => 'Proszę wprowadzić swoje obecne hasło dla weryfikacji', 'Please enter your last name' => 'Prosze wpisać Nazwisko', 'Please enter your name' => 'Prosze wpisac twoje imię', 'Please login' => 'Prosze sie zalogować', 'Please select' => 'Proszę wybrać', 'Please select an item...' => 'Proszę wybrać pozycję...', 'Please select payment system for payment' => 'Przoszę wybrać rodzaj płatności', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Proszę użyć %sDodaj/Odnów Subskrypcje%s formy aby zamówic lub odnowić subskrypcje.', 'Please wait %d seconds before next login attempt' => 'Proszę poczekać %d sekund aby ponownie się zalogować', 'Plugin' => 'Wtyczka', 'Plugin List Id' => 'Numer Wtyczki', 'PostAffiliatePro Parent Affiliate ID' => 'Numer Skierowania od Partnera ', 'PostAffiliatePro Referral ID' => 'Po Partnerskie Numer Skierowania', 'Prev' => 'Poprzednie', 'Preview' => 'Podgląd', 'Price' => 'Cena', 'Processing your Transaction' => 'Przetwarzanie twojej transakcji', 'Processing your product upgrade' => 'Przetwarzanie ulepszenia twojego produktu', 'Product' => 'Produkt', 'Product %s is incompatible with product %s. Reason: %s' => 'Produkt %s jest niekompatybilny z produktem %s. Powód %s', 'Product Categories' => 'Kategorie Produktów', 'Product Title' => 'Nazwa Produktu', 'Product upgrade finished successfully' => 'Ulepszenie produktu zakończone sukcesem', 'Product(s) to display' => 'Produkt(y) które będą wyświetlane', 'Products' => 'Produkty', 'Products keep empty to report all products' => 'Produkty zostaw puste aby wyświetlić wszytkie produkty', 'Profile' => 'Edytuj profil', 'Profile update transaction failed' => 'Uaktualnienie Profila nie powiodła się', 'Protected Content [%s-%d]' => 'Zabezpieczona Zawartość [%s-%d]', 'Purchased Credits' => 'Kupione Kredyty', 'Qty' => 'Ilość', 'Quantity' => 'Ilość', 'Quick Order' => 'Szybkie Zamówienie', 'Quickpay parameters' => 'Parametry Quickpay', 'Re-Open Ticket' => 'Otwórz ponownie wiadomość', 'Read-only' => 'Przeczytaj - tylko', 'Real Path' => 'Prawdziwa Scieżka', 'Record' => 'Archiwa', 'Record Type' => 'Rodzaj rekordu', 'Record [%s] not found' => 'Rekordu [%s] nie znaleziono', 'Records that match all these conditions' => 'Dane ktore odpowiadaja tym regułom', 'Recurring' => 'Powtarzające się', 'Redirect to NetDebit booking form.' => 'Przekieruj do formularza rezerwacyjnego NetDebit', 'Reference number is:' => 'Numer Referencji:', 'Referer' => 'Polecający', 'Referred Affiliate' => 'Polecony Partner', 'Refresh' => 'Odśwież', 'Refresh 3-rd party lists' => 'Odśwież listę osób trzecich', 'Refund' => 'Zwrot', 'Refund Amount' => 'Kwota zwrotu', 'Refunded' => 'Zrefundowany', 'Regional Tax' => 'Podatek Regionalny', 'Register' => 'Zarejestruj się', 'Remote API Permissions' => 'Zdalne zezwalanie API', 'Remove' => 'Usuń', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Usuń Użytkowników kiedy użytkownik zostanie usunięty z aMember przypisane do tego użytkownika wpisy zostana usunięte z %s', 'Remove user' => 'Usuń Użytkownika', 'Reply' => 'Odpisz', 'Required' => 'Wymagane', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Ponów w przypadku problemu jeżeli automatyczna opłata nie działa, aMember moze próbowac ponownie po kilku dniach. i przedłuzyc subskrypcje o ten czas wpisz przez ilę dni ma próbowac pobrać opłatę', 'Return' => 'Wróc', 'Return and try again' => 'Wróć i spróbuj ponownie', 'Review/Pay Commissions' => 'Przeglądaj/Płać partnera prowizję', 'Reward Points' => 'Punkty Lojalnościowe', 'Reward Points Configuration' => 'Konfiguracja Punktów Lojalnościowych', 'Run Report' => 'Przeprowadź Raport', 'Running %s' => 'Procesuje %s', 'Save' => 'Zapisz', 'Save Profile' => 'Zapisz Profil', 'Search' => 'Szukaj', 'Search Products' => 'Szukaj produktu', 'Security code is invalid' => 'Kod zabezpieczający jest nieprawidłowy', 'Select a condition to add into search' => 'Wybierz warunek jaki dodać do wyszukiwarki', 'Select all %s records matching your search' => 'Zaznacz wszystie %s rezultaty rownajace sie twojej szukanej kwesti', 'Send' => 'Wyślij', 'Send Cancel Notifications to User' => 'Wyślij Powiadomienia o Anulowaniu do Użytkownika', 'Send Voucher To' => 'Wyślij Kupon Do', 'Session expired, please enter username and password again' => 'Sesja wygasła czasowo, prosze wpisac uzytkownika i hasło ponownie', 'Settings' => 'Ustawienia', 'Shipping' => 'Wysyłka', 'Shipping Options' => 'Opcje Przesyłki', 'Shopping Cart' => 'Koszyk z zakupami', 'Shopping Cart Module. No data input' => 'Moduł Koszyka, Brak danych', 'Shopping Cart Module. No product id input' => 'Moduł Koszyka, Brak identyfikatora produktu', 'Sign-up' => 'Zapisać się', 'Signature' => 'Podpis', 'Signup Form' => 'Forma Rejestracji', 'Signup here' => 'Zapisz się tutaj', 'Signup/payment functions are disabled for this user account' => 'Rejestracja/płatność jest wyłaczona dla tego użytkownika', 'Simple Search Users' => 'Podstawowa Wyszukiwarka Użytkownikow', 'Site Title' => 'Tytuł Strony', 'Skip First Line' => 'Pomiń Pierwszą Linię', 'Snippets' => 'Wstawki', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Przykro nam, ale nie można użyć tej platności dla tego zamowienia, Prosze wybrać inną płatność', 'Sorry, seems you have used wrong link' => 'Przepraszamy, ale wygląda ze użyleś zły link', 'Source Code — Copy/Paste Into Your Website' => 'Kod żródłowy &mdash; Kopiuj/Wklej na swoją stronę', 'Standard' => 'Standardowy', 'Start' => 'Początek', 'Start Date' => 'Data Początkowa', 'State' => 'Województwo', 'Status' => 'Status', 'Street' => 'Ulica', 'Street (Second Line)' => 'Adress ( Kontynuacja )', 'Street Address' => 'Nazwa Ulicy', 'Street Address (Second Line)' => 'Kontynuacja adresu', 'SubUsers Count (keep zero for non-reseller products)' => 'Ilość Współwłaścicieli (zostaw na 0 dla nie sprzedawanych produktów)', 'SubUsers Product (keep empty for non-reseller products)' => 'Produkty Współwłaścicieli (zostaw puste dla nie sprzedawanych produktów)', 'Subject' => 'Temat', 'Subject can not be empty' => 'Temat nie może być pusty', 'Submit' => 'Prześlij', 'Subscribe And Pay' => 'Zapisz się i zapłać', 'Subscribe all available users' => 'Zapisz wszystkich dostępnych użytkowników', 'Subscribe to Site Newsletters' => 'Zapisz sie do biuletynu strony internetowej', 'Subscribed To Newsletters' => 'Zarejestrowany żeby otrzymywać Newsletters', 'Subscribers' => 'Użytkownicy', 'Subscription Terms' => 'Warunki Subskrypcji', 'Subscription/Product Title' => 'Subskrypcja/Nazwa produktu', 'Subtotal' => 'Suma', 'Subusers' => 'Współwłaściciele', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => 'Sukces: %d (%0.2f %s) Odrzucone %d (%0.2f %s)', 'Such affiliate ID exist' => 'Taki ID partnera istnieje', 'Support Us!' => 'Wesprzyj nas !', 'Target URL' => 'Docelowy URL', 'Tax' => 'Podatek', 'Tax Amount' => 'Kwota Podatku', 'Tax Id' => 'Numer podatkowy', 'Tax Rate for example 18.5 (no percent sign)' => 'Stopa Podatkowa n.p. 18.5 ( bez znaczka - procenty )', 'Tax Title' => 'Nazwa Podatku', 'Tax Value' => 'Wartość Podatku', 'Terms' => 'Warunki', 'Test Mode' => 'Ustawienie Testowe', 'Test Settings' => 'Ustawienia Testowe', 'Thank you for Signing up' => 'Dziękujemy za Rejestrację', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Dziękujemy ! Twoja Płatność jest w toku & przetwarzana. Uaktualnimy twoją subskrypcje jak płatnośc zostanie ukończona. Proszę czekać cierpliwie. Moze to pottrwać od 12-24 godzin. Otrzymasz Email z potwierdzeniem zakupu.', 'The database has encountered a problem, please try again later.' => 'Wystąpił bład w bazie danych, przoszę spróbować później.', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'Plik został usunięty z dysku lub jest uszkodzony. Proszę przesłać go ponownie.', 'The following words are reserved : %s' => 'Następujące słowa są zarezerwowane: <code>%s</code>', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'Wiadomość z twoim hasłem została już wysłana na twoją skrzynkę. Poczekaj 180 minut przed ponowną próbą', 'The password should be at least %d characters long' => 'Hasło powinno być przynajmniej %d ilości liter', 'The user name or password is incorrect' => 'Wpisany użytkownik lub hasło jest nie poprawne', 'There are no confirmed payments for your account' => 'Brak potwierdzonych platności na twoim koncie', 'There are no form available for affiliate signup.' => 'Nie ma dostępnej formy dla rejestrujących sią partnerów.', 'There are no products available for purchase. Please come back later.' => 'Obecnie nie ma dostępnych produktów. Proszę wrócić pózniej', 'This %s is blocked. Please contact site support to find out why' => 'Ten %s jest zablokowany. Proszę skontaktować się z administratorem strony aby dowiedzieć się dlaczego', 'This Month' => 'W Tym Miesiącu', 'This Week (Mon-Sun)' => 'W tym Tygodniu ( Pon- Nie)', 'This Week (Sun-Sat)' => 'W tym Tygodniu ( Nie- So)', 'This coupon belongs to another customer' => 'Tenk kupon należy do innego klienta', 'This field is required' => 'To pole jest wymagane', 'This is a required field' => 'To pole jest wymagane', 'This page will be automatically refreshed within %s' => 'Ta strona zostanie automatycznie odświeżona w ciągu %s', 'This payment system could not handle payments in [%s] currency' => 'Ten system płatności nie jest w stanie przyjąć płatności [%s] w danej walucie', 'This payment system could not handle zero-total invoices' => 'Ten system płatności nie jest w stanie przyjąć faktury o wartości zero', 'Thresehold Date' => 'Zakres Terminu', 'Ticket' => 'Wiadomość', 'Ticket has been submited' => 'Wiadomość została wysłana', 'Tickets' => 'Bilety', 'Title' => 'Tytuł', 'To' => 'Do', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Aby dodać pola do formy, przesuń z \'Dostępne cegiełki\' do \'Formy cegiełek\'. aby usunąć pola, przesuń z powrotem do \'Dostepne cegiełki\'. aby założyć formę wielostronną, wstaw \'Seperator Strony\' w miejsce gdzie chcesz aby forma była podzielona.', 'Today' => 'Dzisiaj', 'Total' => 'Łączna Suma', 'Try again' => 'Spróbuj ponownie', 'Type' => 'Rodzaj', 'USA (Letter)' => 'USA (List)', 'Unable to cancel subscription: ' => 'rezygnacja z subskrypcji nie powiodła się', 'Unable to delete this file as it is used for:' => 'Niemożna skasować tego pliku ponieważ jest używany przez:', 'Unenroll Student' => 'Wyrejestruj Studenta', 'Unit Price' => 'Cena jednostki', 'Unknown period unit: %s' => 'Nieznana jednosta okresu: %s', 'Unsubscribe' => 'Wypisz', 'Unsubscribe from all e-mail messages' => 'Wypisać się z wiadomości emailowych', 'Unsubscribed' => 'Wypisany', 'Unsubscription Confirmation' => 'Potwierdzenie wypisania', 'Update' => 'Uaktualnij', 'Update Credit Card Info' => 'Uaktualnij informacje karty kredytowej', 'Update Debit Card Info' => 'Uaktualnij informacje karty bankowej', 'Updated' => 'Uaktualniony', 'Upgrade Subscription' => 'Zmień Subskrypcje', 'Upload files using FTP client to [%s]' => 'Wgraj pliki używając FTP prgram do [%s]', 'Use Database Connection other than configured for aMember' => 'Użyj innej nazwy bazy dannych niż skonfigurowana do aMember', 'Use Reward Points' => 'Użyj Punktów Lojalnościowych', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Użyj innej bazy danych MySQL wpisz nazwe hosta, użytkownika, hasło dla %s połączenia z bazą danychZ reguły możesz to zostawić odznaczone', 'Used' => 'Użyto', 'Useful Links' => 'Przydatne Linki', 'User' => 'Użytkownik', 'User Agreement' => 'Zgoda Użytkownika', 'User Groups' => 'Grupy użytkowników', 'User Info' => 'Informacje Uzytkownika', 'User Search' => 'Wyszukiwarka Użytkownikow', 'User is locked' => 'Użytkownik jest zablokowany', 'User is not approved' => 'Użytkownik nie jest zatwierdzony', 'User must provide' => 'Użytkownik musi podać', 'Username' => 'Użytkownik', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Użytkownik możesz zmienic nazwe użytkownika tutaj lub pozostawić bez zmian. Użytkownik musi zawierac %d lub więcej znaków i możne tylko zawierać małe litery, cyfry, i podkreślenia.', 'Username %s is already taken. Please choose another username' => 'Użytkownik %s zajety. Prosze wybrać inna nazwe', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'Nazwa użytkownika [%s] zawiera niedozwolone znaki - proszę użyć cyfr i liter', 'Username [%s] is already taken. Please choose another username' => 'Użytkownik [%s] już istnieje. Proszę wybrać inną nazwę użytkownika', 'Username contains invalid characters - please use digits, letters or spaces' => 'Nazwa użytkownika zawiera nieprawidłowe znaki - proszę wpisać cyfry i litery lub odstępy', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Nazwa użytkownika zawiera nieprawidłowe znaki - proszę wpisać cyfry i litery', 'Username/Email' => 'Adres Emailowy lub Nazwa Użytkownika', 'Users subscribed to Newsletter Threads #' => 'Użytkownicy zapisani do biuletynu #', 'VAT Id' => 'Numer Vat', 'Validate E-Mail Address by sending e-mail message with code' => 'Zweryfikuj twoj adres E-Mailowy przez wyslanie emaila z kodem', 'Validation' => 'Potwierdzenie prawidłowości', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'E-mail weryfikacyjny został wysłany na twój adres. E-mail na twoim koncie zostanie zmieniony po potwierdzeniu.', 'Version of script' => 'Wersja skryptu', 'Video' => 'Wideo', 'View Basket' => 'Zobacz Koszyk', 'Visit %sorder page%s to order additional subscriptions' => 'Odwiedż %sstrone zakupu%s aby wykupic dodatkowe subskrypcje', 'Voucher is not yet active' => 'Kupon nie jest jeszcze aktywny', 'Week' => 'Tydzien', 'Wrong code or code expired - please start signup process again' => 'Niepoprawny kod albo kod który wygasł - proszę zacząć proces rejestracji od początku', 'Wrong link - no id passed' => 'Zły link - id nie przeszlo', 'Wrong parameters, error #1253' => 'Nieprawidłowe parametry, bład #1253', 'Wrong password' => 'Złe hasło', 'Wrong verification code' => 'Niepoprawny kod weryfikujący', 'Wrongly signed URL, please contact site admin' => 'Żle pzrypisany URL, proszę się skontaktować z administratorem strony', 'Year' => 'Rok ', 'Years' => 'Lata', 'Yes' => 'Tak', 'Yes, I want to cancel subscription' => 'Tak, chce anulować subskrypcje', 'Yes, continue' => 'Tak, kontynuuj', 'Yes, unsubscribe' => 'Tak, wypisz mnie', 'Yesterday' => 'Wczoraj', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Jesteś zalogowany jako %s. %sWyloguj się%s aby zarejestrować się jako nowy użytkownik.', 'You have %s%d ticket(s)%s that require your attention' => 'Masz %s%d biletów%s, które wymagają twojej uwagi', 'You have no access to %s' => 'Nie masz dostepu do %s', 'You have no active subscriptions' => 'Nie posiadasz aktywnej subskrypcji', 'You have no enough permissions for this operation' => 'Nie masz wystarczających uprawnień do tego dzialania', 'You have no items in your basket - please add something to your basket before checkout' => 'Brak produktów w koszyku - proszę dodać produkt zanim przejdziesz do zapłaty', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'Masz za dużo podużytkownikow przypisanych do tego konta. Mozesz wybrac %d uzykowników aby ich usunąć', 'You must be authorized to access this area' => 'Musisz być autoryzowanym aby mieć dostęp tutaj', 'You must be logged-in to open this media' => 'Musisz być zalogowany aby to otworzyć', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Musisz Ustawić aMember CP -> Ustwaienia -> Zaawansowane -> Przechowywanie Sesji do \'Standardowe Sesje PHP\' To jest wymagane aby wlączyć Logowanie pomiędzy aMember a SilverStripe', 'Your 9 digit ABA Routing Number' => 'Twój 9-cyfrowy Numer Kierunkowy ABA Banku', 'Your Account Removal' => 'Usuwanie Twojego Konta', 'Your Bank Account Number' => 'Twoje Konto Bankowe', 'Your Basket' => 'Twoj Koszyk', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Twoje Obecne Hasło jeśli zamierzasz zmienić hasło, prosimy podać obecne hasło dla weryfikacji', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Twoj adres emailowy potwierdzenie zostanie wysłane na podany adres', 'Your General Affiliate Link' => 'Twój ogólny link partnera', 'Your Membership Information' => 'Informacje o twoim Członkowstwie', 'Your Payment is PENDING & Under Process' => 'Twoja Płatność jest w toku & przetwarzana', 'Your Personal Downloads' => 'Twoje pliki do ściągania', 'Your Reseller Packages' => 'Twoje Pakiety Sprzedawcy', 'Your account has been automatically locked.' => 'Twoje konto zostało automatycznie zablokowane', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Twoje konto nie zostalo jeszcze zatwierdzone, otrzymasz wiadomość emailem kiedy twoje konto z dostępem do serwisu zostanie zatwierdzone.', 'Your password is too long' => 'Twoje Hasło jest za długie', 'Your payment has been successfully processed.' => 'Twoja płatność powiodła się.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Twoja płatność nie została jeszcze zatwierdzona, może to potrwać pare minut aby dostać potwierdzenie o udanej płatnośći.', 'Your profile has been updated successfully' => 'Twój profil został uaktualniony', 'Your subject is too verbose' => 'Twój temat jest za długi', 'Your subscription does not allow access to this media' => 'Twoja subskrypcja nie zezwala na dostęp do tych mediów', 'Your subscription has been successfully processed.' => 'Twoja subskrypcja została zatwierdzona.', 'ZIP' => 'Kod Pocztowy', 'ZIP Code' => 'Kod Pocztowy', 'Zip' => 'Kod Pocztowy', '[Select country]' => '[Wybierz kraj]', '[Select state]' => '[Wybierz stan]', '_default_locale' => 'pl_PL', 'accepts all major credit cards' => 'przyjmuje wszystkie główne karty kredytowe', 'admin' => 'Administrator', 'affiliate program commissions' => 'prowizja programu partnera', 'after completing order, voucher will be sent to specified address' => 'po zakończeniu zamówienia, kupon będzie wysłany na określony adres email', 'ago' => 'temu', 'banned' => 'Zakazane', 'check box to use points and get discount' => 'Zaznacz pole wyboru aby użyć punktów i dostać zniżkę', 'check it if you want to gift subscription on this product' => 'zaznacz jeśli chcesz podarować abonament na ten produkt', 'commission found by next rules' => 'prowizja znaleziona przy nastepujących zasadach', 'day' => 'dzień', 'days' => 'dni', 'different currency products' => 'produkty z różnymi walutami', 'different rebill times subscriptions' => 'różne czasy refakturowania subskrypcji', 'different the first period subscriptions' => 'różne pierwsze okresy subskrypcji', 'different the second period subscriptions' => 'różne drugie okresy subskrypcji', 'email' => 'email', 'email will contain this sentence' => 'email będzie zawierał następujące zdanie', 'expiration' => 'wygaśnięcie', 'expires' => 'wygasa', 'filtered' => 'przefiltrowany', 'for affiliate commission payouts' => 'wyplata prowizji dla partnera', 'for example: 1111-2222-3333-4444' => 'dla przykladu: 1111-2222-3333-4444', 'generate' => 'generuj', 'hrs' => 'godz', 'iDEAL betaling' => 'iDEAL betaling', 'if not specified, voucher will be sent to your email' => 'Jeśli nieokreślone, kupon będzie wysłany na twój adres email', 'ip' => 'ip', 'just now' => 'w tej chwili', 'link' => 'link', 'login' => 'loguj', 'min' => 'min', 'month' => 'miesiąc', 'months' => 'miesiące', 'more than' => 'więcej niż', 'no records' => 'brak wpisów', 'number of affiliate program clicks' => 'liczba klikniec dla danego programu', 'of products' => 'produktów', 'on %d-th day' => 'tego %d dnia', 'only First Name' => 'tylko Imię', 'only Last Name' => 'tylko Nazwisko', 'or' => 'albo', 'pay using credit card or PayPal' => 'zapłać używajac Karty Kredytowej lub PayPal', 'pay using wire transfer or by sending offline check' => 'zapłać używając przekaz elektroniczny lub książeczką czekową', 'protected area' => 'strefa zabezpieczona', 'return' => 'wróć', 'seconds' => 'sekundy', 'start' => 'początek', 'upgrade' => 'ulepszenie', 'use 4111-1111-1111-1111 for successful transaction' => 'użyj 4111-1111-1111-1111 do poprawnej tranzakcji', 'year' => 'rok', 'years' => 'lata', 'you have %d reward points collected' => 'Uzbierałeś %d punktów lojalnościowych', ); PK\ lldefault/language/user/it.phpnu[Expired' => ' / Scaduto', ' Setup' => 'Impostazioni', ' forever ' => 'per sempre', ' from ' => 'da', ' to ' => 'a', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" può essere acquistato solo se hai anche: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" può essere acquistato solo quando scade la tua iscrizione a: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" non può essere acquistato se non hai anche: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" non può essere acquistato perché la tua iscrizione a: %s è scaduta ', '%d access records…' => '%d record di accesso…', '%d items processed, %d users is unsubscribed. %sBack%s' => '%d azioni eseguite, %d utenti disiscritti. %sIndietro%s', '%d-Tier Affiliates Commission ' => '%d-Tier Affiliates Commission ', '%d-th day' => '%d° giorno', '%s Additional Settings' => '%s Impostazioni Aggiuntive', '%s Database name and Tables Prefix' => '%s Nome Database e Prefisso Tabelle', '%s Integration Settings' => 'Impostazioni di Integrazione di %s', '%s MySQL Hostname' => '%s Hostname MySQL', '%s MySQL Password' => '%s Password MySQL', '%s MySQL Username' => '%s Nome Utente MySQL', '%s database and tables prefix' => 'Prefisso database e tabelle di %s', '%s records on this page are selected. You can choose group operation in the select box below or %scancel%s' => '%s righe selezionate. Puoi selezionare una operazione di gruppo dalla tendina qui sotto o %sannullare%s', '%sEnable%s and %sconfigure%s external cron if you are using credit card payment plugins' => '%sAbilita%s e %sconfigura%s il cron esterno se stai utilizzando i plugin Carte di Credito', ', for %d installments' => ', in %d pagamenti', ', then ' => ', poi ', '-- Please select --' => '-- Seleziona --', '2Factor Authentication' => 'Autenticazione 2Factor', '5-10 lowercase alphanumeriv characters' => '5-10 caratteri alfanumerici minuscoli', 'A duplicate transaction has been submitted. Please wait 2 minutes before next attempt' => 'Hai inviato una transazione due volte. Attendi due minuti prima del prossimo tentativo', 'A/B Signup' => 'A/B Signup', 'ABA Routing Number 9 digits' => 'ABA Routing Number 9 digits', 'API Authentication Information' => 'API Infomrazioni per Autenticazione', 'API Key' => 'API Chiave', 'API Keyyour private API key' => 'API Chiave Privata', 'API hostname' => 'API Hostname', 'Above Form' => 'Sopra il Form', 'Above Form (Header)' => 'Sopra il Form (Testata)', 'Accept' => 'Accetto', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Accetta pagamenti diretti gestisce pagamenti fatti con un metodo di pagamento autonomo (senza previa registrazione ad aMember)', 'Access' => 'Accesso', 'Access Code will be included into URL to make it unique' => 'Access Code will be included into URL to make it unique', 'Access Denied' => 'Accesso Negato', 'Access Log' => 'Log Accessi', 'Access Permissions' => 'Permessi di Accesso', 'Access mode' => 'Modalità di accesso', 'Account Holder first and last name' => 'Account Holder first and last name', 'Account Information' => 'Informazioni Business', 'Account Name' => 'Nome Account', 'Account Number / IBAN' => 'Numero Conto / IBAN', 'Account holder name' => 'Intestatario Conto', 'Account number' => 'Numero Account', 'Action on Simultaneous Login Attempt' => 'Azione in caso di accesso simultaneo', 'Actions' => 'Azioni', 'Activate' => 'Attiva', 'Activation' => 'Attivazione', 'Active' => 'Attivo', 'Active Resources' => 'Download Attivi', 'Active Subscriptions' => 'Risorse Attive', 'Active Users' => 'Utenti Attivi', 'Active Users by Period' => 'Utenti Attivi per Periodo', 'Active Users by Products' => 'Utenti Attivi per Prodotto', 'Active subusers' => 'SubUser Attivi', 'Add' => 'Aggiungi', 'Add "Like" button' => 'Aggiungi pulsante "Mi Piace"', 'Add Access depends on current user\'s groups in ' => 'Aggiungi accesso se l\'utente è nei seguenti gruppi', 'Add Affiliate Points' => 'Aggiungi Punti Affiliato', 'Add Attachments' => 'Aggiungi allegati', 'Add Category Filter to Popup' => 'Aggiungi il filtro categoria al PopUp', 'Add Coupon Code to Affiliates' => 'Aggiungi il buono Sconto agli Affiliati', 'Add Membership' => 'Aggiungi Abbonamento', 'Add New Notification Rule' => 'Aggiungi Nuova Regola di Notifica', 'Add Result for Previous Period' => 'Confronta con dati precedenti', 'Add Result for Same Period in Previous Year' => 'Confronta con l\'anno precedente', 'Add Subscription Before Payment (HIDDEN)' => 'Aggiungi iscrizione prima del Pagamento (NASCOSTO)', 'Add Subscription to the following products right after signup form has been submitted, subscription will be added only for new users' => 'Aggiungi Iscrizione ai Prodotti subito dopo l\'invio del form di iscrizione, aggiunto solo per i nuovi utenti', 'Add Tax' => 'Aggiungi Tasse', 'Add User' => 'Aggiungi Utente', 'Add User Stamp this option applicalable only to PDF files' => 'Add User Stamp this option applicalable only to PDF files', 'Add Widget With Uploaded Files To User Dashboard' => 'Add Widget With Uploaded Files To User Dashboard', 'Add an \'empty\' option to select box to do not choose any products' => 'Add an \'empty\' option to select box to do not choose any products', 'Add free access to a product if user signup from Facebook' => 'Aggiungi Accesso Gratuito se l\'utente si iscrive con Facebook', 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Add reward points to referred affiliate on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)', 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)' => 'Add reward points to user on this product purchase (additional to configured on aMember CP -> Setup -> Reward Points)', 'Add the following product(s) on Expiration' => 'Aggiungi i seguenti prodotti alla Scadenza', 'Add the following product(s) on Signup' => 'Aggiungi i seguenti prodotti all\'Iscrizione', 'Add to Basket' => 'Metti nel Carrello', 'Add user to these groups' => 'Assegna all\'utente i seguenti gruppi', 'Add/Renew Subscription' => 'Acquista/Rinnova', 'Added' => 'Aggiunta', 'Added During Import' => 'Aggiunto in una importazione', 'Added between dates:' => 'Aggiunto tra le date:', 'Added during user creation by demand from plugin [%s]' => 'Aggiunto durante la creazione dell\'utente da parte del plugin [%s]', 'Additional Fields' => 'Campi Personalizzati', 'Address Details' => 'Indirizzo', 'Address Info' => 'Indirizzo', 'Address Info (must match your credit card statement delivery address)' => 'Indirizzo deve corrispondere a quello della carta', 'Address Info (must match your debit card statement delivery address)' => 'Address Info (must match your debit card statement delivery address)', 'Address Information' => 'Indirizzo', 'Admin' => 'Amministratore', 'Admin E-Mail' => 'Email Admin', 'Admin E-Mail Address' => 'Indirizzo Email dell\'Admin', 'Admin First Name' => 'Nome Admin', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Gruppi di Amministratore aMember non tocca mai gli account di %s assegnati ai seguenti gruppi. In questo modo gli account su %s vengono protetti da qualsiasi attività di aMember', 'Admin Last Name' => 'Cognome Admin', 'Admin Username' => 'Nome Utente Amministratore', 'Administrator' => 'Amministratore', 'Admins' => 'Amministratori', 'Advanced' => 'Impostazioni Avanzate', 'Advanced Search' => 'Ricerca Avanzata', 'Advertise our website to your friends and earn money' => 'Promuovi questo sito ai tuoi amici e guadagna', 'Affiliate' => 'Affiliato', 'Affiliate whenever coupons from this batch is used, commission will always be credited to this affiliate. This is true even when another affiliate is permanently tagged to the customer. For sales where the coupon is NOT used, the original (previous) affiliate will continue receiving commissions. If the customer has no affiliate, this affiliate will permanently be tagged to the customer, and will receive credit for future sales.' => 'Assegna Buoni ad Affiliato ogni volta che viene usato un Buono Sconto, la commissione verrà assegnata sempre all\'affiliato. Questo avviene anche se c\'è un altro Affiliato assegnato permanentemente al Cliente. Se il cliente non ha affiliati assegnati e usa il Buono Sconto, l\'affiliato viene assegnato al cliente in questione.', 'Affiliate Affiliate Link' => 'Link Affiliato', 'Affiliate Agreement' => 'Accordo con Affiliati', 'Affiliate Check - City' => 'Bonifico Affiliato - IBAN', 'Affiliate Check - Country' => 'Bonifico Affiliato - BIC/SWIFT', 'Affiliate Check - Payable To' => 'Bonifico Affiliato - Beneficiario', 'Affiliate Check - State' => 'Bonifico Affiliato - Nazione', 'Affiliate Check - Street Address' => 'Bonifico Affiliato - Indirizzo', 'Affiliate Check - ZIP Code' => 'Bonifico Affiliato - CAP/ZIP', 'Affiliate Clicks' => 'Click Affiliati', 'Affiliate Clicks for' => 'Click Affiliati per', 'Affiliate Coupons' => 'Buoni Sconto Affiliati', 'Affiliate Group IN (%s)' => 'Gruppo Affiliato IN (%s)', 'Affiliate Id#' => 'ID Affiliato #', 'Affiliate Info' => 'Affiliazione', 'Affiliate Keywords' => 'Keyword Affiliati', 'Affiliate Leads' => 'Lead Affiliato', 'Affiliate Link' => 'Link Affiliato', 'Affiliate Manager this user always will be assigned as 2-tier affiliate for all affiliates' => 'Affiliate Manager this user always will be assigned as 2-tier affiliate for all affiliates', 'Affiliate Payout - Pagseguro E-Mail address' => 'Payout Affiliato - Indirizzo Email Pagseguro', 'Affiliate Payout - Paypal E-Mail address' => 'Indirizzo Email di Paypal', 'Affiliate Payout - Propay E-Mail address' => 'Payout Affiliato - Indirizzo Email', 'Affiliate Payout Type' => 'Metodo di Pagamento', 'Affiliate Payouts' => 'Payout Affiliati', 'Affiliate Program' => 'Programma di Affiliazione', 'Affiliate Sales' => 'Vendite Affiliati', 'Affiliate Sales Number' => 'Numero Vendite Affiliati', 'Affiliate Signup Form' => 'Modulo di Registrazione Affiliato', 'Affiliate Source' => 'Provenienza Affiliato', 'Affiliate Tier' => 'Tier Affiliato', 'Affiliate commission to %s' => 'Commissione Affiliato a %s', 'Affiliate commission up to %s' => 'Commissioni Affiliato fino a %s', 'Affiliate generated %d item sales last %d days' => 'L\'affiliato ha generato %d vendite negli ultimi %d giorni', 'Affiliate generated %d sales last %d days' => 'L\'affiliato ha generato %d di vendite negli ultimi %d giorni', 'Affiliate generated %d%s in commissions last %d days' => 'L\'affiliato ha generato %d%s in commissioni negli ultimi %d giorni', 'Affiliate has Products IN (%s)' => 'Affiliato ha Prodotti IN (%s)', 'Affiliate has Products from Category IN (%s)' => 'Affiliato ha Prodotti nella Categoria IN (%s)', 'Affiliate info' => 'Programma di Affiliazione', 'Affiliate link with Custom Landing Page' => 'Link Affiliato con Pagina Landing Personalizzata', 'Affiliate points' => 'Punti Affiliato', 'Affiliate points current' => 'Punti Affiliato attuali', 'Affiliate points total' => 'Totale Punti Affiliato', 'Affiliate stats' => 'Statistiche Affiliato', 'Affiliates' => 'Affiliati', 'After Purchase Display this content on thank you page You can use %invoice.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.' => 'After Purchase Display this content on thank you page You can use %invoice.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.', 'After first payment has been completed' => 'Dopo che il primo pagamento viene completato', 'After the user has been added' => 'Dopo che l\'utente è stato aggiunto al database', 'Agreement text' => 'Testo dell\'accordo', 'All' => 'Tutti', 'All %s records on this page are selected' => 'Tutti i %s record su questa pagina sono stati selezionati', 'All Affiliates' => 'Tutti gli Affiliati', 'All Categories' => 'Tutte le Categorie', 'All Clicks' => 'Click Totali', 'All Downloads History Report' => 'Report di tutti i download', 'All Files' => 'Tutti i File', 'All Time' => 'Da Inizio Attività', 'All Users' => 'Tutti gli Utenti', 'All achieved affiliate points' => 'Tutti i Punti Affiliato archiviati', 'All records' => 'Tutti i Record', 'All/Unique Clicks' => 'Click (Totali/Unici)', 'Allow Affiliate to redirect Referrers to any url' => 'Permetti all\'affiliato di redirigere i Referrers a qualsiasi url', 'Allow Instant Commission functionality for all affiliates By default instant commissions will be enabled only if you enable this in affiliate profile' => 'Allow Instant Commission functionality for all affiliates By default instant commissions will be enabled only if you enable this in affiliate profile', 'Allow Login via IP Address' => 'Permetti il Login con l\'indirizzo IP', 'Allow payment if anonymous proxy Whether IP address is %sAnonymous Proxy%s (anonymous proxy = very high risk)' => 'Allow payment if anonymous proxy Whether IP address is %sAnonymous Proxy%s (anonymous proxy = very high risk)', 'Allow payment if country not matched Whether country of IP address matches billing address country (mismatch = higher risk)' => 'Allow payment if country not matched Whether country of IP address matches billing address country (mismatch = higher risk)', 'Allow payment if free e-mail Whether e-mail is from free e-mail provider (free e-mail = higher risk)' => 'Allow payment if free e-mail Whether e-mail is from free e-mail provider (free e-mail = higher risk)', 'Allow payment if high risk countries Whether IP address or billing address country is in Egypt, Ghana, Indonesia, Lebanon, Macedonia, Morocco, Nigeria, Pakistan, Romania, Serbia and Montenegro, Ukraine, or Vietnam' => 'Allow payment if high risk countries Whether IP address or billing address country is in Egypt, Ghana, Indonesia, Lebanon, Macedonia, Morocco, Nigeria, Pakistan, Romania, Serbia and Montenegro, Ukraine, or Vietnam', 'Allow to Search Directory by the following Fields' => 'Permetti di cercare le Directory con i seguenti campi', 'Allow to export Leads' => 'Permetti di esportare i Lead', 'Allow to filter Leads' => 'Permetti di filtrare i Lead', 'Allowed Phone Types The TNI service is able to categorize customer inputted US and Canadian phone numbers into %seight different phone types%s such as fixed land line, mobile, VoIP, and invalid phone numbers' => 'Allowed Phone Types The TNI service is able to categorize customer inputted US and Canadian phone numbers into %seight different phone types%s such as fixed land line, mobile, VoIP, and invalid phone numbers', 'Already in Basket' => 'Già presente nel Basket', 'Alternate' => 'Alterna', 'Always' => 'Sempre', 'Amazon S3 storage is not configured' => 'Account Amazon S3 non è configurato', 'Amount' => 'Importo', 'Amount Paid' => 'Bilancio Finale', 'An Error has occurred' => 'Si è verificato un Errore', 'An account with the same email [%s] is already exists.' => 'Esiste già un account con la stessa email [%s].', 'An account with the same email already exists.' => 'Esiste già un account con lo stesso indirizzo e-mail.', 'An error occurred while cancellation request' => 'Errore durante la richiesta di cancellazione', 'An error occurred while handling your payment or you cancelled it.' => 'Errore nell\'elaborare il tuo pagamento, oppure lo hai cancellato.', 'An error occurred while handling your payment.' => 'Si è verificato un errore durante la gestione del tuo pagamento.', 'An internal error happened in the script, please contact webmaster for details' => 'Si è verificato un errore interno, ti prego di avvertire l\'amministratore', 'Anti Spam check failed' => 'Controllo Anti Spam fallito', 'Any' => 'Qualsiasi', 'Any Product' => 'Qualsiasi Prodotto', 'Any product' => 'Qualsiasi Prodotto', 'Api Key' => 'Chiave API', 'Application' => 'Iscrizione', 'Apply' => 'Applica', 'Apply Coupon (optional)' => 'Applica Buono Sconto (opzionale)', 'Apply Filter' => 'Applica Filtro', 'Assign Group' => 'Assegna Gruppo', 'Assign JACL Group' => 'Assegna Gruppo JACL', 'Assign JomSocial Group' => 'Assegna Gruppo JomSocial', 'Assign User Groups (HIDDEN)' => 'Assegna Gruppo (NASCOSTO)', 'Assign this Ticket to yourself' => 'Assegna il Ticket a te', 'Assigned by Administrator %s at %s' => 'Assegnato dall\'Amministratore %s a %s', 'Assigned by COOKIE at %s' => 'Assegnato dal COOKIE a %s', 'Assigned by Coupon %s at %s' => 'Assegnato dal Buono Sconto %s a %s', 'Assigned by IP %s at %s' => 'Assegnato da IP %s a %s', 'Assigned by Invoice %s at %s' => 'Assegnato dalla Ricevuta %s a %s', 'Assigned to usergroup' => 'Assegnato al Gruppo', 'Attach File' => 'Allega File', 'Attachments' => 'Allegati', 'Authentication' => 'Autenticazione', 'Authentication problem, please contact website administrator' => 'Problema di autenticazione, contatta l\'amministratore', 'Auto Login Link' => 'Link di AutoLogin', 'Auto-Responder' => 'AutoRisponditore', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Iscivi automaticamente gli utenti alla lista quando diventa accessibile per loro', 'Auto-generated Template Settings' => 'Impostazioni Template Default', 'Available Bricks (drag to left to add)' => 'Campi Disponibili (trascina a sinistra per aggiungerli)', 'Available Credits' => 'Crediti Disponibili', 'Avatar Size width×height' => 'Dimensione Avatar larghezza × altezza', 'Average Lifetime Value' => 'Valore Medio a Vita', 'Average Lifetime Value (Cohort Analysis)' => 'Valore Medio a Vita (Analisi Cohort)', 'Avoid using standard layout you have to design entire page in the \'Offer Text\' field' => 'Avoid using standard layout you have to design entire page in the \'Offer Text\' field', 'Awaiting Admin Response' => 'In Attesa di Risposta dall\'Amministratore', 'Awaiting User Response' => 'In Attesa di Risposta dall\'Utente', 'Aweber Application' => 'Applicazione Aweber', 'Back' => 'Indietro', 'Back to shopping' => 'Continua Acquisti', 'Bad URL, enter the correct OpenGate URL' => 'URL errato, inserisci un OpenGate URL corretto', 'Bank Account Name name associated with the bank account' => 'Bank Account Name name associated with the bank account', 'Bank Account Number' => 'Numero Conto Banca', 'Bank Account Number Up to 20 digits' => 'Bank Account Number Up to 20 digits', 'Bank Account Type please select one' => 'Bank Account Type please select one', 'Bank Code' => 'Codice Banca', 'Bank Details' => 'Dettagli Banca', 'Bank Identification' => 'Identificazione Banca', 'Bank Name' => 'Nome Banca', 'Bank Name name of the bank which issued the credit card' => 'Bank Name name of the bank which issued the credit card', 'Bank Phone customer service phone number listed on back of your credit card' => 'Bank Phone customer service phone number listed on back of your credit card', 'Bank code / BIC' => 'BIC/SWIFT', 'Bank name' => 'Nome Banca', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Gruppi Bannati aMember non tocca mai gli account di %s assegnati ai seguenti gruppi. In questo modo gli account su %s vengono protetti da qualsiasi attività di aMember', 'Banners and Links' => 'Link e Banner', 'Banners and Text Links' => 'Gestisci Link e Banner', 'Batch for Affiliate Coupons new coupons for affiliate will be generated in this batch' => 'Batch for Affiliate Coupons new coupons for affiliate will be generated in this batch', 'Begin' => 'Inizia', 'Begin Date' => 'Data di Inizio', 'Below Form' => 'Sotto il Form', 'Below Form (Footer)' => 'Sotto il Form (Footer)', 'Between Dates' => 'Tra le Date', 'Billing Address' => 'Indirizzo di Pagamento', 'Billing Address must match your credit card statement delivery address' => 'Billing Address must match your credit card statement delivery address', 'Billing International Province for international provinces outside of US & Canada include the province name here' => 'Billing International Province for international provinces outside of US & Canada include the province name here', 'Billing Name Billing Address First and Last name' => 'Billing Name Billing Address First and Last name', 'Billing Plan(s) to display' => 'Piani di Pagamento da visualizzare', 'Bonuses' => 'Bonus', 'Both Affiliate and member' => 'Entrambi, Affiliati e Utenti', 'Bounces' => 'Rimbalzi', 'Brick Position' => 'Posizione Inserto', 'Browse Events' => 'Analizza gli Eventi', 'Bruteforce Notification' => 'Notifica Forzatura Password', 'Bulk Actions' => 'Azioni di Gruppo', 'Bundle Discount' => 'Sconto sul Bundle', 'Button Title' => 'Nome Pulsante', 'CC Demo' => 'Demo CC', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'Errore di protezione CSRF - il modulo deve essere inviato entro %d minuti dopo la visualizzazione, riprova', 'CSS Selector for conteiner' => 'Selettore CSS per il Contenitore', 'CSV File was not specified' => 'Non hai specificato il file CSV', 'Campaign' => 'Campagna', 'Can Operate with Notifications' => 'Può Operare con le Notifiche', 'Can Operate with OTO' => 'Può Operare con le OTO', 'Can add/edit/delete Milestones' => 'Può aggiungere/cambiare/cancellare i Milestone', 'Can manage software licenses' => 'Può cambiare le licenze', 'Can manage software licensing schemes' => 'Può cambiare gli schemi licenza dei software', 'Can manage webhooks' => 'Può cambiare i webhooks', 'Can not handle this billing terms' => 'Non posso gestire questi termini di pagamento', 'Can not handle this billing terms: first_period != second_period' => 'Non posso gestire questi termini di pagamento: first_period != second_period', 'Can not handle this billing terms: first_total is zero' => 'Non posso gestire questi termini di pagamento: first_total è zero', 'Can not handle this billing terms: not in possible periods' => 'Non posso gestire questi termini di pagamento: periodi non accettabili', 'Can view/edit customer Credit Card information and rebills' => 'Può vedere/modificare le informazioni della Carta di Credito dei Clienti e i Riaddebiti', 'Can\'t obtaint OAuth2 token' => 'Non riesco ad ottenere il token OAuth2', 'Cancel' => 'Annulla', 'Cancel Feedback' => 'Cancella Feedback', 'Cancel Subscription' => 'ANNULLA ABBONAMENTO RICORRENTE', 'Cancelation Reason' => 'Motivo della Cancelazione', 'Cancellation Feedback' => 'Feedback Cancelazione', 'Cancellation Reason' => 'Ragione della Cancelazione', 'Cancellation Reasons' => 'Ragioni della Cancelazione', 'Cancelled' => 'Annullata il', 'Cannot connect to database. Check hostname, username and password settings' => 'Non riesco a connettermi con il database. Controlla hostname, username e password', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Non si può usare il plugin del pagamento GRATIS con un prodotto che costa più di 0.0', 'Cannot validate VAT Id, please try again' => 'Non è stato possibile convalidate il VAT Id, prova di nuovo', 'Card Expire Month and Year' => 'Scadenza Carta mese e anno', 'Card Expire Select card expiration date - month and year' => 'Scadenza Carta mese e anno', 'Card Expires' => 'Carta Scade', 'Card Issue # is required for Maestro/Solo/Switch credit cards only' => 'Card Issue # is required for Maestro/Solo/Switch credit cards only', 'Card Start Date is required for Maestro/Solo/Switch credit cards only' => 'Card Start Date is required for Maestro/Solo/Switch credit cards only', 'Cardholder Name cardholder first and last name, exactly as on the card' => 'Nome e Cognome come compaiono sulla carta', 'Catalog Prices Include Tax' => 'I prezzi a catalogo includono le tasse', 'Categories' => 'Categorie', 'Category' => 'Categoria', 'Category [%s] not found' => 'Categoria [%s] non trovata', 'Category of question' => 'Categoria di domande', 'Change' => 'Modifica', 'Change Category' => 'Cambia Categoria', 'Change Manager' => 'Cambia Manager', 'Change Owner' => 'Cambia Owner', 'Change Password' => 'Modifica Password', 'Change Password/Edit Profile' => 'Cambia Password/Modifica Profilo', 'Change Subscription' => 'Modifica Iscrizione', 'Change Username' => 'Modifica Nome Utente', 'Change Your Password' => 'Cambia Password', 'Change payout info' => 'Modifica Sistema di Pagamento', 'Changes in User Profile' => 'Modifiche nel Profilo Utente', 'Check Payable To' => 'Assegno pagabile a', 'Checkboxes (multiple products can be selected)' => 'Checkbox (puoi selezionare più prodotti)', 'Checkboxes for Selected Lists' => 'Checkbox per le Liste Selezionate', 'Checkout' => 'Paga', 'Checkout Secret Key at paddle.com' => 'Controlla la Secret Key su paddle.com', 'Checkout error: ' => 'Errore nel Pagamento:', 'Checkout payment' => 'Completa Pagamento', 'Choose New Password must be %d or more characters' => 'Choose New Password must be %d or more characters', 'Choose a Password must be %d or more characters' => 'Scegli una Password deve avere %d o più caratteri', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Scegli un Nome Utente deve essere di almeno %d caratteri e può contenere solo lettere, numeri e il simbolo underscore ( _ )', 'Choose admins to include to roster You can choose same admin several times to balance tickets accordingly' => 'Choose admins to include to roster You can choose same admin several times to balance tickets accordingly', 'Choose another payment processor or try again with the same.' => 'Scegli un altro metodo di pagamento o riprova.', 'Choose date Period to rebuild' => 'Scegli data/periodo per ricostruire', 'Choose products to include into test invoice' => 'Scegli i prodotti da incluedere nella ricevuta di prova', 'Churn Rate' => 'Tasso Abbandono', 'City' => 'Comune', 'City ' => 'Comune', 'Clear Pending Invoices' => 'Cancella ricevute pendenti', 'Click "Continue" to pay this order using stored credit card %s' => 'Clicca "Continua" per pagare usando la carta registrata %s', 'Click Url' => 'Clicca URL', 'Click button to continue' => 'Clicca il pulsante per continuare', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Clicca qui se non vuoi aspettare oltre (o se il tuo browser si è fermato qui).', 'Click to Assign' => 'Clicca per Assegnare', 'Click to Edit' => 'Clicca per Modificare', 'Clicks' => 'Click', 'Clicks/Sales Statistics' => 'Statistiche Affiliati', 'Close' => 'Chiudi', 'Close This Ticket After Response' => 'Chiusi questo Ticket dopo aver risposto', 'Close Ticket' => 'Chiudi il Ticket', 'Close Ticket(s)' => 'Chiudi Ticket', 'Closed' => 'Chiuso', 'Code' => 'Codice', 'Comment' => 'Nota', 'Comment for admin reference' => 'Nota per Admin', 'Comment for your reference' => 'Nota per tua referenza futura', 'Comment will be shown above table with users' => 'Commento visualizzato sopra le tabelle con utenti', 'Comments? (Optional)' => 'Commenti? (Opzionale)', 'Commission' => 'Commissioni Guadaganate', 'Commission Earned' => 'Commissioni Guadagnate', 'Commission Rules' => 'Regole Commissioni', 'Commissions' => 'Commissioni', 'Company Logo for Invoice it must be png/jpeg/tiff file' => 'Logo per la Ricevuta deve essere un file png/jpeg/tiff', 'Company Name the company name associated with the billing address for the transaction' => 'Company Name the company name associated with the billing address for the transaction', 'Complete Payment' => 'Completa il Pagamento', 'Completed' => 'Completato', 'Condition' => 'Condizione', 'Conditions After actual payment aMember will check user invoice and in case of it contains one of defined product or product from defined product category this OTO will be shown for him instead of ordinary thank you page. In case of you use OTO (Downsell) condition it will be matched if user click NO link in defined offer and this OTO will be shown for user' => 'Conditions After actual payment aMember will check user invoice and in case of it contains one of defined product or product from defined product category this OTO will be shown for him instead of ordinary thank you page. In case of you use OTO (Downsell) condition it will be matched if user click NO link in defined offer and this OTO will be shown for user', 'Conditions/Commissions' => 'Condizioni/Commissioni', 'Configuration' => 'Configurazione', 'Configured Tax Values' => 'Valori Tasse Configurati', 'Confirm' => 'Conferma', 'Confirm Billing Country' => 'Conferma Sede Fiscale', 'Confirm E-Mail Address second field will be displayed to enter email address twice' => 'Conferma Email compare un nuovo campo per confermare l\'email', 'Confirm New Password' => 'Conferma Nuova Password', 'Confirm Password' => 'Conferma Password', 'Confirm Payment' => 'Conferma Pagamento', 'Confirm Your E-Mail Address' => 'Conferma Indirizzo Email', 'Confirm Your Password' => 'Conferma la Password', 'Confirm download' => 'Conferma Download', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Un link di conferma è appena stato spedito nella tua casella di posta elettronica. Se non ricevi la mail entro 5 minuti, controlla nella cartella dello SPAM - potrebbe essere finita lì per errore.', 'Consider only initial purchase disregard subsequent recurring payments' => 'Consider only initial purchase disregard subsequent recurring payments', 'Content' => 'Contenuto', 'Content You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.' => 'Content You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.', 'Content Categories' => 'Categorie di Contenuto', 'Content Categories these categories will be shown in user\'s menu if user has access to resources in this category. You can uses these categories to organize your content by pages' => 'Categorie di Contenuto queste categorie verranno mostrate all\'utente nel menù se ha il permesso di accedere. Puoi utilizzare queste categorie per ognaizzare i tuoi contenuti in pagine', 'Continue' => 'Continua', 'Continue Shopping' => 'Continua Acquisti', 'Conversation' => 'Conversazione', 'Copy of' => 'Copia di', 'Corrective Invoice Number: ' => 'Numero Ricevuta corretto: ', 'Count' => 'Conteggio', 'Count Free item to match discount?' => 'Conteggio il prodotto gratuito per lo sconto?', 'Count conversion for these products only' => 'Conteggia comverisone solo per questi prodotti', 'Count of Messages' => 'Conteggio dei Messaggi', 'Count of User Messages in Helpdesk' => 'Conteggio dei Messaggi Utente nell\'Helpdesk', 'Count of product purchase' => 'Numero Prodotti Acquistati', 'Count of signups' => 'Numero di Registrazioni', 'Count of user signups' => 'Numero di Utenti Registrati', 'Country' => 'Nazione', 'Country Title' => 'Nazione', 'Coupon' => 'Buono Sconto', 'Coupon Batch' => 'Gruppo Buoni Sconto', 'Coupon Batch create coupons in this batch as invite codes' => 'Coupon Batch create coupons in this batch as invite codes', 'Coupon Code' => 'Codice Buono Sconto', 'Coupon Discount' => 'Buono Sconto', 'Coupon can be used only if you have active subscription for these products: %s' => 'Il Buono Sconto può essere usato solo se hai: %s', 'Coupon can be used only if you have expired subscription(s) for these products: %s' => 'Il Buono Sconto può essere usato solo se non hai: %s', 'Coupon cannot be used because you have active subscription(s) to: %s' => 'Non puoi usare questo Buono Sconto perché hai: %s', 'Coupon cannot be used because you have expired subscription(s) to: %s' => 'Non puoi usare questo Buono Sconto perché non hai: %s', 'Coupon code disabled' => 'Buono Sconto Disabilitato', 'Coupon code expired' => 'Buono Sconto Scaduto', 'Coupon is not yet active' => 'Il Buono Sconto non è ancora attivo', 'Coupon usage limit exceeded' => 'Numero Massimo di utilizzo del Buono Sconto superato', 'Coupons one coupon per line' => 'Coupons one coupon per line', 'Coupons Batch' => 'Gruppo Buoni Sconto', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Crea Utenti aMember in Automatico crea nuovo utente in aMember se si logga in aMember le stesse credenziali di %s', 'Created' => 'Creato', 'Credit Card Code' => 'Codice Carta (CVV) di 3 cifre, dietro la carta', 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards)' => 'Codice Carta (CVV) di 3 cifre, dietro la carta', 'Credit Card Code The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).' => 'Codice Carta (CVV) di 3 cifre, dietro la carta', 'Credit Card Info' => 'Info Carta di Credito', 'Credit Card Number' => 'Numero Carta', 'Credit Card Number for example: 1111-2222-3333-4444' => 'Numero Carta senza spazi o simboli', 'Credit Card Rebills' => 'Riaddebiti Carte', 'Credit Card Type please select one' => 'Credit Card Type please select one', 'Credit Cards' => 'Carte di Credito', 'Credits' => 'Crediti', 'Credits Balance' => 'Totale Crediti', 'Credits History' => 'Storico Crediti', 'Credits spent by products breakdown' => 'Crediti usati per prodotto', 'Currency' => 'Valuta', 'Currency which currencies to fetch' => 'Currency which currencies to fetch', 'Currency you can choose from list of currencies supported by paysystems' => 'Valuta scegli tra le valute supportate dal Sistema di Pagamento', 'Currency Code' => 'Codice Valuta', 'Currency Exchange Rates' => 'Cambio valuta', 'Current affiliate points' => 'Punti Affiliato Attuali', 'Current password entered incorrectly, please try again' => 'Hai inserito la password attuale sbagliata. Riprova', 'Custom Bold Font for Invoice (optional) Useful for invoices with non-Latin symbols when there is a problem with displaying such symbols in the PDF invoice.Please upload .ttf file only.' => 'Font Grassetto Personalizzato Ricevuta (opzionale) utile per ricevute con simboli non latini quando c\'è un problema di visualizzazione di alcuni simboli. Caricare solo file.ttf ', 'Custom Commission' => 'Commissione Personalizzata', 'Custom Element' => 'Elemento Personalizzato', 'Custom Font for Invoice (optional) Useful for invoices with non-Latin symbols when there is a problem with displaying such symbols in the PDF invoice. Please upload .ttf file only.' => 'Font Personalizzato Ricevuta (opzionale) utile per ricevute con simboli non latini quando c\'è un problema di visualizzazione di alcuni simboli. Caricare solo file.ttf ', 'Custom PDF Template for Invoice (optional)' => 'Template Ricevuta Personalizzato (opzionale)', 'Custom Template Settings' => 'Impostazioni Template Personalizzato', 'Customer account has been automatically locked.' => 'Account del Cliente bloccato automaticamente.', 'Customize' => 'Personalizza', 'DONE' => 'FATTO', 'Dashboard' => 'Bacheca', 'Data Integrity Code' => 'Codice Integrità dei Dati', 'Database name or prefix is wrong - could not find table [%s] with fields [%s] inside database [%s]:' => 'Nome p prefisso database errato - non trovo la tabella [%s] con i campi [%s] nel database [%s]:', 'Date' => 'Data ', 'Date and time of payment: %s' => 'Data e Ora del Pagamento: %s', 'Date must be in format %s' => 'La data deve essere nel formato %s', 'Date of First Collection' => 'Data della prima collezione', 'Date/Time' => 'Data/Ora', 'Date: ' => 'Data: ', 'Dates date range when notification is shown' => 'Dates date range when notification is shown', 'Day' => 'Giorno', 'Day of Notification Sending' => 'Giorno di invio della Notifica', 'Days' => 'Giorni', 'Deactivate Student' => 'Disattiva Studente', 'Deactivate User' => 'Disattiva Utente', 'Debit Card Number' => 'Numero Carta di Debito', 'Decline all transactions Plugin will decline all payment attempts' => 'Decline all transactions Plugin will decline all payment attempts', 'Decrease Affiliate Points' => 'Diminuisci Punti Affiliato', 'Default Avatar' => 'Avatar di Default', 'Default Coupon Batch placeholder %coupon% will be replaced with coupon code from this batch' => 'Default Coupon Batch placeholder %coupon% will be replaced with coupon code from this batch', 'Default Home Folder' => 'Cartella Home di Default', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Livello di Default livello di default - l\'utente torna a questo livello di accesso a meno che non esista un\'iscrizione attiva (è il caso in cui tutte le iscrizioni sono scadute)', 'Default Level users created by demand will have access to the sele (for example all subscriptions expired)' => 'Default Level users created by demand will have access to the sele (for example all subscriptions expired)', 'Default Order By' => 'Ordina Default per', 'Default Product' => 'Product di Default', 'Default Product access to this product will be added if customer has not any other active subscription and vise versa access to this product will be removed if customer signup to any other product' => 'Default Product access to this product will be added if customer has not any other active subscription and vise versa access to this product will be removed if customer signup to any other product', 'Default Value for this field hidden field will be populated with this value' => 'Default Value for this field hidden field will be populated with this value', 'Default amount of donation' => 'Donazione di Default', 'Default unchecked Leave unchecked if you want newsletter default to be checked' => 'Default unchecked Leave unchecked if you want newsletter default to be checked', 'Define Custom Html Message' => 'Definisci il messaggio HTML personalizzato', 'Delete' => 'Elimina', 'Delete %s' => 'Elimina %s', 'Delete other session when user try to login from new one' => 'Blocca l\'altra sessione se l\'utente ne crea un\'altra', 'Delivery Time' => 'Ora di Spedizione', 'Description' => 'Descrizione', 'Detail Page Fields link to details page will be displayed if any fields are selected here' => 'Detail Page Fields link to details page will be displayed if any fields are selected here', 'Detail Page Template alternative template for detail page' => 'Detail Page Template alternative template for detail page', 'Device' => 'Dispositivo', 'Did\'t Use Any Coupon' => 'Nessun Buono Sconto', 'Did\'t Use Coupon from Batch: %s' => 'Non ha usato Buono Sconto del Gruppo: %s', 'Did\'t Use Coupon with Code: %s' => 'Non ha usato Buono Sconto: %s', 'Digits only please' => 'Solo numeri prego', 'Direct Debits are not available in your country (%s)' => 'Direct Debit non è disponibile nella tua nazione (%s)', 'DirectOne Merchant ID your directone 9-digit merchant id' => 'DirectOne Merchant ID your directone 9-digit merchant id', 'DirectOne Password it is special password which can be set via the Settings page of the Members section on the DirectOne website' => 'DirectOne Password it is special password which can be set via the Settings page of the Members section on the DirectOne website', 'Directory Access' => 'Accesso alla Cartella', 'Disable' => 'Disabilita', 'Disable Ability to Update Profile in case of user logged in via IP' => 'Disabilita Modifica Profili nel caso l\'utente sia loggato via IP', 'Disable Single Login Session Protection' => 'Disabilita Protezione Login Unico', 'Disable login via IP if this box is checked, login via IP will not work for your account' => 'Disable login via IP if this box is checked, login via IP will not work for your account', 'Disable online VAT Id Validation' => 'Disabilita la validazione online della VAT Id', 'Disabled' => 'Disabilitato', 'Discard' => 'Abbandona', 'Discount' => 'Sconto', 'Discount this discount will be applied to total of invoice. In case of discount is more than total - discount will be ignored. if user use coupon with purchase - max discount will be used' => 'Discount this discount will be applied to total of invoice. In case of discount is more than total - discount will be ignored. if user use coupon with purchase - max discount will be used', 'Discount Rule' => 'Regola Sconto', 'Display' => 'Visualizza', 'Display All Affiliate Coupons' => 'Mostra tutti i Buoni Sconto Affiliati', 'Display All Products' => 'Mostra tutti i Prodotti', 'Display It Anyway' => 'Mostra comunque', 'Display Link Invite a Friend in Active Resources block' => 'Display Link Invite a Friend in Active Resources block', 'Display Link Invite a Friend in Useful Links block' => 'Display Link Invite a Friend in Useful Links block', 'Display List of Invited Users in customer account' => 'Display List of Invited Users in customer account', 'Display Products in Popup' => 'Mostra Prodotti nel PopUp', 'Display Separate Block on customer dashboard' => 'Display Separate Block on customer dashboard', 'Display Separate Invoice for Refunds Setting affect aMember Control Panel only. User will see regular invoice which includes refund information inside' => 'Mantieni Ricevuta Separata per Rimborsi Admin vede comunque la ricevuta originale, il cliente vede la ricevuta con indicato il rimborso.', 'Display Type' => 'Tipo di Visualizzazione', 'Display in 2 rows' => 'Visualizza in 2 righe', 'Display name publicly as' => 'Mostra Nome Pubblico come', 'Display new Terms only active users of leave empty to show for all users' => 'Display new Terms only active users of leave empty to show for all users', 'Disregard' => 'Abbandona', 'Do Import' => 'Importa Adesso', 'Do not Include Subscription Terms to PDF Invoice' => 'Non includere Termini Iscrizione nel PDF', 'Do not add to Login Form' => 'Non aggiungere al Modulo di Login', 'Do not add to Signup Form' => 'Non aggiungere al Modulo di Registrazione', 'Do not check Access Permissions for this field on this form (show it without any conditions)' => 'Do not check Access Permissions for this field on this form (show it without any conditions)', 'Do not create coupon for affiliate' => 'Non creare Buono Sconto per Affiliato', 'Do not require to fill in these fields' => 'Campi non obbligatori', 'Do not show \'Credits Balance\' link at Useful Links' => 'Non mostrare il link \'Totale Crediti\' tra i Link Utili', 'Do not show \'Credits History\' tab at User Menu' => 'Non mostrare il menù \'Storico Crediti\' nell\'account utente', 'Do you really want to %s %s %s records' => 'Vuoi veramente %s %s %s record', 'Do you really want to %s?' => 'Vuoi veramente %s?', 'Do you really want to cancel subscription?' => 'Vuoi veramente annullare la tua iscrizione?', 'Do you really want to delete record?' => 'Vuoi veramente eliminare il record?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Vuoi veramente cancellarti dalla lista %s?', 'Do you really want to void commission?' => 'Vuoi veramente cancellare la commissione?', 'Does not Ask Current Password user will not need to enter his current password to change it' => 'Does not Ask Current Password user will not need to enter his current password to change it', 'Does not Confirm Password second field will not be displayed to enter password twice' => 'Does not Confirm Password second field will not be displayed to enter password twice', 'Does not allow to Copy&Paste to confirmation field' => 'Non permettere il copia/incolla nel campo di conferma', 'Does not allow to close notification' => 'Non permettere la chiusura della notifica', 'Does not show Agreement Text display only tick box' => 'Does not show Agreement Text display only tick box', 'Donation Amount %s' => 'Donazione di %s', 'Donation Product Product which will be added to user\'s account' => 'Donation Product Product which will be added to user\'s account', 'Done' => 'Fatto', 'Donee' => 'Donatore', 'Donee name' => 'Nome del Donatore', 'Donee\'s Invoice' => 'Ricevuta del Donatore', 'Download' => 'Scarica', 'Download Files (.zip)' => 'Scarica File (.zip)', 'Download Invoices (.pdf)' => 'Scarica Ricevute (.pdf)', 'Download Invoices As Single File (.pdf)' => 'Scarica Ricevute in un unico file (.pdf)', 'Download limit exceeded for this file' => 'Numero di download massimo superato per questo file', 'Downloaded on your own server' => 'Scaricato sul tuo server', 'Downloads' => 'Download', 'Downloads History' => 'Storico Download', 'Downloads History Report per File' => 'Report Storico Download per File', 'Downloads History Report per User' => 'Report Storico Download per Utente', 'Downloads by files breakdown' => 'Download per File', 'Drag&Drop rows to change display order. You may want to temporary change setting \'%sRecords per Page (for grids)%s\' to some big value so all records were on one page and you can arrange all items.' => 'Sposta le righe con Drag&Drop per cambiare l\'ordine.
      Eventualmente aumenta temporaneamente i \'%sRisultati per Pagina%s\'
      così da avere tutte le righe su una unica pagina.', 'Drop Me' => 'Cancellami', 'E-Mail' => 'Email', 'E-Mail Address' => 'Indirizzo Email', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'Email e Conferma Email sono diversi. Per favore inseriscili di nuovo entrambi.', 'E-Mail Format' => 'Formato Email', 'E-Mail Messages' => 'Messaggi Email', 'E-Mail Verification' => 'Verifica Indirizzo Email', 'EU VAT ID: ' => 'EU VAT (Partita Iva): ', 'EU VAT Id (optional)' => 'EU VAT (Partita Iva) Inserisci anche il prefisso', 'EU VAT Report' => 'EU VAT Resoconto', 'Edit' => 'Modifica', 'Edit %s' => 'Modifica %s', 'Edit Brick Labels' => 'Modifica Etichette Campo', 'Edit Categories' => 'Modifica Categorie', 'Edit E-Mail Template' => 'Modifica Template Email', 'Edit Profile Form' => 'Modifica il Form del Profilo', 'Edit Your Cart' => 'Modifica la Carta', 'Electronically Supplied Service Enable if ALL your products are electronic services.' => 'Servizi Somministrati Via Web Abilita se TUTTI i tuoi prodotti sono servizi elettronici.', 'Electronically Supplied Service Enable if your product is an electronic service.' => 'Servizi Somministrati Via Web Abilita se TUTTI i tuoi prodotti sono servizi elettronici.', 'Email' => 'Email', 'Email Address' => 'Indirizzo Email', 'Email Confirmation URL' => 'Link Conferma Email', 'Email Link' => 'Link Email', 'Email Placeholder' => 'Segnaposto Email', 'Email Subject' => 'Oggetto Email', 'Email Template For Donee' => 'Template Email per Donatore', 'Email Template For Grantor' => 'Template Email per Concedente', 'Email [%s] is not valid' => 'Email [%s] non valida', 'Email admin regarding account sharing' => 'Email all\'Amministratore se Blocco Utente per condivisione account', 'Email change confirmation' => 'Conferma di Cambio Email', 'Email user regarding account sharing' => 'Email al Cliente se Blocco Utente per condivisione account', 'Emotional' => 'Emotivo', 'Empty response from Sagepay server' => 'Risposta nulla dal server Sagepay', 'Enable' => 'Abilita', 'Enable Debug Mode' => 'Abilita Modalità Debug', 'Enable Gift Option By Default' => 'Abilita L\'opzione Regalo di Default', 'Enable Instant Commissions' => 'Abilita Commissioni Istantanee', 'Enable Location Validation aMember will require two peices of location evidence before an invoice is created. Invoice that fials validation will be blocked and user will receive warning.' => 'Abilita Validazione Nazione aMember richiederà due prove di provenienza prima di creare la ricevuta. Se la validazione fallisce la ricevuta viene bloccata e l\'utente avvisato.', 'Enable PDF Invoice attach invoice file (.pdf) to Payment Receipt email' => 'Abilita Ricevuta PDF allegata alla Email Ricevuta Pagamento', 'Enable Receipts Emails' => 'Abilita ricevuta via Email', 'Enable Self-Validation If validation failed, user will be able to confirm current location manually ' => 'Abilita Auto Validazione se la validazione automatica fallisce, l\'utente può confermare la nazionalità manualmente. ', 'Enable double opt-in' => 'Abilita il double opt-in', 'Enable for Admins' => 'Abilita per gli Amministratori', 'Enable for Users' => 'Abilita per gli Utenti', 'Enabled' => 'Abilitato', 'Enabled Modules' => 'Abilita Moduli', 'Encrypt/Decrypt secret key' => 'Crittografa/Decrittografa SecretKey', 'End' => 'Fine', 'End Date' => 'Data di Termine', 'Enjoy your membership. Please click %shere%s to access your member\'s area.' => 'Goditi il tuo acquisto. Per favore clicca %squi%s per accedere alla tua area riservata.', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Congratulazioni per la tua iscrizione. Per entrare e utilizzare il materiale entra nell\'area riservata qui %sEntra%s', 'Enter ID generated by software' => 'Inserisci ID generato dal software', 'Enter coupon code' => 'Buono Sconto se ce l\'hai inseriscilo qui', 'Enter gift voucher code' => 'Inserisci il Codice Omaggio', 'Enter username of existing user' => 'Inserisci Nome Utente esistente', 'Error' => 'Errore', 'Error 404 - Not Found' => 'Errore 404 - Non Trovato', 'Error : upload folder [%s] does not exists' => 'Errore : la cartella di aupload [%s] non esiste', 'Error Message' => 'Message di Errore', 'Error from Storage Engine' => 'Errore dal Motore di Storage', 'Error happened during payment process' => 'Errore durante il processo di pagamento', 'Error happened during payment process. ' => 'Errore durante il processo di pagamento.', 'Error happened during transaction handling. Please contact website administrator' => 'Errore durante la gestione della transazione. Contatta l\'amministratore.', 'European (A4)' => 'Europeo (A4)', 'Exact' => 'SCEGLI LE DATE', 'Exclude from Directory if this box is checked, user will not be displayed in public members directory' => 'Exclude from Directory if this box is checked, user will not be displayed in public members directory', 'Exclude from Directory if this box is checked, you will not be displayed in public members directory' => 'Exclude from Directory if this box is checked, you will not be displayed in public members directory', 'Exclude the following categories from Filter' => 'Escludi le seguenti categorie', 'Expiration Date' => 'Data di Scadenza', 'Expiration E-Mail' => 'Email di Scadenza', 'Expire' => 'Scade', 'Expire Date' => 'Data di Scadenza', 'Expire Product Title' => 'Nome Prodotto Scaduto', 'Expire the following product(s) on Expiration' => 'Fai scadere i seguenti prodotti alla Scadenza', 'Expire the following product(s) on Signup' => 'Fai scadere i seguenti prodotti all\'iscrizione', 'Expired' => 'Scaduto', 'Expired List User will be added to this list immediately when his subscription expires' => 'Expired List User will be added to this list immediately when his subscription expires', 'Expired Users' => 'Utenti Scaduti', 'Expires' => 'Scade', 'Export' => 'Esporta', 'Export Format' => 'Formato di Esportazione', 'External Coupon' => 'Buono Sconto Esterno', 'FaceBook App ID' => 'ID App Facebook', 'FaceBook Application' => 'Applicazione Facebook', 'Facebook App Secret' => 'Chiave Segreta dell\'App Facebook', 'Facebook SDK was not loaded. Got an error: %s' => 'Facebook SDK non caricata. C\'è stato un errore: %s', 'Fallback paysystems if invoice was started with %s and user canceled payment process OR payment was failed. By default all enabled paysystems will be listed' => 'Fallback paysystems if invoice was started with %s and user canceled payment process OR payment was failed. By default all enabled paysystems will be listed', 'Features' => 'Caratteristiche', 'Field' => 'Campo', 'Field Revisions' => 'Controllo Campi', 'Field Type' => 'Tipo di Campo', 'Field Updated' => 'Campo Aggiornato', 'Fields' => 'Campi', 'Fields To Display' => 'Campi da Visualizzare', 'Fields To Export' => 'Campi da Esportare', 'Fields delimited by' => 'Campi delimitati da', 'Fields to Display in Grid' => 'Campi da Visualizzare', 'Fields to track' => 'Campi da Tracciare', 'Fieldset' => 'Set di Campi', 'Fieldset title' => 'Nome dei Set di Campi', 'File' => 'File', 'File Downloads' => 'Download del File', 'File Storage' => 'File Storage', 'File Upload' => 'Carica File', 'File should contain CSV list of user records for import in the following format:
      %s' => 'File should contain CSV list of user records for import in the following format:
      %s', 'File-Upload: browse uploaded files' => 'Scorri i file caricati', 'Filename' => 'Nome File', 'Filename for Invoice %public_id% will be replaced with real public id of invoice, %receipt_id% will be replaced with payment receipt, also you can use the following placehoders %payment.date%, %user.name_f%, %user.name_l%' => 'Nome File Ricevuta segnaposto: %public_id% -> ID Pubblico, %receipt_id% ID Pagamento, puoi usare anche %payment.date%, %user.name_f%, %user.name_l%', 'Files' => 'File', 'Files keep empty to report all files' => 'File vuoto significa "tutti i file"', 'Files List' => 'lista dei File', 'Files located on Amazon S3 storage. (Warning: Your buckets should not contain letters in uppercase in its name)' => 'File su Amazon S3. (Attenzione: non usare lettere maiuscole nel nome dei tuoi bucket)', 'Files located on Selectel storage. ' => 'File nel Servizio selezionato. ', 'Files uploaded via aMember web interface' => 'Files caricati con l\'interfaccia di Amember', 'Files were uploaded! %sBack%s' => 'File caricati! %sIndietro%s', 'Filter' => 'Filtra', 'Filter Directory' => 'Filtra Cartelle', 'Filter Leads' => 'Filtra Lead', 'Filter Text' => 'Filtra Testo', 'Filter by Content or Link' => 'Filtra per Contenuto o Link', 'Filter by Username or Name or E-Mail Address#' => 'Filtra per Nome Utente o Email#', 'First & Last Name' => 'Nome e Cognome', 'First Name' => 'Nome di Battesimo', 'First Payment' => 'Primo Pagamento', 'First Time Purchase of Product' => 'Prima volta che il prodotto viene acquistato', 'First Time Purchase: %s' => 'Primo Acquisto: %s', 'Flat Amount' => 'Ammontare Fisso', 'Folder %s (%s)' => 'Cartella %s (%s)', 'Folders' => 'Cartelle', 'Footer this content will be included to footer' => 'Footer this content will be included to footer', 'Force I Agree' => 'Forza "Acconsento"', 'Force User to Choose Some Product from this Brick' => 'Forza l\'utente a Scegliere un Prodotto', 'Forgot password?' => 'Password dimenticata?', 'Form Bricks (drag to right to remove)' => 'Sezioni Form (trascina a destra per rimuovere)', 'Form Page Break' => 'Interruzione di Pagina nel Modulo', 'Free' => 'Gratis', 'Free Access' => 'Accesso Gratuito', 'Free Access without log-in' => 'Accesso Gratuito senza Login', 'Free Signup' => 'Iscrizione Gratuita', 'From' => 'Da', 'From Address' => 'Email da', 'Get Link' => 'Ottieni Link', 'Get Password' => 'Reimposta la Password', 'Get Payment Link' => 'Ottieni Link di Pagamento', 'Get affiliate coupons' => 'Ottieni Buoni Sconto Affiliato', 'GetClicky Site Id GetClicky Account -> Preferences -> Info' => 'GetClicky Site Id GetClicky Account -> Preferences -> Info', 'Gift Voucher' => 'Voucher Regalo', 'Gift Voucher Donee' => 'Voucher Regalo Donatore', 'Gift Voucher Grantor' => 'Voucher Regalo Concedente', 'Gift Voucher Period Of Validity After Creation' => 'Periodo validità del Voucher Regalo dopo la Creazione', 'Gift Vouchers' => 'Voucher Regalo', 'Global Commission' => 'Commissioni Globali', 'Global Limit of IP Addresses empty or 0 - without limit' => 'Global Limit of IP Addresses empty or 0 - without limit', 'Global Tax' => 'Tassa Globale', 'Go Back' => 'Torna Indietro', 'Goal' => 'Obiettivo', 'Grantor' => 'Concedente', 'Grantor\'s Invoice' => 'Ricevuta Concedente', 'Group By' => 'Raggruppa per', 'Groups' => 'Gruppi', 'Groups Limit' => 'Limite Gruppi', 'Groups Priority you may drag and drop groups to sort it. if there are several groups available for user aMember will choose groups that are higher in this list as "Primary"' => 'Priorità Gruppi puoi ordinare i Gruppi col drag&drop, se un utente ha diversi gruppi associati aMember considera primario quello che è più in alto in questa lista.', 'HTML Code that will be displayed' => 'Codice HTML che sarà visualizzato', 'HTML Message' => 'HTML', 'HTML text' => 'testo HTML', 'Has %s Affiliate Commission' => 'Ha %s Commissione Affiliato', 'Has Affiliate Commission' => 'Ha Commissione Affiliato', 'Has Not Used Payment System' => 'Non ha usato Sistema Pagamento', 'Has Used Payment System' => 'Ha usato Sistema Pagamento', 'Has invoice canceled between dates' => 'Ha una ricevuta cancellata tra le date', 'Has payment made between dates' => 'ha un pagamento tra le date', 'Has pending invoice with products' => 'Ha una ricevuta pendente per il prodotto', 'Has subscription between dates' => 'Si è iscritto tra le date', 'Has subscription on date' => 'Si è iscritto il', 'Has subscription that expire between dates' => 'Iscrizione che scade tra le date', 'Have uploaded at least 1 file' => 'Ha caricato almeno un file', 'Having Active Subscription To:' => 'Che hanno un Abbonamento Attivo a:', 'Having Expired Subscription To:' => 'Che hanno un Abbonamento Scaduto a:', 'Having active subscription to' => 'Ha iscrizione attiva a', 'Having expired subscription to' => 'Ha iscrizione scaduta a', 'Having no active subscription to' => 'Non ha iscrizione attiva a', 'Header this content will be included to header' => 'Header this content will be included to header', 'Header Logo keep it empty for default value' => 'Header Logo keep it empty for default value', 'Help Desk Url it must be with https and without slash on the end, for example https://example.zendesk.com' => 'Help Desk Url it must be with https and without slash on the end, for example https://example.zendesk.com', 'Helpdesk' => 'Helpdesk', 'Helpdesk: Can operate with helpdesk tickets' => 'Helpdesk: può operare con i ticket', 'Helpdesk: Categories' => 'Helpdesk: Categorie', 'Here you can assign user groups to products. To add new user groups %sclick here%s. ' => 'Qui puoi assegnare Gruppi Utenti ai prodotti. Per aggiungere un nuovo Gruppo Utente %sclicca qui%s. ', 'Hidden' => 'Nascosto', 'Hide do not display this item in members area' => 'Non Mostrare non visualizzare nell\'Area Riservata', 'Hide do not display this item link in members area' => 'Non Mostrare Link non visualizzare nell\'Area Riservata', 'Hide Brick Title' => 'Nascondi Titolo Sezione', 'Hide Invoice after XX days' => 'Nascondi la Ricevuta dipo XX giorni', 'Hide Label' => 'Nascondi Etichetta', 'Hide Payment Forms and History from SubUsers' => 'nascondi Form di Pagamento e Storici ai SubUser', 'Hide Select if there is only one choice' => 'Hide Select if there is only one choice', 'History' => 'Storico', 'Hosted at Activecampaing\'s server' => 'Usa il Server di Activecampaign', 'Hours' => 'Ore', 'Housenumber' => 'Civico', 'How to calculate limits? Pages Limit and Groups Limit' => 'How to calculate limits? Pages Limit and Groups Limit', 'I confirm I\'m based in %s' => 'Confermo che la mia sede fiscale è %s', 'I have read and agree to the Terms & Conditions' => 'Ho letto e accetto i Termini e Condizioni', 'ID used for placeholders in emails' => 'ID used for placeholders in emails', 'IF' => 'SE', 'IP Address' => 'Indirizzo IP', 'IP Addresses' => 'Indirizzi IP', 'If product is not available because of require/disallow settings' => 'Se il prodotto non è disponibile per le impostazioni abilita/disabilita', 'If you already have an account on our website, please %slog in%s to continue' => 'Se hai già un account sul nostro sito, fai %sil login per continuare%s', 'If you are a registered member, please %slogin%s' => 'Se sei un utente registrato, effettua %sil login%s', 'If you are not registered yet, please %ssignup%s' => 'Se non sei ancora registrato, %sregistrati adesso%s', 'Import from CSV' => 'Importa da CSV', 'In order to comply with EU VAT Rules we need you to confirm your billing country.' => 'Per adempiere alle norme EU per l\'iva, conferma manualmente la nazione.', 'Include Access Periods to PDF Invoice' => 'Includi Periodi di Accesso nel PDF', 'Include only users who have active subscritpions to these products' => 'Solo utenti con questi prodotti', 'Include to Directory' => 'Includi nella Cartella', 'Include to Directory matching users will be displayed in this members directory in case of empty all active users will be included' => 'Includi nella Directory matching users will be displayed in this members directory in case of empty all active users will be included', 'Income' => 'Incasso', 'Income Report - payments minus refunds' => 'Report Entrate: introiti meno i rimborsi', 'Incorrect Parent Affiliate ID' => 'ID Affiliato sponsor errato', 'Index Page Fields' => 'Campi della Pagina Iniziale', 'Initial Receipt# Number' => 'Numero Iniziale Ricevuta puoi impostarlo solo all\'inizio, poi se lo cambi non funziona più', 'Initial Receipt# Refund Number' => 'Numero Iniziale Rimborso puoi impostarlo solo all\'inizio, poi se lo cambi non funziona più', 'Input Type' => 'Tipo di Input', 'Insert comment into email' => 'Inserisci commento nell\'email', 'Insufficient credits' => 'Crediti insufficienti', 'Integer Value' => 'Valore Intero', 'Integer value required' => 'È richiesto un valore numerico senza virgola', 'Integration' => 'Integrazione', 'Integration key' => 'Chiave di integrazione', 'Integrations' => 'Integrazioni', 'Internal Error' => 'Errore Interno', 'Invalid Account Number' => 'Numero Conto non valido', 'Invalid Bank Account Number' => 'Conto bancario non valido', 'Invalid Bank Identifier Code' => 'Codice Identificativo banca non valido', 'Invalid Credit Card Number' => 'Numero Carta di Credito non valido!', 'Invalid Debit Card Number' => 'Numero Carta di Debito non valido', 'Invalid EU VAT Id format' => 'Formato EU VAT non corretto (ricordati del prefisso, IT per l\'Italia)', 'Invalid Emails' => 'Email non valide', 'Invalid Expiration Date - Month' => 'Data di Scadenza non valida - Mese', 'Invalid Expiration Date - Year' => 'Data di Scadenza non valida - Anno', 'Invalid Issue Number' => 'Numero di Emissione non Valido', 'Invalid Routing Number' => 'Numero di routing non valido', 'Invalid VAT Id, please try again' => 'VAT ID non valida, prova di nuovo', 'Invite' => 'Invita', 'Invite Code' => 'Codice Invito', 'Invite Email Message' => 'Messaggio Email di Invito', 'Invite a Friend' => 'Invita un Amico', 'Invited Users' => 'Utenti Invitati', 'Invoice' => 'Ricevute', 'Invoice Approved' => 'Ricevuta Approvata', 'Invoice Contact information included at top, use <br> for new line' => 'Informazioni Contatto Ricevuta visualizzati in alto, usa
      per accapo', 'Invoice First Total' => 'SubTotale Ricevuta', 'Invoice Footer Note This text will be included at bottom to PDF Invoice. You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.' => 'Nota Piè di Pagina Ricevuta puoi usare tutti i segnaposto come %user.login%, %user.name_f%, %user.name_l% ecc...', 'Invoice Internal ID#' => 'ID Interno Ricevuta', 'Invoice Number: ' => 'Numero Ricevuta: ', 'Invoice Public ID#' => 'ID Pubblico Ricevuta', 'Invoice Second Total' => 'Totale Ricevuta', 'Invoice Summary' => 'Riepilogo Ricevuta', 'Invoice Text' => 'Testo Ricevuta', 'Invoice is expired' => 'Ricevuta scaduta', 'Invoice not found' => 'Ricevuta non Trovata!', 'Invoice numbering' => 'Numerazione Ricevute', 'Invoices/Access' => 'Ricevute/Accessi', 'Is Affiliate? customer / affiliate status' => 'Is Affiliate? customer / affiliate status', 'Is Donation Required?' => 'Donazione obbligatoria?', 'Is Gift Voucher?' => 'È un Voucher Regalo?', 'Is Html?' => 'È Html?', 'Is Locked' => 'È Bloccato', 'Is Paid?' => 'È Pagato?', 'Is Send At Later Date?' => 'È spedisci un altro giorno?', 'Is Send Email to Grantor?' => 'È spedisci email al Concedente?', 'Is a Subuser:' => 'È un SubUser:', 'Is Disabled?' => 'È Disabilitato?', 'It is last message that will be shown to user before account removal, you can place some special offer here.' => 'questo è l\'ultimo messaggio che vede l\'utente prima di cancellarsi, puoi mettere una offerta speciale qui.', 'It looks like you are not at home right now.' => 'risulta che in questo momento non sei nel territorio nazionale indicato.', 'Item' => 'Elemento', 'JSON Web Token' => 'Web Token JSON', 'JavaScript Code it will be injected on signup form' => 'JavaScript Code it will be injected on signup form', 'Joint Venture Agreement' => 'Accordo di Joint Venture', 'JunglePay payment' => 'Pagamento JunglePay', 'Keep empty to use default value from field settings' => 'Lascia vuoto per lasciare il valore di default', 'Keyword' => 'Parola Chiave', 'Keywords' => 'Tue Keyword', 'Label' => 'Etichetta', 'Language' => 'Lingua', 'Language Display this brick only for the following languages. Keep it empty to display for any language.' => 'Language Display this brick only for the following languages. Keep it empty to display for any language.', 'Last 14 Days' => 'Ultimi 14 Giorni', 'Last 30 Days' => 'Ultimi 30 Giorni', 'Last 6 Months' => 'Ultimi 6 Mesi', 'Last 7 Days' => 'Ultimi 7 Giorni', 'Last 90 Days' => 'Ultimi 90 Giorni', 'Last Business Week (Mon-Fri)' => 'Ultimo Giorno Lavorativo (Lun-Ven)', 'Last File Upload' => 'Ultimo file caricato', 'Last Messages in Helpdesk' => 'Ultimo Messaggio all\'Helpdesk', 'Last Month' => 'Ultimo Mese', 'Last Name' => 'Cognome', 'Last Quarter' => 'Trimestre Scorso', 'Last Signin' => 'Ultima Iscrizione', 'Last Used Login' => 'Ultimo Login', 'Last Week (Mon-Sun)' => 'Ultima Settimana (Lun-Ven)', 'Last Week (Sun-Sat)' => 'Ultima Settimana (Dom-Sab)', 'Last Year' => 'Anno Scorso', 'Leads' => 'Lead', 'Legal Address Please enter the legal address of your organisation which will be included in the Direct Debit Guarantee statement' => 'Legal Address Please enter the legal address of your organisation which will be included in the Direct Debit Guarantee statement', 'Legal Name Please enter the legal name of your organisation which will be included in the Direct Debit Guarantee statement' => 'Legal Name Please enter the legal name of your organisation which will be included in the Direct Debit Guarantee statement', 'License Key' => 'Chiave di Licenza', 'Licenses' => 'Licenze', 'Licensing Schemes' => 'Schemi Licenze', 'Lifetime' => 'Per sempre', 'Like Button Action' => 'Azione Pulsante Mi Piace', 'Like Button Layout' => 'Layout Pulsante Mi Piace', 'Like Url' => 'URL Mi Piace', 'Limit' => 'Limite', 'Limit Access to Invite Feature leave it empty if there is not any restrictions' => 'Limit Access to Invite Feature leave it empty if there is not any restrictions', 'Limit Number of Display per User keep it empty for unlimited' => 'Limit Number of Display per User keep it empty for unlimited', 'Limit of IP Addresses' => 'Limite Indirizzi IP', 'Limit of Simultaneous Active Sessions' => 'Limite di Sessioni Attive Simultanee', 'Link' => 'Link', 'Link PayPal Account' => 'Connetti Account PayPal', 'Link Type' => 'Tipo di Link', 'Link is either expired or invalid' => 'Il Link è scaduto o non valido', 'Linked PayPal Account' => 'Account PayPal Collegato', 'Links' => 'Link', 'List Page Template alternative template for list page' => 'List Page Template alternative template for list page', 'Lists All List will be displayed if none selected' => 'Liste se non selezioni niente verranno visualizzate tutte', 'Live Edit %s' => 'Modifica Live %s', 'Loading' => 'Sto caricando', 'Location validation failed.' => 'Validazione Nazionalità Fallita!', 'Locked Group Whenever user is locked in aMember, plugin adds user to this group in %s Select any group with limited access which doesn\'t allow to login into %s Some scripts have special group for this situations: \'Unregistered\' or \'Guest\'' => 'Gruppi Bloccati Quando un utente viene bloccato aMember lo assegna a questi gruppi, in %s. Seleziona un gruppo con accesso limitato che non permetta il login a %s, come ad esempio \'Utente ospite\' ecc...', 'Log In' => 'Entra', 'Log Requests' => 'Richieste di Log', 'Log all API Requests' => 'Metti nel Log tutte le richieste API', 'Login' => 'Entra', 'Login Button Size' => 'Dimensione Pulsante Login', 'Login Indicator' => 'Indicatore Login', 'Login Monitor' => 'Monitor Login', 'Login Reminder' => 'Ricorda Login', 'Login Reminder to User' => 'Ricorda Login all\'utente', 'Login as User' => 'Accedi come questo Cliente', 'Logout' => 'Esci', 'Lost Password Sending Error' => 'Errore nell\'invio del messaggio di password persa', 'Lost Password Sent' => 'Messaggio di Recupero Password inviato correttamente', 'Lost password?' => 'Hai perso o dimenticato la Password?', 'Low Stock Notification' => 'Notifica Scorta Bassa', 'Low Stock Notification to Admin' => 'Notifica Scorta Bassa ad Admin', 'Low Stock Threshold' => 'Livello Scorta Bassa', 'MILESTONE PLUGIN: Goal \'%s\' completed!' => 'PLUGIN MILESTONE: Goal \'%s\' completato!', 'Mail Payment Admin' => 'Email Pagamento Admin', 'Mail Queue' => 'Coda Email', 'Make Payment' => 'Procedi al Pagamento', 'Make a Donation' => 'Fai una Donazione', 'Make donation recurring' => 'Fai una Donazione Ricorrente', 'Make the first letters of first and last name Uppercase' => 'Rendi maiuscole le prime lettere di Nome e Cognome', 'Make this Brick Required Only in Case There is not any Required Brick on Page Above It' => 'Rendi questa sezione obbligatoria solo se non c\'è nessuna sezione abbligatoria sopra questa', 'Make user who invite Affiliate' => 'Rendi utente chi invita l\'Affiliato', 'Manage Newsletters' => 'Gestisci Newsletter', 'Manually Approve' => 'Sezione Approvazione Manuale', 'Manually Approve Admin' => 'Approva Manualmente Admin', 'Manually Approve Invoice' => 'Approva Manualmente Ricevuta', 'Manually Approve Invoice Admin' => 'Approva Manualmente Ricevuta Admin', 'Marketing Materials' => 'Materiali di Marketing', 'MaxMind Credit Card Fraud Detection' => 'Sistema Anti Frode MaxMind', 'MaxMind License' => 'Licenza MaxMind', 'MaxMind User ID' => 'Nome Utente MaxMind', 'Maximum amount of donation' => 'Ammontare Massimo Donazione', 'Maxmind License Key %sObtain a Free or Premium license key%s' => 'Maxmind License Key %sObtain a Free or Premium license key%s', 'Member Record' => 'Risultato Utente', 'Members Directory' => 'Directory Utenti', 'Members Directory [%s] does not exists' => 'Directory Utente [%s] non esiste', 'Membership Type' => 'Tipo di Prodotto/Iscrizione', 'Merchant Key' => 'Chiave Rivenditore', 'Merchant Secret' => 'Segreto Rivenditore', 'Message' => 'Messaggio', 'Message It is last message that will be shown to user before account removal, you can place some special offer here.' => 'Message It is last message that will be shown to user before account removal, you can place some special offer here.', 'Message This message will be shown on accept page. You can clarify situation for user here and provide link to new Agreement text. Placeholder %button% will be replaced with actual button.' => 'Message This message will be shown on accept page. You can clarify situation for user here and provide link to new Agreement text. Placeholder %button% will be replaced with actual button.', 'Message on cancel feedback page for customer' => 'Message on cancel feedback page for customer', 'Message Text' => 'Messaggio Testo', 'Message can not be empty' => 'Il corpo del messaggio non può essere vuoto', 'Message has been sent successfully' => 'Messaggio spedito correttamente', 'Message template when goal is completed' => 'Template Messagggio quanto il goal è completato', 'Message template when goal is not reached' => 'Template Messagggio quanto il goal è raggiunto', 'Milestones' => 'Milestone', 'Minimum Number of Items in invoice to apply discount' => 'Numero Minimo di Prodotti in Ricevuta per applicare lo sconto', 'Minimum amount of donation keep it empty if there is not any limit' => 'Minimum amount of donation keep it empty if there is not any limit', 'Month' => 'Mese', 'Month (30 days)' => 'Mese (30 giorni)', 'Months' => 'Mesi', 'Multiplier' => 'Moltiplicatore', 'My Country' => 'La mia Nazione', 'My Tickets' => 'Miei Ticket', 'NEVER' => 'MAI', 'Name' => 'Nome', 'Name of Account Holder first and last name' => 'Name of Account Holder first and last name', 'Name of Friend' => 'Nome Amico', 'Never' => 'Mai', 'Never subscribed to' => 'Mai iscritto a', 'New' => 'Nuovo', 'New %s' => 'Nuovo/a %s', 'New Email' => 'Nuova Email', 'New Password' => 'Nuova Password', 'New Value' => 'Nuovo Valore', 'Newsletter' => 'Newsletter', 'Newsletter Subscriptions' => 'Iscrizioni Newsletter', 'Newsletters' => 'Newsletter', 'Next' => 'clicca qui e continua...', 'Next Rebill' => 'Prossimo Addebito', 'No' => 'No', 'No Category' => 'Nessuna Categoria', 'No commissions on this date' => 'Nessuna Commissione in questa data', 'No coupons found with such coupon code' => 'Non esistono Buoni Sconto con questo Codice', 'No files uploaded' => 'Nessun file caricato', 'No gift vouchers found with such code' => 'Nessun Vouchers Regalo con questo codice', 'No items in this section' => 'Niente in questa sezione', 'No items selected for purchase' => 'Nessun Articolo Selezionato per l\'acquisto', 'No licenses assigned yet' => 'Nessuna Licenza assegnata', 'No payouts have been made to your account yet' => 'Non ci sono ancora Payout Affiliato per questo account', 'No records found' => 'Non ci sono ancora dati da mostrare', 'No records in this member directory yet' => 'Nessun Risultato ancora in questa directory utenti', 'No result found' => 'Nessun Risultato', 'No, cancel' => 'No, annulla', 'No, is not a subuser' => 'No, non è SubUser', 'No, keep me subscribed' => 'No, mantieni l\'iscrizione', 'No, please keep me subscribed' => 'No, mantieni l\'iscrizione', 'Nochex Merchant ID Your default merchant id is the email address you use with your Nochex account' => 'Nochex Merchant ID Your default merchant id is the email address you use with your Nochex account', 'Normal' => 'Normale', 'Not Affiliate' => 'Non Affiliato', 'Not Approved Affiliates' => 'Affiliati non Approvati', 'Not Paid' => 'Non Pagato', 'Not Recurring' => 'Non Ricorrente', 'Not Selected' => 'Seleziona Qui', 'Not Send' => 'Non Spedito', 'Not Used' => 'Non Usato', 'Not assigned to usergroup' => 'Non assegnato al Gruppo Utenti', 'Not enough credits to debit' => 'Crediti insufficienti per il debito', 'Not registered yet?' => 'Non sei ancora registrato?', 'Notes' => 'Note', 'Nothing, allow simultaneous login for same user from different computers' => 'Niente, permetti login simultanei agli utenti', 'Notification' => 'Notifica', 'Notifications' => 'Notifiche', 'Notify Admin about new user with risk score more then define threshold' => 'Notifica Rischio Admin se c\'è un nuovo utente con Punteggio di Rischio superiore al limite', 'Notify Admin once user removed himself' => 'Notifica Admin se utente si cancella sa solo da aMember', 'Notify Admin after User Log in to His Account' => 'Notifica Admin quando l\'utente accede', 'Notify Admin on Simultaneous Login' => 'Notifica Admin per Login Simultanei', 'Notify User about new file upload' => 'Notifica Utente Nuovo Upload', 'Notify User on Simultaneous Login' => 'Notifica Utente per Login Simultaneo', 'Notify admin about new upload' => 'Notifica Admin di un nuovo upload', 'NuevoMailer installation URL' => 'URL Intallazione NuevoMailer', 'Number Identification Enable %sTelephone Number Identification (TNI)%s service' => 'Number Identification Enable %sTelephone Number Identification (TNI)%s service', 'Number of Active Users by Date' => 'Numero di Utenti Attivi per Data', 'Number of Affiliates' => 'Numero di Affiliati', 'Number of Messages to display' => 'Numero di Messaggi da Visualizzare', 'Number of Users who Purchase product B after Product A' => 'Numero di Utenti che acquistano il prodotto B dopo il prodotto A', 'Number of cancel on each billing cycle' => 'Numero Cancellazioni per ogni rinnovo', 'Number of users who becomes inactive in given period' => 'Numero Utenti che si Cancellano', 'Numeric Value' => 'Valore Numerico', 'Numeric value required' => 'È richiesto un valore numerico', 'OK. Press \'Continue...\' to refresh Database name autocompletion database' => 'OK. Premi \'Continua...\' per aggiornare il Database', 'Offer Page Settings' => 'Impostazioni Pagina Offerta', 'Offline Check' => 'Bonifico Bancario', 'Offline Payment' => 'Pagamento Offline', 'Offline bank account info' => 'Informazioni Banca', 'Old Value' => 'Valore Precedente', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'Quando hai terminato la configurazione di questo plugin, non dimenticare di aggiungere un nuovo elemento in %sProteggi Contenuti -> Integrazioni%s', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Newsletters%s page' => 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Newsletters%s page', 'Online backup is disabled if you have CC payment plugins enabled. Use offline backup instead' => 'Backup Online disabilitato se hai plugin CC abilitati. In questo caso usa Backup Offline', 'Only Affiliate %s(rarely used)%s' => 'Solo Affiliati %s(usato raramente)%s', 'Only Affiliate, not a member' => 'Solo Affiliato, non Utente', 'Only Billing Plans selected below' => 'Solo Piani di Pagamento selezionati sotto', 'Only Products selected below' => 'Solo Prodotti selezionati sotto', 'Open Link in New Window' => 'Apri Link in Nuova Finestra', 'Optimize Mail Log' => 'Ottimizza Mail Log', 'Order reference: %s' => 'Riferimento Ordine: %s', 'Order with credits' => 'Ordina con i Crediti', 'Other' => 'Altri', 'Our system will try to charge your card again on %s' => 'Il nostro sistema tenterà un nuovo addevito il %s', 'Out of Stock Notification' => 'Notifica di Esaurimento Merce', 'Out of Stock Notification to Admin' => 'Notifica di Esaurimento Merce ad Admin', 'Owner' => 'Proprietario', 'PDF Invoice Unpaid' => 'Ricevuta PDF non pagata', 'Page Title' => 'Nome Pagina', 'Pages' => 'Pagine', 'Pages Limit' => 'Limite Pagine', 'Paid (Included to Payout)' => 'Pagato (Incluso nel Payout)', 'Paper Format' => 'Formato Carta', 'Parent User' => 'Utente Genitore', 'Parent User Info' => 'Info Utente Genitore', 'Partner Share for First Payment calculated for first payment in each invoice' => 'Partner Share for First Payment calculated for first payment in each invoice', 'Partner Share for Rebills' => 'Quota Partner per Rinnovi', 'Password' => 'Password', 'Password Change E-Mail' => 'Emai Cambio Password', 'Password Salt' => 'Salatura Password', 'Password and Password Confirmation are different. Please reenter both' => 'Password e Conferma Password sono diversi. Reiseriscile entrambe!', 'Password must contain at least %d letters or digits' => 'La Password deve contenere almeno %d caratteri', 'Password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars' => 'La Password deve contenere almeno 2 lettere miuscole, 2 numeri e 2 caratteri speciali', 'Passwords do not match' => 'Le Password non corrispondono', 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this product to do it' => 'Percorso verrà utilizzato per costruire una URL semplice, se lasci vuoto aMember userà il codice ID del prodotto', 'Path should be unique across all products' => 'Il percorso deve essere unico tra tutti i prodotti', 'Path to %s' => 'Percorso a %s', 'Path to %s Folder' => 'Percorso alla cartella %s', 'Path to Source Folder' => 'Percorso Cartella Sorgente', 'Path to Target Folder' => 'Percorso Cartella Obiettivo', 'Pay' => 'Procedi al Pagamento', 'Pay with Card' => 'Paga con la Carta', 'Pay with your Credit Card' => 'Paga con Carta di Credito', 'PayForIt payment' => 'Pagamento PayForIt', 'Payanyway plugin does not support recurring billing!' => 'Il Plugin Payanyway not supporta il pagamento ricorrente!', 'Payment' => 'Pagamenti', 'Payment Amount' => 'Ammontare Pagamento', 'Payment Canceled' => 'Pagamento Cancellato', 'Payment Confirmation' => 'Conferma Pagamento', 'Payment Currency' => 'Valuta Pagamento', 'Payment E-mail' => 'Email Pagamento', 'Payment Error' => 'Errore nel Pagamento', 'Payment Failed' => 'Il Pagamento non è andato a buon fine', 'Payment History' => 'Storico Pagamenti', 'Payment Info' => 'Info Pagamento', 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when he chooses to pay using this payment system you can use the following tags: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total' => 'Istruzioni Pagamento per il Cliente puoi mettere qualsiasi HTML, verrà mostrto al cliente quando sceglie di pagare con questo metodo. Puoi utilizzare i seguenti segnaposto: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total', 'Payment Instructions for customer you can enter any HTML here, it will be displayed to customer when they set up a direct debit using this payment system you can use the following tags: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total' => 'Istruzioni Pagamento per il Cliente puoi mettere qualsiasi HTML, verrà mostrto al cliente quando sceglie di pagare con questo metodo. Puoi utilizzare i seguenti segnaposto: %s - Receipt HTML %s - Invoice Title %s - Invoice Id %s - Invoice Total', 'Payment Link' => 'Link Pagamento', 'Payment Link to Complete Pending Invoice' => 'Link Pagamento per completare ricevuta in attesa', 'Payment Options if none selected, all enabled will be displayed' => 'Payment Options if none selected, all enabled will be displayed', 'Payment Receipt Id' => 'Ricevuta Pagamento', 'Payment Routing Number' => 'Numero Pagamento', 'Payment System' => 'Metodo Pagamento', 'Payment System Description' => 'Descrizione Metodo Pagamento', 'Payment System Domain Leave default value if you are not sure' => 'Payment System Domain Leave default value if you are not sure', 'Payment System Title' => 'Nome Metodo Pagamento', 'Payment Type' => 'Tipo Pagamento', 'Payment error: ' => 'Errore nel Pagamento:', 'Payment failed' => 'Pagamento non Riuscito', 'Payment info' => 'Info Pagamento', 'Payment is already processed, please go to %sMembership page%s' => 'Il Pagamento è già stato processato, vai alla %sArea Riservata%s', 'Payments' => 'Pagamenti', 'Payments Amount' => 'Ammontare Pagamento', 'Payments History' => 'Storico Pagamenti', 'Payments by New vs Existing members' => 'Pagamenti dei Nuovi Membri vs. Clienti', 'Payments by payment system breakdown' => 'Pagamenti in base al Metodo di Pagamento ', 'Payments by product categories breakdown' => 'Pagamenti in base alle Categorie Prodotti', 'Payments by products breakdown' => 'Pagamenti in base al Prodotto', 'Payments from existing customers' => 'Pagamenti dai Già Clienti', 'Payments from new customers' => 'Pagamenti dai Nuovi Clienti', 'Payments total' => 'Pagamenti Totali', 'Payments vs Refunds' => 'Pagamenti vs Rimborsi', 'Payments/Access' => 'Pagamenti/Accessi', 'Payout' => 'Impostazioni Payout', 'Payout Date' => 'Data Payout', 'Payout Method' => 'Metodo Pagamento', 'Payout Method Title' => 'Nome Metodo Payout', 'Payouts' => 'Tuoi Payout', 'Paypal interface language en_US - english, de_DE - german, default is german' => 'Paypal interface language en_US - english, de_DE - german, default is german', 'Paysystem (optional)' => 'Sistema Pagamento (opzionale)', 'Paysystem IN (%s)' => 'Sistema Pagamento IN (%s)', 'Pending' => 'In Attesa', 'Pending Invoice Notifications to Admin' => 'Notifica Admin per Ricevuta in Attesa', 'Pending Invoice Notifications to User' => 'Notifica Utente per Ricevuta in Attesa', 'Pending Invoices' => 'Ricevute in Attesa di Pagamento', 'Pending Invoices Block' => 'Sezione Ricevute in Attesa', 'Pending List User will be added to this list immediately after signup' => 'Pending List User will be added to this list immediately after signup', 'Pending subusers' => 'SubUser in Attesa', 'Percentage of users who convert from free to paid within given amount of days' => 'Percentuale di Utenti che si convertono da Gratis a Paganti in un dato numero di giorni', 'Period' => 'Periodo', 'Period must be in interval 1-24 months' => 'Il Periodo di Validità deve rientrare in un intervallo di 1 - 24 mesi', 'Period must be in interval 1-5 years' => 'Il Periodo di Validità deve rientrare in un intervallo di 1 - 5 anni', 'Period must be in interval 1-90 days' => 'Il Periodo di Validità deve rientrare in un intervallo di 1 - 90 giorni', 'Personal Content' => 'Contenuto Personale', 'Personal Content These files will be available for downloads only for this user on his dashboard' => 'Contenuto Personale Questi file saranno disponibili per il download solo a questo utente nel suo account personale', 'Personal Content: Upload File' => 'Contenuto Personale: Carica File', 'Personal Folder' => 'Cartella Personale', 'Phone' => 'Telefono', 'Phone Number' => 'Numero di Telefono', 'Plain-Text Message' => 'TESTO', 'Plain-Text Password' => 'Password testuale', 'Please %sdefine payout method%s to get commission in our affiliate program.' => 'Per ricevere i pagamenti da Affiliato %simposta il metodo di pagamento%s, puoi scegliere PayPal o Bonifico Bancario.', 'Please %senable at least one payout method%s since you use affiliate module' => 'Per favore %sabilita almento un metodo di pagamento%s dato che stai usando il modulo affiliato', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Per favore %sentra%s nella tua Area Riservata%s. Se non hai ancora completato il pagamento potrai farlo dopo aver effettuato l\'accesso cliccando su "Acquista/Rinnova"', 'Please Enter URL of Your Landing Page' => 'Inserisci URL della Landing Page', 'Please Select' => 'Seleziona', 'Please agree to Affiliate Agreement' => 'Per favore acconsenti all\'Accordo Affiliati', 'Please agree to User Agreement' => 'Accetta le Condizioni d\'uso', 'Please answer above question' => 'Per favore rispondi alla domanda qui sopra', 'Please choose' => 'Seleziona', 'Please choose a Bank Account Type' => 'Per favore scegli un tipi di conto bancario', 'Please choose a Credit Card Type' => 'Scegli il tipo di Carta di Credito', 'Please choose a membership type' => 'Seleziona un tipo di Prodotto/Servizio', 'Please choose a payment system' => 'Seleziona un Metodo di Pagamento', 'Please choose state' => 'Scegli la Provincia', 'Please confirm your billing address manually' => 'Per favore conferma il tuo indirizzo manualmente', 'Please contact webmaster' => 'Per favore contatta il Webmaster', 'Please enter %s' => 'Seleziona %s', 'Please enter Account Number' => 'Per favore inserisci il numero di conto', 'Please enter Bank Account Name' => 'Per favore inserisci il nome della banca', 'Please enter Bank Identifier Code' => 'Per favore inserisci il codice identificativo della banca', 'Please enter Bank Name' => 'Per favore inserisci il nome della banca', 'Please enter Branch Sort Code' => 'Per favore inserisci Branch Sort Code', 'Please enter City' => 'Inserisci il Comune', 'Please enter Country' => 'Inserisci la tua Nazione', 'Please enter Credit Card Code' => 'Inserisci il Codice della Carta di Credito', 'Please enter Credit Card Number' => 'Inserisci il numero della Carta di Credito', 'Please enter Credit Card expiration date' => 'Per favore inserisci data di scadenza della carta di credito', 'Please enter Debit Card Number' => 'Per favore inserisci il numero della carta di debito', 'Please enter EU VAT Id' => 'Inserisci la EU VAT (ricordati del prefisso, IT per l\'Italia)', 'Please enter Password' => 'Inserisci la Password', 'Please enter Routing Number' => 'Per favore inserisci il Routing Number', 'Please enter State' => 'Inserisci la Provincia', 'Please enter Street Address' => 'Inserisci la Via', 'Please enter ZIP code' => 'Inserisci il Codice di Avviamento Postale', 'Please enter a valid e-mail address' => 'Inserisci un Indirizzo Email Valido', 'Please enter billing name' => 'Per favore inserisci il nome per il pagamento', 'Please enter cardholder name exactly as on card' => 'Inserisci il nome esattamente come compare sulla tua carta', 'Please enter correct amount' => 'Per favore inserisci l\'ammontare corretto', 'Please enter coupon code' => 'Buono Sconto se ce l\'hai inseriscilo qui', 'Please enter credit card holder first and last name' => 'Per favore inserisci nome e cognome del proprietario della carta di credito', 'Please enter credit card holder first name' => 'Inserisci il Nome dell\'intestatario della Carta di Credito', 'Please enter credit card holder last name' => 'Inserisci il Cognome dell\'intestatario della Carta di Credito', 'Please enter credit card holder name' => 'Inserisci il Nome dell\'intestatario della Carta di Credito', 'Please enter debit card holder first name' => 'Per favore inserisci il nome del proprietario della carta di debito', 'Please enter debit card holder last name' => 'Per favore inserisci il cognome del proprietario della carta di debito', 'Please enter debit card holder name' => 'Per favore inserisci il nome del proprietario della carta di debito', 'Please enter first name' => 'Per favore inserisci il nome', 'Please enter gift voucher code' => 'Per favore inserisci il codice del Voucher Regalo', 'Please enter housenumber' => 'Inserisci il Numero Civico', 'Please enter last name' => 'Per favore inserisci il cognome', 'Please enter name' => 'Per favore inserisci il nome', 'Please enter phone number' => 'Inserisci un Numero di Telefono', 'Please enter valid Email' => 'Inserisci un Indirizzo Email Valido', 'Please enter valid HTTPS url with "/api" at the end' => 'Per favore un URL HTTPS valido con "/api" alla fine', 'Please enter valid Username. It must contain at least %d characters' => 'Inserisci un Nome Utente Valido. Deve contenere almeno %d caratteri', 'Please enter your First Name' => 'Inserisci il tuo Nome', 'Please enter your Last Name' => 'Inserisci il tuo Cognome', 'Please enter your current password for validation' => 'Inserisci la tua password attuale per convalida', 'Please enter your last name' => 'Per favore inserisci il tuo cognome', 'Please enter your name' => 'Per favore inserisci il tuo nome', 'Please keep me subscribed' => 'Per favore lasciami iscritto', 'Please login' => 'Entra nell\'Area Riservata', 'Please note: it is impossible to restore your current account after deleting but you still can signup again as new user.' => 'Please note: it is impossible to restore your current account after deleting but you still can signup again as new user.', 'Please save your settings before use preview link' => 'Salva Impostazioni prima di usare il link anteprima', 'Please select' => 'Seleziona', 'Please select an item...' => 'Seleziona un elemento...', 'Please select card type' => 'Seleziona il tipo di carta', 'Please select payment system for payment' => 'Seleziona un Metodo di Pagamento per acquistare', 'Please select the biller and click button to continue' => 'Seleziona il creditore e clicca il pulsante per continuare', 'Please specify donation amount' => 'Per favore specifica l\'ammontare della donazione', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Usa il modulo che trovi in %sAcquista/Rinnova%s per sottoscrivere o rinnovare gli abbonamenti.', 'Please wait %d seconds before next attempt' => 'Per favore attendi %d secondi prima del prossimo tentativo', 'Please wait %d seconds before next login attempt' => 'Devi aspettare %d secondi prima di riprovare a loggarti', 'Please wait while we process your order...' => 'Per favore attendi mentre processiamo il tuo ordine...', 'Plugin' => 'Plugin', 'Plugin List Id' => 'Lista ID Plugin', 'Plugin List Id value required' => 'Plugin List Id value required', 'Plugin [%s] is not configured yet. Please %scomplete configuration%s' => 'Il Plugin [%s] non è ancora configurato. Per favore %scompleta la configurazione%s', 'Position for HTML' => 'Posizione dell\'HTML', 'Postal Index' => 'Casella Postale', 'Prev' => 'Precedente', 'Preview' => 'Anteprima', 'Previous Period' => 'Periodo Precedente', 'Previous Year' => 'Anno Precedente', 'Price' => 'Prezzo', 'Priority' => 'Priorità', 'Priority of discount First match discount with higher priority will be applied' => 'Priority of discount First match discount with higher priority will be applied', 'Proceed to Checkout' => 'Procedi al Pagamento', 'Process %s' => 'Sto elaborando %s', 'Process Payment Day' => 'Giorno per Elaborare Pagamento ', 'Processing' => 'Sto elaborando', 'Processing your Invoice' => 'Sto elaborando la Ricevuta', 'Processing your Transaction' => 'Sto processando la tua Transazione', 'Processing your product upgrade' => 'Sto elaborando il tuo upgrade', 'Product' => 'Prodotto', 'Product user should have active access to one of following products in order to personal folder was created' => 'Product user should have active access to one of following products in order to personal folder was created', 'Product %s is incompatible with product %s. Reason: %s' => 'Prodotto %s incompatibile con prodotto %s. Ragione: %s', 'Product A' => 'Prodotto A', 'Product B' => 'Prodotto B', 'Product Categories' => 'Categorie i Prodotti', 'Product Category IN (%s)' => 'Categoria Prodotto IN (%s)', 'Product Category NOT IN (%s)' => 'Categoria Prodotto NON IN (%s)', 'Product Chaining Rules' => 'Regole Concatenamento Prodotti', 'Product Convertion' => 'Conversione Prodotti', 'Product Description displayed on the shopping cart page' => 'Product Description displayed on the shopping cart page', 'Product Gategories' => 'Categorie Prodotti', 'Product ID' => 'ID Prodotto', 'Product ID at paddle.com' => 'ID prodotto su paddle.com', 'Product Picture for shopping cart pages. Only jpg, png and gif formats allowed' => 'Product Picture for shopping cart pages. Only jpg, png and gif formats allowed', 'Product Title' => 'Nome del Prodotto', 'Product Title of the Latest Purchased Product' => 'Nome Prodotto dell\'ultimo acquisto', 'Product Welcome E-mail' => 'Email Benvenuto Prodotto', 'Product categories keep empty to report all categories' => 'Categorie Prodotti vuoto significa "tutte le categorie"', 'Product(s)' => 'Prodotto', 'Product(s) Title' => 'Nome Prodotto', 'Product(s) to display' => 'Prodotti da Visualizzare', 'Products' => 'Prodotti', 'Products keep empty to report all products' => 'Prodotti vuoto significa "tutti i prodotti"', 'Products leave it empty to include all products' => 'Products leave it empty to include all products', 'Products IN (%s)' => 'Prodotti IN (%s)', 'Products NOT IN (%s)' => 'Prodotti NON IN (%s)', 'Products from selected Categories' => 'Prodotti da Categorie selezionate', 'Products in this Brick is Optional (Not Required)' => 'Prodotto opzionale in questa sezione (Non Obbligatorio)', 'Products not found. Click %shere%s to continue shopping.' => 'Prodotto non trovato. Clicca %squi%sper continuare acquisti.', 'Profile' => 'Modifica Profilo', 'Profile Changed' => 'Profilo Modificato', 'Profile update transaction failed' => 'Aggiornamento Profilo Fallito!', 'Protected Content [%s-%d]' => 'Contenuto Protetto [%s-%d]', 'Public Key Please include -----BEGIN PUBLIC KEY-----' => 'Public Key Please include -----BEGIN PUBLIC KEY-----', 'Publish' => 'Pubblica', 'Publish Date set it if you want to grant lifetime acces to this item for users with active subscription on this date' => 'Publish Date set it if you want to grant lifetime acces to this item for users with active subscription on this date', 'Purchased Credits' => 'Crediti Acquistati', 'Qty' => 'Q.tà', 'Quantity' => 'Visualizza per', 'Quarter' => 'Trimestre', 'Quarter (90 days)' => 'Trimestre (90 giorni)', 'Questions with possible answers one question per line question and answers should be separated by pipe, for example Question1?|Answer1|Answer2|Answer3 Question2?|Answer1|Answer2 register of answers does not matter' => 'Questions with possible answers one question per line question and answers should be separated by pipe, for example Question1?|Answer1|Answer2|Answer3 Question2?|Answer1|Answer2 register of answers does not matter', 'Queue' => 'Coda', 'Quick Filter' => 'Filtro Veloce', 'Quick Order' => 'Ordine Rapido', 'Quickpay parameters' => 'Parametri Quickpay', 'Radio-buttons (one product can be selected)' => 'Radio-button (può essere selezionato un solo prodotto)', 'Random Questions' => 'Domande Casuali', 'Re-Open Ticket' => 'Riapri il Ticket', 'Read-only' => 'Sola Lettura', 'Real Path' => 'Percorso Reale', 'Reason' => 'Ragione', 'Rebuild' => 'Ricostruisci', 'Rebuild Completed!' => 'Ricostruzione Completata!', 'Rebuild Invoice Database' => 'Ricostruisci Database Ricevute', 'Rebuild Invoices. Please wait...' => 'Ricostruisco Ricevute. Per favore attendi...', 'Rebuild completed. %sReturn%s' => 'Ricostruzione Completata. %sTorna Indietro%s', 'Rebuild...' => 'Ricostruisco...', 'Receipt# Number Prefix If you change prefix numbers will start over from 1 You can use %year% shortcode in invoice number. It will be replaced to actual year For example: INV-%year%-' => 'Prefisso Numero Ricevuta Se cambi il prefisso la numerazione partirà di nuovo da 1 Puoi usare il segnaposto %year% che verrà cambiato con l\'anno corrente (esempio: RIC-%year%-) così la numerazione si resetta ogni anno.', 'Record' => 'Elemento', 'Record Date' => 'Data Risultato', 'Record Type' => 'Tipo Risultato', 'Record [%s] not found' => 'Risultato [%s] non trovato', 'Records Per Page' => 'Risultati per Pagina', 'Records that match all these conditions' => 'Record che corrispondono a tutte queste condizioni', 'Rectifies Invoice Number: ' => 'Rettifica Numero Ricevuta: ', 'Recurring' => 'Ricorsivo', 'Recurring? Product must be recurring as well, First & Second periods will be taken from product config' => 'Recurring? Product must be recurring as well, First & Second periods will be taken from product config', 'Redirect URL aMember will redirect user to this url after account removal, User will be redirected to aMember root url in case of this option is empty' => 'Redirect URL aMember will redirect user to this url after account removal, User will be redirected to aMember root url in case of this option is empty', 'Redirect URL aMember will redirect user to this url after user click Accept button. User will be redirected to aMember root url in case of this option is empty' => 'Redirect URL aMember will redirect user to this url after user click Accept button. User will be redirected to aMember root url in case of this option is empty', 'Redirect to NetDebit booking form.' => 'Redirect al form di prenotazione di NetDebit', 'Reference' => 'Referenza', 'Reference number is:' => 'Il numero di riferimento è:', 'Referer' => 'Referer', 'Referred Affiliate' => 'Presentato da Affiliato', 'Referred By' => 'Presentato da', 'Refresh' => 'Aggiorna', 'Refresh 3-rd party lists' => 'Aggiorna le liste di terze parti', 'Refund' => 'Rimborsi', 'Refund Amount' => 'Ammontare Rimborsato', 'Refund Failed' => 'Rimborso Fallito', 'Refund Receipt# Prefix If you change prefix numbers will start over from 1You can use %year% shortcode in invoice number. It will be replaced to actual year For example: RFND-%year%-' => 'Prefisso Ricevuta Rimborso Se cambi il prefisso la numerazione partirà di nuovo da 1 Puoi usare il segnaposto %year% che verrà cambiato con l\'anno corrente (esempio: RIMB-%year%-) così la numerazione si resetta ogni anno.', 'Refunded' => 'Rimborsato', 'Regional Tax' => 'Tassa Locale', 'Register' => 'Registrati', 'Registered' => 'Registrato', 'Registration E-Mail to Subusers' => 'Email Registrazione per SubUser', 'Registration country and your IP address country doesn\'t match. ' => 'Nazione di Registrazione e Nazione del tuo indirizzo IP non coincidono. ', 'Remaining quantity' => 'Quantità Rimanente', 'Remote API Permissions' => 'Permessi API Remoti', 'Remove' => 'Rimuovi', 'Remove It From Signup Form' => 'Rimuovi dal Form di Registrazione', 'Remove Label' => 'Rimuovi Etichetta', 'Remove Mode action after new invoice completed' => 'Remove Mode action after new invoice completed', 'Remove My Account' => 'Cancella il mio account', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Elimina Utenti Wordpress quando un utente viene cancellato in aMember viene cancellato anche in %s', 'Remove all user\'s pending invoices' => 'Cancella tutte le ricevute in attesa degli utenti', 'Remove user' => 'Rimuovi Utente', 'Remove user\'s pending invoices that has either same product or product from same category as completed invoice' => 'Cancella le ricevute in attesa di utenti che hanno lo stesso prodotto o un prodotto nella stessa categoria in una ricevuta pagata', 'Remove user\'s pending invoices that has same product as completed invoice' => 'Cancella le ricevute in attesa di utenti che hanno lo stesso prodotto in una ricevuta pagata', 'Reply' => 'Rispondi', 'Report' => 'Report Affiliato', 'Report Period Take into Account only subscriptions that began in defined period, keep empty to use all subscriptions' => 'Periodo di Riferimento Considera solo abbonamenti iniziati tra queste date Se lasci vuoto si considerano TUTTI gli abbonamenti', 'Requested Type To be used if you have multiple plans in one account and wish to select type of query you wish to make. By default the service uses the highest level available' => 'Requested Type To be used if you have multiple plans in one account and wish to select type of query you wish to make. By default the service uses the highest level available', 'Require Behaviour' => 'Richiedi Comportamento', 'Required' => 'Obbligatorio', 'Required Referral Number to get Bonus Subscription' => 'Required Referral Number to get Bonus Subscription', 'Reseller can log-in as subuser' => 'Il Rivenditore può autenticarsi come SubUser', 'Reseller can manage the following subuser fields' => 'Il Rivenditore può gestire i seguenti campi SubUser', 'Reseller cannot delete subuser accounts' => 'Il Rivenditore non può cancellare gli account SubUser', 'Reseller cannot edit subusers accounts after insertion' => 'Il Rivenditore non può editare gli account SubUser dopo averli inseriti', 'Resellers can delete subusers' => 'Il Rivenditore può cancellare SubUsers', 'Resellers can delete subusers only when limit is over' => 'Il Rivenditore può cancellare SubUsers solo se ha raggiunto il limite', 'Resellers cannot delete subusers' => 'I Rivenditori non possono cancellare i SubUsers', 'Resellers-only page' => 'Pagina riservata ai Rivenditori', 'Resend Postback enter list of URLs to resend incoming postback' => 'inoltra Postback lista di URL a cui rispedire il postback', 'Reset' => 'Resetta', 'Reset Accept Status for Active Users of leave empty to reset for all users' => 'Reset Accept Status for Active Users of leave empty to reset for all users', 'Reset Accept Status for Users' => 'Resetta Stato Accettazione Utenti', 'Reset Filter' => 'Reimposta il Filtro', 'Resume Subscription' => 'Riattiva Iscrizione', 'Retention Rate' => 'Percentuale Retention', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Riprova se Fallito se non è riuscito l\'addebito periodico, aMember può ripeterlo per alcuni giorni ed estendere l\'abbonamento del cliente per quel periodo di tempo inserisci il numero di giorni entro i quali ripetere il tentativo di addebito', 'Return' => 'Torna Indietro', 'Return and try again' => 'Torna Indietro e Riprova', 'Review/Pay Commissions' => 'Esamina/Paga Payout', 'Reward Points' => 'Punti Premio', 'Reward Points Configuration' => 'Configurazione Punti Premio', 'Risk Score' => 'Punteggio di Rischio', 'Risk Score Overall %sRisk Score%s (decimal from 0 to 10) For orders that return a fraud score of 2.5 and above, it is recommended to hold for review, or require the validation with the Telephone Verification service ' => 'Risk Score Overall %sRisk Score%s (decimal from 0 to 10) For orders that return a fraud score of 2.5 and above, it is recommended to hold for review, or require the validation with the Telephone Verification service ', 'Robots instructions for search engines' => 'Motori di Ricerca', 'Rows Count per Page at Credits History page empty - it uses global settings' => 'Rows Count per Page at Credits History page empty - it uses global settings', 'Run Report' => 'Avvia Report', 'Running %s' => 'Sto eseguendo %s', 'Sales' => 'Vendite', 'Save' => 'Salva', 'Save Profile' => 'Salva Profilo', 'Search' => 'Ricerca', 'Search Products' => 'Ricerca Prodotti', 'Search Results' => 'Risultati Ricerca', 'Search by Voucher Code' => 'Cerca per Voucher Regalo', 'Second and Subsequent Payments' => 'Secondo Pagamento e Seguenti', 'Secret Key' => 'Chiave Segreta', 'Secret key' => 'Chiave Segreta', 'Secure Payment' => 'Pagamento Sicuro', 'Security Code' => 'Codice Sicurezza', 'Security code is either invalid or expired' => 'Codice Sicurezza non valido o scaduto', 'Security code is invalid' => 'Il codice di sicurezza non è valido', 'Select Search Criteria' => 'Seleziona Criteri di Ricerca', 'Select a condition to add into search' => 'Seleziona una condizione da aggiungere alla ricerca', 'Select all %s records matching your search' => 'Seleziona tutti i %s record che corrispondono alla tua ricerca', 'Select by default' => 'Seleziona di Default', 'Select-box (one product can be selected)' => 'Select-box (si può scegliere un solo prodotto)', 'Selected Users has not any associated files' => 'Gli utenti selezionati non hanno nessun file associato', 'Selectel storage is not configured' => 'Lo storage selezionato non è configurato', 'Self-Service Setup' => 'Impostazioni Self-Service', 'Self-Service Store' => 'Negozio Self-Service', 'Selz payout' => 'Payout Selz', 'Send' => 'Invia', 'Send Cancel Notifications to Admin' => 'Invia Notifica di Cancellazione ad Admin', 'Send Cancel Notifications to User' => 'Invia Notifica Cancellazione al Cliente', 'Send Free Payment Admin' => 'Invia Pagamento Gratuito ad Admin', 'Send Message' => 'Invia Messaggio', 'Send Notification after XX since Last Sign In' => 'Invia Notifica dopo XX dall\'ultimo accesso', 'Send Payment Admin' => 'Invia Pagamento ad Admin', 'Send Payment Link' => 'Invia Link di Pagamento', 'Send Payment Link default email template' => 'Send Payment Link default email template', 'Send Payment Mail' => 'Invia Email di Pagamento', 'Send Reminder to Admin if coupon batch is almost empty' => 'Send Reminder to Admin if coupon batch is almost empty', 'Send Reminder to User if he has not logged in to site for a long time' => 'Invia Reminder all\'Utente se non si è loggato per molto tempo', 'Send Security Code' => 'Invia Codice Sicurezza', 'Send Signup Mail' => 'Invia Email di Registrazione', 'Send Voucher To' => 'Invia Voucher a', 'Send opt-in/out emails' => 'Invia Email di opt-in/out', 'Sender Name' => 'Nome Mittente', 'Sending' => 'Sto spedendo', 'Sent above notification in case of batch has less than ... coupons' => 'Invia la notifica qui sopra se il gruppo ha meno di ... Buoni Sconto', 'Sequential Receipt# Numbering aMember still creates unique id for invoices, but it will generate PDF receipts for each payment that will be available in the member area for customers' => 'Numero Sequenziale Ricevute', 'Serial Numbers' => 'Numeri Seriali', 'Session Timeout, min' => 'Timeout Sessione, min', 'Session expired, please enter username and password again' => 'La sessione è scaduta, reinserisci nome utente e password', 'Set LInk Expiration' => 'Imposta scadenza LInk', 'Set Successfully' => 'Impostazione avvenuta con successo', 'Settings' => 'Impostazioni', 'Shipping' => 'Spedizione', 'Shipping Address Information' => 'Indirizzo di Spedizione', 'Shipping Options' => 'Opzioni Spedizione', 'Shipwire Shipping Address Brick' => 'Sezione Indirizzo Spedizione Shipwire', 'Shop Id Unique Shop ID in the system' => 'Shop Id Unique Shop ID in the system', 'Shopping Cart' => 'Carrello', 'Shopping Cart Module. No data input' => 'Modulo Carrello Vendita. Nessun dato in ingresso', 'Shopping Cart Module. No product id input' => 'Modulo Carrello Vendita. Nessun ID prodotto in ingresso', 'Shopping Cart Signup' => 'Registrazione Carrello Vendita', 'Show Tax even it is 0' => 'Mostra Tasse anche se 0', 'Show error and do not allow to login until session timeout' => 'Mostra Errore e fa attendere il Timeout Sessione', 'Show these fields' => 'Mostra questi campi', 'Sign-up' => 'Registrati', 'Signature' => 'Firma', 'Signup Form' => 'Modulo di Registrazione', 'Signup here' => 'Registrati Qui', 'Signup/payment functions are disabled for this user account' => 'le funzioni di pagamento sono disabilitate per questo account', 'Simple Search Users' => 'Ricerca Utenti Veloce', 'Single Checkbox' => 'Checkbox singola', 'Single Login Session' => 'Login Univoco', 'Site Title' => 'Nome Sito', 'Skip First Line' => 'Ignora Prima Linea', 'Skrill E-Mail' => 'Email Skrill', 'Snippets' => 'Snippet', 'Software Download' => 'Download Software', 'Software Downloads' => 'Download Software', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Mi spiace, è impossibile usare questo metodo di pagamento per questo ordine. Seleziona un altro metodo di pagamento tra quelli disponibili', 'Sorry, license re-activation limit reached' => 'Mi spiace, hai raggiunto il limite di riattivazione della licenza', 'Sorry, seems you have used wrong link' => 'Mi spiace, sembra che tu stia usando un link sbagliato', 'Sorry, we have not found an activation record to deactivate' => 'Mi spiace, non ho trovato una registrazione attiva da disattivare', 'Sorry, you have already reached limit of activations (%d active, %d allowed)' => 'Mi spiace, hai raggiunto il limite di attivazioni (%d attive, %d permesse)', 'Sort code' => 'Codice Ordinamento', 'Source Code — Copy/Paste Into Your Website' => 'Codice Affiliato— Copia/Incolla nel tuo sito', 'Spam Reports' => 'Report Spam', 'Specific User' => 'Utente Specifico', 'Specified folder is not writable - please chmod the folder to 777, so aMember can write .htaccess file for folder protection' => 'La cartella specificata non è scrivibile - per favore porta il chmod della cartella a 777, così aMember può editare il file .htaccess per proteggere la cartella', 'Spent Amount' => 'Importo Speso', 'Start' => 'Inizio', 'Start Date' => 'Data di Inizio', 'State' => 'Provincia', 'State Title' => 'Nome Stato', 'Statistics' => 'Tue Statistiche', 'Status' => 'Stato', 'Status of your subscription has been changed.' => 'Lo Stato della tua Iscrizione è cambiato.', 'Stay signed in' => 'Rimani Iscritto', 'Street' => 'Via', 'Street (Second Line)' => 'Via (Seconda Riga)', 'Street Address' => 'Indirizzo', 'Street Address (Second Line)' => 'Indirizzo (Seconda Riga)', 'Sub-Affiliates' => 'Sub-Affiliati', 'SubUsers Count (keep zero for non-reseller products)' => 'Numero SubUser (0 se non vuoi che il prodotto vada ai rivenditori)', 'SubUsers Product (keep empty for non-reseller products)' => 'Prodotto per SubUser (vuoto se non vuoi che il prodotto vada ai rivenditori)', 'Subject' => 'Oggetto', 'Subject can not be empty' => 'Il campo Oggetto non può essere lasciato vuoto', 'Subject or Ticket#' => 'Oggetto o Ticket#', 'Submit Details' => 'Invia Dettagli', 'Submit New Ticket' => 'Invia Nuovo Ticket', 'Subscribe And Pay' => 'Paga con la Carta', 'Subscribe Now' => 'Iscriviti Ora', 'Subscribe all available users' => 'Iscrivi tutti gli utenti attuali', 'Subscribe to Site Newsletters' => 'Iscriviti alle Newsletter del Sito', 'Subscribed To Newsletters' => 'Iscrizione alla Newsletter avvenuta', 'Subscribed to Newsletter Lists' => 'Iscritto alle Newsletter', 'Subscribed to any of (including expired)' => 'Iscritto a qualunque tra (inclusi scaduti)', 'Subscribers' => 'Iscritti', 'Subscription Limit' => 'Limite Iscrizioni', 'Subscription Terms' => 'Condizioni di Iscrizione', 'Subscription expired, please contact your reseller to upgrade subscription' => 'Iscrizione scaduta, per favore contatta ilm tuo rivenditore per riattivare', 'Subscription limit' => 'Limite Iscrizioni', 'Subscription limit for each user' => 'Limite Iscrizioni per ogni utente', 'Subscription/Product Title' => 'Prodotto/Abbonamento', 'Subtotal' => 'Sub Totale', 'Subuser e-mail address can be changed by site admin only' => 'La Email del SubU può essere cambiata solo dall\'amministratore del sito', 'Subusers' => 'SubUser', 'Subusers Assigned To (reseller username or id#):' => 'SubUser assegnati a (nome utente rivenditore o id#):', 'Subusers Assigned To [%s #%d]' => 'SubUser assegnati a [%s #%d]', 'Success: %d (%0.2f %s) Failed: %d (%0.2f %s)' => 'Completati: %d (%0.2f %s) Falliti: %d (%0.2f %s)', 'Successfull update' => 'Aggiornamento Riuscito', 'Such affiliate ID exist' => 'Questa ID Affiliato esiste', 'Sum all available limits' => 'Somma tutti i limiti disponibili', 'Super Groups Plugin will not remove these groups from user\'s account. This is useful if you add additional group to user manually and this group is not linked to any product. If that additional group is not added to Super groups, it will be removed when plugin updates user account' => 'Super Gruppi il Plugin non rimuove i gruppi dagli account utenti. Questa opzione è utile se aggiungi manualmente un nuovo gruppo all\'utente e questo gruppo non è legato a nessun prodotto in aMember. Se il gruppo aggiuntivo non viene riportato nei Super Gruppi, verrà rimosso dall\'utente quando il Plugin lo aggiorna.', 'Super Groups aMember will not remove %s groups from user\'s account This is useful if you add additional group to user in %s manually and this group is not linked to any aMember product If that additional group is not added to Super groups, it will be removed when aMember updates user account' => 'Super Gruppi aMember non rimuove i gruppi %s dagli account utenti. Questa opzione è utile se aggiungi manualmente un nuovo gruppo all\'utente in %s e questo gruppo non è legato a nessun prodotto in aMember. Se il gruppo aggiuntivo non viene riportato nei Super Gruppi, verrà rimosso dall\'utente quando aMember lo aggiorna.', 'Support' => 'Supporto', 'Support Us!' => 'Supportaci!', 'Surrender' => 'Rinuncio', 'Switch default identity block with block with avatar' => 'Scambia la sezione identità di default con quelloa con avatar', 'THEN YOU RECEIVE' => 'POI RICEVI', 'TOTAL' => 'TOTALI', 'Tags' => 'Tag', 'Tags comma separated list of tags' => 'Tags comma separated list of tags', 'Take' => 'Prendi', 'Target By User' => 'Target per Utente', 'Target Folder URL' => 'Target URL Cartella', 'Target URL' => 'URL Destinazione', 'Tax' => 'Tasse', 'Tax Amount' => 'Importo Tasse', 'Tax Id' => 'IVA/VAT', 'Tax Rate' => 'Percentuale IVA/VAT', 'Tax Rate for example 18.5 (no percent sign)' => 'Percentuale Tasse esempio 18.5 (senza simbolo di percentuale)', 'Tax Report' => 'Report Tasse', 'Tax Title' => 'Nome Tassa', 'Tax Value' => 'Importo Tasse', 'Tax by Customer Country' => 'Tasse per Nazione Clienti', 'Taxable Income' => 'Ricavo Imponibile', 'Taxable Subtotal' => 'Imponibile', 'Terms' => 'Termini', 'Test Mode' => 'Modalità Test', 'Test Mode Enabled The cents part of the amount you pass to DirectOne will determine the response code for the test script. For example, an amount of 100 ($1.00) with return a response of 00 which represents an approved transaction response. An amount of 151 ($1.51) will return a response of 51 which represents a declined transaction response.' => 'Test Mode Enabled The cents part of the amount you pass to DirectOne will determine the response code for the test script. For example, an amount of 100 ($1.00) with return a response of 00 which represents an approved transaction response. An amount of 151 ($1.51) will return a response of 51 which represents a declined transaction response.', 'Test Settings' => 'Impostazioni del Test', 'Text to Add to each PDF file This text will be included at bottom to PDF fileYou can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.' => 'Text to Add to each PDF file This text will be included at bottom to PDF fileYou can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.', 'Thank you for Signing up' => 'Congratulazioni per la Registrazione', 'Thank you for your purchase. Your subscription will become active as soon as the payment has been verified.' => 'Grazie per l\'acquisto. La tua iscrizione sarà attivata non appena il pagamento sarà stato verificato.', 'Thank you! We sent invite code to your friend.' => 'Grazie! Il Codice Invito per il tuo amico è stato inviato.', 'Thanks Success' => 'Grazie, successo', 'Thanks for the payment request. It may take up to 48 hours....' => 'Grazie per la richiesta di pagamento, potrebbero volerci fino a 48 ore per elaborarla....', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Grazie! Il tuo pagamento è instato di ATTESA E VERIFICA. La tua iscrizione sarà confermata quando il pagamento sarà completato. Per favore controlla il tuo account durante questo processo. Potrebbero volerci 12-24 ore. Riceverai una Email di notifica della Ricezione del pagamento.', 'The "Card Code" is a three- or four-digit security code that is printed on the back of credit cards in the card\'s signature panel (or on the front for American Express cards).' => 'Il codice CVV è un numero di 3 o 4 cifre che si trova nel retro della carta, vicono alla firma (o di fronte nelle American Express).', 'The coupon entered is not valid with any product(s) being purchased. No discount will be applied' => 'Il Buono Sconto inserito non è valido per nessuno dei prodotti acquistati, quindi non verrà applicato nessuno sconto', 'The database has encountered a problem, please try again later.' => 'Il database ha incontrato un problema, riprova.', 'The file has been removed from disk or corrupted. Please re-upload it.' => 'File cancellato dal disco o danneggiato. Per favore ricaricalo di nuovo.', 'The following words are reserved : %s' => 'Le seguenti parole sono riservate : %s', 'The information you have entered is incorrect. Username [%s] does not exist in database' => 'Informazione inserita non corretta. In Nome Utente [%s] non esiste nel database', 'The message containing your password has already been sent to your inbox. Please wait 180 minutes for retrying' => 'Il messaggio contenente la tua password è già stato inviato. Per fvore attendi 180 minuti prima di riprovare', 'The minimum donation amount is %s' => 'L\'importo minimo di donazione è %s', 'The password should be at least %d characters long' => 'La password dovrebbe avere almeno %d caratteri', 'The result is filtered.' => 'Risultato filtrato.', 'The user name or password is incorrect' => 'Il Nome Utente o la Password non sono corretti', 'There are %d pending subuser subscriptions. %sUpgrade your access%s' => 'Ci sono %d iscrizioni di SubUsers in attesa. %sAggiorna il tuo Accesso%s', 'There are no confirmed payments for your account' => 'Non ci sono ancora pagamenti confermati per il tuo account', 'There are no form available for affiliate signup.' => 'Non ci sono form di registrazione per gli affiliati.', 'There are no products available for purchase. Please come back later.' => 'Non ci sono ancora prodotti da acquistare, per favore ritorna più avanti.', 'There are no products available to order with credits' => 'Non ci sono prodotti da ordinare con i Crediti', 'There is %d active login session for this user from following IP address(es): %s' => 'Ci sono %d sessioni login attive per questo utente da questi IP: %s', 'There is issue with second factor Authentication' => 'C\'è un problema con l\'autenticazione doppia (Second Factor)', 'These details can be found on your cheque book, bank statement, or bank card' => 'Questi dettagli si trovano nel tuo libretto assegni, estratto conto bancario e sulla carta', 'This %s is blocked. Please contact site support to find out why' => 'Questo %s è bloccato. Contatta il supporto del sito per ricevere chiarimenti', 'This Coupon Code is already being used, please select another one' => 'Questo Buono Sconto è già stato usato, per favore utilizzane un altro', 'This Month' => 'Questo Mese', 'This Quarter' => 'Questo trimestre', 'This Week (Mon-Sun)' => 'Questa Settimana (Lun-Dom)', 'This Week (Sun-Sat)' => 'Questa Settimana (Dom-Sab)', 'This Year' => 'Anno Corrente', 'This coupon belongs to another customer' => 'Questo Buono Sconto appartiene a un altro cliente', 'This customer is a reseller' => 'Questo Cliente è un Rivenditore', 'This customer is a subuser of' => 'Questo Cliente è un SubUser di', 'This customer was invited by %s' => 'Questo Cliente è stato invitato da %s', 'This field is a requried field' => 'Questo campo è obbligatorio', 'This field is required' => 'Questo campo è obbligatorio', 'This is a required field' => 'Campo obbligatorio', 'This page will be automatically refreshed within %s' => 'Questa pagina sarà automaticamente aggiornata entro %s', 'This payment system could not handle payments in [%s] currency' => 'Questo sistema di pagamento non può gestire pagamenti nella valuta [%s]', 'This payment system could not handle recurring subscriptions' => 'Questo Sistema di Pagamento non può gestire abbonamenti ricorrenti', 'This payment system could not handle zero-total invoices' => 'Questo sistema di pagamento non può gestire ricevute con totale zero', 'This paysystem can not work with multiple products in card' => 'Questo Sistema di Pagamento non funziona con prodotti multipli nella carta', 'This plugin can not handle recurring subscriptions with free trial' => 'Questo Sistema di Pagamento non può gestire abbonamenti ricorrenti con prova gratuita', 'This report works only with radio and select fields. You have not such custom fields yet.' => 'Questo report funziona solo con campi radio e select. Non hai ancora settato questi campi obbligatori.', 'Thresehold Date' => 'Data Limite', 'Threshold Date' => 'Data Soglia', 'Ticket' => 'Ticket', 'Ticket Roster' => 'Lista (turni) Ticket', 'Ticket has been submited' => 'Il ticket è stato inviato correttamente', 'Tickets' => 'Ticket', 'Title' => 'Titolo', 'Title Just for your reference' => 'Title Just for your reference', 'Title for link to Personal Folder in member area' => 'Nome Link della Cartella Personale nell\'area riservata', 'To' => 'A', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Per aggiungere un campo nel modulo, spostalo dai \'Campi Disponibili\' ai \'Campi Modulo\'. Per rimuovere dei campi, spostali di nuovo nei \'Campi Disponibili\'. Per costruire moduli multi pagina, inserisci un elemento \'Interruzione Pagina\' nel posto dove vuoi che la pagina venga spezzata.', 'To add new user groups %sClick here%s.' => 'Per aggiungere altri Gruppi Utente %sClicca qui%s.', 'To assign groups to products %sClick here%s.' => 'Per assegnare Gruppi ai prodotti %sClicca qui%s.', 'Today' => 'Oggi', 'Token is empy in response object' => 'Token vuoto nella risposta', 'Token value' => 'Token', 'Too many Lost Password requests. Please wait 180 minutes for retrying' => 'Troppe richieste di Password Persa. Per favore attendi 180 minuti prima di riprovare', 'Top Affiliate' => 'Migliori Affiliati', 'Top Affiliates by Points' => 'Migliori Affiliati per Punteggio', 'Top Margin How much [pt] skip from top of template before start to output invoice 1 pt = 0.352777 mm' => 'Top Margin How much [pt] skip from top of template before start to output invoice 1 pt = 0.352777 mm', 'Total' => 'Totale', 'Total Amount of Payment' => 'Totale Importo Pagamento', 'Total Price' => 'Prezzo Totale', 'Total Records: %s' => 'Risultati totali: %s', 'Track Only Initial Payment for recurring subscription aMember notify iDevAffiliate only about initial payment' => 'Track Only Initial Payment for recurring subscription aMember notify iDevAffiliate only about initial payment', 'Transaction aborted by user.' => 'Transazione annullata dall\'utente.', 'Transaction failed' => 'Transazione fallita', 'Transactions' => 'Transazioni', 'Transactions History' => 'Storico Transazioni', 'Try again' => 'Riprova', 'Trying to load foreign subuser' => 'Cerco di caricare SubUser forestiero', 'Two-Factor Authentication (%s)' => 'Autenticazione Doppia [Two Factor] (%s)', 'Type' => 'Tipo', 'Type Username or E-Mail' => 'Email', 'Type a keyword to search in FAQ' => 'Cerca nelle FAQ', 'USA (Letter)' => 'USA (Letter)', 'Unable to cancel subscription: ' => 'Impossibile cancellare abbonamento: ', 'Unable to delete this file as it is used for:' => 'Non posso cancellare questo file perché viene usato per:', 'Unable to handle invoice, class: %s undefined' => 'Impossibile gestire la ricevuta, classe: %s non definita', 'Unassign Affiliate' => 'Dissocia Affiliato', 'Unassign Partner' => 'Dissocia Partner', 'Unassign this Ticket from yourself' => 'Annulla Associazione al Ticket', 'Undefined' => 'Non Definito', 'Underscore is not allowed for username' => 'Non puoi usare Underscore nel Nome Utente', 'Unenroll Student' => 'Cancella Iscrizione Studente', 'Unique Clicks' => 'Click Unici', 'Unit Price' => 'Prezzo', 'Unknown' => 'Sconosciuto', 'Unknown period unit: %s' => 'Unità temporale sconosciuta: %s', 'Unlimited' => 'Illimitato', 'Unsubscribe' => 'Cancella Iscrizione', 'Unsubscribe by Existing Reports' => 'Cancellazioni da Report Esistenti', 'Unsubscribe by Webhooks' => 'Cancellazioni da Webhooks', 'Unsubscribe customer from selected newsletter threads' => 'Disiscrivi Cliente dalle seguenti newsletter', 'Unsubscribe from all e-mail messages' => 'Cancella l\'iscrizione da tutti i messaggi e-mail', 'Unsubscribed' => 'Disiscritto', 'Unsubscription Confirmation' => 'Conferma Cancellazione Iscrizione', 'Update' => 'Aggiorna', 'Update Credit Card' => 'Aggiorna Carta di Credito', 'Update Credit Card Info' => 'Aggiorna Carta di Credito', 'Update Debit Card Info' => 'Aggiorna Carta di Debito', 'Update Echeck Info' => 'Aggiorna Info Echeck', 'Update Iban Info' => 'Aggiorna IBAN', 'Update Password' => 'Aggiorna Password', 'Update eCheck Info' => 'Aggiorna Info eCheck', 'Update failed' => 'Aggiornamento fallito', 'Updated' => 'Aggiornato', 'Upgrade Invoice' => 'Aggiorna Ricevuta', 'Upgrade Status' => 'Aggiorna Stato', 'Upgrade Subscription' => 'Aggiorna Iscrizione', 'Upload Categories' => 'Carica Categorie', 'Upload Category' => 'Carica Categoria', 'Upload File to Active Users of' => 'Carica File per gli Utenti Attivi di', 'Upload files using FTP client to [%s]' => 'Carica i file utilizzando un client FTP su [%s]', 'Uploaded' => 'Caricato', 'Uploaded File Names' => 'Nomi dei File Caricati', 'Uploaded Files' => 'File Caricati', 'Uploads' => 'Caricamenti', 'Use Database Connection other than configured for aMember' => 'Usa una Connessione al Database diversa da quella configurata in aMember', 'Use MaxMind Credit Card Fraud Detection' => 'Usa Anti Frode di MaxMind', 'Use Pre-Defined Template' => 'Usa Template Pre-Definito', 'Use Reward Points' => 'Usa Punti Ricompensa', 'Use SSL for Authenticated URLs enable this option if you use https for your site' => 'Use SSL for Authenticated URLs enable this option if you use https for your site', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Usa un altro DataBase MySQL usa un host personalizzato, utente, password per la connessione al database %s Normalmente puoi lasciare deselezionata questa opzione', 'Use another card' => 'Usa un\'altra carta', 'Use different profile form for subusers' => 'Usa Profilo diverso per i SubUser', 'Use maximum from available' => 'Usa il massimo del disponibile', 'Use normal, non customized invoice' => 'Usa Ricevuta normale, non personalizzata', 'Used' => 'Usato', 'Used Any Coupon' => 'Usato qualsiasi Buono Sconto', 'Used Coupon' => 'Usato Buono Sconto', 'Used Coupon from Batch: %s' => 'Usato Buono Sconto dal Gruppo: %s', 'Used Coupon with Code: %s' => 'Usato Buono Sconto: %s', 'Useful Links' => 'Link Utili', 'User' => 'Utente', 'User %s' => 'Utente %s', 'User %s is already working on this ticket.' => 'L\'utente %s sta già lavorando su questo Ticket.', 'User %s not found' => 'Utente %s non trovato', 'User Affiliate Link' => 'Link Affiliato Utente', 'User Agreement' => 'Condizioni d\'uso', 'User Base Fields' => 'Campi Base Utente', 'User City' => 'Comune Utente', 'User Country' => 'Nazione Utente', 'User Demographics' => 'Demografica Utente', 'User Distribution by Custom Field' => 'Distribuzione Utenti per Campi Personalizzati', 'User First Name' => 'Nome di Battesimo', 'User Group' => 'Gruppo Utente', 'User Groups' => 'Gruppi Utenti', 'User ID' => 'ID Utente', 'User Info' => 'Info Utente', 'User Internal ID#' => 'ID# Interno Utente', 'User Last Name' => 'Cognome', 'User Personal Folder URL' => 'URL Cartella Personale Utente', 'User Phone' => 'Telefono Utente', 'User Search' => 'Ricerca Utenti', 'User State' => 'Provincia Utente', 'User Status (0-pending, 1-active, 2-expired)' => 'Stato Utente (0-in attesa, 1-attivo, 2-scaduto)', 'User Street' => 'Indirizzo Utente', 'User Street (Second Line)' => 'Indirizzo Utente (Seconda Linea)', 'User Subscriptions Status' => 'Stato Iscrizione Utente', 'User Unsubscribe Link' => 'Link Cancellazione Utente', 'User ZIP' => 'CAP/ZIP Utente', 'User can Choose Product in any Brick of Such Type on Page but he Should Choose at least One Product still' => 'L\'Utente può scegliere qualsiasi prodotto in una sezione di questo tipo sulla pagina ma DEVE comunque sceglierne ALMENO uno', 'User can choose to make donation recurring' => 'L\'Utente può scegliere di rendere la donazione ricorrente', 'User is locked' => 'Utente Bloccato', 'User is not approved' => 'Utente non approvato', 'User limit in FileRun is already reached' => 'Limite Utilizzo FileRun già raggiunto', 'User must provide' => 'L\'utente deve dare', 'User should have/had access in same month as publish date' => 'L\'utente deve avere/ha avuto accesso lo stesso mese della pubblicazione', 'User should have/had acecss on publish date exactly' => 'L\'utente deve avere/ha avuto accesso il giorno della pubblicazione', 'Username' => 'Nome Utente', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Nome Utente qui puoi scegliere un nuovo nome utente o tenere il vecchio. Il nome utente deve essere di almeno %d caratteri e può contenere solo lettere minuscole, numeri e il simbolo underscore ( _ )', 'Username %s is already taken. Please choose another username' => 'Il Nome Utente %s è già utilizzato da un altro utente. Scegline uno diverso!', 'Username [%s] contains invalid characters - please use digits, letters, dash and underscore' => 'Nome Utente [%s] contiene caratteri non permessi - per favore usa numeri, lettere, trattino e trattino basso', 'Username [%s] is already taken. Please choose another username' => 'Nome Utente [%s] già in uso. Per favore scegli un altro nome utente', 'Username and password can not be the same' => 'Nome Utente e Password non possono essere uguali', 'Username contains invalid characters - please use digits, letters or spaces' => 'Il Nome Utente contiene caratteri non validi - usa lettere, numeri o spazi', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Il Nome Utente contiene caratteri non validi - usa lettere o numeri', 'Username/Email' => 'Indirizzo Email', 'Users Take into Account only user who sign up in defined period, keep empty to use all user' => 'Utenti da Considerare solo quelli iscritti tra le date, lascia vuoto per includere tutti', 'Users subscribed to Newsletter Threads #' => 'Utenti iscritti alle Newsletter #', 'VAT Id' => 'P.IVA/VAT', 'VAT Settings are incorrect - no Vat Id configured' => 'Impostazione P.IVA/VAT sbagliate - nessuna P.IVA/VAT configurata', 'Validate E-Mail Address by sending e-mail message with code' => 'Convalida l\'indirizzo Email inviando un messaggio con un codice di verifica', 'Validate Location even if Invoice has no VAT Validate All New Invoices (even if invoice has no VAT) If unchecked, location will be validated only when user selects country inside EU and only if VAT should be applied to invoice. Free invoices won\'t be validated still' => 'Validazione Nazionalità per IVA/VAT Non Dovuta Se non spunti, la nazionalità verrà validata SOLO per utenti in EU e solo se è dovuta la IVA/VAT Ricevute Gratis non verranno comunque validate.', 'Validation' => 'Validazione', 'Value' => 'Valore', 'Verification email has been sent to your address. E-mail will be changed in your account after confirmation' => 'Email di verifica spedita al tuo indirizzo email. Il cambio enail verrà registrato solo dopo la conferma', 'Verify Email Profile' => 'Verifica Email Profilo', 'Verify Email Signup' => 'Verifica Email Modulo Iscrizione', 'Version' => 'Versione', 'Version of script' => 'Versione dello script', 'Versions' => 'Versioni', 'View Basket' => 'Vedi il Carrello', 'Visit %sorder page%s to order additional subscriptions' => 'Visita la %spagina d\'ordine%s per scoprire altri prodotti/servizi ', 'Void' => 'Annulla', 'Void Amount' => 'Annulla Importo', 'Voucher Code Length' => 'Lnghezza Voucher Regalo', 'Voucher is already used' => 'Voucher Regalo già usato', 'Voucher is expired' => 'Voucher Regalo scaduto', 'Voucher is not yet active' => 'Voucher Regalo non ancora attivo', 'Watchers' => 'Osservatori', 'Watchers notify the following admins about new messages in this ticket' => 'Watchers notify the following admins about new messages in this ticket', 'We ask you to update your password periodically for security reason.' => 'Per favore aggiorna la tua password periodicamente per ragioni di sicurezza.', 'We review all affiliates manually, so your affiliate account status is pending. You will receive email when your account will be approved. Thank you for your patience.' => 'Controlliamo le iscrizioni di tutti gli affiliati manualmente, quindi il tuo account affiliato è "in attesa". Riceverai una email quando il tuo account sarà definitivamente approvato. Grazie per la pazienza.', 'We updated our Terms & Conditions. Please accept new one.' => 'Abbiamo aggiornato i Termini e Condizioni, per continuare devi accettarli.', 'Webhooks' => 'Webhook', 'Week' => 'Settimana', 'Weeks' => 'Settimane', 'Wepay does not support trial periods!' => 'Wepay non supporta i periodi prova!', 'What to Display' => 'Cosa Mostrare', 'Who is paying the fee' => 'Chi paga la commissione', 'Write your comment...' => 'Scrivi il tuo commento...', 'Write your reply...' => 'Scrivi la tua risposta...', 'Wrong code or code expired - please start signup process again' => 'Codice errato oppure scaduto - ti preghiamo di ripetere il processo di registrazione', 'Wrong columns count. Please use exact format for import file: %s' => 'Numero Colonne Errato. Per favore usa il formato esatto per importare il file: %s', 'Wrong link - no id passed' => 'Link Errato! Non è stata passata nessuna id', 'Wrong parameters, error #1253' => 'Parametri non corretti, errore #1253', 'Wrong password' => 'Password Errata', 'Wrong path: not a folder: %s' => 'Percorso Errato: non è una cartella: %s', 'Wrong step' => 'Passo Errato', 'Wrong value submitted' => 'Valore Inviato Errato', 'Wrong verification code' => 'Codice di Verifica Errato', 'Wrongly signed URL, please contact site admin' => 'URL con firma errata, contatta l\'amministratore', 'Year' => 'Anno', 'Years' => 'Anni', 'Yes' => 'Sì', 'Yes, I want to cancel subscription' => 'Sì, annulla la mia iscrizione', 'Yes, I want to remove my account with all associated info on this site' => 'Sì, voglio rimuovere il mio account con tutte le informazioni associate da questo sito', 'Yes, continue' => 'Sì, continua', 'Yes, is a subuser' => 'Sì, è un SubUser', 'Yes, unsubscribe' => 'Sì, cancellami', 'Yesterday' => 'Ieri', 'You are going to download "%s" file. %s credit will be deducted from your balance. You have %s credits.' => 'Sta per scaricare il file "%s". Verranno dedotti %s crediti dal tuo conto. Ora hai %s crediti.', 'You are logged-in as' => 'Loggato come', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Sei loggato come %s. %sEsci%s se vuoi accedere con un altro account.', 'You are trying to access disabled module [%s]' => 'Stai cercando di accedere ad un modulo disabilitato [%s]', 'You can assign some coupon codes to specific affiliate. Whenever coupon is used, commission will always be credited to this affiliate. This is true even when another affiliate is permanently tagged to the customer. For sales where the coupon is NOT used, the original (previous) affiliate will continue receiving commissions. If the customer has no affiliate, this affiliate will permanently be tagged to the customer, and will receive credit for future sales.' => 'Puoi assegnare un Buono Sconto ad un Affiliato specifico. Ogni volta che il Buono Sconto viene utilizzato verrà assegnata una commissione all\'affiliato. Questo avviene anche se c\'è un altro Affiliato assegnato permanentemente al Cliente. Se il cliente non ha affiliati assegnati e usa il Buono Sconto, l\'affiliato viene assegnato al cliente in questione.', 'You can change Number of %sRecords per Page%s in section %sSetup/Configuration%s' => 'Puoi cambiare il numero di %sRisultati per Pagina%s nella sezione %sSetup/Configurazione%s', 'You can find info regarding pdf invoice customization %shere%s' => 'Trovi infomrazioni sulla personalizzazione delle Ricevute %squi%s', 'You can get this token from the Authy mobile app. Otherwise you should receive SMS with token.' => 'Puoi avere questo token dalla applicazione smartphone Authy. Oppure lo riceverai via SMS.', 'You can not merge ordinary user with subuser and vice versa' => 'Non puoi Unire un Utente normale con un SubUser e viceversa', 'You can not merge subusers of different user' => 'Non puoi Unire SubUser di Utenti diversi', 'You can not use your own email' => 'Non puoi usare la tua email', 'You can remove your account in our system.' => 'Puoi rimuovere il tuo account nel nostro sistema.', 'You can\'t use your affiliate coupon code' => 'Non puoi usare il tuo stesso Buono Sconto Affiliato', 'You don;t have permission to access this area' => 'Non hai il permesso di accedere a quest\'area', 'You have %d items in shopping cart' => 'Hai %d prodotti nel carrello', 'You have %d items in your Basket' => 'Hai %d prodotti nel carrello', 'You have %s credits (%sTransaction History%s)' => 'Hai %s crediti (%sStorico Transazioni%s)', 'You have %s%d ticket(s)%s that require your attention' => 'Hai %s%d Ticket%s a cui rispondere', 'You have no access to %s' => 'Non hai accesso a %s', 'You have no active subscriptions' => 'Non hai iscrizioni attive', 'You have no enough permissions for this operation' => 'Non hai i permessi necessari per completare questa operazione', 'You have no items in shopping cart' => 'Il carrello è vuoto', 'You have no items in your basket - please add something to your basket before checkout' => 'Non ci sono oggetti nel tuo carrello - aggiungi qualcosa al tuo carrello prima di andare alla cassa', 'You have no saved credit card at OpenGateway' => 'Non hai Carte di Credito salvate su OpenGateway', 'You have no subscription' => 'Nessuna Iscrizione', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'Hai troppi SubUser assegnati a questo account. Forse desideri rimuovere %d utenti dal tuo account', 'You must be authorized to access this area' => 'Devi essere autorizzato per accedere a quest\'area', 'You must be logged-in to open this media' => 'Devi prima accedere per vedere questo file', 'You must be logged-in to run this action' => 'Devi prima accedere per fare questa azione', 'You must be logged-in to use this function' => 'Devi prima accedere per usare questa funzione', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Devi settare Setup/Configurazione -> Avanzate -> Dove salvo le Sessioni -> a \'Sessioni PHP Standard\'. Questo è necessario se vuoi abilitare il Login Unico tra aMember e SilverStrype', 'Your 9 digit ABA Routing Number' => 'ABA Routing Number di 9 cifre', 'Your API Key' => 'Chiave API', 'Your Account Removal' => 'rimozione del tuo Account', 'Your BIC Bank Identifier Code' => 'Your BIC Bank Identifier Code', 'Your Bank Account Number' => 'Numero Conto Bancario', 'Your Bank Account Number Up to 20 digits' => 'Your Bank Account Number Up to 20 digits', 'Your Basket' => 'Il tuo Carrello', 'Your Cellphone' => 'Cellulare', 'Your Credits Balance: ' => 'Totale Crediti: ', 'Your Current Password' => 'Password Attuale', 'Your Current Password if you are changing password, please enter your current password for validation' => 'La tua Password attuale se stai modificando la password, inserisci prima la tua password attuale per la convalida', 'Your Custom Affiliate Link' => 'Link Affiliato Personalizzato', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'La Tua Email ti arriverà una email per la conferma', 'Your General Affiliate Link' => 'Link Affiliato Generale', 'Your IBAN International Bank Account Number' => 'Your IBAN International Bank Account Number', 'Your Leads' => 'Tuoi Lead', 'Your Membership Information' => 'Area Riservata', 'Your Message' => 'Messaggio', 'Your Name your first and last name' => 'Your Name your first and last name', 'Your Password' => 'Password', 'Your Payment is PENDING & Under Process' => 'Il tuo pagamento è in stato di ATTESA e VERIFICA', 'Your Personal Downloads' => 'File Personali Riservati', 'Your Personal Uploads' => 'Tuoi File Personali', 'Your Reseller Packages' => 'I tuoi Pacchetti di Rivenditore', 'Your Subscriptions' => 'I Tuoi Abbonamenti', 'Your Username' => 'Nome Utente', 'Your Zendesk Agent Email Address' => 'Email Agente su Zendesk', 'Your account has been automatically locked.' => 'Il tuo account è stato bloccato.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Il tuo account non è ancora stato approvato. Ti verrà inviata una email di notifica non appena un amministratore del sito avrà controllato il tuo account e abilitato l\'accesso.', 'Your account require additional authentification factor' => 'Il tuo account richiede un ulteriore fattore di identificazione', 'Your answer is wrong' => 'Risposta errata', 'Your card details have been updated.' => 'Carta di Credito aggiornata correttamente.', 'Your cart is empty. Click %shere%s to continue shopping.' => 'Carrello vuoto. Clicca %squi%s per continuare con gli acquisti.', 'Your content on Amazon S3 should not be public. Please restrict public access to your files on Amazon S3 side and ensure you can not access it directly from Amazon S3. aMember use Access Key and Secret Key to generate links with authentication token for users to provide access them to your content on Amazon S3.' => 'Your content on Amazon S3 should not be public. Please restrict public access to your files on Amazon S3 side and ensure you can not access it directly from Amazon S3. aMember use Access Key and Secret Key to generate links with authentication token for users to provide access them to your content on Amazon S3.', 'Your download will start shortly. Click %s this link %s if you don\'t want to wait any longer...' => 'Il Download partirà a breve. Clicca %s questo link %s se non vuoi attendere oltre...', 'Your password has been changed successfully. You can %slogin to your account%s with new password.' => 'Password cambiata correttamente. Ora puoi %saccedere al tuo account%s con la nuova password.', 'Your password has been e-mailed to you. Please check your mailbox' => 'Password inviata alla tua email. Controlla la tua casella di posta', 'Your password is too long' => 'La tua Password è troppo lunga', 'Your payment has been successfully processed.' => 'Il tuo Pagamento è stato effettuato correttamente.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Il tuo pagamento non è ancora stato confermato dal sistema. Ci possono volere alcuni minuti per ricevere la conferma.', 'Your profile has been updated successfully' => 'profilo aggiornato correttamente', 'Your sales domain in justclick eg. username.justclick.ru' => 'Your sales domain in justclick eg. username.justclick.ru', 'Your subject is too verbose' => 'Il campo oggetto è troppo lungo', 'Your subscription does not allow access to this media' => 'La tua iscrizione non ti permette l\'accesso a questo media', 'Your subscription has been successfully processed.' => 'La tua iscrizione è stata processata correttamente.', 'Your upgrade is being processed please wait' => 'Sto processando il tuo Upgrade', 'ZIP' => 'CAP', 'ZIP Code' => 'CAP', 'Zip' => 'Cap', 'Zipcode' => 'CAP/ZIP', '[Select country]' => '[Seleziona Nazione]', '[Select state]' => '[Seleziona Provincia]', '_default_locale' => 'it', 'aMember Payment Process' => 'Processo Pagamento aMember', 'aMember Root URL' => 'URL installazione aMember', 'accepts all major credit cards' => 'accetta le principali Carte di Credito', 'add access to selected product even if user choose 0 donation amount' => 'dai accesso al prodotto selezionato anche se l\'utente non ha donato nulla', 'added between %s and %s' => 'aggiunto tra %s e %s', 'admin' => 'amministratore', 'affiliate <-> user relation is expired (%saccording your settings%s User-Affiliate Relation Lifetime is %d day(s)), no commissions will be added for new payments' => 'affiliato <-> la relazione con l\'utente è scaduta (%sin base alle impostazioni la%s Relazione Utente-Affiliato è %d giorni, non verrà aggiunta nessuna commissione hai nuovi pagamenti', 'affiliate program commissions' => 'commissioni programma di affiliazione', 'after completing order, voucher will be sent to specified address' => 'dopo aver completato l\'ordine, verrà spedito il Voucher Regalo all\'indirizzo specificato', 'ago' => 'fa', 'all requests will be added to %sLogs%s, useful if something is going wrong' => 'all requests will be added to %sLogs%s, useful if something is going wrong', 'any product' => 'qualsiasi prodotto', 'as chosen on signup page' => 'come scelto nel modulo d\'ordine', 'assigned to usergroups [%s]' => 'assegnato ai Gruppi [%s]', 'back to full report' => 'torna al report completo', 'banned' => 'bannato', 'begins' => 'inizia', 'cancel' => 'annulla iscrizione', 'card declined' => 'carta non accettata', 'check box to use points and get discount' => 'spunta qui per usare i Punti e avere uno sconto', 'check future subscriptions too' => 'controlla anche le iscrizioni future', 'check it if you want to gift subscription on this product' => 'spunta qui se vuoi iscriverti agli omaggi su questo prodotto', 'choose a version' => 'scegli una versione', 'click to see password' => 'clicca per vedere la password', 'click to upload' => 'clicca per caricare', 'commission found by next rules' => 'comissione trovata dalle regole che seguono', 'configure' => 'impostazioni', 'count of all invoices by theme' => 'numero di Ricevute per Tema', 'count of non invoices by theme' => 'numero di non Ricevute per Tema', 'count of paid invoices by signup form' => 'numero di Ricevute pagate da modulo d\'ordine', 'count of paid invoices by theme' => 'numero di Ricevute pagate per Tema', 'day' => 'giorno', 'days' => 'giorni', 'delivery confirmation' => 'conferma di spedizione', 'different currency products' => 'prodotti con valute diverse', 'different rebill times subscriptions' => 'abbonamenti con rinnovi diversi', 'different the first period subscriptions' => '"primo periodo di inscrizione" diversi', 'different the second period subscriptions' => '"secondo periodo di inscrizione" diversi', 'disable' => 'disabilita', 'download' => 'scarica', 'email' => 'email', 'email will contain this sentence' => 'l\'email conterrà questa frase', 'empty - use global setting if 0 - without limit' => 'empty - use global setting if 0 - without limit', 'expiration' => 'scadenza', 'expires' => 'scade', 'filter' => 'filtra', 'filtered' => 'guarda tutti', 'for affiliate commission payouts' => 'per ricevere le commissioni', 'for example: 1111-2222-3333-4444' => 'per esempio: 1111-2222-3333-4444', 'for example: 1111222233334444' => 'per esempio: 1111222233334444', 'free' => 'gratis', 'generate' => 'genera', 'has all values selected' => 'ha tutti i valori selezionati', 'has not used payment system %s' => 'non ha usato sistema di pagamento %s', 'has used payment system %s' => 'ha usato sistema di pagamento %s', 'have invoice for %s that canceled between %s and %s' => 'ha ricevuta per %s cancellata tra %s e %s', 'have no active subscriptions to %s' => 'non ha iscrizione attiva a %s', 'have payment for %s that made between %s and %s' => 'ha pagato %s tra %s e %s', 'have subscription for %s that expire between %s and %s' => 'have subscription for %s that expire between %s and %s', 'have subscription for %s between %s and %s' => 'è iscritto a %s tra %s e %s', 'have subscription for %s for date %s ' => 'è iscritto a %s in data %s ', 'hide if logged-in' => 'nascondi se loggato', 'hrs' => 'ore', 'if not specified, voucher will be sent to your email' => 'se non specificato, il Voucher regalo verrà spedito alla tua email', 'including pending records' => 'inclusi utenti in attesa', 'internal error, please repeat payment later' => 'errore interno, per favore riprova più tardi', 'ip' => 'IP', 'just now' => 'poco fa', 'labels' => 'etichette', 'last signin between %s and %s' => 'ultimo accesso tra %s e %s', 'limit amount of subscription for this product per user, keep empty if you do not want to limit amount of subscriptions' => 'limita il numero di acqusiti di questo prodotto per utente, lascia vuoto per non impostare limiti', 'limit amount of subscription for this product, keep empty if you do not want to limit amount of subscriptions' => 'limita il numero di acqusiti di questo prodotto, lascia vuoto per non impostare limiti', 'lines skipped' => 'righe ignorate', 'login' => 'entra', 'min' => 'min', 'month' => 'mese', 'months' => 'mesi', 'more than' => 'più di', 'never signin' => 'mai fatto accesso', 'next rebill' => 'prossimo addebito', 'no records' => 'nessun risultato', 'number of active users per product' => 'numero di utenti attivi per prodotto', 'number of affiliate program clicks' => 'numero di click da affiliati', 'number of sales by affiliate' => 'numero di vendite di tutti gli affiliati', 'number of users per region' => 'numero di utenti per area geografica', 'of products' => 'dei prodotti', 'on %d-th day' => 'il %d° giorno', 'only First Name' => 'solo il Nome', 'only Last Name' => 'solo il Cognome', 'only files downloaded by registered users is taken to account' => 'vengono conteggiati solo i file scaricati da utenti registrati', 'or' => 'oppure', 'pay using credit card or PayPal' => 'paga usando la carta di credito o PayPal', 'pay using wire transfer or by sending offline check' => 'paga usando il bonifico bancario o inviando un assegno per posta', 'please select billing plan to add manual access to users added by demand' => 'seleziona il Piano di Pagamento per aggiungere l\'accesso manuale all\'utente creato su richiesta', 'preview' => 'anteprima', 'protected area' => 'area riservata', 'reCAPTCHA Theme' => 'Tema reCAPTCHA', 'records processed.' => 'risultati processati.', 'remaining' => 'rimanenti', 'report includes only user who did at least one payment' => 'il report include solo gli utenti che hanno almeno un pagamento', 'reset' => 'pulisci', 'return' => 'indietro', 'seconds' => 'secondi', 'separated by commas for several address, eg: 12.12.12.12,23.23.23.23,34.34.34.34 separated by hyphen for rage address, eg: 123.123.123.1-123.123.123.100 IMPORTANT: Do not use leading zero in IP address segments. For example this IP is incorrect: 127.000.000.001' => 'separated by commas for several address, eg: 12.12.12.12,23.23.23.23,34.34.34.34 separated by hyphen for rage address, eg: 123.123.123.1-123.123.123.100 IMPORTANT: Do not use leading zero in IP address segments. For example this IP is incorrect: 127.000.000.001', 'signature required' => 'firma richiesta', 'spent %s %s' => 'speso %s %s', 'start' => 'inizio', 'subscribed to newsletter lists #' => 'iscritto alle newsletter #', 'this field is required' => 'campo obbligatorio', 'trackable' => 'tracciabile', 'unsubscribe' => 'cancellati', 'upgrade' => 'aggiorna', 'use 4111-1111-1111-1111 for successful transaction' => 'usa 4111-1111-1111-1111 per una transazione riuscita', 'use this coupon' => 'usa questo Buono Sconto', 'used coupon %s' => 'Buono Sconto usato %s', 'username, e-mail or name contains string [%s]' => 'Nome Utente, Email o Nome contiene [%s]', 'what you entered when creating your account' => 'ciò che hai scritto quando hai creato il tuo account', 'year' => 'anno', 'years' => 'anni', 'you can upload your filese here' => 'puoi caricare i tuoi file qui', 'you have %d reward points collected' => 'hai collezionato %d Punti Premio', 'you were referred by %s' => 'sei stato presentato da %s', ); PK\:/22default/language/user/da.phpnu[ ' en evighed. ', ' from ' => ' fra ', ' to ' => ' til ', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '" %s "kan bestilles sammen med disse produkter / subscripton (er): %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '" %s "kan kun bestilles, hvis du er udløbet abonnement (er) for disse produkter: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '" %s "kan ikke bestilles, fordi du har aktivt abonnement (r) til: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '" %s "kan ikke bestilles, fordi du er udløbet abonnement (r) til: %s', '%d-Tier Affiliates Commission ' => '%d-Tier Affiliates Kommissionen ', '%d-th day' => '%d -th dag', '%s MySQL Hostname' => '%s MySQL Hostname', '%s MySQL Password' => '%s MySQL kodeord', '%s MySQL Username' => '%s MySQL brugernavn', '%s database and tables prefix' => '%s database og tabeller præfiks', 'API Authentication Information' => 'API Authentication Information', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Accepter Direkte betalinger handle betalinger på betalingssystem side (uden tilmelding til aMember først)', 'Access' => 'Adgang', 'Access Denied' => 'Adgang nægtet', 'Access Log' => 'Adgang Log', 'Access Permissions' => 'Adgangstilladelser', 'Actions' => 'Handlinger', 'Active' => 'Aktive', 'Active Resources' => 'Aktive ressourcer', 'Active Subscriptions' => 'Aktive Abonnementer', 'Active Users' => 'Aktive brugere', 'Active subusers' => 'Aktive subusers', 'Add "Like" button' => 'Tilføj "Like " knappen', 'Add New Notification Rule' => 'Tilføj ny meddelelse Rule', 'Add User' => 'Tilføj bruger', 'Add to Basket' => 'Føj til indkøbskurv', 'Add/Renew Subscription' => 'Tilføj / Forny abonnement', 'Added' => 'tilføjede', 'Additional Fields' => 'Yderligere felter', 'Address Info' => 'Adresse Info', 'Address Information' => 'Address Information', 'Admin' => 'Admin', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Admin Grupper aMember aldrig rører %s regnskaber assigned til følgende grupper. Dette beskytter %s regnskaber mod enhver aMember aktivitet', 'Admin Username' => 'Admin Brugernavn', 'Administrator' => 'Administrator', 'Advanced' => 'Avanceret', 'Advanced Search' => 'Avanceret søgning', 'Advertise our website to your friends and earn money' => 'Annoncer på vor hjemmeside for dine venner og tjen penge', 'Affiliate' => 'Affiliate', 'Affiliate Clicks' => 'Affiliate klik', 'Affiliate Id#' => 'Affiliate Id #', 'Affiliate Info' => 'Affiliate Info', 'Affiliate Payout - Paypal E-Mail address' => 'Affiliate Udbetaling - Paypal e-mail-adresse', 'Affiliate Payout Type' => 'Affiliate Udbetaling Type', 'Affiliate Program' => 'Affiliate Program', 'Affiliate Sales' => 'Affiliate Sales', 'Affiliate Signup Form' => 'Affiliate tilmeldingsformular', 'Affiliate info' => 'Affiliate info', 'Affiliate stats' => 'Affiliate statistik', 'Affiliates' => 'Affiliates', 'All' => 'Alle', 'All %s records on this page are selected' => 'Alle %s registreringer på denne side er valgt', 'All Affiliates' => 'Alle Affiliates', 'All Time' => 'Alle tider', 'All Users' => 'Alle brugere', 'All records' => 'Alle rekorder', 'Amazon S3 storage is not configured' => 'Amazon S3 storage er ikke konfigureret', 'Amount' => 'beløbet.', 'An Error has occurred' => 'Er opstået en fejl', 'An account with the same email already exists.' => 'En konto med samme e-mail findes allerede.', 'An error occurred while handling your payment.' => 'En fejl opstod under håndtering af din betaling.', 'An internal error happened in the script, please contact webmaster for details' => 'En intern fejl skete i scriptet, så kontakt webmaster for detaljer', 'Any Product' => 'Ethvert produkt', 'Any product' => 'Ethvert produkt', 'Api Key' => 'API-nøgle', 'Apply' => 'Anvend', 'Apply Filter' => 'Anvend filter', 'Attachments' => 'Vedhæftede', 'Authentication' => 'Authentication', 'Authentication problem, please contact website administrator' => 'Authentication problem, bedes du kontakte website administator', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Auto-Tilmeld brugerne til listen Når det bliver tilgængeligt for dem', 'Available Bricks (drag to left to add)' => 'Tilgængelige Bricks (træk til venstre for at tilføje)', 'Available Credits' => 'Tilgængelige Credits', 'Awaiting Admin Response' => 'Afventer Admin svar', 'Awaiting User Response' => 'Afventer Bruger Reaktion', 'Back' => 'Tilbage', 'Bank Identification' => 'Bank Identifikation', 'Bank Name' => 'Bank Name', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Banned Grupper aMember aldrig rører %s regnskaber assigned til følgende grupper. Dette beskytter %s regnskaber mod enhver aMember aktivitet', 'Banners and Links' => 'Bannere og links', 'Banners and Text Links' => 'Administrer Bannere og links', 'Begin Date' => 'Begynd Dato', 'Both Affiliate and member' => 'Både Affiliate og medlem', 'CC Demo' => 'CC Demo', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF beskyttelse error - formular skal indsendes inden %d minutter efter visning, skal du gentage', 'Can view/edit customer Credit Card information and rebills' => 'Kan se / redigere kunde-kreditkortoplysninger og genfakture', 'Cancel' => 'Annullér', 'Cancel Subscription' => 'Annuller abonnement', 'Cancelled' => 'Aflyst', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Kan ikke bruge gratis betaling plugin med det produkt, som koster mere end 0,0', 'Cannot validate VAT Id, please try again' => 'Kan ikke validere moms Id, prøv igen', 'Category' => 'Kategori', 'Change' => 'Skift', 'Change Password' => 'Skift adgangskode', 'Change Password/Edit Profile' => 'Skift adgangskode / Edit Profile', 'Change Username' => 'Skift brugernavn', 'Change payout info' => 'Skift udbetaling info', 'Checkout' => 'Til kassen', 'Checkout error: ' => 'Checkout fejl: ', 'Choose a Password must be %d or more characters' => 'Vælg en adgangskode must være %d eller flere tegn', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Vælg et brugernavn it skal være %d eller flere tegn may kun indeholde bogstaver, tal og understregninger', 'City' => 'By', 'Click button to continue' => 'Klik på knappen for at fortsætte', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Klik her, hvis du ikke ønsker at vente længere (eller hvis din browser ikke automatisk sende dig).', 'Click to Edit' => 'Klik for at redigere', 'Clicks' => 'Klik', 'Clicks/Sales Statistics' => 'Affiliate Klik / salgsstatistikker', 'Close' => 'Luk', 'Close Ticket' => 'Luk billet', 'Closed' => 'Lukket', 'Code' => 'Kode', 'Comment' => 'Kommentar:', 'Comment for admin reference' => 'Kommentar for admin henvisning', 'Commission' => 'Gebyr', 'Commissions' => 'Kommissioner', 'Configuration' => 'Konfiguration', 'Configured Tax Values' => 'Konfigurerede skattemæssige værdier', 'Confirm New Password' => 'Bekræft ny adgangskode', 'Confirm Password' => 'Bekræft adgangskode', 'Confirm Payment' => 'Bekræft Betaling', 'Confirm Your E-Mail Address' => 'Bekræfte din e-mail adresse', 'Confirm Your Password' => 'Bekræft din adgangskode', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Bekræftelse link er blevet sendt til din e-mail-adresse. Kontrollér din postkasse. Hvis du ikke har modtaget e-mail within 5 minutter, skal du kontrollere også \'Spam\' mappe - vores message kan kvalificeres som spam ved en fejltagelse.', 'Content' => 'Indhold', 'Continue' => 'Fortsæt', 'Conversation' => 'samtale ', 'Copy of' => 'Kopi af', 'Count of signups' => 'Optælling af tilmeldinger', 'Count of user signups' => 'Tæl til brugernes tilmeldinger', 'Country' => 'Land', 'Coupon' => 'Kupon', 'Coupon Code' => 'Kuponkode', 'Coupon Discount' => 'Kuponkode', 'Coupon code disabled' => 'Kuponkode deaktiveret', 'Coupon code expired' => 'Kuponkode udløbet', 'Coupon is not yet active' => 'Kupon er endnu ikke er aktiv', 'Coupon usage limit exceeded' => 'Kupon brugsgrænse overskredet', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Opret aMember Brugere af efterspørgslen silently skabe kunde i aMember hvis user forsøger at logge ind aMember med Den samme brugernavn og password som for %s', 'Credit Card Code' => 'Kreditkortkode', 'Credit Card Info' => 'Kreditkort Info', 'Credit Card Number' => 'Kreditkortnummer', 'Credit Card Rebills' => 'Credit Card Rebills', 'Credit Cards' => 'Kreditkort', 'Credits' => 'Credits', 'Currency' => 'Valuta', 'Currency Exchange Rates' => 'Valutakurser', 'Current password entered incorrectly, please try again' => 'Nuværende adgangskode indtastes forkert, prøv igen', 'Custom Commission' => 'Brugerdefineret Kommissionen', 'Customer account has been automatically locked.' => 'Kunde konto er blevet låst automatisk.', 'Customize' => 'Tilpas', 'DONE' => 'Ok', 'Dashboard' => 'Instrumentbræt', 'Data Integrity Code' => 'Dataintegritetskode', 'Date' => 'Dato', 'Date and time of payment: %s' => 'Dato og tidspunkt for betaling: %s', 'Date must be in format %s' => 'Datoen skal være i formatet %s', 'Date/Time' => 'Dato / tid', 'Date: ' => 'Dato: ', 'Day' => 'Dag', 'Days' => 'dage', 'Deactivate Student' => 'Deaktiver Student', 'Deactivate User' => 'Deaktiver Bruger', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Standard Level default niveau - brugeren tilbage til dette adgangsniveau Hvis ingen aktive abonnementer findes (for eksempel alle abonnementer udløbet)', 'Delete' => 'Slet', 'Delete %s' => 'Slet %s', 'Description' => 'Beskrivelse', 'Disable online VAT Id Validation' => 'Deaktiver online moms Id Validation', 'Disabled' => 'Deaktiveret', 'Discard' => 'Kassér', 'Discount' => 'Rabat', 'Display Type' => 'Skærmtype', 'Display in 2 rows' => 'Visning i 2 rækker', 'Do not add to Login Form' => 'Må ikke tilføje til Login Form', 'Do not add to Signup Form' => 'Må ikke tilføje til tilmeldingsformular', 'Do you really want to %s %s %s records' => 'Vil du virkelig ønsker at %s %s %s records', 'Do you really want to %s?' => 'Vil du virkelig ønsker at %s ?', 'Do you really want to cancel subscription?' => 'Vil du virkelig ønsker at annullere abonnement?', 'Do you really want to delete record?' => 'Vil du virkelig ønsker at slette post?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Vil du virkelig ønsker at afmelde %s periodiske meddelelser?', 'Done' => 'Udført', 'Download' => 'Download', 'Download limit exceeded for this file' => 'Hent overskredet for denne fil', 'Downloaded on your own server' => 'Downloaded på din egen server', 'E-Mail' => '*E-mail:', 'E-Mail Address' => 'E-mail adresse', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'E-mail-adresse og e-mail-adresse Bekræftelses er forskellige. Venligst indtaste både', 'E-Mail Format' => 'E-mail-format', 'E-Mail Messages' => 'E-mail-meddelelser', 'E-Mail Verification' => 'E-Mail Verifikation', 'EU VAT' => 'EU-moms', 'EU VAT ID: ' => 'EU moms-id: ', 'EU VAT Id (optional)' => 'EU-moms-ID (valgfrit)', 'Edit' => 'Rediger', 'Edit %s' => 'Rediger %s', 'Edit Brick Labels' => 'Rediger Brick Labels', 'Edit E-Mail Template' => 'Rediger e-mail skabelon', 'Email' => 'E-mail', 'Email Subject' => 'Email Emne', 'Email admin regarding account sharing' => 'E-mail admin om konto deling', 'Email user regarding account sharing' => 'E-mail bruger hensyn konto deling', 'Empty response from Sagepay server' => 'Tomt svar fra SagePay server', 'Enabled Modules' => 'Aktiverede moduler', 'End' => 'End', 'End Date' => 'Slutdato', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Nyd dit medlemskab. Til login, så klik her %s Login %s', 'Enter coupon code' => 'Indtast kuponkode', 'Error 404 - Not Found' => 'Fejl 404 - Ikke fundet', 'Error : upload folder [%s] does not exists' => 'Fejl: upload mappe [ %s ] ikke eksisterer', 'Error happened during transaction handling. Please contact website administrator' => 'Fejl skete under transaktionen håndtering. Kontakt venligst hjemmesiden administrator', 'European (A4)' => 'Europæisk (A4)', 'Exact' => 'Præcis. ', 'Expire Date' => 'Udløbsdato', 'Expired' => 'Udløbet', 'Expired Users' => 'Udløbne Brugere', 'Expires' => 'Udløber', 'Export' => 'Eksporter', 'Export Format' => 'Eksportformat', 'FaceBook App ID' => 'Facebook app-id', 'FaceBook Application' => 'Facebook applikation', 'Facebook App Secret' => 'Facebook App Secret', 'Features' => 'Funktioner', 'Field' => 'Field', 'Field Type' => 'Felttype', 'Field Updated' => 'Field Opdateret', 'Fields To Display' => 'Felter der skal vises', 'Fields To Export' => 'Felter du vil eksportere', 'Fieldset' => 'Fieldset', 'Fieldset title' => 'Fieldset titel', 'File' => 'Fil', 'File Downloads' => 'File Downloads', 'File Storage' => 'File Storage', 'Filename' => 'filnavn', 'Files' => 'Filer', 'Files uploaded via aMember web interface' => 'Filer uploadet via aMember web interface', 'Filter' => 'Filtre', 'First & Last Name' => 'First & Last Name', 'First Name' => 'Fornavn', 'Folder %s (%s)' => 'Folder %s ( %s )', 'Folders' => 'Mapper', 'Form Page Break' => 'Form sideskift', 'Free' => 'Gratis', 'Free Access' => 'Gratis adgang', 'From' => 'Fra', 'Get Password' => 'Få kodeord', 'Global Commission' => 'Globale Kommission', 'Global Tax' => 'Global Tax', 'Groups' => 'Grupper', 'HTML Code that will be displayed' => 'HTML-kode, der vil blive vist', 'HTML Message' => 'HTML Message', 'HTML text' => 'HTML-teksten', 'Having Active Subscription To:' => 'Under Aktiv abonnement på:', 'Having Expired Subscription To:' => 'Efter Udløbet abonnement på:', 'Helpdesk' => 'Helpdesk', 'Hide do not display this item link in members area' => 'Hide Vil ikke vise dette element link i medlemmer område', 'Hosted at Activecampaing\'s server' => 'Hosted hos Activecampaing server', 'Housenumber' => 'Husnummer', 'IP Address' => 'IP-adresse', 'If you already have an account on our website, please %slog in%s to continue' => 'Hvis du allerede har en konto på vores hjemmeside, så %s login %s for at fortsætte', 'If you are a registered member, please %slogin%s' => 'Hvis du er registreret som medlem, skal du %s login %s', 'If you are not registered yet, please %ssignup%s' => 'Hvis du ikke er registreret endnu, venligst %sopret dig%s', 'Income Report - payments minus refunds' => 'Indkomst Report - betalinger minus refusioner', 'Incorrect Parent Affiliate ID' => 'Forkert Parent Affiliate ID', 'Integer Value' => 'Heltalsværdi', 'Integer value required' => 'Integer ønskede værdi', 'Integration' => 'Integration', 'Integrations' => 'Integrationer', 'Internal Error' => 'Intern fejl', 'Invalid Credit Card Number' => 'Ugyldigt kreditkortnummer', 'Invalid Expiration Date - Month' => 'Ugyldig Udløbsdato - Måned', 'Invalid Expiration Date - Year' => 'Ugyldig Udløbsdato - År', 'Invalid Issue Number' => 'Ugyldigt Issue nummer', 'Invalid VAT Id, please try again' => 'Ugyldig moms Id, prøv igen', 'Invoice' => 'fakturaen.', 'Invoice Number: ' => 'Fakturanummer: ', 'Invoice not found' => 'Faktura ikke fundet', 'Is Locked' => 'Låses', 'Is Paid?' => 'Er betalt?', 'Is Disabled?' => 'Er handicappet?', 'Item' => 'Vare', 'Label' => 'Mærkat', 'Language' => 'Sprog', 'Last 14 Days' => 'Sidste 14 dage', 'Last 30 Days' => 'Sidste 30 dage', 'Last 7 Days' => 'Sidste 7 dage', 'Last Business Week (Mon-Fri)' => 'Sidste arbejdsuge (man-fre)', 'Last Messages in Helpdesk' => 'Sidste Meddelelser i Helpdesk', 'Last Month' => 'Sidste måned', 'Last Name' => 'Efternavn', 'Last Week (Mon-Sun)' => 'Sidste uge (man-søn)', 'Last Week (Sun-Sat)' => 'Sidste uge (Sun-lør)', 'Leads' => 'Leads', 'License Key' => 'Licens Nøglen', 'Lifetime' => 'Levetid', 'Like Url' => 'Ligesom Url', 'Link' => 'Link', 'Links' => 'Links', 'Live Edit %s' => 'Levende Rediger %s', 'Loading' => 'Indlæser...', 'Log In' => 'Log på', 'Log all API Requests' => 'Log alle API Anmodninger', 'Login' => 'Login', 'Login as User' => 'Login som bruger', 'Logout' => 'Log ud', 'Lost Password Sending Error' => 'Glemt adgangskode afsendelsesfejl', 'Lost Password Sent' => 'Glemt adgangskode sendt', 'Lost password?' => 'Glemt adgangskode', 'Mail Queue' => 'Mail Queue', 'Make Payment' => 'Foretag betaling', 'Manage Newsletters' => 'Administrer Nyhedsbreve', 'Marketing Materials' => 'Marketing Materials', 'Membership Type' => 'Medlemskab Type', 'Merchant Key' => 'Sælgernøgle', 'Merchant Secret' => 'Sælger Hemlighed', 'Message' => 'Besked', 'Message can not be empty' => 'Besked kan ikke være tom', 'Month' => 'Måned', 'Months' => 'måneder. ', 'Multiplier' => 'Multiplikator', 'My Country' => 'Mit land', 'Name' => 'Navn', 'Never' => 'Aldrig', 'New' => 'Nyhed', 'New %s' => 'Nye %s', 'New Password' => 'Ny adgangskode', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Ny adgangskode Du kan vælge ny adgangskode her eller holde det uændret must være %d eller flere tegn', 'Newsletter' => 'Nyhedsbrev', 'Newsletter Subscriptions' => 'Nyhedsbrev Abonnementer', 'Next' => 'Næste', 'No' => 'Nej', 'No commissions on this date' => 'Ingen provision på denne dato', 'No coupons found with such coupon code' => 'Ingen kuponer fundet med sådan kuponkode', 'No items selected for purchase' => 'Ingen varer udvalgt til køb', 'No records found' => 'Ingen poster fundet', 'No, cancel' => 'Nej, annullere', 'No, keep me subscribed' => 'Nej, hold mig tegnede', 'No, please keep me subscribed' => 'Nej, skal du holde mig tegnede', 'Not Approved Affiliates' => 'Ikke godkendt Affiliates', 'Not Selected' => 'Ikke valgt', 'Not registered yet?' => 'Ikke registreret endnu?', 'Number of Messages to display' => 'Antal beskeder, der vises', 'Numeric Value' => 'Numerisk værdi', 'Numeric value required' => 'Numerisk ønskede værdi', 'Offline Payment' => 'Offline Betaling', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'Når plugin konfigurationen er færdig på denne side, så glem ikke at tilføje a rekord på %s aMember CP -> Beskyt Content -> Integrationer %s side', 'Only Affiliate %s(rarely used)%s' => 'Kun Affiliate %s (sjældent brugt) %s', 'Order reference: %s' => 'Bestillingsnummer: %s', 'Other' => 'Andet', 'Pages' => 'Pages', 'Password' => 'Adgangskode', 'Password and Password Confirmation are different. Please reenter both' => 'Password og adgangskode Bekræftelse er forskellige. Venligst indtaste både', 'Password must contain at least %d letters or digits' => 'Adgangskoden skal indeholde mindst %d bogstaver eller tal', 'Passwords do not match' => 'Adgangskoderne stemmer ikke overens', 'Path to %s' => 'Sti til %s', 'Path to %s Folder' => 'Path to %s mappe', 'Payanyway plugin does not support recurring billing!' => 'Payanyway plugin understøtter ikke tilbagevendende fakturering!', 'Payment' => 'Betaling', 'Payment Error' => 'Betaling Fejl', 'Payment Failed' => 'Betaling mislykkedes', 'Payment System' => 'Betaling System', 'Payment System Description' => 'Betaling System beskrivelse', 'Payment System Title' => 'Betaling System Title', 'Payment error: ' => 'Betaling fejl: ', 'Payment failed' => 'Betaling mislykkedes', 'Payment is already processed, please go to %sMembership page%s' => 'Betalingen er allerede behandlet, kan du gå til %s Medlemskab side%s', 'Payments' => 'Udbetalinger', 'Payments History' => 'Betalinger History', 'Payments by New vs Existing members' => 'Betaling af New vs Eksisterende medlemmer', 'Payments by payment system breakdown' => 'Betaling med betaling systemnedbrud', 'Payments by products breakdown' => 'Betaling med produkter opdeling', 'Payments from existing customers' => 'Udbetalinger fra eksisterende kunder', 'Payments from new customers' => 'Udbetalinger fra nye kunder', 'Payments total' => 'Betalinger I alt', 'Payout Method' => 'Udbetaling Method', 'Payouts' => 'Udbetalinger', 'Pending' => 'Afventer', 'Pending Invoices' => 'Ventende Fakturaer', 'Pending subusers' => 'Ventende subusers', 'Period' => 'Punktum.', 'Period must be in interval 1-24 months' => 'Periode skal være i intervallet 1-24 måneder', 'Period must be in interval 1-5 years' => 'Periode skal være i intervallet 1-5 år', 'Period must be in interval 1-90 days' => 'Periode skal være i intervallet 1-90 dage', 'Personal Content' => 'Personligt indhold', 'Phone' => 'Telefon', 'Phone Number' => 'Telefon:', 'Plain-Text Message' => 'Plain-Text Message', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Du skal %s login %s til din eksisterende konto. %s Hvis du ikke har fuldført betaling, vil du være i stand til at fuldføre det efter login', 'Please Select' => 'Vælg venligst', 'Please agree to User Agreement' => 'Accepter brugeraftale', 'Please choose' => 'Vælg venligst', 'Please choose a Credit Card Type' => 'Vælg et kreditkort Type', 'Please choose a membership type' => 'Vælg en type medlemskab', 'Please choose a payment system' => 'Vælg et betalingssystem', 'Please choose state' => 'Vælg stat', 'Please enter %s' => 'Indtast venligst %s', 'Please enter City' => 'Indtast venligst by', 'Please enter Country' => 'Angiv land', 'Please enter Credit Card Code' => 'Angiv Kreditkortkode', 'Please enter Credit Card Number' => 'Angiv Kreditkortnummer', 'Please enter Password' => 'Angiv kodeord', 'Please enter State' => 'Angiv stat', 'Please enter Street Address' => 'Angiv Gade', 'Please enter ZIP code' => 'Indtast venligst postnummer', 'Please enter a valid e-mail address' => 'Angiv en gyldig e-mail-adresse', 'Please enter coupon code' => 'Angiv kuponkode', 'Please enter credit card holder first name' => 'Angiv kreditkort holder fornavn', 'Please enter credit card holder last name' => 'Angiv kreditkort holder efternavn', 'Please enter credit card holder name' => 'Angiv kreditkort holder navn', 'Please enter housenumber' => 'Angiv husnummer', 'Please enter phone number' => 'Indtast venligst telefonnummer', 'Please enter valid Email' => 'Indtast venligst gyldig e-mail', 'Please enter valid Username. It must contain at least %d characters' => 'Angiv gyldig brugernavn. Den skal indeholde mindst %d tegn', 'Please enter your First Name' => 'Angiv fornavn', 'Please enter your Last Name' => 'Indtast venligst dit efternavn', 'Please enter your current password for validation' => 'Indtast din nuværende adgangskode for validering', 'Please login' => 'Log venligst ind', 'Please select' => 'Vælg venligst', 'Please select an item...' => 'Vælg en vare ...', 'Please select payment system for payment' => 'Vælg betalingssystem til betaling', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Brug venligst %sTilføj / Forny abonnement%s formular at bestille eller forny abonnementet.', 'Please wait %d seconds before next login attempt' => 'Vent venligst %d sekunder før næste login forsøg', 'Plugin' => 'Plugin', 'Plugin List Id' => 'Plugin Id', 'PostAffiliatePro Parent Affiliate ID' => 'PostAffiliatePro Parent Affiliate ID', 'PostAffiliatePro Referral ID' => 'PostAffiliatePro Henvisnings id', 'Prev' => 'Prev', 'Preview' => 'Eksempel', 'Price' => 'Pris', 'Processing your Transaction' => 'Behandling din Transaktion', 'Product' => 'Produkt', 'Product Categories' => 'Produktkategorier', 'Product Title' => 'Product Title', 'Product(s) to display' => 'Produkt (er) for at vise', 'Products' => 'produkterne.', 'Products keep empty to report all products' => 'Produkter keep tomme til at indberette alle produkter', 'Profile' => 'Rediger profil', 'Profile update transaction failed' => 'Profil update transaktion mislykkedes', 'Purchased Credits' => 'Købte Credits', 'Qty' => 'Antal', 'Quantity' => 'Mængde', 'Quick Order' => 'Kvikordre', 'Re-Open Ticket' => 'Re-Open Ticket', 'Read-only' => 'Skrivebeskyttet.', 'Record' => 'Optag', 'Record Type' => 'Posttype', 'Records that match all these conditions' => 'Records, der matcher alle disse betingelser', 'Recurring' => 'Tilbagevendende', 'Reference number is:' => 'Referencenummer er:', 'Referer' => 'Referer', 'Referred Affiliate' => 'Henvist Affiliate', 'Refresh' => 'Opdatér', 'Refresh 3-rd party lists' => 'Refresh 3-rd partilister', 'Refund' => 'Refusion', 'Refund Amount' => 'Refund Beløb', 'Refunded' => 'Refunderet', 'Regional Tax' => 'Regional Tax', 'Register' => 'Registrer', 'Remote API Permissions' => 'Fjernbetjening API Tilladelser', 'Remove' => 'Fjern', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Fjern Brugere Når brugerpost fjernet fra aMember must den tilhørende record fjernes fra %s', 'Remove user' => 'Fjern bruger', 'Reply' => 'Svar', 'Required' => '- Påkrævet', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Prøv igen om manglende Hvis tilbagevendende fakturering er slået fejl, aMember kan gentage det efter flere dage, og forlænge kundens abonnement for denne periode Indtast antal dage til at gentage fakturering forsøg', 'Return' => 'kommer tilbage. ', 'Return and try again' => 'Retur og prøv igen', 'Review/Pay Commissions' => 'Anmeldelse / Pay Affiliate Kommissionen', 'Run Report' => 'Kør rapport', 'Running %s' => 'Kører %s', 'Save' => 'Save (Gem)', 'Save Profile' => 'Gem profil', 'Search' => 'Søg', 'Search Products' => 'Søg blandt produkter', 'Security code is invalid' => 'Sikkerhed kode er ugyldig', 'Select a condition to add into search' => 'Vælg en betingelse for at tilføje til søgning', 'Select all %s records matching your search' => 'Vælg alle %s poster, der matcher din søgning', 'Send' => 'Send', 'Send Cancel Notifications to User' => 'Send Annuller meddelelser til Bruger', 'Session expired, please enter username and password again' => 'Sessionen er udløbet, skal du indtaste brugernavn og kodeord igen', 'Settings' => 'Indstillinger', 'Shipping' => 'Forsendelse', 'Shopping Cart' => 'kurv', 'Sign-up' => 'Tilmeld dig', 'Signup Form' => 'Tilmeldingsformular', 'Signup here' => 'Tilmeld dig her', 'Signup/payment functions are disabled for this user account' => 'Tilmelding / betaling funktioner er deaktiveret for denne brugerkonto', 'Simple Search Users' => 'Simple Search Brugere', 'Site Title' => 'Site Title', 'Skip First Line' => 'Spring First Line', 'Snippets' => 'Snippets', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Beklager, det er umuligt at bruge denne betalingsmetode for denne ordre. Vælg en anden betalingsmetode', 'Sorry, seems you have used wrong link' => 'Beklager, synes du har brugt forkert link', 'Source Code — Copy/Paste Into Your Website' => 'Source Code - Kopier / Sæt ind på din hjemmeside', 'Standard' => 'Standard', 'Start' => 'starter ', 'Start Date' => 'Startdato', 'State' => 'Tilstand', 'Status' => 'Status', 'Street' => 'Street.', 'Street Address' => 'Gade', 'SubUsers Count (keep zero for non-reseller products)' => 'SubUsers Count (holde nul for ikke-forhandler produkter)', 'SubUsers Product (keep empty for non-reseller products)' => 'SubUsers Product (holde tomme for ikke-forhandler produkter)', 'Subject' => 'Emne', 'Subject can not be empty' => 'Emne kan ikke være tom', 'Subscribe And Pay' => 'Abonnér og betale', 'Subscribe to Site Newsletters' => 'Abonner på nyhedsbreve', 'Subscribed To Newsletters' => 'Tegnet til nyhedsbreve', 'Subscribers' => 'Abonnenter', 'Subscription Terms' => 'Abonnementsvilkår', 'Subscription/Product Title' => 'Abonnement / Product Title', 'Subtotal' => 'Samlede direkte omkostninger', 'Subusers' => 'Subusers', 'Such affiliate ID exist' => 'En sådan affiliate ID eksisterer', 'Target URL' => 'Target URL', 'Tax' => 'Moms', 'Tax Amount' => 'Skat Beløb', 'Tax Id' => 'Skat Id', 'Tax Rate for example 18.5 (no percent sign)' => 'Skat for eksempel 18,5 (intet procenttegn)', 'Tax Title' => 'Skat Title', 'Tax Value' => 'Skat Value', 'Terms' => 'Vilkår', 'Test Mode' => 'Testtilstand', 'Test Settings' => 'Testindstillinger', 'Thank you for Signing up' => 'Tak for Tilmelding', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Tak! Din betaling er AFVENTENDE & Under Behandling. Vi vil opdatere dit abonnement, når din betaling er gennemført. Please stay tuned under denne proces. Det kan tage 12-24 timer. Du vil modtage e-mail-meddelelse om modtagelse af betaling.', 'The database has encountered a problem, please try again later.' => 'Databasen er stødt på et problem, prøv igen senere.', 'The password should be at least %d characters long' => 'Adgangskoden skal være på mindst %d tegn', 'The user name or password is incorrect' => 'Det brugernavn eller adgangskode er forkert', 'There are no confirmed payments for your account' => 'Der er ingen bekræftede betalinger for din konto', 'There are no form available for affiliate signup.' => 'Der er ingen formular til rådighed for affiliate tilmelding.', 'There are no products available for purchase. Please come back later.' => 'Der er ingen produkter til rådighed for køb. Kom tilbage senere.', 'This %s is blocked. Please contact site support to find out why' => 'Denne %s er blokeret. Kontakt venligst site support for at finde ud af, hvorfor', 'This Month' => 'Denne måned', 'This Week (Mon-Sun)' => 'Denne uge (man-søn)', 'This Week (Sun-Sat)' => 'Denne uge (Sun-lør)', 'This coupon belongs to another customer' => 'Denne kupon tilhører en anden kunde', 'This field is required' => 'Dette felt er påkrævet', 'This is a required field' => 'Dette er et obligatorisk felt', 'This page will be automatically refreshed within %s' => 'Denne side vil automatisk blive opdateret indenfor %s', 'This payment system could not handle payments in [%s] currency' => 'Denne betaling system kunne ikke håndtere betalinger i [ %s ] valuta', 'This payment system could not handle zero-total invoices' => 'Denne betaling system kunne ikke håndtere nul-total fakturaer', 'Thresehold Date' => 'Thresehold Dato', 'Ticket' => 'Billet', 'Ticket has been submited' => 'Billet er blevet FORELAGT', 'Tickets' => 'Billetter', 'Title' => 'Titel', 'To' => 'Til', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Hvis du vil tilføje felter i formularen, flytte post fra \'Tilgængelige Bricks "til" Form Bricks\'. For fjerne felter, flytte den tilbage til \'Tilgængelige Bricks\'. For gør form multi-side, indsæt \'PageSeparator-element på plads hvor du ønsker siden skal opdeles.', 'Today' => 'I dag', 'Total' => 'Total', 'Try again' => 'Prøv igen', 'Type' => 'Type', 'USA (Letter)' => 'USA (Letter)', 'Unable to delete this file as it is used for:' => 'Kan ikke slette denne fil, da den bruges til:', 'Unenroll Student' => 'Framelde dig igen Student', 'Unit Price' => 'Enhedspris', 'Unknown period unit: %s' => 'Ukendt periode enhed: %s', 'Unsubscribe' => 'Afmeld', 'Unsubscribe from all e-mail messages' => 'Afmeld fra alle e-mails', 'Unsubscribed' => 'Afmeldt', 'Unsubscription Confirmation' => 'Afmelding Bekræftelse', 'Update' => 'Opdater', 'Update Credit Card Info' => 'Opdater information om kreditkort', 'Updated' => 'Opdateret', 'Upgrade Subscription' => 'Opgrader Abonnement', 'Upload files using FTP client to [%s]' => 'Upload filer ved hjælp af FTP-klient til [ %s ]', 'Use Database Connection other than configured for aMember' => 'Brug databaseforbindelse andet end konfigureret til aMember', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Brug en anden MySQL Db Brug custom vært, bruger, password for %s database connectionUsually kan du lade dette umarkeret', 'Useful Links' => 'nyttige-links', 'User' => 'Bruger Training ', 'User Agreement' => 'Bruger-aftalen', 'User Groups' => 'Brugergrupper', 'User Info' => 'Bruger Info', 'User Search' => 'Bruger Søg', 'User is locked' => 'Bruger er låst', 'User is not approved' => 'Brugeren er ikke godkendt', 'User must provide' => 'Brugeren skal give', 'Username' => 'Brugernavn', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Brugernavn Du kan vælge nyt brugernavn her eller holde det uændret. Brugernavn skal være %d eller flere tegn i længden og kan Kun indeholde små bogstaver, tal og underscore', 'Username %s is already taken. Please choose another username' => 'Brugernavn %s er allerede taget. Vælg venligst et andet brugernavn', 'Username contains invalid characters - please use digits, letters or spaces' => 'Brugernavn indeholder ugyldige tegn - skal du bruge cifre, bogstaver eller mellemrum', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Brugernavn indeholder ugyldige tegn - skal du bruge tal og bogstaver', 'Username/Email' => 'E-mail-adresse eller brugernavn', 'Users subscribed to Newsletter Threads #' => 'Brugere, der abonnerer på Nyhedsbrev Tråde #', 'VAT Id' => 'Momsnr.', 'Validate E-Mail Address by sending e-mail message with code' => 'Valider E-mail adresse ved at sende e-mail med kode', 'Validation' => 'Validering', 'Version of script' => 'Version af script', 'Video' => 'Video', 'View Basket' => 'View Basket', 'Visit %sorder page%s to order additional subscriptions' => 'Besøg %s bestillingssiden %s for at bestille ekstra abonnementer', 'Week' => 'Uge', 'Wrong code or code expired - please start signup process again' => 'Forkert kode eller kode udløbet - begynde tilmeldingsprocessen igen', 'Wrong link - no id passed' => 'Forkert link - ingen id bestået', 'Wrong parameters, error #1253' => 'Forkerte parametre, fejl # 1253', 'Wrong password' => 'Forkert adgangskode', 'Wrong verification code' => 'Forkert bekræftelseskode', 'Wrongly signed URL, please contact site admin' => 'Fejlagtigt underskrevet webadresse, du bedes kontakte Kundeservice', 'Year' => 'år', 'Years' => 'år', 'Yes' => 'Ja', 'Yes, I want to cancel subscription' => 'Ja, jeg ønsker at annullere abonnement', 'Yes, continue' => 'Ja, fortsætter', 'Yes, unsubscribe' => 'Ja, afmeld', 'Yesterday' => 'i går. ', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Du er logget ind som %s . %s Logout %s til tilmelding som ny bruger.', 'You have %s%d ticket(s)%s that require your attention' => 'Du har %s %d billetter %s , der kræver din opmærksomhed', 'You have no access to %s' => 'Du har ikke adgang til %s', 'You have no active subscriptions' => 'Du har ingen aktive abonnementer', 'You have no enough permissions for this operation' => 'Du har ingen nok tilladelser til denne operation', 'You have no items in your basket - please add something to your basket before checkout' => 'Du har ingen varer i din kurv - du tilføje noget til din kurv før checkout', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'Du har for mange subusers tildelt denne konto. Du kan vælge at fjerne %d brugere fra din konto', 'You must be authorized to access this area' => 'Du skal have tilladelse til at få adgang til dette område', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Du skal indstille aMember CP -> Setup -> Avanceret -> Session Storage til »Standart PHP Sessions \'Dette er nødvendigt for at muliggøre Single Log mellem aMember og SilverStrype', 'Your Account Removal' => 'Din konto Removal', 'Your Basket' => 'Din indkøbskurv', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Din nuværende adgangskode Hvis du skifter adgangskode, kan du indtaste din nuværende adgangskode for validering', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Din e-mail adresse a bekræftelsesmail vil blive sendt til dig på denne adresse', 'Your General Affiliate Link' => 'Dit General Affiliate Link', 'Your Membership Information' => 'Dit Medlemskab Information', 'Your Payment is PENDING & Under Process' => 'Din betaling er AFVENTENDE & Under Behandling', 'Your Personal Downloads' => 'Dine personlige Downloads', 'Your Reseller Packages' => 'Din forhandler pakker', 'Your account has been automatically locked.' => 'Din konto er blevet låst automatisk.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Din konto er ikke godkendt endnu. Du får besked via e-mail, når administratoren gennemgå din konto og give adgang.', 'Your password is too long' => 'Din adgangskode er for lang', 'Your payment has been successfully processed.' => 'Din betaling er blevet behandlet.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Din betaling er endnu ikke bekræftet af betalingssystem. Det kan tage flere minutter at få bekræftelse af betalingen.', 'Your subject is too verbose' => 'Motivet er for ordrig', 'Your subscription has been successfully processed.' => 'Din tilmelding er blevet behandlet.', 'ZIP' => 'Postnummer', 'ZIP Code' => 'Postnummer', 'Zip' => 'Postnummer', '[Select country]' => '[Vælg land]', '[Select state]' => '[Vælg tilstand]', '_default_locale' => '_default_locale', 'admin' => 'admin', 'affiliate program commissions' => 'affiliate program provisioner', 'ago' => 'siden. ', 'banned' => 'forbudt', 'commission found by next rules' => 'Kommissionen fandt ved næste regler', 'days' => 'dage', 'email' => 'Email', 'expiration' => 'udløb', 'expires' => 'udløber', 'filtered' => 'filtreret', 'for affiliate commission payouts' => 'for affiliate provision udbetalinger', 'for example: 1111-2222-3333-4444' => 'for eksempel: 1111-2222-3333-4444', 'generate' => 'generere', 'hrs' => 'timer', 'ip' => 'ip', 'just now' => 'lige nu', 'link' => 'link', 'login' => 'Log ind', 'min' => 'min', 'month' => 'Måned', 'more than' => 'mere end', 'no records' => 'ingen optegnelser', 'number of affiliate program clicks' => 'Antallet af affiliate program klik', 'of products' => 'af produkter', 'on %d-th day' => 'på %d -ende dag', 'only First Name' => 'kun Fornavn', 'only Last Name' => 'kun Efternavn', 'or' => 'ELLER', 'pay using credit card or PayPal' => 'betale med kreditkort eller PayPal', 'pay using wire transfer or by sending offline check' => 'betale med bankoverførsel eller ved at sende offline kontrol', 'protected area' => 'Beskyttet område', 'return' => 'kommer tilbage. ', 'seconds' => 'sekunder', 'start' => 'starter ', 'use 4111-1111-1111-1111 for successful transaction' => 'anvende 4111-1111-1111-1111 for vellykket transaktion', ); PK\/G++default/language/user/ro.phpnu[ 'Pentru totdeauna', ' from ' => 'De la', ' to ' => 'Către', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" poate fi comandat doar cu aceste produse/abonamente: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" poate fi comandat doar dacă abonamentul pentru aceste produse a expirat %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" nu poate fi comandat deoarece aveți abonamente active la: : %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" nu poate fi comandat deoarece aveți abonamente expirate pentru: %s', '%d-Tier Affiliates Commission ' => 'Comision afiliați nivelul %d ', '%d-th day' => 'a %d-a zi', '%s MySQL Hostname' => 'Numele gazdei MySQL %s', '%s MySQL Password' => 'Parola MySQL %s', '%s MySQL Username' => 'Nume de utilizator MySQL %s', '%s database and tables prefix' => 'Baza de date %s și prefix tabele', 'API Authentication Information' => 'Informații de autentificare API', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Acceptați plăți directe Ocupati-vă de plățile efectuate în sistemul de plată (fără a fi înregistrat aMember)', 'Access' => 'Acces', 'Access Denied' => 'Acces respins', 'Access Log' => 'Istoric acces', 'Access Permissions' => 'Permisiuni de acces', 'Actions' => 'Acţiuni', 'Active' => 'Activ', 'Active Resources' => 'Resurse active', 'Active Subscriptions' => 'Abonamente active', 'Active Users' => 'Utilizatori activi', 'Active subusers' => 'Sub-utilizatori activi', 'Add "Like" button' => 'Adăugați butonul "Îmi place"', 'Add New Notification Rule' => 'Adăugați regulă nouă de notificare', 'Add User' => 'Adăugaţi utilizator', 'Add to Basket' => 'Adăugați în coșul de produse', 'Add/Renew Subscription' => 'Adăugați / reînnoiți abonamente', 'Added' => 'Adăugat', 'Additional Fields' => 'Câmpuri suplimentare', 'Address Info' => 'Informații adresă', 'Address Information' => 'Informații adresă', 'Admin' => 'Admin', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupuri administratori aMember nu atinge niciodată %s conturile Atribuite următoarele grupuri. Aceasta protejează %s conturile față de orice activitate aMember', 'Admin Username' => 'Numele de utilizator al administratorului', 'Administrator' => 'Administrator', 'Advanced' => 'Avansat', 'Advanced Search' => 'Căutare avansată', 'Advertise our website to your friends and earn money' => 'Recomandă site-ul nostru prietenilor tăi și câștigă comisioane', 'Affiliate' => 'Afiliat', 'Affiliate Clicks' => 'Click-uri afiliați', 'Affiliate Id#' => 'ID afiliat', 'Affiliate Info' => 'Info afiliați', 'Affiliate Payout - Paypal E-Mail address' => 'Plată afiliat - e-mail Paypal', 'Affiliate Payout Type' => 'Tipul de plată pentru afiliaţi', 'Affiliate Program' => 'Program afiliați', 'Affiliate Sales' => 'Vânzări afiliați', 'Affiliate Signup Form' => 'Formular de înscriere afiliat', 'Affiliate info' => 'Info afiliați', 'Affiliate stats' => 'Statistici afiliați', 'Affiliates' => 'Afiliaţi', 'All' => 'Toate', 'All %s records on this page are selected' => 'Toate înregistrările %s din această pagină sunt selectate', 'All Affiliates' => 'Toti membrii afiliaţi', 'All Time' => 'Tot timpul', 'All Users' => 'Toţi utilizatorii', 'All records' => 'Toate înregistrările', 'Amazon S3 storage is not configured' => 'Stocarea Amazon S3 nu este configurată', 'Amount' => 'Suma', 'An Error has occurred' => 'A apărut o eroare', 'An account with the same email already exists.' => 'Un cont cu aceeași adresă de email există deja', 'An error occurred while handling your payment.' => 'A apărut o eroare în timpul efectuării plății.', 'An internal error happened in the script, please contact webmaster for details' => 'A apărut o eroare în script, vă rugăm să contactați suportul pentru detalii', 'Any Product' => 'Orice produs', 'Any product' => 'Orice produs', 'Api Key' => 'Cheie API', 'Apply' => 'Aplicare', 'Apply Filter' => 'Aplicați filtrul', 'Attachments' => 'Atașamente', 'Authentication' => 'Autentificare', 'Authentication problem, please contact website administrator' => 'Problemă de autentificare, vă rugăm să contactați administratorul', 'Auto-Subscribe users to list once it becomes accessible for them' => 'Auto-înscriere pe lista utilizatorilor odată ce aceasta devine accesibilă pentru ei', 'Available Bricks (drag to left to add)' => 'Căsuțe disponibile (trageţi spre stânga pentru a adăuga)', 'Available Credits' => 'Credite disponibile', 'Awaiting Admin Response' => 'În curs de așteptare a răspunsului de la administrator', 'Awaiting User Response' => 'Așteaptă răspuns utilizator', 'Back' => 'Înapoi', 'Bank Identification' => 'Informațiile despre bancă', 'Bank Name' => 'Numele băncii', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Grupuri interzise aMember nu atinge niciodată %s conturile Atribuite următoarele grupuri. Aceasta protejează %s conturile față de orice activitate aMember', 'Banners and Links' => 'Bannere și link-uri', 'Banners and Text Links' => 'Gestionare banere și linkurile text', 'Begin Date' => 'Data de începere', 'Both Affiliate and member' => 'Atât afiliat cât și abonat', 'CC Demo' => 'CC demo', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF eroare de protecție - formularul trebuie să fie trimis în termen de %d minute de la afișare, vă rugăm să repetați', 'Can view/edit customer Credit Card information and rebills' => 'Poate vizualiza/edita informații card de credit și rambursări', 'Cancel' => 'Anulați', 'Cancel Subscription' => 'Anulați abonamentul', 'Cancelled' => 'Anulat', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Nu puteți folosi modulul de plată gratuită cu produse care costă mai mult de 0.0', 'Cannot validate VAT Id, please try again' => 'Codul fiscal nu poate fi validat, vă rugăm să încercați din nou', 'Category' => 'Categorie', 'Change' => 'Schimbați', 'Change Password' => 'Schimbați parola', 'Change Password/Edit Profile' => 'Schimbare parolă / Editare profil', 'Change Subscription' => 'Schimbarea de subscripţie', 'Change Username' => 'Schimbați numele de utilizator', 'Change payout info' => 'Modificați informațiile de plată', 'Checkout' => 'Plătiți', 'Checkout error: ' => 'Eroare la plată: ', 'Choose a Password must be %d or more characters' => 'Alegeți o parolă Trebuie să fie de %d sau mai multe caractere', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Alegeți un nume de utilizator Trebuie să fie de %d sau mai multe caractere în lungime Poate conține numai litere, numere și sublinieri', 'City' => 'Oraș', 'Click button to continue' => 'Faceţi clic pe buton pentru a continua', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Faceți clic aici dacă nu doriți să așteptați mai mult (sau în cazul în care navigatorul dumneavoastră nu vă redirecționează automat).', 'Click to Edit' => 'Clic pentru a edita', 'Clicks' => 'Click-uri', 'Clicks/Sales Statistics' => 'Click-uri afiliați / statistică vânzări', 'Close' => 'Închideți', 'Close Ticket' => 'Închideți tichet', 'Closed' => 'Închis', 'Code' => 'Cod', 'Comment' => 'Comentariu', 'Comment for admin reference' => 'Comentariu pentru administrator', 'Commission' => 'Comision', 'Commissions' => 'Comisioane', 'Configuration' => 'Configurație', 'Configured Tax Values' => 'Valori fiscale configurate', 'Confirm' => 'Confirmă', 'Confirm New Password' => 'Confirmati parola nouă', 'Confirm Password' => 'Confirmați parola', 'Confirm Payment' => 'Confirmați plata', 'Confirm Your E-Mail Address' => 'Confirmați adresa dumneavoastră de e-mail', 'Confirm Your Password' => 'Confirmaţi parola', 'Confirmation link has been sent to your e-mail address. Please check your mailbox. If you have not received e-mail within 5 minutes, please check also the \'Spam\' folder - our message may be classifed as spam by mistake.' => 'Link-ul de confirmare a fost trimis la adresa dumneavoastră de e-mail. Vă rugăm să verificați căsuța poștală. Dacă nu ați primit mesajul în termen de 5 minute, vă rugăm să verificați și folderul "spam" -  mesajul nostru poate fi clasificat ca spam din greșeală.', 'Content' => 'Conţinut', 'Continue' => 'Continuați', 'Conversation' => 'Conversaţie', 'Copy of' => 'Copie a', 'Count of signups' => 'Numărul de înscrieri', 'Count of user signups' => 'Numărul de înscrieri ale utilizatorilor', 'Country' => 'Ţara', 'Coupon' => 'Cupon', 'Coupon Code' => 'Codul cuponului', 'Coupon Discount' => 'Cupon de reducere', 'Coupon code disabled' => 'Codul cuponului este dezactivat', 'Coupon code expired' => 'Codul cuponului este expirat', 'Coupon is not yet active' => 'Cuponul nu este încă activ', 'Coupon usage limit exceeded' => 'Limita utilizare a cuponului a fost depășită', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Crearți utilizatori la cerere în mod silențios dacă cineva încearcă să se autentifice cu același nume de utilizator și parolă precum %s', 'Credit Card Code' => 'Codul cardului de credit', 'Credit Card Info' => 'Informații card de credit', 'Credit Card Number' => 'Numărul cardului de credit', 'Credit Card Rebills' => 'Rambursare card de credit', 'Credit Cards' => 'Carduri de credit', 'Credits' => 'Credite', 'Currency' => 'Monedă', 'Currency Exchange Rates' => 'Rata de schimb valutar', 'Current password entered incorrectly, please try again' => 'Parola actuală a fost introdusă incorect, vă rugăm să încercaţi din nou', 'Custom Commission' => 'Comision personalizat', 'Customer account has been automatically locked.' => 'Contul clientului a fost blocat automat.', 'Customize' => 'Personalizați', 'DONE' => 'Terminat', 'Dashboard' => 'Tabloul de Bord', 'Data Integrity Code' => 'Cod de integritate a datelor', 'Date' => 'Data', 'Date and time of payment: %s' => 'Data și ora efectuării plății: %s', 'Date must be in format %s' => 'Data trebuie să fie în formatul %s', 'Date/Time' => 'Dată / Oră', 'Date: ' => 'Data:', 'Day' => 'Ziua', 'Days' => 'Zile', 'Deactivate Student' => 'Dezactivare student', 'Deactivate User' => 'Dezactivare utilizator', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Nivelul implicit Nivelul implicit - resetare de utilizator la acest nivel de acces În cazul în care nu există abonamente active, (De exemplu, toate abonamentele au expirat)', 'Delete' => 'Ștergeți', 'Delete %s' => 'ștergeți %s', 'Description' => 'Descriere', 'Disable online VAT Id Validation' => 'Dezactivați validarea on-line codurilor fiscale (pt. TVA)', 'Disabled' => 'Dezactivat', 'Discard' => 'Renunţaţi', 'Discount' => 'Reducere', 'Display Type' => 'Tip de afișare', 'Display in 2 rows' => 'Afişează în 2 rânduri', 'Do not add to Login Form' => 'Nu adăugați la formularul de autentificare', 'Do not add to Signup Form' => 'Nu adăugați la formularul de înscriere', 'Do you really want to %s %s %s records' => 'Doriți cu adevărat să %s %s %s înregistrări', 'Do you really want to %s?' => 'Doriți cu adevărat să %s?', 'Do you really want to cancel subscription?' => 'Doriți cu adevărat să anulați abonamentul?', 'Do you really want to delete record?' => 'Doriți cu adevărat să ștergeți înregistrarea?', 'Do you really want to unsubscribe from %s periodical messages?' => 'Doriți cu adevărat să vă dezabonați de la mesajele %s periodice?', 'Done' => 'Terminat', 'Download' => 'Descarcă', 'Download limit exceeded for this file' => 'Limita de descărcare pentru acest fişier a fost depăşită', 'Downloaded on your own server' => 'Descărcat pe serverul propriu', 'E-Mail' => 'E-mail', 'E-Mail Address' => 'Adresă e-mail', 'E-Mail Address and E-Mail Address Confirmation are different. Please reenter both' => 'Adresele de e-mail introduse sunt diferite. Vă rugăm să le introduceți din nou.', 'E-Mail Format' => 'Formatul de e-mail', 'E-Mail Messages' => 'Mesaje e-mail', 'E-Mail Verification' => 'Verificare e-mail', 'EU VAT' => 'Cod fiscal din UE', 'EU VAT ID: ' => 'Codul fiscal european:', 'EU VAT Id (optional)' => 'Cosul fiscal european (opțional)', 'Edit' => 'Editează', 'Edit %s' => 'Editează %s', 'Edit Brick Labels' => 'Editați etichetele cărămizilor', 'Edit E-Mail Template' => 'Editare format e-mail', 'Email' => 'E-mail', 'Email Subject' => 'Subiect mesaj', 'Email admin regarding account sharing' => 'Trimite e-mail administratorului cu privire la distribuirea de cont', 'Email user regarding account sharing' => 'Trimite e-mail utilizatorului cu privire la distribuirea de cont', 'Empty response from Sagepay server' => 'Răspuns gol de la serverul Sagepay', 'Enabled Modules' => 'Module activate', 'End' => 'Sfârșit', 'End Date' => 'Dată de sfârșit', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Bucurați-vă de abonamentul dumneavoastră. Pentru a vă autentifica, faceți click aici %sAutentificare%s', 'Enter coupon code' => 'Introduceţi codul promoţional', 'Error 404 - Not Found' => 'Eroare 404 – nu găsesc', 'Error : upload folder [%s] does not exists' => 'Eroare: directorul pentru încărcare [%s] nu există', 'Error happened during transaction handling. Please contact website administrator' => 'S-a produs o eroare în timpul validării tranzacției. Vă rugăm contactați administratorul site-ului', 'European (A4)' => 'European (A4)', 'Exact' => 'Exact', 'Expire Date' => 'Data expirării', 'Expired' => 'Expirat', 'Expired Users' => 'Utilizatori expirați', 'Expires' => 'Expiră', 'Export' => 'Export', 'Export Format' => 'Format de export', 'FaceBook App ID' => 'ID-ul aplicației Facebook', 'FaceBook Application' => 'Aplicație Facebook', 'Facebook App Secret' => 'Secretul aplicației Facebook', 'Features' => 'Caracteristici', 'Field' => 'Câmp', 'Field Type' => 'Tipul câmpului', 'Field Updated' => 'Câmp actualizat', 'Fields To Display' => 'Câmpuri pentru afișare', 'Fields To Export' => 'Câmpuri pentru export', 'Fieldset' => 'Set de câmpuri', 'Fieldset title' => 'Titlu pentru setul de câmpuri', 'File' => 'Fişier', 'File Downloads' => 'Descărcări de fişiere', 'File Storage' => 'Locație de stocare fișiere', 'Filename' => 'Nume fişier', 'Files' => 'Fişiere ', 'Files uploaded via aMember web interface' => 'Fișierele încărcate prin interfața web', 'Filter' => 'Filtru', 'First & Last Name' => 'Nume și prenume', 'First Name' => 'Prenume', 'Folder %s (%s)' => 'Director %s (%s)', 'Folders' => 'Directoare', 'Form Page Break' => 'Divizor de pagini pentru formular', 'Free' => 'Gratuit', 'Free Access' => 'Acces gratuit', 'From' => 'De la', 'Get Password' => 'Obţineţi parola', 'Global Commission' => 'Comision global', 'Global Tax' => 'Taxă globală', 'Groups' => 'Grupuri', 'HTML Code that will be displayed' => 'Codul HTML care va fi afişat', 'HTML Message' => 'Mesajul HTML', 'HTML text' => 'Textul HTML', 'Having Active Subscription To:' => 'având abonament activ la:', 'Having Expired Subscription To:' => 'având abonament expirat la:', 'Helpdesk' => 'Asistență online', 'Hide do not display this item link in members area' => 'Ascunde nu afișa acest element în zona de membri', 'Hosted at Activecampaing\'s server' => 'Găzduit la serverul Activecampaing', 'Housenumber' => 'Numărul casei', 'IP Address' => 'Adresa IP', 'If you already have an account on our website, please %slog in%s to continue' => 'Dacă aveți deja un cont pe site-ul nostru, vă rugăm să vă %sautentificați%s pentru a continua', 'If you are a registered member, please %slogin%s' => 'Dacă sunteți înregistrat, vă rugăm să vă %sautentificați%s', 'If you are not registered yet, please %ssignup%s' => 'Dacă nu sunteţi încă înregistrat, vă rugăm să vă %sînregistrați%s', 'Income Report - payments minus refunds' => 'Raportul de venituri - plăți minus rambursări', 'Incorrect Parent Affiliate ID' => 'ID-ul de afiliere părinte este incorect', 'Integer Value' => 'Valoare întreagă', 'Integer value required' => 'Întreaga valoarea necesară', 'Integration' => 'Integrare', 'Integrations' => 'Integrări', 'Internal Error' => 'Eroare internă', 'Invalid Credit Card Number' => 'Numarului cardului este Invalid', 'Invalid Expiration Date - Month' => 'Data de expirare este invalidă - Luna', 'Invalid Expiration Date - Year' => 'Data de expirare este invalidă - Anul', 'Invalid Issue Number' => 'Numărul emis este invalid', 'Invalid VAT Id, please try again' => 'Cod fiscal incorect, vă rugăm să încercați din nou', 'Invite Code' => 'Cod de Invitație', 'Invoice' => 'Factură', 'Invoice Number: ' => 'Număr factură:', 'Invoice not found' => 'Factura nu a fost găsită', 'Is Locked' => 'Este blocat', 'Is Paid?' => 'Este plătit?', 'Is Disabled?' => 'Este oprit?', 'Item' => 'Element', 'Label' => 'Etichetă', 'Language' => 'Limbă', 'Last 14 Days' => 'Ultimele 14 zile', 'Last 30 Days' => 'Ultimele 30 de zile', 'Last 7 Days' => 'Ultimele 7 zile', 'Last Business Week (Mon-Fri)' => 'Ultima saptamană de lucru (luni-vineri)', 'Last Messages in Helpdesk' => 'Ultimele mesaje în asistența online', 'Last Month' => 'Ultima lună', 'Last Name' => 'Prenumele (Numele de familie)', 'Last Week (Mon-Sun)' => 'Săptămâna trecută (lu-du)', 'Last Week (Sun-Sat)' => 'Săptămâna trecută (du-sâ)', 'Leads' => 'Oportunități', 'License Key' => 'Cheia de licență', 'Lifetime' => 'Permanent', 'Like Url' => 'URL „îmi place”', 'Link' => 'Link', 'Links' => 'Link-uri', 'Live Edit %s' => 'Editare directă %s', 'Loading' => 'Se încarcă', 'Log In' => 'Autentificare', 'Log all API Requests' => 'Jurnalizați toate cererile API', 'Login' => 'Autentificare', 'Login as User' => 'Autentificare ca utilizator', 'Logout' => 'Deconectare', 'Lost Password Sending Error' => 'Eroare la trimiterea mesajului pentru recuperarea parolei', 'Lost Password Sent' => 'Mesajul pentru parola pierdută a fost trimis', 'Lost password?' => 'Parolă pierdută', 'Mail Queue' => 'Coada de așteptare pentru poșta electronică', 'Make Payment' => 'Efectuați plata', 'Manage Newsletters' => 'Gestionare newsletter-elor', 'Marketing Materials' => 'Materiale de marketing', 'Membership Type' => 'Tipul de abonament', 'Merchant Key' => 'Cheie de comerciant', 'Merchant Secret' => 'Secret de comerciant', 'Message' => 'Mesaj', 'Message can not be empty' => 'Mesajul nu poate fi gol', 'Month' => 'Lună', 'Months' => 'Luni', 'Multiplier' => 'Multiplicator', 'My Country' => 'Ţara mea', 'Name' => 'Nume', 'Never' => 'Niciodată', 'New' => 'Nou', 'New %s' => '%s nou ', 'New Password' => 'Parolă nouă', 'New Password you can choose new password here or keep it unchanged must be %d or more characters' => 'Parola nouă puteți alege o nouă parolă aici sau puteți să o mențineți neschimbata pe cea veche. Trebuie să fie de %d sau mai mult caractere', 'Newsletter' => 'Newsletter', 'Newsletter Subscriptions' => 'Abonamente la newsletter', 'Next' => 'Următorul', 'No' => 'Nu', 'No commissions on this date' => 'Nu există nici un comision pentru această dată', 'No coupons found with such coupon code' => 'Nici un cupon găsit pentru codul de cupon folosit', 'No items selected for purchase' => 'Nici un produs selectat pentru achiziționare', 'No records found' => 'Nici o inregistrare găsită', 'No, cancel' => 'Nu, anulează', 'No, keep me subscribed' => 'Nu, ține-mă abonat.', 'No, please keep me subscribed' => 'Nu, vă rog să imi mentineți abonamentul', 'Not Approved Affiliates' => 'Afiliaţi neaprobaţi', 'Not Selected' => 'Neselectat', 'Not registered yet?' => 'Neînregistrat încă?', 'Number of Messages to display' => 'Numărul de mesaje pentru afişare', 'Numeric Value' => 'Valoare numerică', 'Numeric value required' => 'Valoare numerică necesară', 'Offline Payment' => 'Plată manuală', 'Once the plugin configuration is finished on this page, do not forget to add a record on %saMember CP -> Protect Content -> Integrations%s page' => 'Odată ce configurarea modulului este terminată pe această pagină, nu uitați să adăugați o înregistrare pe pagina %saMember CP -> Conținut protejat -> Integrări%s', 'Only Affiliate %s(rarely used)%s' => 'Doar %s de afiliat (rar folosit) %s', 'Order reference: %s' => 'Referințe comandă: %s', 'Other' => 'Altele', 'Pages' => 'Pagini', 'Password' => 'Parolă', 'Password and Password Confirmation are different. Please reenter both' => 'Parolele introduse sunt diferite Vă rugăm să le introduceți din nou pe amândouă', 'Password must contain at least %d letters or digits' => 'Parola trebuie să conţină cel puţin %d litere sau cifre', 'Passwords do not match' => 'Parolele nu se potrivesc', 'Path to %s' => 'Cale către %s ', 'Path to %s Folder' => 'Calea către directorul %s', 'Payanyway plugin does not support recurring billing!' => 'Modulul Payanyway nu acceptă facturări recurente!', 'Payment' => 'Plată', 'Payment Error' => 'Eroare de plată', 'Payment Failed' => 'Plata a eşuat', 'Payment System' => 'Sistemul de plăți', 'Payment System Description' => 'Descrierea sistemul de plată', 'Payment System Title' => 'Titlul sistemului de plată', 'Payment error: ' => 'Eroare de plată: ', 'Payment failed' => 'Tranzacție eșuată', 'Payment is already processed, please go to %sMembership page%s' => 'Plata este deja procesată, vă rugăm să accesați %sPagina abonatului%s', 'Payments' => 'Plăţi', 'Payments History' => 'Istoric plăți', 'Payments by New vs Existing members' => 'Plățile efectuate de către abonații noi sau de către cei deja existenți', 'Payments by payment system breakdown' => 'Detalierea sistemului de plată al plăților efectuate', 'Payments by products breakdown' => 'Detalierea sistemului de plată al produselor', 'Payments from existing customers' => 'Plăţi de la clienţii existenţi', 'Payments from new customers' => 'Plăţile de la clienţii noi', 'Payments total' => 'Total plăţi', 'Payout Method' => 'Metoda de plată', 'Payouts' => 'Plăţi', 'Pending' => 'În așteptare', 'Pending Invoices' => 'Facturi în aşteptare', 'Pending subusers' => 'Sub-utilizatori în așteptare', 'Period' => 'Perioadă', 'Period must be in interval 1-24 months' => 'Perioada trebuie să fie în intervalul de 1-24 luni', 'Period must be in interval 1-5 years' => 'Perioada trebuie să fie în intervalul de 1-5 ani', 'Period must be in interval 1-90 days' => 'Perioada trebuie să fie în intervalul de 1-90 zile', 'Personal Content' => 'Conţinut personal', 'Phone' => 'Telefon', 'Phone Number' => 'Număr de telefon', 'Plain-Text Message' => 'Mesaj tip text', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Vă rugăm să vă %sautentificați%s în contul dumneavoastră existent. %s Dacă nu ați terminat efectuarea plății, o puteți face după autentificare.', 'Please Select' => 'Vă rugăm selectaţi', 'Please agree to User Agreement' => 'Vă rugăm acceptați regulile privind acordul utilizatorului', 'Please choose' => 'Vă rugăm alegeți', 'Please choose a Credit Card Type' => 'Vă rugăm alegeți tipul cardului de credit', 'Please choose a membership type' => 'Vă rugăm să alegeţi tipul de înregistrare', 'Please choose a payment system' => 'Vă rugăm să alegeţi un sistem de plată', 'Please choose state' => 'Alegeți județul', 'Please enter %s' => 'Vă rugăm introduceţi %s', 'Please enter City' => 'Vă rugăm introduceți orașul', 'Please enter Country' => 'Vă rugăm introduceți țara', 'Please enter Credit Card Code' => 'Vă rugăm să introduceți codul cardului de credit', 'Please enter Credit Card Number' => 'Vă rugăm să Introduceți numărul cardului de credit', 'Please enter Password' => 'Vă rog să introduceți parola', 'Please enter State' => 'Vă rugăm să introduceți județul', 'Please enter Street Address' => 'Vă rugăm să introduceți numele străzii', 'Please enter ZIP code' => 'Vă rugăm să introduceți codul poștal', 'Please enter a valid e-mail address' => 'Vă rugăm să introduceți o adresă de e-mail validă', 'Please enter coupon code' => 'Va rugam să introduceti codul cuponului promoțional', 'Please enter credit card holder first name' => 'Vă rugăm să introduceți prenumele titularului de card', 'Please enter credit card holder last name' => 'Vă rugăm introduceți numele titularului de card', 'Please enter credit card holder name' => 'Vă rugăm introduceți numele complet al titularului de card', 'Please enter housenumber' => 'Vă rugăm să introduceți numărul casei', 'Please enter phone number' => 'Vă rugăm să Introduceți numărul de telefon', 'Please enter valid Email' => 'Vă rugăm să introduceți o adresă de email validă', 'Please enter valid Username. It must contain at least %d characters' => 'Vă rugăm să introduceți un nume de utilizator valid. Trebuie să conțină cel putin %d caractere', 'Please enter your First Name' => 'Vă rugăm să introduceți prenumele dumneavoastră.', 'Please enter your Last Name' => 'Vă rugăm să introduceți numele dumneavoastră de familie.', 'Please enter your current password for validation' => 'Vă rugăm să introduceți parola curentă pentru validare', 'Please login' => 'Vă rugăm să vă autentificați', 'Please select' => 'Vă rugăm să selectați', 'Please select an item...' => 'Vă rugăm să selectați o opțiune...', 'Please select payment system for payment' => 'Vă rugăm să alegeți sistemul de plată pentru efectuarea plății', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Vă rugăm să folosiți formularul de înregistrare de la %sAdaugă / reînnoiește abonamente%s pentru a comanda sau reînnoi abonamentul.', 'Please wait %d seconds before next login attempt' => 'Vă rugăm să aşteptaţi %d secunde înainte de a vă autentifica din nou', 'Plugin' => 'Modul', 'Plugin List Id' => 'ID listă module', 'PostAffiliatePro Parent Affiliate ID' => 'ID-ul afiliat părinte PostAffiliatePro', 'PostAffiliatePro Referral ID' => 'ID-ul de afiliere PostAffiliatePro', 'Prev' => 'Anterior', 'Preview' => 'Previzualizare', 'Price' => 'Preţ', 'Processing your Transaction' => 'Prelucrarea tranzacției', 'Product' => 'Produs', 'Product Categories' => 'Categorii de produse', 'Product Title' => 'Titlu produs', 'Product(s) to display' => 'Produs(e) pentru afișare', 'Products' => 'Produse', 'Products keep empty to report all products' => 'Produse păstrează gol pentru a raporta toate produsele', 'Profile' => 'Editare profil', 'Profile update transaction failed' => 'Tranzacţia de actualizare a profilului a eşuat', 'Purchased Credits' => 'Creditele achiziţionate', 'Qty' => 'Cant', 'Quantity' => 'Cantitate', 'Quick Order' => 'Comandă rapidă', 'Re-Open Ticket' => 'Redeschide tichet', 'Read-only' => 'Numai pentru citire', 'Record' => 'Înregistrare', 'Record Type' => 'Tip înregistrare', 'Records that match all these conditions' => 'Înregistrările care se potrivesc cu toate aceste condiţii', 'Recurring' => 'Recurent', 'Reference number is:' => 'Numărul de referinţă este:', 'Referer' => 'Referent', 'Referred Affiliate' => 'Afiliat recomandat', 'Refresh' => 'Împrospătare', 'Refresh 3-rd party lists' => 'Împrospătare liste ale terților', 'Refund' => 'Rambursare', 'Refund Amount' => 'Suma de rambursare', 'Refunded' => 'Rambursat', 'Regional Tax' => 'Taxe regionale', 'Register' => 'Înregistrare', 'Remote API Permissions' => 'Permisiuni acces API', 'Remove' => 'Șterge', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Sterge utilizatori Atunci când utilizatorul este sters din aMember utilizatorul corespondent trebuie șters din %s', 'Remove user' => 'Șterge utilizator', 'Reply' => 'Răspunde', 'Required' => 'Necesar', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Reîncercați în caz de eșec dacă tranzacția a eșuat, aMember o poate repeta după câteva zile și va extinde abonamentul pentru perioada respectivă. Introduceți numărul zilelor de așteptare înainte de a repeta facturarea.', 'Return' => 'Înapoi', 'Return and try again' => 'Înapoi şi încercaţi din nou', 'Review/Pay Commissions' => 'Revizuiește/Plătește comisionul de afiliat', 'Run Report' => 'Rulează raportul', 'Running %s' => 'Rulează %s', 'Save' => 'Salvați', 'Save Profile' => 'Salvare profil', 'Search' => 'Caută', 'Search Products' => 'Caută produse', 'Security code is invalid' => 'Codul de securitate este invalid', 'Select a condition to add into search' => 'Selectaţi o condiţie pentru a adăuga în căutare', 'Select all %s records matching your search' => 'Selectați toate înregistrările %s care se potrivesc căutării dumneavoastră', 'Send' => 'Trimiteți', 'Send Cancel Notifications to User' => 'Trimiteți notificări de anulare către utilizatori', 'Session expired, please enter username and password again' => 'Sesiunea a expirat, vă rugăm să introduceți din nou numele de utilizator și parola', 'Settings' => 'Setări', 'Shipping' => 'Expediere', 'Shopping Cart' => 'Coș de cumpărături', 'Sign-up' => 'Înregistrare', 'Signup Form' => 'Formular de înregistrare', 'Signup here' => 'Înregistrați-vă aici', 'Signup/payment functions are disabled for this user account' => 'Înregistrare/funcțiile de plată sunt dezactivate pentru acest cont de utilizator', 'Simple Search Users' => 'Căutare simplă a utilizatorilor ', 'Site Title' => 'Titlu site', 'Skip First Line' => 'Salt peste prima linie', 'Snippets' => 'Fragmente', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Ne pare rău, este imposibil de folosit tipul acesta de plată pentru comanda curentă. Vă rugăm selectați o altă metodă de plată', 'Sorry, seems you have used wrong link' => 'Ne pare rău, se pare că ați folosit link-ul greșit', 'Source Code — Copy/Paste Into Your Website' => 'Cod sursă — copiază / lipește in website-ul tău', 'Standard' => 'Standard', 'Start' => 'Început', 'Start Date' => 'Data de începere', 'State' => 'Județ', 'Status' => 'Stare', 'Street' => 'Strada', 'Street Address' => 'Strada', 'SubUsers Count (keep zero for non-reseller products)' => 'Contorizarea sub-utilizatoriilor (păstrează zero pentru produsele care nu sunt dedicate revânzării)', 'SubUsers Product (keep empty for non-reseller products)' => 'Produs pentru sub-utilizatori (păstrează zero pentru produsele care nu sunt dedicate revânzării)', 'Subject' => 'Subiect', 'Subject can not be empty' => 'Câmpul subiect nu poate fi gol', 'Subscribe And Pay' => 'Abonați-vă și plătiți', 'Subscribe to Site Newsletters' => 'Abonați-vă la scrisorile periodice ale sitului', 'Subscribed To Newsletters' => 'Abonat la newslettere', 'Subscribers' => 'Abonaţi', 'Subscription Terms' => 'Termenii și condițiile abonamentului', 'Subscription/Product Title' => 'Abonamentul / Titlul produsului', 'Subtotal' => 'Subtotal', 'Subusers' => 'Sub-utilizatori', 'Such affiliate ID exist' => 'Acest ID de afiliat nu există', 'Target URL' => 'URL ţintă', 'Tax' => 'Taxă', 'Tax Amount' => 'Suma taxelor', 'Tax Id' => 'Cod fiscal', 'Tax Rate for example 18.5 (no percent sign)' => 'Rata taxei de exemplu, 18,5 (nici un semn la sută)', 'Tax Title' => 'Titlu taxe', 'Tax Value' => 'Valoarea taxei', 'Terms' => 'Condiții', 'Test Mode' => 'Mod de testare', 'Test Settings' => 'Setări de testare', 'Thank you for Signing up' => 'Vă mulţumim pentru înscriere', 'Thanks! Your Payment is PENDING & Under Process. We will update your subscription once your Payment is Completed. Please stay tuned during this process. It may take 12 - 24 hrs. You will receive Email notification about receipt of Payment.' => 'Multumim! Plata dumneavoastră este în curs de aprobare și procesare. Vom actualiza abonamentul dumneavoastră îndată ce plata este finalizată. Va rugăm sa fiți alert pe parcursul acestui proces. Este posibil ca el să dureze 12 - 24 de ore. Veți primi o notificare prin e-mail despre confirmarea plății.', 'The database has encountered a problem, please try again later.' => 'Baza de date a întâmpinat o problemă, vă rugăm să încercaţi din nou mai târziu.', 'The password should be at least %d characters long' => 'Parola trebuie să fie lungă de cel puțin %d caractere ', 'The user name or password is incorrect' => 'Numele de utilizator sau parola sunt incorecte', 'There are no confirmed payments for your account' => 'Nu există plăți confirmate pentru contul dumneavoastră', 'There are no form available for affiliate signup.' => 'Nu există formulare de înscriere disponibile pentru afiliați', 'There are no products available for purchase. Please come back later.' => 'Nu există produse disponibile pentru achiziționare. Vă rugăm reveniți mai târziu.', 'This %s is blocked. Please contact site support to find out why' => 'Această %s este blocată. Contactați administratorului site-ului pentru a afla motivul', 'This Month' => 'Luna aceasta', 'This Week (Mon-Sun)' => 'Săptămâna aceasta (lu-du)', 'This Week (Sun-Sat)' => 'Săptămâna aceasta (du-sâ)', 'This coupon belongs to another customer' => 'Acest cupon aparține unui alt utilizator', 'This field is required' => 'Acest câmp este obligatoriu', 'This is a required field' => 'Acesta este un câmp obligatoriu', 'This page will be automatically refreshed within %s' => 'Această pagina vă fi actualizată automat în termen de %s', 'This payment system could not handle payments in [%s] currency' => 'Acest sistem de plată nu a poate gestiona plăți în valuta [%s]', 'This payment system could not handle zero-total invoices' => 'Acest sistem de plată nu poate gestiona facturi cu totalul zero', 'Thresehold Date' => 'Dată limită', 'Ticket' => 'Tichet', 'Ticket has been submited' => 'Tichetul a fost trimis', 'Tickets' => 'Tichete', 'Title' => 'Titlu', 'To' => 'Către', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'Pentru a adăuga câmpuri în formular, mutați optiunle din ‘cărămizile disponibile’ in \'cărămizile formularului\'. Pentru a elimina câmpuri, mutați-le înapoi la ‘cărămizile disponibile’ Pentru a crea un formular pe pagini multiple, introduceți elementul \'delimitator pagină’ în locul în care doriți să fie împărțite paginile', 'Today' => 'Astăzi', 'Total' => 'Total', 'Try again' => 'Încercați din nou', 'Type' => 'Tip', 'USA (Letter)' => 'SUA (scrisoare)', 'Unable to delete this file as it is used for:' => 'Nu pot șterge acest fișier deoarece este folosit pentru:', 'Unenroll Student' => 'Dezabonare student', 'Unit Price' => 'Preț unitar', 'Unknown period unit: %s' => 'Unitate de perioadă necunoscută:%s', 'Unsubscribe' => 'Dezabonare', 'Unsubscribe from all e-mail messages' => 'Dezabonare de la toate mesajele de e-mail', 'Unsubscribed' => 'Dezabonat', 'Unsubscription Confirmation' => 'Confirmarea dezabonării', 'Update' => 'Actualizare', 'Update Credit Card Info' => 'Actualizați informațiile cardului de credit', 'Updated' => 'Actualizat', 'Upgrade Subscription' => 'Actualizare abonament', 'Upload files using FTP client to [%s]' => 'Încărcați fișierele folosind clientul FTP pentru a [%s]', 'Use Database Connection other than configured for aMember' => 'Folosiți conexiunea la baza de date în alt mod decât cel configurat pentru aMember', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Folosește o altă bază de date MySQL Folosiți gazdă, utilizator și parolă personalizate pentru conectare la baza de date %s . În mod normal puteți lăsa acestă căsuță nebifată', 'Useful Links' => 'Link-uri utile', 'User' => 'Utilizator', 'User Agreement' => 'Acordul utilizatorului', 'User Groups' => 'Grupuri de utilizatori', 'User Info' => 'Info utilizator', 'User Search' => 'Cautare utilizator', 'User is locked' => 'Utilizatorul este blocat', 'User is not approved' => 'Utilizatorul nu este aprobat', 'User must provide' => 'Utilizatorul trebuie să furnizeze', 'Username' => 'Nume de utilizator', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Nume de utilizator Aveți posibilitatea de a alege un nume de utilizator nou sau puteți să il mentineti neschimbat pe cel vechi. Numele de utilizator trebuie să fie de minim %d caractere lungime și poate conține numai litere mici, cifre și sublinieri', 'Username %s is already taken. Please choose another username' => 'Numele de utilizator %s este deja rezervat. Vă rugăm să alegeți un alt nume de utilizator', 'Username contains invalid characters - please use digits, letters or spaces' => 'Numele de utilizator conține caractere invalide - folosiți cifre, litere sau spații', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Numele de utilizator conține caractere invalide - folosiți doar cifre și litere', 'Username/Email' => 'Adresa de e-mail sau numele de utilizator', 'Users subscribed to Newsletter Threads #' => 'Utilizatorii abonați la listele de distribuție a scrisorilor #', 'VAT Id' => 'Cod fiscal', 'Validate E-Mail Address by sending e-mail message with code' => 'Validați adresa de email prin trimiterea unui mesaj e-mail cu codul', 'Validation' => 'Validare', 'Version of script' => 'Versiune de script', 'Video' => 'Video', 'View Basket' => 'Vizualizare coș de produse', 'Visit %sorder page%s to order additional subscriptions' => 'Vizitați %sPagina de comandă%s pentru a comanda abonamente suplimentare', 'Week' => 'Săptămâna', 'Wrong code or code expired - please start signup process again' => 'Cod greșit sau cod expirat - vă rugăm să începeți procesul de înscriere de la început', 'Wrong link - no id passed' => 'Link greșit - nu a fost transmis nici un ID', 'Wrong parameters, error #1253' => 'Parametrii greșiți, eroare #1253', 'Wrong password' => 'Parolă greșită', 'Wrong verification code' => 'Codul de verificare este greșit', 'Wrongly signed URL, please contact site admin' => 'URL semnat greșit, vă rugăm contactați administratorul', 'Year' => 'Anul', 'Years' => 'Ani', 'Yes' => 'Da', 'Yes, I want to cancel subscription' => 'Da, vreau să anulez abonamentul', 'Yes, continue' => 'Da, continuă', 'Yes, unsubscribe' => 'Da, dezabonează-mă.', 'Yesterday' => 'Ieri', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Sunteți autentificat ca %s. Apăsați %sDeautentificare%s pentru a vă înscrie ca utilizator nou.', 'You have %s%d ticket(s)%s that require your attention' => 'Aveți %s%d tichete%s care vă solicită atenția', 'You have no access to %s' => 'Nu aveţi acces la %s', 'You have no active subscriptions' => 'Nu aveți abonamente active', 'You have no enough permissions for this operation' => 'Nu aveţi permisiuni suficiente pentru această operaţie', 'You have no items in your basket - please add something to your basket before checkout' => 'Nu aveţi niciun produs in coş - vă rugăm să adăugaţi ceva in coşul de cumpăraturi înainte de a efectua plata', 'You have too many subusers assigned to this account. You may choose to remove %d users from your account' => 'Aveți prea mulți sub-utilizatori alocați la acest cont. Puteți alege să eliminați %d utilizatori din contul dumneavoastră.', 'You must be authorized to access this area' => 'Trebuie să fiți autorizat pentru a accesa această zonă', 'You must set aMember CP -> Setup -> Advanced -> Session Storage to \'Standart PHP Sessions\' This is necessary to enable Single Login between aMember and SilverStrype' => 'Trebuie să setați aMember CP -> Setup -> Advanced -> Session Storage la "Standard PHP Sessions" Acest lucru este necesar pentru a permite conectări unice între aMember și SilverStrype', 'Your Account Removal' => 'Anularea contului dumneavoastră', 'Your Basket' => 'Coșul dumneavoastră', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Parola curentă dacă schimbați parola, vă rugăm să introduceți parola curentă pentru validare', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Adresa dumneavoastră de e-mail Un mesaj de confirmare va fi trimis la această adresă', 'Your General Affiliate Link' => 'Linkul dumneavoastră general de afiliat', 'Your Membership Information' => 'Informațiile contului dumneavoastră', 'Your Payment is PENDING & Under Process' => 'Plata dumneavoastră este în curs de aprobare și procesare', 'Your Personal Downloads' => 'Descărcările dumneavoastră personale', 'Your Reseller Packages' => 'Pachetele dumneavoastră pentru revânzare', 'Your Subscriptions' => 'Subcripţiile Tale', 'Your account has been automatically locked.' => 'Contul dumneavoastră a fost blocat automat.', 'Your account has not yet been approved. You will be notified via email once a site administrator has reviewed your account and enabled access.' => 'Contul dumneavoastră nu este aprobat încă. Veți fi notificat prin e-mail atunci când administratorul site-ului verifică contul dumneavoastră și vă permite accesul.', 'Your password is too long' => 'Parola dumneavoastră este prea lungă ', 'Your payment has been successfully processed.' => 'Plata dumneavoastră a fost procesată cu succes.', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Plata dumneavoastră nu este încă confirmată de către sistemul de plată. Poate dura câteva minute pentru a obține confirmarea de plată.', 'Your subject is too verbose' => 'Subiectul dumneavoastră este prea lung', 'Your subscription has been successfully processed.' => 'Abonamentul dumneavoastră a fost procesat cu succes.', 'ZIP' => 'Cod poștal', 'ZIP Code' => 'Cod poștal', 'Zip' => 'Cod poștal', '[Select country]' => '[selectați ţara]', '[Select state]' => '[selectați județul]', '_default_locale' => 'ro', 'admin' => 'administrator', 'affiliate program commissions' => 'comisioane pentru programul de afiliere', 'ago' => 'în urmă', 'banned' => 'blocat', 'commission found by next rules' => 'comision găsit de următoarele reguli', 'days' => 'zile', 'email' => 'e-mail', 'expiration' => 'expirare', 'expires' => 'expiră', 'filtered' => 'filtrate', 'for affiliate commission payouts' => 'pentru plățile de comision către afiliați', 'for example: 1111-2222-3333-4444' => 'de exemplu: 1111-2222-3333-4444', 'generate' => 'generează', 'hrs' => 'ore', 'ip' => 'IP', 'just now' => 'chiar acum', 'link' => 'link', 'login' => 'autentificare', 'min' => 'min', 'month' => 'lună', 'more than' => 'mai mult decât', 'no records' => 'nu conține înregistrări', 'number of affiliate program clicks' => 'Numărul de clicuri pentru programele de afiliere', 'of products' => 'de produse', 'on %d-th day' => 'în a %d-a zi', 'only First Name' => 'numai prenumele', 'only Last Name' => 'numai numele', 'or' => 'sau', 'pay using credit card or PayPal' => 'Efectuați plata utilizând PayPal sau card de credit', 'pay using wire transfer or by sending offline check' => 'Plătiți utilizând transfer bancar (OP) sau prin trimitere de cec', 'protected area' => 'zonă protejată', 'return' => 'înapoi', 'seconds' => 'secunde', 'start' => 'Inceput', 'use 4111-1111-1111-1111 for successful transaction' => 'utilizați 4111-1111-1111 pentru tranzacții reușite', ); PK\qqiidefault/language/user/nb.phpnu[ 'for alltid', ' from ' => 'fra', ' to ' => 'til', '"%s" can be ordered along with these products/subscripton(s) only: %s' => '"%s" kan bare bestilles sammen med disse produkter/abonnementer: %s', '"%s" can only be ordered if you have expired subscription(s) for these products: %s' => '"%s" kan bare bli bestilt hvis du har utgåtte abonnementer for disse produkter: %s', '"%s" cannot be ordered because you have active subscription(s) to: %s' => '"%s" kan ikke bestilles fordi du har aktive abonnementer for: %s', '"%s" cannot be ordered because you have expired subscription(s) to: %s' => '"%s" kan ikke bestilles fordi du har utgåtte abonnementer for: %s', '%s database and tables prefix' => '%s database og tabeller prefiks', 'Accept Direct Payments handle payments made on payment system side (without signup to aMember first)' => 'Legg til Direktebetaling håndter betalinger gjort på betalingssystemets side (uten å registrere deg på aMember først)', 'Access' => 'Tilgang', 'Access Denied' => 'Ingen tilgang', 'Access Log' => 'Adgangslog', 'Access Permissions' => 'Bestem tilganger', 'Actions' => 'Handlinger', 'Active Users' => 'Aktive brukere', 'Add "Like" button' => 'Legg til "Like" knapp', 'Add to Basket' => 'Legg til i Handlekurv', 'Add/Renew Subscription' => 'Legg til/fornye abonnement', 'Address Info' => 'Adresseinfo', 'Address Information' => 'Adresseinformasjon', 'Admin Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Admin Grupper aMember rører aldri %s kontoer som er satt til de følgende gruppene. Dette beskytter %s kontoer mot all aMember aktivitet', 'Administrator' => 'Administrator', 'Advertise our website to your friends and earn money' => 'Reklamer til dine venner på vår webside og tjen penger', 'Affiliate Clicks' => 'Partner klikk', 'Affiliate Info' => 'Partner Info', 'Affiliate Payout Type' => 'Partner Utbetalingsmåte', 'Affiliate Program' => 'Partnerprogram', 'Affiliate Sales' => 'Partner salg', 'Affiliate Signup Form' => 'Partners påmeldingsskjema ', 'Affiliate info' => 'Partner info', 'Affiliate stats' => 'Partnerstatistikk', 'Affiliates' => 'Partnere', 'All %s records on this page are selected' => 'All %s informasjon på denne siden er valgt', 'All Affiliates' => 'Alle partnere', 'All Users' => 'Alle brukere', 'All records' => 'Alle dokumenter', 'Amount' => 'Sum', 'An Error has occurred' => 'En feil har oppstått', 'An account with the same email already exists.' => 'En konto med samme epost finnes allerede', 'An error occurred while handling your payment.' => 'En feil har oppstått under din betaling.', 'An internal error happened in the script, please contact webmaster for details' => 'En intern feil oppstod under kjøring av skriptet, vennligst kontakt webmesteren for detaljer', 'Any Product' => 'Vilkårlig Produkt', 'Any product' => 'Vilkårlig produkt', 'Apply' => 'Bruk', 'Apply Filter' => 'Skru på filter', 'Attachments' => 'Vedlegg', 'Authentication' => 'Autorisering', 'Authentication problem, please contact website administrator' => 'Autentisering problem, vennligst kontakt websidens administrator', 'Available Bricks (drag to left to add)' => 'Tilgjengelige elementer (dra over til venstre for å legge til)', 'Awaiting Admin Response' => 'Venter på svar fra admin', 'Awaiting User Response' => 'Venter på svar fra bruker', 'Back' => 'Tilbake', 'Bank Identification' => 'Bank identifikasjon', 'Bank Name' => 'Bank navn', 'Banned Groups aMember never touches %s accounts assigned to the following groups. This protects %s accounts against any aMember activity' => 'Blokkerte grupper aMember rører aldri %s kontoer som er satt til de følgende gruppene. Dette beskytter %s kontoer mot all aMember aktivitet', 'Banners and Links' => 'Faner og Lenker', 'Banners and Text Links' => 'Administrer faner og tekstlenker ', 'Both Affiliate and member' => 'Både partner og medlem', 'CC Demo' => 'CC Demo', 'CSRF protection error - form must be submitted within %d minutes after displaying, please repeat' => 'CSRF beskyttelse feilmelding - skjema må leveres innen %d minutter etter det først blir vist, vennligst gjenta ', 'Can view/edit customer Credit Card information and rebills' => 'Kan se/endre kunders Kredittkortinformasjon og faste trekk', 'Cancel' => 'Kanseller', 'Cancel Subscription' => 'Kanseller abonnement', 'Cancelled' => 'Kansellert ', 'Cannot use FREE payment plugin with a product which cost more than 0.0' => 'Kan ikke bruke GRATIS betalingsmetode når produktet koster mer en 0.0', 'Category' => 'Kategori', 'Change' => 'Forandre', 'Change Password' => 'Bytte passord', 'Change Password/Edit Profile' => 'Bytte passord/endre profil', 'Change Subscription' => 'Forandre abonnement', 'Change Username' => 'Forandre brukernavn', 'Change payout info' => 'Forandre utbetalingsinfo ', 'Checkout' => 'Gå til kassen', 'Checkout error: ' => 'Gå til kassen Feil:', 'Choose a Password must be %d or more characters' => 'Velg et Passord må være %d eller flere tegn', 'Choose a Username it must be %d or more characters in length may only contain letters, numbers, and underscores' => 'Velg et brukernavn det må være %d eller flere tegn langt kan bare inneholde bokstaver, tall eller understreker', 'City' => 'Sted', 'Click here if you do not want to wait any longer (or if your browser does not automatically forward you).' => 'Klikk her hvis du ikke liker å vente (eller hvis nettleseren din ikke automatisk sender deg videre).', 'Click to Edit' => 'Trykk for å redigere', 'Clicks' => 'Klikk', 'Clicks/Sales Statistics' => 'Partner-klikk/salgsstatistikk', 'Close' => 'Lukk', 'Close Ticket' => 'Lukk Ticket', 'Closed' => 'Stengt', 'Comment' => 'Kommentar', 'Confirm' => 'Bekreft', 'Confirm New Password' => 'Bekreft nytt Passord', 'Confirm Password' => 'Bekreft passord', 'Confirm Payment' => 'Bekreft betaling', 'Confirm Your Password' => 'Bekreft ditt passord', 'Continue' => 'Fortsett', 'Conversation' => 'Samtale', 'Country' => 'Land', 'Coupon' => 'Rabattkupong', 'Coupon Discount' => 'Rabattkupong', 'Coupon code disabled' => 'Rabattkode er deaktivert', 'Coupon code expired' => 'Rabattkode er utgått', 'Coupon is not yet active' => 'Rabattkoden er ikke aktiv enda', 'Coupon usage limit exceeded' => 'Rabattkodes grense er overskredet', 'Create aMember Users By Demand silently create customer in aMember if user tries to login into aMember with the same username and password as for %s' => 'Lag aMember bruker ved behov lag en bruker i stillhet i aMember hvis bruker prøver å logge inn på aMember med det samme brukernavnet og passordet som for %s', 'Credit Card Code' => 'Kredittkortkode', 'Credit Card Info' => 'Kredittkort Info', 'Credit Card Number' => 'Kredittkortnummer', 'Credit Card Rebills' => 'Fast trekk fra Kredittkort ', 'Credit Cards' => 'Kredittkort', 'Current password entered incorrectly, please try again' => 'Nåværende passord er skrevet inn feil, vennligst prøv igjen', 'Custom Commission' => 'Egendefinert Provisjon', 'DONE' => 'FERDIG', 'Date' => 'Dato', 'Date and time of payment: %s' => 'Dato og tidspunkt for betalingen: %s', 'Date must be in format %s' => 'Dato må være i dette formatet %s', 'Day' => 'Dag', 'Days' => 'Dager', 'Default Level default level - user reset to this access level if no active subscriptions exists (for example all subscriptions expired)' => 'Standard Nivå standard nivå - bruker resetter til dette tilgangsnivået hvis ingen aktive abonnementer finnes (for eksempel hvis alle abonnementer har gått ut)', 'Delete' => 'Slett', 'Delete %s' => 'Slett %s', 'Description' => 'Beskrivelse', 'Discard' => 'Forkast', 'Discount' => 'Rabatt', 'Do not add to Login Form' => 'Ikke legg til Logg inn Skjema', 'Do not add to Signup Form' => 'Ikke legg til Registrerings Skjema', 'Do you really want to %s %s %s records' => 'Ønsker du virkelig og slette %s %s %s dokumentene', 'Do you really want to %s?' => 'Ønsker du virkelig å %s?', 'Do you really want to cancel subscription?' => 'Ønsker du virkelig å kansellere abonnementet?', 'Do you really want to delete record?' => 'Ønsker du virkelig og slette dokumentet?', 'E-Mail' => 'E-post', 'E-Mail Address' => 'E-postadresse', 'E-Mail Format' => 'E-post format', 'E-Mail Verification' => 'Epost verifikasjon', 'Edit' => 'Rediger', 'Edit %s' => 'Rediger %s', 'Edit E-Mail Template' => 'Rediger epost mal', 'End' => 'Slutt', 'Enjoy your membership. To Login please click here %sLogin%s' => 'Vi håper du blir fornøyd med ditt medlemskap. For å logge inn trykk her %sLogg inn%s', 'Error 404 - Not Found' => 'Feilmelding 404 - Siden finnes ikke', 'Error happened during transaction handling. Please contact website administrator' => 'En feil oppstod under transaksjonen. Vennlig kontakt websidens administrator', 'Expired Users' => 'Utgåtte brukere', 'Export' => 'Eksporter', 'Export Format' => 'Eksporter format', 'FaceBook App ID' => 'Facebook App ID', 'FaceBook Application' => 'Facebook Søknad', 'Facebook App Secret' => 'Facebook App Hemmelighet', 'Features' => 'Egenskaper', 'Field Updated' => 'Felt oppdatert', 'Fields To Export' => 'Felter å eksportere ', 'Filter' => 'Filtrer', 'First & Last Name' => 'For og Etternavn', 'Folder %s (%s)' => 'Mappe %s (%s)', 'Form Page Break' => 'Skjema sideskift', 'Free' => 'Gratis', 'Free Access' => 'Gratis tilgang', 'Get Password' => 'Skaff passord', 'HTML Message' => 'HTML melding', 'Having Active Subscription To:' => 'Har aktive abonnement til:', 'Having Expired Subscription To:' => 'Har utgåtte abonnement til:', 'Helpdesk' => 'Serviceavdeling', 'Housenumber' => 'Hjemmetelefonnummer ', 'If you already have an account on our website, please %slog in%s to continue' => 'Hvis du er et registrert medlem, vennligst %slogg inn%s', 'If you are a registered member, please %slogin%s' => 'Hvis du er et registrert medlem, vennligst %slogg inn%s', 'Income Report - payments minus refunds' => 'Inntektsrapport - betalinger minus refusjoner', 'Integer value required' => 'Heltallsverdi kreves', 'Internal Error' => 'Intern feil', 'Invalid Credit Card Number' => 'Ugyldig Kredittkortnummer', 'Invalid Expiration Date - Month' => 'Ugyldig utløpsdato - Måned', 'Invalid Expiration Date - Year' => 'Ugyldig utløpsdato - År', 'Invalid Issue Number' => 'Ugyldig utgavenummer', 'Invite Code' => 'Invitasjonskode', 'Invoice' => 'Faktura', 'Invoice not found' => 'Faktura ikke funnet', 'Item' => 'Artikkel', 'Language' => 'Språk', 'Lifetime' => 'Livstid', 'Like Url' => 'Lik Url', 'Link' => 'Lenke', 'Live Edit %s' => 'Direkte redigering %s', 'Login' => 'Logg inn', 'Logout' => 'Logg ut', 'Lost Password Sending Error' => 'Feil ved oversendelse av tapt passord', 'Lost Password Sent' => 'Tapt passord er sendt', 'Lost password?' => 'Tapt passord', 'Make Payment' => 'Gjennomfør betaling', 'Manage Newsletters' => 'Administrer nyhetsbrev', 'Marketing Materials' => 'Markedsføringsmateriale ', 'Membership Type' => 'Type medlemskap', 'Message' => 'Meldinger', 'Message can not be empty' => 'Melding kan ikke være tom', 'Month' => 'Måned', 'Months' => 'Måneder', 'Multiplier' => 'Multiplikator', 'Name' => 'Navn', 'New' => 'Ny', 'New %s' => 'Ny %s', 'New Password' => 'Nytt Passord', 'Newsletter' => 'Nyhetsbrev', 'Newsletter Subscriptions' => 'Nyhetsbrev abonnementer', 'Next' => 'Neste', 'No' => 'Nei', 'No commissions on this date' => 'Ingen provisjon på dette tidspunkt', 'No coupons found with such coupon code' => 'Ingen rabattkupong funnet med den koden', 'No items selected for purchase' => 'Ingen produkter er valgt for kjøp', 'No records found' => 'Ingen oppføringer funnet', 'No, cancel' => 'Nei, avbryt', 'No, please keep me subscribed' => 'Nei, jeg ønsker å fortsette abonnementet', 'Not Selected' => 'Ikke valgt', 'Not registered yet?' => 'Ikke registrert enda?', 'Numeric value required' => 'Tallverdi kreves', 'Offline Payment' => 'Offline Betaling', 'Only Affiliate %s(rarely used)%s' => 'Bare partner %s(sjeldent brukt)%s', 'Order reference: %s' => 'Ordre referanse: %s', 'Password' => 'Passord', 'Password and Password Confirmation are different. Please reenter both' => 'Passord og Passord Bekreftelse er forskjellig. Vennligst skriv inn begge på nytt', 'Password must contain at least %d letters or digits' => 'Passord må inneholde minst %d bokstaver eller tegn', 'Passwords do not match' => 'Passordene er ikke like', 'Path to %s' => 'Sti til %s', 'Path to %s Folder' => 'Sti til %s mappe', 'Payment Error' => 'Betalings feilmelding', 'Payment Failed' => 'Betaling feilet', 'Payment System' => 'Betalingssystemer', 'Payment System Description' => 'Betalingssystem Beskrivelse', 'Payment System Title' => 'Betalingssystem Tittel', 'Payment error: ' => 'Betalings feilmelding ', 'Payment failed' => 'Betaling feilet', 'Payments' => 'Betalinger', 'Payments History' => 'Betalingshistorikk ', 'Period must be in interval 1-24 months' => 'Perioden må være mellom 1-24 måneder', 'Period must be in interval 1-5 years' => 'Perioden må være mellom 1-5 år', 'Period must be in interval 1-90 days' => 'Perioden må være mellom 1-90 dager', 'Phone' => 'Telefon', 'Plain-Text Message' => 'Ren-tekst melding', 'Please %slogin%s to your existing account.%sIf you have not completed payment, you will be able to complete it after login' => 'Vennligst %slogg inn%s med din eksisterende konto %shvis du ikke har fullført betalingen, så kan du fullføre den etter du har logget inn', 'Please Select' => 'Vennligst velg', 'Please agree to User Agreement' => 'Vennligst godta brukervilkårene', 'Please choose' => 'Vennligst velg', 'Please choose a Credit Card Type' => 'Vennligst velg en type Kredittkort', 'Please choose a membership type' => 'Vennligst velg type medlemskap', 'Please choose a payment system' => 'Vennligst velg et betalingssystem', 'Please choose state' => 'Vennligst velg fylke', 'Please enter %s' => 'Vennligst skriv inn %s', 'Please enter City' => 'Vennligst skriv inn sted', 'Please enter Country' => 'Vennlist skriv inn land', 'Please enter Credit Card Code' => 'Vennligst skriv inn Kredittkortkode', 'Please enter Credit Card Number' => 'Vennligst skriv inn Kredittkortnummer', 'Please enter Password' => 'Vennligst skriv inn Passord', 'Please enter State' => 'Vennlist skriv inn fylke', 'Please enter Street Address' => 'Vennligst skriv inn gateadresse', 'Please enter ZIP code' => 'Vennligst skriv inn postnummer', 'Please enter a valid e-mail address' => 'Vennligst skriv inn en gyldig epost adresse', 'Please enter credit card holder first name' => 'Vennligst skriv inn kredittkortholders fornavn', 'Please enter credit card holder last name' => 'Vennligst skriv kredittkortholders etternavn', 'Please enter credit card holder name' => 'Vennligst skriv inn kredittkortholders navn', 'Please enter housenumber' => 'Vennligst skriv inn hjemmetelefonnummer', 'Please enter phone number' => 'Vennlist skriv inn telefonnummer', 'Please enter valid Email' => 'Vennligst skriv inn en gydlig epost', 'Please enter valid Username. It must contain at least %d characters' => 'Vennligst skriv inn gyldig brukernavn. Det må inneholde minst %d tegn', 'Please enter your First Name' => 'Vennligst skriv inn ditt Fornavn', 'Please enter your Last Name' => 'Vennligst skriv inn dit Etternavn', 'Please enter your current password for validation' => 'Vennligst skriv inn nytt passord for validering', 'Please login' => 'Vennligst logg inn ', 'Please select payment system for payment' => 'Vennligst velg betalingssystem til betaling', 'Please use %sAdd/Renew subscription%s form to order or renew subscription.' => 'Vennligst bruk %sLegg til/Forny abonnement%s skjema for å bestille eller fornye et abonnement.', 'Please wait %d seconds before next login attempt' => 'Vennligst vent %d sekunder før du prøver å logge inn igjen', 'Prev' => 'Forrige', 'Price' => 'Pris', 'Product' => 'Produkt', 'Product(s) to display' => 'Produkt(er) som skal vises', 'Products' => 'Produkter', 'Profile' => 'Rediger profil', 'Qty' => 'Antall', 'Quantity' => 'Kvantitet', 'Quick Order' => 'Hurtigbestilling', 'Re-Open Ticket' => 'Gjenåpne Ticket', 'Record' => 'Dokument', 'Records that match all these conditions' => 'Dokumenter som matcher disse betingelsene', 'Reference number is:' => 'Referansenummeret er:', 'Referred Affiliate' => 'Henvist Partner', 'Refresh' => 'Last inn igjen', 'Register' => 'Registrer', 'Remove Users when user record removed from aMember must the related record be removed from %s' => 'Fjern brukere når bruker informasjon slettes fra aMember må de relaterte informasjonen bli slettet fra %s', 'Reply' => 'Svar', 'Retry On Failure if the recurring billing has failed, aMember can repeat it after several days, and extend customer subscription for that period enter number of days to repeat billing attempt' => 'Prøv igjen ved feil hvis den faste belastningen har feilet, kan aMember gjøre et nytt forsøk etter noen dager, og forlenge kundens abonnement i denne perioden skriv inn antall dager per forsøk på belastning', 'Return' => 'Gå tilbake', 'Return and try again' => 'Gå tilbake og forsøk på nytt', 'Review/Pay Commissions' => 'Se over/betal partnerprovisjon', 'Run Report' => 'Kjør rapport', 'Running %s' => 'Kjører %s', 'Save' => 'Lagre', 'Save Profile' => 'Lagre profil', 'Search' => 'Søk', 'Search Products' => 'Søk produkter', 'Security code is invalid' => 'Sikkerhetskoden er ugyldig', 'Select a condition to add into search' => 'Velg en forutsetning til søket', 'Select all %s records matching your search' => 'Velg all %s informasjon som passer med søket ditt', 'Session expired, please enter username and password again' => 'Sesjon utgått, vennligst skriv inn brukernavn og passord igjen', 'Shipping' => 'Frakt', 'Shopping Cart' => 'Handlekurv', 'Sign-up' => 'Registre', 'Signup Form' => 'Registreringsskjema', 'Signup here' => 'Registrer deg her', 'Simple Search Users' => 'Forenklet brukersøk', 'Sorry, it is impossible to use this payment method for this order. Please select another payment method' => 'Beklager, det er ikke mulig å bruke denne betalingsmetoden for denne ordre. Vennligst velg en annen betalingsmetode.', 'Sorry, seems you have used wrong link' => 'Beklager, du har brukt feil lenke', 'Source Code — Copy/Paste Into Your Website' => 'Kildekode — Kopier/lim inn til din Webside', 'Start' => 'Start', 'State' => 'Fylke', 'Status' => 'Status', 'Street' => 'Gate', 'Street Address' => 'Gateadresse', 'Subject' => 'Emne', 'Subject can not be empty' => 'Emne kan ikke være tomt', 'Subscribe to Site Newsletters' => 'Abonner på webside nyhetsbrev', 'Subscribers' => 'Abonnementer', 'Subscription Terms' => 'Abonnementsvilkår', 'Subscription/Product Title' => 'Abonnements/Produkts tittel ', 'Subtotal' => 'Delsum', 'Target URL' => 'Mål URL', 'Tax' => 'Mva', 'Tax Amount' => 'Mva-beløp', 'Terms' => 'Vilkår', 'Test Settings' => 'Test Konfigurasjon', 'Thank you for Signing up' => 'Takk for at du registrerte deg', 'The database has encountered a problem, please try again later.' => 'Databasen er midlertidig utilgjengelig, vennligst prøv igjen senere.', 'The password should be at least %d characters long' => 'Passordet må være minst %d tegn langt', 'The user name or password is incorrect' => 'Brukernavnet eller passordet er ikke korrekt', 'There are no confirmed payments for your account' => 'Det er ingen bekreftede betalinger for denne kontoen', 'This %s is blocked. Please contact site support to find out why' => 'Denne %s er blokkert. Vennligst ta kontakt med support for å finne årsaken', 'This coupon belongs to another customer' => 'Denne rabattkupongen er brukt av annen kunde', 'This is a required field' => 'Dette feltet må fylles inn', 'This page will be automatically refreshed within %s' => 'Denne siden vil bli automatisk lastet inn på nytt innen %s', 'This payment system could not handle payments in [%s] currency' => 'Dette betalingssystemet kan ikke håndtere betalinger i [%s] valuta ', 'This payment system could not handle zero-total invoices' => 'Dette betalingssystemet kan ikke håndtere fakturaer med en sum på 0', 'Ticket' => 'Feilmelding (Ticket)', 'Ticket has been submited' => 'Feilmelding (Ticket) er innlevert', 'Tickets' => 'Feilmeldinger (Tickets)', 'Title' => 'Tittel', 'To add fields into the form, move item from \'Available Bricks\' to \'Form Bricks\'. To remove fields, move it back to \'Available Bricks\'. To make form multi-page, insert \'PageSeparator\' item into the place where you want page to be split.' => 'For å legge til felter i skjemaet, flytt enhet fra \'Tilgjengelige Elementer\' til \'Skjema Elementer\' For å fjerne felter, flytt det tilbake til \'Tilgjengelige Elementer\'. For å gjøre et skjema flersidig, sett inn \'SideSkift\' enhet på det stedet du ønsker delingen.', 'Total' => 'Totalt', 'Try again' => 'Prøv igjen', 'Unknown period unit: %s' => 'Ukjent periode enhet: %s', 'Unsubscribe from all e-mail messages' => 'Stopp alle abonnement fra alle epost nyhetsbrev', 'Unsubscription Confirmation' => 'Oppsigelse-bekreftelse', 'Update' => 'Oppdater', 'Update Credit Card Info' => 'Oppdater Kredittkort Info', 'Updated' => 'Oppdatert', 'Upgrade Subscription' => 'Oppgrader abonnement', 'Use Database Connection other than configured for aMember' => 'Bruk en annen databasetilknytning enn den som er konfigurert for aMember', 'Use another MySQL Db use custom host, user, password for %s database connectionUsually you can leave this unchecked' => 'Bruk en annen MySQL Db bruk egendefinert host, bruker, passord for %s database tilkobling. Som regel kan du la dette være tomt', 'User' => 'Bruker', 'User Agreement' => 'Brukervilkår', 'User Info' => 'Brukerinformasjon', 'User Search' => 'Brukersøk', 'Username' => 'Brukernavn', 'Username you can choose new username here or keep it unchanged. Username must be %d or more characters in length and may only contain small letters, numbers, and underscore' => 'Brukernavn du kan velge et nytt brukernavn her eller beholde det gamle. Brukernavn må være %d eller flere tegn langt, og kan bare inneholde små bokstaver, tall eller understreker', 'Username %s is already taken. Please choose another username' => 'Brukernavn %s er opptatt. Vennligst velg et annet brukernavn', 'Username contains invalid characters - please use digits, letters or spaces' => 'Brukernavn inneholder ugyldige tegn - vennligst bruk kun tall, bokstaver og mellomrom', 'Username contains invalid characters - please use digits, letters, dash and underscore' => 'Brukernavn inneholder ugyldige tegn - vennligst bruk både bokstaver og tall', 'Username/Email' => 'E-post adresse eller brukernavn', 'Users subscribed to Newsletter Threads #' => 'Brukere abonnert på Nyhetsbrev tråder #', 'Validate E-Mail Address by sending e-mail message with code' => 'Bekreft epost adresse ved å sende epost beskjeden med kode', 'View Basket' => 'Sjekk Handlekurv', 'Week' => 'Uke', 'Wrong code or code expired - please start signup process again' => 'Feil kode eller så er koden utgått - vennligst start registrerings prosessen igjen', 'Wrong parameters, error #1253' => 'Feil parametere, feil #1253', 'Wrong verification code' => 'Feil verifikasjonskode', 'Wrongly signed URL, please contact site admin' => 'Feil signert URL, vennligst kontakt sidens admin', 'Year' => 'År', 'Years' => 'År', 'Yes, I want to cancel subscription' => 'Ja, jeg ønsker å kansellere abonnementet', 'Yes, continue' => 'Ja, fortsett', 'You are logged-in as %s. %sLogout%s to signup as new user.' => 'Du er logget inn som %s. %sLogg ut%s for å registrere en ny bruker.', 'You have no access to %s' => 'Du har ikke tilgang til %s', 'You have no active subscriptions' => 'Du har ingen aktive abonnement', 'You have no enough permissions for this operation' => 'Du har ikke tilgang til å utføre denne operasjonen', 'You have no items in your basket - please add something to your basket before checkout' => 'Du har ingen artikler i din handlekurv - vennligst fyll opp i handlekurv før du går til kassen ', 'You must be authorized to access this area' => 'Du må være autorisert for å få tilgang til dette området', 'Your Basket' => 'Din handlekurv', 'Your Current Password if you are changing password, please enter your current password for validation' => 'Ditt nåværende Passord hvis du skrifter passord, vennligst skriv inn ditt nåværende passord for validering.', 'Your E-Mail Address a confirmation email will be sent to you at this address' => 'Din e-post adresse en bekreftelses e-post vil bli sendt til deg på denne adresse', 'Your Membership Information' => 'Ditt medlemskap - informasjon', 'Your Subscriptions' => 'Dine abonnementer', 'Your password is too long' => 'Ditt passord er for langt', 'Your payment is not yet confirmed by payment system. It may take several minutes to get confirmation of the payment.' => 'Din betaling har ikke blitt bekreftet av betalingssystemet enda. Det kan ta noen få minutter før vi får bekreftelsen på betalingen.', 'Your subject is too verbose' => 'Emne ditt inneholder for mange ord', 'ZIP' => 'Postnummer', 'ZIP Code' => 'Postnummer', '[Select country]' => '[Velg Land]', '[Select state]' => '[Velg Fylke]', '_default_locale' => 'en_US', 'admin' => 'admin', 'affiliate program commissions' => 'Partner program provisjoner', 'ago' => 'siden', 'banned' => 'blokkert', 'commission found by next rules' => 'provisjon funnet av neste regler', 'days' => 'dager', 'email' => 'e-post', 'expiration' => 'utløpsfrist', 'filtered' => 'Filtrert', 'for example: 1111-2222-3333-4444' => 'for eksempel 1111-2222-3333-4444', 'hrs' => 'timer', 'ip' => 'ip', 'just now' => 'akkurat nå', 'login' => 'Logg inn', 'min' => 'min', 'no records' => 'ingen informasjon', 'number of affiliate program clicks' => 'antall partner program klikk', 'of products' => 'av produkter', 'on %d-th day' => 'på %d-ende dag', 'pay using credit card or PayPal' => 'betal med kredittkort eller PayPal', 'pay using wire transfer or by sending offline check' => 'betal ved bankoverføring, sjekk eller annet godkjent betalingsmiddel', 'return' => 'returner', 'seconds' => 'sekunder', 'start' => 'start', 'use 4111-1111-1111-1111 for successful transaction' => 'bruk 4111-1111-1111-1111 for suksessfull transaksjon', ); PK\ $㨺default/language/admin/nl.phpnu[ '%d dagen na beëindiging', '%d days before expiration' => '%d dagen voor beëindiging', '%d user(s) matches your search' => '%d gebruiker(s) komen overeen met je zoekopdracht', '%d-th subscription day' => '%d-e abonnementsdag', '%s Plugins' => '%s Plugins', '-- Please Select --' => '-- Selecteren s.v.p. --', '..th subscription day (starts from 2)' => '..e abonnementsdag (begint vanaf 2)', 'API Keys' => 'API Sleutels', 'Access Method' => 'Toegangsmethode', 'Account Sharing Prevention' => 'Bescherming tegen het delen van account', 'Account Verification' => 'Accountverificatie', 'Add Chargeback' => 'Toevoegen Terugvordering', 'Add Invoice' => 'Factuur Toevoegen', 'Add Payment' => 'Betaling Toevoegen', 'Add Payment Manually' => 'Betaling handmatig toevoegen', 'Add Refund' => 'Toevoegen Terugbetaling', 'Add Report to My Dashboard' => 'Toevoegen Rapport aan Mijn Dashboard', 'Add Signature to Response' => 'Voeg een handtekening toe aan de reaktie', 'Add Subscription' => 'Abonnement Toevoegen', 'Add User Fields' => 'Velden Toevoegen', 'Add points to affiliate for each %s in payment' => 'Ken affiliate punten toe voor elke %s van de betaling', 'Additional' => 'Extra', 'Admin Accounts' => 'Beheer Accounts', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'E-mailadres Beheerder gebruikt om e-mailberichten aan beheerder te versturen en als standaard uitgaand adres', 'Admin Free Subscription Notifications to admin once free signup is completed' => 'Beheerder Gratis abonnement Noticifaties aan admin indien gratis aanmelding is voltooid', 'Admin Log' => 'Beheerderslogboek', 'Admin Pages Theme' => 'Thema Beheerderspagina\'s', 'Admin Payment Notifications to admin once payment is received' => 'Beheerder Betaalnotificaties aan beheerder indien betaling is ontvangen', 'Admin Settings' => 'Beheerderinstellingen', 'Admin notification' => 'Beheerder kennisgeving', 'Admin username must be alphanumeric in small caps' => 'Beheerder gebruikersnaam moet alfanumeriek en in kleine letters zijn', 'Administrator Login' => 'Beheerder Login', 'Administrator has been removed, id [%d]' => 'Beheerder is verwijderd, id [%d]', 'Advanced Settings' => 'Geavanceerde Instellingen', 'Affiliate Commission' => 'Affiliateprovisie', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Levensduur Affiliate Cookie dagen om cookies te bewaren over doorverwijzende affiliate', 'Affiliate Registration E-Mail' => 'Affiliate Registratie-e-mail', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Affiliates Uitbetaaldag kies een dag van de maand wanneer uitbetaling wordt gegenereerd', 'Affiliates Signup Type' => 'Type Affiliate-aanmelding', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'Na het maken van veranderingen aan htpasswd beschermde gedeeltes, denk eraan [Hulpmiddelen->Herbouwen Db] uit te voeren om het htpasswd bestand te verversen.', 'All Subscription Period' => 'Alle Abonnementsperioden', 'All new users automatically become affiliates' => 'Alle nieuwe gebruikers worden automatisch affiliates', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Toegestane E-mailaantal voer het e-mailaantal dat is toegestaan binnen bovenstaande periode', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Toegestane E-mailperiode kies als je host het aantal e-mailberichten per dag of per uur beperkt', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Altijd Onthouden als ingesteld op Ja, gebruiker niet vragen - altijd onthouden', 'Amazon SES' => 'Amazon SES', 'Amazon SES Access Id' => 'Amazon SES Toegangs ID', 'Amazon SES Secret Key' => 'Amazon SES Geheime Sleutel', 'American Date Format' => 'Amerikaans datumformaat', 'Apply Tax?' => 'Belasting Toepassen?', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'Toepassen op terugkerende? couponkorting toepassen op terugkerende rekeningen?', 'Approve' => 'Goedkeuren', 'Assign Category' => 'Categorie Toewijzen', 'At least one billing plan must be added' => 'Minstens één betaalplan moet worden toegevoegd', 'Available' => 'Beschikbaar', 'Available Upgrades' => 'Beschikbare Upgrades', 'Available for users from groups' => 'Beschikbaar voor gebruikers uit groepen', 'Back to Dashboard' => 'Terug naar Dashboard', 'Backup' => 'Backup', 'Banner' => 'Banner', 'Banners' => 'Banners', 'Basket HTML Code' => 'Mandje HTML Code', 'Billing' => 'Facturering', 'Blob (unlimited length binary data)' => 'Blob (binaire data van oneindige lengte)', 'Blocking IP/E-Mail' => 'Blokkeren IP/E-mail', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Tijdelijk onbeschikbaar voor gepland onderhoud. Probeer nogmaals over een minuutje...', 'Browse' => 'Bladeren', 'Browse Found Users' => 'Blader Gevonden Gebruikers', 'Browse Users' => 'Gebruikers Bladeren', 'Bruteforce Protection' => 'Brute Kracht Bescherming', 'Build Demo' => 'Aanmaken Demo', 'Building demo records' => 'Aanmaken demorecords', 'Button/Link HTML Code' => 'Knop/Link HTML Code', 'Can not find user with such username' => 'Kan geen gebruiker vinden met dergelijke gebruikersnaam', 'Can not find user with such username or email' => 'Kan gebruiker met dergelijke gebruikersnaam of e-mail niet vinden', 'Can\'t be changed because your server have suhosin extension enabled' => 'Kan niet gewijzigd worden, omdat je server de suhosin extensie ingeschakeld heeft', 'Cancellations' => 'Annuleringen', 'Change Configuration Settings' => 'Wijzig Configuratie Instellingen', 'Change Paysystem' => 'Verander Betaalsysteem', 'Charge Second Price Once' => 'Tweede Prijs Eenmalig in Rekening Brengen', 'Charge Second Price x Times' => 'Tweede Prijs x Keer in Rekening Brengen', 'Check for beta version' => 'Controleer op beta versie', 'CheckBoxes' => 'Checkboxen', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => 'Kies %1$sBestand%2$s > %1$sOpslaan Als%2$s', 'Choose Products and/or Product Categories that allows access' => 'Kies Producten en/of Productcategorieën die toegang geven', 'Choose Upgrades to Install' => 'Kies te installeren upgrades', 'Choose action when locked %s used by customer during signup' => 'Kies actie wanneer geblokkeerde %s gebruikt door klant tijdens aanmelding', 'Clean up v4 Database' => 'Opschonen v4 Database', 'Cleaning up' => 'Aan het opruimen', 'Cleanup' => 'Opruimen', 'Clear' => 'Schoon', 'Clear Access Log' => 'Opschonen Toegangslogboek', 'Clear Incomplete Invoices' => 'Opschonen Onvoltooide Facturen', 'Click to Expand' => 'Klik om uit te vouwen', 'Code Length generated coupon code length between 4 and 32' => 'Codelengte lengte van de gegenereerde coupon code tussen 4 en 32', 'Collapse Menu' => 'Menu Invouwen', 'Comma' => 'Komma', 'Commission earned' => 'Verdiende provisie', 'Commission for First Payment calculated for first payment in each invoice' => 'Provisie op Eerste Betaling berekend over eerste betaling van iedere factuur', 'Commission for Free Signup calculated for first customer invoice only' => 'Provisie op Gratis Aanmelding alleen berekend over de eerste factuur van de klant', 'Commission for Rebills' => 'Provisie op Terugkerende Betalingen', 'Conditions' => 'Voorwaarden', 'Configured License Keys' => 'Geconfigureerde Licentiesleutels', 'Copy' => 'Kopieren', 'Copy Upgrades' => 'Kopiëer upgrades', 'Copy from another language' => 'Kopieer van een andere taal', 'Core' => 'Kern', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Kon bestand [%s] niet downloaden. Fout %s. S.v.p. later %snogmaals proberen%s.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'Kon lijst met upgrades niet van remote server halen. %sNogmaals proberen%s', 'Could not fetch upgrades list. Connection error [%s]' => 'Kon lijst met upgrades niet ophalen. Verbindingsfout [%s]', 'Coupons' => 'Coupons', 'Coupons Batches' => 'Couponpartijen', 'Coupons Count how many coupons need to be generated' => 'Coupon Teller aantal coupons dat gegenereerd moet worden', 'Create Folder' => 'Maak Map', 'Create Session Key' => 'Creëer Sessiesleutel', 'Create ticket as' => 'Ticket aanmaken als', 'Custom Commission Rules added' => 'Aangepaste Provisieregels toegevoegd', 'Custom HTML' => 'Aangepaste HTML', 'Custom Signup Form Title keep empty to use default title' => 'Titel Aangepast Aanmeldformulier leeglaten om standaard titel te gebruiken', 'Customer' => 'Klant', 'Customize Dashboard' => 'Dashboard Aanpassen', 'Daily' => 'Dagelijks', 'Date Time' => 'Datum Tijd', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Datum om te Verwijderen alle records voor deze datum zullen worden verwijderd van de geselecteerde tabellen', 'Dates date range when coupon can be used' => 'Datums perdiode waarbinnen een coupon gebruikt kan woren', 'Dates can be in the folowing formats' => 'Datums kunnen in de volgende formaten zijn', 'Days to Send' => 'Aantal dagen te versturen', 'Default - user clicks a link to become affiliate' => 'Standaard - gebruiker klikt een link om affiliate te worden', 'Default Billing Plan' => 'Standaard Factureringsplan', 'Default Commission' => 'Standaard commissie', 'Default Locale' => 'Standaard Landinstelling', 'Default Signup' => 'Standaard Aanmelding', 'Default for Members' => 'Standaard voor Leden', 'Default value for field (that is default value for inputs, not SQL DEFAULT)' => 'Standaardwaarde voor veld (dat betekent de standaardwaarde voor input, niet SQL DEFAULT)', 'Delete Old Records' => 'Verwijder Oude Records', 'Delete Saved Search?' => 'Verwijder Opgeslagen Zoekopdracht?', 'Delete payment and access record' => 'Verwijder betaal- en toegangsrecord', 'Delimiter' => 'Scheidingsteken', 'Demo History' => 'Demo Geschiedenis', 'Description displayed to visitors on order page below the title' => 'Beschrijving vertoond aan bezoekers op bestelpagina onder de titel', 'Details' => 'Details', 'Die and show ugly error message' => '\'Die\' en toon lelijke foutmelding', 'Digits and latin letters only please' => 'Alleen cijfers en Latijnse letters s.v.p.', 'Disable auto-locking for this customer' => 'Automatische blokkering voor deze klant uitschakelen', 'Disallow new Signups by %s' => 'Weiger nieuwe Aanmeldingen via %s', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'Bestelling van dit product weigeren als gebruiker in bezit is van wanneer gebruiker dit abonnement bestelt, wordt gecontroleerd of gebruiker geen van de volgende abonnementen heeft', 'Display Language Choice' => 'Vertoon Taalkeuze', 'Display Mode' => 'Afbeeldingsmodus', 'Display error message' => 'Toon foutmelding', 'Do not generate products use existing products for demo records' => 'Genereer geen producten gebruik bestaande producten voor demorecords', 'Do you really want to change Rebill Date for this invoice?' => 'Wil je werkelijk de Herhaalbetalingsdatum van deze factuur aanpassen?', 'Do you really want to refund payment' => 'Wil je werkelijk terugbetalen', 'Do you really want to stop this subscription?' => 'Wil je werkelijk dit abonnement beëindigen?', 'Documentation' => 'Documentatie', 'Download Upgrades' => 'Download upgrades', 'Duration:' => 'Duur:', 'E-Mail Address to Send to' => 'E-mailadres aan te Versturen', 'E-Mail Backup Address' => 'E-mail Backup Adres', 'E-Mail Commission to Admin' => 'E-mail Provisie naar Beheerder', 'E-Mail Commission to Affiliate' => 'E-mail Provisie naar Affiliate', 'E-Mail Database Backup' => 'Backup van de E-maildatabase', 'E-Mail Queue' => 'E-mail Wachtrij', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'Naam E-mailafzender gebruikt om de naam van de afzender te tonen in uitgaande e-mails', 'E-Mail Sending' => 'E-mail aan het versturen', 'E-Mail System Configuration' => 'E-mailsysteem Configuratie', 'E-Mail Type' => 'Type E-mail', 'E-Mail Users' => 'E-mail Gebruikers', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'E-mail is succesvol verzonden aan %s klanten. ID van de e-mailpartij is %s', 'E-Mail sending started' => 'E-mail aan het versturen gestart', 'E-Mails History' => 'E-mailhistorie', 'E-Mails by Admin Request' => 'E-mails op Verzoek Beheerder', 'E-Mails by User Request' => 'E-mails op Verzoek Gebruiker', 'Earn points for %s in payment' => 'Verdien punten voor %s van de betaling', 'Edit Custom Commission Rules' => 'Aangepaste Provisieregels Bewerken', 'Edit Groups' => 'Bewerk Groepen', 'Edit Messages' => 'Berichten Bewerken', 'Email Backup Frequency' => 'E-mail Backup Frequentie', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'E-mail Verzendwijze S.V.P. ONGEWIJZIGD LATEN als e-mailen vanuit aMember werkt', 'Email Sent' => 'E-mail verstuurd', 'Email address is required field.' => 'E-mailadres is een vereist veld', 'Enable plugins if necessary' => 'Indien nodig plugins inschakelen', 'Enter Maintenance Mode' => 'Onderhoudsmodus Starten', 'Enter admin password for confirmation' => 'Voer ter bevestiging het wachtwoord van de beheerder in.', 'Error Log' => 'Foutenlogboek', 'Error/Debug Log' => 'Fouten/Debug Logboek', 'Errors' => 'Fouten', 'Errors:' => 'Fouten:', 'European Date Format' => 'Europees datumformaat', 'Every %s' => 'Iedere %s', 'Exchange Rate' => 'Wisselkoers', 'Exchange Rate enter cost of 1 (one) %s' => 'Wisselkoers voer in de kosten van 1 (één) %s', 'Field Name' => 'Veldnaam', 'Field Title' => 'Veldtitel', 'Field Values' => 'Veldwaarden', 'File (max filesize %s)' => 'Bestand (max bestandsgrootte %s)', 'File is required' => 'Bestand is vereist', 'Filter by Category' => 'Filter op categorie', 'Filter by String' => 'Filter met tekenreeks', 'Filter by name or description' => 'Filter op naam of omschrijving', 'Filter by string or by invoice#/member#' => 'Filter op tekenreeks of op factuur#/lid#', 'First Period' => 'Eerste Periode', 'First Price' => 'Eerste Prijs', 'First Price price of first period of subscription' => 'Eerste Prijs prijs van eerste periode van abonnement', 'First Tax' => 'Eerste Belasting', 'First Total' => 'Eerste Totaal', 'First and Last Name' => 'Voor- en achternaam', 'First available protected url' => 'Eerst beschikbare beschermde URL', 'First visited' => 'Eerst bezocht', 'Fix aMember Pro License Key' => 'Herstel aMember Pro Licentiesleutel', 'Fixed Url' => 'Vaste URL', 'Fixed date' => 'Vaste datum', 'FlowPlayer License Key you may get your key in %smembers area%s' => 'FlowPlayer Licentiesleutel je kunt je sleutel verkrijgen in %sleden gedeelte%s', 'Folder URL' => 'Map URL', 'Form Type' => 'Formuliertype', 'Forms Editor' => 'Formulieren Editor', 'Future' => 'Toekomst', 'General' => 'Algemeen', 'General Link' => 'Algemene Link', 'General Settings' => 'Algemene Instellingen', 'Generate' => 'Genereren', 'Generate Basket HTML' => 'Genereer Mandje HTML', 'Generate Button HTML' => 'Genereer Knop HTML', 'Generate Payout Manually' => 'Handmatig Uitbetaling Genereren', 'Generate Report' => 'Genereer Rapport', 'Generated' => 'Gegenereerd', 'Generation of demo data was terminated while processing. Not all records were created.' => 'Generatie van demodata was afgebroken tijdens verwerking. Niet alle records zijn aangemaakt.', 'Get Available Upgrades List' => 'Lijst ophalen met beschikbare upgrades', 'Get New Password' => 'Verkrijg Nieuw Wachtwoord', 'Global' => 'Algemeen', 'Graph Bar' => 'Staafgrafiek', 'Graph Line' => 'Lijngrafiek', 'Help & Support' => 'Hulp & Ondersteuning', 'Hostname' => 'Hostnaam', 'Hour' => 'Uur', 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database' => 'Ik begrijp dat een upgrade mijn aangepaste PHP bestanden en sjablonen overschrijft, ik heb al een backup gemaakt van de aMember folder en database', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'BELANGRIJK BERICHT: Dit zal niet de inhoud beschermen. Als iemand de link url weet, zal hij in staat zijn de link zonder problemen te openen. Dit is alleen om te controleren welke extra links de gebruiker zal zien na in te loggen op het lidmaatschapgedeelte.', 'IP' => 'IP', 'IP within' => 'IP binnen', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Als je van de betaaldienst verandert, kun je deze pagina gebruiken om bestaande abonnementen van de ene betaaldienst naar de andere te wijzigen. Het is alleen mogelijk als volledige creditcard-informatie is opgeslagen aan de kant van aMember.', 'Image' => 'Afbeelding', 'Import Finished' => 'Import Beëindigd', 'Import Users' => 'Gebruikers Importeren', 'Important Notice:' => 'Belangrijke melding:', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'In de \'Exporteren van tekstbestanden\' dialoog, selecteer de opties die je wilt en klik dan op %1$sOK%2$s.', 'In the File name box, type a name for the file.' => 'Voer een naam in voor het bestand, in de box voor Bestandsnaam.', 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.' => 'In de lijst met bestandstypen, selecteer %1$sTekst CSV%2$s en klik %1$sOpslaan%2$s. Je kunt de melding te zien krijgen. Klik %1$sHuidig Formaat Behouden%2$s.', 'Insert' => 'Invoegen', 'Install Updates' => 'Updates Installeren', 'Integer field (only numbers)' => 'Integer veld (alleen hele getallen)', 'Integration plugins' => 'Integratie plugins', 'Internal PHP mail() function (default)' => 'Interne PHP mail() functie (standaard)', 'Invoice Log' => 'Facturen Logboek', 'Invoices' => 'Facturen', 'Invoices Per User' => 'Facturen Per Gebruiker', 'Is Affiliate?' => 'Is dit een affiliate?', 'Is Approved' => 'Is Toegestaan', 'Is Disabled' => 'Is Uitgeschakeld', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'Is Uitgeschakeld? productsortering uitschakelen, verberg het van aanmeld- en vernieuwformulieren', 'It is required to setup a cron job to trigger backup generation' => 'Het is nodig om een CRON job op te zetten om backup generatie in werking te zetten', 'Items' => 'Items', 'JavaScript Code' => 'Javascript code', 'Key' => 'Sleutel', 'Key must be 20 chars or longer' => 'Sleutel moet bestaan uit 20 karakters of meer', 'Languages' => 'Talen', 'Last %s Customers' => 'Laatste %s klanten', 'Last %s Helpdesk Messages' => 'Laatste %s Helpdeskberichten', 'Last %s Payments' => 'Laatste %s Betalingen', 'Last Payments List' => 'Overzicht Laatste Betalingen', 'Last Users List' => 'Overzicht Laatste Gebruikers', 'Last available protected url' => 'Laatst beschikbare beschermde URL', 'Last existing subscription date of this product' => 'Laatste bestaande abonnementsdatum van dit product', 'Last expiration date in the renewal group' => 'Laatste expiratiedatum in de vernieuwingsgroep', 'Last login' => 'Laatste Login', 'Length of admin password must be from %d to %d' => 'Lengte van het beheerderswachtwoord moet vallen tussen %d en %d', 'Length of username must be from %d to %d' => 'Lengte van de gebruikersnaam moet vallen tussen %d en %d', 'Light Boxes' => 'Lightboxen', 'Lightbox Main Image' => 'Lightbox Hoofdafbeelding', 'Lightbox Thumbnail Image' => 'Lightbox Mini-afbeelding', 'Limit Downloads Count' => 'Beperk Downloads Teller', 'Lines Proccessed:' => 'Regels verwerkt:', 'Lines Skipped:' => 'Regels overgeslagen:', 'Lines Success:' => 'Regels geslaagd:', 'Link to reset your password was sent to your Email.' => 'Link om je wachtwoord te resetten is verstuurd naar je e-mail.', 'Lock' => 'Blokkeren', 'Locked Value' => 'Geblokkeerde Waarde', 'Log Outgoing E-Mail Messages for ... days' => 'Leg Uitgaande E-mailberichten vast voor ... dagen', 'Log in' => 'Inloggen', 'Logged in as %s' => 'Ingelogd als %s', 'Login Page' => 'Loginpagina', 'Logs' => 'Logboeken', 'Logs: Access' => 'Logboek: Toegang', 'Logs: Admin Log' => 'Logboek: Beheerlogboek', 'Logs: Errors' => 'Logboek: Foutmeldingen', 'Logs: Invoice' => 'Logboek: Facturen', 'Logs: Mail Queue' => 'Logboek: E-mailwachtrij', 'Lookup' => 'Opzoeken', 'Lost your password?' => 'Wachtwoord kwijt?', 'Mail' => 'Mail', 'Maintenance Mode' => 'Onderhoudsmodus', 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s' => 'Onderhoudsmodus is momenteel ingeschakeld. Alleen ingelogde beheerders zoals jij hebben toegang. %sUitschakelen%s', 'Manage Product Upgrade Paths' => 'Beheer Product Opwaardeerpaden', 'Manage Products' => 'Beheer Producten', 'Manually Added' => 'Handmatig Toegevoegd', 'Mark NOT Paid' => 'Als NIET Betaald Markeren', 'Mark Paid' => 'Als Betaald Markeren', 'Mass Subscribe' => 'Bulk Aanmelding', 'Membership' => 'Lidmaatschap', 'Membership Info Page' => 'Lidmaatschapsinformatiepagina', 'Merge' => 'Samenvoegen', 'Miscellaneous' => 'Overig', 'Monthly' => 'Maandelijks', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Titel Meervoudige Bestelling als de gebruiker meerdere producten bestelt, toon dan het volgende op het betaalsysteem in plaats van de productnaam', 'Name of Preset' => 'Naam van voorkeurinstelling', 'Need points to get %s discount' => 'Punten nodig om %s korting te krijgen', 'New Autoresponder' => 'Nieuwe Autoresponder', 'New Expiration E-Mail' => 'Nieuwe Beëindiging-e-mail', 'New Modules Available' => 'Nieuwe Modules Beschikbaar', 'New Rewrite' => 'New Rewrite', 'New Ticket Autoresponder to Customer aMember will email an autoresponder to user each time user create new ticket' => 'Nieuw Ticket Autoresponder aan Klant aMember zal iedere keer dat gebruiker een nieuw ticket aanmaakt een autoresponder aan de gebruiker e-mailen', 'New password has been e-mailed to your e-mail address' => 'Nieuw wachtwoord is naar je e-mailadres verstuurd', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'Geen creditcards opgeslagen voor deze gebruiker. %sToevoegen Creditcard%s', 'No Invoices Found' => 'Geen Facturen Gevonden', 'No Tax' => 'Geen Belasting', 'No Updates Available' => 'Geen updates beschikbaar', 'No more charges' => 'Geen andere betalingen', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'Geen enkele regel gevonden in het bestand. Het lijkt erop dat het bestand leeg is. Je kunt terugkeren en een ander bestand proberen.', 'No search name passed' => 'Geen zoeknaam opgegeven', 'No upgrades to install' => 'Geen upgrades om te installeren', 'Not Approved' => 'Niet Goedgekeurd', 'Not Approved Users' => 'Niet Goedgekeurde Gebruikers', 'Not Confirmed Users' => 'Onbevestigde Gebruikers', 'Not-SQL field (default)' => 'Niet-SQL veld (standaard)', 'Number of Payments to display' => 'Aantal te tonen betalingen', 'Number of Users to display' => 'Aantal te tonen gebruikers', 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.' => 'Aantal facturen die goedkeuring nodig hebben: %d. %sKlik hier%s om deze facturen te beoordelen.', 'Number of users who require approval: %d. %sClick here%s to review these users.' => 'Aantal gebruikers die goedkeuring nodig hebben: %d. %sKlik hier%s om deze gebruikers te beoordelen.', 'Numeric field' => 'Numeriek veld', 'OTO - Offer to purchase additional product (with optional discount)' => 'OTO - Aanbieden van aanvullende producten (met optioneel korting)', 'One field can be assigned to one column only, you assigned following fields to several columns: ' => 'Een veld kan maar aan één kolom worden toegewezen, je hebt de volgende velden toegewezen aan meedere kolommen:', 'One field can be assigned to one column only.' => 'Eén veld kan slechts aan één kolom worden toegekend', 'Only admin can enable user as an affiliate' => 'Alleen beheerder kan gebruiker machtigen tot affiliate', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Uitgaand E-mailadres gebruikt als Van: adres voor het verzenden van e-mailberichten aan gebruikers. Indien leeg, wordt [E-mailadres Beheerder] gebruikt', 'Overwrite User if Exist User with Same Login' => 'Gebruiker overschrijven als gebruiker met dezelfde login bestaat', 'PDF Invoice' => 'PDF Factuur', 'Paid' => 'Betaald', 'Password Length' => 'Wachtwoordlengte', 'Password changed' => 'Wachtwoord gewijzigd', 'Password must not be equal to username' => 'Wachtwoord mag niet gelijk zijn aan gebruikersnaam', 'Passwords must be the same' => 'Wachtwoorden moeten identiek zijn', 'Path to Folder' => 'Pad naar map', 'Path/URL' => 'Pad/URL', 'Payment Receipt' => 'Betaalbewijs', 'Payment date' => 'Betaaldatum', 'Payment has been successfully refunded' => 'Betaling is met succes teruggestort', 'Payment#/Receipt#' => 'Betaal#/Kwitantie#', 'Payout %d Details' => 'Uitbetaling %d Details', 'Payout Details' => 'Uitbetalingsdetails', 'Paysystem' => 'Betaalsysteem', 'Pending Invoice Notification Rules' => 'Kennisgevingregels voor Hangende Facturen', 'Permissions' => 'Rechten', 'Please assign the following fields: ' => 'Wijs de volgende velden een waarde toe:', 'Please choose another field name. This name is already used' => 'Kies s.v.p. een andere veldnaam. Deze naam is al in gebruik.', 'Please enter valid e-mail address' => 'S.v.p. een geld e-mailadres invoeren', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'Voer je gebruikersnaam of e-mailadres in Je ontvangt via e-mail een link om een nieuw wachtwoord aan te maken.', 'Please note: By default, aMember does not change users password and login values to a generated value in cases where an existing email address is found. You may decide to update an existing record, in the next step of the import process, where a matching email or username already exists.' => 'Let op: Standaard wijzigt aMember geen gebruikerswachtwoorden en loginwaarden in een gegenereerde waarde in situaties waarbij een bestaand emailadres is gevonden. Je kunt besluiten een bestaand record bij te werken, waarbij de overeenkomende email of gebruikersnaam reeds bestaat, in de volgende stap van het importproces.', 'Please run %sRebuild Db%s to update status for imported customers' => 'Voer %sDb Herbouwen%s uit, om de status van geimporteerde klanten te verversen', 'Please select date before today' => 'Selecteer s.v.p. een datum voor vandaag', 'Please specify new rebill date: ' => 'S.v.p. een nieuwe herhaalbetalingsdatum specificeren:', 'Please wait' => 'Een moment s.v.p.', 'Plugins' => 'Plugins', 'Product Availability' => 'Productbeschikbaarheid', 'Product Category' => 'Product Categorie', 'Product Upgrades' => 'Productopwaarderingen', 'Products Per Invoice' => 'Producten Per Factuur', 'Protect Content' => 'Bescherm Inhoud', 'Protection Method' => 'Beveiligingsmethode', 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty' => 'Hoeveelheid standaard - 1, gewoonlijk is het niet nodig dit te wijzigen Eerste en Tweede Prijs is het totaal voor genoemde hoeveelheid', 'Quit Maintenance Mode' => 'Onderhoudsmodus Stoppen', 'REST API Documentation' => 'REST API Documentatie', 'RadioButtons' => 'Radioknoppen', 'Rebill' => 'Terugkerende Betaling', 'Rebill Second Price until cancelled' => 'Breng Tweede Prijs in rekening tot annulering', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Aantal terugkerende betalingen dit is het aantal betalingen die plaatsvinden tegen de Tweede Prijs', 'Rebuild Db' => 'Db Herbouwen', 'Receipt' => 'Kwitantie', 'Receipt#' => 'Kwitantie#', 'Recipients' => 'Ontvangers', 'Records Deleted Sucessfully' => 'Records Succesvol Verwijderd', 'Redirect URL' => 'Doorverwijs URL', 'Referrer' => 'Doorverwijzer', 'Refund Payment' => 'Terugbetalen', 'Remember Login remember username/password in cookies' => 'Login Onthouden gebruikersnaam/wachtwoor onthouden in cookies', 'Remind Password to Admin' => 'Herinner Wachtwoord aan Beheerder', 'Remind Password to Customer' => 'Herinner Wachtwoord aan Klant', 'Remove Category' => 'Categorie Verwijderen', 'Remove From Dashboard' => 'Verwijder van Dashboard', 'Repeat Action Handling' => 'Herhaal Handeling', 'Replace Product' => 'Vervang Product', 'Report Bugs' => 'Programmafouten Melden', 'Reports' => 'Rapporten', 'Reseller Packages' => 'Wederverkoper-pakketten', 'Resend' => 'Opnieuw versturen', 'Resend Email' => 'E-mail Opnieuw Versturen', 'Resend Signup E-Mail' => 'Aanmeld-e-mail opnieuw versturen', 'Resource' => 'Bron', 'Restore' => 'Herstellen', 'Retreive Access Parameters if necessary' => 'Indien nodig ophalen toegangsparameters', 'Return to Payouts List' => 'Terug naar Uitbetalingslijst', 'Root URL root script URL, usually %s' => 'Root URL root script URL, gebruikelijk %s', 'Root Url and License Keys' => 'Root URL en Licentiesleutels', 'Run Reports' => 'Uitvoeren Rapportages', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'SMTP Hostnaam', 'SMTP Hostname is required if you have enabled SMTP method' => 'SMTP Hostnaam is vereist als je SMTP methode hebt ingeschakeld', 'SMTP Password' => 'SMTP Wachtwoord', 'SMTP Port' => 'SMTP Poort', 'SMTP Security' => 'SMTP Beveiliging', 'SMTP Username' => 'SMTP Gebruikersnaam', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (kon niet gebruikt worden voor meervoudige-selectie en checkbox velden)', 'SQL Date Format' => 'SQL datumformaat', 'Sales Statistic' => 'Verkoop Statistieken', 'Save This Search' => 'Deze zoekopdracht opslaan', 'Saved Credit Cards' => 'Opgeslagen Creditcards', 'Saved Reports' => 'Opgeslagen Rapporten', 'Saved Search' => 'Opgeslagen Zoekopdracht', 'Second Period' => 'Tweede Periode', 'Second Price' => 'Tweede Prijs', 'Second Price price that must be billed for second and the following periods of subscription' => 'Tweede Prijs prijs die wordt berekend voor tweede en opvolgende termijnen van het abonnement', 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form' => 'Geheime Code als dit formulier niet gekozen is als standaard, is deze code (in URL) noodzakelijk om het formulier te openen', 'Secure Root URL secure URL, usually %s' => 'Beveiligde Root URL beveiligde URL, gebruikelijk %s', 'Select (Multiple Values)' => 'Selectie (Meerdere waarden)', 'Select (Single Value)' => 'Selectie (Enkele waarde)', 'Select a plugin' => 'Selecteer een plugin', 'Select option' => 'Selecteer optie', 'Selected for E-Mailing' => 'Geselecteerd voor e-mailing', 'Semicolon' => 'Puntkomma', 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member' => 'Verstuur Annuleringskennisgeving aan Beheerder', 'Send E-Mail Message' => 'Verstuur E-mailbericht', 'Send E-Mail Messages' => 'Verstuur E-mailberichten', 'Send E-Mail if customer has subscription (required)' => 'Verstuur e-mail als klant een abonnement heeft (vereist)', 'Send E-Mail only if customer has no subscription (optional)' => 'Verstuur e-mail alleen als klant geen abonnement heeft (optioneel)', 'Send New E-Mail' => 'Verstuur nieuwe e-mail', 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket' => 'Verstuur Kennisgeving van Nieuwe Berichten aan Beheerder aMember zal een kennisgevingsbericht e-mailen aan beheerder iedere keer als een gebruiker reageert op een ticket', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Verstuur Kennisgeving van Nieuwe Berichten aan Klant aMember zal een kennisgevingsbericht e-mailen aan gebruiker iedere keer als een beheerder reageert op een ticket', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'Verstuur Registratie-e-mail zodra klant het aanmeldformulier voltooid (vóór de betaling)', 'Send Registration E-Mail to this user' => 'Verstuur registratie-e-mail aan deze gebruiker', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Verstuur Aanmeld-e-mail zodra EERSTE abonnement is voltooid', 'Send Test E-Mail' => 'Verstuur Test E-mail', 'Send message' => 'Verstuur Bericht', 'Send reports to my email' => 'Verstuur rapporten naar mijn e-mail', 'Sender' => 'Afzender', 'Sending Test E-Mail...' => 'Test E-mail aan het versturen...', 'Sending e-mail (sent to %d from %d)' => 'E-mail aan het versturen (verstuurd aan %d door %d)', 'Session Storage' => 'Sessie-opslag', 'Setup/Configuration' => 'Setup/Configuratie', 'Shopping Cart Settings' => 'Winkelwagen Instellingen', 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation' => 'Handtekening Tekst Je kunt de volgende tijdelijke aanduidingen %name_f%, %name_l% gebruiken. Deze worden vervangen door de voor- en achternaam van de uitvoerende beheerder.', 'Signup Form Configuration' => 'Configuratie Aanmeldformulier', 'Signup Info' => 'Aanmeldingsinformatie', 'Signup Messages' => 'Aanmeldberichten', 'Site is temporarily disabled for maintenance' => 'Site is tijdelijk buiten gebruik voor onderhoud', 'Size' => 'Grootte', 'Size of input field' => 'Grootte van het inputveld', 'Skip' => 'Overslaan', 'Skip Line if Exist User with Same Login' => 'Sla regel over als gebruiker met dezelfde login bestaat', 'Sort' => 'Sorteren', 'Sort Order' => 'Sorteervolgorde', 'Source' => 'Bron', 'Space' => 'Spatie', 'Standard PHP Sessions' => 'Standaard PHP Sessies', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Startdatum Berekening regels voor berekening startdatum abonnement . LAATSTE datum wordt gekozen uit alternatieven. Deze instellingen zijn niet van invloed op wederkerende abonnementen', 'Start and Expiration Dates' => 'Aanvang- en verloopdatums', 'Started' => 'Gestart', 'Step %d of %d' => 'Stap %d van %d', 'Stop Recurring' => 'Stop Terugkering', 'String' => 'Tekenreeks', 'Subaffiliate' => 'Onderaffiliate', 'Submitting...' => 'Aan het versturen...', 'Subscription' => 'Abonnement', 'Super Admin' => 'Super Beheerder', 'Surcharge' => 'Toeslag', 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead' => 'Toeslag dat extra zal worden berekend wanneer klant [Van]->[Naar] plan wijzigt. aMember zal niet de Eerste Prijs doorberekenen bij opwaardering, gebruik daarvoor de Toeslag.', 'Table' => 'Tabel', 'Tabulation' => 'Tabteken', 'Template alternative template for signup page' => 'Sjabloon alternatief sjabloon voor aanmeldpagina', 'Terms Text automatically calculated if empty' => 'Voorwaarden Tekst automatisch gegenereerd indien leeg', 'Test E-Mail Settings' => 'Test E-mailinstellingen', 'Text' => 'Tekst', 'Text (unlimited length string/data)' => 'Tekst (tekenreeks/data van oneindige lengte)', 'Text Links' => 'Tekstlinken', 'TextArea' => 'Tekstgebied', 'The password is entered incorrectly' => 'Wachtwoord in onjuist ingevoerd', 'This code can be inserted into any HTML page on your website or into any WordPress post or page' => 'deze code kan op iedere HTML pagina van je website of op iedere Wordpress post of pagina worden ingevoegd', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Dit e-mailsjabloon is voor de betreffende taal leeg. Toets [Kopieren] om het sjabloon vanuit de standaard taal [Engels] te kopieren Toets [Overslaan] om vanaf niets het handmatig in te typen.', 'This field is requred' => 'Dit veld is vereist', 'Ticket#' => 'Ticket#', 'Time' => 'Tijd', 'Title displayed to customers' => 'Titel vertonen aan klanten', 'Title of Report for your Reference' => 'Titel van het rapport voor jouw kennisgeving', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'Voor dit product moet gebruiker in bezit zijn van wanneer gebruiker dit abonnement bestelt, wordt gecontroleerd of gebruiker een van de volgende abonnementen heeft', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'Om een spreadsheet als komma-gescheiden bestand (CSV) op te slaan (OpenOffice):', 'Total Paid' => 'Totaal Betaald', 'Total to Pay' => 'Totaal te Betalen', 'Trace' => 'Traceren', 'Traditional .htpasswd' => 'Traditioneel .htpasswd', 'Transactions Log' => 'Transacties Logboek', 'URL must be specified without trailing slash' => 'URL moet worden opgegeven zonder te eindigen op een slash', 'URL must start from %s or %s' => 'URL moet beginnen met %s of %s', 'Unable to cancel subscription' => 'Niet in staat abonnement te annuleren', 'Unable to change rebill date' => 'Niet in staat de herhaalbetalingsdatum aan te passen', 'Unlock' => 'Deblokkeren', 'Unpack Upgrades' => 'Upgrades uitpakken ', 'Update Error' => 'Update Fout', 'Update License Information' => 'Bijwerken Licentie-informatie', 'Update User if Exist User with Same Login' => 'Gebruiker bijwerken als gebruiker met dezelfde login bestaat', 'Upgrade' => 'Upgrade', 'Upgrade Database' => 'Upgrade Database', 'Upgrade Download Problem' => 'Probleem bij downloaden upgrade', 'Upgrade Finished' => 'Upgrade Klaar', 'Upgrade From' => 'Opwaarderen van', 'Upgrade To' => 'Opwaarderen naar', 'Upload' => 'Upload', 'Upsell - Replace Product from [Conditions] field' => 'Upsell - Vervang Product van [Voorwaarden] veld', 'Upsell Configuration' => 'Upsell-configuratie', 'Upsell Paths' => 'Upsell Paden', 'Use Custom Settings' => 'Gebruik Aangepaste Instellingen', 'Use E-Mail Throttle Queue' => 'Gebruik Wachtrij E-mailklep', 'Use External Cron' => 'Gebruik externe CRON', 'Use Global Settings' => 'Gebruik Universele Instellingen', 'Use this %slink%s to delete data from aMember v4 database and use clean database for import' => 'Gebruik deze %slink%s om data uit de aMember v4 database te verwijderen en een schone database te gebruiken om te importeren', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'Gebruikerscoupon Gebruiksteller aantal keren dat een couponcode gebruikt kan worden door een klant', 'User Id' => 'GebruikersID', 'User Invoices' => 'Gebruiker Facturen', 'User Pages Theme' => 'Thema Gebruikerspagina\'s', 'User currently has access to the following products' => 'Gebruiker heeft momenteel toegang tot de volgende producten ', 'User had access to the following products' => 'Gebruiker had toegang tot de volgende producten', 'User is not found in database' => 'Gebruiker is niet gevonden in de database', 'User notification' => 'Gebruikersmelding', 'User-Affiliate Relation Lifetime how long (in days) calculate commission for referred affiliate (default: 0 - forever)' => 'Levensduur Gebruiker-Affiliate Relatie hoelang (in dagen) provisie te berekenen voor doorverwijzende affiliate (standaard: 0 - voor altijd)', 'Username or e-mail address' => 'Gebruikersnaam of e-mailadres', 'Users' => 'Gebruikers', 'Users Report' => 'Gebruikersrapport', 'Utilities' => 'Hulpprogramma\'s', 'VAT' => 'BTW', 'Valid license key are one-line string,starts with L and ends with X' => 'Geldige licentiesleutel is een tekenreeks van één regel, begint met L en eidigt op X', 'Value use % as wildcard mask' => 'Waarde gebruik % als wildcard masker', 'Value must be alpha-numeric' => 'Waarde moet alfanumeriek zijn', 'Value must be alphanumeric' => 'Waarde moet alfanumeriek zijn', 'Values must not be equal' => 'Waardes mogen niet gelijk zijn', 'Verify E-Mail Address On Signup Page e-mail verification may be enabled for each signup form separately at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Verifieer E-mailadres Op Aanmeldpagina e-mailverificatie kan ingeschakeld worden voor ieder aanmeldformulier apart op aMember CP -> Formulieren Editor -> Bewerken, klik "configureren" op E-mailbouwsteen', 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Verifieer E-mailadres Op Profielpagina e-mailverificatie kan ingeschakeld worden voor profielpagina op aMember CP -> BFormulieren Editor -> Bewerken, klik "configureren" op E-mailbouwsteen', 'Version Info' => 'Versie Informatie', 'Video Player' => 'Videospeler', 'View' => 'Bekijken', 'View Coupons' => 'Bekijk coupons', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'We zullen een verzoek naar het betaalsysteem sturen of je wordt doorgestuurd naar de pagina van het betaalsysteem waar je een verzoek tot terugbetaling kunt versturen.', 'Weekly' => 'Wekelijks', 'Yes, assign category' => 'Ja, wijs categorie toe', 'Yes, do not e-mail this customer for any reasons' => 'Ja, verstuur geen e-mails aan deze klant voor geen enkele reden', 'Yes, locked' => 'Ja, geblokkeerd', 'Yes, remove category' => 'Ja, verwijder categorie', 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.' => 'Je kunt dit rapport %sopslaan%s voor toekomstig gebruik. Je kunt dit rapport aan je dashboard voegen of periodiek naar je email sturen.', 'You can download %sexample file%s.' => 'Je kunt een %svoorbeeldbestand%s downloaden.', 'You can import users from CSV file to aMember.' => 'Je kunt gebruikers importeren vanuit een CSV bestand naar aMember', 'You can not merge user with itself' => 'Je kunt gebruiker niet samenvoegen met zichzelf', 'You have currently choosed the following users for e-mail to:' => 'Je hebt op dit moment de volgende gebruikers gekozen te e-mailen:', 'You have generated %d demo products and %d demo customers' => 'Je hebt %d demoproducten en %d demogebruikers gegenereerd', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'Je hebt licentiesleutels van oudere versies van aMember, vervang deze s.v.p. met de laatste, één-regel sleutels', 'You have no permissions to perform requested operation' => 'Je hebt geen toestemming om verzochte bewerking uit te voeren', 'Your Password enter your current password in order to edit admin record' => 'Je Wachtwoord voer je huidige wachtwoord in om het beheerderrecord te kunnen bewerken', 'Zip Code' => 'Postcode', '[From] and [To] billing plans must not be equal' => '[Van] en [Naar] betaalplannen mogen niet gelijk zijn', 'aMember Database (default)' => 'aMember Database (standaard)', 'aMember will look for templates in [application/default/views/signup/] folder and in theme\'s [signup/] folder and template filename must start with [signup]' => 'aMember zal naar sjablonen zoeken in de [applicatie/default/views/signup/] map en in de thema\'s [signup/] map. De bestandsnaam van het sjabloon moet beginnen met [signup]', 'access log table (used by admin only)' => 'tabel toegangslogboek (alleen gebruikt door beheerder)', 'admin log table (used by admin only)' => 'tabel beheerderslogboek (alleen gebruikt door beheerder)', 'after' => 'na', 'allow max' => 'toestaan max', 'change' => 'veranderen', 'collapse details' => 'details invouwen', 'days after expiration' => 'dagen na beëindiging', 'days before expiration' => 'dagen voor beëindiging', 'days before rebilling' => 'dagen voor herhaalbetaling', 'displaying records %d-%d from %d' => 'weergave van records %d tot %d van %d', 'do not show disabled products' => 'vertoon geen uitgeschakelde producten', 'do not show pending invoices' => 'hangende facturen niet tonen', 'downloads within' => 'downloads binnen', 'during subscription period' => 'tijdens abonnementsperiode', 'error_log table (used by admin only)' => 'tabel foutenlogboek (alleen gebruikt door beheerder)', 'expand details' => 'details uitvouwen', 'first paid at' => 'eerst betaald op', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'als code aanwezig is, zijn producten verborgen in winkelwagentje, deze code is vereist om deze producten te zien', 'if customer uses more than' => 'als gebruiker meer dan', 'if user enters wrong password' => 'als gebruiker een verkeerd wachtwoord invoert', 'leave it empty in case of you want this item be available for all users' => 'leeglaten als je wilt dat dit item beschikbaar is voor alle gebruikers', 'login, email or name' => 'login, e-mail of naam', 'must be a number in format 99 or 99.99' => 'moet een getal zijn van het formaat 99 of 99.99', 'must be equal or greather than 0' => 'moet groter of gelijk zijn aan nul', 'must be equal or greather than 0.0' => 'moet groter of gelijk zijn aan 0.0', 'on expiration day' => 'op vervaldag', 'open in new window' => 'open in nieuw window', 'or %smake access free%s' => 'of %sgratis toegang geven%s', 'put website offline, making it available for admins only' => 'zet de website offline, maak het alleen beschikbaar voor beheerders', 'seconds, he will be forced to wait until next try' => 'seconden, wordt hij gedwongen te wachten tot een volgende poging', 'sending' => 'aan het versturen', 'sent successfully' => 'succesvol verstuurd', 'switch to show all records' => 'omschakelen naar vertoning van alle records', 'switch to show only active records' => 'omschakelen naar vertoning van alleen actieve records', 'this item is available for %sall registered customers%s. click to %smake this item protected%s %sor %smake this item available without login and registration%s %s' => 'dit item is beschikbaar voor %salle geregistreerde klanten%s. klik om %sdit item te beschermen%s %sof %smaak dit item beschikbaar zonder inloggen en registratie%s %s', 'times within' => 'keren binnen', 'version' => 'versie', ); PK\ӞNXOqOqdefault/language/admin/es.phpnu[ '%d días después de la expiración', '%d days before expiration' => '%d días antes de la expiración', '%d user(s) matches your search' => '%d usuario(s) coinciden con su búsqueda', 'Access Method' => 'Método de acceso', 'Account Sharing Prevention' => 'Evitar que se compartan las cuentas', 'Account Verification' => 'Verificación de cuenta', 'Add Payment' => 'Añadir pago', 'Add Payment Manually' => 'Añadir pago manualmente', 'Add Subscription' => 'Añadir Suscripción', 'Add User Fields' => 'Añadir campos', 'Additional' => 'Adicional', 'Admin Accounts' => 'Cuentas Administradores', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'Administrar direcciones de correo electrónico usados para enviar notificaciones por correo electrónico al administrador y dirección de salida por defecto', 'Admin Log' => 'Historial Administrador', 'Admin Pages Theme' => 'Tema de las páginas de administrador', 'Admin Payment Notifications to admin once payment is received' => 'Administrar notificaciones de pago para administrar una vez que se reciba el pago', 'Admin Settings' => 'Ajustes Administrador', 'Administrator Login' => 'Conexión de administrador', 'Affiliate Commission' => 'Comisión Afiliado', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Tiempo de vida de Cookie de Afiliado días para almacenar cookies de afiliados referidos', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Día Pago de Afiliados elige un día del mes en el que el pago sea generado', 'Affiliates Signup Type' => 'Modo de Registro de Afiliado', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'Tras realizar cualquier cambio en áres protegidas por htpasswd, por favor, inicia [Utilidades->Reconstrutir BD] para refrescar el archivo htpasswd', 'All new users automatically become affiliates' => 'Todos los nuevos usuarios se convierten automáticamente en afiliados', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Número de correos permitido introducir el número de correos permitidos dentro del periodo señalado anteriormente', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Correos permitidos por periodo elegir si su servidor limita el número de correos electrónico por día u hora', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Recordar siempre si se marca sí, no se preguntará al cliente, se recordará siempre', 'Assign Category' => 'Asignar categoría', 'Available Upgrades' => 'Actualizaciones disponibles', 'Backup' => 'Copia de seguridad', 'Banner' => 'Banner', 'Billing' => 'Facturación', 'Blob (unlimited length binary data)' => 'Blob (datos binarios de longitud ilimitada)', 'Blocking IP/E-Mail' => 'Bloqueando IP/Correo electrónico', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'No disponible temporalmente por un mantenimiento programado. Acceda de nuevo en un minuto.', 'Browse Found Users' => 'Revisar los usuarios encontrados', 'Browse Users' => 'Echar un vistazo a los usuarios', 'Bruteforce Protection' => 'Protección de fuerza bruta', 'Build Demo' => 'Crear Demo', 'Building demo records' => 'Creando registros de prueba', 'Can not find user with such username or email' => 'No se ha podido encontrar ningún usuario con ese nombre de usuario o dirección de correo electrónico', 'Cancellations' => 'Cancelaciones', 'Change Configuration Settings' => 'Cambiar los ajustes de la configuración', 'Change Paysystem' => 'Cambiar Sistema de Pago', 'Charge Second Price Once' => 'Cargar el segundo precio una vez', 'Charge Second Price x Times' => 'Cargar el segundo precio x veces', 'CheckBoxes' => 'Casillas de Verificación', 'Choose Products and/or Product Categories that allows access' => 'Selecciona Productios y/o Categorías de Productos que permiten el acceso', 'Choose Upgrades to Install' => 'Seleccionar la actualizaciones a instalar', 'Choose action when locked %s used by customer during signup' => 'Elige la acción cuando %s bloqueado es usado por clientes durante el registro', 'Cleaning up' => 'Limpiando', 'Cleanup' => 'Limpiar', 'Clear' => 'Limpiar', 'Clear Access Log' => 'Limpiar registro de acceso', 'Click to Expand' => 'Hacer click para expandir', 'Comma' => 'Coma', 'Commission earned' => 'Comisión obtenida', 'Commission for First Payment calculated for first payment in each invoice' => 'Comisión por Primer Pago calculada para el primer pago en cada factura', 'Commission for Free Signup calculated for first customer invoice only' => 'Comisión por Registro Gratuíto calculada sólo para la primera factura del cliente', 'Commission for Rebills' => 'Comisión por Refacturación', 'Copy' => 'Copiar', 'Copy Upgrades' => 'Copiar actualizaciones', 'Copy from another language' => 'Copiar desde otro idioma', 'Core' => 'Fundamental', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'No se ha podido descargar el fichero [%s]. Error %s. Por favor, %sinténtelo de nuevo%s más tarde.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'No se ha podido obtener el listado de actualizaciones desde el servidor remoto. %sInténtelo de nuevo%', 'Could not fetch upgrades list. Connection error [%s]' => 'No se ha podido obtener la lista de actualizaciones. Error de conexión [%s]', 'Coupons' => 'Cupones', 'Coupons Batches' => 'Lotes de Cupones', 'Create Session Key' => 'Crear clave de sesión', 'Create ticket as' => 'Crear ticket como', 'Custom Commission Rules added' => 'Reglas de Comisión personalizadas añadidas', 'Custom Signup Form Title keep empty to use default title' => 'Título de formulario de registro del cliente dejar en blanco para utilizar el título por defecto', 'Customer' => 'Cliente', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Fecha de Purga todos los registros anteriores a esta fecha será eliminados de las tablas seleccionadas', 'Default - user clicks a link to become affiliate' => 'Por defecto: el usuario hace clic en un enlace para convertirse en afiliado.', 'Default Billing Plan' => 'Plan de facturación por defecto', 'Default Commission' => 'Comisión predeterminada', 'Default Signup' => 'Registro por defecto', 'Default for Members' => 'Por defecto para los miembros', 'Delete Old Records' => 'Eliminar Antiguos Registros', 'Delimiter' => 'Delimitador', 'Demo History' => 'Historial de Prueba', 'Description displayed to visitors on order page below the title' => 'Descripción', 'Details' => 'Detalles', 'Die and show ugly error message' => 'Terminar y mostrar un feo mensaje de error', 'Disable auto-locking for this customer' => 'Deshabilitar el auto-bloqueo para este cliente', 'Disallow new Signups by %s' => 'Desactivar nuevos registros a %s', 'Display Language Choice' => 'Mostrar elección de idioma', 'Display error message' => 'Mostrar mensaje de error', 'Do not generate products use existing products for demo records' => 'No generar productos usar los productos existentes para registros de prueba', 'Do you really want to refund payment' => 'De verdad quiere reembolsar el pago', 'Do you really want to stop this subscription?' => '¿Quiere cancelar realmente esta suscripción?', 'Download Upgrades' => 'Descargar actualizaciones', 'Duration:' => 'Duración:', 'E-Mail Address to Send to' => 'Dirección de correo electrónico a las que enviarlo', 'E-Mail Backup Address' => 'Copia de seguridad de la dirección de correo electrónico', 'E-Mail Commission to Admin' => 'Enviar Comisiones por email a Administrador', 'E-Mail Commission to Affiliate' => 'Enviar Comisiones por email a Afiliado', 'E-Mail Database Backup' => 'Copia de seguridad de la base de datos del correo electrónico', 'E-Mail Queue' => 'Cola de correo electrónico', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'Nombre del remitente del correo electrónico se usa para mostrar el nombre del remitente en los correos enviados', 'E-Mail Sending' => 'Envío Correo Electrónico', 'E-Mail System Configuration' => 'Configuración del sistema de correo electrónico', 'E-Mail Type' => 'Tipo de Correo Electrónico', 'E-Mail Users' => 'Usuarios de correo electrónico', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'El correo electrónico ha sido satisfactoriamente enviado a %s clientes. El ID del Lote de Correos es %s', 'E-Mail sending started' => 'El envío del correo electrónico ha comenzado', 'E-Mails History' => 'Historial Correo Electrónicos', 'E-Mails by Admin Request' => 'Correos electrónicos por petición del administrador', 'E-Mails by User Request' => 'Correos electrónicos por petición del usuario', 'Edit Custom Commission Rules' => 'Editar Reglas de Comisión personalizadas', 'Edit Groups' => 'Editar grupos', 'Email Backup Frequency' => 'Frecuencia de la copia de seguridad de los correos electrónicos', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'Método de envío de correos electrónicos POR FAVOR NO CAMBIAR si el envío desde aMember funciona', 'Email Sent' => 'Correo electrónico enviado', 'Enable plugins if necessary' => 'Habilitar plugins si es necesario', 'Enter Maintenance Mode' => 'Entrar en modo mantenimiento', 'Error Log' => 'Historial de Errores', 'Error/Debug Log' => 'Registro de Error/Depuración', 'Errors' => 'Errores', 'Errors:' => 'Errores:', 'Every %s' => 'Cada %s', 'Exchange Rate' => 'Tipo Cambio', 'Exchange Rate enter cost of 1 (one) %s' => 'Tipo de Cambio introduce el coste de 1 (un) %s', 'Field Name' => 'Nombre de Campo', 'Field Title' => 'Título de Campo', 'Field Values' => 'Valor de Campos', 'File is required' => 'Archivo requerido', 'Filter by String' => 'Filtrar por caracteres', 'Filter by string or by invoice#/member#' => 'Filtrat por cadena o por factura de#/miembro#', 'First Period' => 'Primer periodo', 'First Price' => 'Primer precio', 'First Price price of first period of subscription' => 'Primer precio precio del primer periodo de suscripción', 'First and Last Name' => 'Nombre y Apellido', 'First visited' => 'Vistado por Primera vez', 'Fix aMember Pro License Key' => 'Establecer una clave de licencia de miembro Pro', 'Fixed date' => 'fecha fija', 'Folder URL' => 'URL de Carpeta', 'Form Type' => 'Tipo de formulario', 'Forms Editor' => 'Editor de formularios', 'Future' => 'Futuro', 'General' => 'General', 'General Settings' => 'Ajustes generales', 'Generate' => 'Generar', 'Generate Payout Manually' => 'Generar Pago Manualmente', 'Generation of demo data was terminated while processing. Not all records were created.' => 'La generación de datos de prueba fue terminada mientras se procesaba. No se han creado todos los registros.', 'Get Available Upgrades List' => 'Obtener la lista de actualizaciones disponibles', 'Get New Password' => 'Obtener Nueva Contraseña', 'Global' => 'Global', 'Hostname' => 'Nombre de servidor', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'NOTA IMPORTANTE: Esto no protege el contenido. Si alguien conoce la url del enlace, será capaz de abrir el enlace sin problema. Esto sólo controla que enlaces adicionales verá el usuario tras conectarse al área de miembros.', 'IP' => 'IP', 'IP within' => 'IP en', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Si estas cambiando de procesador de pagos, puedes usar esta página para cambiar la suscripción existente de un procesador de pago a otro. Sólo es posible si la información completa de la tarjeta de crédito está guardada en el área de un miembro.', 'Import Users' => 'Importar usuarios', 'Install Updates' => 'Instalar actualizaciones', 'Integer field (only numbers)' => 'Campo números enteros (sólo números)', 'Integration plugins' => 'Plugins integración', 'Internal PHP mail() function (default)' => 'Función PHP mail() (por defecto) interna', 'Intro Text on Helpdesk Page' => 'introducir texto en la página de atención al usuario', 'Invoice Log' => 'Registro de factura', 'Invoices Per User' => 'Facturas por Usuario', 'Is Affiliate?' => '¿Es afiliado?', 'Is Approved' => 'Está aprobado', 'It is required to setup a cron job to trigger backup generation' => 'Se necesita configurar una tarea de cron para iniciar la creación de una copia de seguridad', 'Languages' => 'Idiomas', 'Last %s Customers' => 'Últimos %s clientes', 'Last existing subscription date of this product' => 'La última fecha existente de suscripción de este producto', 'Last login' => 'Última conexión', 'Length of admin password must be from %d to %d' => 'La longitud de la contraseña de administrador debe de ser de %d a %d', 'Length of username must be from %d to %d' => 'La longitud del usuario debe de ser de %d a %d', 'Lightbox Main Image' => 'Lightbox Imagen Principal', 'Lightbox Thumbnail Image' => 'Lightbox Imagen en Miniatura', 'Lines Proccessed:' => 'Líneas procesadas:', 'Lines Skipped:' => 'Líneas saltadas:', 'Lines Success:' => 'Líneas correctas:', 'Link to reset your password was sent to your Email.' => 'Enlace para restaurar la contraseña que enviamos a tu correo eclectrónico.', 'Lock' => 'Bloquear', 'Locked Value' => 'Valor Bloqueado', 'Log Outgoing E-Mail Messages for ... days' => 'Registrar los mensajes de correo enviados durante ... días', 'Log in' => 'Conectarse', 'Logged in as %s' => 'Conectado como %s', 'Login Page' => 'Página de identificación', 'Logs' => 'Registros', 'Lookup' => 'Búsqueda', 'Lost your password?' => '¿Ha perdido su contraseña?', 'Mail' => 'Correo', 'Maintenance Mode' => 'Modo mantenimiento', 'Manage Product Upgrade Paths' => 'Gestionar las rutas de actualización de producto', 'Manage Products' => 'Gestionar productos', 'Manually Added' => 'Añadido manualmente', 'Mark NOT Paid' => 'Marcar como NO pagado', 'Mark Paid' => 'Marcar como Pagado', 'Membership' => 'Miembros', 'Method' => 'Método', 'Miscellaneous' => 'Miscelánea', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Compra de varios títulos cuando el usuario compra varios productos, muestra lo siguiente en el sistema de pago en lugar del nombre del producto', 'New Autoresponder' => 'Nuevo Autocontestador', 'New Expiration E-Mail' => 'Nueva Expiración Correo Electrónico', 'New Modules Available' => 'Nuevos módulos disponibles', 'New Rewrite' => 'Nueva versión reescrita', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'No hay información de Tarjetas de Crédito almacenadas para este cliente. %sAñadir Tarjeta de Crédito%s', 'No Invoices Found' => 'No se han encontrado facturas', 'No Updates Available' => 'No hay actualizaciones disponibles', 'No more charges' => 'No hay más cargos', 'No search name passed' => 'No se ha indicado un nombre para la búsqueda', 'No upgrades to install' => 'No hay ninguna actualización a instalar', 'Not Approved Users' => 'Usuarios no aprobados', 'Not-SQL field (default)' => 'Campo No-SQL(por defecto)', 'Numeric field' => 'Campo numérico', 'Only admin can enable user as an affiliate' => 'Sólo el administrador puede activar un usuario como afiliado', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Dirección de correo saliente usado como De: dirección para enviar mensajes de correo electrónico a los clientes. Si está en blanco, se usa [Dirección de correo electrónico del administrador]', 'Overwrite User if Exist User with Same Login' => 'Sobreescribir usuario si existe usuario con la misma identificación', 'PDF Invoice' => 'Factura en Pdf', 'Paid' => 'Pagado', 'Password Length' => 'Longitud de la contraseña', 'Password must not be equal to username' => 'La contraseña no debe ser igual que el usuario', 'Passwords must be the same' => 'Las contraseñas deben de ser la misma', 'Path to Folder' => 'Ruta a la Carpeta', 'Path/URL' => 'Ruta/URL', 'Payment date' => 'Fecha de pago', 'Payment has been successfully refunded' => 'El pago se ha reembolsado correctamente', 'Payout %d Details' => 'Pago %d Detalles', 'Payout Details' => 'Detalles de Pago', 'Paysystem' => 'Sistema de pago', 'Permissions' => 'Permisos', 'Please assign the following fields: ' => 'Por favor, asigna los siguientes campos:', 'Please choose another field name. This name is already used' => 'Por favor, elige otro nombre de campo. Este nombre ya está siendo utilizado', 'Please enter valid e-mail address' => 'Por favor, indique una dirección de correo electrónico válida', 'Please select date before today' => 'Por favor selecciona una fecha antes de hoy', 'Please wait' => 'Por favor, espere', 'Plugins' => 'Plugins', 'Product Availability' => 'Disponibilidad del producto', 'Product Upgrades' => 'Actualizaciones de producto', 'Products Per Invoice' => 'Productos por Factura', 'Protect Content' => 'Proteger contenido', 'Protection Method' => 'Método de Protección', 'Quit Maintenance Mode' => 'Salir del modo mantenimiento', 'RadioButtons' => 'Botones de radio', 'Rebill' => 'Refacturar', 'Rebill Second Price until cancelled' => 'Refacturar el segundo precio hasta la cancelación', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Número de refacturación Este es el número de pagos que tendrán lugar con el segundo precio', 'Rebuild Db' => 'Reconstruir base de datos', 'Receipt' => 'Recibo', 'Recipients' => 'Receptores', 'Records Deleted Sucessfully' => 'Registros Eliminados Satisfactoriamente', 'Referrer' => 'Referenciar', 'Refund Payment' => 'Reembolsar pago', 'Remember Login remember username/password in cookies' => 'Recordar identificación recordar usuario/contraseña en cookies', 'Remind Password to Admin' => 'Recordar contraseña del administrador', 'Remind Password to Customer' => 'Recordar contraseña al cliente', 'Remove Category' => 'Eliminar categoría', 'Repeat Action Handling' => 'Repetir el manejo de la acción', 'Reports' => 'Reportes', 'Resend' => 'Reenviar', 'Resend Signup E-Mail' => 'Reenviar correo electrónico de registro', 'Resource' => 'Recurso', 'Restore' => 'Restaurar', 'Retreive Access Parameters if necessary' => 'Recuperar los parámetros de acceso si es necesario', 'Return to Payouts List' => 'Regresar a la Lista de Pagos', 'Root URL root script URL, usually %s' => 'URL raiz URL de script raíz, normalmente %s', 'Root Url and License Keys' => 'URL raíz y claves de licencia', 'Run Reports' => 'Ejecutar informes', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'Nombre del servidor SMTP', 'SMTP Hostname is required if you have enabled SMTP method' => 'Se necesita el nombre del servidor SMTP si ha activado el método SMTP', 'SMTP Password' => 'Contraseña SMTP', 'SMTP Port' => 'Puerto SMTP', 'SMTP Security' => 'Seguridad SMTP', 'SMTP Username' => 'Usuario SMTP', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (no puede usarse para campos multiselección o de casilla de verificación)', 'Save This Search' => 'Guardar esta búsqueda', 'Saved Credit Cards' => 'Tarjeta de Crédito Guardadas', 'Saved Search' => 'Búsqueda guardada', 'Second Period' => 'Segundo periodo', 'Second Price' => 'Segundo precio', 'Second Price price that must be billed for second and the following periods of subscription' => 'Segundo precio precio que se tiene que facturar para el segundo y los siguientes periodos de suscripción', 'Secure Root URL secure URL, usually %s' => 'URL raíz segura URL segura, normalmente %s', 'Select (Multiple Values)' => 'Seleccionar (valores múltiples)', 'Select (Single Value)' => 'Seleccionar (valor único)', 'Select a plugin' => 'Selecciona un plugin', 'Selected for E-Mailing' => 'Seleccionados para E-Mailing', 'Semicolon' => 'Punto y coma', 'Send E-Mail Message' => 'Enviar Mensaje Correo Electrónico', 'Send E-Mail Messages' => 'Enviar mensajes por correo electrónico', 'Send New E-Mail' => 'Enviar Nuevo Correo Electrónico', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Enviar notificaciones sobre nuevos mensajes al cliente aMember enviará una notificación al usuario cada vez que el administrador responda a un ticket de usuario', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Enviar correo electrónico de registro una vez que la PRIMERA suscripción se complete', 'Send Test E-Mail' => 'Enviar correo de prueba', 'Sender' => 'Remitente', 'Sending Test E-Mail...' => 'Enviando correo de prueba...', 'Sending e-mail (sent to %d from %d)' => 'Enviado correo electrónico (enviado %d de %d)', 'Setup/Configuration' => 'Instalación/configuración', 'Signup Form Configuration' => 'Configuración del formulario de registro', 'Signup Info' => 'Información de registro', 'Site is temporarily disabled for maintenance' => 'El sitio está temporalmente desactivado por mantenimiento', 'Size of input field' => 'Tamaño campo entrada', 'Skip' => 'Saltar', 'Skip Line if Exist User with Same Login' => 'Saltar línea si existe un usuario con el mismo login', 'Sort' => 'Ordenar', 'Sort Order' => 'Orden', 'Source' => 'Fuente', 'Space' => 'Espacio', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Cálculo de la fecha de inicio reglas para el cálculo de la fecha de inicio de la suscripción. Se elegirá la fecha MÁXIMA de entre las alternativas. Esta configuración no tendrá efecto para suscripciones repetitivas', 'Started' => 'Comenzado', 'Step %d of %d' => 'Paso %d de %d', 'Stop Recurring' => 'Dejar de referenciar', 'String' => 'Cadena', 'Submitting...' => 'Enviando...', 'Subscription' => 'Suscripción', 'Super Admin' => 'SuperAdministrador', 'Surcharge' => 'Sobrecarga', 'Tabulation' => 'Tabulación', 'Template alternative template for signup page' => 'Plantilla plantilla alternativa para la página de registro', 'Terms Text automatically calculated if empty' => 'Texto de términos calculado automáticamente si está vacío', 'Test E-Mail Settings' => 'Probar configuración del correo electrónico', 'Text' => 'Texto', 'Text (unlimited length string/data)' => 'Texto (cadena/datos longitud ilimitada)', 'TextArea' => 'Área de Texto', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Esta plantilla de correo electrónico está vacía en el idioma ofrecido. Presiona [Copiar] para copiar la plantilla del idioma por defecto [Inglés] Presiona [Saltar] para escribirla manualmente desde cero', 'This field is requred' => 'Campo requerido', 'Ticket#' => 'Entrada#', 'Time' => 'Hora', 'Title displayed to customers' => 'Título', 'Total Paid' => 'Total Pagado', 'Total to Pay' => 'Total a Pagar', 'Trace' => 'Rastrear', 'Traditional .htpasswd' => '.htpasswd tradicional', 'URL must be specified without trailing slash' => 'La URL se tiene que indicar sin la barra final', 'URL must start from %s or %s' => 'La URL debe comenzar por %s o %s', 'Unlock' => 'Desbloquear', 'Unpack Upgrades' => 'Desempaquetar actualizaciones', 'Update Error' => 'Error de actualización', 'Update License Information' => 'Actualizar Información de Licencia', 'Update User if Exist User with Same Login' => 'Actualizar usuario si existe usuario con la misma identificación', 'Upgrade' => 'Actualizar', 'Upgrade Database' => 'Actualizar base de datos', 'Upgrade Download Problem' => 'Problema en la descarga de la actualización', 'Upgrade Finished' => 'Actualización terminada', 'Upgrade From' => 'Actualizar desde', 'Upgrade To' => 'Actualizar a', 'Upload' => 'Cargar', 'Use E-Mail Throttle Queue' => 'Usar cola acelerada de correos electrónicos', 'Use External Cron' => 'Usar Cron externo', 'User Invoices' => 'Facturas del usuario', 'User Pages Theme' => 'Tema de las páginas de usuario', 'User currently has access to the following products' => 'El usuario actualmente tiene acceso a los siguientes productos', 'User had access to the following products' => 'El usuario ha tenido acceso a los siguientes productos', 'User is not found in database' => 'Usuario no encontrado en la base de datos', 'Username or e-mail address' => 'Nombre de usuario o dirección de correo electrónico', 'Users' => 'Usuarios', 'Value use % as wildcard mask' => 'Valor usar % como máscara', 'Values must not be equal' => 'Los valores deben ser iguales', 'Version Info' => 'Información de la versión', 'View' => 'Ver', 'View Coupons' => 'Ver Cupones', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Enviaremos una petición al sistema de pago o se le redireccionará a una página de sistema de pago para enviar la petición de reembolso', 'Yes, assign category' => 'Si, asignar categoría', 'Yes, do not e-mail this customer for any reasons' => 'Si, no envíe un correo electrónico a este usuario por ningún motivo', 'Yes, locked' => 'Si, bloqueado', 'Yes, remove category' => 'Si, eliminar categoría', 'You have currently choosed the following users for e-mail to:' => 'Actualmente ha seleccionado los siguientes usuarios a los que enviarles un correo electrónico:', 'You have generated %d demo products and %d demo customers' => 'Has generado %d productos de prueba y %d clientes de prueba', 'Your Password enter your current password in order to edit admin record' => 'Tu Contraseña introduce tu contraseña actual para editar el registro de administrador', '[From] and [To] billing plans must not be equal' => '[Desde] y [A] en los planes de facturación no pueden ser iguales', 'access log table (used by admin only)' => 'acceder a tablas de historial (usado sólo por administrador)', 'admin log table (used by admin only)' => 'tabla historial administrador (usado sólo por administrador)', 'change' => 'cambiar', 'collapse details' => 'expandir detalles', 'days after expiration' => 'días después de la expiración', 'days before expiration' => 'antes de la expiración', 'displaying records %d-%d from %d' => 'Mostrar las entradas %d-% de %d', 'error_log table (used by admin only)' => 'tabla error_log (usado sólo por administrador)', 'expand details' => 'expandir detalles', 'first paid at' => 'primer pago en', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'si está presente el código, los productos estarán ocultos en el carro de la compra y es necesario este código para ver estos productos', 'if customer uses more than' => 'si los clientes usan más de', 'if user enters wrong password' => 'si el usuario introduce una contraseña incorrecta', 'login, email or name' => 'conexión, dirección de correo o nombre', 'must be a number in format 99 or 99.99' => 'tiene que ser un número en formato 99 o 99.99', 'must be equal or greather than 0' => 'tiene que ser igual o mayor que 0', 'must be equal or greather than 0.0' => 'tiene que ser igual o mayor que 0.0', 'on expiration day' => 'en la fecha de expiración', 'open in new window' => 'abrir en nueva ventana', 'or %smake access free%s' => 'o %shaz el acceso libre%s', 'put website offline, making it available for admins only' => 'desconecta el sitio web, haciéndolo visible solo para los administradores', 'sending' => 'enviando', 'sent successfully' => 'enviado correctamente', 'switch to show all records' => 'cambiar para mostrar todos los registros', 'switch to show only active records' => 'cambiar para mostrar solo los registros activos', 'times within' => 'veces en', 'version' => 'versión', ); PK\Tibodefault/language/admin/en.phpnu['_'); PK\zt9e{e{default/language/admin/tr.phpnu[ 'sona erdikten %d gün sonra', '%d days before expiration' => 'sona ermeden %d gün önce', '%d user(s) matches your search' => 'Aramanıza %d kullanıcı(lar) uyuyor', '%d-th subscription day' => '%d. üyelik günü', 'Access Method' => 'Erişim Metodu', 'Account Sharing Prevention' => 'Hesap Paylaşım Engellemesi', 'Account Verification' => 'Hesap Doğrulama', 'Add Chargeback' => 'Geri Ödeme Ekle', 'Add Payment' => 'Ödeme Ekle', 'Add Payment Manually' => 'Manuel Olarak Ödeme Ekle', 'Add Refund' => 'Ödeme İade Ekle', 'Add Subscription' => 'Abonelik Ekle', 'Add User Fields' => 'Alan Ekle', 'Additional' => 'İlave', 'Admin Accounts' => 'Yöentici Hesapları', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'Yönetici Email Adresi yöneticiye bildiri göndermek için ve varsayılan gönderen adresi olarak kullanılır', 'Admin Log' => 'Yönetici Logu', 'Admin Pages Theme' => 'Admin Sayfaları Teması', 'Admin Payment Notifications to admin once payment is received' => 'Yönetici Ödeme Bilgilendirmeleri ödeme gerçekleştikten sonra yöneticiye', 'Admin Settings' => 'Yönetici Ayarları', 'Administrator Login' => 'Yönetici Girişi', 'Advanced Settings' => 'Gelişmiş Ayarlar', 'Affiliate Commission' => 'Affiliate Komisyonu', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Affiliate Cookie Ömrü gönderen affiliate hakkında cookienin kaç gün saklanacağı', 'Affiliate Registration E-Mail' => 'Affiliate Kayıt Emaili', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Affiliatelerin Ödeme Günü ödemenin oluşturulması için bir gün seç', 'Affiliates Signup Type' => 'Affiliatelerin Kaydolma Şekli', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'htpasswd korumalı alanlarda değişiklikler yaptıktan sonra , lütfen htpasswd dosyasını yenilemek için [Utilities->Rebuild Db]yi çalıştırın', 'All new users automatically become affiliates' => 'Bütün yeni kullanıcılar otomatik olarak affiliate olurlar', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'İzin Verilen Email Sayısı yukarıda bahsedilen zaman aralığında izin verilen email sayısını girin', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Belli Zaman Aralığında Gönderilebilen Email Sayısı eğer email barındırıcınız sınırlıyorsa kullanın', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Her Zaman Hatırla eğer evet ise müşteriye sorma-her zaman hatırla', 'American Date Format' => 'Amerikan Tarih Formatı', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'Tekrar Edene Ekle? kupon indirimlerini tekrar eden faturalandırmalara ekle?', 'Assign Category' => 'Kategori Belirle', 'At least one billing plan must be added' => 'En azından bir ödeme planı eklenmelidir', 'Available Upgrades' => 'Müsait Yükseltmeler', 'Backup' => 'Yedekleme', 'Banner' => 'Banner', 'Billing' => 'Faturalama', 'Blob (unlimited length binary data)' => 'Blob (sınırsız uzunlukta binary veri)', 'Blocking IP/E-Mail' => 'IP/E-Mail Engelleme', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Planlanmış bakım için kısa süreliğine müsait değil . Bir dakika içinde tekrar deneyin.', 'Browse' => 'Gözat', 'Browse Found Users' => 'Bulunan Kullanıcılara Gözat', 'Browse Users' => 'Kullanıcılara Gözat', 'Bruteforce Protection' => 'Kaba Kuvvet Koruma', 'Build Demo' => 'Demo Oluştur', 'Building demo records' => 'Demo kayıtlar oluşturuluyor', 'Can not find user with such username or email' => 'Bu isim ya da emaille kullanıcı bulunamıyor', 'Cancellations' => 'İptaller', 'Change Configuration Settings' => 'Yapılandırma Ayarlarını Değiştir', 'Change Paysystem' => 'Ödeme sitemini değiştir', 'Charge Second Price Once' => 'İkinci Fiyatı Bir Kez Çek', 'Charge Second Price x Times' => 'İkinci Fiyatı x Kere Çek', 'CheckBoxes' => 'Onay Kutusu', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => '%1$sDosya%2$s Seç > %1$sFarklı Kaydet%2$s.', 'Choose Products and/or Product Categories that allows access' => 'Erişime izin veren Ürün ve/veya Ürün Kategorilerini Seçin', 'Choose Upgrades to Install' => 'Yüklenecek Yükseltmeleri Seç', 'Choose action when locked %s used by customer during signup' => 'Kilitli %s müşteri tarafından kayıt esnasında kullanılırsa şu eylemi seç', 'Cleaning up' => 'Temizleniyor', 'Cleanup' => 'Temizle', 'Clear' => 'Temizle', 'Clear Access Log' => 'Giriş Logunu Temizle', 'Click to Expand' => 'Genişletmek için Tıklayın', 'Code Length generated coupon code length between 4 and 32' => 'Kod Uzunluğu oluşturulan kupon uzunluğu 4 ve 32 arasında', 'Comma' => 'Virgül', 'Commission for First Payment calculated for first payment in each invoice' => 'İlk Ödeme için Komisyon her faturada ilk ödeme için hesaplanır', 'Commission for Free Signup calculated for first customer invoice only' => 'Ücretsiz Kaydolma için Komisyon sadece müşteriye kesilen ilk faturadan hesaplanır', 'Commission for Rebills' => 'Tekrar Faturalama için Komisyon', 'Configured License Keys' => 'Yapılandırılmış Lisans Anahtarları', 'Copy' => 'Kopyala', 'Copy Upgrades' => 'Yükseltmeleri Kopyala', 'Copy from another language' => 'Başka bir lisandan kopyala', 'Core' => 'Core', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Bu dosya indirilemedi [%s]. Hata %s. Lütfen daha sonra %stekrar deneyin%s.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'Uzaktaki sunucudan yükseltmeler alınamadı. %sTekrar Deneyin%', 'Could not fetch upgrades list. Connection error [%s]' => 'Yükseltme listesi alınamadı. Bağlantı Hatası [%s]', 'Coupons' => 'Kuponlar', 'Coupons Batches' => 'Kupon Lotları', 'Coupons Count how many coupons need to be generated' => 'Kupon Sayısı oluşturulması gereken kupon sayısı', 'Create Session Key' => 'Session Anahtarı Oluştur', 'Create ticket as' => 'Şu şeklide bilet oluştur', 'Custom Commission Rules added' => 'Özel Komisyon Kuralları Eklendi', 'Custom Signup Form Title keep empty to use default title' => 'Özel Yazılma Form Başlığı Varsayılan başlığı boş bırak', 'Customer' => 'Müşteri', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Arındırma Tarihi Seçili tablolardaki bu tarihten önceki bütün kayıtlar silinecektir', 'Dates date range when coupon can be used' => 'Tarihler kuponun kulllanılabileceği tarih aralığı', 'Dates can be in the folowing formats' => 'Tarihler şu formatlarda olabilirler', 'Default - user clicks a link to become affiliate' => 'Varsayılan - kullanıcı affiliate olmak için bir linki tıklar', 'Default Billing Plan' => 'Varsayılan Faturalama Planı', 'Default Signup' => 'Varsayılan Kayıt', 'Default for Members' => 'Üyeler için Varsayılan', 'Delete Old Records' => 'Eski Kayıtları Sil', 'Delete payment and access record' => 'Ödemeyi ve erişim kayıtlarını sil', 'Delimiter' => 'Ayraç', 'Demo History' => 'Demo Geçmişi', 'Description displayed to visitors on order page below the title' => 'Tanım başlığın altındaki kısımda kullanıcılara gösterilir', 'Details' => 'Detaylar', 'Die and show ugly error message' => 'Durdur ve çirkin hata mesajı göster', 'Disable auto-locking for this customer' => 'Bu müşteri için otomatik kilitlemeyi devre dışı bırak', 'Disallow new Signups by %s' => '%s nin bir daha kayıt olmasına izin verme ', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'Eğer kullanıcıda varsa siparişe engel ol kullanıcı bu ürünü sipariş ettiğinde aşağıdaki aboneliklerinin olup olmadığı kontrol edilir', 'Display Language Choice' => 'Lisan Seçimini Göster', 'Display error message' => 'Hata Mesajı Göster', 'Do not generate products use existing products for demo records' => 'Ürün oluşturma demo kayıtlar için mevcut ürünleri kullan', 'Do you really want to refund payment' => 'Ödemeyi gerçekten iade etmek istiyormusunuz?', 'Do you really want to stop this subscription?' => 'Aboneliğinizi gerçekten durdurmak istiyormusunuz?', 'Download Upgrades' => 'Yükseltmeleri İndir', 'Duration:' => 'Süre:', 'E-Mail Address to Send to' => 'Gönderilecek Email Adresi', 'E-Mail Backup Address' => 'Email yedekleme adresi', 'E-Mail Commission to Admin' => 'Komisyonu Yöneticiye Email At', 'E-Mail Commission to Affiliate' => 'Komsiyonu Affiliate e Email At', 'E-Mail Database Backup' => 'Email Veri Tabanı Yedeklemesi', 'E-Mail Queue' => 'Email Sırası', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'Email Gönderen Adı dışarı giden emaillerde gönderen adı olarak görünür', 'E-Mail Sending' => 'Email gönderiliyor', 'E-Mail System Configuration' => 'Email Sistem Yapılanması', 'E-Mail Type' => 'Email Çeşidi', 'E-Mail Users' => 'Kullanıcılar Email Yolla', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => '%s müşteriye başarıyla email gönderildi.Email lot ID si %s', 'E-Mail sending started' => 'Email gönderimi başladı', 'E-Mails History' => 'Email Geçmişi', 'E-Mails by Admin Request' => 'Yöneticiden Giden Emailler', 'E-Mails by User Request' => 'Kullanıcı İsteğiyle Gönderilen Emaiiler', 'Edit Custom Commission Rules' => 'Özel Komisyon Kurallarını Düzenle', 'Edit Groups' => 'Grupları Düzenle', 'Email Backup Frequency' => 'Email Yedekleme Frekansı ', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'Email Gönderme Metodu aMember dan email gönderimi çalışıyorsa LÜTFEN DEĞİŞTİRMEYİN', 'Email Sent' => 'Email gönderildi', 'Email address is required field.' => 'Email adresi gerekli alandır.', 'Enable plugins if necessary' => 'Gerekliyse eklentileri yükle', 'Enter Maintenance Mode' => 'Bakım Moduna Gir', 'Error Log' => 'Hata Logu', 'Error/Debug Log' => 'Hata/Debug Logu', 'Errors' => 'Hatalar', 'Errors:' => 'Hatalar:', 'European Date Format' => 'Avrupa Tarih Formatı', 'Every %s' => 'Her %s', 'Exchange Rate' => 'Kur', 'Exchange Rate enter cost of 1 (one) %s' => 'Kur 1(bir) adetin fiyatını girin %s', 'Field Name' => 'Alan Adı', 'Field Title' => 'Alan Başlığı', 'Field Values' => 'Alan Değerleri', 'File is required' => 'Dosya Gereklidir', 'Filter by string or by invoice#/member#' => 'Dizgi yada fatura numarası/üye numarası na göre filtrele', 'First Period' => 'İlk Dönem', 'First Price' => 'İlk Fiyat', 'First Price price of first period of subscription' => 'İlk Fiyat Aboneliğin ilk döneminin fiyatı', 'First and Last Name' => 'Ad ve Soyad', 'First available protected url' => 'İlk müsait korunan URL', 'First visited' => 'İlk ziyaret edilen', 'Fix aMember Pro License Key' => 'aMember Pro Lisans Anahtarını Düzenle', 'Fixed Url' => 'Sabit URL', 'Fixed date' => 'Sabit Tarih', 'Folder URL' => 'Dizin URLi', 'Form Type' => 'Form Çeşidi', 'Forms Editor' => 'Form Düzenleyici', 'Future' => 'Gelecek', 'General' => 'Genel', 'General Settings' => 'Genel Ayarlar', 'Generate' => 'Oluştur', 'Generate Payout Manually' => 'Ödemeyi Manuel Olarak Oluştur', 'Generated' => 'Oluşturulmuş', 'Generation of demo data was terminated while processing. Not all records were created.' => 'Demo datanın oluşturulması işlem yapılırken sonlandırıldı. Bütün kayıtlar oluşturulmadı.', 'Get Available Upgrades List' => 'Mevcut Yükseltme Listesini Al', 'Get New Password' => 'Yeni Şifre Al', 'Global' => 'Global', 'Hostname' => 'Hostname', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'ÖNEMLİ NOT: Bu içeriği korumayacaktır. Birisi link URLsini bildiği takdirde linki açabilecektir. Bu sadece kullanıcı giriş yaptıktan sonra hangi linkleri görebileceğini kontrol eder.', 'IP' => 'IP', 'IP within' => 'IP süresinde', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Bir ödeme işlemcisinden ayrılıyorsanız, mevcut aboneliği bir başka ödeme işlemcisine taşımak için bu sayfayı kullanabilirsiniz . Bu sadece bütün kredi kartı bilgisi aMember sitesinde saklanırsa mümkün olur.', 'Import Finished' => 'İthal işlemi Bitti', 'Import Users' => 'Kullanıcı İthal Et', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'Text dosyası ihracı iletişim kutusunda istediğiniz seçenekleri seçin ve sonra %1$sOK%2$s yı tıklayın.', 'In the File name box, type a name for the file.' => 'Dosya ismi kutusunda dosya için isim kaydet', 'Insert' => 'Ekle', 'Install Updates' => 'Yükseltmeleri Yükle', 'Integer field (only numbers)' => 'Tamsayı alanı (sadece rakam)', 'Integration plugins' => 'Birleştirme Eklentileri', 'Internal PHP mail() function (default)' => 'Içsel PHP mail() fonksiyonu (varsayılan)', 'Intro Text on Helpdesk Page' => 'Yardım Masası Sayfasındaki Giriş Yazısı', 'Invoice Log' => 'Fatura Logu', 'Invoices Per User' => 'Kullanıcı Başına Fatura', 'Is Approved' => 'Onaylandı', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'Devre Dışı mı?? ürün siparişini devre dışı bırak, kayıt olma ve yenileme formlarında gösterme', 'It is required to setup a cron job to trigger backup generation' => 'Yedekleme oluşturmak için cron job yapılması gereklidir', 'Languages' => 'Lisanlar', 'Last %s Customers' => 'Son %s Müşteri', 'Last available protected url' => 'En son müsait korunan URL', 'Last existing subscription date of this product' => 'Bu ürün için mevcut en son abone olma tarihi', 'Last login' => 'Son Giriş', 'Length of admin password must be from %d to %d' => 'Yönetici şifresinin uzunluğu %d den %d e kadar olmalıdır', 'Length of username must be from %d to %d' => 'Kullanıcı adının uzunluğu %d den %d e kadar olmalıdır', 'Lightbox Main Image' => 'Işık Kutusu Ana Görseli', 'Lightbox Thumbnail Image' => 'Işık Kutusu Thumbnail Görseli', 'Lines Proccessed:' => 'İşlenen Satırlar:', 'Lines Skipped:' => 'Atlanan Satırlar:', 'Lines Success:' => 'Başarılı Sıralar:', 'Link to reset your password was sent to your Email.' => 'Şifrenizi sıfırlama linki Emailinize gönderildi.', 'Lock' => 'Kilitle', 'Locked Value' => 'Kilitli Değer', 'Log Outgoing E-Mail Messages for ... days' => 'Gönderilen mesajları ... gün boyunca kaydet', 'Log in' => 'Giriş Yap', 'Login Page' => 'Giriş Sayfası', 'Logs' => 'Loglar', 'Lookup' => 'Ara', 'Lost your password?' => 'Şifrenizi Kayıp mı Ettiniz?', 'Mail' => 'Posta', 'Maintenance Mode' => 'Bakım Modu', 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s' => 'Bakım modu şu anda açık. Sadece sizin gibi giriş yapmış yöneticiler ulaşabilir. %sDevre Dışı Bırak%s', 'Manage Product Upgrade Paths' => 'Ürün Güncelleme Yollarını Hallet', 'Manage Products' => 'Ürünleri İdare Et', 'Manually Added' => 'Manuel Olarak Eklendi', 'Mark NOT Paid' => 'Ödenmedi Olarak İşaretle', 'Mark Paid' => 'Ödendi Olarak İşaretle', 'Membership' => 'Üyelik', 'Membership Info Page' => 'Üyelik Bilgi Sayfası', 'Method' => 'Metod', 'Miscellaneous' => 'Çeşitli', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Çoklu Sipariş Başlığı kullanıcı birden fazla ürün sipariş ettiğinde, ürün ismi yerine aşağıdakini ödeme sisteminde göster', 'New Autoresponder' => 'Yeni Autoresponder', 'New Expiration E-Mail' => 'Yeni Bitiş Emaili', 'New Modules Available' => 'Yeni Modüller Mevcut', 'New Rewrite' => 'Yeni Rewrite', 'No Invoices Found' => 'Fatura Bulunamadı', 'No Updates Available' => 'Mevcut Yükseltme Yok', 'No more charges' => 'Başka Değişiklik Yok', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'Dosyada hiç satır bulunamadı.Dosya boş görünüyor.Geri dönüp başka dosya deneyin.', 'No search name passed' => 'Arama ismi geçmemiş', 'No upgrades to install' => 'Yüklenecek yükseltme yok', 'Not Approved Users' => 'Onaylanmayan Kullanıcılar', 'Not Confirmed Users' => 'Onaylanmamış Kullanıcılar', 'Not-SQL field (default)' => 'SQL alanı deği (varsayılan)', 'Numeric field' => 'Sayısal Alan', 'Only admin can enable user as an affiliate' => 'Kullanıcıyı sadece yönetici affiliate olarak atayabilir', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Dışarı Giden Email Adresi Gönderen olarak kullanılır: müşterilere email göndermek için kullanılan adres Boşsa [Yönetici Email Adresi] kullanılır', 'Overwrite User if Exist User with Same Login' => 'Aynı Giriş İsmiyle Kullanıcı Mevcutsa Kullanıcının Üstüne Yaz', 'Paid' => 'Ödendi', 'Password Length' => 'Şifre Uzunluğu', 'Password must not be equal to username' => 'Şifre kullanıcı adıyla aynı olmamalıdır', 'Passwords must be the same' => 'Şifreler aynı olmalıdır', 'Path to Folder' => 'Dizin Pathi', 'Path/URL' => 'Path/URL', 'Payment date' => 'Ödeme Tarihi', 'Payment has been successfully refunded' => 'Ödeme başarıyla geri iade edildi', 'Payout %d Details' => 'Ödeme %d Detayları', 'Payout Details' => 'Ödeme Detayları', 'Paysystem' => 'Ödeme Sistemi', 'Permissions' => 'İzinler', 'Please assign the following fields: ' => 'Lütfen aşağıdaki alanları tahsis edin: ', 'Please choose another field name. This name is already used' => 'Lütfen başka bir alan adı kullanın. Bu isim kullanılmaktadır.', 'Please enter valid e-mail address' => 'Lütfen geçerli bir email girin', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'Lütfen kullanıcı adı ya da emailinizi girin. Yeni bir şifre oluşturmak için emailinize bir link gönderilecektir.', 'Please select date before today' => 'Bugünden önce bir tarih seçmelisiniz', 'Please wait' => 'Lütfen Bekleyin', 'Product Availability' => 'Ürün Müsaitliği', 'Product Upgrades' => 'Ürün Güncellemeleri', 'Products Per Invoice' => 'Fatura Başına Ürünler', 'Protect Content' => 'İçerik Koru', 'Protection Method' => 'Koruma Şekli', 'Quit Maintenance Mode' => 'Bakım Modundan Çık', 'RadioButtons' => 'SeçenekDüğmeleri', 'Rebill' => 'Tekrar Faturalama', 'Rebill Second Price until cancelled' => 'İkinci Fiyatı İptal Edilinceye Kadar Çek', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Tekrar Faturalama Zamanları Bu ikinci fiyatta oluşacak ödeme sayısıdır', 'Rebuild Db' => 'Veritabanını yeniden kur', 'Receipt' => 'Makbuz', 'Recipients' => 'Alıcılar', 'Records Deleted Sucessfully' => 'Kayıtlar Başarıyla Silindi', 'Referrer' => 'Yönlendiren', 'Refund Payment' => 'Ödemeyi Geri İade Et', 'Remember Login remember username/password in cookies' => 'Giriş Bilgisini Hatırla kullanıcı adı/şifre yi cookilerde hatırla', 'Remind Password to Admin' => 'Yöneticiye Şifre Hatırlat', 'Remind Password to Customer' => 'Kullanıcıya Şifresini Hatırlat', 'Remove Category' => 'Kategori Kaldır', 'Repeat Action Handling' => 'Eylem İşlemini Tekrarla', 'Reports' => 'Raporlar', 'Resend' => 'Tekrar Gönder', 'Resend Signup E-Mail' => 'Kayıt Emailini Tekrar Gönder', 'Resource' => 'Kaynak', 'Restore' => 'Eski Haline Getir', 'Retreive Access Parameters if necessary' => 'Gerekliyse Erişim Parametrelerini Al', 'Return to Payouts List' => 'Ödemeler Listesine Dön', 'Root URL root script URL, usually %s' => 'Root URL root komut URLsi, genellikle %s', 'Root Url and License Keys' => 'Root Url ve Lisans Anahtarları', 'Run Reports' => 'Raporları Çalıştır', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'SMTP Hostname', 'SMTP Hostname is required if you have enabled SMTP method' => 'SMTP metodunu etkinleştirdiyseniz SMTP Hostname gereklidir', 'SMTP Password' => 'SMTP Şifresi', 'SMTP Port' => 'SMTP Portu', 'SMTP Security' => 'SMTP Güvenliği', 'SMTP Username' => 'SMTP Kullanıcı Adı', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (çoklu seçim ve onay kutusu alanları için kullanılamaz)', 'SQL Date Format' => 'SQL Tarih Formatı', 'Save This Search' => 'Bu aramayı kaydet', 'Saved Credit Cards' => 'Kayıtlı Kredi Kartları', 'Saved Search' => 'Kaydedilmiş Arama', 'Second Period' => 'İkinci Dönem', 'Second Price' => 'İkinci Fiyat', 'Second Price price that must be billed for second and the following periods of subscription' => 'İkinci Fiyat ikinci ve daha sonraki abonelik dönemlerinde çekilecek fiyat', 'Secure Root URL secure URL, usually %s' => 'Güvenli Root URL güvenli URL, genellikle %s', 'Select (Multiple Values)' => 'Seç (Çoklu Değer)', 'Select (Single Value)' => 'Seç (Tek Değer)', 'Select a plugin' => 'Bir eklenti seçin', 'Selected for E-Mailing' => 'Email için Seçili', 'Semicolon' => 'Noktalı Virgül', 'Send E-Mail Message' => 'Email Gönder', 'Send E-Mail Messages' => 'Email mesajları gönder', 'Send New E-Mail' => 'Yeni Email Gönder', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Yeni Mesajlar Hakkında Müşteriyi Bilgilendir yönetici her bir bileti yanıtladığında aMember kullanıcıya bilgilendirme yollayacaktır', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'Kayıt Olma Mesajı Gönder müşteri kayıt formunu tamamlayınca (ödemeden önce)', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Kaydolma emaili Gönder İLK abonelik gerçekleştikten sonra', 'Send Test E-Mail' => 'Test Emaili Gönder', 'Sender' => 'Gönderen', 'Sending Test E-Mail...' => 'Test Email Gönderiliyor...', 'Sending e-mail (sent to %d from %d)' => 'Email gönderiliyor (gönderilen %d gönderen %d)', 'Session Storage' => 'Session Saklama', 'Setup/Configuration' => 'Kurum/Yapılandırma', 'Signup Form Configuration' => 'Giriş Formu Yapılandırması', 'Signup Info' => 'Kayıt Bilgileri', 'Signup Messages' => 'Kaydolma Mesajları', 'Site is temporarily disabled for maintenance' => 'Site bakım nedeniyle geçici olarak çevrim dışıdır', 'Size of input field' => 'Girdi alanının boyutu', 'Skip' => 'Atla', 'Skip Line if Exist User with Same Login' => 'Aynı Giriş İsmiyle Kullanıcı Mevcutsa Satır Atla', 'Sort' => 'Sırala', 'Sort Order' => 'Sıralama Düzeni', 'Source' => 'Kaynak', 'Space' => 'Boşluk', 'Standard PHP Sessions' => 'Standart PHP Sessionları', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Başlangıç Tarihi Hesaplaması başlangıç tarihi hesaplaması kuralları. alternatifler içinde en yüksek tarih seçilecektir. Tekrarlayan aboneliklerde bu ayarların etkisi yoktur', 'Started' => 'Başladı', 'Stop Recurring' => 'Tekrar etmeyi durudur', 'String' => 'Dizi', 'Submitting...' => 'İbraz Ediliyor...', 'Subscription' => 'Abonelik', 'Super Admin' => 'Süper Yönetici', 'Surcharge' => 'Ek Ücret', 'Tabulation' => 'Tab', 'Template alternative template for signup page' => 'Şablon kayıt sayfası için alternatif şablon', 'Terms Text automatically calculated if empty' => 'Dönem Dizgisi boşsa otomatik olarak hesaplanır', 'Test E-Mail Settings' => 'Test Email Ayarları', 'Text' => 'Yazı', 'Text (unlimited length string/data)' => 'Yazı (sınırsız uzunlukta dizi/veri)', 'TextArea' => 'Yazma Alanı', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Bu email şablonu verilen lisanda boştur. Şablonu varsayılan lisandan[İngilizce] kopyalamak için [Kopyala]ya basın Sıfırdan yazmak için [Atla]ya bas.', 'This field is requred' => 'Bu alan gereklidir', 'Time' => 'Zaman', 'Title displayed to customers' => 'İsim Müşteriler Gösterilen', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'Bu ürünü sipariş etmek için kullanıcıda bulunması gereken kullanıcı bu ürünü sipariş ettiğinde aşağıdaki abonelikleri olup olmadığı kontrol edilir', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'Elektronik çizelgeyi virgülle ayrılmış(CSV) kaydetmek için (OpenOffice):', 'Total Paid' => 'Toplam Ödenmiş', 'Total to Pay' => 'Toplam Ödenecek', 'Trace' => 'işaret', 'Traditional .htpasswd' => 'Geleneksel .htpasswd', 'Transactions Log' => 'İşlem Kayıtları', 'URL must be specified without trailing slash' => 'URL en sonda eğik çizgi (/) olmadan belirtilmelidir ', 'URL must start from %s or %s' => 'URL %s ya da %s den başlamalıdır', 'Unlock' => 'Kilidi Aç', 'Unpack Upgrades' => 'Yükseltmeleri Aç', 'Update Error' => 'Yükseltme Hatası', 'Update License Information' => 'Lisans Bilgisini Güncelle', 'Update User if Exist User with Same Login' => 'Aynı Giriş İsmiyle Kullanıcı Mevcutsa Kullanıcıyı Güncelle', 'Upgrade' => 'Yükselt', 'Upgrade Database' => 'Veritabanını Yükselt', 'Upgrade Download Problem' => 'Yükseltme İndirme Sorunu', 'Upgrade Finished' => 'Yükseltme Bitti', 'Upgrade From' => 'Bundan Güncelle', 'Upgrade To' => 'Buna Güncelle', 'Upload' => 'Yükle', 'Use E-Mail Throttle Queue' => 'Email Throttle Queue Kullan', 'Use External Cron' => 'Dış Cron Kullan', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'Kullanıcı Kupon Kullanım Sayısı bir kupon kodu kullanıcı tarafından kaç kere kullanılır', 'User Invoices' => 'Kullanıcı Faturaları', 'User Pages Theme' => 'Kullanıcı Sayfaları Teması', 'User currently has access to the following products' => 'Kullanıcının şu anda erişimi olan ürünler', 'User had access to the following products' => 'Kullanıcının şu ürünlere erişimi vardı.', 'Username or e-mail address' => 'Kullanıcı adı ya da email adresi', 'Users' => 'Kullanıcılar', 'Valid license key are one-line string,starts with L and ends with X' => 'Geçerli lisans anahtarları tek satırdır, L harfi ile başlar X harfi ile biter', 'Value use % as wildcard mask' => 'Değer % yi wildcard maskesi olarak kullan', 'Values must not be equal' => 'Değerler eşit olmamalıdır', 'Version Info' => 'Versiyon Bilgisi', 'View' => 'Görünüm', 'View Coupons' => 'Kuponları Gör', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Ödeme sistemine bir istekte bulunacağız ya da sizi iade için ödeme sistemine yönlendireceğiz.', 'Yes, assign category' => 'Evet, Kategori Belirle', 'Yes, do not e-mail this customer for any reasons' => 'Evet, bu müşteriye herhangi bir nedenle email göndermeyin', 'Yes, locked' => 'Evet, kilitli', 'Yes, remove category' => 'Evet Kategoriyi Kaldır', 'You can download %sexample file%s.' => '%sörneknbsp;dosyalar%s indirebilirsiniz.', 'You can import users from CSV file to aMember.' => 'CSV dosyasından aMember\'a kullanıcı ithal edebilirsiniz.', 'You have currently choosed the following users for e-mail to:' => 'Email göndermek için aşağıdaki kullanıcıları seçmiş durumdasınız:', 'You have generated %d demo products and %d demo customers' => '%d demo ürün ve %d demo müşteri oluşturdunuz', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'aMember in geçmiş versiyonlarından kalan lisans anahtarlarınız var, lütfen en yenisiyle değiştirin', 'You have no permissions to perform requested operation' => 'Bu işlemi yapmaya yetkiniz yok.', 'Your Password enter your current password in order to edit admin record' => 'Şifreniz yönetici kayıtlarınızı düzenlemek için mevcut şifrenizi girin', '[From] and [To] billing plans must not be equal' => '[Bundan] [Buna] faturalama planları farklı olmalıdır', 'aMember Database (default)' => 'aMember Veritabanı (varsayılan)', 'access log table (used by admin only)' => 'erişim log tablosu (sadece yönetici tarafından kullanılır)', 'admin log table (used by admin only)' => 'yönetici log tablosu (sadece yönetici tarafından kullanılır)', 'change' => 'değiştir', 'collapse details' => 'detayları kapat', 'days after expiration' => 'sona ermeden sonra gün sayısı', 'days before expiration' => 'sona ermeden önce gün sayısı', 'error_log table (used by admin only)' => 'hata log tablosu (sadece yönetici tarafından kullanılır)', 'expand details' => 'detayları genişlet', 'first paid at' => 'ilk ödendiği', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'eğer kod mevcutsa bu ürünler alış veriş sepetinizde gizlenecektir ve ürünleri görmek için bu kod gereklidir.', 'if customer uses more than' => 'eğer müşteri bundan daha fazla kullanırsa', 'if user enters wrong password' => 'eğer kullanıcı yanlış şifre kullanırsa', 'login, email or name' => 'Giriş , email ya da isim', 'must be a number in format 99 or 99.99' => '99 ya da 99.99 formatında bir rakam olmalı', 'must be equal or greather than 0' => '0 a eşit ya da bdaha büyük olmalı', 'must be equal or greather than 0.0' => '0.0 dan büyük ya da eşit olmalıdır', 'on expiration day' => 'sona erme gününde', 'open in new window' => 'yeni pencerede aç', 'or %smake access free%s' => 'ya da %serişimi serbest yapın%s', 'put website offline, making it available for admins only' => 'web sitesini çevrim dışı yap, sadece yöneticiler ulaşabilsin', 'sending' => 'gönderiliyor', 'sent successfully' => 'başarıyla gönderildi', 'switch to show all records' => 'bütün kayıtları göstermeye geç', 'switch to show only active records' => 'sadece aktif kayıtları göstermeye geç', 'times within' => 'sürede kez', 'version' => 'versiyon', ); PK\Gqqdefault/language/admin/fr.phpnu[ '%d jours après expiration', '%d days before expiration' => '%d jours avant expiration', '%d user(s) matches your search' => '%d utilisateurs correspondent à votre recherche', '%d-th subscription day' => '%d-è jour d\'abonnement', 'Access Method' => 'Méthode d\'accès', 'Account Sharing Prevention' => 'Prévention du partage de compte', 'Account Verification' => 'Vérification du compte', 'Add Payment' => 'Ajouter paiement', 'Add Payment Manually' => 'Ajouter un paiement manuellement', 'Add Subscription' => 'Ajouter un abonnement', 'Add User Fields' => 'Ajouter des champs', 'Additional' => 'Additionnel', 'Admin Accounts' => 'Comptes Admin', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'Adresse email administrateur utilisé pour envoyer des emails de notifications aux admins et comme adresse d\'envoi par défaut', 'Admin Log' => 'Log Admin', 'Admin Pages Theme' => 'Thème des pages administrateur', 'Admin Payment Notifications to admin once payment is received' => 'Notifications de paiement administrateur à l\'administrateur une fois le paiement reçu', 'Admin Settings' => 'Paramètres Admin', 'Administrator Login' => 'Connexion adminisratue', 'Affiliate Commission' => 'Commission affilié', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Durée de vie du Cookie Affilié jours pour conserver les cookies sur un affilié spécifique', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Jour de paiement des affiliés choisissez un jour du mois où le paiement est généré', 'Affiliates Signup Type' => 'Type d\'inscription pour les Affiliés', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'Après avoir effectué n\'importe quel changement aux zones protégées htpasswd, veuillez lancer [Utiltites->Rebuild Db] pour mettre à jour le fichier htpasswd', 'All new users automatically become affiliates' => 'Tous les nouveaux utilisateurs deviennent affiliés', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Nombre d\'emails autorisés entrez le nombre d\'emails autorisés dans la période ci-dessus', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Périodes d\'emails autorisées choisissez si votre hôte limite les emails par jour ou par heure', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Toujours se souvenir si fixé sur Oui, ne pas demander à l\'utilisateur - toujours se souvenir', 'Assign Category' => 'Assigner une catégorie', 'Available Upgrades' => 'Mises à niveau disponibles', 'Backup' => 'Sauvegarde', 'Banner' => 'Bannière', 'Billing' => 'Facturation', 'Blob (unlimited length binary data)' => 'Blob (donnée binaire à longueur illimitée)', 'Blocking IP/E-Mail' => 'Bloquer IP/email', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Temporairement indisponible pour maintenance. Vérifiez dans une minute.', 'Browse Found Users' => 'Naviguer parmi les utilisateurs trouvés', 'Browse Users' => 'Naviguer parmi les utilisateurs', 'Bruteforce Protection' => 'Protection bruteforce', 'Build Demo' => 'Construire la démo', 'Building demo records' => 'Enregistrements démo en cours d\'élaboration', 'Can not find user with such username or email' => 'Utilisateur introuvable avec un tel nom d\'utilisateur ou email', 'Cancellations' => 'Annulations', 'Change Configuration Settings' => 'Changer les options de configuration', 'Change Paysystem' => 'Changer le système de paiement', 'Charge Second Price Once' => 'Facturer le second prix une fois', 'Charge Second Price x Times' => 'Facturer le second prix x fois', 'CheckBoxes' => 'Cases à cocher', 'Choose Products and/or Product Categories that allows access' => 'Choisir les produits et/ou les catégories de produit qui permettent l\'accès', 'Choose Upgrades to Install' => 'Choisissez les mises à niveau à installer', 'Choose action when locked %s used by customer during signup' => 'Choisissez l\'action quand la touche majuscule %s est utilisée par le client pendant l\'inscription', 'Cleaning up' => 'Nettoyage en cours', 'Cleanup' => 'Nettoyage', 'Clear' => 'Vider', 'Clear Access Log' => 'Effacer les enregistrements d\'accès', 'Click to Expand' => 'Cliquez pour étendre', 'Comma' => 'Virgules', 'Commission earned' => 'Commission gagnée', 'Commission for First Payment calculated for first payment in each invoice' => 'Commission pour le premier paiement calculée pour le premier paiement dans chaque facture', 'Commission for Free Signup calculated for first customer invoice only' => 'Commission pour une inscription gratuite calculée pour la première facture client uniquement', 'Commission for Rebills' => 'Commission pour les refacturations', 'Copy' => 'Copier', 'Copy Upgrades' => 'Copier les mises à niveau', 'Copy from another language' => 'Copier depuis une autre langue', 'Core' => 'Coeur', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Echec du téléchargement du fichier [%s]. Erreur %s. Veuillez %sréessayer%s plus tard.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'Impossible de récupérer la liste des mises à niveau depuis le serveur distant. %sVeuillez réessayer%', 'Could not fetch upgrades list. Connection error [%s]' => 'Impossible de récupérer la liste des mises à niveau. Erreur de connexion [%s]', 'Coupons' => 'Coupons', 'Coupons Batches' => 'Groupes de Coupons', 'Create Session Key' => 'Créer une clé de session', 'Create ticket as' => 'Créer un ticket', 'Custom Commission Rules added' => 'Règles de commission personnalisées ajoutées', 'Custom Signup Form Title keep empty to use default title' => 'Titre de formulaire d\'inscription personnalisé laisser vide pour utiliser le titre par défaut', 'Customer' => 'Client', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Date pour le nettoyage tous les enregistrements antérieurs à cette date seront supprimés des tables sélectionnées', 'Default - user clicks a link to become affiliate' => 'Par défaut - l\'utilisateur clique sur un lien pour devenir affilié', 'Default Billing Plan' => 'Plan de facturation par défaut', 'Default Commission' => 'Commission par défaut', 'Default Signup' => 'Inscription par défaut', 'Default for Members' => 'Par défaut pour les membres', 'Delete Old Records' => 'Supprimer les anciens enregistrements', 'Delimiter' => 'Délimiteur', 'Demo History' => 'Historique de la démo', 'Description displayed to visitors on order page below the title' => 'Description affichée aux visiteurs sur la page de commande sous le titre', 'Details' => 'Détails', 'Die and show ugly error message' => 'Crash et affichage d\'un message d\'erreur moche', 'Disable auto-locking for this customer' => 'Désactiver le verrouillage automatique pour cet utilisateur', 'Disallow new Signups by %s' => 'Rejeter les nouvelles inscriptions par %s', 'Display Language Choice' => 'Afficher le choix de langue', 'Display error message' => 'Afficher le message d\'erreur', 'Do not generate products use existing products for demo records' => 'Ne générez pas de produits utilisez les produits existants pour les enregistrements de démo', 'Do you really want to refund payment' => 'Souhaitez-vous réellement rembourser le paiement', 'Do you really want to stop this subscription?' => 'Souhaitez-vous vraiment arrêter cet abonnement ?', 'Download Upgrades' => 'Télécharger les mises à niveau', 'Duration:' => 'Durée :', 'E-Mail Address to Send to' => 'Adresses email pour envoyer à', 'E-Mail Backup Address' => 'Adreses email de backup', 'E-Mail Commission to Admin' => 'E-Mail la commission à l\'Admin', 'E-Mail Commission to Affiliate' => 'E-mail la commission à l\'affilié', 'E-Mail Database Backup' => 'Sauvegarde de la base de données email', 'E-Mail Queue' => 'Emails en attente', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'Nom de l\'expéditeur du mail', 'E-Mail Sending' => 'Envoi d\'E-Mail', 'E-Mail System Configuration' => 'Configuration du système d\'email', 'E-Mail Type' => 'Type d\'E-Mail', 'E-Mail Users' => 'Envoyer un email aux utilisateurs', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'L\'E-Mail a été envoyé avec succès aux %s clients. L\'ID du groupe d\'E-Mail est %s', 'E-Mail sending started' => 'Envoi de l\'E-mail commencé', 'E-Mails History' => 'Historique des E-Mails', 'E-Mails by Admin Request' => 'Envoyer par mail sur requête d\'un administrateur', 'E-Mails by User Request' => 'Envoyer par email sur requête de l\'utilisateur', 'Edit Custom Commission Rules' => 'Editer les règles personnalisées de commission', 'Edit Groups' => 'Modifier les groupes', 'Email Backup Frequency' => 'Fréquence des sauvegardes email', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'Méthode d\'envoi d\'email VEUILLEZ NE PAS CHANGER si l\'envoi d\'emails depuis aMember fonctionne', 'Email Sent' => 'Email envoyé', 'Enable plugins if necessary' => 'Activer les plugins si nécessaire', 'Enter Maintenance Mode' => 'Entrer en mode maintenance', 'Error Log' => 'Log d\'erreur', 'Error/Debug Log' => 'Enregistrement d\'erreur/de déboguage', 'Errors' => 'Erreurs', 'Errors:' => 'Erreurs :', 'Every %s' => 'chaque %s', 'Exchange Rate' => 'Taux de change', 'Exchange Rate enter cost of 1 (one) %s' => 'Taux de change entrer le coût pour 1(un) %s', 'Field Name' => 'Nom du champ', 'Field Title' => 'Titre du champ', 'Field Values' => 'Valeurs du champ', 'File is required' => 'Le fichier est requis', 'Filter by String' => 'Filtrer par chaine', 'Filter by string or by invoice#/member#' => 'Filtrer par chaine ou par facture#/membre#', 'First Period' => 'Première période', 'First Price' => 'Premier prix', 'First Price price of first period of subscription' => 'Premier prix prix de la première période d\'abonnement', 'First and Last Name' => 'Prénom et Nom', 'First visited' => 'Première visite le', 'Fix aMember Pro License Key' => 'Réparer la clé de licence aMember Pro', 'Fixed date' => 'Date réparée', 'Folder URL' => 'URL Dossier', 'Form Type' => 'Type de formulaire', 'Forms Editor' => 'Editeur de formulaires', 'Future' => 'Futur', 'General' => 'Général', 'General Settings' => 'Options générales', 'Generate' => 'Générer', 'Generate Payout Manually' => 'Générer le paiement manuellement', 'Generation of demo data was terminated while processing. Not all records were created.' => 'La génération de donnée de démo a été arrêtée en cours de traitement. Certains enregistrements n\'ont pas été créés.', 'Get Available Upgrades List' => 'Obtenir la liste des mises à niveau disponibles', 'Get New Password' => 'Obtenir un nouveau mot de passe', 'Global' => 'Global', 'Hostname' => 'Nom d\'hôte', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'NOTE IMPORTANTE : Votre contenu ne sera pas protégé. Si quelqu\'un connaît l\'URL du lien, il sera capable d\'ouvrir le lien sans problème. Cela contrôle uniquement quels liens additionnels seront visibles par l\'utilisateur after l\'authentification dans la zone membres.', 'IP' => 'IP', 'IP within' => 'IP en', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Si vous changez de processeur de paiement, vous pouvez utiliser cette page pour passer l\'abonnement existant d\'un processeur de paiement à l\'autre. Cela est possible uniquement si les informations complètes de carte de crédit sont stockées chez aMember.', 'Import Users' => 'Importer les utilisateurs', 'Install Updates' => 'Installer les mises à jour', 'Integer field (only numbers)' => 'Champ entier (nombres uniquement)', 'Integration plugins' => 'Intégration des plugins', 'Internal PHP mail() function (default)' => 'Fonction mail() PHP interne (par défaut)', 'Intro Text on Helpdesk Page' => 'Texte d\'introduction sur la page du Bureau d\'aide', 'Invoice Log' => 'Enregistrement de facture', 'Invoices Per User' => 'Factures par utilisateur', 'Is Affiliate?' => 'Est affilié ?', 'Is Approved' => 'Est approuvé', 'It is required to setup a cron job to trigger backup generation' => 'Il est nécessaire de mettre en place un cron job pour déclencher la génération de sauvegardes', 'Languages' => 'Langues', 'Last %s Customers' => '%s derniers clients', 'Last existing subscription date of this product' => 'Dernière date d\'abonnement existante de ce produit', 'Last login' => 'Dernière connexion', 'Length of admin password must be from %d to %d' => 'La longueur du mot de passe admin doit être compris entre %d et %d', 'Length of username must be from %d to %d' => 'La longueur du nom d\'utilisateur doit être comprise entre %d et %d', 'Lightbox Main Image' => 'Image principale Lightbox', 'Lightbox Thumbnail Image' => 'Image vignette Lightbox', 'Lines Proccessed:' => 'Lignes traitées :', 'Lines Skipped:' => 'Lignes ignorées :', 'Lines Success:' => 'Lignes avec succès :', 'Link to reset your password was sent to your Email.' => 'Le lien pour réinitialiser votre mot de passe a été envoyé à votre adresse Email.', 'Lock' => 'Verrouiller', 'Locked Value' => 'Valeur bloquée', 'Log Outgoing E-Mail Messages for ... days' => 'Enregistrer les emails sortants pour ... jours', 'Log in' => 'Connexion', 'Logged in as %s' => 'Connecté en tant que %s', 'Login Page' => 'Page de connexion', 'Logs' => 'Enregistrements', 'Lookup' => 'Regarder', 'Lost your password?' => 'Mot de passe perdu ?', 'Mail' => 'Mail', 'Maintenance Mode' => 'Mode de maintenance', 'Manage Product Upgrade Paths' => 'Gérer les chemins de mise à jour des produits', 'Manage Products' => 'Gérer les produits', 'Manually Added' => 'Ajouté manuellement', 'Mark NOT Paid' => 'Marque comme non payé', 'Mark Paid' => 'Marqué comme payé', 'Membership' => 'Abonnement', 'Method' => 'Méthode', 'Miscellaneous' => 'Divers', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Titre commande multiple lorsque l\'utilisateur commande plusieurs produits, afficher ceci sur le système de paiement au lieu du nom du produit', 'New Autoresponder' => 'Nouveau répondeur automatique', 'New Expiration E-Mail' => 'Nouvel E-Mail d\'Expiration', 'New Modules Available' => 'Nouveaux modules disponibles', 'New Rewrite' => 'Nouvelle réécriture', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'Aucune Carte de Crédit stockée pour ce client. %sAjouter une Carte de Crédit%s', 'No Invoices Found' => 'Aucune facture trouvée', 'No Updates Available' => 'Pas de mise à jour disponible', 'No more charges' => 'Pas plus de frais', 'No search name passed' => 'Pas de nom de recherche passé', 'No upgrades to install' => 'Pas de mises à niveau à installer', 'Not Approved Users' => 'Utilisateurs non approuvés', 'Not-SQL field (default)' => 'Champ non-SQL (par défaut)', 'Numeric field' => 'Champ numérique', 'Only admin can enable user as an affiliate' => 'Seuls un admin peut activer un utilisateur en tant qu\'affilié', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Adresse email d\'envoi utilisée comme adresse email d\'expédition des mails aux clients. Si vide [Admin E-Mail Address] est utilisée', 'Overwrite User if Exist User with Same Login' => 'Ecraser l\'utilisateur s\'il existe un utilisateur avec le même identifiant', 'PDF Invoice' => 'Facture PDF', 'Paid' => 'Payé', 'Password Length' => 'Longueur du mot de passe', 'Password must not be equal to username' => 'Le mot de passe ne peut pas être identique au nom d\'utilisateur', 'Passwords must be the same' => 'Les mots de passe doivent être identiques', 'Path to Folder' => 'Chemin vers le dossier', 'Path/URL' => 'Chemin/URL', 'Payment date' => 'Date de paiement', 'Payment has been successfully refunded' => 'Le paiement a été remboursé avec succès.', 'Payout %d Details' => '%d Détails du paiement', 'Payout Details' => 'Détails du paiement', 'Paysystem' => 'Système de paiement', 'Permissions' => 'Permissions', 'Please assign the following fields: ' => 'Veuillez remplir les champs suivants :', 'Please choose another field name. This name is already used' => 'Veuillez choisir un autre nom de champs. Ce nom est déjà utilisé', 'Please enter valid e-mail address' => 'Veuillez saisir une adresse email valide', 'Please select date before today' => 'Veuillez sélectionner une date avant aujourd\'hui', 'Please wait' => 'Veuillez attendre', 'Plugins' => 'Plugins', 'Product Availability' => 'Disponibilité du produit', 'Product Upgrades' => 'Mises à jour de produits', 'Products Per Invoice' => 'Produits par facture', 'Protect Content' => 'Protéger le contenu', 'Protection Method' => 'Méthode de protection', 'Quit Maintenance Mode' => 'Quitter le mode maintenance', 'RadioButtons' => 'Boutons radio', 'Rebill' => 'Refacturer', 'Rebill Second Price until cancelled' => 'Refacturer le second prix jusqu\'à annulation', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Nombre de refacturations Ceci est le nombre de paiements qui auront lieu au Second Prix', 'Rebuild Db' => 'Reconstruire la base de données', 'Receipt' => 'Reçu', 'Recipients' => 'Destinataires', 'Records Deleted Sucessfully' => 'Enregistrements supprimés avec succès', 'Referrer' => 'Parrain', 'Refund Payment' => 'Rembourser le paiement', 'Remember Login remember username/password in cookies' => 'Se souvenir de la connexion se souvenir du nom d\'utilisateur/mot de passe dans les cookies', 'Remind Password to Admin' => 'Rappeler le mot de passe à l\'administrateur', 'Remind Password to Customer' => 'Rappeler le mot de passe à l\'utilisateur', 'Remove Category' => 'Supprimer la catégorie', 'Repeat Action Handling' => 'Répéter le traitement de l\'action', 'Reports' => 'Rapports', 'Resend' => 'Envoyer de nouveau', 'Resend Signup E-Mail' => 'Renvoyer l\'email d\'inscription', 'Resource' => 'Ressource', 'Restore' => 'Restaurer', 'Retreive Access Parameters if necessary' => 'Récupérer les paramètres d\'accès si nécessaire.', 'Return to Payouts List' => 'Retour à la liste des paiements', 'Root URL root script URL, usually %s' => 'URL racine URL script racine, habituellement %s', 'Root Url and License Keys' => 'URL racine et clés de licence', 'Run Reports' => 'Lancer les rapports', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'Nom d\'hôte SMTP', 'SMTP Hostname is required if you have enabled SMTP method' => 'Le nom d\'hôte SMTP est requis si vous avez activé la méthode SMTP', 'SMTP Password' => 'Mot de passe SMTP', 'SMTP Port' => 'Port SMTP', 'SMTP Security' => 'Sécurité SMTP', 'SMTP Username' => 'Nom d\'utilisateur SMTP', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (ne peut pas être utilisé pour les champs avec sélections multiples et les cases à cocher)', 'Save This Search' => 'Enregistrer cerre cherche', 'Saved Credit Cards' => 'Cartes de crédit sauvegardées', 'Saved Search' => 'Recherche enregistrée', 'Second Period' => 'Seconde période', 'Second Price' => 'Second prix', 'Second Price price that must be billed for second and the following periods of subscription' => 'Second Prix le prix qui doit être facturé pour la seconde et les périodes suivantes de l\'abonnement', 'Secure Root URL secure URL, usually %s' => 'URL Racine sécurisée URL sécurisée, habituellement %s', 'Select (Multiple Values)' => 'Sélectionner (valeurs multiples)', 'Select (Single Value)' => 'Sélectionner (valeur unique)', 'Select a plugin' => 'Sélectionner un plugin', 'Selected for E-Mailing' => 'Sélectionné pour l\'E-Mailing', 'Semicolon' => 'Virgule', 'Send E-Mail Message' => 'Envoyer un message E-Mail', 'Send E-Mail Messages' => 'Envoyer des emails', 'Send New E-Mail' => 'Envoyer un nouvel E-Mail', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Envoyer des notifications de nouveaux messages aux client aMember enverra une notification aux utilisateurs à chaque fois qu\'un administrateur répond à un ticket utilisateur', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Envoyer un email d\'inscription une fois que le PREMIER abonnement est effectué', 'Send Test E-Mail' => 'Envoyer un email de test', 'Sender' => 'Expéditeur', 'Sending Test E-Mail...' => 'Envoi de l\'email de test ...', 'Sending e-mail (sent to %d from %d)' => 'Envoi de l\'e-mail (envoyé à %d de %d)', 'Setup/Configuration' => 'Installation/configuration', 'Signup Form Configuration' => 'Configuration du formulaire d\'inscription', 'Signup Info' => 'Informations d\'inscription', 'Site is temporarily disabled for maintenance' => 'Le site est temporairement fermé pour maintenance', 'Size of input field' => 'Taille du champ de saisie', 'Skip' => 'Passer', 'Skip Line if Exist User with Same Login' => 'Passer cette ligne s\'il existe un utilisateur avec le même identifiant', 'Sort' => 'Trier', 'Sort Order' => 'Ordre de tri', 'Source' => 'Source', 'Space' => 'Espace', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Calcul de la date du début règles pour le calcul de la date du début de l\'abonnement la date MAX des alternatives sera choisie. Cette option n\'a aucun effet sur les abonnements récurrents', 'Started' => 'Commencé', 'Step %d of %d' => 'Etape %d de %d', 'Stop Recurring' => 'Arrêter récurrence', 'String' => 'Chaîne', 'Submitting...' => 'Envoi en cours ...', 'Subscription' => 'Abonnement', 'Super Admin' => 'Super Admin', 'Surcharge' => 'Surfacturer', 'Tabulation' => 'Tabulation', 'Template alternative template for signup page' => 'Modèle modèles alternatifs pour la page d\'inscription', 'Terms Text automatically calculated if empty' => 'Conditions calculé automatiquement si vide', 'Test E-Mail Settings' => 'Tester les options de mail', 'Text' => 'Texte', 'Text (unlimited length string/data)' => 'Texte (longueur de chaîne/donnée illimitée)', 'TextArea' => 'Zone de texte', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Ce gabarit d\'email est vide pour la langue sélectionnée. Appuyer sur [Copy] pour copier le gabarit du langage par défaut [Anglais] Appuyer sur [Passer] pour le rédiger manuellement depuis le début.', 'This field is requred' => 'Ce champ est requis', 'Ticket#' => 'Ticket#', 'Time' => 'Heure', 'Title displayed to customers' => 'Titre affiché aux clients', 'Total Paid' => 'Total payé', 'Total to Pay' => 'Total à payer', 'Trace' => 'Tracer', 'Traditional .htpasswd' => '.htpasswd traditionnel', 'URL must be specified without trailing slash' => 'L\'URL doit être spécifiée sans slash', 'URL must start from %s or %s' => 'L\'URL doit être commencer à %s or %s', 'Unlock' => 'Déverrouiller.', 'Unpack Upgrades' => 'Décompresser les mises à niveau', 'Update Error' => 'Erreur de la mise à jour', 'Update License Information' => 'Mettre à jour les informations de licence', 'Update User if Exist User with Same Login' => 'Mettre à jour l\'utilisateur s\'il existe un utilisateur avec le même identifiant', 'Upgrade' => 'Mise à niveau', 'Upgrade Database' => 'Mettre à niveau la base de données', 'Upgrade Download Problem' => 'Problème de téléchargement de la mise à niveau', 'Upgrade Finished' => 'Mise à niveau terminée', 'Upgrade From' => 'Mettre à niveau depuis', 'Upgrade To' => 'Mettre à niveau vers', 'Upload' => 'Transfert', 'Use E-Mail Throttle Queue' => 'Utiliser', 'Use External Cron' => 'Utiliser externe', 'User Invoices' => 'Factures de l\'utilisateur', 'User Pages Theme' => 'Thème des pages utilisateur', 'User currently has access to the following products' => 'L\'utilisateur a actuellement accès aux produits suivants', 'User had access to the following products' => 'L\'utilisateur avait accès aux produits suivants', 'User is not found in database' => 'L\'utilisateur n\'est pas trouvé dans la base de donnée', 'Username or e-mail address' => 'Nom d\'utilisateur ou adresse email', 'Users' => 'Utilisateur', 'Value use % as wildcard mask' => 'Valeur utiliser % comme masque invité', 'Values must not be equal' => 'Les valeurs doivent être identiques', 'Version Info' => 'Informations de version', 'View' => 'Visualiser', 'View Coupons' => 'Voir les Coupons', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Nous enverrons une requête au système de paiement ou vous serez redirigé vers le système de paiement pour envoyer une requête de remboursement', 'Yes, assign category' => 'Oui, assigner une catégorie', 'Yes, do not e-mail this customer for any reasons' => 'Oui, n\'envoyer de mail à cet utilisateur sous aucun prétexte', 'Yes, locked' => 'Oui, verrouillé', 'Yes, remove category' => 'Oui, supprimer la catégorie', 'You have currently choosed the following users for e-mail to:' => 'Vous avez actuellement choisi les utilisateurs suivants :', 'You have generated %d demo products and %d demo customers' => 'Vous avez généré %d produits démo et %d clients démo', 'Your Password enter your current password in order to edit admin record' => 'Votre mot de passe entrez votre mot de passe actuel afin d\'éditer les enregistrements admin', '[From] and [To] billing plans must not be equal' => 'Les plans de facturation [De] et [A] ne doivent pas être égaux', 'access log table (used by admin only)' => 'Accéder à la table de log (utilisé uniquement par l\'admin)', 'admin log table (used by admin only)' => 'table de log admin (utilisé par l\'admin uniquement)', 'change' => 'changer', 'collapse details' => 'afficher les détails', 'days after expiration' => 'jours après expiration', 'days before expiration' => 'jours avant expiration', 'displaying records %d-%d from %d' => 'enregistrements affichés %d-%d de %d', 'error_log table (used by admin only)' => 'table error_log (utilisé par l\'admin uniquement)', 'expand details' => 'afficher les détails', 'first paid at' => 'payé en premier à', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'si le code est présent, les produits seront masqués dans le panier et ce code sera nécessaire pour les voir', 'if customer uses more than' => 'si le client utilise plus de', 'if user enters wrong password' => 'si l\'utilisateur saisit un mot de passe incorrect', 'login, email or name' => 'nom d\'utilisateur, email ou nom', 'must be a number in format 99 or 99.99' => 'doit être un nombre au format 99 ou 99.99', 'must be equal or greather than 0' => 'doit être égal ou supérieur à 0', 'must be equal or greather than 0.0' => 'doit être égal ou supérieur à 0.0', 'on expiration day' => 'au jour d\'expiration', 'open in new window' => 'Ouvrir dans une nouvelle fenêtre', 'put website offline, making it available for admins only' => 'mettre le site hors-ligne, disponible pour les admins seulement', 'sending' => 'envoi en cours', 'sent successfully' => 'envoyé avec succès', 'switch to show all records' => 'changer pour afficher tous les enregistrements', 'switch to show only active records' => 'changer pour afficher uniquement les enregistrements actifs', 'times within' => 'fois en', 'version' => 'version', ); PK\aXy^y^default/language/admin/zh.phpnu[ '过期后%d天', '%d days before expiration' => '过期前%d天', '%d user(s) matches your search' => '%d用户匹配您的搜索', '%d-th subscription day' => '第%d订阅日', 'Access Method' => '访问方法', 'Account Sharing Prevention' => '防止账户共享', 'Account Verification' => '账户验证', 'Add Payment' => '增加支付', 'Add Payment Manually' => '手动添加支付', 'Add Subscription' => '增加订阅', 'Add User Fields' => '增加栏', 'Additional' => '额外的', 'Admin Accounts' => '管理员账户', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => '管理员电子邮件地址 用来给管理员发送电邮通知 并作为默认的发送地址', 'Admin Log' => '管理员日志', 'Admin Pages Theme' => '管理员页面主题', 'Admin Payment Notifications to admin once payment is received' => '管理员支付通知 一旦支付收到发给管理员', 'Admin Settings' => '管理员设置', 'Administrator Login' => '管理员登录', 'Affiliate Commission' => '分销佣金', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => '分销COOKIES时长 存储推荐分销COOKIE的天数', 'Affiliates Payout Day choose a day of month when payout is generated' => '分销取款日 选择月份中的1天生成取款', 'Affiliates Signup Type' => '分销注册类型', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => '在对htpasswd 保护区做了更改之后,请运行[Utiltites->Rebuild Db] 来刷新htpasswd文件夹', 'All new users automatically become affiliates' => '所有新用户自动成为分销商', 'Allowed E-Mails Count enter number of emails allowed within the period above' => '允许的电子邮件数 输入上面时间段内允许的电子邮件数', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => '允许的电子邮件时期 如果您的主机限制每天或每小时的邮件请选择', 'Always Remember if set to Yes, don\'t ask customer - always remember' => '总是记住 如果设是,不要问顾客-总是记住', 'Assign Category' => '分配目录', 'Available Upgrades' => '可用的升级', 'Backup' => '备份', 'Banner' => '条幅', 'Billing' => '账单', 'Blob (unlimited length binary data)' => 'BLOB(无限制长度二进制数据)', 'Blocking IP/E-Mail' => '屏蔽IP/电子邮件', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => '定期维修不可用。1分钟后检查。', 'Browse Found Users' => '浏览找到的用户', 'Browse Users' => '浏览用户', 'Bruteforce Protection' => '暴力破解保护', 'Build Demo' => '建立演示', 'Building demo records' => '建立演示记录', 'Can not find user with such username or email' => '无法找到此用户名或邮件的用户', 'Cancellations' => '取消', 'Change Configuration Settings' => '更改配置设置', 'Change Paysystem' => '更改支付系统', 'Charge Second Price Once' => '第二价格支付一次', 'Charge Second Price x Times' => '第二价格支付X次', 'CheckBoxes' => '复选框', 'Choose Products and/or Product Categories that allows access' => '选择产品和/或允许进入的产品目录', 'Choose Upgrades to Install' => '选择要安装的升级', 'Choose action when locked %s used by customer during signup' => '当客户在注册过程使用锁定%s时,选择行为', 'Cleaning up' => '清除', 'Cleanup' => '清除', 'Clear' => '清除', 'Clear Access Log' => '清除访问日志', 'Click to Expand' => '点击扩展', 'Comma' => '逗号', 'Commission earned' => '获得的佣金', 'Commission for First Payment calculated for first payment in each invoice' => '首次支付的佣金 在每张发票中为首次支付计算', 'Commission for Free Signup calculated for first customer invoice only' => '免费注册的佣金 仅为首次客户发票计算', 'Commission for Rebills' => '再次支付的佣金', 'Copy' => '复制', 'Copy Upgrades' => '复制升级', 'Copy from another language' => '从其他语言复制', 'Core' => '核心', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => '无法下载文件[%s]。错误%s。请过后%s重试%s。', 'Could not fetch upgrades list from remote server. %sTry again%' => '无法从远程服务器获取升级列表。%s重试%s', 'Could not fetch upgrades list. Connection error [%s]' => '无法获取升级列表。连接错误[%s]', 'Coupons' => '优惠券', 'Coupons Batches' => '优惠券批', 'Create Session Key' => '创建会话密钥', 'Create ticket as' => '创建问题作为', 'Custom Commission Rules added' => '增加的定制佣金规则', 'Custom Signup Form Title keep empty to use default title' => '自定义注册表格标题 保持空白来使用默认标题', 'Customer' => '顾客', 'Date to Purge all records prior to this date will be removed from selected tables' => '清除日期 在此日期前所有记录从选定的表中移除', 'Default - user clicks a link to become affiliate' => '默认-用户点击链接成为分销商', 'Default Billing Plan' => '默认账单计划', 'Default Commission' => '默认佣金', 'Default Signup' => '默认注册', 'Default for Members' => '对会员默认', 'Delete Old Records' => '删除旧记录', 'Delimiter' => '定界符', 'Demo History' => '演示历史', 'Description displayed to visitors on order page below the title' => '描述 在订购页面标题下方显示给访问者', 'Details' => '详情', 'Die and show ugly error message' => '终止并显示难看的错误消息', 'Disable auto-locking for this customer' => '为此客户禁用自动锁定', 'Disallow new Signups by %s' => '通过%s不允许新注册', 'Display Language Choice' => '显示语言选择', 'Display error message' => '显示错误消息', 'Do not generate products use existing products for demo records' => '不生成产品 为演示记录使用现有产品', 'Do you really want to refund payment' => '您真的想退款', 'Do you really want to stop this subscription?' => '您真的想退订?', 'Download Upgrades' => '下载升级', 'Duration:' => '持续:', 'E-Mail Address to Send to' => '用于接收到电子邮件地址', 'E-Mail Backup Address' => '电子邮件备份地址', 'E-Mail Commission to Admin' => '电子邮件发送佣金给管理员', 'E-Mail Commission to Affiliate' => '电子邮件发送佣金给分销商', 'E-Mail Database Backup' => '电子邮件数据库备份', 'E-Mail Queue' => '电子邮件队列', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => '电子邮件发送者姓名', 'E-Mail Sending' => '电子邮件发送', 'E-Mail System Configuration' => '电子邮件系统配置', 'E-Mail Type' => '电子邮件类型', 'E-Mail Users' => '电子邮件用户', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => '电子邮件被成功发送给%s客户。电子邮件批次用户名是%s', 'E-Mail sending started' => '电子邮件发送开始', 'E-Mails History' => '电子邮件历史', 'E-Mails by Admin Request' => '根据管理员请求的电子邮件', 'E-Mails by User Request' => '根据用户请求的电子邮件', 'Edit Custom Commission Rules' => '编辑定制的佣金规则', 'Edit Groups' => '编辑群组', 'Email Backup Frequency' => '电子邮件备份频率', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => '电子邮件发送方法 如果aMember 邮件正常请不要更改', 'Email Sent' => '发送的邮件', 'Enable plugins if necessary' => '如果必要,开启插件', 'Enter Maintenance Mode' => '进入维修模式', 'Error Log' => '错误日志', 'Error/Debug Log' => '错误/调试 日志', 'Errors' => '错误', 'Errors:' => '错误:', 'Every %s' => '每个%s', 'Exchange Rate' => '汇率', 'Exchange Rate enter cost of 1 (one) %s' => '汇率 输入1%s费用', 'Field Name' => '栏名称', 'Field Title' => '栏标题', 'Field Values' => '字段值', 'File is required' => '需要文件', 'Filter by String' => '根据短语过滤', 'Filter by string or by invoice#/member#' => '根据字符串或发票过滤#/会员#', 'First Period' => '第一期', 'First Price' => '第一价格', 'First Price price of first period of subscription' => '第一价格 第一期订阅价格', 'First and Last Name' => '名和姓', 'First visited' => '首次访问', 'Fix aMember Pro License Key' => '修复aMember Pro许可密钥', 'Fixed date' => '固定日期', 'Folder URL' => '文件夹链接', 'Form Type' => '表格类型', 'Forms Editor' => '表格编辑器', 'Future' => '未来', 'General' => '总体', 'General Settings' => '常规设置', 'Generate' => '生成', 'Generate Payout Manually' => '手动生成取款', 'Generation of demo data was terminated while processing. Not all records were created.' => '演示数据生成在处理过程中被终止。不是全部记录被创建。', 'Get Available Upgrades List' => '获取可用的升级列表', 'Get New Password' => '获得新密码', 'Global' => '全球', 'Hostname' => '主机', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => '重要注意:这将不保护内容。如果某人知道链接,他将能打开链接。这只控制用户在登录用户区域后能看见的其他链接。', 'IP' => 'IP地址', 'IP within' => 'IP地址在', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => '如果您从支付方式移动到其他,您可使用此页面在现有的订阅支付方式间切换。只有信用卡完整信息被存储在aMember这边才可能。', 'Import Users' => '导入用户', 'Install Updates' => '安装更新', 'Integer field (only numbers)' => '整数栏(仅数字)', 'Integration plugins' => '整合插件', 'Internal PHP mail() function (default)' => '内部PHP邮件() 功能(默认)', 'Intro Text on Helpdesk Page' => '服务台页面的介绍文字', 'Invoice Log' => '发票日志', 'Invoices Per User' => '每个用户发票', 'Is Affiliate?' => '是分销?', 'Is Approved' => '被通过', 'It is required to setup a cron job to trigger backup generation' => '需要CRON工作来引发备份生成', 'Languages' => '语言', 'Last %s Customers' => '前%s顾客', 'Last existing subscription date of this product' => '此产品的上次订阅日期', 'Last login' => '上次登录', 'Length of admin password must be from %d to %d' => '管理员密码长度必须从%d到%d', 'Length of username must be from %d to %d' => '用户名长度必须从%d到%d', 'Lightbox Main Image' => '灯箱主图', 'Lightbox Thumbnail Image' => '灯箱缩略图片', 'Lines Proccessed:' => '处理的行:', 'Lines Skipped:' => '跳过的行:', 'Lines Success:' => '成功的行:', 'Link to reset your password was sent to your Email.' => '重置密码的链接发送到您的电子邮件', 'Lock' => '锁定', 'Locked Value' => '锁定值', 'Log Outgoing E-Mail Messages for ... days' => '保存发出的邮件消息……天', 'Log in' => '登录', 'Logged in as %s' => '作为%s登录', 'Login Page' => '登录页面', 'Logs' => '日志', 'Lookup' => '查询', 'Lost your password?' => '丢失您的密码?', 'Mail' => '邮件', 'Maintenance Mode' => '维修模式', 'Manage Product Upgrade Paths' => '管理产品升级途径', 'Manage Products' => '管理产品', 'Manually Added' => '已手动添加', 'Mark NOT Paid' => '标记未支付', 'Mark Paid' => '标记已支付', 'Membership' => '会员', 'Method' => '方法', 'Miscellaneous' => '其他', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => '多个订购标题 当用户订购多个产品 在支付系统显示下列 而不是产品名称', 'New Autoresponder' => '新自动应答', 'New Expiration E-Mail' => '新过期电子邮件', 'New Modules Available' => '可用的新模块', 'New Rewrite' => '新改写', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => '此客户无信用卡被存储。%s增加信用卡%s', 'No Invoices Found' => '发票未找到', 'No Updates Available' => '无可用更新', 'No more charges' => '无更多收费', 'No search name passed' => '搜索名称未通过', 'No upgrades to install' => '无升级安装', 'Not Approved Users' => '未通过用户', 'Not-SQL field (default)' => 'Not-SQL 栏(默认)', 'Numeric field' => '数字栏', 'Only admin can enable user as an affiliate' => '仅管理员可使用户成为分销商', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => '发出的电子邮件地址 用作从:发送电子邮件消息的地址 给顾客。如果空白,[管理员电子邮件地址] 被使用', 'Overwrite User if Exist User with Same Login' => '如果相同用户登录改写用户', 'PDF Invoice' => 'PDF格式的发票', 'Paid' => '已支付', 'Password Length' => '密码长度', 'Password must not be equal to username' => '密码不能等于用户名', 'Passwords must be the same' => '密码不能相同', 'Path to Folder' => '文件夹路径', 'Path/URL' => '路径/链接', 'Payment date' => '支付日期', 'Payment has been successfully refunded' => '支付已成功退还', 'Payout %d Details' => '取款%d详情', 'Payout Details' => '取款详情', 'Paysystem' => '支付系统', 'Permissions' => '允许', 'Please assign the following fields: ' => '请指定以下栏:', 'Please choose another field name. This name is already used' => '请选择其他栏名称。此名已经被使用。', 'Please enter valid e-mail address' => '请输入有效电子邮件地址', 'Please select date before today' => '请选择今天之前的日期', 'Please wait' => '请等待', 'Plugins' => '插件', 'Product Availability' => '产品可用性', 'Product Upgrades' => '产品升级', 'Products Per Invoice' => '每个发票产品', 'Protect Content' => '保护内容', 'Protection Method' => '保护方法', 'Quit Maintenance Mode' => '退出维修模式', 'RadioButtons' => '单选按钮', 'Rebill' => '再次支付', 'Rebill Second Price until cancelled' => '重复第二价格直到取消', 'Rebill Times This is the number of payments which will occur at the Second Price' => '重复支付次数 这是支付数字 将以第二价格发生', 'Rebuild Db' => '重建数据库', 'Receipt' => '收据', 'Recipients' => '收件人', 'Records Deleted Sucessfully' => '记录成功删除', 'Referrer' => '推荐人', 'Refund Payment' => '退款', 'Remember Login remember username/password in cookies' => '记住登陆 在COOKIES里记住用户名/密码', 'Remind Password to Admin' => '提醒管理员密码', 'Remind Password to Customer' => '提醒顾客密码', 'Remove Category' => '移除目录', 'Repeat Action Handling' => '重复动作处理', 'Reports' => '报告', 'Resend' => '再发送', 'Resend Signup E-Mail' => '重新发送注册邮件', 'Resource' => '资源', 'Restore' => '还原', 'Retreive Access Parameters if necessary' => '如有必要,检索访问参数', 'Return to Payouts List' => '返回取款列表', 'Root URL root script URL, usually %s' => '根链接 根脚本链接,通常%s', 'Root Url and License Keys' => '根链接和许可证密钥', 'Run Reports' => '运行报告', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'SMTP 主机名', 'SMTP Hostname is required if you have enabled SMTP method' => '如果您已经开启SMTP 方法,要求SMTP 主机名', 'SMTP Password' => 'SMTP 密码', 'SMTP Port' => 'SMTP 端口', 'SMTP Security' => 'SMTP 安全', 'SMTP Username' => 'SMTP 用户名', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (不能用于多选和复选框栏)', 'Save This Search' => '保存此搜索', 'Saved Credit Cards' => '保存的信用卡', 'Saved Search' => '保存的搜索', 'Second Period' => '第二时期', 'Second Price' => '第二价格', 'Second Price price that must be billed for second and the following periods of subscription' => '第二价格 在订阅的第二和以下时期必须支付的价格', 'Secure Root URL secure URL, usually %s' => '安全根链接 安全链接,通常%s', 'Select (Multiple Values)' => '选择(复数值)', 'Select (Single Value)' => '选择(单数值)', 'Select a plugin' => '选择插件', 'Selected for E-Mailing' => '选择发送电邮', 'Semicolon' => '分号', 'Send E-Mail Message' => '发送电子邮件消息', 'Send E-Mail Messages' => '发送电子邮件消息', 'Send New E-Mail' => '发送新电子邮件', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => '给顾客发送新消息通知 aMember将电邮通知给用户 每次管理员答复一条问题', 'Send Signup E-Mail once FIRST subscripton is completed' => '发送注册电子邮件 一旦第一次订阅完成', 'Send Test E-Mail' => '发送测试电子邮件', 'Sender' => '发送者', 'Sending Test E-Mail...' => '发送测试电子邮件中……', 'Sending e-mail (sent to %d from %d)' => '发送电子邮件(从%d发送到%d)', 'Setup/Configuration' => '安装/配置', 'Signup Form Configuration' => '注册表格配置', 'Signup Info' => '注册信息', 'Site is temporarily disabled for maintenance' => '网站维护暂时不可用', 'Size of input field' => '输入栏大小', 'Skip' => '跳过', 'Skip Line if Exist User with Same Login' => '如果相同用户登录跳线', 'Sort' => ' 排序', 'Sort Order' => '排序订购', 'Source' => '源', 'Space' => '空间', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => '开始日期计算 订阅开始日期计算规则 替代的最大日期将被选择 这个设置对重复订阅无影响', 'Started' => '已开始', 'Step %d of %d' => '%d 的步骤%d ', 'Stop Recurring' => '停止周期支付', 'String' => '字符串', 'Submitting...' => '提交中……', 'Subscription' => '订阅', 'Super Admin' => '超级管理员', 'Surcharge' => '附加费', 'Tabulation' => '制表', 'Template alternative template for signup page' => '模板 注册页面的替代模板', 'Terms Text automatically calculated if empty' => '条款文字 如果空白自动计算', 'Test E-Mail Settings' => '测试电子邮件设置', 'Text' => '文字', 'Text (unlimited length string/data)' => '文字(无限制长度字符串/数据)', 'TextArea' => '文字区域', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => '此电邮模板在给定的语言内是空白的。 按[Copy] 从默认语言[英语]复制模板 按[Skip]从头开始手工输入', 'This field is requred' => '此栏必填', 'Ticket#' => '问题号码', 'Time' => '时间', 'Title displayed to customers' => '标题 显示给客户', 'Total Paid' => '已支付总计', 'Total to Pay' => '支付总计', 'Trace' => '追踪', 'Traditional .htpasswd' => '传统。HT密码', 'URL must be specified without trailing slash' => '链接必须无结尾的斜线', 'URL must start from %s or %s' => '链接必须从%s或%s开始', 'Unlock' => '解锁', 'Unpack Upgrades' => '拆开升级', 'Update Error' => '更新错误', 'Update License Information' => '更新许可证信息', 'Update User if Exist User with Same Login' => '如果相同用户登录更新用户', 'Upgrade' => '升级', 'Upgrade Database' => '升级数据库', 'Upgrade Download Problem' => '升级下载问题', 'Upgrade Finished' => '升级完成', 'Upgrade From' => '升级表格', 'Upgrade To' => '升级至', 'Upload' => '上传', 'Use E-Mail Throttle Queue' => '使用电子邮件序列', 'Use External Cron' => '使用外部Cron', 'User Invoices' => '用户发票', 'User Pages Theme' => '用户页面主题', 'User currently has access to the following products' => '用户当前可访问下列产品', 'User had access to the following products' => '用户曾访问下列产品', 'User is not found in database' => '数据库中无此用户', 'Username or e-mail address' => '用户名或邮件地址', 'Users' => '用户', 'Value use % as wildcard mask' => '值 使用%作为通配符掩码', 'Values must not be equal' => '值不能相等', 'Version Info' => '版本信息', 'View' => '浏览', 'View Coupons' => '查看优惠券', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => '我们将提交请求到支付系统或您将被跳转到支付系统提交退款请求', 'Yes, assign category' => '是,分配目录', 'Yes, do not e-mail this customer for any reasons' => '是对,不要向客户发送电邮', 'Yes, locked' => '是的,被锁定', 'Yes, remove category' => '是,移除目录', 'You have currently choosed the following users for e-mail to:' => '您目前已选择下列用户来发送电子邮件:', 'You have generated %d demo products and %d demo customers' => '你生成%d演示产品和%d演示客户', 'Your Password enter your current password in order to edit admin record' => '您的密码 输入您当前密码 以便编辑管理员记录', '[From] and [To] billing plans must not be equal' => '[From] 和[To] 收费计划必须不能相等', 'access log table (used by admin only)' => '进入日志表格(仅管理员使用)', 'admin log table (used by admin only)' => '管理员日志表格(仅管理员使用)', 'change' => '更改', 'collapse details' => '合并详情', 'days after expiration' => '过期后几天', 'days before expiration' => '过期前几天', 'displaying records %d-%d from %d' => '从%d显示记录%d-%d', 'error_log table (used by admin only)' => '错误日志表格(仅管理员使用)', 'expand details' => '扩展详情', 'first paid at' => '首次支付于', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => '如果有代码,产品将被隐藏到购物车,需要代码来查看这些产品', 'if customer uses more than' => '如果客户使用多于', 'if user enters wrong password' => '如果用户输入错误密码', 'login, email or name' => '登录,电邮或名字', 'must be a number in format 99 or 99.99' => '必须是格式为99或99.99的数字', 'must be equal or greather than 0' => '必须等于或大于0', 'must be equal or greather than 0.0' => '必须等于或大于0.0', 'on expiration day' => '在过期日', 'open in new window' => '在新窗口打开', 'or %smake access free%s' => '或%s免费进入%s', 'put website offline, making it available for admins only' => '将网站离线,只对管理员可用', 'sending' => '发送中', 'sent successfully' => '成功发送', 'switch to show all records' => '切换到显示所有记录', 'switch to show only active records' => '切换到仅显示有效记录', 'times within' => '次数在', 'version' => '版本', ); PK\8 E1default/language/admin/de.phpnu[ '%d Tage nach Ablauf', '%d days before expiration' => '%d Tage vor Ablauf', '%d user(s) matches your search' => '%d Benutzer entspricht Ihrer Suche', '%d-th subscription day' => '%d-th Zeichnungstag', '%s Plugins' => '%s Plugins', '-- Please Select --' => '-- Bitte wählen --', '..th subscription day (starts from 2)' => '..ter Abonnement-Tag (beginnend bei 2)', 'API Keys' => 'API Keys', 'Access Method' => 'Zugriffsmethode', 'Account Sharing Prevention' => 'Sicherung gegen der Verteilung der Kontos', 'Account Verification' => 'Kontoüberprüfung', 'Add Chargeback' => 'Ausgleich hinzufügen', 'Add Invoice' => 'Rechnung hinzufügen', 'Add Payment' => 'Zahlung hinzufügen', 'Add Payment Manually' => 'Zahlung manuell hinzufügen', 'Add Refund' => 'Erstattung hinzufügen', 'Add Report to My Dashboard' => 'Bericht meiner Startseite hinzufügen', 'Add Signature to Response' => 'Antwort-Signatur hinzufügen', 'Add Subscription' => 'Abonnement hinzufügen', 'Add User Fields' => 'Felder hinzufügen', 'Add points to affiliate for each %s in payment' => 'Punkte zu Partner für jede %s in Zahlungen hinzufügen', 'Additional' => 'Zusätzlich', 'Address' => 'Adresse', 'Admin Accounts' => 'Admin-Accounts', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'Admin E-Mail-Adresse verwendet, um E-Mail-Benachrichtigungen an admin sendenund als Standard ausgehende IP-Adresse', 'Admin Email' => 'Administrator E-Mail', 'Admin Free Subscription Notifications to admin once free signup is completed' => 'Verwalten kostenloser Abonnement-Benachrichtigungen zum Verwalten, sobald kostenlose Registrierung abgeschlossen', 'Admin Log' => 'Administrator Protokoll', 'Admin Pages Theme' => 'Das Motiv der Administratorseiten', 'Admin Payment Notifications to admin once payment is received' => 'Admin Zahlungsbestätigung an Admin, sobald die Zahlung eingegangen ist', 'Admin Settings' => 'Die Einstellungen des Administrators', 'Admin notification' => 'Admin-Benachrichtigung', 'Admin username must be alphanumeric in small caps' => 'Benutzername des Administrators darf nur kleine, alphanumerische Zeichen enhalten', 'Administrator Login' => 'Administrator Anmeldung', 'Administrator has been removed, id [%d]' => 'Administrator wurde entfernt, ID [%d]', 'Advanced Settings' => 'Erweiterte Einstellungen', 'Affiliate Commission' => 'Kommission für die Partner', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Lebensdauer Partner-Cookie Anzahl Tage, um Cookies über die Partner zu speichern', 'Affiliate Information' => 'Partner-Information', 'Affiliate Registration E-Mail' => 'Partner-Registrierungs-E-Mail', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Partner-Auszahlungs-Tag wählen Sie einen Tag im Monat, an dem die Auszahlung erzeugt wird', 'Affiliates Signup Type' => 'Partner-Einschreibungstyp', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'Nachdem Sie Änderungen an durch htpasswd geschütze Orte gemacht haben, führen Sie bitte [Nützliche Tools -> DB erneuern] aus, um die htpasswd-Datei zu aktualisieren', 'All Subscription Period' => 'Alle Abonnement-Zeiträume', 'All new users automatically become affiliates' => 'Alle neue Benutzer werden automatisch Partner', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Erlaubt E-Mails Count Angabe der E-Mails innerhalb der oben erlaubt', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Erlaubt E-Mails für den Zeitraum wählen, ob Ihr Gastgeber ist die Begrenzung von E-Mails pro Tag oder pro Stunde', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Errinern Sie sich immer Wenn ja, fragen Sie nicht den Kunden - errinern Sie sich immer', 'Amazon SES' => 'Amazon SES', 'Amazon SES Access Id' => 'Amazon SES Zugriffs-ID', 'Amazon SES Secret Key' => 'Amazon SES Sicherheitsschlüssel', 'American Date Format' => 'Amerikanisches Datumsformat', 'Apply Tax?' => 'Steuer einbeziehen?', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'Wiederholt anwendbar? Coupon bei wiederholter Rechnungsstellung anwendbar?', 'Approve' => 'Freigeben', 'Assign Category' => 'Kategorie bestimmen', 'At least one billing plan must be added' => 'Mindestens ein Rechnungsstellungsplan muss hinzugefügt werden', 'Available' => 'Verfügbar', 'Available Upgrades' => 'Verfügbare Upgrades', 'Available for users from groups' => 'Verfügbar für Gruppenbenutzer', 'Back to Dashboard' => 'Zurück zur Startseite', 'Backup' => 'Datensicherung', 'Banner' => 'Banner', 'Banners' => 'Banner', 'Basket HTML Code' => 'Korb HTML Code', 'Billing' => 'Fakturierung ', 'Blob (unlimited length binary data)' => 'Broßes Binär-Objekt (unbegrenzter Länge der Binärdaten)', 'Blocking IP/E-Mail' => 'Sperrung der IP/E-Mail', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Kurz nicht für geplante Wartungsarbeiten verfügbar. Überprüfen Sie zurück in einer Minute.', 'Browse' => 'Durchsuchen', 'Browse Found Users' => 'Gefundene Benutzer durchsuchen', 'Browse Users' => 'Benutzer durchsuchen', 'Bruteforce Protection' => 'Brute-force Sicherung', 'Build Demo' => 'Demo erstellen', 'Building demo records' => 'Demo-Datensätze erstellen', 'Button/Link HTML Code' => 'Schaltflächen/Link HTML Code', 'Can not find user with such username' => 'Benutzer mit diesem Benutzernamen konnte nicht gefunden werden', 'Can not find user with such username or email' => 'Kann nicht Benutzer mit solchen Benutzernamen oder E-Mail finden ', 'Can\'t be changed because your server have suhosin extension enabled' => 'Kann nicht geändert werden, da suhosin-Erweiterung auf Server aktiviert', 'Cancellations' => 'Abbestellungen', 'Change Configuration Settings' => 'Konfigurationseinstellungen ändern', 'Change Paysystem' => 'Auszahlungssystem ändern', 'Charge Second Price Once' => 'Zweiten Preis einmal in Rechnung stellen', 'Charge Second Price x Times' => 'Zweiter Preis X mal in Rechnung stellen', 'Check for beta version' => 'Nach Beta-Version suchen', 'CheckBoxes' => 'Kontrollboxen', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => 'Wählen Sie %1$sDatei%2$s > %1$sSpeichern unter%2$s.', 'Choose Products and/or Product Categories that allows access' => 'Wählen Sie Produkte und / oder Produktkategorien, dass den Zugang erlaubt', 'Choose Upgrades to Install' => 'Wählen Sie Upgrades zu installieren', 'Choose action when locked %s used by customer during signup' => 'Wählen Sie eine Aktion, wenn gesperrte %s bei der Anmeldung vom Kunden verwendet werden', 'Clean up v4 Database' => 'v4-Datenbank bereinigen', 'Cleaning up' => 'Aufräumen', 'Cleanup' => 'Säuberungsaktion', 'Clear' => 'Leeren', 'Clear Access Log' => 'Klares Zugriffsprotokoll', 'Clear Incomplete Invoices' => 'Bereinige unfertige Rechnungen', 'Click to Expand' => 'Klicken Sie zum Vergrößern', 'Code Length generated coupon code length between 4 and 32' => 'Code-Länge Länge des erzeugten Couponcodes zwischen 4 und 32', 'Collapse Menu' => 'Menü einklappen', 'Comma' => 'Komma', 'Commission % of commission received by referred affiliate' => 'Kommission % der Kommission vom zugehörigen Partner erhalten', 'Commission earned' => 'Kommission verdient', 'Commission for First Payment calculated for first payment in each invoice' => 'Kommission für die erste Zahlung berechnet für die erste Zahlung in jeder Rechnung', 'Commission for Free Signup calculated for first customer invoice only' => 'Kommission für Kostenlose Anmeldung wird nur für die ersten Kunden Rechnung berechnet', 'Commission for Rebills' => 'Kommission für erneuten Rechnungen', 'Conditions' => 'Konditionen', 'Configured License Keys' => 'Eingetragene Lizenzschlüssel', 'Copy' => 'Kopieren', 'Copy Upgrades' => 'Kopieren Sie die Upgrades', 'Copy from another language' => 'Kopie aus einer anderen Sprache', 'Core' => 'Der Kern', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Konnte nicht Datei herunterladen [%s]. Fehler %s. Bitte %sversuchen Sie es erneut%s später.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'Upgrade-Übersicht konnte nicht vom Server geladen werden. %sErneut versuchen%s', 'Could not fetch upgrades list. Connection error [%s]' => 'Upgrades Liste Konnte nicht abgerufen werden.Verbindungsfehler[%s]', 'Coupons' => 'Coupons', 'Coupons Batches' => 'Haufen von Coupons', 'Coupons Count how many coupons need to be generated' => 'Anzahl Coupons wie viele Coupons müssen erzeugt werden', 'Create Folder' => 'Ordner erstellen', 'Create Session Key' => 'Einmalschlüssel erstellen', 'Create ticket as' => 'Neues Ticket erstellen als', 'Credit' => 'Haben', 'Custom Commission Rules added' => 'Benutzerdefinierte Kommissions-Regeln hinzugefügt', 'Custom HTML' => 'Eigenes HTML', 'Custom Signup Form Title keep empty to use default title' => 'Benutzerdefinierte Anmeldeformular Titel halten leer zum ursprünglichen Titel verwenden', 'Customer' => 'Kunde', 'Customize Dashboard' => 'Startseite personalisieren', 'Daily' => 'Täglich', 'Date Time' => 'Uhrzeit', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Datum zur Löschung alle Datensätze vor diesem Datum werden aus ausgewählten Tabellen entfernt werden', 'Dates date range when coupon can be used' => 'Datum in welchem Zeitraum kann der Coupon benutzt werden', 'Dates can be in the folowing formats' => 'Datumseinträge können folgende Formate haben', 'Days to Send' => 'Versanddauer', 'Debit' => 'Soll', 'Default - user clicks a link to become affiliate' => 'Standardeinstellung - Der Benutzer klickt auf einen Link, um Partner werden', 'Default Billing Plan' => 'Standard Fakturierungsplan', 'Default Commission' => 'Standard Kommission', 'Default Locale' => 'Standard-Gebietsschema', 'Default Signup' => 'Standard Anmeldung', 'Default for Members' => 'Standard für Mitglieder', 'Default value for field (that is default value for inputs, not SQL DEFAULT)' => 'Standardwert für Feld (ist Standardwert für Eingabefelder, kein SQL-Standard)', 'Delete Old Records' => 'Löschen Sie alte Datensätze', 'Delete Saved Search?' => 'Gespeicherte Suche löschen?', 'Delete payment and access record' => 'Zahlung und Zugriffsdatensatz löschen', 'Delimiter' => 'Trennzeichen', 'Demo History' => 'Die Geschichte des Demo', 'Description displayed to visitors on order page below the title' => 'Beschreibung angezeigt für Besucher auf der Bestellungsseite unter dem Tite', 'Details' => 'Unterlagen', 'Die and show ugly error message' => 'Abbrechen und hässliche Fehlermeldung anzeigen ', 'Digits and latin letters only please' => 'Nur Ziffern und lateinische Zeichen bitte', 'Disable auto-locking for this customer' => 'Deaktivieren Sie die automatische Verriegelung für diesen Kunden', 'Disallow new Signups by %s' => 'Neue Anmeldungen von %s nicht erlauben', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'Bestellung dieses Produkts Nicht gestatten, wenn Benutzer hat wenn der Benutzer Aufträge dieses Abonnement, wird es überprüft werden dass er keine jede der folgenden Abos', 'Display Language Choice' => 'Die Sprachen Wahl zeigen', 'Display Mode' => 'Anzeigemodus', 'Display error message' => 'Fehlermeldung anzeigen', 'Do not generate products use existing products for demo records' => 'Produkte nicht generieren Bestehende Produkte für Demo-Datensätze verwenden', 'Do you really want to change Rebill Date for this invoice?' => 'Wollen Sie wirklich das Mahnungsdatum ändern?', 'Do you really want to refund payment' => 'Wollen Sie wirklich die Zahlung zurückerstatten', 'Do you really want to stop this subscription?' => 'Wollen Sie wirklich dieses Abonnement stoppen?', 'Documentation' => 'Dokumentation', 'Download Upgrades' => 'Upgrades herunterladen', 'Duration:' => 'Dauer:', 'E-Mail Address to Send to' => 'E-Mail-Adresse zu senden', 'E-Mail Backup Address' => 'E-Mail Sicherungs Adresse', 'E-Mail Commission to Admin' => 'E-mail Kommission für den Administrator ', 'E-Mail Commission to Affiliate' => 'E-mail Kommission für den Partner', 'E-Mail Database Backup' => 'E-Mail Absicherungs der Datenbank', 'E-Mail Queue' => 'E-Mail Reihe', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'E-Mail Absender Name verwendet werden, um des Namens des Absenders in ausgehenden E-Mails angezeigt', 'E-Mail Sending' => 'E-Mail versenden', 'E-Mail System Configuration' => 'E-Mail System Konfiguration', 'E-Mail Type' => 'E-Mail-Typ', 'E-Mail Users' => 'E-Mail-Benutzer', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'E-Mail wurde erfolgreich an %s Kunden gesendet. E-Mail Batch-ID %s', 'E-Mail sending started' => 'Die Sendung des E-Mail hat begonnen', 'E-Mails History' => 'EMails Geschichte', 'E-Mails by Admin Request' => 'E-Mails von Admin gefordert', 'E-Mails by User Request' => 'E-Mails von Benutzer gefordert', 'Earn points for %s in payment' => 'Verdiene Punkte für %s in Zahlungen', 'Edit Custom Commission Rules' => 'Benutzerdefinierte Kommissions Regeln editieren', 'Edit Groups' => 'Gruppen bearbeiten', 'Edit Messages' => 'Nachrichten bearbeiten', 'Email Backup Frequency' => 'E-mail Sicherungs Häufigkeit ', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'E-Mail versenden Methode Bitte ändern Sie NICHT, wenn E-Mails aus aMember Werke', 'Email Sent' => 'E-Mail gesendet', 'Email address is required field.' => 'E-Mail-Adresse ist erforderlich.', 'Enable plugins if necessary' => 'Plugins aktivieren falls nötig', 'Enter Maintenance Mode' => 'Starten Sie die Aufrechterhaltung', 'Enter admin password for confirmation' => 'Geben Sie das Admin-Passwort zur Bestätigung ein', 'Error Log' => 'Fehlerprotokoll', 'Error/Debug Log' => 'Fehler/Fehler beseitigen', 'Errors' => 'Fehler ', 'Errors:' => 'Fehler:', 'European Date Format' => 'Europäisches Datumsformat', 'Every %s' => 'Jeder %s', 'Exchange Rate' => 'Wechselkurs', 'Exchange Rate enter cost of 1 (one) %s' => 'Wechselkurs Geben Sie Kosten für 1 (einen) %s', 'Field Name' => 'Feldname', 'Field Title' => 'Feld Titel', 'Field Values' => 'Feldwerte', 'File (max filesize %s)' => 'Datei (max. Dateigröße %s)', 'File is required' => 'Die Datei ist erforderlich', 'Filter by Category' => 'Nach Kategorie filtern', 'Filter by String' => 'Filtern nach Reihe', 'Filter by name or description' => 'Nach Name oder Beschreibung filtern', 'Filter by string or by invoice#/member#' => 'Filtern nach Reihe oder per Rechnung # / Mitglied #', 'First Period' => 'Die erste Periode', 'First Price' => 'Erster Preis', 'First Price price of first period of subscription' => 'Erster Preis Preis der ersten Periode des Bezugsrechts', 'First Tax' => 'Anfangssteuer', 'First Total' => 'Anfangssumme', 'First and Last Name' => 'Vor-und Nachname', 'First available protected url' => 'Erste verfügbare geschützte URL', 'First visited' => 'Zuerst besucht', 'Fix aMember Pro License Key' => 'aMember Pro Lizenzschlüssel reparieren', 'Fixed Url' => 'Feste URL', 'Fixed date' => 'Termin', 'FlowPlayer License Key you may get your key in %smembers area%s' => 'FlowPlayer-Lizenzschlüssel Sie erhalten Ihren Schlüssel im %sMitgliederbereich%s', 'Folder URL' => 'Ordner-URL', 'Form Type' => 'Formulartyp', 'Forms Editor' => 'Formular Editor', 'Future' => 'Zukunft', 'General' => 'Allgemein', 'General Link' => 'Allgemeiner Link', 'General Settings' => 'Haupteinstellungen', 'Generate' => 'Generieren', 'Generate Basket HTML' => 'Erzeuge HTML für Warenkorb', 'Generate Button HTML' => 'Erzeuge HTML für Schaltfläche', 'Generate Payout Manually' => 'Auszahlung manuell erzeugen', 'Generate Report' => 'Bericht generieren', 'Generated' => 'Erzeugt', 'Generation of demo data was terminated while processing. Not all records were created.' => 'Generierung von Demo-Daten wurde während der Verarbeitung beendet. Nicht alle Datensätze wurden erstellt.', 'Get Available Upgrades List' => 'Bekommen Sie die verfügbare Upgrades Liste', 'Get New Password' => 'Einen neuen Passwort bekommen', 'Global' => 'Global', 'Graph Bar' => 'Diagramm', 'Graph Line' => 'Diagrammlinie', 'Help & Support' => 'Hilfe & Support', 'Hostname' => 'Hostname', 'Hour' => 'Stunde', 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database' => 'Ich verstehe, dass das Upgrade von mir angepasste PHP-Dateien und Templates überschreiben könnte, und habe bereits eine Sicherung der aMember Pro-Ordner und Datenbank erstellt.', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'WICHTIGER HINWEIS: Dies wirdn nicht Inhalte schutzen. Wenn jemand die Url des Links kennt, wird er in der Lage sein es ohne ein Problem zu öffnen. Dies kontrolliert, welche zusätzliche Links werden die Benutzer nach dem Login auf Mitglied-Bereich sehen.', 'IP' => 'IP', 'IP within' => 'IP im', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Wenn Sie von einen Kreditkarten-Zahlungsabwickler bewegen, können Sie diese Seite benutzen, um ihren bestehendes Abonnement von einen Kreditkarten-Zahlungsabwickler zu einem anderen zu wechseln. Es ist nur möglich, wenn vollständige Kreditkartennummer Informationen über ein Mitglied Seite gespeichert ist.', 'Image' => 'Bild', 'Import Finished' => 'Import abgeschlossen', 'Import Users' => 'Benutzer importieren', 'Important Notice:' => 'Wichtiger Hinweis:', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'Im Dialog zum Exportieren von Textdateien wählen Sie die benötigten Optionen aus und klicken %1$sOK%2$s.', 'In the File name box, type a name for the file.' => 'Im Dateinamen-Feld geben Sie den Namen der Datei ein.', 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.' => 'Wählen Sie %1$sText CSV%2$s als Dateitypen und klicken %1$sSpeichern%2$s. Eine Mitteilung erscheint, klicken Sie %1$sDerzeitiges Format beibehalten%2$s.', 'Insert' => 'Einfügen', 'Install Updates' => 'Installieren Sie Updates', 'Integer field (only numbers)' => 'Integer-Feld (nur Zahlen)', 'Integration plugins' => 'Integration-Plugins', 'Internal PHP mail() function (default)' => 'Interne PHP mail ()-Funktion (Standard)', 'Intro Text on Helpdesk Page' => 'Intro Text auf Helpdesk Seite', 'Invoice Log' => 'Rechnungs Log', 'Invoices' => 'Rechnungen', 'Invoices Per User' => 'Rechnungen pro Benutzer', 'Is Affiliate?' => 'Ist Partner?', 'Is Approved' => 'Ist zugelassen', 'Is Disabled' => 'Ist deaktiviert', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'Ist deaktiviert? deaktiviere Produktsortierung, entferne sie von Anmeldung und Erneuerungsformularen', 'Is Unsubscribed? if enabled, this will unsubscribe the customer from: * messages that you send from aMember Cp, * autoresponder messages, * subscription expiration notices' => 'Ist abbgestellt? wenn dieser aktiviert ist, wird diese abbestellen den Kunden aus: * Nachrichten, die Sie aus aMember Cp senden, * Autoresponder-Nachrichten, * Abonnementablauf Hinweise', 'It is required to setup a cron job to trigger backup generation' => 'Es ist erforderlich einen Cron Job zu erstellen, um die Sicherungs Generation auszulösen', 'Items' => 'Artikel', 'JavaScript Code' => 'JavaScript-Code', 'Key' => 'Schlüssel', 'Key must be 20 chars or longer' => 'Schlüssel muss 20 Zeichen oder länger sein', 'Languages' => 'Sprachen', 'Last %s Customers' => 'Letzte %s Kunden', 'Last %s Helpdesk Messages' => 'Letzte %s Helpdesk-Nachrichten', 'Last %s Payments' => 'Letzte %s Zahlungen', 'Last Payments List' => 'Liste letzter Zahlungen', 'Last Users List' => 'Liste letzter Benutzer', 'Last available protected url' => 'Letzte geschützte verfügbare URL', 'Last existing subscription date of this product' => 'Letztes bestehendes Abonnement Datum dieses Produkts', 'Last expiration date in the renewal group' => 'Letztes Ablaufdatum der Erneuerungs-Gruppe', 'Last login' => 'Letzte Anmeldung', 'Length of admin password must be from %d to %d' => 'Die Länge des Administrator-Passworts muss zwischen %d und %d liegen', 'Length of username must be from %d to %d' => 'Die Länge des Benutzernames muss zwischen %d und %d liegen', 'Light Boxes' => 'Lightboxen', 'Lightbox Main Image' => 'Das Hauptbild des Leuchtkasten', 'Lightbox Thumbnail Image' => 'Minibild des Leuchtkasten', 'Limit Downloads Count' => 'Download-Anzahl begrenzen', 'Lines Proccessed:' => 'Zeilen bearbeitet:', 'Lines Skipped:' => 'Zeilen übersprungen:', 'Lines Success:' => 'Linien Erfolg:', 'Link to reset your password was sent to your Email.' => 'Link zum Zurücksetzen des Passworts wurde an Ihre Mailadresse gesendet.', 'Lock' => 'Sperren', 'Locked Value' => 'Festgeschriebener Wert', 'Log Outgoing E-Mail Messages for ... days' => 'Login für ausgehende E-Mail-Nachrichten für ... Tage', 'Log in' => 'Anmelden', 'Logged in as %s' => 'Angemeldet als %s', 'Login Page' => 'Login Seite', 'Logs' => 'Logs', 'Logs: Access' => 'Logs: Zugriff', 'Logs: Admin Log' => 'Logs: Admin-Log', 'Logs: Errors' => 'Logs: Fehler', 'Logs: Invoice' => 'Logs: Rechnung', 'Logs: Mail Queue' => 'Logs: Mail-Warteschlange', 'Lookup' => 'Nachschlagen', 'Lost your password?' => 'Passwort vergessen?', 'Mail' => 'Mail', 'Maintenance Mode' => 'Wartungsarbeiten ', 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s' => 'Wartungsmodus ist derzeit aktiviert. Nur eingeloggte Administratoren, wie Sie können darauf zugreifen. %sDeaktivieren%s', 'Manage Product Upgrade Paths' => 'Verwalten Sie die Produkt-Upgrade-Pfaden', 'Manage Products' => 'Produkte verwalten', 'Manually Added' => 'Manuell hinzugefügte', 'Mark NOT Paid' => 'Als unbezahlt markieren', 'Mark Paid' => 'Als bezahlt markieren', 'Mass Subscribe' => 'Massen-Abonnement', 'Membership' => 'Mitgliedschaft', 'Membership Info Page' => 'Mitgliedschafts-Info-Seite', 'Merge' => 'Zusammenführen', 'Method' => 'Die Methode', 'Miscellaneous' => 'Sonstiges', 'Monthly' => 'Monatlich', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Mehrere Sortierung: Titel wenn der Benutzer mehrere Produkte bestellt, zeigen das folgende auf Zahlungssystem anstelle von Produktnamen', 'Name of Preset' => 'Vorlage', 'Need points to get %s discount' => 'Sie benötigen Punkte, um %s Ermäßigung zu bekommen', 'New Autoresponder' => 'Neuer automatischer Beantworter', 'New Expiration E-Mail' => 'Neue Verfall Email', 'New Modules Available' => 'Neue Module verfügbar', 'New Rewrite' => 'Neue Umformulierung', 'New Ticket Autoresponder to Customer aMember will email an autoresponder to user each time user create new ticket' => 'Auto-Responder für neue Tickets an Kunden aMember wird dem Benutzer eine automatische Antwort schicken, wenn dieser ein neues Ticket erstellt', 'New password has been e-mailed to your e-mail address' => 'Das neue Passwort wurde an Ihre E-Mail-Adresse geschickt', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'es existieren keine für diesen Kunden gespeicherte Kreditkarten %s Fügen Sie eine Kreditkarte zu%s', 'No Invoices Found' => 'Keine Rechnungen gefunden', 'No Tax' => 'Steuerfrei', 'No Updates Available' => 'Keine Updates verfügbar', 'No more charges' => 'Keine Gebühren', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'Keine Zeile in dieser Datei gefunden. Die Datei scheint leer zu sein. Sie können zurückkehren und eine andere Datei versuchen.', 'No search name passed' => 'Keinne Suche Namen übergeben', 'No upgrades to install' => 'Keine Upgrades zu installieren', 'Not Approved' => 'Nicht freigegeben', 'Not Approved Users' => 'Nicht autorisierte Benutzer', 'Not Confirmed Users' => 'Nicht-bestätigte Benutzer', 'Not-SQL field (default)' => 'Nicht-SQL-Feld (vorgegeben)', 'Number of Payments to display' => 'Anzahl anzuzeigender Zahlungen', 'Number of Users to display' => 'Anzahl anzuzeigender Benutzer', 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.' => 'Anzahl Rechnungen, die Freigabe benötigen: %d. %sHier klicken%s, um Rechnungen anzuzeigen.', 'Number of users who require approval: %d. %sClick here%s to review these users.' => 'Anzahl Benutzer, die Freigabe benötigen: %d. %sHier klicken%s, um Benutzer anzuzeigen.', 'Numeric field' => 'Numerisches Feld', 'OTO - Offer to purchase additional product (with optional discount)' => 'OTO - Angebot weitere Produkte zu kaufen (mit optionaler Ermäßigung)', 'One field can be assigned to one column only, you assigned following fields to several columns: ' => 'Ein Feld kann nur einer Spalte zugeordnet werden, Sie orndeten folgende Felder verschiedenen Spalten zu:', 'One field can be assigned to one column only.' => 'Ein Feld kann nur einer Spalte zugeordnet werden.', 'Only admin can enable user as an affiliate' => 'Nur der Administrator kann den Benutzer zum Partner machen', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Ausgehende E-Mail-Adresse verwendet als Von:-Adresse für das Versenden von E-Mail-Nachrichten zu den Kunden. Wenn leer, wird [Admin E-Mail-Adresse] verwendet', 'Overwrite User if Exist User with Same Login' => 'Überschreiben des Benutzers, wenn ein Benutzer mit gleichen Anmeldung existiert', 'PDF Invoice' => 'Rechnung im PDF-Format', 'Paid' => 'Bezahlt', 'Password Length' => 'Passwort Länge', 'Password changed' => 'Passwort geändert', 'Password must not be equal to username' => 'Passwort kann nicht identisch mit dem Benutzernamen sein', 'Passwords must be the same' => 'Passwörter müssen gleich sein', 'Path to Folder' => 'Pfad zum Ordner', 'Path/URL' => 'Pfad/URL', 'Payment Receipt' => 'Zahlungsbestätigung', 'Payment date' => 'Fälligkeit', 'Payment has been successfully refunded' => 'Die Zahlung wurde erfolgreich erstattet', 'Payment#/Receipt#' => 'Zahlungs-/Rechnungs-Nr.', 'Payout %d Details' => 'Details Auszahlung %d', 'Payout Details' => 'Auszahlungs-Details', 'Paysystem' => 'Zahlungssystem', 'Pending Invoice Notification Rules' => 'Benachrichtigungs-Regeln ausstehender Rechnungen', 'Permissions' => 'Erlaubnisse', 'Please assign the following fields: ' => 'Bitte bestimmen Sie die folgende Bereiche:', 'Please choose another field name. This name is already used' => 'Bitte wählen Sie ein anderes Feldaname. Dieser Name wird bereits verwendet', 'Please enter valid e-mail address' => 'Bitte geben Sie eine gültige E-Mail-Adresse ein', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'Bitte geben Sie Benutzernamen oder E-Mail- Adresse ein. Sie werden einen Link zum erzeugen eines neuen Passworts per E-Mail erhalten', 'Please note: By default, aMember does not change users password and login values to a generated value in cases where an existing email address is found. You may decide to update an existing record, in the next step of the import process, where a matching email or username already exists.' => 'Bitte beachten: Standardmäßig ändert aMember Benutzerpasswörter und Login-Werte nicht zu einem generierten Wert, wenn eine vorhandene Mailadresse gefunden wurde. Sie sollten im nächsten Schritt des Import-Vorgangs den Datensatz aktualisieren, bei dem die übereinstimmende Mailadresse oder Benutzname bereits existiert.', 'Please run %sRebuild Db%s to update status for imported customers' => 'Bitte führen Sie %sDB erneuern%s aus, um den Status importierter Nutzer zu aktualisieren', 'Please select date before today' => 'Bitte wählen Sie ein Datum vor Heute', 'Please specify new rebill date: ' => 'Bitte neues Mahnungsdatum angeben:', 'Please wait' => 'Bitte warten', 'Plugins' => 'Plugins', 'Product Availability' => 'Produkt-Verfügbarkeit', 'Product Category' => 'Produktkategorie', 'Product Upgrades' => 'Product Upgrades', 'Products Per Invoice' => 'Artikel pro Rechnung', 'Protect Content' => 'Inhalt schützen', 'Protection Method' => 'Schutz-Methode', 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty' => 'Menge Standard - 1, Änderung normalerweise nicht notwendig Einstiegs- und Folgepreis sind Gesamtsumme der angegebenen Menge', 'Quit Maintenance Mode' => 'Beenden der Aufrechterhaltung', 'REST API Documentation' => 'REST API Dokumentation', 'RadioButtons' => 'Radio Knöpfe', 'Rebill' => 'Erneute Rechnung', 'Rebill Second Price until cancelled' => 'Erneute Zahlung zweiter Preis bis auf Widerruf', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Zeit der erneuten Zahlungen Dies ist die Anzahl der Zahlungen, die auf dem zweiten Preis auftreten wird', 'Rebuild Db' => 'Umbau Db', 'Receipt' => 'Empfang', 'Receipt#' => 'Belegnummer', 'Recipients' => 'Empfänger ', 'Records Deleted Sucessfully' => 'Datensätze erfolgreich gelöscht', 'Redirect URL' => 'Redirect URL', 'Referrer' => 'Der Referrer', 'Refund Payment' => 'Erstattung von Zahlungen', 'Remember Login remember username/password in cookies' => ' Login Speichern Benutzername / Passwort in Cookies speichern', 'Remind Password to Admin' => 'Passwort an Admin errinern', 'Remind Password to Customer' => 'Passwort an Kunden errinern', 'Remove Category' => 'Kategorie entfernen', 'Remove From Dashboard' => 'Von Startseite entfernen', 'Repeat Action Handling' => 'Wiederholen Sie die Aktion Bearbeitung', 'Replace Product' => 'Produkt ersetzen', 'Report Bugs' => 'Fehler melden', 'Reports' => 'Berichte', 'Reseller Packages' => 'Reseller-Pakete', 'Resend' => 'Zurücksenden', 'Resend Email' => 'E-Mail erneut senden', 'Resend Signup E-Mail' => 'Anmeldungs E-Mail wieder senden', 'Resource' => 'Quelle', 'Restore' => 'Wiederherstellen', 'Retreive Access Parameters if necessary' => 'Rufen sie die Zugangs Eckdaten ab', 'Return to Payouts List' => 'Zur Auszahlungs-Liste zurückkehren', 'Root URL root script URL, usually %s' => 'Stamm-URL root Skript-URL, in der Regel %s', 'Root Url and License Keys' => 'Stamm-URL und Erlaubnisschlüssel', 'Run Reports' => 'Berichte zeigen', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'SMTP Hostname', 'SMTP Hostname is required if you have enabled SMTP method' => 'SMTP Hostname ist erforderlich, wenn Sie SMTP-Methode aktiviert habt', 'SMTP Password' => 'SMTP Passwort', 'SMTP Port' => 'SMTP Port', 'SMTP Security' => 'SMTP Sicherung', 'SMTP Username' => 'SMTP Benutzername', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (konnte nicht für Multi-Select und Checkbox-Felder verwendet werden)', 'SQL Date Format' => 'SQL-Datumsformat', 'Sales Statistic' => 'Verkaufsstatistik', 'Save This Search' => 'Diese Suche speichern', 'Saved Credit Cards' => 'Gespeicherte Kreditkarten', 'Saved Reports' => 'Gespeicherte Berichte', 'Saved Search' => 'Gespeicherte Suche', 'Second Period' => 'Zweite Periode', 'Second Price' => 'Zweiter Preis', 'Second Price price that must be billed for second and the following periods of subscription' => 'Zweiter Preis Preis, der für die zweite und in Rechnung gestellt werden mussdie folgenden Zeiträume von Bezugsrechten', 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form' => 'Sicherheitscode sollte Formular nicht als Standard gewählt, wird dieser Code (innerhalb der URL) notwendig, um das Formular zu öffnen', 'Secure Root URL secure URL, usually %s' => 'Sichere Stamm-URL sichere URL, in der Regel %s', 'Select (Multiple Values)' => 'Wählen Sie (Mehrwertig )', 'Select (Single Value)' => 'Wählen Sie (Einzelwert )', 'Select a plugin' => 'Wählen Sie ein Plugin', 'Select option' => 'Option wählen', 'Selected for E-Mailing' => 'Ausgewählt für E-Mailing', 'Semicolon' => 'Semikolon', 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member' => 'Kündigungsbestätigung an Admin', 'Send E-Mail Message' => 'Senden Sie E-Mail Nachricht', 'Send E-Mail Messages' => 'Senden Sie E-Mail-Nachrichten', 'Send E-Mail if customer has subscription (required)' => 'Sende E-Mail, wenn Kunde Abonnement hat (erforderlich)', 'Send E-Mail only if customer has no subscription (optional)' => 'Sende E-Mail nur, wenn Kunde kein Abonnement hat (erforderlich)', 'Send New E-Mail' => 'Senden Sie eine Neue E-Mail', 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket' => 'Sende Benachrichtigung über neue Nachrichten an Admin aMember schickt Benachrichtigungs-E-Mail an Admin immer wenn Benutzer auf Ticket antwortet', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Senden Sie neue Nachrichten an den Kunden aMember wird eine Benachrichtigung an Benutzer senden E-Mailjedes Mal reagiert der Sdmnistrator auf einen Benutzer-Ticket', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'Registrierungs-Mail wenn Benutzer Anmeldeforumalr ausgefüllt hat (vor Zahlung)', 'Send Registration E-Mail to this user' => 'Registrierungsmail an Benutzer senden', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Senden Anmelden per E-Mail Sobald das erste Abonnement abgeschlossen ist', 'Send Test E-Mail' => 'Senden Sie die Test EMail', 'Send message' => 'Nachricht senden', 'Send reports to my email' => 'Sende Berichte an meine E-Mail', 'Sender' => 'Absender', 'Sending Test E-Mail...' => 'Senden einer Test-E-Mail ...', 'Sending e-mail (sent to %d from %d)' => 'Senden von E-Mail (an %d von %d)', 'Session Storage' => 'Sitzungsspeicher', 'Setup/Configuration' => 'Setup / Konfiguration', 'Shopping Cart Settings' => 'Warenkorb-Einstellungen', 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation' => 'Signatur Sie können die folgenden Platzhalter benutzen: $name_f%, %name_l%; Diese wird zum Vor- und Nachnamen des zugehörigen Admins hinzugefügt', 'Signup Form Configuration' => 'Anmeldeformular Konfiguration', 'Signup Info' => 'Anmeldungs Information', 'Signup Messages' => 'Anmeldenachrichten', 'Site is temporarily disabled for maintenance' => 'Seite ist vorübergehend für Wartungsarbeiten deaktiviert', 'Size' => 'Größe', 'Size of input field' => 'Größe des Eingabefeldes', 'Skip' => 'Ausslasen', 'Skip Line if Exist User with Same Login' => 'Zeilensprung, wenn ein Benutzer mit gleichen Anmeldung existiert', 'Sort' => 'Sortieren', 'Sort Order' => 'Sortierung', 'Source' => 'Quelle', 'Space' => 'Leerzeichen', 'Standard PHP Sessions' => 'Standard-PHP-Sitzungen', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Startdatum Berechnung Regeln für die Anmeldung Startdatumsberechnung. MAX Datum wird aus Alternativen gewählt. Diese Einstellung hat keine Wirkung für wiederkehrende Abonnements Produktverfügbarkeit', 'Start and Expiration Dates' => 'Anfangs- und Enddaten', 'Started' => 'Angefangen', 'Step %d of %d' => 'Schritt %d von %d', 'Stop Recurring' => 'Wiederkehrung stoppen', 'String' => 'Reihung', 'Subaffiliate' => 'Subpartner', 'Submitting...' => 'Einreichen ...', 'Subscription' => 'Abonnement', 'Super Admin' => 'Super-Admin', 'Surcharge' => 'Der Aufpreis', 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead' => 'Aufpreis wird zusätzlich angerechnet, wenn Kunde [Von]->[Nach] Plan wechselt aMember wird nicht den Einstiegspreis bei der Aufwertung erheben, nutzen Sie den Aufpreis', 'Table' => 'Tabelle', 'Tabulation' => 'Tabellierung ', 'Template alternative template for signup page' => 'Vorlage alternative Vorlage für Anmeldeseite', 'Terms Text automatically calculated if empty' => 'AGB Text automatisch berechnet, wenn leer', 'Test E-Mail Settings' => 'Test-E-Mail-Einstellungen', 'Text' => 'Text', 'Text (unlimited length string/data)' => 'Text (unbegrenzter Länge der Reihung / Daten)', 'Text Links' => 'Textlinks', 'TextArea' => 'Der Text Bereich', 'The password is entered incorrectly' => 'Das eingegebene Passwort ist falsch', 'This code can be inserted into any HTML page on your website or into any WordPress post or page' => 'dieser Code kann in jede HTML-Seite auf Ihrer Website, jeden WordPress-Beitrag oder jede WordPress-Seite eingefügt werden', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Diese E-Mail Mustervorlage ist in bestimmten Sprache leer. Drücken Sie [Kopie], um Mustervorlage von Standardsprache zu kopieren [English] Drücken Sie [Auslassen], um manuell zu tippen.', 'This field is requred' => 'Dieses Feld ist erforderlich', 'Ticket#' => 'Ticket#', 'Time' => 'Zeit', 'Title displayed to customers' => 'Titel für Kunden angezeigt', 'Title of Report for your Reference' => 'Titel des Berichts zur Information', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'Um dieses Produkt zu bestellen muss der Benutzer über eine verfügen wenn der Benutzer Aufträge dieses Abonnement, wird es überprüft werden dass Benutzer hat eine aus der folgenden Abos', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'Speichern einer Tabelle als Datei komma-separierter Werte (CSV) (OpenOffice):', 'Total Paid' => 'Insgesamt ausgezahlt', 'Total to Pay' => 'Zahlbetrag', 'Trace' => 'Nachzeichnen', 'Traditional .htpasswd' => 'Traditionelles .htpasswd', 'Transactions Log' => 'Transaktions-Log', 'URL must be specified without trailing slash' => 'URL muss ohne Schrägstrich am Ende angegeben werden', 'URL must start from %s or %s' => 'URL muss aus %s oder %s anfangen', 'Unable to cancel subscription' => 'Abonnement kann nicht beendet werden', 'Unable to change rebill date' => 'Mahnungsdatum konnte nicht geändert werden', 'Unlock' => 'Aufsperren', 'Unpack Upgrades' => 'Entpacken Sie die Upgrades', 'Update Error' => 'Aktualisierungsfehler', 'Update License Information' => 'Lizenz-Information aktualisieren', 'Update User if Exist User with Same Login' => 'Aktualisierung des Benutzers, wenn ein Benutzer mit gleichen Anmeldung existiert', 'Upgrade' => 'Upgrade', 'Upgrade Database' => 'Upgrade einer Datenbank', 'Upgrade Download Problem' => 'Upgrade Herunterladungs Problem', 'Upgrade Finished' => 'Aktualisierung abgeschlossen', 'Upgrade From' => 'Upgrade von', 'Upgrade To' => 'Upgrade auf', 'Upload' => 'Hochladen ', 'Upsell - Replace Product from [Conditions] field' => 'Upsell - Ersetze Produkte aus [Bedingungen]-Feld', 'Upsell Configuration' => 'Upsell-Konfiguration', 'Upsell Paths' => 'Upsell-Pfade', 'Use Custom Settings' => 'Benutzerdefinierte Einstellungen nutzen', 'Use E-Mail Throttle Queue' => 'Verwenden Sie E-Mail Gas Queue', 'Use External Cron' => 'Verwenden Sie externen Cron', 'Use Global Settings' => 'Globale Einstellungen nutzen', 'Use this %slink%s to delete data from aMember v4 database and use clean database for import' => 'Benutze diesen %slink%s, um Daten aus der aMember v4-Datenbank zu löschen und eine bereinigte Datenbank zum Import zu nutzen', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'Anzahl Verwendungen eines Coupons pro Nutzer wie oft ein Coupon pro Nutzer verwendet werden kann', 'User Id' => 'Benutzer-ID', 'User Invoices' => 'Benutzer Rechnungen', 'User Pages Theme' => 'Das Motiv der Benutzerseiten', 'User currently has access to the following products' => 'Benutzer hat derzeit Zugriff auf die folgenden Produkte', 'User had access to the following products' => 'Benutzer hatte Zugang zu den folgenden Produkten', 'User is not found in database' => 'Der Benutzer ist nicht in der Datenbank gefunden', 'User notification' => 'Nutzer-Benachrichtigung', 'User-Affiliate Relation Lifetime how long (in days) calculate commission for referred affiliate (default: 0 - forever)' => 'Benutzer-Partner-Beziehungsdauer Anzahl (in Tagen): berechne Kommissionen für zugehörige Partner (Vorgabe: 0 - immer)', 'Username or e-mail address' => 'Benutzername oder E-Mail Adresse', 'Users' => 'Benutzer', 'Users Report' => 'Benutzer-Bericht', 'Utilities' => 'Nützliche Tools', 'VAT' => 'USt.', 'Valid license key are one-line string,starts with L and ends with X' => 'Gültige Lizenzschlüssel sind einzeilig, beginnen mit L und enden mit X', 'Value use % as wildcard mask' => 'Wert verwende % als Platzhalter', 'Value must be alpha-numeric' => 'Werte müssen alphanumerisch sein', 'Value must be alphanumeric' => 'Wert muss alphanumerisch sein', 'Values must not be equal' => 'Werte dürfen nicht übereinstimmen', 'Verify E-Mail Address On Signup Page e-mail verification may be enabled for each signup form separately at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Bestätige E-Mail-Adresse auf Registrierungsseite E-Mail-Bestätigung sollte für jedes Registrierungsformular einzeln unter aMember CP -> Formular-Editor > Bearbeiten, per Klick auf "konfigurieren" im E-Mail-Baustein, aktiviert sein', 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Bestätige neue E-Mail-Adresse auf Profilseite E-Mail-Bestätigung für das Profilformular sollte unter aMember CP -> Formular-Editor > Bearbeiten, per Klick auf "konfigurieren" im E-Mail-Baustein, aktiviert sein', 'Version Info' => 'Information der Version', 'Video Player' => 'Video Player', 'View' => 'Überblick', 'View Coupons' => 'Coupons überblicken', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Wir werden einen Antrag auf Zahlung Systems unterbreiten, oder Sie werden zum Zahlungssystem Seite umgeleitet werden, um Antrag auf Rückerstattung einreichen', 'Weekly' => 'Wöchentlich', 'Yes, assign category' => 'Ja, bestimmen Sie die Kategorie', 'Yes, do not e-mail this customer for any reasons' => 'Ja, diesen Kunden aus irgendwelchen Gründen nicht emailen', 'Yes, locked' => 'Ja, gesperrt', 'Yes, remove category' => 'Ja, entfernen Sie die Kategorie', 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.' => 'Sie können die Bericht für künftige Verwendung %sspeichern%s.', 'You can download %sexample file%s.' => 'Sie können die %sBeispieldatei%s herunterladen.', 'You can import users from CSV file to aMember.' => 'Sie können Nutzer aus einer CSV-Datei nach aMember importieren.', 'You can not merge user with itself' => 'Sie können Benutzer nicht mit sich selbst vereinen', 'You have currently choosed the following users for e-mail to:' => 'Sie haben derzeit die folgenden Benutzer für E-Mail gewählt:', 'You have generated %d demo products and %d demo customers' => 'Sie haben %d Demo-Produkte und %d Demo Kunden generiert', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'Sie haben Lizenzschlüssel früherer Versionen von aMember, bitte ersetzen Sie ihn mit neuen, einzeiligen Schlüsseln', 'You have no permissions to perform requested operation' => 'Sie haben keine Rechte die angeforderte Aktion auszuführen', 'Your Password enter your current password in order to edit admin record' => 'Ihr Passwort geben Ihr aktuelles Passwort ein num die Eintragung des Administrators zu editieren', 'Zip Code' => 'Postleitzahl', '[From] and [To] billing plans must not be equal' => '[Von] und [zu] Abrechnungs Pläne müssen nicht gleich sein', 'aMember Database (default)' => 'aMember Datenbank (Standard)', 'aMember will look for templates in [application/default/views/signup/] folder and in theme\'s [signup/] folder and template filename must start with [signup]' => 'aMember sucht im Ordner [application/default/views/signup] nach Vorlagen, sowie im Themes Ordner [signup/] und der Dateiname des Templates muss mit [signup] beginnen', 'access log table (used by admin only)' => 'Zugang Log-Tabelle (nur von Administrator verwendet)', 'admin log table (used by admin only)' => 'Administrator Protokoll-Tabelle (nur von Administrator verwendet)', 'after' => 'nach', 'allow max' => 'erlaube maximal', 'change' => 'ändern', 'collapse details' => 'Unterlagen verkleinern', 'days after expiration' => 'Tage nach Ablauf', 'days before expiration' => 'Tage vor Ablauf', 'days before rebilling' => 'Tage bis zur erneuten Rechnungsstellung', 'displaying records %d-%d from %d' => 'Datensätze %d-%d von %d', 'do not show disabled products' => 'deaktivierte Produkte ausblenden', 'do not show pending invoices' => 'ausstehende Rechnungen ausblenden', 'downloads within' => 'Downloads innerhalb', 'during subscription period' => 'während Abonnement-Zeitraum', 'error_log table (used by admin only)' => 'Fehlerprotokoll-Tabelle (nur von Administrator verwendet)', 'expand details' => 'Unterlagen erweitern', 'first paid at' => 'Erstmals bezahlt auf ', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'wenn der Code vorhanden ist, werden die Produkte im Warenkorb versteckt werden und dieser Code wird benötigt, um diese Produkte zu sehen', 'if customer uses more than' => 'wenn der Kunde mehr als nutzt ', 'if user enters wrong password' => 'Wenn Benutzer einen falsches Kennwort eingibt ', 'leave it empty in case of you want this item be available for all users' => 'lassen Sie dieses Feld leer, wenn Sie es allen Benutzern zugänglich machen möchten', 'login, email or name' => 'Anmeldung, E-Mail oder Name', 'must be a number in format 99 or 99.99' => 'muss eine Zahl im Format zu 99 oder 99,99 sein', 'must be equal or greather than 0' => 'muss gleich oder größer als 0 sein', 'must be equal or greather than 0.0' => 'muss gleich oder größer als 0,0 sein', 'on expiration day' => 'am Ablauftag', 'open in new window' => 'Im neuem Fenster öffnen', 'or %smake access free%s' => 'oder %sZugang erlauben%s', 'put website offline, making it available for admins only' => 'Stellen Sie die Website offline, Sie ist nur für Administratoren verfügbar ', 'seconds, he will be forced to wait until next try' => 'Sekunden, die gewartet werden müssen bis nächster Versuch möglich', 'sending' => 'Senden', 'sent successfully' => 'Erfolgreich gesendet', 'switch to show all records' => 'Alle Datensätze zeigen', 'switch to show only active records' => 'Nur aktive Datensätze zeigen', 'this item is available for %sall registered customers%s. click to %smake this item protected%s %sor %smake this item available without login and registration%s %s' => 'dieser Artikel ist für %salle registrierten Benutzer%s verfügbar. klicken, um %sArtikel zu schützen%s %soder %sdiesen Artikel ohne Login und Registrierung verfügbar zu machen%s %s', 'this item is available for %sall visitors (without log-in and registration) and for all members%s click to %smake this item protected%s or %smake log-in required%s ' => 'dieser Artikel ist für %salle Besucher (ohne Login und Registrierung) und alle Mitglieder%s verfügbar klicken, um %sdiesen Artikel zu schützen%s oder %sLogin zu erfordern%s ', 'times within' => 'mal innerhalb von', 'version' => 'Version', ); PK\rF--default/language/admin/ru.phpnu[ '%d дней после истечения', '%d days before expiration' => '%d дней перед истечением', '%d user(s) matches your search' => '%d пользователей соответсвуют условиям вашего поиска', '%d-th subscription day' => '%d-ый день подписки', '%s Plugins' => '%s Плагины', '-- Please Select --' => '-- Пожалуйста выберите --', '-- Without A Category --' => '-- Без Категории --', '..th subscription day (starts from 2)' => '..ый день подписки (начиная со второго)', '100% discount' => '100% скидка', 'API Keys' => 'API ключи', 'Accepted Payout Methods' => 'Доступные способы выплат', 'Access Method' => 'Способ доступа', 'Account Sharing Prevention' => 'Предотвращение совместного использования аккаунта', 'Account Verification' => 'Проверка пользователя', 'Active (free)' => 'Активный (бесплатный)', 'Add & Checkout' => 'Добавить и перейти к оформлению заказа', 'Add & Go to Basket' => 'Добавить и перейти на страницу с корзиной', 'Add Access Manually' => 'Добавить Доступ', 'Add Chargeback' => 'Добавить возвратный платеж', 'Add Invoice' => 'Добавить заказ', 'Add Payment' => 'Добавить платеж', 'Add Payment Manually' => 'Добавить платеж вручную', 'Add Refund' => 'Добавить возврат', 'Add Report to My Dashboard' => 'Добавить отчет на панель управления', 'Add Signature to Response' => 'Добавить подпись в ответ', 'Add Subscription' => 'Добавить подписку', 'Add User Fields' => 'Добавить поля', 'Add points to affiliate for each %s in payment' => 'Добавить очки партнерам для каждого %s в платеже', 'Add to Basket only' => 'Добавить в корзину', 'Admin Accounts' => 'Администраторы', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'E-Mail адрес администратора используется для отправки email уведомлений администратору и как адрес получателя по-умолчанию', 'Admin Email' => 'Администратор', 'Admin Free Subscription Notifications to admin once free signup is completed' => 'Уведомление администратора о бесплатной подписке администратору когда бесплатная регистрация завершена', 'Admin Log' => 'Лог администратора', 'Admin Pages Theme' => 'Тема страницы администратора', 'Admin Payment Notifications to admin once payment is received' => 'Уведомление администратора о платеже администратору когда платеж получен', 'Admin Settings' => 'Настройки администратора', 'Admin notification' => 'Уведомление администратора', 'Admin username must be alphanumeric in small caps' => 'Имя и фамилия должны быть буквенно-цифровыми', 'Administrator Login' => 'Вход администратора', 'Administrator has been removed, id [%d]' => 'Администратор был удален, id [%d]', 'Advanced Settings' => 'Расширенные настройки', 'Affiliate %s not found' => 'Партнер %s не найден', 'Affiliate Commission' => 'Комиссионные', 'Affiliate Commission Rules' => 'Правила начисления комиссии', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Время жизни партнерских cookies количество дней хранения cookies о связанных партнерах', 'Affiliate Information' => 'Партнерская иформация', 'Affiliate Payout Paid Notification to User send email to user when his payout is marked as paid' => 'Уведомление партнера о совершенных выплатах отправить email партнеру когда администратор помечает его выплаты как оплаченне', 'Affiliate Registration E-Mail' => 'E-Mail сообщение о регистрации партнера', 'Affiliates Payout Day choose a day of month when payout is generated' => 'День выплаты партнеров выберите день месяца когда генерируется выплата', 'Affiliates Signup Type' => 'Тип партнерской регистрации', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'После любых изменений в настройках папок, защищенных методом htpasswd, пожалуйста запустите [Utiltites -> Rebuild Db] для обновления файла htpasswd', 'All Banners' => 'Все Баннеры', 'All Subscription Period' => 'Весь период подписки', 'All new users automatically become affiliates' => 'Все новые пользователи автоматически становятся партнерами', 'Allow for some affiliates, disallow for others' => 'Разрешить для некоторых партнеров, запретить для остальных', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Разрешенное количество E-Mail введите количество email-ов разрешенное для указанного выше периода', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Разрешенный период E-Mail выберите если ваш хост ограничивает количество e-mail сообщений в день/час', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Всегда запоминать если выбрано да, не спрашивать пользователя - всегда запоминать', 'Amazon SES' => 'Amazon SES', 'Amazon SES Access Id' => 'Id доступа Amazon SES', 'Amazon SES Secret Key' => 'Секретный ключ Amazon SES', 'American Date Format' => 'Американский формат даты', 'Apply Tax?' => 'Добавлять налог?', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'Применять купон к повторяющимся платежам?', 'Approve' => 'Утвержден', 'Assign Category' => 'Назначить категорию', 'At least one billing plan must be added' => 'Должен быть добвален хотя бы один план платежей', 'Autoclose Tickets Due to Inactivity' => 'Автоматически закрывать Запрос в случае отсутствия активности', 'Available' => 'Доступно', 'Available Upgrades' => 'Достуные обновления', 'Available for users from groups' => 'Доступно для пользователей из групп', 'Back to Dashboard' => 'Назад к панели управления', 'Back to FAQ List' => 'Назад к списку вопросов', 'Backup' => 'Создать резервную копию', 'Banner' => 'Баннер', 'Banner Categories' => 'Категории Баннеров', 'Banners' => 'Баннеры', 'Basket HTML Code' => 'HTML код корзины', 'Begin date should be before Expire date' => 'Дата начала должна быть раньше даты окончания', 'Billing' => 'План платежей', 'Billing Terms' => 'Условия Оплаты', 'Blob (unlimited length binary data)' => 'Блоб (бинарные данные неограниченной длины)', 'Blocking IP/E-Mail' => 'Блокирование по IP/E-Mail', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Сайт временно закрыт для техобслуживания. Возвращайтесь через минутку.', 'Browse' => 'Просмотреть', 'Browse Countries' => 'Просмотреть страны', 'Browse Found Users' => 'Просмотреть найденных пользователей', 'Browse Users' => 'Все клиенты', 'Bruteforce Protection' => 'Защита Bruteforce', 'Build Demo' => 'Создать демо', 'Building demo records' => 'Создать демо записи', 'Button/Link HTML Code' => 'HTML код Кнопки/Ссылки', 'Calculate Affiliate Commissions from Totals Including Tax by default commission calculated from amounts before tax' => 'Рассчитывать комиссионные на основе суммы платежа включая налоги по умолчанию комиссионные расчитываются на основе суммы платежа до налогов', 'Can not find user with such username' => 'Не могу найти пользователя с данным именем', 'Can not find user with such username or email' => 'Не могу найти пользователя с таким именем пользователя или паролем', 'Can\'t be changed because your server have suhosin extension enabled' => 'Не может быть изменено поскольку ваш сервер имеет включенное расширение suhosin', 'Cancellations' => 'Отмены подписок', 'Change Configuration Settings' => 'Изменить настройки конфигурации', 'Change Password Notification send email to user after password change' => 'Уведомление о смене пароля отправлять email с уведомлением клиенту после того как он поменяет пароль', 'Change Paysystem' => 'Поменять платежную систему', 'Change rebill date' => 'Изменить дату следующего платежа', 'Charge Second Price Once' => 'Взимать стоимость вторичного периода один раз', 'Charge Second Price x Times' => 'Взимать стоимость вторичного периода x раз', 'Check for beta version' => 'Проверить бета-версию', 'Check other Affiliate Program Settings' => 'Другие настройки партнерской программы', 'CheckBoxes' => 'Чекбоксы', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => 'Выбрать %1$sФайл%2$s > %1$sСохранить как%2$s.', 'Choose Products and/or Product Categories that allows access' => 'Выберите продукты и/или категории продуктов которые открывают доступ', 'Choose Upgrades to Install' => 'Выберите обновления для установки', 'Choose action when locked %s used by customer during signup' => 'Выберите действие, когда в течение регистрации покупателем используется блокировка %s', 'Clean up v4 Database' => 'Очистить базу данных v4', 'Cleaning up' => 'Очистка', 'Cleanup' => 'Уборка', 'Clear' => 'Очистить', 'Clear Access Log' => 'Очищать лог доступа', 'Clear Incomplete Invoices' => 'Очищать незавершенные заказы', 'Click to Expand' => 'Нажмите чтобы развернуть', 'Code Length generated coupon code length between 4 and 32' => 'Длина кода длина созданного купона между 4 и 32', 'Collapse Menu' => 'Скрыть меню', 'Comma' => 'Запятая', 'Comment for Your Reference' => 'Комментарий', 'Commission earned' => 'Заработанная комиссия', 'Commission for First Payment calculated for first payment in each invoice' => 'Комиссия за первый платеж вычисляется для первого платежа в каждой покупке', 'Commission for Free Signup calculated for first customer invoice only' => 'Комиссия за бесплатную подписку вычисляется только однажды для каждого пользователя', 'Commission for Rebills' => 'Комиссия для повторного платежа', 'Conditions' => 'Условия', 'Configured License Keys' => 'Настроенные лицензионные ключи', 'Copy' => 'Копировать', 'Copy Upgrades' => 'Скопировать обновления', 'Copy from another language' => 'Скопировать с другого языка', 'Core' => 'Ядро', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Не могу скачать файл [%s]. Ошибка %s.Пожалуйста %sпопробуйте снова%s позже.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'Не могу скачать список обновлений с удаленного сервера. %sПопробуйте снова%s', 'Could not fetch upgrades list. Connection error [%s]' => 'Не могу скачать список обновлений. Ошибка соединения [%s]', 'Countries/States' => 'Страны/Регионы', 'Coupon Codes' => 'Коды купонов', 'Coupon used for %d transactions' => 'Купон использован для %d транзакций', 'Coupons' => 'Купоны', 'Coupons Batches' => 'Серии купонов', 'Coupons Count how many coupons need to be generated' => 'Количество купонов сколько необходимо сгенерировать купонов', 'Create Folder' => 'Создать папку', 'Create Session Key' => 'Создать ключ сессии', 'Create ticket as' => 'Создать тикет как', 'Custom Commission Rules added' => 'Созданы специальные правила комиссии', 'Custom HTML' => 'Пользовательский HTML', 'Custom Signup Form Title keep empty to use default title' => 'Название формы регистрации оставьте пустым для использования названия по-умолчанию', 'Customer' => 'Пользователь', 'Customize Dashboard' => 'Настроить панель управления', 'Daily' => 'Ежедневно', 'Date Time' => 'Дата время', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Дата для очистки все записи произведенные до этой даты будут удалены из выбранной таблицы', 'Dates date range when coupon can be used' => 'Даты Временные границы использования купонов', 'Dates can be in the folowing formats' => 'Даты могут быть в следующих форматах', 'Days to Send' => 'Дни отправки', 'Default - user clicks a link to become affiliate' => 'По умолчанию - пользователь кликая по ссылке становится партнером', 'Default Billing Plan' => 'Порядок оплаты по умолчанию', 'Default Commission' => 'Комиссия по умолчанию', 'Default Locale' => 'Локаль по-умолчанию', 'Default Not Found Page' => 'Системная страницы не найдена', 'Default Signup' => 'Регистрация по умолчанию', 'Default Size width×height' => 'Размер ширина×высота', 'Default for Members' => 'По-умолчанию для пользователей', 'Default value for field (that is default value for inputs, not SQL DEFAULT)' => 'Значение по умолчанию для поля (значение по умолчанию для поля ввода, это не SQL DEFAULT)', 'Delete Old Records' => 'Удалить устаревшие записи', 'Delete Saved Search?' => 'Удалить сохраненые результаты поиска?', 'Delete payment and access record' => 'Удалить записи платеж и доступ', 'Delimiter' => 'Разделитель', 'Demo History' => 'Демо история', 'Description displayed to visitors on order page below the title' => 'Описание показывается посетителю на странице заказа под названием', 'Details' => 'Детали', 'Die and show ugly error message' => 'Остановить выполнение скрипта и показать неформатированное сообщение об ошибке', 'Digits and latin letters only please' => 'Пожалуйста, только цифры и латинские символы', 'Disable Visual HTML Editor' => 'Выключить WYSIWYG HTML редактор', 'Disable auto-locking for this customer' => 'Выключить авто-блокировку для этого пользователя', 'Disallow for some affiliates, allow for others' => 'Запретить для некоторых партнеров, запретить для остальных', 'Disallow new Signups by %s' => 'Отклонять новые регистрации по %s', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'Не разрешать заказывать продукт если пользователь имеет когда пользователь заказывает данную подписку, производиться проверка на наличие одной из следующих подписок', 'Display Language Choice' => 'Показавать панель выбора языка', 'Display Mode' => 'Режим отображения', 'Display error message' => 'Показать сообщение об ошибке', 'Do not Allow Spaces in Username' => 'Не разрешать пробельные символы в имени пользователя', 'Do not Lowercase Username by default, aMember automatically lowercases entered username here you can disable this function' => 'Не приводить имя пользователя к нижнему регистру по умолчанию, все именя пользователей приводятся к нижнему регистру, здесь вы можете отключить эту функцию', 'Do not generate products use existing products for demo records' => 'Не генерировать продукты использовать существующие продукты для демо записей', 'Do you really want to change Rebill Date for this invoice?' => 'Вы действительно хотите изменить дату повторного платежа для этого заказа?', 'Do you really want to delete this item?' => 'Вы действительно хотите удалить данный элемент?', 'Do you really want to refund payment' => 'Вы действительно хотите вернуть платеж', 'Do you really want to stop this subscription?' => 'Вы дейтвительно хотите остановить эту подписку?', 'Do you really want to void this commission?' => 'Вы действительно хотите аннулировать эту комиссию?', 'Documentation' => 'Документация', 'Does Not Allow to Upload Attachments for Users' => 'Запретить загрузку файлов для клиентов', 'Does Not Show FAQ Tab in Member Area' => 'Не добавлять раздел FAQ в меню', 'Download CSV File' => 'Сохранить CSV файл', 'Download Upgrades' => 'Скачать обновления', 'Duration:' => 'Продолжительность:', 'E-Mail Address to Send to' => 'E-Mail адрес получателя', 'E-Mail Backup Address' => 'E-Mail', 'E-Mail Commission to Admin' => 'E-Mail сообщение о комиссии администратору', 'E-Mail Commission to Affiliate' => 'E-Mail сообщение о комиссии партнеру', 'E-Mail Database Backup' => 'Отсылка резервной копии базы данных на E-Mail', 'E-Mail Queue' => 'Очередь E-Mail', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'Имя отправителя E-Mail используется для отображения имени отправителя в исходящих сообщениях', 'E-Mail Sending' => 'Отправка письма', 'E-Mail System Configuration' => 'Конфигурация системы отправки E-mail', 'E-Mail Type' => 'тип E-Mail', 'E-Mail Users' => 'Сделать рассылку', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'E-Mail было успешно отправлено %s покупателю. ID партии Email%s', 'E-Mail sending started' => 'Начата отправка письма', 'E-Mails History' => 'История письма', 'E-Mails by Admin Request' => 'E-Mail по запросу администратора', 'E-Mails by User Request' => 'E-Mail по требованию пользователя', 'Earn points for %s in payment' => 'Заработать очки для %s в платеже', 'Edit Custom Commission Rules' => 'Редактировать специальные правила выплат', 'Edit Groups' => 'Редактировать группы', 'Edit Messages' => 'Редактирование сообщений', 'Edit States' => 'Редактировать регион', 'Email Addresses Separated by Comma' => 'Email адреса через запятую', 'Email Backup Frequency' => 'Частота отсылки резервной копии базы данных на E-Mail', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'Метод отправки email ПОЖАЛУЙСТА НЕ ИЗМЕНЯЙТЕ если отправка сообщений от aMember работает', 'Email Sent' => 'Письмо отправлено', 'Email address is required field.' => 'Email адрес это обязательное поле.', 'Enable plugins if necessary' => 'Включить плагины если необходимо', 'Enter Maintenance Mode' => 'Войти в режим техобслуживания', 'Enter admin password for confirmation' => 'Ввести пароль администратора для подтверждения', 'Enter title for your new category' => 'Введите название новой категории', 'Error Log' => 'Лог ошибок', 'Error/Debug Log' => 'Лог ошибок/отладки', 'Errors' => 'Ошибки', 'Errors:' => 'Ошибок:', 'European Date Format' => 'Европейский формат даты', 'Every %s' => 'Каждый %s', 'Exchange Rate' => 'Обменный курс', 'Exchange Rate enter cost of 1 (one) %s' => 'Обменный курс введите цену 1 (одного) %s', 'Field Name' => 'Имя поля', 'Field Title' => 'Название поля', 'Field Values' => 'Значения полей', 'File (max filesize %s)' => 'Файл (размер файла %s)', 'File is required' => 'Файл обязательный ', 'Filter By Title or Category' => 'Фильтровать по заголовку или категории', 'Filter by Affiliate/Banner/IP' => 'Фильтровать по партнеру/баннеру/IP', 'Filter by Affiliate/User/Banner' => 'Фильтровать по партнеру/клиенту/баннеру', 'Filter by Affiliate/User/Product' => 'Фильтровать по партнеру/клиенту/продукту', 'Filter by Category' => 'Фильтровать по категориям', 'Filter by Paysystem' => 'Фильтровать по платежной системе', 'Filter by Product' => 'Фильтровать по продукту', 'Filter by String' => 'Фильтр по строке', 'Filter by User/Product' => 'Фильтровать по клиенту/продукту', 'Filter by name or description' => 'Фильтровать по имени/описанию', 'Filter by string or by invoice#/member#' => 'Фильтровать по строке или по №заказа/№пользователя', 'First Payment (calculated for first payment in each invoice)' => 'Первый платеж (расчитывается для первого платежа в каждом заказе)', 'First Period' => 'Первый период', 'First Price' => 'Первая цена', 'First Price price of first period of subscription' => 'Начальная цена цена начального периода подписки', 'First Tax' => 'Налог на первый платеж', 'First Total' => 'Итоговая цена первого платежа', 'First and Last Name' => 'Имя и фамилия', 'First available protected url' => 'Первый доступный защищенный url', 'First visited' => 'Первый визит', 'Fix aMember Pro License Key' => 'Исправить лицензию aMember Pro', 'Fixed Url' => 'Фиксированный URL', 'Fixed date' => 'Фиксированная группа', 'FlowPlayer License Key you may get your key in %smembers area%s' => 'Лицензионный ключ FlowPlayer-а вы можете взять ваш ключ в %sпользовательской области%s', 'Folder URL' => 'URL папки', 'Form Type' => 'Тип формы', 'Forms Editor' => 'Редактор форм', 'Future' => 'Будущее', 'General' => 'Основные', 'General Affiliate Link Redirect URL It is url of landing page for default affiliate link (which does not related to any banner), home page will be used if you keep it empty' => 'Редирект URL для партнерской ссылки Это URL страницы для партнерской ссылки по умолчанию (которая не связана ни с какими баннерами). Главная страница вашего сайта будет использованна если вы оставите это поле пустым', 'General Link' => 'Основная ссылка', 'General Settings' => 'Общие настройки', 'Generate' => 'Генерировать', 'Generate Basket HTML' => 'Сгенерировать HTML код корзины', 'Generate Button HTML' => 'Сгенирировать HTML код кнопки', 'Generate Payout Manually' => 'Создать выплату вручную', 'Generate Report' => 'Сгенирировать отчет', 'Generated' => 'Сгенерировано', 'Generation of demo data was terminated while processing. Not all records were created.' => 'Генерирование демонстративных данных было отменено. Не все записи были созданы.', 'Get Available Upgrades List' => 'Получить список обновлений', 'Get New Password' => 'Получить новый пароль', 'Global' => 'Общие', 'Graph Bar' => 'Гистограмма', 'Graph Line' => 'График', 'Help & Support' => 'Помощь и поддержка', 'Hostname' => 'Имя хоста', 'Hour' => 'Час', 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database' => 'Я понимаю что обновление может переписать настроенные PHP файлы и шаблоны, Я уже сделал резервную копию папки aMember-а и базы данных', 'IMPORTANT NOTE:' => 'ВАЖНО:', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'ВАЖНО. Контент не защищается. Если кто-то знает ссылку, он сможет открыть ее без авторизации. Данная функция контролирует какие дополнительные ссылки пользователь увидит при входе в область пользователей.', 'IP' => 'IP адрес', 'IP within' => 'IP в', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Если вы переключаетесь с одного платежного процессора на другой, вы можете использовать эту страницу для переключения созданных подписок с одного процессора на другой. Это возможно только если номера кредиток сохранены в aMember.', 'Image' => 'Изображение', 'Import Finished' => 'Импорт закончен', 'Import Pre-Defined List of Coupon Codes from CSV File (One coupon code per line)' => 'Импортировать список готовых кодов из CSV файла (один код купона на строке)', 'Import Users' => 'Импорт клиентов', 'Important Notice:' => 'Важные замечания:', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'В диалоге экспорт текстового файла, выберите опции которые вам нужны и затем нажмите %1$sOk%2$s.', 'In the File name box, type a name for the file.' => 'В поле имя файла, введите имя файла', 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.' => 'В списке тип файла, выберите %1$sТекст CSV%2$s и нажмите %1$sСохранить%2$s. Вы можите увидеть окно сообщений. Нажмите %1$sСохранить текущий формат%2$s.', 'Insert' => 'Вставить', 'Install Updates' => 'Установить обновления', 'Integer field (only numbers)' => 'Целое число (только цифры)', 'Integration plugins' => 'Интеграционные плагины', 'Internal PHP mail() function (default)' => 'Внутренняя PHP функция mail() (по-умолчанию)', 'Intro Text on Affiliate Info Page' => 'Текст на страницы с партнерской иформацией', 'Intro Text on Helpdesk Page' => 'Текст на странице службы поддержки', 'Invoice Log' => 'Логи заказов', 'Invoices' => 'Заказы', 'Invoices Per User' => 'Заказы пользователя', 'Is Approved' => 'Одобрен?', 'Is Disabled' => 'Выключена', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'Выключено? выключить заказ продуктов, не показывать на формах регистрации и возобновления', 'It is required to setup a cron job to trigger backup generation' => 'необходимо добавить следующую задачу в cron-tab на вашем сервере', 'Items' => 'Продукты', 'JavaScript Code' => 'JavaScript код', 'Key' => 'Ключ', 'Key must be 20 chars or longer' => 'Длина ключа должна быть не менее 20 символов', 'Languages' => 'Языки', 'Last %s Customers' => 'Последние %s пользователей', 'Last %s Helpdesk Messages' => 'Последних %s сообщений службы поддержки', 'Last %s Invoices' => 'Последние %s счетов', 'Last %s Payments' => 'Последние %s платежи', 'Last %s Refunds' => 'Последние %s возвраты', 'Last Invoices List' => 'Список поледних счетов', 'Last Payments List' => 'Список последних платежей', 'Last Refunds List' => 'Список последних возвратов', 'Last User Logins List' => 'Список последних входов', 'Last Users List' => 'Список последних пользователей', 'Last available protected url' => 'Последний доступный защищенный url', 'Last existing subscription date of this product' => 'Последняя дата подписки на этот продукт', 'Last expiration date in the renewal group' => 'Последняя дата истечения в обновленной группе', 'Last login' => 'Последние посещение', 'Length of admin password must be from %d to %d' => 'Длина пароля адмистратора должна быть от %d до %d', 'Length of username must be from %d to %d' => 'Длина имени пользователя должна быть от %d до %d', 'Light Boxes' => 'Лайтбоксы', 'Lightbox Main Image' => 'Большая лайтбокс картинка', 'Lightbox Thumbnail Image' => 'Маленькая лайтбокс картинка', 'Limit Downloads Count' => 'Ограничение скачек', 'Lines Proccessed:' => 'Строчек обработано:', 'Lines Skipped:' => 'Строчек пропущено:', 'Lines Success:' => 'Строчек обработано успешно:', 'Link to reset your password was sent to your Email.' => 'Ссылка для сброса пароля отправлена на ваш email', 'Loading...' => 'Загрузка...', 'Lock' => 'Заблокировать', 'Locked Value' => 'Закрытое значение', 'Log Outgoing E-Mail Messages for ... days' => 'Вести лог исходящих сообщений для ... дней', 'Log in' => 'Вход', 'Logged in as %s' => '%s', 'Login Page' => 'Страница входа', 'Logs' => 'Логи', 'Logs: Access' => 'Логи: Доступ', 'Logs: Admin Log' => 'Логи: лог администратора', 'Logs: Errors' => 'Логи: Ошибки', 'Logs: Invoice' => 'Логи: Заказ', 'Logs: Mail Queue' => 'Логи: mail очередь ', 'Lookup' => 'Искать', 'Lost your password?' => 'Потеряли пароль?', 'Mail' => 'Письмо', 'Maintenance Mode' => 'Режим обслуживания', 'Manage Product Upgrade Paths' => 'Управление путями обновлений продуктов', 'Manage Products' => 'Управление продуктами', 'Manually Added' => 'Добавлено вручную', 'Mark NOT Paid' => 'Отметить как неоплаченный', 'Mark Paid' => 'Отметить как оплаченный', 'Mass Subscribe' => 'Массовая подписка', 'Membership' => 'Членство', 'Membership Info Page' => 'Страница инофрмации пользователя', 'Merge' => 'Слить', 'Miscellaneous' => 'Прочее', 'Monthly' => 'Ежемесячно', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Составное название заказа когда пользователь заказывает несколько продуктов, показать следующее в платежной системе вместо имени продукта', 'Name of Preset' => 'Название начальной установки', 'Need points to get %s discount' => 'Нужны очки для получения %s дисконта', 'New Autoresponder' => 'Новый автоответчик', 'New Expiration E-Mail' => 'Новое оповещение об окончании подписки', 'New Modules Available' => 'Новые модули доступны', 'New Rewrite' => 'Новые перезаписи', 'New Ticket Autoresponder to Customer aMember will email an autoresponder to user each time user create new ticket' => 'Автоответчик новых запросов покупателей aMember будет отправлять email сообщение пользователю каждый раз как пользователь ответит на запрос', 'New password has been e-mailed to your e-mail address' => 'Новый пароль отправлен на ваш email', 'Next rebill date' => 'Следующий платеж', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'Нет сохраненных кредитных карт для этого пользователя. %sДобавить карту%s', 'No Invoices Found' => 'Счета не найдены', 'No Tax' => 'Без налога', 'No Updates Available' => 'Нет обновлений', 'No more charges' => 'Однократный платеж ', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'В файле не найдено ни одной линии. Кажется файл пуст. Вы можете вернуться назад и использовать другой файл.', 'No search name passed' => 'Не передано имя для поиска', 'No upgrades to install' => 'Нет обновлений для установки', 'Not Approved' => 'Неутвержденный', 'Not Approved Users' => 'Непроверенные пользователи', 'Not Confirmed Users' => 'Не утвержденные пользователи', 'Not-SQL field (default)' => 'Not-SQL поле (по умолчанию)', 'Note' => 'Примечание', 'Number of Payments to display' => 'Количество платежей для отображения', 'Number of Users to display' => 'Количество пользователей для отображения', 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.' => 'Количество счетов которые требуют утверждения: %d. %sНажмите здесь%s для просмотра ', 'Numeric field' => 'Числовое поле', 'OTO - Offer to purchase additional product (with optional discount)' => 'OTO - предложение купить дополнительный продукт (с дополнительной скидкой)', 'One field can be assigned to one column only, you assigned following fields to several columns: ' => 'Одно поле может быть связано только с одной колонкой, вы связали следующие поля с несколькими колонками', 'One field can be assigned to one column only.' => 'Одно поле может быть связанно с одной колонкой.', 'Only admin can enable user as an affiliate' => 'Только администратор может сделать пользователя партнером', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Адрес исходящего сообщения ипользуется как от кого: адрес для отправки e-mail сообщений покупателю. Если пусто, ипользуется [E-Mail адрес администратора]', 'Overwrite User if Exist User with Same Login' => 'Перезаписать пользователя если существует пользователь с таким же логином', 'Paid' => 'Уплачено', 'Password Length' => ' Длина пароля', 'Password changed' => 'Пароль изменен', 'Password must not be equal to username' => 'Пароль не должен совпадать с именем пользователя', 'Passwords must be the same' => 'Пароли должны совпадать', 'Path to Folder' => 'Путь к папке', 'Path/URL' => 'Путь/URL', 'Payment Date' => 'Дата платежа', 'Payment Receipt' => 'Квитанция', 'Payment date' => 'Дата платежа', 'Payment has been successfully refunded' => 'Платеж был успешно отменен', 'Payment#/Receipt#' => 'Платеж#/Рецепт#', 'Payments (amount of all payments made by user minus refunds)' => 'Платежи (сумма всех платежей сделанных клиентом минус возвраты)', 'Payout %d Details' => 'Детали выплаты %d', 'Payout Details' => 'Детали выплат', 'Paysystem' => 'Платежная система', 'Pending Invoice Notification Rules' => 'Правила уведомления об обрабатываемом заказе', 'Permissions' => 'Права доступа', 'Please assign the following fields: ' => 'Пожалуйста введите следующий значения:', 'Please choose another field name. This name is already used' => 'Выберите другое имя поля. Данное имя уже используется', 'Please choose product' => 'Выбирите продукт', 'Please enter expire date' => 'Введите дату окончания', 'Please enter one or more email' => 'Введите один или более email адресов', 'Please enter start date' => 'Введите дату начала', 'Please enter valid e-mail address' => 'Пожалуйста введите проверенный адрес', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'Пожалуйста введите имя пользователя или email Вы получите ссылку для создания нового пароля на ваш email', 'Please note: By default, aMember does not change users password and login values to a generated value in cases where an existing email address is found. You may decide to update an existing record, in the next step of the import process, where a matching email or username already exists.' => 'Пожалуйста учтите: По-умолчанию, aMember не изменяет логин и пароль пользователя на сгенирированные значения когда найден cуществующий email. Вы можете решить обновить существующюю запись, на следующем шаге процесса импорта, где совпадение email или имени пользователя существует.', 'Please run %sRebuild Db%s to update status for imported customers' => 'Пожалуйста запустите %sПереписать базу данных%s для обновления статуса импортированных покупателей', 'Please select date before today' => 'Пожалуйста выберите любую дату до сегодняшнего дня', 'Please specify new rebill date: ' => 'Пожалуйста определите новую дату платежа', 'Please wait' => 'Пожалуйста подождите', 'Plugins' => 'Плагины', 'Product Availability' => 'Доступность продукта', 'Product Category' => 'Категории продукта', 'Product Category: ' => 'Категория продукта: ', 'Product Image' => 'Изображение продукта', 'Product Upgrades' => 'Обновления продуктов', 'Products Per Invoice' => 'Продукты заказа', 'Protect Content' => 'Защита контента', 'Protection Method' => 'Метод защиты', 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty' => 'Количество по умолчанию - 1, обычно вам не нужно изменять это ', 'Quit Maintenance Mode' => 'Выйти из режима техобслуживания', 'REST API Documentation' => 'документация REST API', 'RadioButtons' => 'Радиокнопки', 'Re Send Payment Link' => 'Выслать ссылку на оплату', 'Rebill' => 'Повторный платеж', 'Rebill Date' => 'Дата следующего платежа', 'Rebill Second Price until cancelled' => 'Взимать стоимость второго периода до его отмены', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Количество повторных платежей Это количество платежей которые будут взиматься по второй цене', 'Rebuild Db' => 'Перестроить БД', 'Receipt' => 'Квитанция', 'Receipt#' => 'Квитанция#', 'Recipients' => 'Получатель', 'Record modified, original dates:' => 'Запись изменена, исходные даты', 'Records Deleted Sucessfully' => 'Записи удалены успешно', 'Records per Page (for grids)' => 'Записей на странице (для таблиц)', 'Redirect URL' => 'Ссылка (перенаправление)', 'Referrer' => 'Отправитель', 'Refund Date' => 'Дата возврата', 'Refund Payment' => 'Вернуть платеж', 'Refunds' => 'Возвраты', 'Remember Login remember username/password in cookies' => 'Запомнить логин запомнить имя пользователя/пароль в cookies', 'Remind Password to Admin' => 'Напомнить пароль администратору', 'Remind Password to Customer' => 'Напомнить пароль покупателю', 'Remove Category' => 'Удалить категорию', 'Remove From Dashboard' => 'Удалить с панели управления', 'Repeat Action Handling' => 'Повторить обработку действия', 'Replace Product' => 'Заменить продукт', 'Report Bugs' => 'Сообщить об ошибке', 'Report Settings' => 'Настройки отчета', 'Reports' => 'Отчеты', 'Reseller Packages' => 'Услуги реселлера', 'Resend' => 'Повторная отправка', 'Resend Email' => 'Повторно отправить письмо', 'Resend Payment Link' => 'Выслать ссылку на оплату', 'Resend Signup E-Mail' => 'Переотправить региcтрационный E-Mail', 'Resource' => 'Ресурс', 'Restore' => 'Восстановить из копии', 'Restore Password' => 'Восстановить пароль', 'Retreive Access Parameters if necessary' => 'Получить параметры доступа если необходимо', 'Return to Payouts List' => 'Вернуться к списку выплат', 'Root URL root script URL, usually %s' => 'Корневой URL URL корневого скрипта, обычно %s', 'Root Url and License Keys' => 'Корневой URL и лицензионный ключ', 'Rule Removed' => 'Правило Удалено', 'Run Payout' => 'Сформировать отчет по выплатам', 'Run Reports' => 'Запустить отчет', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'Имя хоста SMTP', 'SMTP Hostname is required if you have enabled SMTP method' => 'Имя хоста SMTP обязательно если вы выбрали SMTP метод', 'SMTP Password' => 'Пароль SMTP', 'SMTP Port' => 'Порт SMTP', 'SMTP Security' => 'Безопасность SMTP ', 'SMTP Username' => 'Имя пользователя SMTP', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (не может быть использован для multi-select и checkbox полей)', 'SQL Date Format' => 'формат даты SQL', 'Sales Statistic' => 'Статистика продаж', 'Save This Search' => 'Сохранить этот поиск', 'Saved Credit Cards' => 'Сохранить кредитные карты', 'Saved Reports' => 'Сохраненные отчеты', 'Saved Search' => 'Сохранить результаты поиска', 'Search by Message' => 'Поиск по сообщению', 'Second Period' => 'Второй период', 'Second Price' => 'Вторая цена', 'Second Price price that must be billed for second and the following periods of subscription' => 'Цена второго периода цена которая будет взиматься на втором и последующих периодах подписки', 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form' => 'Секретный код если форма не выбрана по умолчанию, этот код (внутри URL) будет необходим для открытия формы ', 'Secure Root URL secure URL, usually %s' => 'Защищенный корневой URL защищенный URL, обычно %s', 'Select (Multiple Values)' => 'Выпадающий список (множество значений)', 'Select (Single Value)' => 'Выпадающий список (одно значение)', 'Select Action of Element' => 'Действие', 'Select Product(s) if nothing selected - all products' => 'Продукты если ни чего не выбрано то все доступные продукты', 'Select Type of Element' => 'Тип элемента', 'Select a plugin' => 'Выбрать плагин', 'Select option' => 'Выбрать опцию', 'Selected for E-Mailing' => 'Выбрано для отправки писем', 'Semicolon' => 'Точка с запятой', 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member' => 'Отправить администратору уведомление об отмене отправлять email с уведомлением администратору когда клиент отменил подписку с автопродлением', 'Send E-Mail Message' => 'Отправить E-Mail сообщение', 'Send E-Mail Messages' => 'Отправить E-Mail сообщения', 'Send E-Mail if customer has subscription (required)' => 'Отправить E-Mail если есть подписка', 'Send E-Mail only if customer has no subscription (optional)' => 'Отправить E-Mail если пользователь не имеет подписок (выборочно)', 'Send New E-Mail' => 'Отправить новое письмо', 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket' => 'Отправлять уведомления о новых сообщениях администратору aMember будет отправлять email уведомления администратору каждый раз как пользователь ответит на запрос', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Отправить уведомление о новых сообщениях покупателю aMember будет отправлять email уведомление пользователю каждый раз как администратор отвечает на запрос пользователя', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'Отправлять регистрационный E-Mail когда покупатель зполняет форму регистрации (перед платежем)', 'Send Registration E-Mail to this user' => 'Отправить регистрационный E-Mail этому пользователю', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Отправить регистрационный E-Mail когда ПЕРВАЯ покупка подписки выполнена', 'Send Test E-Mail' => 'Отправить тестовое сообщение', 'Send message' => 'Отправить сообщение', 'Send reports to my email' => 'Отправить отчет на мой email', 'Sender' => 'Отправитель', 'Sending Test E-Mail...' => 'Отправить тестовое E-Mail', 'Sending e-mail (sent to %d from %d)' => 'Отправка письма (отправлено %d от %d)', 'Session Storage' => 'Механизм хранения сессий', 'Setup/Configuration' => 'Конфигурация', 'Shopping Cart Settings' => 'Настройки корзины', 'Show Search Function in FAQ' => 'Показывать форму поиска в FAQ', 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation' => 'Текст подписи Вы можете использовать следующие заменители %name_f%, %name_l% это будет расширенно на имя и фамилию администратора в операциях', 'Signup Form Configuration' => 'Конфигурация формы регистрации', 'Signup Info' => 'Информация о подписке', 'Signup Messages' => 'Сообщения о регистрации', 'Site is temporarily disabled for maintenance' => 'Сайт временно переведен в режим обслуживания', 'Size' => 'Размер', 'Size of input field' => 'Размер поля ввода', 'Skip' => 'Пропустить', 'Skip Line if Exist User with Same Login' => 'Пропустить строчку если существует пользователь с таким же логином', 'Sort' => 'Сортировка', 'Sort Order' => 'Порядок сортировки', 'Source' => 'Основание', 'Space' => 'Пробел', 'Standard PHP Sessions' => 'Стандартная сессия PHP', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Вычисление даты старта правила вычисления даты старта подписки. из возможных вариантов будет выбрана максимальная дата. Эти настройки не повлияют на подписки с повторяющимися платежами', 'Start and Expiration Dates' => 'Даты начала и истечения ', 'Started' => 'Стартовала', 'Step %d of %d' => 'Шаг %d из %d', 'Stop Recurring' => 'Остановить подписку', 'String' => 'Строка', 'Submitting...' => 'Отправка...', 'Subscription' => 'Подписка', 'Super Admin' => 'Главный админ', 'Surcharge' => 'Доплата', 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead' => 'Доплата дополнительная плата когда пользователь переходит [From]->[To] план aMember не взимает первоночальный платеж при обновление, вместо этого взимается дополнительный платеж ', 'System Info' => 'Иформация о системе', 'Table' => 'Таблица', 'Tabulation' => 'Табуляция', 'Template alternative template for signup page' => 'Шаблон альтернативный шаблон для формы регистрации', 'Terms Text automatically calculated if empty' => 'Текст условий автоматически вычисляется если не заполнен', 'Test E-Mail Settings' => 'Проверить настройки E-Mail', 'Text' => 'Текст', 'Text (unlimited length string/data)' => 'Текст (строка/данные неограниченной длины)', 'Text Link' => 'Текстовые Ссылки', 'Text Links' => 'Текстовые ссылки', 'TextArea' => 'Текстовое поле', 'The password is entered incorrectly' => 'Пароль введен некорректно', 'This code can be inserted into any HTML page on your website or into any WordPress post or page' => 'этот код может быть вставлен в любую HTML страницу вашего сайта или в любой WordPress пост или страницу', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Шаблон письма пуст для данного языка. Нажмите [Copy] для копирования из языка по умолчанию [English] Нажмите [Skip] для ввода его вручную с нуля', 'This field is requred' => 'Это поле обязательно', 'Ticket Categories' => 'Категории обращений', 'Ticket#' => 'Запрос#', 'Tickets Assigned to Me' => 'Запросы назначенные на меня', 'Time' => 'Время', 'Title displayed to customers' => 'Название показывать покупателям', 'Title of Element' => 'Заголовок', 'Title of Report for your Reference' => 'Название отчета для справки', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'Для заказа данного продукта пользователь должен иметь когда пользователь заказывает эту подписку, производится проверка на наличие одной из следующих подписок', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'Для сохранения таблицы как разделенной запятыми значением (СSV) файл (OpenOffice): ', 'To verify import result go to %sBrowse Users%s' => 'Вы можете просмотреть импортированных пользователей %sсдесь%s', 'Total Paid' => 'Всего оплачено', 'Total to Pay' => 'Всего оплатить', 'Trace' => 'Отслеживать', 'Traditional .htpasswd' => 'Традиционно .htpasswd', 'Transactions Log' => 'Лог транзакций', 'Transactions with this coupon:' => 'Транзакции с этим купоном:', 'URL must be specified without trailing slash' => 'URL должен быть указан без косой черты', 'URL must start from %s or %s' => 'URL должен начинаться с %s или %s', 'Unable to cancel subscription' => 'Невозможно отменить подписку', 'Unable to change rebill date' => 'Невозможно изменить дату повторного платежа', 'Unlock' => 'Разблокировать', 'Unpack Upgrades' => 'Распаковать обновления', 'Update Error' => 'Ошибка обновления', 'Update License Information' => 'Обновить информацию о лицензии', 'Update User if Exist User with Same Login' => 'Обновить пользователя если существует пользователь с таким логином', 'Upgrade' => 'Обновление', 'Upgrade Database' => 'Обновить базу данных', 'Upgrade Download Problem' => 'Не могу скачать обновление', 'Upgrade Finished' => 'Обновление закончено', 'Upgrade From' => 'Обновить из', 'Upgrade To' => 'Обновить до', 'Upload' => 'Закачать', 'Upsell - Replace Product from [Conditions] field' => 'Увеличение продаж - Заменить продукт из [Conditions] поля ', 'Upsell Configuration' => 'Настройка увелечения объема покупки', 'Upsell Paths' => 'Пути увеличения продаж', 'Use Custom Settings' => 'Использовать частные настройки', 'Use E-Mail Throttle Queue' => 'Использовать E-Mail очередь прерывания', 'Use External Cron' => 'Ипользовать внешний cron', 'Use Global Settings' => 'Использовать глобальные настройки', 'Used For' => 'Использован для', 'Used Rules' => 'Использованное правило', 'User Access' => 'Доступ клиента', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'Количество использования купона клиентом сколько раз один купон может быть использован одним клиентом', 'User Email' => 'Клиент', 'User Id' => 'Id пользователя', 'User Invoices' => 'Пользовательские заказы', 'User Pages Theme' => 'Тема страницы пользователя', 'User currently has access to the following products' => 'У пользователя есть доступ к следующим продуктам', 'User had access to the following products' => 'Пользователь имел или имеет доступ к следующим продуктам', 'User is not found in database' => 'Пользователь не найден в базе данных', 'User notification' => 'Уведомление пользователя', 'User-Affiliate Relation Lifetime how long (in days) calculate commission for referred affiliate (default: 0 - forever)' => 'Время жизни связи Пользователь-Партнер как долго (в днях) вычислять комиссию для связанного партнера (по умолчанию: 0 - всегда)', 'Username Length' => 'Длина имени пользователя', 'Username or e-mail address' => 'Имя пользователя или адрес электронной почты', 'Users' => 'Клиенты', 'Users Report' => 'Отчет о пользователях', 'Utilities' => 'Утилиты', 'Valid license key are one-line string,starts with L and ends with X' => 'Корректный лицензионный ключ это строка, начинающаяся с L и заканчивающаяся на X', 'Value use % as wildcard mask' => 'Значение используйте % как знак подстановки', 'Value must be alpha-numeric' => 'Значение должно быть буквенно-цифровым', 'Value must be alphanumeric' => 'Значение должно быть буквенно-цифровым', 'Values must not be equal' => 'Значения должны быть различными', 'Verify E-Mail Address On Signup Page e-mail verification may be enabled for each signup form separately at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Проверить E-Mail адрес на странице регистрации проверка e-mail может быть включена отдельно для каждой формы регистрации в панели управления aMember -> Редактор форм -> Редактировать, нажмите "конфигурировать" в E-Mail модуле', 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Проверить новый E-Mail адрес на странице профиля проверка e-mail для формы профиля может быть включена в панели управления aMember -> Редактор форм -> Редактировать, нажать "конфигурировать" в E-Mail модуле', 'Version Info' => 'Версия', 'Video Player' => 'Видео плеер', 'View' => 'Просмотр', 'View Coupons' => 'Просмотреть Купоны', 'Void Commission' => 'Аннулировать комиссию', 'Voided' => 'Аннулирована', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Мы отправим запрос платежной системе или вы будете перенаправлены на платежную систему для отправки запроса возврата платежа', 'Weekly' => 'Еженедельно', 'Yes, assign category' => 'Да, назначить категорию', 'Yes, assign group' => 'Да, добавить группу', 'Yes, do not e-mail this customer for any reasons' => 'Да, не писать пользователю по любым причинам', 'Yes, locked' => 'Да, заблокирован', 'Yes, remove category' => 'Да, удалить категорию', 'Yes, remove group' => 'Да, убрать группу', 'You can assign some coupon codes to specific user. Only this user will be able to use this coupon.' => 'Вы можете закрепить некоторые купоны за клиентами. Только этот клиент сможет использовать купон.', 'You can download %sexample file%s.' => 'Вы можете скачать %sфайл примера%s.', 'You can import users from CSV file to aMember.' => 'Вы можете импортировать пользователей из CSV файла в aMember.', 'You can not delete your own account' => 'Вы не можете удалить вашу собственную учетную запись', 'You can not merge user with itself' => 'Вы не можете объединить пользователя с самим собой', 'You have currently choosed the following users for e-mail to:' => 'Вы уже выбрали следующих пользователей для отправки e-mail: ', 'You have generated %d demo products and %d demo customers' => 'Вы создали %d демо продуктов и %d демо покупателей', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'У вас есть лицензионные ключи от предидущих версий aMember, пожалуйста замените их последними, однострочными ключами', 'You have no permissions to perform requested operation' => 'У вас нет прав доступа для выполнения затребованной операции', 'Your Password enter your current password in order to edit admin record' => 'Ваш пароль введите ваш текущий пароль для редактирования админской записи', 'Zip Code' => 'Почтовый индекс', '[From] and [To] billing plans must not be equal' => '[From] и [To] планы платежей должны быть различными', 'aMember Database (default)' => 'aMember база данных (по-умолчанию)', 'aMember generate payout reports automatically according your settings %shere%s. Please note user without defined valid payout method will not be included to this payout report. They should define it first in his member area.' => 'aMember формирует отчеты по выплатам в автоматическом режиме в соответствии с вашими %sнастройками%s. Обратите внимание на то что комиссионные для партнеров, которые не указали способ выплаты, не будут включены в отчет. Для того чтобы получать выплаты они дожны указать сначало способ выплат.', 'aMember generate payout reports automatically according your settings below. Then you can use these reports to make real payout. You can find list of payout reports %shere%s. User without defined valid payout method will not be included to payout report until he fill payout method in member area.' => 'aMember формирует отчет о выплатах автоматически в соответствии с вашими настройками ниже. Затем вам необходимо использовать этот отчет чтобы сделать реальные выплаты. Список отчетов о выплатах можно нйти %sсдесь%s. Комиссионные партнера без выбранного способа выплат не будут включены в очередной отчет до тех пора пока он не выбирит его в пользовательском разделе.', 'aMember will look for templates in [application/default/views/signup/] folder and in theme\'s [signup/] folder and template filename must start with [signup]' => 'aMember будет искать шаблон в [application/default/views/signup/] папке и в папке тем [signup/] название файла шаблона должно начинаться с [signup]', 'access log table (used by admin only)' => 'лог-таблица доступов (используется только администратором)', 'add category' => 'добавить категорию', 'admin log table (used by admin only)' => 'лог-таблица администратора', 'after' => 'после', 'allow max' => 'предоставить max', 'browse' => 'просмотреть', 'change' => 'изменить', 'collapse details' => 'скрыть подробности', 'created at' => 'добавлен', 'days after expiration' => 'дней после истечения', 'days before expiration' => 'дней перед истечением', 'days before rebilling' => 'Дней перед повторным платежом', 'displaying records %d-%d from %d' => 'записи %d-%d из %d', 'do not show disabled products' => 'не показывать отключенные продукты', 'do not show pending invoices' => 'не показывать заказы находящиеся на рассмотрении', 'do not show refunded payments' => 'не показывать платежи по которым был сделан возврат', 'downloads within' => 'скачивать в течение', 'during subscription period' => 'в течение периода подписки', 'error_log table (used by admin only)' => 'таблица error_log (используется только администратором)', 'expand details' => 'показать подробности', 'first paid at' => 'первый платеж в ', 'hours' => 'часов', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'если код предоставлен, в электронном магазине продукты будут спрятаны и этот код будет обязателен для того чтобы увидеть эти продукты', 'if customer uses more than' => 'Если пользователь использует больше чем', 'if user enters wrong password' => 'если пользователь ввел неправильный пароль', 'immediately after subscription is started' => 'сразу после начала подписки', 'leave it empty in case of you want this item be available for all users' => 'оставьте пустым чтобы сделать доступным для всех пользователей', 'login, email or name' => 'логин, email или имя', 'must be a number in format 99 or 99.99' => 'должен быть номер в формате 99 или 99.99', 'must be equal or greather than 0' => 'должна быть не меньше нуля', 'must be equal or greather than 0.0' => 'должно быть не меньше нуля', 'new' => 'новый', 'next 30 days' => 'ближайшие 30 дней', 'on expiration day' => 'в день истечения', 'open in new window' => 'открыть в новом окне', 'or %smake access free%s' => 'или %sсделать доступ бесплатным%s', 'put website offline, making it available for admins only' => 'перевести сайт в режим обслуживания, сделав его доступным только для администраторов', 'refund' => 'возврат', 'replace' => 'заменить', 'seconds, he will be forced to wait until next try' => 'секунд, он будет ждать перед следующей попыткой ', 'sending' => 'отправка', 'sent successfully' => 'отправленно успешно', 'switch to show all records' => 'показать истекшие записи', 'switch to show only active records' => 'скрыть истекшие записи', 'this item is available for %sall registered customers%s. click to %smake this item protected%s %sor %smake this item available without login and registration%s %s' => 'этот элемент доступен для %s всех зарегистрированных покупателей%s. нажмите %s для того что бы сделать элемент защищенным %s %s или %sчто бы сделать элемент доступным без входа и регистрации %s %s', 'this item is available for %sall visitors (without log-in and registration) and for all members%s click to %smake this item protected%s or %smake log-in required%s ' => 'этот элемент доступен для %s всех посетителей (без входа и регистрации) и для всех пользователей%s нажмите %sдля того что бы сделать этот элемент защищенным%s или %sсделать вход обязательным%s ', 'times within' => 'раз в течение', 'version' => 'версия', 'void' => 'аннулировать', ); PK\urHndefault/language/admin/he.phpnu[ '%d ימים לאחר תאריך התפוגה', '%d days before expiration' => '%d ימים לפני פקיעה', '%d user(s) matches your search' => '%d משתמשים תאמו את החיפוש', '%d-th subscription day' => 'מנוי %d ימים', '%s Plugins' => '%s תוספים', '-- Please Select --' => '--אנא בחר--', '..th subscription day (starts from 2)' => 'מספר ימי המנוי (מתחיל מ -2)', 'Access Method' => 'שיטת גישה', 'Account Sharing Prevention' => 'מניעת שיתוף חשבון', 'Account Verification' => 'אימות חשבון', 'Add Chargeback' => 'הוסף חיוב חוזר', 'Add Invoice' => 'הוספת חשבונית', 'Add Payment' => 'הוסף תשלום', 'Add Payment Manually' => 'הוסף תשלום ידני', 'Add Refund' => 'הוסף זיכוי', 'Add Report to My Dashboard' => 'הוסף דוח ללוח', 'Add Subscription' => 'הוסף מנוי', 'Add User Fields' => 'הוספת שדות', 'Additional' => 'נוספים', 'Admin Accounts' => 'חשבונות מנהלים', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'כתובת דואל מנהל משמש לצורך שליחת התראות למנהל', 'Admin Free Subscription Notifications to admin once free signup is completed' => 'התראת מנוי חינם למנהל לאחר הרשמה למוצר שהוגדר כחינם', 'Admin Log' => 'יומן מנהל', 'Admin Pages Theme' => 'תבנית מנהל', 'Admin Payment Notifications to admin once payment is received' => 'התראות תשלום למנהל ברגע שתשלום מתקבל', 'Admin Settings' => 'אפשרויות מנהל', 'Admin notification' => 'התראת מנהל', 'Admin username must be alphanumeric in small caps' => 'שם משתמש חייב להיות אלפאנומרי באותיות קטנות', 'Administrator Login' => 'כניסת מנהל', 'Administrator has been removed, id [%d]' => 'מנהל הוסר, זיהוי [%d]', 'Advanced Settings' => 'הגדרות מתקדמות', 'Affiliate Commission' => 'עמלת תוכנית שותפים', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'זמן חיים עוגיית תכנית שותפים מספר הימים לשמירת המידע של המפנה', 'Affiliate Registration E-Mail' => 'מייל רישום', 'Affiliates Payout Day choose a day of month when payout is generated' => 'יום תשלומים לחברי תכנית השותפים בחר יום בחודש ליצירת התשלום', 'Affiliates Signup Type' => 'סוג הרשמה לתכנית שותפים', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'לאחר ביצוע שינויים כלשהם באזורים מוגנים htpasswd, בבקשה להפעיל [כלים-> צור מחדש בסיס נתונים] כדי לרענן קובץ htpasswd', 'All Subscription Period' => 'כל תקופת המנוי', 'All new users automatically become affiliates' => 'כל המשתמשים באופן אוטומטי יצורפו כחברים', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'מכסת אימיילים', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'מכסת מיילים בחר אם השרת שלך מגביל בהודעות מיילים יומיות', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'זכור תמיד', 'Amazon SES' => 'Amazon SES', 'Amazon SES Access Id' => 'זיהוי הרשאה Amazon SES', 'Amazon SES Secret Key' => 'מפתח סודי Amazon SES', 'American Date Format' => 'פורמט תאריך אמריקאי', 'Apply Tax?' => 'להוסיף מס?', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'החל על חוזר?', 'Approve' => 'מאושר', 'Assign Category' => 'הקצאת קטגוריה', 'At least one billing plan must be added' => 'לפחות תכנית תשלומים אחת חייבת להתקיים', 'Available' => 'זמין', 'Available Upgrades' => 'שדרוגים זמינים', 'Available for users from groups' => 'זמין לקבוצות משתמשים', 'Back to Dashboard' => 'חזור ללוח', 'Backup' => 'גיבוי', 'Banner' => 'באנר', 'Banners' => 'באנר', 'Billing' => 'חיובים', 'Blob (unlimited length binary data)' => 'כתם', 'Blocking IP/E-Mail' => 'חסום IP/ מייל', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'לא זמין עקב תחזוקה, נסו שוב בעוד כדקה', 'Browse' => 'דפדף', 'Browse Found Users' => 'סקור משתמשים שמצאו', 'Browse Users' => 'רשימת משתמשים', 'Bruteforce Protection' => 'הגנת Bruteforce ', 'Build Demo' => 'בנה דמו', 'Building demo records' => 'בונה רשומות דמו', 'Can not find user with such username' => 'לא נמצא משתמש עם שם המשתמש הנל', 'Can not find user with such username or email' => 'לא נמצא משתמש עם שם משתמש וכתובת מייל כפי שהוכנס', 'Can\'t be changed because your server have suhosin extension enabled' => 'לא ניתן לשנות עקב מגבלות שרת', 'Cancellations' => 'ביטולים', 'Change Configuration Settings' => 'שנה הגדרות תצורה', 'Change Paysystem' => 'שנה תשלומים', 'Charge Second Price Once' => 'חייב מחיר שני פעם אחת', 'Charge Second Price x Times' => 'חייב מחיר שני X פעמים', 'Check for beta version' => 'בדוק עבור גרסאות בטא', 'CheckBoxes' => 'CheckBoxes', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => 'בחר %1$sקובץ%2$s > %1$sשמור כ%2$s.', 'Choose Products and/or Product Categories that allows access' => 'בחר מוצרים ו / או קטגוריות מוצר המאפשר גישה', 'Choose Upgrades to Install' => 'בחר שדרוגים להתקנה', 'Choose action when locked %s used by customer during signup' => 'בחר פעולה כאשר נעול %s', 'Cleaning up' => 'מנקה', 'Cleanup' => 'מנקה', 'Clear' => 'נקה', 'Clear Access Log' => 'נקה יומני רישום', 'Click to Expand' => 'לחץ להרחבה', 'Code Length generated coupon code length between 4 and 32' => 'אורך קוד אורך קוד הקופון בין 4 ל - 32', 'Collapse Menu' => 'הסתר תפריט', 'Comma' => 'פסיק', 'Commission earned' => 'רווח עמלות', 'Commission for First Payment calculated for first payment in each invoice' => 'תשלום עמלה ראשנה', 'Commission for Free Signup calculated for first customer invoice only' => 'עמלה עבור הרשמת חינם', 'Commission for Rebills' => 'עמלה עבור חיוב מחדש', 'Conditions' => 'תנאים', 'Configured License Keys' => 'רשיונות מוגדרים', 'Copy' => 'העתק', 'Copy Upgrades' => 'העתק שדרוג', 'Copy from another language' => 'העתק משפה אחרת', 'Core' => 'ליבה', 'Could not fetch upgrades list from remote server. %sTry again%' => 'לא יכול להביא את רשימת שדרוגים משרת מרוחק. %sנסה שוב%', 'Could not fetch upgrades list. Connection error [%s]' => 'לא יכול להביא רשימת עדכונים מהשרת, שגיאת התחברות [%s]', 'Coupons' => 'קופונים', 'Coupons Batches' => 'סדרות קופונים', 'Coupons Count how many coupons need to be generated' => 'מספר קופונים כמה קופונים לייצר?', 'Create Folder' => 'צור ספריה', 'Create Session Key' => 'צור מפתח מושב', 'Create ticket as' => 'צור קריאת שירות כ', 'Custom Commission Rules added' => 'חוק מותאם אישית נוסף', 'Custom HTML' => 'תוכן HTML מותאם אישית', 'Custom Signup Form Title keep empty to use default title' => 'כותרת מותאמת אישית לטופס הרשמה', 'Customer' => 'לקוח', 'Customize Dashboard' => 'התאם אישית לוח', 'Daily' => 'יומי', 'Date Time' => 'תאריך זמן', 'Date to Purge all records prior to this date will be removed from selected tables' => 'תאריך לניקוי כל הרשומות הקודמות לתאריך זה ימחקו', 'Dates date range when coupon can be used' => 'תאריכים טווח תאריכים עבור זמינות הקופונים', 'Dates can be in the folowing formats' => 'תאריכים אפשרים בפורמטים הבאים', 'Days to Send' => 'ימים לשליחה', 'Default - user clicks a link to become affiliate' => 'ברירת מחדל- משתמש לוחץ על קישור על מנת להפוך לחבר בתכנית השותפים', 'Default Billing Plan' => 'תכנית חיוב ברירת מחדל', 'Default Commission' => 'עמלת ברירת מחדל', 'Default Locale' => 'שפת ברירת מחדל', 'Default Signup' => 'הרשמת ברירת מחדל', 'Default for Members' => 'ברירת מחדל לחברים', 'Default value for field (that is default value for inputs, not SQL DEFAULT)' => 'ערך ברירת מחדל', 'Delete Old Records' => 'מחק רשומות ישנות', 'Delete payment and access record' => 'מחק רשומת תשלום', 'Delimiter' => 'מפריד', 'Demo History' => 'היסטורית נתוני דמו', 'Description displayed to visitors on order page below the title' => 'תאור מוצג למבקרים בעמוד הרכישה מתחת לכותרת', 'Details' => 'פרטים', 'Die and show ugly error message' => 'הצג הודעה לא נחמדה', 'Disable auto-locking for this customer' => 'בטל נעילה אוטומטית ללקוח זה', 'Disallow new Signups by %s' => 'אל תאפשר הרשמה לפי %s', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'איסור הזמנת מוצר אם ללקוח יש מנוי ל', 'Display Language Choice' => 'הצג בחירת שפה', 'Display error message' => 'הצג הודעת שגיאה', 'Do not generate products use existing products for demo records' => 'אל תייצר מוצרים השתמש במוצרים קיימים', 'Do you really want to refund payment' => 'אתה בטוח שברצונך לזכות תשלום?', 'Do you really want to stop this subscription?' => 'האם אתה בטוח שאתה רוצה לבטל מנוי זה?', 'Documentation' => 'תיעוד', 'Download Upgrades' => 'הורד שדרוגים', 'Duration:' => 'זמן:', 'E-Mail Address to Send to' => 'כתובת דואל לשליחה', 'E-Mail Backup Address' => 'כתובת דואל למשלוח גיבוי', 'E-Mail Commission to Admin' => 'שלח מייל עמלות למנהל', 'E-Mail Commission to Affiliate' => 'שלח מייל עמלות לחבר', 'E-Mail Database Backup' => 'שלח כהודעת דואל גיבוי בסיס הנתונים', 'E-Mail Queue' => 'תור מייל', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'שם שולח הדואל יוצג ללקוח בזמן שליחת דואל', 'E-Mail Sending' => 'שולח מיילים', 'E-Mail Type' => 'סוג מייל', 'E-Mail Users' => 'שלח מייל למשתמשים', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'מיילים נשלחו בהצלחה ל %s לקוחות. מספר סידורי הוא %s', 'E-Mail sending started' => 'שליחת מיילים התחילה', 'E-Mails History' => 'היסטוריית מיילים', 'E-Mails by Admin Request' => 'הודעת דואל לבקשת המנהל', 'E-Mails by User Request' => 'הודעת דואל לבקשת הלקוח', 'Edit Custom Commission Rules' => 'ערוך חוק עמלה מותאם אישית', 'Edit Groups' => 'ערוך קבוצה', 'Email Backup Frequency' => 'תדירות שליחת גיבוי בסיס הנתונים', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'שיטת שליחת הודעות דואל לא לשנות במידה ועובד', 'Email Sent' => 'מילים שנשלחו', 'Email address is required field.' => 'כתובת מייל נדרשת', 'Enable plugins if necessary' => 'אפשר תוספים במידת הצורך', 'Enter Maintenance Mode' => 'מצב תחזוקה', 'Enter admin password for confirmation' => 'הזן את סיסמת מנהל לאישור', 'Error Log' => 'יומן שגיאות', 'Error/Debug Log' => 'לוג שגיאות', 'Errors' => 'שגיאות', 'Errors:' => 'שגיאות:', 'European Date Format' => 'פורמט תאריך אירופי', 'Every %s' => 'כל %s', 'Exchange Rate' => 'שער חליפין', 'Exchange Rate enter cost of 1 (one) %s' => 'שער חליפין הכנס ערך עבור 1 %s', 'Field Name' => 'שם השדה', 'Field Title' => 'כותרת שדה', 'Field Values' => 'ערך השדה', 'File (max filesize %s)' => 'קובץ גודל מקסימלי %s', 'File is required' => 'קובץ נדרש', 'Filter by Category' => 'סנן לפי קטגוריה', 'Filter by String' => 'סנן לפי מחרוזת', 'Filter by name or description' => 'סנן לפי שם או תיאור', 'Filter by string or by invoice#/member#' => 'סנן לפי מחרוזת או לפי מספר חשבונית/לקוח', 'First Period' => 'תקופה ראשונה', 'First Price' => 'מחיר ראשון', 'First Price price of first period of subscription' => 'המחיר ראשון מחיר של התקופה הראשונה של מנוי', 'First Tax' => 'מס', 'First Total' => 'סכום כולל', 'First and Last Name' => 'שם מלא', 'First available protected url' => 'המוצר הזמין הראשון', 'First visited' => 'ביקור ראשוני', 'Fix aMember Pro License Key' => 'תקן מפתח רישיון Pro aMember', 'Fixed Url' => 'URL קבוע', 'Fixed date' => 'תאריכים קבועים', 'FlowPlayer License Key you may get your key in %smembers area%s' => 'רישיון FlowPlayer ניתן להשיג את הרשיון%s באזור החברים%s', 'Folder URL' => 'מיקום התקיות', 'Form Type' => 'סוג טופס', 'Forms Editor' => 'עורך הטפסים', 'Future' => 'עתידי', 'General' => 'כללי', 'General Settings' => 'הגדרות כלליות', 'Generate' => 'יצר', 'Generate Payout Manually' => 'יצירת תשלום ידנית', 'Generate Report' => 'יצר דוח', 'Generated' => 'נוצר', 'Generation of demo data was terminated while processing. Not all records were created.' => 'הפעולה הופסקה באמצע, לא כל הרשומות הוכנסו', 'Get Available Upgrades List' => 'קבל רשימת שדרוגים זמינים', 'Get New Password' => 'קבל סיסמא חדשה', 'Global' => 'גלובלי', 'Graph Bar' => 'גרף בר', 'Graph Line' => 'גרף קווים', 'Help & Support' => 'עזרה/תמיכה', 'Hostname' => 'שם מארח', 'Hour' => 'שעה', 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database' => 'אני מבין ששדרוג עלול לדרוס את קבצי PHP המותאים אישית שלי, ביצעתי גיבוי', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'הערה חשובה: זה לא מגן על תכנים. אם מישהו יודע מהי כתובת קישור, הוא יוכל לפתוח קישור בלי בעיה. זה פשוט שולט בקישורים הנוספים שהלקוח יראה', 'IP' => 'IP', 'IP within' => 'IP בתוך', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'מעבר משיטת תשלום אחת לשניה, אפשרי במידה ופרטי האשראי שמורים במערכת', 'Image' => 'תמונה', 'Import Finished' => 'תהליך היבוא הסתיים', 'Import Users' => 'ייבוא משתמשים', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'בדיאלוג ייצוא הקבצים בחר את האפשרות שבה אתה מעוניין ולחץ %1$sOK%2$s.', 'In the File name box, type a name for the file.' => 'הכנס שם קובץ בתיבה המתאימה ', 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.' => 'ברשימת סוגי הקובץ, בחר %1$sText CSV%2$s ולחץ %1$sSave%2$s', 'Insert' => 'הכנס', 'Install Updates' => 'התקן שדרוגים', 'Integer field (only numbers)' => 'שדה מספרי (רק מספרים)', 'Integration plugins' => 'תוספי אינטגרציה', 'Internal PHP mail() function (default)' => 'פונקצית PHP MAIL (ברירת מחדל)', 'Invoice Log' => 'יומן חשבוניות', 'Invoices' => 'חשבוניות', 'Invoices Per User' => 'חשבוניות פר לקוח', 'Is Affiliate?' => 'האם שותף?', 'Is Approved' => 'מאושר', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'מבוטל? לבטל הזמנת מוצר, להסתיר אותו מהרשמה וחידוש', 'It is required to setup a cron job to trigger backup generation' => 'הכרחי להפעיל cron על מנל ליצר גיבויים', 'JavaScript Code' => 'קוד JavaScript ', 'Languages' => 'שפה', 'Last %s Customers' => 'מספר %s לקוחות אחרונים', 'Last %s Helpdesk Messages' => '%s קריאות שרות אחרונות', 'Last Users List' => 'רשימת משתמשים אחרונה', 'Last available protected url' => 'המוצר הזמין האחרון', 'Last existing subscription date of this product' => 'תאריך המינוי האחרון של מוצר זה', 'Last expiration date in the renewal group' => 'תאריך פקיעה אחרון בקבוצת המחדשים', 'Last login' => 'כניסה אחרונה', 'Length of admin password must be from %d to %d' => 'אורך סיסמת מנהל חייבת להיות בין %d ל %d', 'Length of username must be from %d to %d' => 'אורך שם המשתמש חייב להיות בין %d ל %d', 'Light Boxes' => 'Light Boxes', 'Lightbox Main Image' => 'Lightbox תמונה ראשית', 'Lightbox Thumbnail Image' => 'תמונה ממוזערת', 'Limit Downloads Count' => 'מכסת הורדות', 'Lines Proccessed:' => 'מספר השורות שעובדו:', 'Lines Skipped:' => 'שורות שדולגו:', 'Lines Success:' => 'שורות שיבואו בהצלחה:', 'Link to reset your password was sent to your Email.' => 'קישור לאיפוס הסיסמא נשלח למייל שהזנת', 'Lock' => 'נעול', 'Locked Value' => 'ערכים נעולים', 'Log Outgoing E-Mail Messages for ... days' => 'רשום ביומן הודעות דואל ל... ימים', 'Log in' => 'היכנס', 'Logged in as %s' => 'מחובר כ %s', 'Login Page' => 'דף כניסה', 'Logs' => 'לוגים', 'Lookup' => 'בדיקה', 'Lost your password?' => 'סיסמתך אבדה?', 'Mail' => 'מייל', 'Maintenance Mode' => 'מצב תחזוקה', 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s' => 'מצב תחזוקה פעיל כעת, רק מנהלים מחוברים יכולים להכנס %sבטל%s', 'Manage Product Upgrade Paths' => 'נהל נתיבים לשדרוג מוצרים', 'Manage Products' => 'נהל מוצרים', 'Manually Added' => 'הוזן באופן ידני', 'Mark NOT Paid' => 'סמן כלא שולם', 'Mark Paid' => 'סמן כשולם', 'Mass Subscribe' => 'הוסף מספר מנויים', 'Membership' => 'חברות', 'Membership Info Page' => 'עמוד מידע חברות', 'Merge' => 'מזג', 'Miscellaneous' => 'שונות', 'Monthly' => 'חודשי', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'כותרת הזמנה מרובה יוצג כאשר לקוח מזמין יותר ממוצר אחד', 'Name of Preset' => 'שם קבוע מראש', 'New Autoresponder' => 'תגובה אוטומטית חדשה', 'New Expiration E-Mail' => 'הודעת דואל פקיעה חדשה', 'New Modules Available' => 'מודלים חדשים זמינים', 'New Rewrite' => 'שכתוב חדש', 'New password has been e-mailed to your e-mail address' => 'סיסמא חדשה נשלחה למייל שהזנת', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'לא נשמרו כרטיסי אשראי עבור לקוח זה , %sהוסף כרטיסי %sאשראי ', 'No Invoices Found' => 'לא נמצאה חשבונית', 'No Tax' => 'אין מס', 'No Updates Available' => 'אין עדכונים זמינים', 'No more charges' => 'לא עוד חיובים', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'נראה שהקובץ ריק, בחר קובץ אחר', 'No search name passed' => 'לא הועבר שם לחיפוש', 'No upgrades to install' => 'אין שדרוגים זמינים', 'Not Approved' => 'לא אושר', 'Not Approved Users' => 'משתמשים לא מאושרים', 'Not Confirmed Users' => 'משתמשים לא מאושרים', 'Not-SQL field (default)' => 'לא SQL , ברירת מחדל', 'Number of Users to display' => 'מספר המשתמשים להצגה', 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.' => 'מספר החשבוניות הדורשות אישור : %d. %sלחץ כאן%s לסקירה', 'Number of users who require approval: %d. %sClick here%s to review these users.' => 'מספר המשתמש הנדרשים אישור : %d. %sלחץ כאן%s לסקירה ', 'Numeric field' => 'שדה נומרי', 'OTO - Offer to purchase additional product (with optional discount)' => 'הצע קנית מוצרים נוספים בהנחה', 'One field can be assigned to one column only, you assigned following fields to several columns: ' => 'תחום אחד ניתן להקצות לעמודה אחת בלבד, שהקצית השדות הבאים במספר עמודות:', 'One field can be assigned to one column only.' => 'שדה אחד יכול להצות לעמודה אחת', 'Only admin can enable user as an affiliate' => 'רק המנהל יכול לאשר חבר בתכנית השותפים', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'כתובת דואל יוצאת מוצג ללקוח בזמן קבלת מייל', 'Overwrite User if Exist User with Same Login' => 'דרוס את המשתמש אם קיים משתמש עם כניסה זהה', 'PDF Invoice' => 'חשבונית PDF', 'Paid' => 'שולם', 'Password Length' => 'אורך סיסמא', 'Password changed' => 'הסיסמא שונתה', 'Password must not be equal to username' => 'סיסמא חייבת להיות שונה מהשם משתמש', 'Passwords must be the same' => 'סיסמאות לא תואמות', 'Path to Folder' => 'נתיב לתיקייה', 'Path/URL' => 'מיקום/URL', 'Payment Receipt' => 'קבלה על תשלום', 'Payment date' => 'תאריך תשלום', 'Payment has been successfully refunded' => 'תשלום זוכה בהצלחה', 'Payout %d Details' => 'פרטי %d תשלום', 'Payout Details' => 'פרטי תשלום', 'Paysystem' => 'מערכת תשלומים', 'Pending Invoice Notification Rules' => 'הגדרות התראות חשבוניות בהמתנה', 'Permissions' => 'הרשאות', 'Please assign the following fields: ' => 'אנא להקצות את השדות הבאים:', 'Please choose another field name. This name is already used' => 'אנא בחר שם שונה', 'Please enter valid e-mail address' => 'אנא הכנס כתובת חוקית', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'הזן את שם המשתמש או הדוא"ל שלך תקבל קישור ליצירה סיסמא חדשה באמצעות דואר אלקטרוני.', 'Please run %sRebuild Db%s to update status for imported customers' => 'אנא b%sבנה מחדשb%s את בסיס הנתונים על מנת לעדכן את הלקוחות שיבואו', 'Please select date before today' => 'אנא בחר תאריך לפני היום', 'Please wait' => 'אנא המתן', 'Plugins' => 'תוספים', 'Product Availability' => 'זמינות מוצר', 'Product Category' => 'קטגורית מוצר', 'Product Upgrades' => 'שדרוגי מוצר', 'Products Per Invoice' => 'מוצרים פר חשבונית', 'Protect Content' => 'הגן על תוכן', 'Protection Method' => 'שיטת הגנה', 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty' => 'כמות ברירת מחדל -1, בדרך כלל אין צורך לשנות מחיר ראשון ושני הינם הסכום הכולל ', 'Quit Maintenance Mode' => 'הפסק מצב תחזוקה', 'RadioButtons' => 'RadioButtons', 'Rebill' => 'חייב שנית', 'Rebill Second Price until cancelled' => 'חייב מחיר שני עד הביטול', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'מספר חיובים שנית זהו מספר התשלומים עבור המחיר השני', 'Rebuild Db' => 'בנה בסיס נתונים מחדש', 'Receipt' => 'קבלה', 'Receipt#' => '#קבלה', 'Recipients' => 'קבלות', 'Records Deleted Sucessfully' => 'רשומה נמחקה בהצלחה', 'Redirect URL' => 'הפנה URL', 'Referrer' => 'מפנה', 'Refund Payment' => 'זיכוי תשלום', 'Remember Login remember username/password in cookies' => 'זכור סיסמא שמור סיסמא/שם משתמש בעוגייה', 'Remind Password to Admin' => 'תזכורת סיסמא למנהל', 'Remind Password to Customer' => 'הזכר סיסמא ללקוח', 'Remove Category' => 'הסר קטגוריה', 'Remove From Dashboard' => 'הסר מהלוח', 'Repeat Action Handling' => 'חזור על פעולת טיפול', 'Replace Product' => 'החלף מוצר', 'Report Bugs' => 'דווח על באגים', 'Reports' => 'דוחות', 'Reseller Packages' => 'חבילת משווק', 'Resend' => 'שלח שוב', 'Resend Signup E-Mail' => 'שלב שוב הודעת הרשמה', 'Resource' => 'משאב', 'Restore' => 'שחזור', 'Retreive Access Parameters if necessary' => 'פרמטרי גישה לאחזר במידת צורך', 'Return to Payouts List' => 'חזור לרשימת תשלומים', 'Root URL root script URL, usually %s' => 'כתובת בסיס בדרך כלל %s', 'Root Url and License Keys' => 'כתובת בסיס ורישיון', 'Run Reports' => 'הרץ דוחות', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'SMTP Hostname', 'SMTP Hostname is required if you have enabled SMTP method' => 'SMTP Hostname הכרחי במידה ואפשרת SMTP', 'SMTP Password' => 'סיסמא SMTP', 'SMTP Port' => 'פורט SMTP', 'SMTP Security' => 'SMTP Security', 'SMTP Username' => 'שם משתמש SMTP', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (לא זמין עבור בחירה מרובה)', 'SQL Date Format' => 'פורמט תאריך SQL', 'Sales Statistic' => 'סטטיסטיקת מכירות', 'Save This Search' => 'שמור חיפוש', 'Saved Credit Cards' => 'כרטיסי אשראי שמורים', 'Saved Reports' => 'דוחות שמורים', 'Saved Search' => 'חיפושים שמורים', 'Second Period' => 'תקופה שנייה', 'Second Price' => 'מחיר שני', 'Second Price price that must be billed for second and the following periods of subscription' => 'מחיר שני מחיר שיש לחייב עבור התקופה השנייה ואחריה', 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form' => 'קוד סודי', 'Secure Root URL secure URL, usually %s' => 'כתובת בסיס מאובטחת בדרך כלל %s', 'Select (Multiple Values)' => 'בחירה (בחירה מרובה)', 'Select (Single Value)' => 'בחירה (ערך יחיד)', 'Select a plugin' => 'בחר תוסף', 'Select option' => 'בחר אפשרות', 'Selected for E-Mailing' => 'נבחרו עבור מיילים', 'Semicolon' => 'נקודה ופסיק', 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member' => 'שלח התראת ביטול למנהל', 'Send E-Mail Message' => 'שלח הודעת מייל', 'Send E-Mail Messages' => 'שלח הודעת דואל', 'Send E-Mail if customer has subscription (required)' => 'שלח בדואר אלקטרוני אם ללקוח יש מנוי (חובה)', 'Send E-Mail only if customer has no subscription (optional)' => 'שלח הודעת דואל רק במידה וללקוח אין אף מנוי(אופציונלי)', 'Send New E-Mail' => 'שלח מייל חדש', 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket' => 'שלח התראה בנוגע קריאות שירות חדשות למנהל', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'שלח התראה בנוגע להודעות חדשות ללקוח בכל פעם שמנהל עונה', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'שלח דואל הרשמה לאחר שהלקוח השלים את תהליך ההרשמה(לפני התשלום)', 'Send Registration E-Mail to this user' => 'שלח מייל הרשמה למשתמש זה', 'Send Signup E-Mail once FIRST subscripton is completed' => 'שלח הודעת דואל הרשמה לאחר השלמת המנוי הראשון', 'Send Test E-Mail' => 'שלח דואל בדיקה', 'Send reports to my email' => 'שלח דוחות למייל מנהל', 'Sender' => 'שולח', 'Sending Test E-Mail...' => 'שולח דואל בדיקה...', 'Sending e-mail (sent to %d from %d)' => 'שולח מיילים ( נשלח ל %d מתוך %d)', 'Session Storage' => 'Session Storage', 'Setup/Configuration' => 'הגדרות', 'Signup Form Configuration' => 'הגדרות טופס הרשמה', 'Signup Info' => 'מידע הרשמה', 'Signup Messages' => 'הודעות הרשמה', 'Site is temporarily disabled for maintenance' => 'אתר אינו פעיל זמנית לצורך התחזוקה', 'Size' => 'גודל', 'Size of input field' => 'גודל השדה', 'Skip' => 'דלג', 'Skip Line if Exist User with Same Login' => 'דלג שורה במידה והמתמש קיים', 'Sort' => 'מיון', 'Sort Order' => 'סדר מיון', 'Source' => 'מקור', 'Space' => 'רווח', 'Standard PHP Sessions' => 'הפעלות PHP סטנדרטיות', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'חישוב תאריך התחלה הגדרות עבור חישוב תארך התחלה', 'Start and Expiration Dates' => 'תאריך התחלה ופקיעה', 'Started' => 'התחלה', 'Step %d of %d' => 'שלב %d מתוך %d', 'Stop Recurring' => 'הפסק מחזוריות', 'String' => 'מחרוזת', 'Submitting...' => 'שולח', 'Subscription' => 'מנוי', 'Super Admin' => 'סופר אדמין', 'Surcharge' => 'תשלום נוסף', 'Table' => 'טבלאות', 'Tabulation' => 'לווח', 'Template alternative template for signup page' => 'תבנית תבנית משנית לדף הרשמה', 'Terms Text automatically calculated if empty' => 'טקסט תנאים מחושב באופן אוטומטי אם ריק', 'Test E-Mail Settings' => 'כתובת מייל לבדיקה', 'Text' => 'טקסט', 'Text (unlimited length string/data)' => 'טקסט( אין הגבלה)', 'Text Links' => 'קישורי טקסט', 'TextArea' => 'TextArea', 'The password is entered incorrectly' => 'הסיסמה לא חוקית', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'תבנית הדואל לא מוגדרת בשפה זאת לחץ העתק על מנת להשתמש בשפה האנגלית או דלג', 'This field is requred' => 'שדה זה נחוץ', 'Ticket#' => '#קריאת שרות', 'Time' => 'זמן', 'Title displayed to customers' => 'כותרת מוצג ללקוחות', 'Title of Report for your Reference' => 'כותרת דוח לעיונך', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'להזמנת מוצר זה ללקוח חייב להיות כאשר לקוח מזמין מוצר זה ,יבדק האם ללקוח יש את המוצר הנבחר', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'שמירת טבלאות כקובץ CSV או OpenOffice', 'Total Paid' => 'סכום כולל ששולם', 'Total to Pay' => 'סכום כולל לתשלום', 'Trace' => 'לעקוב', 'Traditional .htpasswd' => 'מסורתי. Htpasswd', 'Transactions Log' => 'יומן עסקות', 'URL must be specified without trailing slash' => 'חייב להיות מוגדר ללא לוכסן', 'URL must start from %s or %s' => 'כתובת חייבת להתחיל מ %s או %s', 'Unlock' => 'פתח', 'Unpack Upgrades' => 'חלץ שדרוג', 'Update Error' => 'שגיאת עדכון', 'Update License Information' => 'עדכן רשיונות', 'Update User if Exist User with Same Login' => 'עדכן משתמש אם קיים משתמש עם אותו כניסה', 'Upgrade' => 'שדרג', 'Upgrade Database' => 'שדרג בסיס נתונים', 'Upgrade Download Problem' => 'בעיה בהורדת העדכון', 'Upgrade Finished' => 'השדרוג הושלם', 'Upgrade From' => 'שדרוג מ', 'Upgrade To' => 'שדרג ל', 'Upload' => 'העלאה', 'Upsell - Replace Product from [Conditions] field' => 'החלף מוצר משדה [Conditions]', 'Upsell Configuration' => 'אישור Upsell ', 'Upsell Paths' => 'נתיב Upsell ', 'Use Custom Settings' => 'השתמש בהגדרות מותאמות אישית', 'Use E-Mail Throttle Queue' => 'השתמש תור מצערת דואר אלקטרוני', 'Use External Cron' => 'השתמש ב Cron החיצוני', 'Use Global Settings' => 'השתמש בהגדרות גלובליות', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'כמה פעמים קופון אחד זמין עבור אותו לקוח', 'User Id' => 'זיהוי משתמש', 'User Invoices' => 'חשבוניות משתמש', 'User Pages Theme' => 'תבנית דף משתמש', 'User currently has access to the following products' => 'למשתמש יש גישה למוצרים הבאים', 'User had access to the following products' => 'למשתמש יש גישה למוצרים הבאים', 'User is not found in database' => 'שם משתמש לא נמצא בבסיס הנתונים', 'User notification' => 'התראת לקוחות', 'Username or e-mail address' => 'שם משתמש או כתובת מייל', 'Users' => 'משתמשים', 'Users Report' => 'דוח משתמשים', 'VAT' => 'מעמ', 'Valid license key are one-line string,starts with L and ends with X' => 'מפתח רישיון תקף הוא מחרוזת בת שורה אחת, מתחיל עם L ומסתיים עם X', 'Value use % as wildcard mask' => 'ערך השתמש ב % כמסכה כללית', 'Value must be alpha-numeric' => 'ערך חייב להיות אלפא נומרי', 'Value must be alphanumeric' => 'ערך חייב להיות אלפאנומרי', 'Values must not be equal' => 'הערכים חייבים להיות שווים', 'Version Info' => 'אודות הגרסה', 'Video Player' => 'נגן ווידאו', 'View' => 'צפה', 'View Coupons' => 'הצג קופונים', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'אנו נבצע את ההחזר או שתופנה למערכת התשלום ', 'Weekly' => 'שבועי', 'Yes, assign category' => 'כן, הקצה לקטגוריה', 'Yes, do not e-mail this customer for any reasons' => 'כן, אל תשלח הודעות דואל ללקוח זה', 'Yes, locked' => 'כן, נעל', 'Yes, remove category' => 'כן, הסר קטגוריה', 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.' => 'ניתן %sלשמור%s דוח זה לסקירה עתידית, ניתן להוסיף ללוח או לשלוח כהודעת דואל', 'You can download %sexample file%s.' => ' %sexample file%s.', 'You can import users from CSV file to aMember.' => 'ניתן ליבא משתמשים מקובץ CSV', 'You can not merge user with itself' => 'אינך יכול למזג משתמש עם עצמו', 'You have currently choosed the following users for e-mail to:' => 'נבחרו המשתמשים הבאים לשליחת דואל', 'You have generated %d demo products and %d demo customers' => 'נוצרו %d מוצרי דמו ו %d לקוחות דמו', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'יש לך מפתחות רישיון מהגרסות הישנות של aMember, אנא החלף אותם עם החדשה, מפתחות בשורה אחת', 'You have no permissions to perform requested operation' => 'אין לך הרשאות לביצוע פעולה זאת', 'Your Password enter your current password in order to edit admin record' => 'הסיסמא שלך הכנס את סיסמתך הנוכחית על מנת לערוך חשבון מנהל', '[From] and [To] billing plans must not be equal' => '[מ] ו [עד] תכניות תשלום חייבות להיות שונות', 'aMember Database (default)' => 'בסיס נתונים aMember ', 'access log table (used by admin only)' => 'טבלאות יומני רישום( למנהל בלבד)', 'admin log table (used by admin only)' => 'טבלת יומני מנהל', 'after' => 'אחרי', 'allow max' => 'לאפשר מקסימום', 'change' => 'שנה', 'collapse details' => 'הסתר פרטים', 'days after expiration' => 'ימים לאחר פקיעה', 'days before expiration' => 'ימים לפני הפקיעה', 'displaying records %d-%d from %d' => 'מציג רשומות %d-%d מ %d', 'do not show disabled products' => 'לא להציג מוצרים מבוטלים', 'do not show pending invoices' => 'אל תציג חשבוניות בהמתנה לאישור', 'downloads within' => 'הורדות בתוך', 'during subscription period' => 'במהלך תקופת המנוי', 'error_log table (used by admin only)' => 'טבלת יומני שגיאה', 'expand details' => 'הרחב פרטים', 'first paid at' => 'תשלום ראשון ב', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'אם הקוד מוצג, נדרג להקלידו בעגלת הקניות על מנת לצפות במוצרים', 'if customer uses more than' => 'אם לקוח משתמש יותר מ', 'if user enters wrong password' => 'אם משתמש הכניס סיסמא שגויה', 'leave it empty in case of you want this item be available for all users' => 'השאר ריק במידה ואתה מעוניין בזמינות לכל המשתמשים', 'login, email or name' => 'כניסה, מייל או שם', 'must be a number in format 99 or 99.99' => 'חייב להיות מספר בפורמט 99 או 99.99', 'must be equal or greather than 0' => 'חייב להיות גדול או שווה ל 0', 'must be equal or greather than 0.0' => 'חייב להיות גדול או שווה ל-0', 'on expiration day' => 'ביום הפקיעה', 'open in new window' => 'פתח בחלון חדש', 'or %smake access free%s' => 'או סמן %sכגישה חינם%s', 'put website offline, making it available for admins only' => 'הגדר אתר כלא מקוון, רק מנהלים יכולים לגשת', 'sending' => 'שולח', 'sent successfully' => 'נשלח בהצלחה', 'switch to show all records' => 'הצג את כל הרשומות', 'switch to show only active records' => 'הראה רשומות פעילות בלבד', 'times within' => 'פעמים, בתוך', 'version' => 'גרסא', ); PK\0""default/language/admin/default.phpnu[ ' at ', ' day' => ' day', ' hour' => ' hour', '"Call Home" functionality - every .. days software will periodically contact your site to check activation and license status enter 0 to disable' => '"Call Home" functionality - every .. days software will periodically contact your site to check activation and license status enter 0 to disable', '# of users' => '# of users', '%d days after expiration' => '%d days after expiration', '%d days after payment' => '%d days after payment', '%d days before expiration' => '%d days before expiration', '%d days in advance of recurring payment' => '%d days in advance of recurring payment', '%d products…' => '%d products…', '%d user(s) matches your search' => '%d user(s) matches your search', '%d-Tier' => '%d-Tier', '%d-th subscription day' => '%d-th subscription day', '%s Plugins' => '%s Plugins', '%sEnable%s and %sconfigure%s external cron if you are using E-Mail Throttle Queue' => '%sEnable%s and %sconfigure%s external cron if you are using E-Mail Throttle Queue', '%sEnable%s and %sconfigure%s external cron if you are using Periodic E-Mails (Autoresponder/Expiration/Pending Notifications)' => '%sEnable%s and %sconfigure%s external cron if you are using Periodic E-Mails (Autoresponder/Expiration/Pending Notifications)', '-- Filter by Product --' => '-- Filter by Product --', '-- Please Select --' => '-- Please Select --', '-- Without A Category --' => '-- Without A Category --', '... %d more rows found ...' => '... %d more rows found ...', '..th subscription day (starts from 2)' => '..th subscription day (starts from 2)', '100% discount' => '100% discount', '

      For each item in purchase, aMember will look through all rules, from top to bottom. If it finds a matching multiplier, it will be remembered. If it finds a matching custom rule, it takes commission rates from it. If no matching custom rule was found, it uses "Default" commission settings.

      For n-tier affiliates, no rules are used, you can just define percentage of commission earned by previous level.

      ' => '

      For each item in purchase, aMember will look through all rules, from top to bottom. If it finds a matching multiplier, it will be remembered. If it finds a matching custom rule, it takes commission rates from it. If no matching custom rule was found, it uses "Default" commission settings.

      For n-tier affiliates, no rules are used, you can just define percentage of commission earned by previous level.

      ', '

      Message has been sent successfully. Please wait 2 minutes and check the mailbox %s.
      There must be a message with subject [Test E-Mail]. Do not forget to check Spam folder.

      If the message does not arrive shortly, contact your webhosting support and ask them to find
      in mail.log what happened with a message sent from %s to %s at %s

      ' => '

      Message has been sent successfully. Please wait 2 minutes and check the mailbox %s.
      There must be a message with subject [Test E-Mail]. Do not forget to check Spam folder.

      If the message does not arrive shortly, contact your webhosting support and ask them to find
      in mail.log what happened with a message sent from %s to %s at %s

      ', 'A/B Signup Campaign' => 'A/B Signup Campaign', 'ACTIVE %s' => 'ACTIVE %s', 'ACTIVE category %s' => 'ACTIVE category %s', 'API Keys' => 'API Keys', 'Accepted Payout Methods' => 'Accepted Payout Methods', 'Access Method' => 'Access Method', 'Access Period' => 'Access Period', 'Access Permissions this category will be available only for users with proper access permission' => 'Access Permissions this category will be available only for users with proper access permission', 'Access Permissions this field will be removed from form if access permission does not match and user will not be able to update this field' => 'Access Permissions this field will be removed from form if access permission does not match and user will not be able to update this field', 'Account Sharing Prevention' => 'Account Sharing Prevention', 'Account Verification' => 'Account Verification', 'Action' => 'Action', 'Activations' => 'Activations', 'Active (free)' => 'Active (free)', 'Add & Checkout' => 'Add & Checkout', 'Add & Go to Basket' => 'Add & Go to Basket', 'Add Access Manually' => 'Add Access Manually', 'Add Chargeback' => 'Add Chargeback', 'Add Child' => 'Add Child', 'Add Invoice' => 'Add Invoice', 'Add Invoice and Payment/Access Manually' => 'Add Invoice and Payment/Access Manually', 'Add Option' => 'Add Option', 'Add Payment' => 'Add Payment', 'Add Payment Manually' => 'Add Payment Manually', 'Add Pending Invoice and Send Link to Pay It to Customer' => 'Add Pending Invoice and Send Link to Pay It to Customer', 'Add Refund' => 'Add Refund', 'Add Report to My Dashboard' => 'Add Report to My Dashboard', 'Add Root Node' => 'Add Root Node', 'Add Signature to Response' => 'Add Signature to Response', 'Add Subscription' => 'Add Subscription', 'Add To Basket Button Behaviour' => 'Add To Basket Button Behaviour', 'Add User Fields' => 'Add User Fields', 'Add only Access Records' => 'Add only Access Records', 'Add points to affiliate for each %s in payment' => 'Add points to affiliate for each %s in payment', 'Add to Basket and Checkout' => 'Add to Basket and Checkout', 'Add to Basket and Popup Basket' => 'Add to Basket and Popup Basket', 'Add to Basket only' => 'Add to Basket only', 'Add to Menu' => 'Add to Menu', 'Additional' => 'Additional', 'Address' => 'Address', 'Admin Accounts' => 'Admin Accounts', 'Admin Can Edit His Messages within 5 minutes after post' => 'Admin Can Edit His Messages within 5 minutes after post', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address', 'Admin Email' => 'Admin Email', 'Admin Free Subscription Notifications to admin once free signup is completed' => 'Admin Free Subscription Notifications to admin once free signup is completed', 'Admin Log' => 'Admin Log', 'Admin Login Required' => 'Admin Login Required', 'Admin Pages Theme' => 'Admin Pages Theme', 'Admin Payment Notifications to admin once payment is received' => 'Admin Payment Notifications to admin once payment is received', 'Admin Recipients' => 'Admin Recipients', 'Admin Settings' => 'Admin Settings', 'Admin notification' => 'Admin notification', 'Admin username must be alphanumeric in small caps' => 'Admin username must be alphanumeric in small caps', 'Administrator Login' => 'Administrator Login', 'Administrator has been removed, id [%d]' => 'Administrator has been removed, id [%d]', 'Advanced Settings' => 'Advanced Settings', 'Affiliate %s not found' => 'Affiliate %s not found', 'Affiliate Can View Sales Details Leave this checkbox unselected to restrict affiliates from seeing their sales details' => 'Affiliate Can View Sales Details Leave this checkbox unselected to restrict affiliates from seeing their sales details', 'Affiliate Commission' => 'Affiliate Commission', 'Affiliate Commission Details for' => 'Affiliate Commission Details for', 'Affiliate Commission Rules' => 'Affiliate Commission Rules', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Affiliate Cookie Lifetime days to store cookies about referred affiliate', 'Affiliate Email' => 'Affiliate Email', 'Affiliate Id' => 'Affiliate Id', 'Affiliate Information' => 'Affiliate Information', 'Affiliate Login' => 'Affiliate Login', 'Affiliate Name' => 'Affiliate Name', 'Affiliate Payout Conversion Rate how many credits affiliate should recieve for %s' => 'Affiliate Payout Conversion Rate how many credits affiliate should recieve for %s', 'Affiliate Payout Paid Notification to User send email to user when his payout is marked as paid' => 'Affiliate Payout Paid Notification to User send email to user when his payout is marked as paid', 'Affiliate Registration E-Mail' => 'Affiliate Registration E-Mail', 'Affiliate Registration Notification to Admin' => 'Affiliate Registration Notification to Admin', 'Affiliate items count trigger this commission if affiliate made more than ... item sales within ... days before the current date (only count of items in new invoices is calculated' => 'Affiliate items count trigger this commission if affiliate made more than ... item sales within ... days before the current date (only count of items in new invoices is calculated', 'Affiliate sales amount trigger this commission if affiliate made more than ... sales within ... days before the current date (only new invoices calculated)' => 'Affiliate sales amount trigger this commission if affiliate made more than ... sales within ... days before the current date (only new invoices calculated)', 'Affiliate sales count trigger this commission if affiliate made more than ... sales within ... days before the current date (only count of new invoices is calculated)' => 'Affiliate sales count trigger this commission if affiliate made more than ... sales within ... days before the current date (only count of new invoices is calculated)', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Affiliates Payout Day choose a day of month when payout is generated', 'Affiliates Signup Type' => 'Affiliates Signup Type', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file', 'All Banners' => 'All Banners', 'All Content' => 'All Content', 'All Content Page' => 'All Content Page', 'All Products List' => 'All Products List', 'All Subscription Period' => 'All Subscription Period', 'All new users automatically become affiliates' => 'All new users automatically become affiliates', 'Allow Affiliates to redirect Referrers to any url' => 'Allow Affiliates to redirect Referrers to any url', 'Allow Redirects to Other Domains By default aMember does not allow to redirect to foreign domain names via \'amember_redirect_url\' parameter. These redirects are only allowed for urls within your domain name. This is restricted to avoid potential security issues. ' => 'Allow Redirects to Other Domains By default aMember does not allow to redirect to foreign domain names via \'amember_redirect_url\' parameter. These redirects are only allowed for urls within your domain name. This is restricted to avoid potential security issues. ', 'Allow cancel recurring subscription from user account' => 'Allow cancel recurring subscription from user account', 'Allow customers to disable activations in user area' => 'Allow customers to disable activations in user area', 'Allow for some affiliates, disallow for others' => 'Allow for some affiliates, disallow for others', 'Allow redirecting to external URLs' => 'Allow redirecting to external URLs', 'Allow resume cancelled recurring subscription' => 'Allow resume cancelled recurring subscription', 'Allow to Use Password Hash from 3ty part Scripts to Authenticate User in aMember you need to enable this option only if you imported users from 3ty part script without known plain text password' => 'Allow to Use Password Hash from 3ty part Scripts to Authenticate User in aMember you need to enable this option only if you imported users from 3ty part script without known plain text password', 'Allow usage of coupons for %sUpgrade paths%s' => 'Allow usage of coupons for %sUpgrade paths%s', 'Allow use Cart only to Registered Users' => 'Allow use Cart only to Registered Users', 'Allow user to download PDF invoice in his account' => 'Allow user to download PDF invoice in his account', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Allowed E-Mails Count enter number of emails allowed within the period above', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour', 'Alphabetically (ASC)' => 'Alphabetically (ASC)', 'Alphabetically (DESC)' => 'Alphabetically (DESC)', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Always Remember if set to Yes, don\'t ask customer - always remember', 'Amazon SES' => 'Amazon SES', 'Amazon SES Access Id' => 'Amazon SES Access Id', 'Amazon SES Region' => 'Amazon SES Region', 'Amazon SES Secret Key' => 'Amazon SES Secret Key', 'American Date Format' => 'American Date Format', 'Amount excl. Tax' => 'Amount excl. Tax', 'Amount excl. VAT' => 'Amount excl. VAT', 'An Admin Account with the same email already exists.' => 'An Admin Account with the same email already exists.', 'Any Coupon' => 'Any Coupon', 'Apply Tax?' => 'Apply Tax?', 'Apply this rule if affiliate has active access to' => 'Apply this rule if affiliate has active access to', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'Apply to recurring? apply coupon discount to recurring rebills?', 'Approve' => 'Approve', 'Archive' => 'Archive', 'Assign Category' => 'Assign Category', 'Assign Paysystem to Product' => 'Assign Paysystem to Product', 'At least one billing plan must be added' => 'At least one billing plan must be added', 'Attach PDF Invoice' => 'Attach PDF Invoice', 'Attach invoice file (.pdf) to Payment Receipt to Admin' => 'Attach invoice file (.pdf) to Payment Receipt to Admin', 'Attach invoice file (.pdf) to Payment Receipt to User' => 'Attach invoice file (.pdf) to Payment Receipt to User', 'Attached User Data (XML)' => 'Attached User Data (XML)', 'Auto Buffering whether loading of clip into player\'s memory should begin straight away. When this is true and autoPlay is false then the clip will automatically stop at the first frame of the video.' => 'Auto Buffering whether loading of clip into player\'s memory should begin straight away. When this is true and autoPlay is false then the clip will automatically stop at the first frame of the video.', 'Auto Play whether the player should start playback immediately upon loading' => 'Auto Play whether the player should start playback immediately upon loading', 'Auto-locking for this customer is temporary disabled until %s' => 'Auto-locking for this customer is temporary disabled until %s', 'Autoclose Tickets Due to Inactivity' => 'Autoclose Tickets Due to Inactivity', 'Automatically Login Customer After Signup' => 'Automatically Login Customer After Signup', 'Autoresponder message will be automatically sent by cron job when configured conditions met. If you set message to be sent after payment, it will be sent immediately after payment received. Auto-responder message will not be sent if:
      • User has unsubscribed from e-mail messages
      ' => 'Autoresponder message will be automatically sent by cron job when configured conditions met. If you set message to be sent after payment, it will be sent immediately after payment received. Auto-responder message will not be sent if:
      • User has unsubscribed from e-mail messages
      ', 'Available' => 'Available', 'Available Locales defines both language and date/number formats, default locale is always enabled' => 'Available Locales defines both language and date/number formats, default locale is always enabled', 'Available Products' => 'Available Products', 'Available Upgrades' => 'Available Upgrades', 'Available for users from groups' => 'Available for users from groups', 'BCC blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients' => 'BCC blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients', 'BEGIN' => 'BEGIN', 'Back to Countries' => 'Back to Countries', 'Back to Dashboard' => 'Back to Dashboard', 'Back to FAQ List' => 'Back to FAQ List', 'Backup' => 'Backup', 'Backup can be runned by POST request only' => 'Backup can be runned by POST request only', 'Backup file header' => 'Backup file header', 'Banner' => 'Banner', 'Banner Categories' => 'Banner Categories', 'Banners' => 'Banners', 'Base Currency base currency to be used for reports and affiliate commission. It could not be changed if there are any invoices in database.' => 'Base Currency base currency to be used for reports and affiliate commission. It could not be changed if there are any invoices in database.', 'Basket' => 'Basket', 'Basket HTML Code' => 'Basket HTML Code', 'Basket Layout' => 'Basket Layout', 'Begin date should be before Expire date' => 'Begin date should be before Expire date', 'Bi-Weekly (on %s)' => 'Bi-Weekly (on %s)', 'Billing' => 'Billing', 'Billing Terms' => 'Billing Terms', 'Bind To activation will be tied to the following installation parameters usually 1 choice is quite enough' => 'Bind To activation will be tied to the following installation parameters usually 1 choice is quite enough', 'Bindings' => 'Bindings', 'Blob (unlimited length binary data)' => 'Blob (unlimited length binary data)', 'Block This IP Address' => 'Block This IP Address', 'Blocking IP/E-Mail' => 'Blocking IP/E-Mail', 'Both Form (signup & member)' => 'Both Form (signup & member)', 'Bottom' => 'Bottom', 'Bottom Left' => 'Bottom Left', 'Bottom Right' => 'Bottom Right', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Briefly unavailable for scheduled maintenance. Check back in a minute.', 'Browse' => 'Browse', 'Browse Countries' => 'Browse Countries', 'Browse Found Users' => 'Browse Found Users', 'Browse States' => 'Browse States', 'Browse Users' => 'Browse Users', 'Browse Webhooks' => 'Browse Webhooks', 'Bruteforce Notification notify admin when bruteforce attack is detected' => 'Bruteforce Notification notify admin when bruteforce attack is detected', 'Bruteforce Protection' => 'Bruteforce Protection', 'Buffer Length The amount of video data (in seconds) which should be loaded into Flowplayer\'s memory in advance of playback commencing.' => 'Buffer Length The amount of video data (in seconds) which should be loaded into Flowplayer\'s memory in advance of playback commencing.', 'Build Demo' => 'Build Demo', 'Building demo records' => 'Building demo records', 'Button' => 'Button', 'Button/Link HTML Code' => 'Button/Link HTML Code', 'By Affiliate Active Product' => 'By Affiliate Active Product', 'By Affiliate Active Product Category' => 'By Affiliate Active Product Category', 'By Affiliate Group Id' => 'By Affiliate Group Id', 'By Affiliate Item Sales Count' => 'By Affiliate Item Sales Count', 'By Affiliate Sales Amount' => 'By Affiliate Sales Amount', 'By Affiliate Sales Count' => 'By Affiliate Sales Count', 'By Product' => 'By Product', 'By Product Category' => 'By Product Category', 'By Used Coupon' => 'By Used Coupon', 'By Used Payment System' => 'By Used Payment System', 'CONTINUE' => 'CONTINUE', 'Cache Backend' => 'Cache Backend', 'Calculate Affiliate Commissions from Totals Including Tax by default commission calculated from amounts before tax' => 'Calculate Affiliate Commissions from Totals Including Tax by default commission calculated from amounts before tax', 'Calculate Commission' => 'Calculate Commission', 'Calculate Commission for this Invoice' => 'Calculate Commission for this Invoice', 'Campaign Title for admin reference' => 'Campaign Title for admin reference', 'Campaign Type' => 'Campaign Type', 'CampaignMonitor (Transactional API)' => 'CampaignMonitor (Transactional API)', 'Campaignmonitor API Key' => 'Campaignmonitor API Key', 'Can not find user with such username' => 'Can not find user with such username', 'Can not find user with such username or email' => 'Can not find user with such username or email', 'Can not save config for dashboard widget without config form [%s]' => 'Can not save config for dashboard widget without config form [%s]', 'Can\'t be changed because your server have suhosin extension enabled' => 'Can\'t be changed because your server have suhosin extension enabled', 'Cancel All Changes in Translations on Current Page' => 'Cancel All Changes in Translations on Current Page', 'Cancellations' => 'Cancellations', 'Cart View Width × Height' => 'Cart View Width × Height', 'Catalogue Layout' => 'Catalogue Layout', 'Categories List' => 'Categories List', 'Category root category of hierarchy which included to shopping cart all categories is included by default' => 'Category root category of hierarchy which included to shopping cart all categories is included by default', 'Change Configuration Settings' => 'Change Configuration Settings', 'Change Invoice Rebill Date' => 'Change Invoice Rebill Date', 'Change Order' => 'Change Order', 'Change Password Notification send email to user after password change' => 'Change Password Notification send email to user after password change', 'Change Paysystem' => 'Change Paysystem', 'Change rebill date' => 'Change rebill date', 'Charge Second Price Once' => 'Charge Second Price Once', 'Charge Second Price x Times' => 'Charge Second Price x Times', 'Check for beta version' => 'Check for beta version', 'Check other Affiliate Program Settings' => 'Check other Affiliate Program Settings', 'CheckBoxes' => 'CheckBoxes', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => 'Choose %1$sFile%2$s > %1$sSave As%2$s.', 'Choose Category' => 'Choose Category', 'Choose Products and/or Product Categories that allows access' => 'Choose Products and/or Product Categories that allows access', 'Choose Upgrades to Install' => 'Choose Upgrades to Install', 'Choose a plugin' => 'Choose a plugin', 'Choose action when locked %s used by customer during signup' => 'Choose action when locked %s used by customer during signup', 'Choose another Report' => 'Choose another Report', 'Clean up data. Please wait...' => 'Clean up data. Please wait...', 'Clean up v4 Database' => 'Clean up v4 Database', 'Clean up...' => 'Clean up...', 'Cleaning up' => 'Cleaning up', 'Cleanup' => 'Cleanup', 'Clear' => 'Clear', 'Clear Access Log' => 'Clear Access Log', 'Clear Incomplete Invoices' => 'Clear Incomplete Invoices', 'Clear Incomplete Users' => 'Clear Incomplete Users', 'Click Tracking Code' => 'Click Tracking Code', 'Click to Expand' => 'Click to Expand', 'Client API ID' => 'Client API ID', 'Closed Caption Position' => 'Closed Caption Position', 'Closed Captions file must be in SRT format, applicable only for video files' => 'Closed Captions file must be in SRT format, applicable only for video files', 'Closed Tickets' => 'Closed Tickets', 'Code Length generated coupon code length between 4 and 32' => 'Code Length generated coupon code length between 4 and 32', 'Collapse Menu' => 'Collapse Menu', 'Comma' => 'Comma', 'Comment for Your Reference' => 'Comment for Your Reference', 'Commission % of commission received by referred affiliate' => 'Commission % of commission received by referred affiliate', 'Commission earned' => 'Commission earned', 'Commission for First Payment calculated for first payment in each invoice' => 'Commission for First Payment calculated for first payment in each invoice', 'Commission for Free Signup calculated for first customer invoice only' => 'Commission for Free Signup calculated for first customer invoice only', 'Commission for Rebills' => 'Commission for Rebills', 'Commissions Included to Payout' => 'Commissions Included to Payout', 'Completed!' => 'Completed!', 'Conditions' => 'Conditions', 'Config values updated...' => 'Config values updated...', 'Configure ReCaptcha to Enable this Option' => 'Configure ReCaptcha to Enable this Option', 'Configured License Keys' => 'Configured License Keys', 'Confirmed Manually' => 'Confirmed Manually', 'Consumer Email' => 'Consumer Email', 'Consumer Name' => 'Consumer Name', 'Consumer Sales' => 'Consumer Sales', 'Converting' => 'Converting', 'Converting CC info (%d from %d)' => 'Converting CC info (%d from %d)', 'Converting started' => 'Converting started', 'Copy' => 'Copy', 'Copy Upgrades' => 'Copy Upgrades', 'Copy from another language' => 'Copy from another language', 'Core' => 'Core', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Could not download file [%s]. Error %s. Please %stry again%s later.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'Could not fetch upgrades list from remote server. %sTry again%', 'Could not fetch upgrades list. Connection error [%s]' => 'Could not fetch upgrades list. Connection error [%s]', 'Could not load payment plugin [%s]' => 'Could not load payment plugin [%s]', 'Could not move uploaded file' => 'Could not move uploaded file', 'Could not open folder [%s] to remove .htaccess from it. Do it manually' => 'Could not open folder [%s] to remove .htaccess from it. Do it manually', 'Could not read XML' => 'Could not read XML', 'Could not write file [%s] - check file permissions and make sure it is writeable' => 'Could not write file [%s] - check file permissions and make sure it is writeable', 'Counrty Title' => 'Counrty Title', 'Count all IP as different' => 'Count all IP as different', 'Count of Licenses' => 'Count of Licenses', 'Countries/States' => 'Countries/States', 'Country Confirmed by User' => 'Country Confirmed by User', 'Country: %s' => 'Country: %s', 'Coupon Codes' => 'Coupon Codes', 'Coupon From Batch' => 'Coupon From Batch', 'Coupon used for %d transactions' => 'Coupon used for %d transactions', 'Coupon with such code is already exits' => 'Coupon with such code is already exits', 'Coupons' => 'Coupons', 'Coupons Batches' => 'Coupons Batches', 'Coupons Count how many coupons need to be generated' => 'Coupons Count how many coupons need to be generated', 'Coupons Usage Count how many times single coupon can be used' => 'Coupons Usage Count how many times single coupon can be used', 'Create Folder' => 'Create Folder', 'Create Session Key' => 'Create Session Key', 'Create ticket as' => 'Create ticket as', 'Credit' => 'Credit', 'Credit Card Expiration Notice if saved customer credit card expires soon, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Credit Card Expiration Notice if saved customer credit card expires soon, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only', 'Credit Card Plugins' => 'Credit Card Plugins', 'Credit Card Rebill Failed if credit card rebill failed, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Credit Card Rebill Failed if credit card rebill failed, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only', 'Credit Card Rebill Successfull if credit card rebill was sucessfull, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Credit Card Rebill Successfull if credit card rebill was sucessfull, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only', 'Credit Type' => 'Credit Type', 'Cron Last Run' => 'Cron Last Run', 'Cron job has been running last time %s, it is more than 24 hours before. Most possible external cron job has been set incorrectly. It may cause very serious problems with the script. You can find info how to set up cron job for your installation here.' => 'Cron job has been running last time %s, it is more than 24 hours before. Most possible external cron job has been set incorrectly. It may cause very serious problems with the script. You can find info how to set up cron job for your installation here.', 'Current' => 'Current', 'Current Server Date and Time' => 'Current Server Date and Time', 'Custom Commission Rules added' => 'Custom Commission Rules added', 'Custom HTML' => 'Custom HTML', 'Custom Signup Form Title keep empty to use default title' => 'Custom Signup Form Title keep empty to use default title', 'Customer' => 'Customer', 'Customer Country' => 'Customer Country', 'Customize Dashboard' => 'Customize Dashboard', 'Daily' => 'Daily', 'Data' => 'Data', 'Date Format' => 'Date Format', 'Date Of Transaction' => 'Date Of Transaction', 'Date Time' => 'Date Time', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Date to Purge all records prior to this date will be removed from selected tables', 'Date/Time Of Transaction' => 'Date/Time Of Transaction', 'Dates date range when coupon can be used' => 'Dates date range when coupon can be used', 'Dates can be in the folowing formats' => 'Dates can be in the folowing formats', 'Days to Send' => 'Days to Send', 'Debit' => 'Debit', 'Default - user clicks a link to become affiliate' => 'Default - user clicks a link to become affiliate', 'Default Billing Plan' => 'Default Billing Plan', 'Default Commission' => 'Default Commission', 'Default Index Page' => 'Default Index Page', 'Default Locale' => 'Default Locale', 'Default Not Found Page' => 'Default Not Found Page', 'Default Signup' => 'Default Signup', 'Default Size width×height' => 'Default Size width×height', 'Default for Members' => 'Default for Members', 'Default for Profile' => 'Default for Profile', 'Default value for field (that is default value for inputs, not SQL DEFAULT)' => 'Default value for field (that is default value for inputs, not SQL DEFAULT)', 'Delay Payout (days) number of days that should go through before commision is included to payout report' => 'Delay Payout (days) number of days that should go through before commision is included to payout report', 'Delete Old Records' => 'Delete Old Records', 'Delete Preset' => 'Delete Preset', 'Delete Saved Search?' => 'Delete Saved Search?', 'Delete User' => 'Delete User', 'Delete payment and access record' => 'Delete payment and access record', 'Delimiter' => 'Delimiter', 'Demo History' => 'Demo History', 'Description displayed to visitors on order page below the title' => 'Description displayed to visitors on order page below the title', 'Detail View Width × Height' => 'Detail View Width × Height', 'Detailed (list of products)' => 'Detailed (list of products)', 'Detailed Rebill Report for %s' => 'Detailed Rebill Report for %s', 'Details' => 'Details', 'Die and show ugly error message' => 'Die and show ugly error message', 'Digits and latin letters only please' => 'Digits and latin letters only please', 'Directory Listings' => 'Directory Listings', 'Disable All Campaigns' => 'Disable All Campaigns', 'Disable Checking for aMember Updates' => 'Disable Checking for aMember Updates', 'Disable Customer Account' => 'Disable Customer Account', 'Disable New Signups' => 'Disable New Signups', 'Disable Visual HTML Editor' => 'Disable Visual HTML Editor', 'Disable auto-locking for this customer' => 'Disable auto-locking for this customer', 'Disallow for some affiliates, allow for others' => 'Disallow for some affiliates, allow for others', 'Disallow new Signups by %s' => 'Disallow new Signups by %s', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions', 'Disallow use of coupon from this batch if user has when user uses coupon, it will be checked that he has no any from the following subscriptions' => 'Disallow use of coupon from this batch if user has when user uses coupon, it will be checked that he has no any from the following subscriptions', 'Disclaimer of Credit Card Recurring Billing' => 'Disclaimer of Credit Card Recurring Billing', 'Disclosure Admin real name in user interface otherwise only word Administrator is shown' => 'Disclosure Admin real name in user interface otherwise only word Administrator is shown', 'Discount additional discount to invoice total besides coupon' => 'Discount additional discount to invoice total besides coupon', 'Display Language Choice' => 'Display Language Choice', 'Display Mode' => 'Display Mode', 'Display Options' => 'Display Options', 'Display error message' => 'Display error message', 'Display inside layout When displaying to customer, will the header/footer from current theme be displayed?' => 'Display inside layout When displaying to customer, will the header/footer from current theme be displayed?', 'Do not Allow Spaces in Username' => 'Do not Allow Spaces in Username', 'Do not Lowercase Username by default, aMember automatically lowercases entered username here you can disable this function' => 'Do not Lowercase Username by default, aMember automatically lowercases entered username here you can disable this function', 'Do not Show Unsubscribe Block on Member Page' => 'Do not Show Unsubscribe Block on Member Page', 'Do not create invoice. Add only access record' => 'Do not create invoice. Add only access record', 'Do not generate products use existing products for demo records' => 'Do not generate products use existing products for demo records', 'Do not include Unsubscribe Link into e-mails' => 'Do not include Unsubscribe Link into e-mails', 'Do not include records with empty VAT' => 'Do not include records with empty VAT', 'Do you really want to Calculate Commission for this invoice? Commission will be added to affiliate account.' => 'Do you really want to Calculate Commission for this invoice? Commission will be added to affiliate account.', 'Do you really want to Delete User %s?' => 'Do you really want to Delete User %s?', 'Do you really want to change Rebill Date for this invoice?' => 'Do you really want to change Rebill Date for this invoice?', 'Do you really want to delete product?' => 'Do you really want to delete product?', 'Do you really want to delete this item?' => 'Do you really want to delete this item?', 'Do you really want to refund payment' => 'Do you really want to refund payment', 'Do you really want to restore product?' => 'Do you really want to restore product?', 'Do you really want to resume this subscription?' => 'Do you really want to resume this subscription?', 'Do you really want to stop this subscription?' => 'Do you really want to stop this subscription?', 'Do you really want to void this commission?' => 'Do you really want to void this commission?', 'Documentation' => 'Documentation', 'Does Not Allow to Upload Attachments for Users' => 'Does Not Allow to Upload Attachments for Users', 'Does Not Quote Message in Reply' => 'Does Not Quote Message in Reply', 'Does Not Require Login to Access FAQ Section make it public' => 'Does Not Require Login to Access FAQ Section make it public', 'Does Not Show FAQ Tab in Member Area' => 'Does Not Show FAQ Tab in Member Area', 'Download Backup / Restore from Backup' => 'Download Backup / Restore from Backup', 'Download CSV' => 'Download CSV', 'Download CSV File' => 'Download CSV File', 'Download Upgrades' => 'Download Upgrades', 'Due Date' => 'Due Date', 'Duration:' => 'Duration:', 'E-Mail Address to Send to' => 'E-Mail Address to Send to', 'E-Mail Backup Address' => 'E-Mail Backup Address', 'E-Mail Commission to Admin' => 'E-Mail Commission to Admin', 'E-Mail Commission to Affiliate' => 'E-Mail Commission to Affiliate', 'E-Mail Database Backup' => 'E-Mail Database Backup', 'E-Mail Messages on Rebilling Event' => 'E-Mail Messages on Rebilling Event', 'E-Mail Payment Receipt to User every time payment is received' => 'E-Mail Payment Receipt to User every time payment is received', 'E-Mail Queue' => 'E-Mail Queue', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'E-Mail Sender Name used to display name of sender in outgoing e-mails', 'E-Mail Sending' => 'E-Mail Sending', 'E-Mail System Configuration' => 'E-Mail System Configuration', 'E-Mail Type' => 'E-Mail Type', 'E-Mail Users' => 'E-Mail Users', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s', 'E-Mail sending started' => 'E-Mail sending started', 'E-Mails History' => 'E-Mails History', 'E-Mails by Admin Request' => 'E-Mails by Admin Request', 'E-Mails by User Request' => 'E-Mails by User Request', 'EU VAT Report Details' => 'EU VAT Report Details', 'EU Vat Report' => 'EU Vat Report', 'EXPIRED %s' => 'EXPIRED %s', 'EXPIRED category %s' => 'EXPIRED category %s', 'Earn points for %s in payment' => 'Earn points for %s in payment', 'Echeck Plugins' => 'Echeck Plugins', 'Edit Custom Commission Rules' => 'Edit Custom Commission Rules', 'Edit Groups' => 'Edit Groups', 'Edit Messages' => 'Edit Messages', 'Edit Options' => 'Edit Options', 'Edit Product' => 'Edit Product', 'Edit States' => 'Edit States', 'Email Addresses Separated by Comma' => 'Email Addresses Separated by Comma', 'Email Admin Regarding Account Sharing' => 'Email Admin Regarding Account Sharing', 'Email Backup Frequency' => 'Email Backup Frequency', 'Email Domain used to generate email address for users' => 'Email Domain used to generate email address for users', 'Email Layouts' => 'Email Layouts', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works', 'Email Sent' => 'Email Sent', 'Email Template Layouts' => 'Email Template Layouts', 'Email Template with Payment Link' => 'Email Template with Payment Link', 'Email User Regarding Account Sharing' => 'Email User Regarding Account Sharing', 'Email address is required field.' => 'Email address is required field.', 'Email has been send' => 'Email has been send', 'Email is required if you have enabled Email Backup Feature' => 'Email is required if you have enabled Email Backup Feature', 'Emails' => 'Emails', 'Empty Payout Method Notification to User send email to user in case he has commission but did not define payout method yet. This email will be sent only once.' => 'Empty Payout Method Notification to User send email to user in case he has commission but did not define payout method yet. This email will be sent only once.', 'Enable Click Tracking Code Enable ability to track affiliate clicks on any page on your site' => 'Enable Click Tracking Code Enable ability to track affiliate clicks on any page on your site', 'Enable Keywords Support Enable ability to track traffic sources adding keywords to url' => 'Enable Keywords Support Enable ability to track traffic sources adding keywords to url', 'Enable Live Conversation (experimental) update conversation instantly without page reload (can consume more server resources)' => 'Enable Live Conversation (experimental) update conversation instantly without page reload (can consume more server resources)', 'Enable PDF Invoice' => 'Enable PDF Invoice', 'Enable ReCaptcha on login and restore password forms' => 'Enable ReCaptcha on login and restore password forms', 'Enable plugins if necessary' => 'Enable plugins if necessary', 'Enable use of coupons allow use coupons on shopping cart checkout page' => 'Enable use of coupons allow use coupons on shopping cart checkout page', 'Encrypted Pass' => 'Encrypted Pass', 'Encrypted Password' => 'Encrypted Password', 'Enter Maintenance Mode' => 'Enter Maintenance Mode', 'Enter admin password for confirmation' => 'Enter admin password for confirmation', 'Enter title for your new category' => 'Enter title for your new category', 'Error Log' => 'Error Log', 'Error deleting record! Please refresh page and try again' => 'Error deleting record! Please refresh page and try again', 'Error during e-mail sending' => 'Error during e-mail sending', 'Error occurred, please check Errors Log for clue' => 'Error occurred, please check Errors Log for clue', 'Error/Debug Log' => 'Error/Debug Log', 'Errors' => 'Errors', 'Errors:' => 'Errors:', 'European Date Format' => 'European Date Format', 'Event' => 'Event', 'Events to inclulde to widget, leave it empty to include all events' => 'Events to inclulde to widget, leave it empty to include all events', 'Every %s' => 'Every %s', 'Exact Period' => 'Exact Period', 'Exchange Rate' => 'Exchange Rate', 'Exchange Rate enter cost of 1 (one) %s' => 'Exchange Rate enter cost of 1 (one) %s', 'Expiration message will be sent when configured conditions met. Additional restrictions applies to do not sent unnecessary e-mails. Expiration message will not be sent if:
      • User has other active products with the same renewal group
      • User has unsubscribed from e-mail messages
      ' => 'Expiration message will be sent when configured conditions met. Additional restrictions applies to do not sent unnecessary e-mails. Expiration message will not be sent if:
      • User has other active products with the same renewal group
      • User has unsubscribed from e-mail messages
      ', 'Expire (maximum expiration date)' => 'Expire (maximum expiration date)', 'Extend Existing Subscription Period' => 'Extend Existing Subscription Period', 'FORM' => 'FORM', 'Failures' => 'Failures', 'Field Description for dispaying on signup and profile editing screen (for user)' => 'Field Description for dispaying on signup and profile editing screen (for user)', 'Field Name' => 'Field Name', 'Field Title' => 'Field Title', 'Field Type sql field will be added to table structure, common field will not, we recommend you to choose second option' => 'Field Type sql field will be added to table structure, common field will not, we recommend you to choose second option', 'Field Values' => 'Field Values', 'Fields You can add new fields %shere%s' => 'Fields You can add new fields %shere%s', 'File (max filesize %s)' => 'File (max filesize %s)', 'File %s is already exist. You can not create already existing translation.' => 'File %s is already exist. You can not create already existing translation.', 'File Download' => 'File Download', 'File [%s] cannot be deleted - remove it manually to unprotect folder' => 'File [%s] cannot be deleted - remove it manually to unprotect folder', 'File is required' => 'File is required', 'Filter By Title or Category' => 'Filter By Title or Category', 'Filter by Affiliate/Banner/IP' => 'Filter by Affiliate/Banner/IP', 'Filter by Affiliate/User/Banner' => 'Filter by Affiliate/User/Banner', 'Filter by Affiliate/User/Product' => 'Filter by Affiliate/User/Product', 'Filter by Category' => 'Filter by Category', 'Filter by Country' => 'Filter by Country', 'Filter by Paysystem' => 'Filter by Paysystem', 'Filter by Product' => 'Filter by Product', 'Filter by Status' => 'Filter by Status', 'Filter by String' => 'Filter by String', 'Filter by User/Product' => 'Filter by User/Product', 'Filter by name or description' => 'Filter by name or description', 'Filter by string or by invoice#/member#' => 'Filter by string or by invoice#/member#', 'Find an user…' => 'Find an user…', 'First Payment (calculated for first payment in each invoice)' => 'First Payment (calculated for first payment in each invoice)', 'First Period' => 'First Period', 'First Price' => 'First Price', 'First Price price of first period of subscription' => 'First Price price of first period of subscription', 'First Tax' => 'First Tax', 'First Time Purchase' => 'First Time Purchase', 'First Total' => 'First Total', 'First and Last Name' => 'First and Last Name', 'First available protected url' => 'First available protected url', 'First visited' => 'First visited', 'Fix aMember Pro License Key' => 'Fix aMember Pro License Key', 'Fixed Url' => 'Fixed Url', 'Fixed date' => 'Fixed date', 'FlowPlayer License Key you may get your key in %smembers area%s' => 'FlowPlayer License Key you may get your key in %smembers area%s', 'Folder %s is not a writable for the PHP script. Please
      chmod this file using webhosting control panel file manager or using your
      favorite FTP client to 777 (write and read for all)
      Please, don\'t forget to chmod it back to 755 after creation of translation' => 'Folder %s is not a writable for the PHP script. Please
      chmod this file using webhosting control panel file manager or using your
      favorite FTP client to 777 (write and read for all)
      Please, don\'t forget to chmod it back to 755 after creation of translation', 'Folder Options' => 'Folder Options', 'Folder URL' => 'Folder URL', 'Force Change Password' => 'Force Change Password', 'Force Change Password ask user to change password every XX days' => 'Force Change Password ask user to change password every XX days', 'Force https Connection redirect all request to https' => 'Force https Connection redirect all request to https', 'Form Type' => 'Form Type', 'Form to Include to Roster' => 'Form to Include to Roster', 'Forms Editor' => 'Forms Editor', 'Front Page' => 'Front Page', 'Full' => 'Full', 'Future' => 'Future', 'General' => 'General', 'General Affiliate Link Redirect URL It is url of landing page for default affiliate link (which does not related to any banner), home page will be used if you keep it empty' => 'General Affiliate Link Redirect URL It is url of landing page for default affiliate link (which does not related to any banner), home page will be used if you keep it empty', 'General Link' => 'General Link', 'General Settings' => 'General Settings', 'Generate' => 'Generate', 'Generate Basket HTML' => 'Generate Basket HTML', 'Generate Batch of Random Coupon Codes (You will be able to alter codes later if you want)' => 'Generate Batch of Random Coupon Codes (You will be able to alter codes later if you want)', 'Generate Button HTML' => 'Generate Button HTML', 'Generate Payout Manually' => 'Generate Payout Manually', 'Generate Products Count' => 'Generate Products Count', 'Generate Report' => 'Generate Report', 'Generate Users Count' => 'Generate Users Count', 'Generated' => 'Generated', 'Generated License Valid To' => 'Generated License Valid To', 'Generation of demo data was terminated while processing. Not all records were created.' => 'Generation of demo data was terminated while processing. Not all records were created.', 'Get Available Upgrades List' => 'Get Available Upgrades List', 'Get New Password' => 'Get New Password', 'Global' => 'Global', 'Global Translations' => 'Global Translations', 'Got an error when attempting to re-encode CC record. CC and config tables were restored from backup. Check "aMember CP -> Error Log" for more info ' => 'Got an error when attempting to re-encode CC record. CC and config tables were restored from backup. Check "aMember CP -> Error Log" for more info ', 'Graph Bar' => 'Graph Bar', 'Graph Line' => 'Graph Line', 'Gravatar' => 'Gravatar', 'HTML Code %url% will be replaced with actual url of affilate link' => 'HTML Code %url% will be replaced with actual url of affilate link', 'HTML E-Mail Unsubscribe Link %link% will be replaced to actual unsubscribe URL' => 'HTML E-Mail Unsubscribe Link %link% will be replaced to actual unsubscribe URL', 'Hash' => 'Hash', 'Help & Support' => 'Help & Support', 'Hide \'Add/Renew Subscription\' tab (User Menu) and show \'Shopping Cart\' tab instead' => 'Hide \'Add/Renew Subscription\' tab (User Menu) and show \'Shopping Cart\' tab instead', 'Hide Quick Order Button' => 'Hide Quick Order Button', 'Hide disabled activations in user area' => 'Hide disabled activations in user area', 'Hide expired licenses in user area' => 'Hide expired licenses in user area', 'Hide from Dashboard do not display this item link in members area' => 'Hide from Dashboard do not display this item link in members area', 'Hide from Dashboard do not display this item link in members dashboard This doesn\'t remove link from category.' => 'Hide from Dashboard do not display this item link in members dashboard This doesn\'t remove link from category.', 'Hide from Menu do not include link to this form in members menu' => 'Hide from Menu do not include link to this form in members menu', 'Home Page' => 'Home Page', 'Hostname' => 'Hostname', 'Hour' => 'Hour', 'I submitted refund already and only wanted to add refund record to invoice' => 'I submitted refund already and only wanted to add refund record to invoice', 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database' => 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database', 'ID' => 'ID', 'IMPORTANT NOTE:' => 'IMPORTANT NOTE:', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.', 'IP' => 'IP', 'IP within' => 'IP within', 'IP(Country)' => 'IP(Country)', 'If only one protected URL, go directly to the URL. Otherwise go to membership page' => 'If only one protected URL, go directly to the URL. Otherwise go to membership page', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.', 'Image' => 'Image', 'Image height must be number greater than %d' => 'Image height must be number greater than %d', 'Image width must be number greater than %d' => 'Image width must be number greater than %d', 'Immediately' => 'Immediately', 'Import E-Mail Templates from XML file' => 'Import E-Mail Templates from XML file', 'Import Encrypted Password' => 'Import Encrypted Password', 'Import Finished' => 'Import Finished', 'Import Finished. %d templates imported.' => 'Import Finished. %d templates imported.', 'Import History' => 'Import History', 'Import Mode' => 'Import Mode', 'Import Pre-Defined List of Coupon Codes from CSV File (One coupon code per line)' => 'Import Pre-Defined List of Coupon Codes from CSV File (One coupon code per line)', 'Import Users' => 'Import Users', 'Import data. Please wait...' => 'Import data. Please wait...', 'Import of data was terminated while processing. Anyway some data was imported.' => 'Import of data was terminated while processing. Anyway some data was imported.', 'Import...' => 'Import...', 'Import: Step 1 of 4' => 'Import: Step 1 of 4', 'Import: Step 2 of 4' => 'Import: Step 2 of 4', 'Import: Step 3 of 4' => 'Import: Step 3 of 4', 'Import: Step 4 of 4' => 'Import: Step 4 of 4', 'Important Notice:' => 'Important Notice:', 'In case of video do not start play before full download and you use mp4 format more possible that metadata (moov atom) is located at the end of file. There is special programs that allow to relocate this metadata to the beginning of your file and allow play video before full download (On Linux mashine you can use qt-faststart utility to do it). Also your video editor can has option to locate metadata at beginning of file (something like FastStart or Web Optimized option). You need to relocate metadata for this file and reupload it to aMember. You can use such utilites as AtomicParsley or similar to check your file structure.' => 'In case of video do not start play before full download and you use mp4 format more possible that metadata (moov atom) is located at the end of file. There is special programs that allow to relocate this metadata to the beginning of your file and allow play video before full download (On Linux mashine you can use qt-faststart utility to do it). Also your video editor can has option to locate metadata at beginning of file (something like FastStart or Web Optimized option). You need to relocate metadata for this file and reupload it to aMember. You can use such utilites as AtomicParsley or similar to check your file structure.', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.', 'In the File name box, type a name for the file.' => 'In the File name box, type a name for the file.', 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.' => 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.', 'Incorrect refund [type] passed: %s' => 'Incorrect refund [type] passed: %s', 'Index Page %sthis page will be public and do not require any login/password%s you can create new pages %shere%s' => 'Index Page %sthis page will be public and do not require any login/password%s you can create new pages %shere%s', 'Information is not available' => 'Information is not available', 'Insert' => 'Insert', 'Install Updates' => 'Install Updates', 'Instances Limit How many simultaneous bindings for license may exists (default - 1)' => 'Instances Limit How many simultaneous bindings for license may exists (default - 1)', 'Integer field (only numbers)' => 'Integer field (only numbers)', 'Integration plugins' => 'Integration plugins', 'Internal PHP mail() function (default)' => 'Internal PHP mail() function (default)', 'Intro Text on Affiliate Info Page' => 'Intro Text on Affiliate Info Page', 'Intro Text on Helpdesk Page' => 'Intro Text on Helpdesk Page', 'Invoice (Internal Id)' => 'Invoice (Internal Id)', 'Invoice (Public Id)' => 'Invoice (Public Id)', 'Invoice (Sequential Receipt Number)' => 'Invoice (Sequential Receipt Number)', 'Invoice Approved Notification to User (Invoice)' => 'Invoice Approved Notification to User (Invoice)', 'Invoice Country' => 'Invoice Country', 'Invoice Log' => 'Invoice Log', 'Invoice Number' => 'Invoice Number', 'Invoice link has been sent to user again' => 'Invoice link has been sent to user again', 'Invoice/User/License/Bindings' => 'Invoice/User/License/Bindings', 'Invoices' => 'Invoices', 'Invoices Information' => 'Invoices Information', 'Invoices Per User' => 'Invoices Per User', 'Is Affiliate?' => 'Is Affiliate?', 'Is Affiliate? (0 - No, 1 - Yes)' => 'Is Affiliate? (0 - No, 1 - Yes)', 'Is Approved' => 'Is Approved', 'Is Disabled' => 'Is Disabled', 'Is Disabled?' => 'Is Disabled?', 'Is Disabled? If you disable this coupons batch, it will not be available for new purchases. Existing invoices are not affected.' => 'Is Disabled? If you disable this coupons batch, it will not be available for new purchases. Existing invoices are not affected.', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'Is Disabled? disable product ordering, hide it from signup and renewal forms', 'Is Unsubscribed? if enabled, this will unsubscribe the customer from: * messages that you send from aMember Cp, * autoresponder messages, * subscription expiration notices' => 'Is Unsubscribed? if enabled, this will unsubscribe the customer from: * messages that you send from aMember Cp, * autoresponder messages, * subscription expiration notices', 'Is Unsubscribed? (0 - No, 1 - Yes)' => 'Is Unsubscribed? (0 - No, 1 - Yes)', 'It is required to setup a cron job to trigger backup generation' => 'It is required to setup a cron job to trigger backup generation', 'It will replace all your exising database with backup. Do you really want to proceed?' => 'It will replace all your exising database with backup. Do you really want to proceed?', 'Items' => 'Items', 'JWPlayer License Key' => 'JWPlayer License Key', 'JavaScript Code' => 'JavaScript Code', 'Just Add Pending Invoice' => 'Just Add Pending Invoice', 'Key' => 'Key', 'Key Generator' => 'Key Generator', 'Key must be 20 chars or longer' => 'Key must be 20 chars or longer', 'Key/Default' => 'Key/Default', 'Keygenerator' => 'Keygenerator', 'Languages' => 'Languages', 'Last %s Customers' => 'Last %s Customers', 'Last %s Helpdesk Messages' => 'Last %s Helpdesk Messages', 'Last %s Invoices' => 'Last %s Invoices', 'Last %s Payments' => 'Last %s Payments', 'Last %s Refunds' => 'Last %s Refunds', 'Last %s User Notes' => 'Last %s User Notes', 'Last %s User Signin' => 'Last %s User Signin', 'Last Error' => 'Last Error', 'Last Invoices List' => 'Last Invoices List', 'Last Payments List' => 'Last Payments List', 'Last Refunds List' => 'Last Refunds List', 'Last Signin Info' => 'Last Signin Info', 'Last User Logins List' => 'Last User Logins List', 'Last User Notes' => 'Last User Notes', 'Last Users List' => 'Last Users List', 'Last available protected url' => 'Last available protected url', 'Last existing subscription date of this product' => 'Last existing subscription date of this product', 'Last expiration date in the renewal group' => 'Last expiration date in the renewal group', 'Last login' => 'Last login', 'Layout use placholder %content% for email output' => 'Layout use placholder %content% for email output', 'Length of admin password must be from %d to %d' => 'Length of admin password must be from %d to %d', 'Length of username must be from %d to %d' => 'Length of username must be from %d to %d', 'License Activations' => 'License Activations', 'License Info' => 'License Info', 'Licensing Method' => 'Licensing Method', 'Lifetime (%s)' => 'Lifetime (%s)', 'Light Box' => 'Light Box', 'Light Boxes' => 'Light Boxes', 'Lightbox Main Image' => 'Lightbox Main Image', 'Lightbox Thumbnail Image' => 'Lightbox Thumbnail Image', 'Limit Downloads Count' => 'Limit Downloads Count', 'Lines Proccessed:' => 'Lines Proccessed:', 'Lines Skipped:' => 'Lines Skipped:', 'Lines Success:' => 'Lines Success:', 'Link to reset your password was sent to your Email.' => 'Link to reset your password was sent to your Email.', 'List View Width × Height' => 'List View Width × Height', 'Live Products' => 'Live Products', 'Loading...' => 'Loading...', 'Local Translations' => 'Local Translations', 'Lock' => 'Lock', 'Locked Value' => 'Locked Value', 'Locked Value/Comment' => 'Locked Value/Comment', 'Log Outgoing E-Mail Messages for ... days' => 'Log Outgoing E-Mail Messages for ... days', 'Log in' => 'Log in', 'Logged in as %s' => 'Logged in as %s', 'Login As User' => 'Login As User', 'Login Page' => 'Login Page', 'Login/Name/Email/Invoice/Receipt/IP' => 'Login/Name/Email/Invoice/Receipt/IP', 'Logo Image watermark on video' => 'Logo Image watermark on video', 'Logs' => 'Logs', 'Logs: Access' => 'Logs: Access', 'Logs: Admin Log' => 'Logs: Admin Log', 'Logs: Errors' => 'Logs: Errors', 'Logs: File Downloads' => 'Logs: File Downloads', 'Logs: Invoice' => 'Logs: Invoice', 'Logs: Mail Queue' => 'Logs: Mail Queue', 'Lookup' => 'Lookup', 'Lost your password?' => 'Lost your password?', 'Mail' => 'Mail', 'Maintenance Mode' => 'Maintenance Mode', 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s' => 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s', 'Manage Additional User Fields' => 'Manage Additional User Fields', 'Manage Countries/States' => 'Manage Countries/States', 'Manage Product Upgrade Paths' => 'Manage Product Upgrade Paths', 'Manage Products' => 'Manage Products', 'Manage Translation of Messages' => 'Manage Translation of Messages', 'Manually (Sort Order in Admin Interface)' => 'Manually (Sort Order in Admin Interface)', 'Manually Added' => 'Manually Added', 'Manually Approve New Invoices manually approve all new invoices' => 'Manually Approve New Invoices manually approve all new invoices', 'Manually Approve New Users manually approve all new users (first payment) don\'t enable it if you have huge users base already - all old members become not-approved' => 'Manually Approve New Users manually approve all new users (first payment) don\'t enable it if you have huge users base already - all old members become not-approved', 'Manually Approve Note (New Signup/Invoice) this message will be shown for customer after purchase. you can use html markup here' => 'Manually Approve Note (New Signup/Invoice) this message will be shown for customer after purchase. you can use html markup here', 'Mark NOT Paid' => 'Mark NOT Paid', 'Mark Paid' => 'Mark Paid', 'Mass Subscribe' => 'Mass Subscribe', 'Maximum number of events' => 'Maximum number of events', 'Membership' => 'Membership', 'Membership Info Page' => 'Membership Info Page', 'Merge' => 'Merge', 'Merge with user %s <%s> (%s) [#%d]' => 'Merge with user %s <%s> (%s) [#%d]', 'Message will be included to email to user' => 'Message will be included to email to user', 'Messages to Customer after Payment' => 'Messages to Customer after Payment', 'Method' => 'Method', 'Minimum Payout minimal commission amount earned by affiliate to include it to payout report' => 'Minimum Payout minimal commission amount earned by affiliate to include it to payout report', 'Miscellaneous' => 'Miscellaneous', 'Modules' => 'Modules', 'Monthly' => 'Monthly', 'Multi Upload' => 'Multi Upload', 'Multiple CheckBoxes' => 'Multiple CheckBoxes', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name', 'Multiply commission calculated by the following rules to number specified in this field. To keep commission untouched, enter 1 or delete this rule' => 'Multiply commission calculated by the following rules to number specified in this field. To keep commission untouched, enter 1 or delete this rule', 'NEVER (oops! no records that it has been running at all!)' => 'NEVER (oops! no records that it has been running at all!)', 'Name First and Last name' => 'Name First and Last name', 'Name must be entered and it may contain lowercase letters, underscores and digits' => 'Name must be entered and it may contain lowercase letters, underscores and digits', 'Name of Preset' => 'Name of Preset', 'Name of template is undefined' => 'Name of template is undefined', 'Nearest' => 'Nearest', 'Nearest 15th Day of Month' => 'Nearest 15th Day of Month', 'Nearest 1st Day of Month' => 'Nearest 1st Day of Month', 'Nearest Friday' => 'Nearest Friday', 'Nearest Monday' => 'Nearest Monday', 'Nearest Saturday' => 'Nearest Saturday', 'Nearest Sunday' => 'Nearest Sunday', 'Nearest Thursday' => 'Nearest Thursday', 'Nearest Tuesday' => 'Nearest Tuesday', 'Nearest Wednesday' => 'Nearest Wednesday', 'Need points to get %s discount' => 'Need points to get %s discount', 'New Activation' => 'New Activation', 'New Affiliate Payout to Admin' => 'New Affiliate Payout to Admin', 'New Autoresponder' => 'New Autoresponder', 'New Expiration E-Mail' => 'New Expiration E-Mail', 'New Form Campaign' => 'New Form Campaign', 'New Modules Available' => 'New Modules Available', 'New Payment E-Mail' => 'New Payment E-Mail', 'New Product Welcome E-Mail' => 'New Product Welcome E-Mail', 'New Rewrite' => 'New Rewrite', 'New Tax Group' => 'New Tax Group', 'New Theme Campaign' => 'New Theme Campaign', 'New Ticket Autoresponder to Customer aMember will email an autoresponder to user each time user create new ticket' => 'New Ticket Autoresponder to Customer aMember will email an autoresponder to user each time user create new ticket', 'New password has been e-mailed to your e-mail address' => 'New password has been e-mailed to your e-mail address', 'Next Day' => 'Next Day', 'Next Hour' => 'Next Hour', 'Next rebill date' => 'Next rebill date', 'No Access URL customer without required access will be redirected to this url, leave empty if you want to redirect to default \'No access\' page' => 'No Access URL customer without required access will be redirected to this url, leave empty if you want to redirect to default \'No access\' page', 'No Access URL customer without required access will see link to this url in the player window leave empty if you want to redirect to default \'No access\' page' => 'No Access URL customer without required access will see link to this url in the player window leave empty if you want to redirect to default \'No access\' page', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'No Credit Cards stored for this customer. %sAdd Credit Card%s', 'No Echecks stored for this customer. %sAdd Echeck%s' => 'No Echecks stored for this customer. %sAdd Echeck%s', 'No Invoices Found' => 'No Invoices Found', 'No Layout' => 'No Layout', 'No License Configured' => 'No License Configured', 'No Tax' => 'No Tax', 'No Updates Available' => 'No Updates Available', 'No activation' => 'No activation', 'No data to display yet' => 'No data to display yet', 'No more charges' => 'No more charges', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'No one line found in the file. It looks like file is empty. You can go back and try another file.', 'No payment found' => 'No payment found', 'No protection plugins enabled, please enable new-rewrite or htpasswd at aMember CP -> Setup -> Plugins' => 'No protection plugins enabled, please enable new-rewrite or htpasswd at aMember CP -> Setup -> Plugins', 'No search name passed' => 'No search name passed', 'No upgrades to install' => 'No upgrades to install', 'Not Applied' => 'Not Applied', 'Not Approved' => 'Not Approved', 'Not Approved Users' => 'Not Approved Users', 'Not Confirmed Users' => 'Not Confirmed Users', 'Not Included to Payout' => 'Not Included to Payout', 'Not Product' => 'Not Product', 'Not Product Category' => 'Not Product Category', 'Not Sent' => 'Not Sent', 'Not payment# submitted' => 'Not payment# submitted', 'Not-SQL field (default)' => 'Not-SQL field (default)', 'Note' => 'Note', 'Number of Invoices to display' => 'Number of Invoices to display', 'Number of License Reactivations Allowed for all instances (default - 0)' => 'Number of License Reactivations Allowed for all instances (default - 0)', 'Number of Notes to display' => 'Number of Notes to display', 'Number of Payments to display' => 'Number of Payments to display', 'Number of Refunds to display' => 'Number of Refunds to display', 'Number of Users to display' => 'Number of Users to display', 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.' => 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.', 'Number of users who require approval: %d. %sClick here%s to review these users.' => 'Number of users who require approval: %d. %sClick here%s to review these users.', 'Numeric field' => 'Numeric field', 'OK' => 'OK', 'OTO - Offer to purchase additional product (with optional discount)' => 'OTO - Offer to purchase additional product (with optional discount)', 'Ok' => 'Ok', 'One Column' => 'One Column', 'One field can be assigned to one column only, you assigned following fields to several columns: ' => 'One field can be assigned to one column only, you assigned following fields to several columns: ', 'One field can be assigned to one column only.' => 'One field can be assigned to one column only.', 'Only Instant' => 'Only Instant', 'Only admin can enable user as an affiliate' => 'Only admin can enable user as an affiliate', 'Optional Conditions' => 'Optional Conditions', 'Origin' => 'Origin', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used', 'Overwrite User if Exist User with Same Login' => 'Overwrite User if Exist User with Same Login', 'Owner set the following admin as owner of ticket' => 'Owner set the following admin as owner of ticket', 'PDF Invoice' => 'PDF Invoice', 'Page Not Found (404) %sthis page will be public and do not require any login/password%s you can create new pages %shere%s' => 'Page Not Found (404) %sthis page will be public and do not require any login/password%s you can create new pages %shere%s', 'Page Peel' => 'Page Peel', 'Page Where Log In Link was Clicked' => 'Page Where Log In Link was Clicked', 'Page Where Logout Link was Clicked' => 'Page Where Logout Link was Clicked', 'Paid' => 'Paid', 'Params' => 'Params', 'Password Hash' => 'Password Hash', 'Password Length' => 'Password Length', 'Password changed' => 'Password changed', 'Password must not be equal to username' => 'Password must not be equal to username', 'Passwords must be the same' => 'Passwords must be the same', 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this page to do it' => 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this page to do it', 'Path should be unique' => 'Path should be unique', 'Path to Folder' => 'Path to Folder', 'Path/URL' => 'Path/URL', 'Payment Date' => 'Payment Date', 'Payment Receipt' => 'Payment Receipt', 'Payment System Choose payment system to be used with this product' => 'Payment System Choose payment system to be used with this product', 'Payment System: ' => 'Payment System: ', 'Payment belongs to another customer' => 'Payment belongs to another customer', 'Payment date' => 'Payment date', 'Payment email will be automatically sent after payment received. Payment email will not be sent if:
      • User has unsubscribed from e-mail messages
      ' => 'Payment email will be automatically sent after payment received. Payment email will not be sent if:
      • User has unsubscribed from e-mail messages
      ', 'Payment from' => 'Payment from', 'Payment has been successfully refunded' => 'Payment has been successfully refunded', 'Payment is already refunded' => 'Payment is already refunded', 'Payment#/Receipt#' => 'Payment#/Receipt#', 'Payments (amount of all payments made by user minus refunds)' => 'Payments (amount of all payments made by user minus refunds)', 'Payments/Refunds' => 'Payments/Refunds', 'Payout %d Details' => 'Payout %d Details', 'Payout Details' => 'Payout Details', 'Payout Type' => 'Payout Type', 'Paysystem' => 'Paysystem', 'Paysystem Receipt ID' => 'Paysystem Receipt ID', 'Paysystem: %s' => 'Paysystem: %s', 'Pending Invoice Notification Rules' => 'Pending Invoice Notification Rules', 'Pending Invoice Notifications to Admin only one email will be send for each defined day. all email for specific day will be selected and conditions will be checked. First email with matched condition will be send and other ignored' => 'Pending Invoice Notifications to Admin only one email will be send for each defined day. all email for specific day will be selected and conditions will be checked. First email with matched condition will be send and other ignored', 'Pending Invoice Notifications to User only one email will be send for each defined day. all email for specific day will be selected and conditions will be checked. First email with matched condition will be send and other ignored' => 'Pending Invoice Notifications to User only one email will be send for each defined day. all email for specific day will be selected and conditions will be checked. First email with matched condition will be send and other ignored', 'Period: %s-%s' => 'Period: %s-%s', 'Permanently Locked' => 'Permanently Locked', 'Permissions' => 'Permissions', 'Player Configuration this option is applied only for video files' => 'Player Configuration this option is applied only for video files', 'Please assign the following fields: ' => 'Please assign the following fields: ', 'Please choose another field name. This name is already used' => 'Please choose another field name. This name is already used', 'Please choose product' => 'Please choose product', 'Please click on the button below to create backup of aMembers tables in MySQL database.' => 'Please click on the button below to create backup of aMembers tables in MySQL database.', 'Please enter expire date' => 'Please enter expire date', 'Please enter one or more email' => 'Please enter one or more email', 'Please enter start date' => 'Please enter start date', 'Please enter valid e-mail address' => 'Please enter valid e-mail address', 'Please enter valid e-mail addresses' => 'Please enter valid e-mail addresses', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'Please enter your username or email address. You will receive a link to create a new password via email.', 'Please note: By default, aMember does not change users password and login values to a generated value in cases where an existing email address is found. You may decide to update an existing record, in the next step of the import process, where a matching email or username already exists.' => 'Please note: By default, aMember does not change users password and login values to a generated value in cases where an existing email address is found. You may decide to update an existing record, in the next step of the import process, where a matching email or username already exists.', 'Please run %sRebuild Db%s to update status for imported customers' => 'Please run %sRebuild Db%s to update status for imported customers', 'Please select date before today' => 'Please select date before today', 'Please specify new rebill date: ' => 'Please specify new rebill date: ', 'Please specify number greater then zero' => 'Please specify number greater then zero', 'Please specify number less then 9999' => 'Please specify number less then 9999', 'Please upload file [%s]
      ' => 'Please upload file [%s]
      ', 'Please wait' => 'Please wait', 'Plugin Id' => 'Plugin Id', 'Plugins' => 'Plugins', 'Poster Image applicable only for video files' => 'Poster Image applicable only for video files', 'Poster Image default poster image' => 'Poster Image default poster image', 'Product Availability' => 'Product Availability', 'Product Category' => 'Product Category', 'Product Category: ' => 'Product Category: ', 'Product Image' => 'Product Image', 'Product Options' => 'Product Options', 'Product Search' => 'Product Search', 'Product Sort' => 'Product Sort', 'Product Upgrades' => 'Product Upgrades', 'Product is not if none specified, rule works for all products' => 'Product is not if none specified, rule works for all products', 'Product is not included to Category if none specified, rule works for all product categories' => 'Product is not included to Category if none specified, rule works for all product categories', 'Product welcome email will be automatically sent immediately after payment received. Product welcome email will not be sent if:
      • User has unsubscribed from e-mail messages
      ' => 'Product welcome email will be automatically sent immediately after payment received. Product welcome email will not be sent if:
      • User has unsubscribed from e-mail messages
      ', 'Product: ' => 'Product: ', 'Products coupons can be used with selected products only. if nothing selected, coupon can be used with any product' => 'Products coupons can be used with selected products only. if nothing selected, coupon can be used with any product', 'Products List From Category' => 'Products List From Category', 'Products Per Invoice' => 'Products Per Invoice', 'Products per Page' => 'Products per Page', 'Products that bring credits' => 'Products that bring credits', 'Products that can be purchased with credits' => 'Products that can be purchased with credits', 'Protect Content' => 'Protect Content', 'Protect Files List' => 'Protect Files List', 'Protection Method' => 'Protection Method', 'Purchase IP' => 'Purchase IP', 'Put Chosen Products After' => 'Put Chosen Products After', 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty' => 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty', 'Queue Status' => 'Queue Status', 'Quick Start' => 'Quick Start', 'Quit Maintenance Mode' => 'Quit Maintenance Mode', 'REST API Documentation' => 'REST API Documentation', 'RadioButtons' => 'RadioButtons', 'Re Send Payment Link' => 'Re Send Payment Link', 'Rebill' => 'Rebill', 'Rebill Date' => 'Rebill Date', 'Rebill Date changed from %s to %s' => 'Rebill Date changed from %s to %s', 'Rebill Operation Completed for %s' => 'Rebill Operation Completed for %s', 'Rebill Second Price until cancelled' => 'Rebill Second Price until cancelled', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Rebill Times This is the number of payments which will occur at the Second Price', 'Rebill date has been changed!' => 'Rebill date has been changed!', 'Rebills' => 'Rebills', 'Rebuild DB' => 'Rebuild DB', 'Rebuild Db' => 'Rebuild Db', 'Rebuild Users Database' => 'Rebuild Users Database', 'Receipt' => 'Receipt', 'Receipt ID' => 'Receipt ID', 'Receipt#' => 'Receipt#', 'Recent Activity' => 'Recent Activity', 'Recipients' => 'Recipients', 'Record modified, original dates:' => 'Record modified, original dates:', 'Records Deleted Sucessfully' => 'Records Deleted Sucessfully', 'Records per Page (for grids)' => 'Records per Page (for grids)', 'Redirect' => 'Redirect', 'Redirect After Login where customer redirected after successful login at %s' => 'Redirect After Login where customer redirected after successful login at %s', 'Redirect After Logout' => 'Redirect After Logout', 'Redirect Default Signup Page to Cart' => 'Redirect Default Signup Page to Cart', 'Redirect URL' => 'Redirect URL', 'Referrer' => 'Referrer', 'Refund (Sequential Receipt Number)' => 'Refund (Sequential Receipt Number)', 'Refund Date' => 'Refund Date', 'Refund Payment' => 'Refund Payment', 'Refund amount cannot exceed payment amount' => 'Refund amount cannot exceed payment amount', 'Refund date cannot be before payment date' => 'Refund date cannot be before payment date', 'Refund from' => 'Refund from', 'Refunded Amount' => 'Refunded Amount', 'Refunded Date/Time' => 'Refunded Date/Time', 'Refunds' => 'Refunds', 'Refunds are not implemented for this payment system. This action will not issue actual refund. It will just add refund record in aMember and revoke user access. You must go to payment processor and do actual refund if you did not do it yet.' => 'Refunds are not implemented for this payment system. This action will not issue actual refund. It will just add refund record in aMember and revoke user access. You must go to payment processor and do actual refund if you did not do it yet.', 'Registration IP(Country)' => 'Registration IP(Country)', 'Registrations' => 'Registrations', 'Remember Login remember username/password in cookies' => 'Remember Login remember username/password in cookies', 'Remember Period cookie will be stored for ... days' => 'Remember Period cookie will be stored for ... days', 'Remind Password to Admin' => 'Remind Password to Admin', 'Remind Password to Customer' => 'Remind Password to Customer', 'Remove Category' => 'Remove Category', 'Remove From Dashboard' => 'Remove From Dashboard', 'Remove Group' => 'Remove Group', 'Renew Form (member)' => 'Renew Form (member)', 'Renew on rebill prorate existing license for rebills (do not generate new license)' => 'Renew on rebill prorate existing license for rebills (do not generate new license)', 'Renewal Group Allows you to set up sequential or parallel subscription periods. Subscriptions from the same group will begin at the end of subscriptions from the same group. Subscriptions from different groups can run side-by-side' => 'Renewal Group Allows you to set up sequential or parallel subscription periods. Subscriptions from the same group will begin at the end of subscriptions from the same group. Subscriptions from different groups can run side-by-side', 'Reparing' => 'Reparing', 'Repeat Action Handling' => 'Repeat Action Handling', 'Replace Product' => 'Replace Product', 'Reply To mailbox for replies to message' => 'Reply To mailbox for replies to message', 'Report Bugs' => 'Report Bugs', 'Report Dates' => 'Report Dates', 'Report Period' => 'Report Period', 'Report Settings' => 'Report Settings', 'Report Type' => 'Report Type', 'Reports' => 'Reports', 'Requester History' => 'Requester History', 'Require Approval Notification to Admin' => 'Require Approval Notification to Admin', 'Require Approval Notification to Admin (New Signup)' => 'Require Approval Notification to Admin (New Signup)', 'Require Approval Notification to Affiliate' => 'Require Approval Notification to Affiliate', 'Require Approval Notification to User (New Signup)' => 'Require Approval Notification to User (New Signup)', 'Require Approval Only if Invoice has these Products (Invoice) By default each invoice will be set as "Not Approved" although you can enable this functionality only for selected products' => 'Require Approval Only if Invoice has these Products (Invoice) By default each invoice will be set as "Not Approved" although you can enable this functionality only for selected products', 'Require Strong Password password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars' => 'Require Strong Password password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars', 'Reseller Packages' => 'Reseller Packages', 'Resend' => 'Resend', 'Resend Email' => 'Resend Email', 'Resend Payment Link' => 'Resend Payment Link', 'Resend Signup E-Mail' => 'Resend Signup E-Mail', 'Resource' => 'Resource', 'Restart is not allowed' => 'Restart is not allowed', 'Restore' => 'Restore', 'Restore %s' => 'Restore %s', 'Restore Database from Backup' => 'Restore Database from Backup', 'Restore Password' => 'Restore Password', 'Restored Successfully' => 'Restored Successfully', 'Resume Recurring' => 'Resume Recurring', 'Retreive Access Parameters if necessary' => 'Retreive Access Parameters if necessary', 'Return to Payouts List' => 'Return to Payouts List', 'Revenue Goal' => 'Revenue Goal', 'Root' => 'Root', 'Root Folder' => 'Root Folder', 'Root URL root script URL, usually %s' => 'Root URL root script URL, usually %s', 'Root Url and License Keys' => 'Root Url and License Keys', 'Rule Removed' => 'Rule Removed', 'Run' => 'Run', 'Run Payout' => 'Run Payout', 'Run Rebill Manually' => 'Run Rebill Manually', 'Run Reports' => 'Run Reports', 'SMTP' => 'SMTP', 'SMTP Hostname' => 'SMTP Hostname', 'SMTP Hostname is required if you have enabled SMTP method' => 'SMTP Hostname is required if you have enabled SMTP method', 'SMTP Password' => 'SMTP Password', 'SMTP Port' => 'SMTP Port', 'SMTP Security' => 'SMTP Security', 'SMTP Username' => 'SMTP Username', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (could not be used for multi-select and checkbox fields)', 'SQL Date Format' => 'SQL Date Format', 'SQL field type if you are unsure, choose first type (string)' => 'SQL field type if you are unsure, choose first type (string)', 'Sales Count' => 'Sales Count', 'Sales Statistic' => 'Sales Statistic', 'Salt' => 'Salt', 'Save Advanced Search' => 'Save Advanced Search', 'Save As Preset' => 'Save As Preset', 'Save This Search' => 'Save This Search', 'Saved Credit Cards' => 'Saved Credit Cards', 'Saved Echecks' => 'Saved Echecks', 'Saved Reports' => 'Saved Reports', 'Saved Search' => 'Saved Search', 'Scaling Setting which defines how video is scaled on the video screen. Available options are: fit: Fit to window by preserving the aspect ratio encoded in the file\'s metadata. half: Half-size (preserves aspect ratio) orig: Use the dimensions encoded in the file. If the video is too big for the available space, the video is scaled using the \'fit\' option. scale: Scale the video to fill all available space. Ignores the dimensions in the metadata. This is the default setting.' => 'Scaling Setting which defines how video is scaled on the video screen. Available options are: fit: Fit to window by preserving the aspect ratio encoded in the file\'s metadata. half: Half-size (preserves aspect ratio) orig: Use the dimensions encoded in the file. If the video is too big for the available space, the video is scaled using the \'fit\' option. scale: Scale the video to fill all available space. Ignores the dimensions in the metadata. This is the default setting.', 'Scheduled Recurring Revenue' => 'Scheduled Recurring Revenue', 'Search by Message' => 'Search by Message', 'Second Period' => 'Second Period', 'Second Price' => 'Second Price', 'Second Price price that must be billed for second and the following periods of subscription' => 'Second Price price that must be billed for second and the following periods of subscription', 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form' => 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form', 'Secure Root URL secure URL, usually %s' => 'Secure Root URL secure URL, usually %s', 'Select (Multiple Values)' => 'Select (Multiple Values)', 'Select (Single Value)' => 'Select (Single Value)', 'Select Action of Element' => 'Select Action of Element', 'Select Condition...' => 'Select Condition...', 'Select Product(s) if nothing selected - all products' => 'Select Product(s) if nothing selected - all products', 'Select Type of Element' => 'Select Type of Element', 'Select a plugin' => 'Select a plugin', 'Select option' => 'Select option', 'Selected for E-Mailing' => 'Selected for E-Mailing', 'Self Service' => 'Self Service', 'Self-Service Store Configuration' => 'Self-Service Store Configuration', 'Semicolon' => 'Semicolon', 'Send Autoclose Notification to User aMember will email an autoresponder to user when ticket is closed due to inactivity' => 'Send Autoclose Notification to User aMember will email an autoresponder to user when ticket is closed due to inactivity', 'Send Cancel (due to upgrade) Notifications to User send email to member when he cancels recurring subscription due to upgrade.' => 'Send Cancel (due to upgrade) Notifications to User send email to member when he cancels recurring subscription due to upgrade.', 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member' => 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member', 'Send Cancel Notifications to User send email to member when he cancels recurring subscription.' => 'Send Cancel Notifications to User send email to member when he cancels recurring subscription.', 'Send Copy of All Admin Notifications will be used to send copy of email notifications to admin you can specify more then one email separated by comma: test@email.com,test1@email.com,test2@email.com' => 'Send Copy of All Admin Notifications will be used to send copy of email notifications to admin you can specify more then one email separated by comma: test@email.com,test1@email.com,test2@email.com', 'Send Credit Card Rebill Stats to Admin Credit Card Rebill Stats will be sent to Admin daily. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Send Credit Card Rebill Stats to Admin Credit Card Rebill Stats will be sent to Admin daily. It works for payment processors like Authorize.Net and PayFlow Pro only', 'Send E-Mail Message' => 'Send E-Mail Message', 'Send E-Mail Messages' => 'Send E-Mail Messages', 'Send E-Mail if customer has subscription (required)' => 'Send E-Mail if customer has subscription (required)', 'Send E-Mail if invoice has the following subscriptions (required)' => 'Send E-Mail if invoice has the following subscriptions (required)', 'Send E-Mail only if customer has no subscription (optional)' => 'Send E-Mail only if customer has no subscription (optional)', 'Send E-Mail when subscription expires (required)' => 'Send E-Mail when subscription expires (required)', 'Send E-Mail when the next subscription is started (required)' => 'Send E-Mail when the next subscription is started (required)', 'Send Grid (Web API)' => 'Send Grid (Web API)', 'Send New E-Mail' => 'Send New E-Mail', 'Send Notification When Ticket is Assigned to Admin aMember will email a notification to admin each time ticket is assigned to him' => 'Send Notification When Ticket is Assigned to Admin aMember will email a notification to admin each time ticket is assigned to him', 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket' => 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket', 'Send Notification to Admin When Profile is Changed admin will receive an email if user has changed profile' => 'Send Notification to Admin When Profile is Changed admin will receive an email if user has changed profile', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'Send Registration E-Mail once customer completes signup form (before payment)', 'Send Registration E-Mail to Admin once customer completes signup form (before payment)' => 'Send Registration E-Mail to Admin once customer completes signup form (before payment)', 'Send Registration E-Mail to this user' => 'Send Registration E-Mail to this user', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Send Signup E-Mail once FIRST subscripton is completed', 'Send Test E-Mail' => 'Send Test E-Mail', 'Send message' => 'Send message', 'Send reports to my email' => 'Send reports to my email', 'SendGrid Password' => 'SendGrid Password', 'SendGrid Username' => 'SendGrid Username', 'Sender' => 'Sender', 'Sending Test E-Mail...' => 'Sending Test E-Mail...', 'Sending e-mail (sent to %d from %d)' => 'Sending e-mail (sent to %d from %d)', 'Server Timezone' => 'Server Timezone', 'Session Storage' => 'Session Storage', 'Set Access Permissions' => 'Set Access Permissions', 'Setup/Configuration' => 'Setup/Configuration', 'Setup/Configuration : ' => 'Setup/Configuration : ', 'Shopping Cart Settings' => 'Shopping Cart Settings', 'Short (quantity and total amount)' => 'Short (quantity and total amount)', 'Should be greater than %d' => 'Should be greater than %d', 'Should be greater than 0' => 'Should be greater than 0', 'Should be less then %d' => 'Should be less then %d', 'Show Activation Details in user area' => 'Show Activation Details in user area', 'Show Avatars in Ticket Conversation this option has priority over gravatar if enabled' => 'Show Avatars in Ticket Conversation this option has priority over gravatar if enabled', 'Show Error Message' => 'Show Error Message', 'Show Gravatars in Ticket Conversation more details about gravatar can be found %shere%s' => 'Show Gravatars in Ticket Conversation more details about gravatar can be found %shere%s', 'Show Search Function in FAQ' => 'Show Search Function in FAQ', 'Show invoices with selected statuses' => 'Show invoices with selected statuses', 'Sign In' => 'Sign In', 'Sign Up' => 'Sign Up', 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation' => 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation', 'Signup Form (signup)' => 'Signup Form (signup)', 'Signup Form Configuration' => 'Signup Form Configuration', 'Signup IP' => 'Signup IP', 'Signup Info' => 'Signup Info', 'Signup Messages' => 'Signup Messages', 'Single CheckBoxe' => 'Single CheckBoxe', 'Single Coupon Code' => 'Single Coupon Code', 'Site is temporarily disabled for maintenance' => 'Site is temporarily disabled for maintenance', 'Size' => 'Size', 'Size Width × Height' => 'Size Width × Height', 'Size of input field' => 'Size of input field', 'Size of textarea field Columns × Rows' => 'Size of textarea field Columns × Rows', 'Skip' => 'Skip', 'Skip Index Page if User is Logged-in When logged-in user try to access /amember/index page, he will be redirected to /amember/member' => 'Skip Index Page if User is Logged-in When logged-in user try to access /amember/index page, he will be redirected to /amember/member', 'Skip Line if Exist User with Same Login' => 'Skip Line if Exist User with Same Login', 'So you can manually mark payment as refunded or charged-back. Access will be revoked immediately.' => 'So you can manually mark payment as refunded or charged-back. Access will be revoked immediately.', 'Softsale' => 'Softsale', 'Software version info' => 'Software version info', 'Sometimes, after configuration errors and as result of software problems, aMember users database and third-party scripts databases becomes out of sync. Then you can run rebuild process manually to get databases fixed.' => 'Sometimes, after configuration errors and as result of software problems, aMember users database and third-party scripts databases becomes out of sync. Then you can run rebuild process manually to get databases fixed.', 'Sort' => 'Sort', 'Sort Order' => 'Sort Order', 'Sort order' => 'Sort order', 'Source' => 'Source', 'Space' => 'Space', 'Specific Coupon' => 'Specific Coupon', 'Specified folder is already protected. Please alter existing record or choose another folder.' => 'Specified folder is already protected. Please alter existing record or choose another folder.', 'Specify Exact Dates' => 'Specify Exact Dates', 'Standard PHP Sessions' => 'Standard PHP Sessions', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions', 'Start and Expiration Dates' => 'Start and Expiration Dates', 'Started' => 'Started', 'Step %d of %d' => 'Step %d of %d', 'Stop Recurring' => 'Stop Recurring', 'Street2' => 'Street2', 'String' => 'String', 'Subaffiliate' => 'Subaffiliate', 'Subject is required' => 'Subject is required', 'Submitting...' => 'Submitting...', 'Subscription' => 'Subscription', 'Subscription (Either ID or Title)' => 'Subscription (Either ID or Title)', 'Subscription Begin Date' => 'Subscription Begin Date', 'Subscription Expiration (or next rebill date if subscription is recurring)' => 'Subscription Expiration (or next rebill date if subscription is recurring)', 'Subscription Expire Date' => 'Subscription Expire Date', 'Subscription field should have either numeric value which represent subscription in current installation or title that exactly match product title in aMember. You can find these values at %sManage Products%s page, column # or Title.' => 'Subscription field should have either numeric value which represent subscription in current installation or title that exactly match product title in aMember. You can find these values at %sManage Products%s page, column # or Title.', 'Suggest Feature' => 'Suggest Feature', 'Super Admin' => 'Super Admin', 'Surcharge' => 'Surcharge', 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead' => 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead', 'System Info' => 'System Info', 'THEME' => 'THEME', 'Table' => 'Table', 'Tables to Purge' => 'Tables to Purge', 'Tabulation' => 'Tabulation', 'Target User move information to' => 'Target User move information to', 'Tax Group Name for your reference' => 'Tax Group Name for your reference', 'Tax information ' => 'Tax information ', 'Technical E-Mail Address shown on error pages. If empty, [Admin E-Mail Address] is used' => 'Technical E-Mail Address shown on error pages. If empty, [Admin E-Mail Address] is used', 'Template alternative template for signup page' => 'Template alternative template for signup page', 'Template alternative template for this page' => 'Template alternative template for this page', 'Template alternative template for this video aMember will look for templates in [application/default/views/] folder and in theme\'s [/] folder and template filename must start with [layout]' => 'Template alternative template for this video aMember will look for templates in [application/default/views/] folder and in theme\'s [/] folder and template filename must start with [layout]', 'Terms Text automatically calculated if empty' => 'Terms Text automatically calculated if empty', 'Test E-Mail Settings' => 'Test E-Mail Settings', 'Text' => 'Text', 'Text (unlimited length string/data)' => 'Text (unlimited length string/data)', 'Text E-Mail Unsubscribe Link %link% will be replaced to actual unsubscribe URL' => 'Text E-Mail Unsubscribe Link %link% will be replaced to actual unsubscribe URL', 'Text Link' => 'Text Link', 'Text Links' => 'Text Links', 'Text in your file should be encoded in UTF-8 encoding.' => 'Text in your file should be encoded in UTF-8 encoding.', 'TextArea' => 'TextArea', 'The action has been repeated, ipn script response [%s]' => 'The action has been repeated, ipn script response [%s]', 'The code [%s] is already used by signup form #%s, please choose another code' => 'The code [%s] is already used by signup form #%s, please choose another code', 'The password is entered incorrectly' => 'The password is entered incorrectly', 'Theme to Include to Roster' => 'Theme to Include to Roster', 'There is %s users with same registration IP Address' => 'There is %s users with same registration IP Address', 'This IP is Banned' => 'This IP is Banned', 'This code can be inserted into any HTML page on your website or into any WordPress post or page' => 'This code can be inserted into any HTML page on your website or into any WordPress post or page', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.', 'This field is required for choosen action' => 'This field is required for choosen action', 'This field is requred' => 'This field is requred', 'This is necessary to run aMember CP -> Rebuild DB -> Rebuild Core and Invoice database after import' => 'This is necessary to run aMember CP -> Rebuild DB -> Rebuild Core and Invoice database after import', 'This rule is for particular affiliate groups you can add user groups and assign it to customers in User editing form' => 'This rule is for particular affiliate groups you can add user groups and assign it to customers in User editing form', 'This rule is for particular payment system' => 'This rule is for particular payment system', 'This rule is for particular product categories if none specified, rule works for all product categories' => 'This rule is for particular product categories if none specified, rule works for all product categories', 'This rule is for particular products if none specified, rule works for all products' => 'This rule is for particular products if none specified, rule works for all products', 'This user exceeded %sAccount Sharing Prevention%s limits and temporarily locked.' => 'This user exceeded %sAccount Sharing Prevention%s limits and temporarily locked.', 'This user is not a reseller' => 'This user is not a reseller', 'Ticket Categories' => 'Ticket Categories', 'Ticket#' => 'Ticket#', 'Tickets Assigned to Me' => 'Tickets Assigned to Me', 'Time' => 'Time', 'Time Format' => 'Time Format', 'Title displayed to customers' => 'Title displayed to customers', 'Title of Element' => 'Title of Element', 'Title of Report for your Reference' => 'Title of Report for your Reference', 'Title/Comment/Code' => 'Title/Comment/Code', 'Title/URL/Path' => 'Title/URL/Path', 'To Pay' => 'To Pay', 'To Product' => 'To Product', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions', 'To restore the aMember database please pick a previously saved aMember Pro backup.' => 'To restore the aMember database please pick a previously saved aMember Pro backup.', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):', 'To starting sharing media files, you have to download either free or commercial version of FlowPlayer
      ' => 'To starting sharing media files, you have to download either free or commercial version of FlowPlayer
      ', 'To use coupon from this batch user must have an when user uses coupon, it will be checked that user has one from the following subscriptions' => 'To use coupon from this batch user must have an when user uses coupon, it will be checked that user has one from the following subscriptions', 'To verify import result go to %sBrowse Users%s' => 'To verify import result go to %sBrowse Users%s', 'Top' => 'Top', 'Top %d Affiliates' => 'Top %d Affiliates', 'Top Affiliates' => 'Top Affiliates', 'Top Left' => 'Top Left', 'Top Right' => 'Top Right', 'Total Paid' => 'Total Paid', 'Total to Pay' => 'Total to Pay', 'Trace' => 'Trace', 'Traditional .htpasswd' => 'Traditional .htpasswd', 'Transactions Log' => 'Transactions Log', 'Transactions with this coupon:' => 'Transactions with this coupon:', 'Translation' => 'Translation', 'Trying to copy from unexisting template : %s' => 'Trying to copy from unexisting template : %s', 'Two Columns' => 'Two Columns', 'URL must be specified without trailing slash' => 'URL must be specified without trailing slash', 'URL must start from %s or %s' => 'URL must start from %s or %s', 'Unable to backup cc and config tables. Check "aMember CP -> Error Log" for more info' => 'Unable to backup cc and config tables. Check "aMember CP -> Error Log" for more info', 'Unable to cancel subscription' => 'Unable to cancel subscription', 'Unable to change rebill date' => 'Unable to change rebill date', 'Unable to delete backup tables. Please delete cc_backup and config_backup tables manually Check "aMember CP -> Error Log" for more info ' => 'Unable to delete backup tables. Please delete cc_backup and config_backup tables manually Check "aMember CP -> Error Log" for more info ', 'Unable to find old keyfile. Please upload it to %s Then refresh page' => 'Unable to find old keyfile. Please upload it to %s Then refresh page', 'Unable to load widget: %s' => 'Unable to load widget: %s', 'Unable to restore back in cc_backup and config_backup tablesPlease restore it manually. Check "aMember CP -> Error Log" for more info ' => 'Unable to restore back in cc_backup and config_backup tablesPlease restore it manually. Check "aMember CP -> Error Log" for more info ', 'Unable to resume subscription' => 'Unable to resume subscription', 'Unknown Widget with Id [%s]' => 'Unknown Widget with Id [%s]', 'Unknown mode [%s] in %s->%s' => 'Unknown mode [%s] in %s->%s', 'Unknown protection method' => 'Unknown protection method', 'Unknown report display type [%s]' => 'Unknown report display type [%s]', 'Unlock' => 'Unlock', 'Unpack Upgrades' => 'Unpack Upgrades', 'Unsubscribe from All Emails' => 'Unsubscribe from All Emails', 'Update Error' => 'Update Error', 'Update License Information' => 'Update License Information', 'Update User if Exist User with Same Login' => 'Update User if Exist User with Same Login', 'Update User if Exist User with Same Login (Do Not Overwrite Existing Password)' => 'Update User if Exist User with Same Login (Do Not Overwrite Existing Password)', 'Upgrade' => 'Upgrade', 'Upgrade Database' => 'Upgrade Database', 'Upgrade Download Problem' => 'Upgrade Download Problem', 'Upgrade Finished' => 'Upgrade Finished', 'Upgrade From' => 'Upgrade From', 'Upgrade Price Calculation Type' => 'Upgrade Price Calculation Type', 'Upgrade To' => 'Upgrade To', 'Upload' => 'Upload', 'Upload file [email-templates.xml]' => 'Upload file [email-templates.xml]', 'Uploaded file is not valid aMember Pro backup' => 'Uploaded file is not valid aMember Pro backup', 'Upsell - Replace Product from [Conditions] field' => 'Upsell - Replace Product from [Conditions] field', 'Upsell Configuration' => 'Upsell Configuration', 'Upsell Paths' => 'Upsell Paths', 'Url' => 'Url', 'Url url of the page POST data will be sent to' => 'Url url of the page POST data will be sent to', 'Use Custom Settings' => 'Use Custom Settings', 'Use E-Mail Throttle Queue' => 'Use E-Mail Throttle Queue', 'Use External Cron' => 'Use External Cron', 'Use Global Settings' => 'Use Global Settings', 'Use Locale Preference' => 'Use Locale Preference', 'Use aMember3 Compatible Urls Enable old style urls (ex.: signup.php, profile.php) Usefull only after upgrade from aMember v3 to keep old links working. ' => 'Use aMember3 Compatible Urls Enable old style urls (ex.: signup.php, profile.php) Usefull only after upgrade from aMember v3 to keep old links working. ', 'Use first %d IP address octets to determine different IP (%s)' => 'Use first %d IP address octets to determine different IP (%s)', 'Use the following product for demo users keep it empty to use any products' => 'Use the following product for demo users keep it empty to use any products', 'Use this %slink%s to delete data from aMember v4 database and use clean database for import' => 'Use this %slink%s to delete data from aMember v4 database and use clean database for import', 'Used For' => 'Used For', 'Used Rules' => 'Used Rules', 'Used coupon' => 'Used coupon', 'User Access' => 'User Access', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'User Coupon Usage Count how many times a coupon code can be used by customer', 'User Email' => 'User Email', 'User IP address' => 'User IP address', 'User Id' => 'User Id', 'User Invoices' => 'User Invoices', 'User Login' => 'User Login', 'User Name' => 'User Name', 'User Notes' => 'User Notes', 'User Pages Theme' => 'User Pages Theme', 'User Session Lifetime (minutes) default - 120' => 'User Session Lifetime (minutes) default - 120', 'User currently has access to the following products' => 'User currently has access to the following products', 'User had access to the following products' => 'User had access to the following products', 'User has %s Pending Invoices' => 'User has %s Pending Invoices', 'User is not found in database' => 'User is not found in database', 'User notification' => 'User notification', 'User-Affiliate Relation Lifetime how long (in days) calculate commission for referred affiliate (default: 0 - forever)' => 'User-Affiliate Relation Lifetime how long (in days) calculate commission for referred affiliate (default: 0 - forever)', 'Username Length' => 'Username Length', 'Username of Source User move information from this user to target user, this user will be deleted' => 'Username of Source User move information from this user to target user, this user will be deleted', 'Username or e-mail address' => 'Username or e-mail address', 'Users' => 'Users', 'Users Breakdown' => 'Users Breakdown', 'Users Report' => 'Users Report', 'Utilities' => 'Utilities', 'VAT' => 'VAT', 'VAT Amount' => 'VAT Amount', 'VAT ID' => 'VAT ID', 'VAT Rate' => 'VAT Rate', 'Valid license key are one-line string,starts with L and ends with X' => 'Valid license key are one-line string,starts with L and ends with X', 'Validation Messages to Customer' => 'Validation Messages to Customer', 'Value use % as wildcard mask' => 'Value use % as wildcard mask', 'Value must be alpha-numeric' => 'Value must be alpha-numeric', 'Value must be alphanumeric' => 'Value must be alphanumeric', 'Values must not be equal' => 'Values must not be equal', 'VatId' => 'VatId', 'Verify E-Mail Address On Signup Page e-mail verification may be enabled for each signup form separately at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Verify E-Mail Address On Signup Page e-mail verification may be enabled for each signup form separately at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick', 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick', 'Version Info' => 'Version Info', 'Versions for [%s]' => 'Versions for [%s]', 'Video Player' => 'Video Player', 'Video for Non User this video will be shown instead of actual video in case of non-user try to access protected video content. %sThis video will be public and do not require any login/password%s. You can add new video %shere%s' => 'Video for Non User this video will be shown instead of actual video in case of non-user try to access protected video content. %sThis video will be public and do not require any login/password%s. You can add new video %shere%s', 'Video for User without Proper Membership Level this video will be shown instead of actual video in case of user without proper access try to access protected video content. %sThis video will be public and do not require any login/password%s. You can add new video %shere%s' => 'Video for User without Proper Membership Level this video will be shown instead of actual video in case of user without proper access try to access protected video content. %sThis video will be public and do not require any login/password%s. You can add new video %shere%s', 'Video/Audio File (max upload size %s) You can use this feature only for video and audio formats that %ssupported by %s%s' => 'Video/Audio File (max upload size %s) You can use this feature only for video and audio formats that %ssupported by %s%s', 'View' => 'View', 'View Coupons' => 'View Coupons', 'Void Commission' => 'Void Commission', 'Voided' => 'Voided', 'WARNING! ALL YOUR CURRENT AMEMBER TABLES AND RECORDS WILL BE REPLACED WITH THE CONTENTS OF THE BACKUP!' => 'WARNING! ALL YOUR CURRENT AMEMBER TABLES AND RECORDS WILL BE REPLACED WITH THE CONTENTS OF THE BACKUP!', 'WARNING! All existing e-mail templates will be removed from database!' => 'WARNING! All existing e-mail templates will be removed from database!', 'WARNING! Once [Merge] button clicked, all invoices, payments, logs and other information regarding \'Source User\' will be moved to the \'Target User\' account. \'Source User\' account will be deleted. There is no way to undo this operation!' => 'WARNING! Once [Merge] button clicked, all invoices, payments, logs and other information regarding \'Source User\' will be moved to the \'Target User\' account. \'Source User\' account will be deleted. There is no way to undo this operation!', 'Warnings' => 'Warnings', 'Watchers notify the following admins about new messages in this category' => 'Watchers notify the following admins about new messages in this category', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request', 'Webhooks Queue' => 'Webhooks Queue', 'Weekly' => 'Weekly', 'Widget with Id [%s] has not config form' => 'Widget with Id [%s] has not config form', 'Widgets' => 'Widgets', 'Wrong id' => 'Wrong id', 'Yes, Delete User' => 'Yes, Delete User', 'Yes, assign category' => 'Yes, assign category', 'Yes, assign group' => 'Yes, assign group', 'Yes, do not e-mail this customer for any reasons' => 'Yes, do not e-mail this customer for any reasons', 'Yes, locked' => 'Yes, locked', 'Yes, remove category' => 'Yes, remove category', 'Yes, remove group' => 'Yes, remove group', 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.' => 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.', 'You can assign some coupon codes to specific user. Only this user will be able to use this coupon.' => 'You can assign some coupon codes to specific user. Only this user will be able to use this coupon.', 'You can download %sexample file%s.' => 'You can download %sexample file%s.', 'You can import users from CSV file to aMember.' => 'You can import users from CSV file to aMember.', 'You can not delete your own account' => 'You can not delete your own account', 'You can not merge user with itself' => 'You can not merge user with itself', 'You can not set up exchange rate for past.' => 'You can not set up exchange rate for past.', 'You can save this search for later usage, just give it a descriptive name and press "Save" button.' => 'You can save this search for later usage, just give it a descriptive name and press "Save" button.', 'You can temporary %sdisable auto-locking for this customer for 1 day%s and allow access for his account.' => 'You can temporary %sdisable auto-locking for this customer for 1 day%s and allow access for his account.', 'You don\'t have any affiliate sales on this period yet' => 'You don\'t have any affiliate sales on this period yet', 'You don\'t have any invoices yet' => 'You don\'t have any invoices yet', 'You don\'t have any payments yet' => 'You don\'t have any payments yet', 'You don\'t have any refunds yet' => 'You don\'t have any refunds yet', 'You don\'t have any users yet' => 'You don\'t have any users yet', 'You have currently choosed the following users for e-mail to:' => 'You have currently choosed the following users for e-mail to:', 'You have generated %d demo products and %d demo customers' => 'You have generated %d demo products and %d demo customers', 'You have imported %d customers' => 'You have imported %d customers', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'You have license keys from past versions of aMember, please replace it with latest, one-line keys', 'You have no permissions to perform requested operation' => 'You have no permissions to perform requested operation', 'You have not added any products, your signup forms will not work until you 'Zweryfikuj Adres E-Mail Na Stronie Rejestracyjnej e-mail weryfikacyjny może być włączony dla każdego formularza rejestracyjnego osobno w aMember CP -> Edytor Formularzy -> Edytuj, kliknij "konfiguruj" na ikonie E-Mail', 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Zweryfikuj Nowy Adres E-Mail Na Stronie Profilu e-mail weryfikacyjny dla formularza profilu może być włączony w aMember CP -> Edytor Formularzy -> Edytuj, kliknij "konfiguruj" na ikonie E-Mail', 'Version Info' => 'Informacja o wersji', 'Video Player' => 'Odtwarzacz Wideo', 'View' => 'Widok', 'View Coupons' => 'Przeglądaj Kupony', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Przekażemy żądanie do systemu płatności lub zostaniesz przekierowany na stronę systemu płatności, aby przesła żądanie zwrotu', 'Weekly' => 'Tygodniowo', 'Yes, assign category' => 'Tak, przydziel kategorię', 'Yes, do not e-mail this customer for any reasons' => 'Tak, nie wysyłaj e-maili do tego klienta w żadnym przypadku', 'Yes, locked' => 'Tak, zablokowane', 'Yes, remove category' => 'Tak, usuń kategorię', 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.' => 'Możesz %szapisać%s ten raport na przyszłość. Będziesz mógł dodać ten raport do twojego panelu administracyjnego lub wysyłać okresowo na twój adres e-mail.', 'You can download %sexample file%s.' => 'Możesz ściągnąć %sprzykładowy&nbsp:plik%s.', 'You can import users from CSV file to aMember.' => 'Możesz importować użytkowników z pliku CSV do aMember', 'You can not merge user with itself' => 'Nie możesz scalić użytkownika z samym sobą', 'You have currently choosed the following users for e-mail to:' => 'Obecnie wybrano następujących użytkowników do e-maila:', 'You have generated %d demo products and %d demo customers' => 'Wygenerowałeś %d produktów demo i %d klientów demo', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'Posiadasz klucze licencji z poprzednich wersji aMember, proszę je zastąpić najnowszymi kluczami jednoliniowymi', 'You have no permissions to perform requested operation' => 'Nie masz uprawnień do wykonania żądanej operacji', 'Your Password enter your current password in order to edit admin record' => 'Twoje hasło wprowadź aktualne hasło aby edytować rekord administratora', 'Zip Code' => 'Kod pocztowy', '[From] and [To] billing plans must not be equal' => '[Z] i [Do] plany rozliczeniowe nie mogą być takie same', 'aMember Database (default)' => 'Baza danych aMember (domyślna)', 'aMember will look for templates in [application/default/views/signup/] folder and in theme\'s [signup/] folder and template filename must start with [signup]' => 'aMember będzie szukał szablonów w folderze [application/default/views/signup/] i w folderze motywów [signup/] i nazwa pliku szablonu musi zaczynać się od [signup]', 'access log table (used by admin only)' => 'tablica logów dostępu (używanych tylko przez administratora', 'admin log table (used by admin only)' => 'Tablica logów administratora (używanych tylko przez administratora)', 'after' => 'po', 'allow max' => 'zezwól maksymalnie', 'change' => 'zmiana', 'collapse details' => 'ukryj szczegóły', 'days after expiration' => 'dni po wygaśnięciu', 'days before expiration' => 'dni przed wygaśnięciem', 'days before rebilling' => 'dni przed ponownym zafakturowaniem', 'displaying records %d-%d from %d' => 'Wyświetlane archiwów %d-%d z %d', 'do not show disabled products' => 'nie pokazuj wyłączonych produktów', 'do not show pending invoices' => 'nie pokazuj oczekujących faktur', 'downloads within' => 'pobrań w przeciągu', 'during subscription period' => 'podczas okresu subskrypcji', 'error_log table (used by admin only)' => 'tablica logów błędów (używanych tylko przez administratora)', 'expand details' => 'pokaż szczegóły', 'first paid at' => 'najpierw zapłacone', 'if code is present, products will be hidden in shopping cart and this code is required to see these products' => 'jeśli kod jest dostępny, produkty będą ukryte w koszyku i ten kod jest wymagany aby je zobaczyć', 'if customer uses more than' => 'jeśli klient używa więcej niż', 'if user enters wrong password' => 'jeśli użytkownik wprowadzi niepoprawne hasło', 'leave it empty in case of you want this item be available for all users' => 'zostaw puste jeżeli chcesz aby ta pozycja była dostępna dla wszystkich użytkowników', 'login, email or name' => 'Login, e-mail lub nazwa', 'must be a number in format 99 or 99.99' => 'musi być liczbą w formacie 99 lub 99.99', 'must be equal or greather than 0' => 'musi być równe lub większe od 0', 'must be equal or greather than 0.0' => 'musi być równe lub większe od 0.0', 'on expiration day' => 'w dniu wygaśnięcia', 'open in new window' => 'otwórz w nowym oknie', 'or %smake access free%s' => 'lub %sprzyznaj darmowy dostęp%s', 'put website offline, making it available for admins only' => 'Ustaw stronę w tryb offline, tak że jest widoczna tylko dla administratorów', 'seconds, he will be forced to wait until next try' => 'sekund, będzie zmuszony czekać przed kolejną próbą', 'sending' => 'wysyłanie', 'sent successfully' => 'wysłano pomyślnie', 'switch to show all records' => 'Przełącz, aby pokazać wszystkie rekordy', 'switch to show only active records' => 'przełącz, aby pokazać tylko aktywne rekordy', 'this item is available for %sall registered customers%s. click to %smake this item protected%s %sor %smake this item available without login and registration%s %s' => 'ta pozycja jest dostępna dla %swszystkich zarejestrowanych klientów%s. kliknij, aby %sustawić tę pozycję jako chronioną%s %slub %sustaw tę pozycję jako dostępną bez logowania i rejestracji%s %s', 'this item is available for %sall visitors (without log-in and registration) and for all members%s click to %smake this item protected%s or %smake log-in required%s ' => 'ten product jest dostępny %sall wizytorów (użytkowników bez kont i rejestracji) i dla wszystkich members%s kliknij aby %smake ten produkt protected%s lub %smake logowanie required%s ', 'times within' => 'razy w przeciągu', 'version' => 'wersja', ); PK\$default/language/admin/it.phpnu[ ' alle ', ' day' => 'giorno', ' hour' => ' ore', '"Call Home" functionality - every .. days software will periodically contact your site to check activation and license status enter 0 to disable' => '"Call Home" functionality - every .. days software will periodically contact your site to check activation and license status enter 0 to disable', '# of users' => '# di utenti', '%d days after expiration' => '%d giorni dopo la scadenza', '%d days after payment' => '%d giorni dopo il pagamento', '%d days before expiration' => '%d giorni prima della scadenza', '%d days in advance of recurring payment' => '%d giorni prima del pagamento ricorrente', '%d products…' => '%d products…', '%d user(s) matches your search' => '%d utente(i) che corrispondono alla tua ricerca', '%d-th subscription day' => '%d° giorno di iscrizione', '%s Plugins' => '%s Plugin', '%sEnable%s and %sconfigure%s external cron if you are using E-Mail Throttle Queue' => '%sAbilita%s e %sconfigura%s il cron esterno se stai usando Email Throttle Queue', '%sEnable%s and %sconfigure%s external cron if you are using Periodic E-Mails (Autoresponder/Expiration/Pending Notifications)' => '%sAbilita%se %sconfigura%s il cron esterno se stai usando Email Automatiche (Autorisponditori o Notifiche di Scadenza o Attesa Pagamento)', '-- Filter by Product --' => '-- Filtra per Prodotto --', '-- Please Select --' => '-- Per favore Seleziona --', '-- Without A Category --' => '-- Senza Categoria --', '... %d more rows found ...' => '... %d ulteriori righe trovate ...', '..th subscription day (starts from 2)' => '..imo giorno di iscrizione (parte da 2)', '

      For each item in purchase, aMember will look through all rules, from top to bottom. If it finds a matching multiplier, it will be remembered. If it finds a matching custom rule, it takes commission rates from it. If no matching custom rule was found, it uses "Default" commission settings.

      For n-tier affiliates, no rules are used, you can just define percentage of commission earned by previous level.

      ' => '

      Per ogni acquisto aMember scorrerà tutte le regole dall\'alto verso il basso. Se trova un moltiplicatore che corrisponde sarà ricordato per la prossima volta. La prima Regola Commissioni che corrisponde ai criteri impostati sarà usata per calcolare le commissioni. Se non viene trovata nessuna corrispondenza in alcuna Regola Commissioni verrà usata la regola Commissione Default.

      Per le generazioni successive di affiliati (n-Tier) non vengono usate le regole, ma si definiscono le percentuali per loro al livello precedente.

      ', '

      Message has been sent successfully. Please wait 2 minutes and check the mailbox %s.
      There must be a message with subject [Test E-Mail]. Do not forget to check Spam folder.

      If the message does not arrive shortly, contact your webhosting support and ask them to find
      in mail.log what happened with a message sent from %s to %s at %s

      ' => '

      Messaggio inviato correttamente. Per favore attendi 2 minuti e controlla la casella di posta %s.
      Dovrebbe esserci un messaggio con oggetto [Email di Test]. Non dimenticare di controllare la cartella SPAM.

      Se il messaggio non arriva a breve contatta il tuo webmaster e chiedi
      di controllare nel log delle email cosa è successo al messaggio inviato da %s a %s alle %s

      ', 'A/B Signup Campaign' => 'A/B Test modulo d\'ordine', 'ACTIVE %s' => 'ATTIVO %s', 'ACTIVE category %s' => 'Categoria ATTIVA %s', 'API Keys' => 'Chiavi API', 'Accepted Payout Methods' => 'Pagamenti Payout Accettati', 'Access Method' => 'Metodo di Accesso', 'Access Period' => 'Periodo Accesso', 'Access Permissions this field will be removed from form if access permission does not match and user will not be able to update this field' => 'Permessi di Accesso questo campo verrà rimosso dal form se l\'utente non ha accesso e non potrà modificarlo', 'Account Sharing Prevention' => 'Prevenzione contro la condivisione dell\'account', 'Account Verification' => 'Verifica Account', 'Action' => 'Azione', 'Active (free)' => 'Attivo (gratis)', 'Add & Checkout' => 'Aggiungi e procedi al Pagamento', 'Add & Go to Basket' => 'Aggiungi e vai al Carrello', 'Add Access Manually' => 'Aggiungi Accesso Manuale', 'Add Chargeback' => 'Aggiungi riaccredito', 'Add Child' => 'Aggiungi Figlio', 'Add Invoice' => 'Aggiungi Ricevuta', 'Add Invoice and Payment/Access Manually' => 'Crea Ricevuta e Pagamento/Accesso', 'Add Option' => 'Aggiungi Opzione', 'Add Payment' => 'Aggiungi un Sistema di Pagamento', 'Add Payment Manually' => 'Aggiungi Manualmente un Pagamento', 'Add Pending Invoice and Send Link to Pay It to Customer' => 'Crea Ricevuta in Attesa e invia Link Pagamento', 'Add Refund' => 'Rimborso', 'Add Report to My Dashboard' => 'Aggiungi Report alla mia Bacheca', 'Add Root Node' => 'Aggiungi Elemento Genitore', 'Add Signature to Response' => 'Aggiungi Firma alla Risposta', 'Add Subscription' => 'Aggiungi un Servizio/Prodotto', 'Add To Basket Button Behaviour' => 'Aggiungi al Comportamento del Pulsante Carrello', 'Add User Fields' => 'Aggiungi Campo', 'Add only Access Records' => 'Aggiungi solo i Dati di Accesso', 'Add points to affiliate for each %s in payment' => 'Aggiungi punti all\'affiliato per ogni %s in pagamento', 'Add to Basket and Checkout' => 'Aggiungi al Carrello e procedi al Pagamento', 'Add to Basket and Popup Basket' => 'Aggiungi al Carrello e aprilo', 'Add to Basket only' => 'Aggiungi solo al Carrello', 'Additional' => 'Aggiuntivo', 'Address' => 'Indirizzo', 'Admin Accounts' => 'Account Amministratori', 'Admin E-Mail Address used to send email notifications to admin and as default outgoing address' => 'Indirizzo email dell\'Amministratore utilizzato per inviare notifiche email all\'amministratore e come indirizzo email di uscita di default', 'Admin Email' => 'Email Admin', 'Admin Free Subscription Notifications to admin once free signup is completed' => 'Notifiche Email all\'Amministratore quando un\'iscrizione gratuita è completata', 'Admin Log' => 'Log Amministratori', 'Admin Login Required' => 'Serve il Login Admin', 'Admin Pages Theme' => 'Tema delle pagine di Amministrazione', 'Admin Payment Notifications to admin once payment is received' => 'Notifica di pagamento all\'Amministratore una volta che il pagamento è terminato', 'Admin Recipients' => 'Destinatari Admin', 'Admin Settings' => 'Settaggi Amministratore', 'Admin notification' => 'Notifiche all\'Amministratore', 'Admin username must be alphanumeric in small caps' => 'Lo username dell\'Amministratore deve essere alfanumerico e composto da caratteri minuscoli', 'Administrator Login' => 'Login Amministratore', 'Administrator has been removed, id [%d]' => 'L\'Amministratore è stato rimossi, id [%d]', 'Advanced Settings' => 'Settaggi Avanzati', 'Affiliate %s not found' => 'Affiliato %s non trovato', 'Affiliate Can View Sales Details Leave this checkbox unselected to restrict affiliates from seeing their sales details' => 'Affiliato può vedere Dettagli Vendita meglio non spuntare per motivi di privacy', 'Affiliate Commission' => 'Commissioni di Affiliazione', 'Affiliate Commission Details for' => 'Dettagli Commissioni di Affiliazione per ', 'Affiliate Commission Rules' => 'Regole Commissioni Affiliati', 'Affiliate Cookie Lifetime days to store cookies about referred affiliate' => 'Durata dei Cookie di Affiliazione indica i giorni di validità del click affiliato', 'Affiliate Email' => 'Amail Affiliato', 'Affiliate Id' => 'ID Affiliato', 'Affiliate Information' => 'Informazioni Affiliato', 'Affiliate Login' => 'Login Affiliato', 'Affiliate Name' => 'Nome Affiliato', 'Affiliate Payout Conversion Rate how many credits affiliate should recieve for %s' => 'Affiliate Payout Conversion Rate how many credits affiliate should recieve for %s', 'Affiliate Payout Paid Notification to User send email to user when his payout is marked as paid' => 'Notifica Pagamento Payout Affiliato inviata all\'affiliato se il suo payout è segnato "pagato"', 'Affiliate Registration E-Mail' => 'e-mail Registrazione Affiliato', 'Affiliate Registration Notification to Admin' => 'Notifica Registrazione Affiliato ad Admin', 'Affiliate items count trigger this commission if affiliate made more than ... item sales within ... days before the current date (only count of items in new invoices is calculated' => 'Affiliate items count trigger this commission if affiliate made more than ... item sales within ... days before the current date (only count of items in new invoices is calculated', 'Affiliate sales amount trigger this commission if affiliate made more than ... sales within ... days before the current date (only new invoices calculated)' => 'Affiliate sales amount trigger this commission if affiliate made more than ... sales within ... days before the current date (only new invoices calculated)', 'Affiliate sales count trigger this commission if affiliate made more than ... sales within ... days before the current date (only count of new invoices is calculated)' => 'Affiliate sales count trigger this commission if affiliate made more than ... sales within ... days before the current date (only count of new invoices is calculated)', 'Affiliates Payout Day choose a day of month when payout is generated' => 'Giorno di Pagamento dell\'affiliato seleziona un giorno del mese in cui generare il pagamento', 'Affiliates Signup Type' => 'Tipo di Iscrizione Affiliato', 'After making any changes to htpasswd protected areas, please run [Utiltites->Rebuild Db] to refresh htpasswd file' => 'Dopo aver effettuato i cambiamenti nelle cartelle contenenti il file di protezione htpasswd, aggiorna il database [Utiltites->Rebuild Db] per agiornare anche il file htpasswd', 'All Banners' => 'Tutti', 'All Content' => 'Tutti i Contenuti', 'All Content Page' => 'Tutte le Pagine', 'All Products List' => 'Tutti i Prodotti', 'All Subscription Period' => 'Tutto il Periodo di Iscrizione', 'All new users automatically become affiliates' => 'Tutti i Nuovi Utenti diventano automaticamente Affiliati', 'Allow Affiliates to redirect Referrers to any url' => 'Permetti Affiliati di redirigere i riferiti a qualsiasi url', 'Allow Redirects to Other Domains By default aMember does not allow to redirect to foreign domain names via \'amember_redirect_url\' parameter. These redirects are only allowed for urls within your domain name. This is restricted to avoid potential security issues. ' => 'Permetti Redirect ad Altri Domini di default aMember non permette il redirect a domini esterni tramite il parametro \'amember_redirect_url\' per kotivi di sicurezza. ', 'Allow cancel recurring subscription from user account' => 'Permetti Cancellazione Abbonamenti dall\'utente nel suo accout personale', 'Allow for some affiliates, disallow for others' => 'Permetti ad alcuni Affiliati, disabilita per altri', 'Allow redirecting to external URLs' => 'Permetti il redirect a URL esterni', 'Allow resume cancelled recurring subscription' => 'Permetti Riattivazione Abbonamenti', 'Allow to Use Password Hash from 3ty part Scripts to Authenticate User in aMember you need to enable this option only if you imported users from 3ty part script without known plain text password' => 'Permetti Password Hash da Software Terzi ti serve questa opzione solo se importi utenti da Software in cui la password non è visibile ma è crittografata.', 'Allow usage of coupons for %sUpgrade paths%s' => 'Permetti Utilizzo Buoni Sconto anche nei %sPercorsi di Aggiornamento%s', 'Allow use Cart only to Registered Users' => 'Permetti di usare il Carrello solo agli utenti registrati', 'Allowed E-Mails Count enter number of emails allowed within the period above' => 'Numero di E-mail permesso inserisci il numero delle email permesse, comprese nel periodo indicato sopra', 'Allowed E-Mails Period choose if your host is limiting e-mails per day or per hour' => 'Periodo permesso per le E-mail seleziona se il tuo host limita le email per giorni o per ore', 'Always Remember if set to Yes, don\'t ask customer - always remember' => 'Da Ricordare se scegli SI, non chiedere all\'utente - da ricordare sempre', 'American Date Format' => 'Formato Data Americano', 'Amount excl. Tax' => 'Importo Tasse escluse', 'Amount excl. VAT' => 'Importo IVA/VAT esclusa', 'An Admin Account with the same email already exists.' => 'C\'è già un account Admin con questo indirizzo email', 'Any Coupon' => 'Qualsiai buono Sconto', 'Apply Tax?' => 'Applicare le Tasse?', 'Apply this rule if affiliate has active access to' => 'Applica questa regola se l\'affiliato ha ', 'Apply to recurring? apply coupon discount to recurring rebills?' => 'Applicare ai Pagamento Ricorrenti? Vuoi applicare lo sconto ai pagamenti ricorrenti?', 'Approve' => 'Approva', 'Archive' => 'Archivio', 'Assign Category' => 'Assegna una Categoria', 'Assign Paysystem to Product' => 'Assegna Sistema di Pagamento al Prodotto', 'At least one billing plan must be added' => 'Deve essere aggiunto almeno un piano di pagamento ', 'Attach PDF Invoice' => 'Allega Ricevuta PDF', 'Attached User Data (XML)' => 'Dati Utente Allegati (XML)', 'Auto Buffering whether loading of clip into player\'s memory should begin straight away. When this is true and autoPlay is false then the clip will automatically stop at the first frame of the video.' => 'Auto Buffering fa caricare subito il file nella memoria del player. Se metti Sì a questo e No ad Auto Play il video si ferma al primo frame.', 'Auto Play whether the player should start playback immediately upon loading' => 'Auto Play al caricamento del video', 'Auto-locking for this customer is temporary disabled until %s' => 'Auto-blocco per questo cliente è temporaneamente disacilitato fino %s', 'Autoclose Tickets Due to Inactivity' => 'Chiudi Automaticamente i Ticket per inattività', 'Automatically Login Customer After Signup' => 'Login Automatico Utenti dopo la registrazione/pagamento', 'Autoresponder message will be automatically sent by cron job when configured conditions met. If you set message to be sent after payment, it will be sent immediately after payment received. Auto-responder message will not be sent if:
      • User has unsubscribed from e-mail messages
      ' => 'Le Email dell\'Autorisponditore saranno inviate automaticamente dal CRON quando le condizioni impostate sono raggiunte. Se hai impostato la spedizione del messaggio dopo il pagamento, sarà spedito immediatamente dopo il pagamento. Le Email dell\'Autorisponditore non saranno inviate se:
      • L\'Utente si è cancellato dai messaggi email
      ', 'Available' => 'Disponibile', 'Available Locales defines both language and date/number formats, default locale is always enabled' => 'Lingue Disponibili sia lingua che formato data/numeri quella di default è sempre attiva', 'Available Products' => 'Prodotti Disponibili', 'Available Upgrades' => 'Aggiornamenti Disponibili', 'Available for users from groups' => 'Disponibile per gli utenti dei gruppi', 'BCC blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients' => 'BCC blind carbon copy allows the sender of a message to conceal the person entered in the Bcc field from the other recipients', 'BEGIN' => 'INIZIA', 'Back to Countries' => 'Torna alle Nazioni', 'Back to Dashboard' => 'Torna alla Bacheca', 'Back to FAQ List' => 'Torna alla lista delle FAQ', 'Backup can be runned by POST request only' => 'Il Backup può essere lanciato solo da un richiesta POST', 'Banner' => 'Banner', 'Banner Categories' => 'Categorie Banner', 'Banners' => 'Banner', 'Basket HTML Code' => 'Codice HTML del Carrello', 'Begin date should be before Expire date' => 'Data Inizio deve essere precedente a Data Scadenza', 'Bi-Weekly (on %s)' => 'Bi-Settimanale (on %s)', 'Billing' => 'Fatturazione', 'Billing Terms' => 'Termini Pagamento', 'Bind To activation will be tied to the following installation parameters usually 1 choice is quite enough' => 'Bind To activation will be tied to the following installation parameters usually 1 choice is quite enough', 'Bindings' => 'Vincoli', 'Blob (unlimited length binary data)' => 'Blob (lunghezza illimitata dati binari)', 'Block This IP Address' => 'Blocca questo IP', 'Blocking IP/E-Mail' => 'Blocco IP/Email', 'Both Form (signup & member)' => 'Entrambi i Form (modulo ordine & accesso membri)', 'Briefly unavailable for scheduled maintenance. Check back in a minute.' => 'Temporaneamente non disponibile per manutenzione programmata. Ritorna tra qualche minuto.', 'Browse' => 'Visualizza', 'Browse Countries' => 'Scegli Nazione', 'Browse Found Users' => 'Visualizza utenti trovati', 'Browse States' => 'Scegli Provincia', 'Browse Users' => 'Ricerca Utenti', 'Browse Webhooks' => 'Scegli Webhook', 'Bruteforce Notification notify admin when bruteforce attack is detected' => 'Notifica Forzatura Password inviata ad Admin se viene rilevata una violazione', 'Bruteforce Protection' => 'Protezione Forzata', 'Buffer Length The amount of video data (in seconds) which should be loaded into Flowplayer\'s memory in advance of playback commencing.' => 'Dimensioni Buffer (secondi) quanto video deve essere caricato nella memoria di Flowplayer prima dell\'esecuzione.', 'Build Demo' => 'Genera una Demo', 'Building demo records' => 'Crea dei Record demo', 'Button/Link HTML Code' => 'Codice HTML Pulsante/Link', 'By Affiliate Active Product' => 'Per Prodotto Attivo Affiliato', 'By Affiliate Active Product Category' => 'Per Categoria Prodotto Attivo Affiliato', 'By Affiliate Group Id' => 'Per Gruppo Affiliato', 'By Affiliate Item Sales Count' => 'Per Numero Prodotti Venduti Affiliato', 'By Affiliate Sales Amount' => 'Per Ammontare Vendite Affiliato', 'By Affiliate Sales Count' => 'Per Numero di Vendite Affiliato', 'By Product' => 'Per Prodotto', 'By Product Category' => 'Per Categoria Prodotto', 'By Used Coupon' => 'Per Buono Sconto', 'By Used Payment System' => 'Per Sistema di Pagamento', 'CONTINUE' => 'CONTINUA', 'Calculate Affiliate Commissions from Totals Including Tax by default commission calculated from amounts before tax' => 'Includi IVA nelle Commissioni Affiliato di default aMember calcola le commissioni escludendo IVA', 'Calculate Commission' => 'Calcola Commissioni', 'Calculate Commission for this Invoice' => 'Calcola Commissioni per questa Ricevuta', 'Campaign Title for admin reference' => 'Campaign Title for admin reference', 'Campaign Type' => 'Tipo Campagna', 'Can not find user with such username' => 'Non trovo un utente con questo Nome Utente', 'Can not find user with such username or email' => 'Impossibile trovare qualcuno con questi Nome Utente o Email', 'Can not save config for dashboard widget without config form [%s]' => 'Non posso salvare la bacheca senza il Form Config [%s]', 'Can\'t be changed because your server have suhosin extension enabled' => 'Non può essere cambiato perché il tuo server ha le estensioni suhosin abilitate', 'Cancel All Changes in Translations on Current Page' => 'Cancella tutte le Traduzioni su questa pagina', 'Cancellations' => 'Cancellazioni', 'Categories List' => 'Lista Categorie', 'Category root category of hierarchy which included to shopping cart all categories is included by default' => 'Category root category of hierarchy which included to shopping cart all categories is included by default', 'Change Configuration Settings' => 'Cambia la Configurazione', 'Change Invoice Rebill Date' => 'Cambia Data Riaddebito Ricevuta', 'Change Order' => 'Cambia Ordine', 'Change Password Notification send email to user after password change' => 'Notifica Cambio Passwrod inviata all\'utente dopo il cambio password', 'Change Paysystem' => 'Cambia Sistema di Pagamento', 'Change rebill date' => 'Cambia Data Riaddebito', 'Charge Second Price Once' => 'Addebita una sola seconda volta il prezzo', 'Charge Second Price x Times' => 'Addebita per x volte il prezzo', 'Check for beta version' => 'Controlla se c\'è una Versione Beta', 'Check other Affiliate Program Settings' => 'Controlla altre Impostazioni Programma di Affiliazione', 'CheckBoxes' => 'CheckBox', 'Choose %1$sFile%2$s > %1$sSave As%2$s.' => 'Scegli %1$sFile%2$s > %1$sSalva con nome%2$s.', 'Choose Products and/or Product Categories that allows access' => 'Scegli il Prodotto o la Categoria di Prodotti che permette l\'accesso', 'Choose Upgrades to Install' => 'Scegli gli Aggiornamenti da installare', 'Choose a plugin' => 'Scegli un Plugin', 'Choose action when locked %s used by customer during signup' => 'Scegli l\'azione da fare quando un utente usa %s bloccato durante la registrazione', 'Choose another Report' => 'Scegli un altro Report', 'Clean up data. Please wait...' => 'Sto pulendo i dati. Attendi...', 'Clean up v4 Database' => 'Pulisco v4 Database', 'Clean up...' => 'Sto pulendo...', 'Cleaning up' => 'Sto facendo Pulizia', 'Cleanup' => 'Pulizia', 'Clear' => 'Libera', 'Clear Access Log' => 'Pulisci i Log di Accesso', 'Clear Incomplete Invoices' => 'Cancella Ricevute non Pagate', 'Clear Incomplete Users' => 'Cancella Utenti non Paganti', 'Click Tracking Code' => 'Codice Tracciamento Affiliati', 'Click to Expand' => 'Clicca per Aprire', 'Closed Tickets' => 'Ticket Chiusi', 'Code Length generated coupon code length between 4 and 32' => 'Lunghezza del Buono Sconto tra 4 e 32', 'Collapse Menu' => 'Chiudi Menu', 'Comma' => 'Virgola', 'Comment for Your Reference' => 'Nota per tua referenza', 'Commission % of commission received by referred affiliate' => 'Commission % of commission received by referred affiliate', 'Commission earned' => 'Commissione Guadagnata', 'Commission for First Payment calculated for first payment in each invoice' => 'Commissione per il Primo Pagamento calcolata per il primo pagamento in ogni ricevuta', 'Commission for Free Signup calculated for first customer invoice only' => 'Commissione per la Registrazione Gratuita calcolata solo quando l\'utente si iscrive', 'Commission for Rebills' => 'Commissione per i Pagamenti Ricorrenti', 'Commissions Included to Payout' => 'Commissioni Incluse nel Payout', 'Completed!' => 'Completato!', 'Conditions' => 'Condizioni', 'Config values updated...' => 'Configurazione aggiornata correttamente...', 'Configured License Keys' => 'Configurazione Codice Licenza', 'Confirmed Manually' => 'Confermato Manualmente', 'Consumer Email' => 'Email Cliente', 'Consumer Name' => 'Nome Cliente', 'Consumer Sales' => 'Vendite Cliente', 'Copy' => 'Copia', 'Copy Upgrades' => 'Copia Aggiornamenti', 'Copy from another language' => 'Copia da un\'altra lingua', 'Could not download file [%s]. Error %s. Please %stry again%s later.' => 'Non si possono scaricare i file [%s]. Errore %s. Per favore %sriprova piu\' tardi%s.', 'Could not fetch upgrades list from remote server. %sTry again%' => 'L\'upgrade non puo\' essere effettuato dal server remoto. %sRiprova ancora%', 'Could not fetch upgrades list. Connection error [%s]' => 'Non si riesce a ricavare la lista aggiornamenti. Errore di Connessione [%s]', 'Could not load payment plugin [%s]' => 'Non riesco ad installare il Plugin Pagamento [%s]', 'Could not move uploaded file' => 'Non riesco a spostare il file caricato ', 'Could not open folder [%s] to remove .htaccess from it. Do it manually' => 'Non riesco ad aprire la Cartella [%s] per rimuovere il file .htaccess. Fallo manualmente', 'Could not read XML' => 'Non riesco a laggere file XML', 'Could not write file [%s] - check file permissions and make sure it is writeable' => 'Non riesco a scrivere sul file [%s] - controlla i permessi del file e assicurati che sia scrivibile', 'Counrty Title' => 'Nome Nazione', 'Count all IP as different' => 'Considera tutti gli IP diversi', 'Count of Licenses' => 'Numero di Licenze', 'Countries/States' => 'Nazioni', 'Country Confirmed by User' => 'Nazione Confermata dall\'Utente', 'Country: %s' => 'Nazione: %s', 'Coupon Codes' => 'Codici Buoni Sconto', 'Coupon From Batch' => 'Buono Sconto dal Gruppo', 'Coupon used for %d transactions' => 'Buono Sconto usato per %d pagamenti', 'Coupon with such code is already exits' => 'Esiste già un Buono Sconto con questo codice', 'Coupons' => 'Buoni Sconto', 'Coupons Batches' => 'Buoni Sconto Disponibili', 'Coupons Count how many coupons need to be generated' => 'Numero Buoni Sconto quanti buoni sconto devono essere generati?', 'Create Folder' => 'Crea cartella', 'Create Session Key' => 'Crea una Chiave di Sessione', 'Create ticket as' => 'Crea Ticket come', 'Credit' => 'Credito', 'Credit Card Expiration Notice if saved customer credit card expires soon, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Credit Card Expiration Notice if saved customer credit card expires soon, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only', 'Credit Card Plugins' => 'Plugin Carte di Credito', 'Credit Card Rebill Failed if credit card rebill failed, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Notifica Riaddebito Carta Fallito inviata al Cliente, funziona solo con sistemi come Authorize.Net e PayFlow Pro', 'Credit Card Rebill Successfull if credit card rebill was sucessfull, user will receive the following e-mail message. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Notifica Riaddebito Carta Avvenuto inviata al Cliente, funziona solo con sistemi come Authorize.Net e PayFlow Pro', 'Credit Type' => 'Tipo Credito', 'Cron Last Run' => 'Ultima Esecuzione Cron', 'Cron job has been running last time %s, it is more than 24 hours before. Most possible external cron job has been set incorrectly. It may cause very serious problems with the script. You can find info how to set up cron job for your installation
      here.' => 'Cron job has been running last time %s, it is more than 24 hours before. Most possible external cron job has been set incorrectly. It may cause very serious problems with the script. You can find info how to set up cron job for your installation here.', 'Current Server Date and Time' => 'Data e Ora correnti del Server', 'Custom Commission Rules added' => 'Regole delle Commissioni Personalizzate aggiunte', 'Custom HTML' => 'HTML Personalizzato', 'Custom Signup Form Title keep empty to use default title' => 'Titolo del Modulo Iscrizione lascia il campo vuoto per usare il titolo di default', 'Customer' => 'Cliente', 'Customer Country' => 'Nazione Cliente', 'Customize Dashboard' => 'Personalizza la Bacheca', 'Daily' => 'Ogni giorno', 'Data' => 'Dati XML', 'Date Format' => 'Formato Data', 'Date Of Transaction' => 'Data Transazione', 'Date Time' => 'Data Ora', 'Date to Purge all records prior to this date will be removed from selected tables' => 'Data da cui Cancellare tutti i record inseriti prima di questa data verranno rimossi dalle tabelle selezionate', 'Dates date range when coupon can be used' => 'Date Intervallo di tempo entro il quale il Buono Sconto può essere usato', 'Dates can be in the folowing formats' => 'Le Date posso essere nei seguenti formati', 'Days to Send' => 'Giorni in cui Spedire', 'Debit' => 'Debito', 'Default - user clicks a link to become affiliate' => 'Default - l\'utente clicca su un link per diventare affiliato', 'Default Billing Plan' => 'Piano di Pagamento di default', 'Default Commission' => 'Commissione di Default', 'Default Index Page' => 'Pagina Index di Default', 'Default Locale' => 'Lingua di Default', 'Default Not Found Page' => 'Pagina 404 di Default', 'Default Signup' => 'Modulo Iscrizione di Default', 'Default Size width×height' => 'dimensioni Default larghezza×altezza', 'Default for Members' => 'Default per i Membri', 'Default for Profile' => 'Default per il Profile', 'Default value for field (that is default value for inputs, not SQL DEFAULT)' => 'Valore di default per il campo (questo è il valore di default del campo, non quello di SQL)', 'Delay Payout (days) number of days that should go through before commision is included to payout report' => 'Ritardo Calcolo Payout (giorni) giorni attesa per includere una commissione nel payout (utile per periodi di garanzia)', 'Delete Old Records' => 'Cancella i Vecchi Record', 'Delete Preset' => 'Cancella Preselezioni', 'Delete Saved Search?' => 'Cancella la Ricerca Salavata?', 'Delete User' => 'Cancella Utente', 'Delete payment and access record' => 'Cancella i Record di Accesso e Pagamento', 'Delimiter' => 'Delimitatore', 'Demo History' => 'Storia della Demo', 'Description displayed to visitors on order page below the title' => 'Descrizione visualizzata ai visitatori sulla pagina di ordine subito sotto il titolo', 'Detailed Rebill Report for %s' => 'Report Dettagliato Riaddebiti per %s', 'Details' => 'Dettagli', 'Die and show ugly error message' => 'Fermati e mostra il triste messaggio di errore', 'Digits and latin letters only please' => 'Solo numeri e lettere latine per favore', 'Disable All Campaigns' => 'Disabilita Tutte le Campagne', 'Disable Checking for aMember Updates' => 'Disabilita Controllo Aggiornamenti aMember', 'Disable Customer Account' => 'Disabilita Account Cliente', 'Disable New Signups' => 'Disabilita Nuove Registrazioni', 'Disable Visual HTML Editor' => 'Disabilita Editor HTML', 'Disable auto-locking for this customer' => 'Disabilita il blocco automatico per questo cliente', 'Disallow for some affiliates, allow for others' => 'Disabilita per alcuni affiliati, abilita per altri', 'Disallow new Signups by %s' => 'Disabilita nuove Registrazione da %s', 'Disallow ordering of this product if user has when user orders this subscription, it will be checked that he has no any from the following subscriptions' => 'Non permettere l\'ordinazione del prodotto se l\'utente ha (quando l\'utente ordina questa iscrizione, verrà controllato che non abbia già accesso si seguenti prodotti/servizi)', 'Disallow use of coupon from this batch if user has when user uses coupon, it will be checked that he has no any from the following subscriptions' => 'Per usare il Buono Sconto l\'utente non deve essere se lasci vuoto questa cosa non viene considerata', 'Disclaimer of Credit Card Recurring Billing' => 'Termini per il riaddebito ricorrente su Carta Di Credito', 'Disclosure Admin real name in user interface otherwise only word Administrator is shown' => 'Disclosure Admin real name in user interface otherwise only word Administrator is shown', 'Discount additional discount to invoice total besides coupon' => 'Sconto Aggiuntivo rispetto all\'eventuale Buono Sconto', 'Display Language Choice' => 'Visualizza la Scelta delle Lingue', 'Display Mode' => 'Modalità Visualizzazione', 'Display error message' => 'Visualizza Messaggio di Errore', 'Display inside layout When displaying to customer, will the header/footer from current theme be displayed?' => 'Utilizza Layout Utente Mostra Testata e Piè di Pagina di default', 'Do not Allow Spaces in Username' => 'Non permettere spazi nel Nome Utente', 'Do not Lowercase Username by default, aMember automatically lowercases entered username here you can disable this function' => 'Non rendere minuscolo Nome Utente di default, aMember rende minuscoli i Nomi Utente qui puoi disabilitare questo automatismo.', 'Do not Show Unsubscribe Block on Member Page' => 'Non Mostrare "Gestione Newsletter" nell\'account utente (apposita sezione)', 'Do not create invoice. Add only access record' => 'Non creare la ricevuta, abilita solo l\'accesso', 'Do not generate products use existing products for demo records' => 'Non generare nuovi prodotti usa i prodotti esistenti per le demo', 'Do not include Unsubscribe Link into e-mails' => 'Non Mettere Link Cancellazione in fondo a tutte le email inviate', 'Do not include records with empty VAT' => 'Non includere risultati senza P.IVA/VAT', 'Do you really want to Calculate Commission for this invoice? Commission will be added to affiliate account.' => 'Vuoi veramente calcolare le commissioni per questa ricevuta? Le commissioni saranno aggiunte all\'account affiliato.', 'Do you really want to Delete User %s?' => 'Vuoi veramente cancellare l\'utente %s?', 'Do you really want to change Rebill Date for this invoice?' => 'Vuoi veramente cambiare data di riaddebito per questa Ricevuta?', 'Do you really want to delete product?' => 'Vuoi veramente cancellare il prodotto?', 'Do you really want to delete this item?' => 'Vuoi veramente cancellare questo elemento?', 'Do you really want to refund payment' => 'Vuoi veramente rimborsare il pagamento?', 'Do you really want to restore product?' => 'Vuoi veramente riattivare questo prodotto?', 'Do you really want to resume this subscription?' => 'Vuoi veramente riattivare questo abbonamento?', 'Do you really want to stop this subscription?' => 'Vuoi veramente chiudere questa iscrizione?', 'Do you really want to void this commission?' => 'Vuoi veramente cancellare questa commissione?', 'Documentation' => 'Documentazione', 'Does Not Allow to Upload Attachments for Users' => 'Non permettere di caricare allegati agli utenti', 'Does Not Quote Message in Reply' => 'Non riportare il messaggio originale nella risposta', 'Does Not Require Login to Access FAQ Section make it public' => 'Does Not Require Login to Access FAQ Section make it public', 'Does Not Show FAQ Tab in Member Area' => 'Non mostrare il menù FAQ nell\'account utente', 'Download Backup / Restore from Backup' => 'Scarica Backup / Rispristina Backup', 'Download CSV' => 'Scarica CSV', 'Download CSV File' => 'Scarica File CSV', 'Download Upgrades' => 'Scarica gli Aggiornamenti', 'Due Date' => 'Scadenza', 'Duration:' => 'Durata:', 'E-Mail Address to Send to' => 'Indirizzo E-Mail a cui inviare', 'E-Mail Backup Address' => 'Email per Backup', 'E-Mail Commission to Admin' => 'E-Mail di Commissione per l\'Amministratore', 'E-Mail Commission to Affiliate' => 'E-Mail di Commissione per l\'Affiliato', 'E-Mail Database Backup' => 'Email per Backup Database', 'E-Mail Messages on Rebilling Event' => 'Messaggi Email per Pagamenti Ricorrenti', 'E-Mail Payment Receipt to User every time payment is received' => 'Email Ricevuta Pagamento al Cliente inviata ogni volta che fa un pagamento', 'E-Mail Queue' => 'Coda e-mail', 'E-Mail Sender Name used to display name of sender in outgoing e-mails' => 'Nome del Mittente nome del mittente che sarà visualizzato nelle email in uscita', 'E-Mail Sending' => 'Sto inviando l\'E-Mail', 'E-Mail System Configuration' => 'Configurazione Sistema Email', 'E-Mail Type' => 'Tipo di E-Mail', 'E-Mail Users' => 'E-Mail ai Clienti', 'E-Mail has been successfully sent to %s customers. E-Mail Batch ID is %s' => 'E-Mail inviata con successo al %s utente. E-Mail ID: %s', 'E-Mail sending started' => 'Iniziato l\'invio delle e-mail', 'E-Mails History' => 'Storico E-Mail', 'E-Mails by Admin Request' => 'E-Mail richieste dall\'Amministratore', 'E-Mails by User Request' => 'E-Mails richieste dal Cliente', 'EU VAT Report Details' => 'Report Dettagli EU VAT', 'EU Vat Report' => 'Report EU VAT', 'EXPIRED %s' => 'SCADUTO %s', 'EXPIRED category %s' => 'SCADUTO categoria %s', 'Earn points for %s in payment' => 'Guadagna Punti per %s acquistando', 'Echeck Plugins' => 'Plugin Echeck', 'Edit Custom Commission Rules' => 'Modifica le Regole di Commissione', 'Edit Groups' => 'Modifica i Gruppi', 'Edit Messages' => 'Traduci aMember', 'Edit Options' => 'Modifica Opzioni', 'Edit Product' => 'Modifica Prodotto', 'Edit States' => 'Modifica Provincie', 'Email Addresses Separated by Comma' => 'Indirizzi email separati da virgola', 'Email Admin Regarding Account Sharing' => 'Manda email ad Admin per violazione Condivisione Account', 'Email Backup Frequency' => 'Frequenza di backup E-mail', 'Email Domain used to generate email address for users' => 'Dominio Email per generare le email degli utenti', 'Email Layouts' => 'Layout Email', 'Email Sending method PLEASE DO NOT CHANGE if emailing from aMember works' => 'Metodo invio email PER FAVORE NON CAMBIARE se l\'invio E-mail da aMember funziona', 'Email Sent' => 'Email Inviata', 'Email Template Layouts' => 'Template Layout Email', 'Email Template with Payment Link' => 'Template Layout con Link Pagamento', 'Email User Regarding Account Sharing' => 'Manda email all\'Utente per violazione Condivisione Account', 'Email address is required field.' => 'L\'indirizzo email è obbligatorio', 'Email has been send' => 'Email Spedita', 'Email is required if you have enabled Email Backup Feature' => 'Email obbligatoria se hai abilitato la funzionalità Backup via Email', 'Emails' => 'Email', 'Empty Payout Method Notification to User send email to user in case he has commission but did not define payout method yet. This email will be sent only once.' => 'Notifica Metodo di Pagamento Affiliato spedita UNA SOLA VOLTA se l\'affiliato ha commissioni ma non ha definito il metodo pagamento payout.', 'Enable Click Tracking Code Enable ability to track affiliate clicks on any page on your site' => 'Abilita Codice Tracciamento Affiliati permetti di tracciare link a qualsiasi pagina del tu sito', 'Enable Keywords Support Enable ability to track traffic sources adding keywords to url' => 'Abilita Supporto Keyword per tracciare sorgenti di traffico con le keyword', 'Enable Live Conversation (experimental) update conversation instantly without page reload (can consume more server resources)' => 'Enable Live Conversation (experimental) update conversation instantly without page reload (can consume more server resources)', 'Enable plugins if necessary' => 'Abilita Plugin se necessario', 'Enable use of coupons allow use coupons on shopping cart checkout page' => 'Enable use of coupons allow use coupons on shopping cart checkout page', 'Encrypted Pass' => 'Password Crittografata', 'Encrypted Password' => 'Password Crittografata', 'Enter Maintenance Mode' => 'Inserisci la modalità manutenzione', 'Enter admin password for confirmation' => 'Inserisci la Password di Amministratore per conferma', 'Enter title for your new category' => 'Inserisci nome della nuova Categoria', 'Error Log' => 'Log Errori', 'Error deleting record! Please refresh page and try again' => 'Errore cancellando l\'elemento! Ricarica la pagina e prova di nuovo', 'Error during e-mail sending' => 'errore durante la spedizione email', 'Error occurred, please check Errors Log for clue' => 'C\'è stato un errore, consulta il Log Errori per capire meglio', 'Error/Debug Log' => 'Log Errore/Debug ', 'Errors' => 'Errori', 'Errors:' => 'Errori:', 'European Date Format' => 'Formato Data Europeo', 'Event' => 'Evento', 'Every %s' => 'Ogni %s', 'Exact Period' => 'Periodo Esatto', 'Exchange Rate' => 'Cambio', 'Exchange Rate enter cost of 1 (one) %s' => 'Cambio inserisci il costo di 1 (uno) %s', 'Expiration message will be sent when configured conditions met. Additional restrictions applies to do not sent unnecessary e-mails. Expiration message will not be sent if:
      • User has other active products with the same renewal group
      • User has unsubscribed from e-mail messages
      ' => 'Le Email di Scadenza vengono spedite quando si verificano le condizioni impostate. Le Email di Scadenza non vengono spedite se:
      • L\'Utente ha altri prodotti attivi nello stesso Gruppo di Rinnovo
      • L\'Utente si è cancellato dai messaggi email
      ', 'Expire (maximum expiration date)' => 'Scadenza (data massima di scadenza)', 'Extend Existing Subscription Period' => 'Estendi il Periodo di Iscrizione attuale', 'FORM' => 'FORM', 'Failures' => 'Fallimenti', 'Field Description for dispaying on signup and profile editing screen (for user)' => 'Descrizione Campo verrà visualizzato dall\'utente nei form', 'Field Name' => 'Nome Campo', 'Field Title' => 'Titolo Campo', 'Field Type sql field will be added to table structure, common field will not, we recommend you to choose second option' => 'Tipo di Campo i campi SQL vengono aggiunti alle tabelle del database quelli non-SQL invece no (si raccomandano questi)', 'Field Values' => 'Valori del Campo', 'Fields You can add new fields %shere%s' => 'Fields You can add new fields %shere%s', 'File (max filesize %s)' => 'File (grandezza massima del file %s)', 'File %s is already exist. You can not create already existing translation.' => 'Il File %s eiste già. Non puoi creare una traduzione che esiste già.', 'File [%s] cannot be deleted - remove it manually to unprotect folder' => 'Il File [%s] non può essere cancellato - rimuovilo manualmente in altra cartella', 'File is required' => 'Il File è richiesto', 'Filter By Title or Category' => 'Filtra per Nome o Categoria', 'Filter by Affiliate/Banner/IP' => 'Filtra per Affiliato/Banner/IP', 'Filter by Affiliate/User/Banner' => 'Filtra per Affiliato/Utente/Banner', 'Filter by Affiliate/User/Product' => 'Filtra per Affiliato/Utente/Prodotto', 'Filter by Category' => 'Filtra per Categoria', 'Filter by Country' => 'Filtra per Nazione', 'Filter by Paysystem' => 'per Pagamento', 'Filter by Product' => 'per Prodotto', 'Filter by Status' => 'Filtra per Stato', 'Filter by String' => 'Filtra per Stinga', 'Filter by User/Product' => 'Filtra per Utente/Prodotto', 'Filter by name or description' => 'Filtra per Nome o Descrizione', 'Filter by string or by invoice#/member#' => 'Filtra per stringa o ricevuta#/cliente#', 'First Payment (calculated for first payment in each invoice)' => 'Primo Pagamento (calcolato per il primo pagamento in ogni ricevuta)', 'First Period' => 'Primo Periodo', 'First Price' => 'Prezzo non Scontato', 'First Price price of first period of subscription' => 'Prezzo non Scontato prezzo del primo periodo di iscrizione', 'First Tax' => 'Tasse', 'First Time Purchase' => 'Primo Acquisto', 'First Total' => 'Totale', 'First and Last Name' => 'Nome e Cognome', 'First available protected url' => 'Primo URL protetto disponibile', 'First visited' => 'Prima Visita', 'Fix aMember Pro License Key' => 'Sistema la chiave di licenza di aMember', 'Fixed Url' => 'URL fisso', 'Fixed date' => 'Data fissa e stabilita', 'FlowPlayer License Key you may get your key in %smembers area%s' => 'Chiave di licenza FlowPlayer trovi la tua licenza nell\'%sArea Riservata%s', 'Folder %s is not a writable for the PHP script. Please
      chmod this file using webhosting control panel file manager or using your
      favorite FTP client to 777 (write and read for all)
      Please, don\'t forget to chmod it back to 755 after creation of translation' => 'Folder %s is not a writable for the PHP script. Please
      chmod this file using webhosting control panel file manager or using your
      favorite FTP client to 777 (write and read for all)
      Please, don\'t forget to chmod it back to 755 after creation of translation', 'Folder URL' => 'URL della Cartella', 'Force Change Password' => 'Forza Cambio Password', 'Force Change Password ask user to change password every XX days' => 'Forza Cambio Password Utente chiedi periodicamente il cambio password', 'Force https Connection redirect all request to https' => 'Force https Connection redirect all request to https', 'Form Type' => 'Tipo di Form', 'Form to Include to Roster' => 'Form da includere nel Roster', 'Forms Editor' => 'Form Editor', 'Front Page' => 'Pagina Frontale', 'Future' => 'Futuro', 'General' => 'Generale', 'General Affiliate Link Redirect URL It is url of landing page for default affiliate link (which does not related to any banner), home page will be used if you keep it empty' => 'URL Link Affiliato Generale la landing page generale del tuo sito, se lasci vuoto viene presa la home page.', 'General Link' => 'Link Generale', 'General Settings' => 'Settaggi Generali', 'Generate' => 'Genera', 'Generate Basket HTML' => 'Genera Carrello HTML', 'Generate Button HTML' => 'Genera Pulsante HTML', 'Generate Payout Manually' => 'Inserisci il Pagamento Manualmente', 'Generate Products Count' => 'Genera Conteggio Prodotti', 'Generate Report' => 'Genera un Report', 'Generate Users Count' => 'Numero Utenti da Generare', 'Generated' => 'Creato', 'Generated License Valid To' => 'Genera Licenza Valida a', 'Generation of demo data was terminated while processing. Not all records were created.' => 'La generazione dei dati demo è terminata. Non tutti i record sono stati creati.', 'Get Available Upgrades List' => 'Acquisisci la Lista di Upgrade disponibili', 'Get New Password' => 'Richiedi una Nuova Password', 'Global' => 'Impostazioni Generali', 'Global Translations' => 'Traduzioni Globali', 'Graph Bar' => 'Grafico a Barre', 'Graph Line' => 'Grafico a Linee', 'HTML Code %url% will be replaced with actual url of affilate link' => 'Codice HTML il segnaposto %url% verrà sostituito con il link affiliato dell\'utente affiliato', 'HTML E-Mail Unsubscribe Link %link% will be replaced to actual unsubscribe URL' => 'HTML Link Cancellazione Email %link% sarà rimpiazzato con il vero URl di cancellazione', 'Help & Support' => 'Aiuto & Supporto', 'Hide \'Add/Renew Subscription\' tab (User Menu) and show \'Shopping Cart\' tab instead' => 'Hide \'Add/Renew Subscription\' tab (User Menu) and show \'Shopping Cart\' tab instead', 'Hide Quick Order Button' => 'Nascondi Pulsante "Ordine Veloce"', 'Hide from Dashboard do not display this item link in members dashboard This doesn\'t remove link from category.' => 'Non Mostrare nell\'Account Questo non rimuove il linkd alla categoria.', 'Hide from Menu do not include link to this form in members menu' => 'Nascondi dal Menù non includere il link al modulo d\'ordine nel menù relativo nell\'area riservata dell\'utente', 'Hostname' => 'Nome Host', 'Hour' => 'Ora', 'I submitted refund already and only wanted to add refund record to invoice' => 'Ho già fatto il rimborso, devo solo indicarlo nella ricevuta', 'I understand that upgrade may overwrite customized PHP files and templates, I have already made a backup of aMember Pro folder and database' => 'Sono consapevole che l\'upgrade potrebbe sovrascrivere i file PHP e i template personalizzati, ho già fatto un backup delle cartelle e del database di aMember', 'IMPORTANT NOTE:' => 'NOTA IMPORTANTE:', 'IMPORTANT NOTE: This will not protect content. If someone know link url, he will be able to open link without a problem. This just control what additional links user will see after login to member\'s area.' => 'NOTA IMPORTANTE: questo non protegge il contenuto. Se qualcuno conosce il link potrà vederne il contenuto senza problemi. Questo serve solo a inserire eventuali link addizionali che l\'utente può visualizzare nella sua Area Riservata.', 'IP' => 'IP', 'IP within' => 'IP dentro', 'IP(Country)' => 'IP(Nazione)', 'If only one protected URL, go directly to the URL. Otherwise go to membership page' => 'Se c\'è solo un URL protetto, vai direttamente a quello, altrimenti vai alla pagina account', 'If you are moving from one payment processor, you can use this page to switch existing subscription from one payment processor to another. It is possible only if full credit card info is stored on aMember side.' => 'Se stai cambiando metodo di pagamento, puoi usare questa pagina per cambiare l\'iscrizione esistente da un metodo ad un altro. È possibile solo se tutte le informaizoni della carta di credito sono salvate in aMember.', 'Image' => 'Immagine', 'Image height must be number greater than %d' => 'L\'altezza immagine deve essere superiore a %d', 'Image width must be number greater than %d' => 'La larghezza immagine deve essere superiore a %d', 'Immediately' => 'Immediatamente', 'Import E-Mail Templates from XML file' => 'Importa Template Email dal file XML', 'Import Encrypted Password' => 'Importa Password Crittografate', 'Import Finished' => 'Importazione terminata', 'Import Finished. %d templates imported.' => 'Importazione Ultimata. %d template importati.', 'Import History' => 'Storico Importazione', 'Import Mode' => 'Modalità Importazione', 'Import Pre-Defined List of Coupon Codes from CSV File (One coupon code per line)' => 'Importa Lista Buoni Sconto da file CSV (Un Buono Sconto per riga)', 'Import Users' => 'Importa Utenti', 'Import data. Please wait...' => 'Sto importando. Attendi...', 'Import of data was terminated while processing. Anyway some data was imported.' => 'Importazione terminata mentre era ancora in corso. Alcuni dati sono stati importati comunque.', 'Import...' => 'Importazione...', 'Import: Step 3 of 4' => 'Importazione: Passo 3 di 4', 'Import: Step 4 of 4' => 'Importazione: Passo 4 di 4', 'Important Notice:' => 'Nota Importante:', 'In case of video do not start play before full download and you use mp4 format more possible that metadata (moov atom) is located at the end of file. There is special programs that allow to relocate this metadata to the beginning of your file and allow play video before full download (On Linux mashine you can use qt-faststart utility to do it). Also your video editor can has option to locate metadata at beginning of file (something like FastStart or Web Optimized option). You need to relocate metadata for this file and reupload it to aMember. You can use such utilites as AtomicParsley or similar to check your file structure.' => 'In case of video do not start play before full download and you use mp4 format more possible that metadata (moov atom) is located at the end of file. There is special programs that allow to relocate this metadata to the beginning of your file and allow play video before full download (On Linux mashine you can use qt-faststart utility to do it). Also your video editor can has option to locate metadata at beginning of file (something like FastStart or Web Optimized option). You need to relocate metadata for this file and reupload it to aMember. You can use such utilites as AtomicParsley or similar to check your file structure.', 'In the Export of text files dialog, select the options you want and then click %1$sOK%2$s.' => 'Nel testo di dialogo in fase di esportazione, seleziona le opzioni che desideri e poi clicca %1$sOK%2$s.', 'In the File name box, type a name for the file.' => 'Nel box del Nome File, digita un nome per il file.', 'In the File type list, select %1$sText CSV%2$s and click %1$sSave%2$s. You may see the message box. Click %1$sKeep Current Format%2$s.' => 'Nella lista dei tipi di file, seleziona %1$sText CSV%2$s e clicca %1$sSave%2$s. Potresti vedere un messaggio nel box. Clicca %1$sMantieni il Formato Attuale%2$s.', 'Incorrect refund [type] passed: %s' => 'Inserito tipo errato di rimborso: %s', 'Index Page %sthis page will be public and do not require any login/password%s you can create new pages %shere%s' => 'Pagina Index %squesta pagina è pubblica, non serve il login%s puoi creare nuove pagine %squi%s', 'Information is not available' => 'Informazione non disponibile', 'Insert' => 'Inserisci', 'Install Updates' => 'Installa gli Aggiornamenti', 'Instances Limit How many simultaneous bindings for license may exists (default - 1)' => 'Instances Limit How many simultaneous bindings for license may exists (default - 1)', 'Integer field (only numbers)' => 'Campo di Interi (solo numeri)', 'Integration plugins' => 'Plugin di Integrazione', 'Internal PHP mail() function (default)' => 'Funzione mail() di PHP (default)', 'Intro Text on Affiliate Info Page' => 'Testo Pagina Info Affiliato', 'Intro Text on Helpdesk Page' => 'Testo introduttivo sulla pagina di helpdesk', 'Invoice (Internal Id)' => 'Ricevuta (ID Interno)', 'Invoice (Public Id)' => 'Ricevuta (ID Pubblico)', 'Invoice (Sequential Receipt Number)' => 'Ricevuta (Numero Ricevuta Sequenziale)', 'Invoice Approved Notification to User (Invoice)' => 'Notifica all\'Utente di Ricevuta Approvata', 'Invoice Country' => 'Nazione Ricevuta', 'Invoice Log' => 'Log delle Ricevute', 'Invoice Number' => 'Numero Ricevuta', 'Invoice link has been sent to user again' => 'Il Link della Ricevuta è stato spedito di nuovo all\'utente', 'Invoice/User/License/Bindings' => 'Ricevuta/Utente/Licenza/Vincoli', 'Invoices' => 'Ricevute', 'Invoices Information' => 'Informazioni Ricevute', 'Invoices Per User' => 'Ricevute per Cliente', 'Is Affiliate?' => 'È affiliato?', 'Is Affiliate? (0 - No, 1 - Yes)' => 'Affiliato? (0 - No, 1 - Sì)', 'Is Approved' => 'È approvato', 'Is Disabled' => 'Disabilitato', 'Is Disabled?' => 'Disabilitato?', 'Is Disabled? If you disable this coupons batch, it will not be available for new purchases. Existing invoices are not affected.' => 'È disabilitato? se lo disabiliti non funzionerà per nuovi acqusiti, ma le ricevute esistenti rimangono inalterate.', 'Is Disabled? disable product ordering, hide it from signup and renewal forms' => 'È disabilitato? disabilita l\'ordine del prodotto, nascondilo dalla pagina di iscrizione e rinnovo', 'Is Unsubscribed? if enabled, this will unsubscribe the customer from: * messages that you send from aMember Cp, * autoresponder messages, * subscription expiration notices' => 'È Disiscritto? se sì, il cliente non riceve: * messaggi che invii manualmente * messaggi autorisponditore, * notifiche scadenza iscrizioni', 'Is Unsubscribed? (0 - No, 1 - Yes)' => 'Cancellato? (0 - No, 1 - Sì)', 'It is required to setup a cron job to trigger backup generation' => 'È necessario settare un cron job per generare i backup automatici', 'It will replace all your exising database with backup. Do you really want to proceed?' => 'Questa azione sostituirà completamente il tuo database con quello di Backup. Vuoi proseguire veramente?', 'Items' => 'Elementi', 'JWPlayer License Key' => 'Licenza JWPlayer', 'JavaScript Code' => 'Codice JavaScript', 'Just Add Pending Invoice' => 'Crea solo Ricevuta in Attesa', 'Key' => 'Chiave', 'Key Generator' => 'Generatore Chiavi', 'Key must be 20 chars or longer' => 'La Chiave deve averalmeno 20 caratteri', 'Keygenerator' => 'Generatore Chiavi', 'Languages' => 'Lingue', 'Last %s Customers' => 'Ultimi %s Clienti', 'Last %s Helpdesk Messages' => 'Ultimi %s Messaggi nell\'Helpdesk', 'Last %s Invoices' => 'Ultime %s Ricevute', 'Last %s Payments' => 'Ultimi %s Pagamenti', 'Last %s Refunds' => 'Ultimi %s Rimborsi', 'Last %s User Notes' => 'Ultime %s Note Utente', 'Last %s User Signin' => 'Ultimi %s Accessi Utente', 'Last Error' => 'Ultimo Errore', 'Last Invoices List' => 'Lista Ultime Ricevute', 'Last Payments List' => 'Lista Ultimi Pagamenti', 'Last Refunds List' => 'Lista Ultimi Rimborsi', 'Last Signin Info' => 'Informazioni Ultimo Accesso', 'Last User Logins List' => 'Lista Accessi Ultimo Utente', 'Last User Notes' => 'Note Ultimo Utente', 'Last Users List' => 'Lista degli Ultimi Clienti', 'Last available protected url' => 'Ultimo URL protetto disponibile', 'Last existing subscription date of this product' => 'L\'ultima data di iscrizione di questo prodotto', 'Last expiration date in the renewal group' => 'Ultima data di scadenza nel gruppo di rinnovo', 'Last login' => 'Ultimo Accesso', 'Length of admin password must be from %d to %d' => 'La lunghezza della password dell\'Amministratore deve essere da %d a %d', 'Length of username must be from %d to %d' => 'La lunghezza del Nome Utente deve essere da %d a %d', 'License Activations' => 'Attivazioni Licenze', 'Licensing Method' => 'Metodo Licenze', 'Lifetime (%s)' => 'Per Sempre (%s)', 'Light Boxes' => 'Light Box', 'Lightbox Main Image' => 'Immagine Principale del LightBox', 'Lightbox Thumbnail Image' => 'Immagine Miniatura del LightBox', 'Limit Downloads Count' => 'Numero Limite di Download', 'Lines Proccessed:' => 'Linee Processate:', 'Lines Skipped:' => 'Linee Saltate:', 'Lines Success:' => 'Linee Corrette:', 'Link to reset your password was sent to your Email.' => 'Il link per reimpostare la tua password è stato inviato nella tua casella di posta elettronica.', 'Loading...' => 'Sto caricando...', 'Local Translations' => 'Traduzioni Locali', 'Lock' => 'Blocca', 'Locked Value' => 'Valore Bloccato', 'Log Outgoing E-Mail Messages for ... days' => 'Log dei messaggi in uscita per ... days', 'Log in' => 'Entra', 'Logged in as %s' => 'Loggato come %s', 'Login As User' => 'Accedi come Utente', 'Login Page' => 'Accesso Area Riservata', 'Login/Name/Email/Invoice/Receipt/IP' => 'Login/Nome/Email/Ricevuta/Pagamento/IP', 'Logs' => 'Log', 'Logs: Access' => 'Log: Accessi', 'Logs: Admin Log' => 'Log: Accessi Admin', 'Logs: Errors' => 'Log: Errori', 'Logs: File Downloads' => 'Log: Download File', 'Logs: Invoice' => 'Log: Ricevuta', 'Logs: Mail Queue' => 'Log: Coda Email', 'Lookup' => 'Ricerca Veloce', 'Lost your password?' => 'Hai Perso la Password?', 'Mail' => 'Mail', 'Maintenance Mode' => 'Modalità Manutenzione', 'Maintenance mode is currently enabled. Only logged-in administrators like you can access it. %sDisable%s' => 'La modalità manutenzione è attualmente abilitata. Solo gli Amministratori possono accedervi. %sDisabilita%s', 'Manage Additional User Fields' => 'Gestisci Campi Utente Aggiuntivi', 'Manage Countries/States' => 'Gestisci Nazioni/Provincie', 'Manage Product Upgrade Paths' => 'Gestisci i percorsi di aggiornamento dei prodotti', 'Manage Products' => 'Gestione Prodotti', 'Manage Translation of Messages' => 'Gestisci Traduzione Messaggi', 'Manually Added' => 'Aggiunto manualmente', 'Manually Approve New Invoices manually approve all new invoices' => 'Approva Manualmente Nuove Ricevute valido per tutte le nuove ricevute generate', 'Manually Approve New Users manually approve all new users (first payment) don\'t enable it if you have huge users base already - all old members become not-approved' => 'Approva Manualmente Nuovi Utenti si applica a tutti i primi pagamenti, non abilitare se hai già molti clienti perché tutti diventeranno automaticamente "non approvati"', 'Manually Approve Note (New Signup/Invoice) this message will be shown for customer after purchase. you can use html markup here' => 'Manually Approve Note (New Signup/Invoice) this message will be shown for customer after purchase. you can use html markup here', 'Mark NOT Paid' => 'Segna come NON PAGATO', 'Mark Paid' => 'Segna come PAGATO', 'Mass Subscribe' => 'Iscrizione di Massa', 'Membership' => 'Iscrizione', 'Membership Info Page' => 'Dettagli Iscrizione', 'Merge' => 'Unisci', 'Merge with user %s <%s> (%s) [#%d]' => 'Unisci con Utente %s <%s> (%s) [#%d]', 'Message will be included to email to user' => 'Message will be included to email to user', 'Messages to Customer after Payment' => 'Messaggio al Cliente dopo l\'Acquisto', 'Method' => 'Metodo', 'Minimum Payout minimal commission amount earned by affiliate to include it to payout report' => 'Importo Minimo Payout Affiliato ammontare minimo delle commisioni per generare il payout', 'Miscellaneous' => 'Miscellanea', 'Modules' => 'Moduli', 'Monthly' => 'Mensilmente', 'Multi Upload' => 'Upload Multiplo', 'Multiple Order Title when user ordering multiple products, display the following on payment system instead of product name' => 'Titolo per Ordine Multiplo quando un utente ordina più prodotti, visualizza il seguente titolo nel sistema di pagamento invece del nome del prodotto', 'Multiply commission calculated by the following rules to number specified in this field. To keep commission untouched, enter 1 or delete this rule' => 'Multiply commission calculated by the following rules to number specified in this field. To keep commission untouched, enter 1 or delete this rule', 'NEVER (oops! no records that it has been running at all!)' => 'MAI (oops! sembra che questo non ha mai girato!)', 'Name First and Last name' => 'Nome e Cognome', 'Name must be entered and it may contain lowercase letters, underscores and digits' => 'Il Nome è obbligatorio e dovrebbe contenere lettere minuscole, trattino basso e numeri', 'Name of Preset' => 'Nome del Profilo', 'Name of template is undefined' => 'Nome Template non definito', 'Nearest' => 'Il più vicino', 'Nearest 15th Day of Month' => 'Il più vicino 15 del mese', 'Nearest 1st Day of Month' => 'Il più vicino primo del mese', 'Nearest Friday' => 'Il più vicino Venerdì', 'Nearest Monday' => 'Il più vicino Lunedì', 'Nearest Saturday' => 'Il più vicino Sabato', 'Nearest Sunday' => 'La più vicina Domenica', 'Nearest Thursday' => 'Il più vicino Giovedì', 'Nearest Tuesday' => 'Il più vicino Martedì', 'Nearest Wednesday' => 'Il più vicino Mercoledì', 'Need points to get %s discount' => 'ti servono Punti per avere lo sconto di %s', 'New Activation' => 'Nuova Attivazione', 'New Affiliate Payout to Admin' => 'Notifica Nuovo Payout ad Admin', 'New Autoresponder' => 'Nuovo Autorisponditore', 'New Expiration E-Mail' => 'Nuova E-Mail di Scadenza ', 'New Form Campaign' => 'Nuova Campagna di Form', 'New Modules Available' => 'Nuovi Moduli Disponibili', 'New Payment E-Mail' => 'Nuova Email Pagamento', 'New Product Welcome E-Mail' => 'Nuova Email Benvenuto per Prodotto', 'New Rewrite' => 'Nuovo Rewrite', 'New Theme Campaign' => 'Nuova Campagna Temi', 'New Ticket Autoresponder to Customer aMember will email an autoresponder to user each time user create new ticket' => 'Notifica Nuovo Ticket al Cliente inviata ogni volta che un utente crea un nuovo ticket', 'New password has been e-mailed to your e-mail address' => 'La Nuova Password è stata inviata al tuo indirizzo E-mail', 'Next Day' => 'Giorni seguente', 'Next Hour' => 'Ora seguente', 'Next rebill date' => 'Prossimo Addebito', 'No Access URL customer without required access will be redirected to this url, leave empty if you want to redirect to default \'No access\' page' => 'URL Utente non Attivo se l\'utente non ha il permesso per questa cartella verrà rediretto a questo URL. Lascia vuoto per inviare alla pagina di default.', 'No Access URL customer without required access will see link to this url in the player window leave empty if you want to redirect to default \'No access\' page' => 'URL Utente non Attivo se l\'utente non ha il permesso per questa cartella verrà rediretto a questo URL. Lascia vuoto per inviare alla pagina di default.', 'No Credit Cards stored for this customer. %sAdd Credit Card%s' => 'Nessuna Carta di Credito salvata per questo utente. %sAggiungi Carta di Credito%s', 'No Echecks stored for this customer. %sAdd Echeck%s' => 'Nessun Echeck registrato per questo cliente. %sAggiungi Echeck%s', 'No Invoices Found' => 'Nessuna Ricevuta', 'No Layout' => 'Nessun Layout', 'No License Configured' => 'Nessuna Licenza Configurata', 'No Tax' => 'No Tasse', 'No Updates Available' => 'Nessun Aggiornamento Sisponibile', 'No activation' => 'Nessuna Attivazione', 'No more charges' => 'Nessun altro Addebito', 'No one line found in the file. It looks like file is empty. You can go back and try another file.' => 'Nessuna linea nel file. Sembra che il file sia vuoto. Torna indietro e riprova con un altro file.', 'No payment found' => 'Nessun Pagamento trovato', 'No protection plugins enabled, please enable new-rewrite or htpasswd at aMember CP -> Setup -> Plugins' => 'Nessun plugin protezione attivato, abilita new-rewrite o htpasswd in Setup/Configurazione -> Plugin', 'No search name passed' => 'Nessun nome di ricerca inserito', 'No upgrades to install' => 'Nessun Aggiornamento da Installare', 'Not Applied' => 'Non Applicato', 'Not Approved' => 'Non Approvato', 'Not Approved Users' => 'Clienti non Approvati', 'Not Confirmed Users' => 'Clienti non Confermati', 'Not Included to Payout' => 'Non incluso nel Payout', 'Not Product' => 'Non Prodotto', 'Not Product Category' => 'Non Categoria Prodotto', 'Not-SQL field (default)' => 'Campo non-SQL (default)', 'Note' => 'Nota', 'Number of Invoices to display' => 'Numero di Ricevute da Visualizzare', 'Number of License Reactivations Allowed for all instances (default - 0)' => 'Number of License Reactivations Allowed for all instances (default - 0)', 'Number of Notes to display' => 'Numero di Note da Visualizzare', 'Number of Payments to display' => 'Numero di Pagamenti da Visualizzare', 'Number of Refunds to display' => 'Numero di Rimborsi da Visualizzare', 'Number of Users to display' => 'Numero di Clienti da visualizzare', 'Number of invoices which require approval: %d. %sClick here%s to review these invoices.' => 'Numero di Ricevute da approvare: %d. %sClicca qui%s per esaminarle.', 'Number of users who require approval: %d. %sClick here%s to review these users.' => 'Numero di Clienti da approvare: %d. %sClicca qui%s per esaminarli.', 'Numeric field' => 'Campo Numerico', 'OTO - Offer to purchase additional product (with optional discount)' => 'OTO - Offri di acquistare un ulteriore prodotto (con un eventuale sconto)', 'One Column' => 'Una Colonna', 'One field can be assigned to one column only, you assigned following fields to several columns: ' => 'Un campo può essere assegnato ad una sola colonna, tu hai assegnato i seguenti campi a più di una colonna: ', 'One field can be assigned to one column only.' => 'Un campo può essere assegnato ad una sola colonna.', 'Only admin can enable user as an affiliate' => 'Solo l\'Amministratore può abilitare gli Utenti come affiliati', 'Optional Conditions' => 'Condizioni Opzionali', 'Origin' => 'Origine', 'Outgoing Email Address used as From: address for sending e-mail messages to customers. If empty, [Admin E-Mail Address] is used' => 'Indirizzo E-mail in Uscita indirizzo da cui inviare le email agli utenti. Se rimane vuoto, viene usato l\'email di default dell\'Amministratore', 'Overwrite User if Exist User with Same Login' => 'Sovrascrivi un Utente se esiste un altro Utente con lo stesso Nome Utente', 'Owner set the following admin as owner of ticket' => 'Owner set the following admin as owner of ticket', 'PDF Invoice' => 'Ricevuta in PDF', 'Page Not Found (404) %sthis page will be public and do not require any login/password%s you can create new pages %shere%s' => 'Pagina Non Trovata (404) %squesta pagina è pubblica e non necessita login%s puoi creare nuove pagine 404 %squi%s', 'Page Peel' => 'Pagina Arrotolata', 'Page Where Log In Link was Clicked' => 'Pagina in cui è stato cliccato il link Login', 'Page Where Logout Link was Clicked' => 'Pagina in cui è stato cliccato il link Logout', 'Paid' => 'Pagata', 'Params' => 'Parametri', 'Password Hash' => 'Hash Password', 'Password Length' => 'Lunghezza Password', 'Password changed' => 'Password Modificata', 'Password must not be equal to username' => 'La Password non può essere uguale al Nome Utente', 'Passwords must be the same' => 'La Password deve essere la stessa', 'Path will be used to construct user-friendly url, in case of you leave it empty aMember will use id of this page to do it' => 'Percorso verrà utilizzato per costruire una URL semplice, se lasci vuoto aMember userà il codice ID della pagina', 'Path should be unique' => 'Il Percorso deve essere unico', 'Path to Folder' => 'Percorso della Cartella', 'Path/URL' => 'Percorso/URL', 'Payment Date' => 'Data Pagamento', 'Payment Receipt' => 'Ricevuta del Pagamento', 'Payment System Choose payment system to be used with this product' => 'Payment System Choose payment system to be used with this product', 'Payment System: ' => 'Sistema di Pagamento: ', 'Payment belongs to another customer' => 'Il pagamento è di un altro cliente', 'Payment date' => 'Data di Pagamento', 'Payment email will be automatically sent after payment received. Payment email will not be sent if:
      • User has unsubscribed from e-mail messages
      ' => 'L\'Email di Pagamento verrà inviata automaticamente dopo il pagamento. L\'Email di Pagamento non verrà inviata se:
      • L\'Utente si è cancellato dai messaggi email
      ', 'Payment has been successfully refunded' => 'Il Pagamento è stato rimborsato con sucesso', 'Payment is already refunded' => 'Pagamento già Rimborsato', 'Payment#/Receipt#' => 'Pagamento#/Ricevuta#', 'Payments (amount of all payments made by user minus refunds)' => 'Pagamenti (pagamenti totali dell\'utente meno i rimborsi)', 'Payments/Refunds' => 'Pagamenti/Rimborsi', 'Payout %d Details' => 'Dettagli di Pagamento %d ', 'Payout Details' => 'Dettagli di Pagamento', 'Paysystem' => 'Sistema di Pagamento', 'Paysystem Receipt ID' => 'ID Ricevuta Sistema Pagamento', 'Paysystem: %s' => 'Sistema Pagamento: %s', 'Pending Invoice Notification Rules' => 'Regole di Notifica per i Pagamenti in Attesa', 'Pending Invoice Notifications to Admin only one email will be send for each defined day. all email for specific day will be selected and conditions will be checked. First email with matched condition will be send and other ignored' => 'Notifiche Ricevuta in Attesa per Admin verrà mandata una sola email per ogni giorno definito. La prima email che è conforme alle condizioni specificate verrà inviata all\'utente, le altre saranno ignorate.', 'Pending Invoice Notifications to User only one email will be send for each defined day. all email for specific day will be selected and conditions will be checked. First email with matched condition will be send and other ignored' => 'Notifiche Ricevuta in Attesa per Utente verrà mandata una sola email per ogni giorno definito. La prima email che è conforme alle condizioni specificate verrà inviata all\'utente, le altre saranno ignorate.', 'Period: %s-%s' => 'Periodo: %s-%s', 'Permanently Locked' => 'È Bloccato?', 'Permissions' => 'Permessi', 'Player Configuration this option is applied only for video files' => 'Configurazione Player questa opzione vale solo per i video', 'Please assign the following fields: ' => 'Assegna i campi seguenti:', 'Please choose another field name. This name is already used' => 'Per favore, scegli un altro nome per il campo. Questo nome è già in uso', 'Please choose product' => 'Per favore scegli il prodotto', 'Please click on the button below to create backup of aMembers tables in MySQL database.' => 'Clicca il pulsante qui sotto per creare un backup delle tabelle di aMember nel database MySQL.', 'Please enter expire date' => 'Per favore inserisci data scadenza', 'Please enter one or more email' => 'Per favore inserisci una o più email', 'Please enter start date' => 'Per favore inserisci data inizio', 'Please enter valid e-mail address' => 'Per favore, inserisci un indirizzo E-mail valido', 'Please enter valid e-mail addresses' => 'Per favore inserisci Email Valide', 'Please enter your username or email address. You will receive a link to create a new password via email.' => 'Per favore, inserisci il tuo Nome Utente o indirizzo E-mail. Riceverai un link per la creazione di una nuova password via email.', 'Please note: By default, aMember does not change users password and login values to a generated value in cases where an existing email address is found. You may decide to update an existing record, in the next step of the import process, where a matching email or username already exists.' => 'Nota Importante: di default, aMember non cambia password e informazioni di login nei casi in cui esiste già l\'email nel database. In quel caso puoi decidere di aggiornare i valori di un utente già esistente nel prossimo passo della procedura di importazione.', 'Please run %sRebuild Db%s to update status for imported customers' => 'Esegui un %sRefresh Database%s per aggiornare lo stato dei Clienti importati', 'Please select date before today' => 'Seleziona una data che sia anteriore ad oggi', 'Please specify new rebill date: ' => 'Per favore specifica una nuova data di riaddebito: ', 'Please specify number greater then zero' => 'Per favore inserisci un numero maggiore di zero', 'Please specify number less then 9999' => 'Per favore inserisci un numero minore di 9999', 'Please upload file [%s]
      ' => 'Per favore carica file [%s]
      ', 'Please wait' => 'Prego Attendere', 'Plugin Id' => 'ID Plugin', 'Plugins' => 'Plugin', 'Poster Image applicable only for video files' => 'Immagine Poster valida solo per file video', 'Poster Image default poster image' => 'Immagine Poster Default', 'Product Availability' => 'Disponibilità del Prodotto', 'Product Category' => 'Categoria del Prodotto', 'Product Category: ' => 'Categoria Prodotto: ', 'Product Image' => 'Immagine Prodotto', 'Product Options' => 'Opzioni Prodotto', 'Product Upgrades' => 'Aggiornamenti del Prodotto', 'Product is not if none specified, rule works for all products' => 'Product is not if none specified, rule works for all products', 'Product is not included to Category if none specified, rule works for all product categories' => 'Prodotto non incluso nella Categoria se non viene specificato nulla, la regola vale per tutte le categorie', 'Product welcome email will be automatically sent immediately after payment received. Product welcome email will not be sent if:
      • User has unsubscribed from e-mail messages
      ' => 'L\'Email di Benvenuto Prodotto verrà inviata automaticamente dopo il pagamento.. L\'Email di Benvenuto Prodotto non verrà inviata se:
      • L\'Utente si è cancellato dai messaggi email
      ', 'Product: ' => 'Prodotto: ', 'Products coupons can be used with selected products only. if nothing selected, coupon can be used with any product' => 'Seleziona i Prodotti se lasci vuoto lo sconto vale per tutti i prodotti', 'Products List From Category' => 'Lista Prodotti della Categoria', 'Products Per Invoice' => 'Prodotti per Ricevuta', 'Products per Page' => 'Prodotti per Pagina', 'Products that bring credits' => 'Prodotti che assegnano Crediti', 'Products that can be purchased with credits' => 'prodotti acquistabili con Crediti', 'Protect Content' => 'Proteggi Contenuti', 'Protect Files List' => 'Lista File Protetti', 'Protection Method' => 'Metodo di Protezione', 'Purchase IP' => 'IP Acquisto', 'Put Chosen Products After' => 'Metti Prodotti Scelti Dopo', 'Quantity default - 1, normally you do not need to change it First and Second Price is the total for specified qty' => 'Quantità di Default - 1, normalmente non c\'è bisogno di cambiarla Il Primo e il Secondo Prezzo sono calcolati sulla quantità specificata', 'Quick Start' => 'Inzio Rapido', 'Quit Maintenance Mode' => 'Uscire dalla modalità di manutenzione', 'REST API Documentation' => 'Documentazione REST API', 'RadioButtons' => 'RadioButton', 'Re Send Payment Link' => 'Rispedisci Link Pagamento', 'Rebill' => 'Ri-addebito', 'Rebill Date' => 'Data Riaddebito', 'Rebill Date changed from %s to %s' => 'Data Riaddebito Cambiata da %s a %s', 'Rebill Operation Completed for %s' => 'Operazione Riaddebito Terminata per %s', 'Rebill Second Price until cancelled' => 'Ri-addebita il secondo prezzo fino alla cancellazione', 'Rebill Times This is the number of payments which will occur at the Second Price' => 'Numero di Ri-addebiti Questo è il numero dei pagamenti con il secondo prezzo da addebitare', 'Rebill date has been changed!' => 'Data Riaddebito cambiata!', 'Rebills' => 'Riaddebiti', 'Rebuild DB' => 'Ricostruisci DATABASE', 'Rebuild Db' => 'Ricostruisci Database', 'Rebuild Users Database' => 'Ricostruisci Database Utenti', 'Receipt' => 'Ricevuta', 'Receipt ID' => 'ID Ricevuta', 'Receipt#' => 'Ricevuta#', 'Recipients' => 'Destinatari', 'Record modified, original dates:' => 'Accesso modificato, date originali:', 'Records Deleted Sucessfully' => 'Record Eliminati con Successo', 'Records per Page (for grids)' => 'Elementi per Pagina (per tabelle) quante righe quando visualizzi tabelle', 'Redirect After Login where customer redirected after successful login at %s' => 'Pagina Atterraggio dopo Login dopo accesso %s', 'Redirect After Logout' => 'Pagina Atterraggio dopo Logout', 'Redirect Default Signup Page to Cart' => 'Manda al Carrello la Pagina d\'Ordine di Default', 'Redirect URL' => 'URL di Reindirizzamento ', 'Referrer' => 'Sponsor', 'Refund (Sequential Receipt Number)' => 'Rimborso (Numero Sequenziale Ricevuta)', 'Refund Date' => 'Data Rimborso', 'Refund Payment' => 'Rimborsa Pagamento', 'Refund amount cannot exceed payment amount' => 'Il Rimborso non può eccedere il Pagamento', 'Refund date cannot be before payment date' => 'La data Rimborso non può precedere quella di Pagamento', 'Refunded Amount' => 'Importo Rimborsato', 'Refunded Date/Time' => 'Rimborsato Data/Ora', 'Refunds' => 'Rimborsi', 'Refunds are not implemented for this payment system. This action will not issue actual refund. It will just add refund record in aMember and revoke user access. You must go to payment processor and do actual refund if you did not do it yet.' => 'I Rimborsi non sono implementati in questo Sistema di pagamento. Questa azione non invierà un rimborso reale ma registrerà semplicemente il rimborso in aMember per revocare l\'accesso. Dovrai andare sul pannello del Client di pagamento per fare il rimborso in denaro vero e proprio, se non lo hai già fatto.', 'Registration IP(Country)' => 'Registrazione IP(Nazione)', 'Registrations' => 'Registrazioni', 'Remember Login remember username/password in cookies' => 'Ricorda le Credenziali di Accesso ricorda Nome Utente e password nei cookie', 'Remember Period cookie will be stored for ... days' => 'Giorni di Persistenza Cookie per quanti giorni rimane sul computer utente', 'Remind Password to Admin' => 'Ricorda Password all\'Amministratore', 'Remind Password to Customer' => 'Ricorda Password al Cliente', 'Remove Category' => 'Rimuovi Categoria', 'Remove From Dashboard' => 'Rimuovi dalla Bacheca', 'Remove Group' => 'Rimuovi Gruppo', 'Renew Form (member)' => 'Rinnova Form (membro)', 'Renew on rebill prorate existing license for rebills (do not generate new license)' => 'Renew on rebill prorate existing license for rebills (do not generate new license)', 'Renewal Group Allows you to set up sequential or parallel subscription periods. Subscriptions from the same group will begin at the end of subscriptions from the same group. Subscriptions from different groups can run side-by-side' => 'Renewal Group Allows you to set up sequential or parallel subscription periods. Subscriptions from the same group will begin at the end of subscriptions from the same group. Subscriptions from different groups can run side-by-side', 'Reparing' => 'Sto Riparando', 'Repeat Action Handling' => 'Ripetere l\'azione di Handling', 'Replace Product' => 'Rimpiazza Prodotto', 'Reply To mailbox for replies to message' => 'Rispondi a indirizzo di risposta al messaggio', 'Report Bugs' => 'Report di un Bug', 'Report Dates' => 'Date Report', 'Report Period' => 'Periodo Report', 'Report Settings' => 'Impostazioni Report', 'Report Type' => 'Tipo Report', 'Reports' => 'Report', 'Requester History' => 'Storico Richiedenti', 'Require Approval Notification to Admin' => 'Notifica Valutazione ad Admin spedita solo se hai impostato validazione da Admin', 'Require Approval Notification to Admin (New Signup)' => 'Richiedi Notifica di Approvazione da Admin (Nuova Registrazione)', 'Require Approval Notification to Affiliate' => 'Notifica Valutazione ad Affiliato spedita solo se hai impostato validazione da Admin', 'Require Approval Notification to User (New Signup)' => 'Richiedi Notifica di Approvazione da Utente (Nuova Registrazione)', 'Require Approval Only if Invoice has these Products (Invoice) By default each invoice will be set as "Not Approved" although you can enable this functionality only for selected products' => 'Require Approval Only if Invoice has these Products (Invoice) By default each invoice will be set as "Not Approved" although you can enable this functionality only for selected products', 'Require Strong Password password should contain at least 2 capital letters, 2 or more numbers and 2 or more special chars' => 'Forza Password Forte se selezioni qui la password dovrà contenere almeno 2 lettere maiuscole, 2 numeri e 2 caratteri speciali', 'Reseller Packages' => 'Pacchetto Rivenditore', 'Resend' => 'Re-invia', 'Resend Email' => 'Rispedisci Email', 'Resend Payment Link' => 'Rispedisci Link Pagamento', 'Resend Signup E-Mail' => 'Re-invia E-mail di Iscrizione', 'Resource' => 'Risorse', 'Restart is not allowed' => 'Non è permesso ripartire', 'Restore' => 'Ripristina', 'Restore %s' => 'Ripristina %s', 'Restore Database from Backup' => 'Ripristina Database da Backup', 'Restore Password' => 'Ripristina Password', 'Restored Successfully' => 'Ripristinato con Successo', 'Resume Recurring' => 'Riattiva Abbonamento', 'Retreive Access Parameters if necessary' => 'Recupera i Parametri di Accesso se necessario', 'Return to Payouts List' => 'Ritorna alla Lista dei Pagamenti', 'Revenue Goal' => 'Obiettivo Fatturato', 'Root' => 'Radice', 'Root Folder' => 'Cartella Radice', 'Root URL root script URL, usually %s' => 'Root URL root script URL, normalmente %s', 'Root Url and License Keys' => 'Root Url e Chiave di Licenza', 'Rule Removed' => 'Regola Rimossa', 'Run' => 'Elabora', 'Run Payout' => 'Elabora Payout', 'Run Rebill Manually' => 'Elabora Riaddebito Manualmente', 'Run Reports' => 'Avvia i Report', 'SMTP Hostname' => 'Hostname SMTP', 'SMTP Hostname is required if you have enabled SMTP method' => 'Hostname SMTP è obbligatorio se hai abilitato il metodo SMTP', 'SMTP Password' => 'Password SMTP', 'SMTP Port' => 'Porta SMTP', 'SMTP Security' => 'Sicurezza SMTP', 'SMTP Username' => 'Username SMTP', 'SQL (could not be used for multi-select and checkbox fields)' => 'SQL (non potrà essere usato per la multiselezione e i campi checkbox)', 'SQL Date Format' => 'Formato data SQL', 'SQL field type if you are unsure, choose first type (string)' => 'Tipo Campo SQL se non sai cosa scegliere, lascia il primo (stringa)', 'Sales Count' => 'Numero Vendite', 'Sales Statistic' => 'Statistiche di Vendita', 'Salt' => 'Salatura', 'Save Advanced Search' => 'Salva Ricerca Avanzata', 'Save As Preset' => 'Salva come Preset', 'Save This Search' => 'Salva questa Ricerca', 'Saved Credit Cards' => 'Carte di Credito salvate', 'Saved Echecks' => 'Echeck Salvati', 'Saved Reports' => 'Report Salvati', 'Saved Search' => 'Ricerca Salvata', 'Scaling Setting which defines how video is scaled on the video screen. Available options are: fit: Fit to window by preserving the aspect ratio encoded in the file\'s metadata. half: Half-size (preserves aspect ratio) orig: Use the dimensions encoded in the file. If the video is too big for the available space, the video is scaled using the \'fit\' option. scale: Scale the video to fill all available space. Ignores the dimensions in the metadata. This is the default setting.' => 'Ridimensionamento fit: adatta alla finestra mantenendo le proporzioni. half: metà dimensione mantenendo le proporzioni. orig: dimensioni originali, se è troppo grande viene applicata opzione "fit" scale: prende tutto lo spazio disponibile ignorando le dimensioni originali.', 'Scheduled Recurring Revenue' => 'Incassi Ricorrenti Previsti', 'Search by Message' => 'Cerca per Messaggio', 'Second Period' => 'Secondo Periodo', 'Second Price' => 'Secondo Prezzo', 'Second Price price that must be billed for second and the following periods of subscription' => 'Secondo Prezzo ammontare che deve essere prelevato per il secondo e i successivi periodi di iscrizione', 'Secret Code if form is not choosen as default, this code (inside URL) will be necessary to open form' => 'Codice Segreto se il modulo non è stato selezionato come default, questo codice (dentro l\'URL) sarà necessario per aprire il form', 'Secure Root URL secure URL, usually %s' => 'Root URL sicuro URL di sicurezza, solitamente %s', 'Select (Multiple Values)' => 'Seleziona (anche più di uno)', 'Select (Single Value)' => 'Seleziona (uno solo)', 'Select Action of Element' => 'Seleziona Azione dell\'elemento', 'Select Condition...' => 'Seleziona Condizione...', 'Select Product(s) if nothing selected - all products' => 'Select Product(s) if nothing selected - all products', 'Select Type of Element' => 'Seleziona Tipo di Elemento', 'Select a plugin' => 'Seleziona un Plugin', 'Select option' => 'Seleziona un\'opzione', 'Selected for E-Mailing' => 'Seleziona a chi mandare E-mail', 'Self-Service Store Configuration' => 'Cnfigurazione Negozio Self-Service', 'Semicolon' => 'Punto e virgola', 'Send Autoclose Notification to User aMember will email an autoresponder to user when ticket is closed due to inactivity' => 'Send Autoclose Notification to User aMember will email an autoresponder to user when ticket is closed due to inactivity', 'Send Cancel (due to upgrade) Notifications to User send email to member when he cancels recurring subscription due to upgrade.' => 'Notifica Cancellazione (per aggiornamento) al Cliente inviata quando cancella abbonamento per aggiornamento.', 'Send Cancel Notifications to Admin send email to admin when recurring subscription cancelled by member' => 'Notifica di Cancellazione all\'Amministratore', 'Send Cancel Notifications to User send email to member when he cancels recurring subscription.' => 'Notifica Cancellazione al Cliente quando cancella l\'abbonamento ricorrente.', 'Send Copy of All Admin Notifications will be used to send copy of email notifications to admin you can specify more then one email separated by comma: test@email.com,test1@email.com,test2@email.com' => 'Inoltra tutte le Notifiche di Admin viene inviata una copia di tutte le notifiche mandate ad Admin, puoi mettere più email separate dalla virgola.', 'Send Credit Card Rebill Stats to Admin Credit Card Rebill Stats will be sent to Admin daily. It works for payment processors like Authorize.Net and PayFlow Pro only' => 'Statistiche Riaddebito Carte ad Admin Inviate ogni giorno, funziona solo con sistemi come Authorize.Net e PayFlow Pro', 'Send E-Mail Message' => 'Invia Messaggio E-mail', 'Send E-Mail Messages' => 'invia Messaggi E-mail', 'Send E-Mail if customer has subscription (required)' => 'Invia E-Mail de il Cliente ha un\'iscrizione attiva (obbligatorio)', 'Send E-Mail if invoice has the following subscriptions (required)' => 'Spedisci Email se la ricevuta ha le seguenti iscrizioni (obbligatorio)', 'Send E-Mail only if customer has no subscription (optional)' => 'Invia E-Mail solo se il Cliente non ha un\'iscrizione attiva (opzionale)', 'Send E-Mail when subscription expires (required)' => 'Spedisci Email quando l\'abbonamento scade (obbligatorio)', 'Send E-Mail when the next subscription is started (required)' => 'Spedisci Email quando viene attivato il prossimo abbonamento (obbligatorio)', 'Send New E-Mail' => 'Invia Nuova E-mail', 'Send Notification When Ticket is Assigned to Admin aMember will email a notification to admin each time ticket is assigned to him' => 'Send Notification When Ticket is Assigned to Admin aMember will email a notification to admin each time ticket is assigned to him', 'Send Notification about New Messages to Admin aMember will email a notification to admin each time user responds to a ticket' => 'Invia la notifica di Nuovo Messaggio all\'Amministratore aMember spedirà un\'e-mail di notifica all\'Amministratore ogni volta che un cliente risponde ad un ticket', 'Send Notification about New Messages to Customer aMember will email a notification to user each time admin responds to a user ticket' => 'Invia la notifica di Nuovo Messaggio all\'utente aMember spedirà un\'e-mail di notifica all\'utente ogni volta che l\'Amministratore risponde ad un suo ticket', 'Send Notification to Admin When Profile is Changed admin will receive an email if user has changed profile' => 'Notifica profilo Modificato ad Admin viene inviata se un utente modifica il suo profilo', 'Send Registration E-Mail once customer completes signup form (before payment)' => 'Invia E-mail di Registrazione una volta che l\'utente compila il modulo di iscrizione (prima del pagamento)', 'Send Registration E-Mail to Admin once customer completes signup form (before payment)' => 'Invia Email registrazione ad Admin quanto il\'utente si iscrive (ma prima del pagamento)', 'Send Registration E-Mail to this user' => 'Invia E-mail di Registrazione a questo utente', 'Send Signup E-Mail once FIRST subscripton is completed' => 'Invia E-mail di Iscrizione dopo che la prima iscrizione è completata', 'Send Test E-Mail' => 'Invia E-mail di Test', 'Send message' => 'Spedisci Messaggio', 'Send reports to my email' => 'Invia i Report alla mia email', 'SendGrid Password' => 'Password SendGrid', 'SendGrid Username' => 'Username SendGrid', 'Sender' => 'Mittente', 'Sending Test E-Mail...' => 'Sto inviando l\'email di test...', 'Sending e-mail (sent to %d from %d)' => 'Sto inviando le e-mail (inviate a %d di %d)', 'Server Timezone' => 'Fuso Orario Server', 'Session Storage' => 'Dove salvo le Sessioni?', 'Set Access Permissions' => 'Imposta Permessi di Accesso', 'Setup/Configuration' => 'Setup/Configurazione', 'Setup/Configuration : ' => 'Setup/Configurazione : ', 'Shopping Cart Settings' => 'Impostazioni Carrello', 'Should be greater than %d' => 'Dovrebbe essere maggiore di %d', 'Should be greater than 0' => 'Dovrebbe essere maggiore di 0', 'Should be less then %d' => 'Dovrebbe essere minore di %d', 'Show Activation Details in user area' => 'Show Activation Details in user area', 'Show Avatars in Ticket Conversation this option has priority over gravatar if enabled' => 'Show Avatars in Ticket Conversation this option has priority over gravatar if enabled', 'Show Error Message' => 'Mostra Messaggi di Errore', 'Show Gravatars in Ticket Conversation more details about gravatar can be found %shere%s' => 'Show Gravatars in Ticket Conversation more details about gravatar can be found %shere%s', 'Show Search Function in FAQ' => 'Mostra Funzione Ricerca nelle FAQ', 'Show invoices with selected statuses' => 'Mostra Ricevuta per gli Stati selezionati', 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation' => 'Signature Text You can use the following placeholders %name_f%, %name_l% it will be expanded to first and last name of admin in operation', 'Signup Form (signup)' => 'Modulo d\'Ordine (signup)', 'Signup Form Configuration' => 'Configurazione del Modulo di Iscrizione', 'Signup IP' => 'IP Signup', 'Signup Info' => 'Info Iscrizione', 'Signup Messages' => 'Messaggi di Iscrizione', 'Site is temporarily disabled for maintenance' => 'Il sito è temporaneamente disabilitato per manutenzione', 'Size' => 'Dimensione', 'Size Width × Height' => 'Dimensione Larghezza × Altezza', 'Size of input field' => 'Dimensione del Campo', 'Size of textarea field Columns × Rows' => 'Dimensione Campo TextArea Colonne × Righe', 'Skip' => 'Salta', 'Skip Index Page if User is Logged-in When logged-in user try to access /amember/index page, he will be redirected to /amember/member' => 'Ignora Pagina Index Utenti Loggati se un utente loggato accede a /amember/index viene rediretto alla pagina /amember/member', 'Skip Line if Exist User with Same Login' => 'Salta la linea se esiste un utente con lo stesso Nome Utente', 'So you can manually mark payment as refunded or charged-back. Access will be revoked immediately.' => 'Perciò puoi contrassegnare manualmente come rimborsato il pagamento e l\'acceso verrà revocato immediatamente.', 'Software version info' => 'Versione Software', 'Sometimes, after configuration errors and as result of software problems, aMember users database and third-party scripts databases becomes out of sync. Then you can run rebuild process manually to get databases fixed.' => 'A volte, dopo errori di configurazione e a causa di errori nei software, il database utenti di aMember
      e i database utenti di software di terze parti si de-sincronizzano.
      In questo caso puoi lanciare la ricostruzione database per sistemare gli errori.', 'Sort' => 'Ordina', 'Sort Order' => 'Ordinamento', 'Sort order' => 'Ordinamento', 'Source' => 'Sorgente', 'Space' => 'Spazio', 'Specific Coupon' => 'Buono Sconto Specifico', 'Specified folder is already protected. Please alter existing record or choose another folder.' => 'Cartella specificata già protetta. Cambia la protezione attuale oppure scegli un\'altra cartella.', 'Specify Exact Dates' => 'Specifica Date Esatte', 'Standard PHP Sessions' => 'Sessioni PHP Standard', 'Start Date Calculation rules for subscription start date calculation. MAX date from alternatives will be chosen. This settings has no effect for recurring subscriptions' => 'Calcolo della data inziale regole per il calcolo della data di inizio iscrizione. Verrà scelta la data più ALTA presente nelle alternative. Questi settaggi non hanno effetto sulle iscrizioni ricorrenti', 'Start and Expiration Dates' => 'Date di Inizio e di Scadenza', 'Started' => 'Iniziato', 'Step %d of %d' => 'Passo %d di %d', 'Stop Recurring' => 'Stop ai Pagamenti Ricorrenti', 'Street2' => 'Indirizzo (seconda linea)', 'String' => 'String', 'Subaffiliate' => 'SubAffiliati', 'Subject is required' => 'Oggetto Obblogatorio', 'Submitting...' => 'Elaborazione...', 'Subscription' => 'Iscrizione', 'Subscription (Either ID or Title)' => 'Abbonamento (ID o Nome)', 'Subscription Begin Date' => 'Data Inizio Abbonamento', 'Subscription Expiration (or next rebill date if subscription is recurring)' => 'Scadenza Iscrizione (o prossimo pagamento se in abbonamento)', 'Subscription Expire Date' => 'Data Scadenza Abbonamento', 'Subscription field should have either numeric value which represent subscription in current installation or title that exactly match product title in aMember. You can find these values at %sManage Products%s page, column # or Title.' => 'Il campo Abbonamento deve contenere un valore numerico che corrisponde ad un Abbonamento di questa installazione, o il Nome esatto di un prodotto di aMember. Puoi trovare questi dati nella pagina %sGestisci Prodotti%s selezionando il prodotto che ti interessa.', 'Suggest Feature' => 'Suggerisci Funzionalità', 'Super Admin' => 'Super Amministratore ', 'Surcharge' => 'Sovraccarico', 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead' => 'Surcharge to be additionally charged when customer moves [From]->[To] plan aMember will not charge First Price on upgrade, use Surcharge instead', 'System Info' => 'Informazioni di Sistema', 'THEME' => 'TEMA', 'Table' => 'Tabella', 'Tables to Purge' => 'Tabelle da Cancellare', 'Tabulation' => 'Tabulazione', 'Target User move information to' => 'Target User move information to', 'Tax information ' => 'Informazioni IVA/VAT', 'Technical E-Mail Address shown on error pages. If empty, [Admin E-Mail Address] is used' => 'Indirizzo Email Tecnico mostrato nelle pagine di errore. Se vuoto viene usato quello di Amministrazione', 'Template alternative template for signup page' => 'Template alternativi per la pagina di iscrizione', 'Template alternative template for this page' => 'Template alternative template for this page', 'Template alternative template for this video aMember will look for templates in [application/default/views/] folder and in theme\'s [/] folder and template filename must start with [layout]' => 'Template alternative template for this video aMember will look for templates in [application/default/views/] folder and in theme\'s [/] folder and template filename must start with [layout]', 'Terms Text automatically calculated if empty' => 'Termini calcolati automaticamente se è vuoto', 'Test E-Mail Settings' => 'Testa e Settaggi E-mail', 'Text' => 'Testo', 'Text (unlimited length string/data)' => 'Text (lunghezza illimitata string/data)', 'Text E-Mail Unsubscribe Link %link% will be replaced to actual unsubscribe URL' => 'TESTO Link Cancellazione Email %link% sarà rimpiazzato con il vero URl di cancellazione', 'Text Link' => 'Link Testuale', 'Text Links' => 'Link Testuali', 'Text in your file should be encoded in UTF-8 encoding.' => 'Il testo nel tuo file deve essere codificato con lo standard UTF-8', 'TextArea' => 'Area di Testo', 'The action has been repeated, ipn script response [%s]' => 'Azione ripetuta di nuovo, la risposta IPN è [%s]', 'The code [%s] is already used by signup form #%s, please choose another code' => 'Il codice [%s] è già in uso in una pagina d\'ordine (signup) #%s, scegli un altro codice', 'The password is entered incorrectly' => 'La Password inserita è sbagliata', 'Theme to Include to Roster' => 'Tema da Includere nel Roster', 'There is %s users with same registration IP Address' => 'Ci sono %s utenti con lo stesso IP di registrazione', 'This IP is Banned' => 'Questo IP è Bloccato', 'This code can be inserted into any HTML page on your website or into any WordPress post or page' => 'Questo codice può essere inserito in qualsiasi pagina HTML del tuo sito o in qualsiasi post o pagina Wordpress', 'This email template is empty in given language. Press [Copy] to copy template from default language [English] Press [Skip] to type it manually from scratch.' => 'Questo template email è vuoto per la lingua selezionata. Premi [Copia] per copiare il template dalla lingua originale [Inglese] Premi [Salta] per scriverlo manualmente.', 'This field is required for choosen action' => 'Questo campo è obbligatorio per l\'azione scelta', 'This field is requred' => 'Questo campo è obbligatorio', 'This is necessary to run aMember CP -> Rebuild DB -> Rebuild Core and Invoice database after import' => 'Dopo l\'impoortazione è necessario lanciare Ricostruisci Database -> Ricostruisci Core Database e Ricevuta Database ', 'This rule is for particular affiliate groups you can add user groups and assign it to customers in User editing form' => 'This rule is for particular affiliate groups you can add user groups and assign it to customers in User editing form', 'This rule is for particular payment system' => 'Questa regola serve per specifici Sistemi di Pagamento ', 'This rule is for particular product categories if none specified, rule works for all product categories' => 'Questa regola vale per specifiche Categorie Prodotti se non viene specificato nulla, la regola vale per tutte le categorie', 'This rule is for particular products if none specified, rule works for all products' => 'This rule is for particular products if none specified, rule works for all products', 'This user exceeded %sAccount Sharing Prevention%s limits and temporarily locked.' => 'Questo Utente ha superato i limiti di %sPrevenzione Condivisione Account%s ed è stato temporaneamente bloccato.', 'This user is not a reseller' => 'Questo Utente non è un Rivenditore', 'Ticket Categories' => 'Categorie Ticket', 'Ticket#' => 'Ticket#', 'Tickets Assigned to Me' => 'Ticket Assegnati a Me', 'Time' => 'Ora', 'Time Format' => 'Formato Ora', 'Title displayed to customers' => 'Titolo visualizzato agli utenti', 'Title of Element' => 'Nome dell\'elemento', 'Title of Report for your Reference' => 'Titolo del Report per tua referenza', 'Title/URL/Path' => 'Nome/URL/Percorso', 'To Pay' => 'Da Pagare', 'To Product' => 'Al Prodotto', 'To order this product user must have an when user orders this subscription, it will be checked that user has one from the following subscriptions' => 'Per ordinare questo prodotto un utente deve avere aMember controlla che l\'utente che sta ordinando abbia una di queste iscrizioni altrimenti blocca l\'ordine', 'To restore the aMember database please pick a previously saved aMember Pro backup.' => 'Per Rigenerare il database di aMember seleziona un backup precedente.', 'To save a spreadsheet as a comma separate value (CSV) file (OpenOffice):' => 'Per salvare un foglio come ile CSV (OpenOffice):', 'To starting sharing media files, you have to download either free or commercial version of FlowPlayer
      ' => 'Per iniziare a condividere file media devi scaricarfe una versione gratuita o a pagamento di FlowPlayer
      ', 'To use coupon from this batch user must have an when user uses coupon, it will be checked that user has one from the following subscriptions' => 'Per usare il Buono Sconto l\'utente deve essere se lasci vuoto questa cosa non viene considerata', 'To verify import result go to %sBrowse Users%s' => 'Per Verificare i riultati dell\'Importazione vai a %sGestione Utenti%s', 'Top %d Affiliates' => 'Migliori %d Affiliati', 'Top Affiliates' => 'Migliori Affiliati', 'Total Paid' => 'Totale Pagato', 'Total to Pay' => 'Totale da Pagare', 'Trace' => 'Traccia', 'Traditional .htpasswd' => '.htpasswd Tradizionale', 'Transactions Log' => 'Log delle Transazioni', 'Transactions with this coupon:' => 'Pagamenti con questo Buono Sconto:', 'Translation' => 'Traduzione', 'Trying to copy from unexisting template : %s' => 'Hai cercato di copiare da un templae inesistente: %s', 'Two Columns' => 'Due Colonne', 'URL must be specified without trailing slash' => 'URL deve essere scritto senza lo slash', 'URL must start from %s or %s' => 'La URL deve iniziate da %s oppure %s', 'Unable to cancel subscription' => 'Impossibile cancellare abbonamento', 'Unable to change rebill date' => 'Impossibile cambiare data riaddebito', 'Unable to load widget: %s' => 'Impossibile Caricare Widget: %s', 'Unable to resume subscription' => 'Impossibile riattivare abbonamento', 'Unknown Widget with Id [%s]' => 'Widget Sconosciuto ID [%s]', 'Unknown mode [%s] in %s->%s' => 'Modalità Sconosciuta [%s] in %s->%s', 'Unknown protection method' => 'Metodo Protezione Sconosciuto', 'Unknown report display type [%s]' => 'Tipo Visualizzazione Report Sconosciuto [%s]', 'Unlock' => 'Sblocca', 'Unpack Upgrades' => 'Scompatta Aggiornamento', 'Update Error' => 'Errore di Update', 'Update License Information' => 'Aggiorna le Informazioni di Licenza', 'Update User if Exist User with Same Login' => 'Aggiorna Utente se Esiste un Utente con lo stesso Login', 'Update User if Exist User with Same Login (Do Not Overwrite Existing Password)' => 'Aggiorna Utente se esiste un Utente con lo stesso Login (Non sovrascrive Password esistenti)', 'Upgrade' => 'Aggiorna', 'Upgrade Database' => 'Aggiorna Database', 'Upgrade Download Problem' => 'Problema di Download con l\'Aggiornamento', 'Upgrade Finished' => 'Aggiornamento Terminato', 'Upgrade From' => 'Aggiorna From', 'Upgrade Price Calculation Type' => 'Aggiorna Calcolo Prezzo', 'Upgrade To' => 'Aggiorna a', 'Upload' => 'Carica', 'Upload file [email-templates.xml]' => 'Carica File [email-templates.xml]', 'Uploaded file is not valid aMember Pro backup' => 'Questo file di Backup non è un backup valido di aMember', 'Upsell - Replace Product from [Conditions] field' => 'Upsell - Rimpiazza il Prodotto dal campo [Conditions]', 'Upsell Configuration' => ' Configurazione Upsell', 'Upsell Paths' => 'Percorsi Upsell', 'Url' => 'URL', 'Url url of the page POST data will be sent to' => 'Url url of the page POST data will be sent to', 'Use Custom Settings' => 'Usa Settaggi Personalizzati', 'Use E-Mail Throttle Queue' => 'Usa Email Throttle', 'Use External Cron' => 'Usa Cron Job esterno', 'Use Global Settings' => 'Use Settaggi Globali', 'Use Locale Preference' => 'Usa Standard Lingua', 'Use aMember3 Compatible Urls Enable old style urls (ex.: signup.php, profile.php) Usefull only after upgrade from aMember v3 to keep old links working. ' => 'Usa URL compatibili con aMember3 Abilita URL vecchio stile (es.: signup.php, profile.php). Serve solo se aggiorni un aMember v3 e vuoi mantenere i vecchi link funzionanti. ', 'Use first %d IP address octets to determine different IP (%s)' => 'Usa %d ottetti per determinare IP differenti (%s)', 'Use the following product for demo users keep it empty to use any products' => 'Use questi Prodotti per Utenti Demo lascia vuoto per usarli tutti', 'Use this %slink%s to delete data from aMember v4 database and use clean database for import' => 'Usa questo %slink%s per cancellare i dati nel database di aMember e usa un database pulito per fare l\'importazione', 'Used For' => 'Usato Per', 'Used Rules' => 'Regole Usate', 'Used coupon' => 'Buono Sconto Usato', 'User Access' => 'Accesso Utente', 'User Coupon Usage Count how many times a coupon code can be used by customer' => 'Numero Buoni Sconto usati dai Clienti quante volte un coupon può essere usato dal cliente', 'User Email' => 'Email Utente', 'User IP address' => 'Indirizzo IP Utente', 'User Id' => 'Id Utente', 'User Invoices' => 'Ricevute Cliente', 'User Login' => 'Login Utente', 'User Name' => 'Nome Utente', 'User Notes' => 'Note Utente', 'User Pages Theme' => 'Tema della Pagine Utente', 'User Session Lifetime (minutes) default - 120' => 'Tempo Massimo Sessione Utente valore in minuti (120 min è il default)', 'User currently has access to the following products' => 'Questo Utente ha l\'accesso attivo ai seguenti prodotti', 'User had access to the following products' => 'Questo Utente ha e aveva accesso ai seguenti prodotti', 'User has %s Pending Invoices' => 'Questo Utente ha %s Ricevute in Attesa', 'User is not found in database' => 'Utente non presente nel database', 'User notification' => 'Notifica all\'Utente', 'User-Affiliate Relation Lifetime how long (in days) calculate commission for referred affiliate (default: 0 - forever)' => 'Relazione Utente-Affiliato per quanti giorni calcolare le commissioni per un cliente riferito da un affiliato (0 significa "per sempre")', 'Username Length' => 'Lunghezza Nome Utente', 'Username of Source User move information from this user to target user, this user will be deleted' => 'Username of Source User move information from this user to target user, this user will be deleted', 'Username or e-mail address' => 'Nome Utente o Indirizzo E-mail', 'Users' => 'Clienti', 'Users Breakdown' => 'In base agli Utenti', 'Users Report' => 'Report Clienti', 'Utilities' => 'Funzioni Utili', 'VAT' => 'IVA/VAT', 'VAT Amount' => 'IVA/VAT Totale', 'VAT ID' => 'P.IVA/VAT', 'VAT Rate' => 'Percentuale IVA/VAT', 'Valid license key are one-line string,starts with L and ends with X' => 'Una chiave di licenza valida è di una stringa sola, inizia con L e termina con X', 'Validation Messages to Customer' => 'Messaggi di Validazione per il Cliente', 'Value use % as wildcard mask' => 'Valore usa % come wildcard', 'Value must be alpha-numeric' => 'Il valore deve essere alfanumerico', 'Value must be alphanumeric' => 'Il valore deve essere alfanumerico', 'Values must not be equal' => 'I valori non possono essere identici', 'VatId' => 'P.IVA/VAT', 'Verify E-Mail Address On Signup Page e-mail verification may be enabled for each signup form separately at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Verifica Indirizzo Email nel modulo d\'ordine (signup) la verifica email può essere abilitata separatamente per ogni form', 'Verify New E-Mail Address On Profile Page e-mail verification for profile form may be enabled at aMember CP -> Forms Editor -> Edit, click "configure" on E-Mail brick' => 'Verifica Nuovo Indirizzo Email nel Profilo la verifica email può essere abilitata nel form profilo', 'Version Info' => 'Info Versione', 'Versions for [%s]' => 'Versioni per [%s]', 'Video Player' => 'Player Video', 'Video/Audio File (max upload size %s) You can use this feature only for video and audio formats that %ssupported by %s%s' => 'File Video/Audio (dimensione massima %s) Puoi usare questa funzionalità solo per i formati %ssupportati da %s%s', 'View' => 'Mostra', 'View Coupons' => 'Mostra i Buoni Sconto', 'Void Commission' => 'Annulla Commissione', 'Voided' => 'Annullata', 'WARNING! ALL YOUR CURRENT AMEMBER TABLES AND RECORDS WILL BE REPLACED WITH THE CONTENTS OF THE BACKUP!' => 'WARNING! ALL YOUR CURRENT AMEMBER TABLES AND RECORDS WILL BE REPLACED WITH THE CONTENTS OF THE BACKUP!', 'WARNING! All existing e-mail templates will be removed from database!' => 'ATTENZIONE! Tutti i Template Email verranno rimossi dal database!', 'WARNING! Once [Merge] button clicked, all invoices, payments, logs and other information regarding \'Source User\' will be moved to the \'Target User\' account. \'Source User\' account will be deleted. There is no way to undo this operation!' => 'WARNING! Once [Merge] button clicked, all invoices, payments, logs and other information regarding \'Source User\' will be moved to the \'Target User\' account. \'Source User\' account will be deleted. There is no way to undo this operation!', 'Warnings' => 'Avvertenze', 'Watchers notify the following admins about new messages in this category' => 'Watchers notify the following admins about new messages in this category', 'We will submit a request to payment system or you will be redirected to payment system page to submit refund request' => 'Tenterò una richiesta al sistema di pagamento o verrai rediretto alla pagina del sistema di pagamento per inoltrare una richiesta manuale di rimborso.', 'Webhooks Queue' => 'Coda Webhook', 'Weekly' => 'Ogni Settimana', 'Widget with Id [%s] has not config form' => 'Il Widget con ID [%s] non ha un form di configurazione', 'Wrong id' => 'ID errato', 'Yes, Delete User' => 'Sì, Cancella Utente', 'Yes, assign category' => 'Sì, assegna la categoria', 'Yes, assign group' => 'Sì. Assegna Gruppo', 'Yes, do not e-mail this customer for any reasons' => 'Sì, non inviare email a questo Cliente per nessuna ragione', 'Yes, locked' => 'Sì, bloccato', 'Yes, remove category' => 'Sì, rimuovi la categoria', 'Yes, remove group' => 'Sì, Rimuovi Gruppo', 'You can %ssave%s this report for future use. You will be able to add this report to your dashboard or send it to your email periodically.' => 'Puoi %ssalvare%s questo report per uso futuro. Puoi mettere questo report sulla tua Bacheca oppure fartelo inviare via email periodicamente.', 'You can assign some coupon codes to specific user. Only this user will be able to use this coupon.' => 'Puoi assegnare dei Buoni Sconto a uno specifico utente. Solo questo utente potrà utilizzarlo.', 'You can download %sexample file%s.' => 'Puoi scaricare il %sfile esempio%s.', 'You can import users from CSV file to aMember.' => 'Puoi importare gli utenti dal file CSV in aMember.', 'You can not delete your own account' => 'Non puoi cancellare il tuo stesso account', 'You can not merge user with itself' => 'Non puoi unire un utente con se stesso', 'You can not set up exchange rate for past.' => 'Non puoi impostare il cambio per il passato.', 'You can save this search for later usage, just give it a descriptive name and press "Save" button.' => 'Hai salvato questa Ricerca per un uso futuro, dagli un Nome Descrittivo e premi il pulsante "Salva".', 'You can temporary %sdisable auto-locking for this customer for 1 day%s and allow access for his account.' => 'Puoi temporaneamente %sdisabilitare l\'auto-blocco per questo utente per un giorno%s e permettere l\'accesso al suo account.', 'You have currently choosed the following users for e-mail to:' => 'Hai selezionato i seguenti utenti per l\'invio della email:', 'You have generated %d demo products and %d demo customers' => 'Hai generato %d prodotti demo e %d utenti demo', 'You have imported %d customers' => 'Hai Importato %d Clienti', 'You have license keys from past versions of aMember, please replace it with latest, one-line keys' => 'Hai una chiave di licenza valida per le precedenti versioni di aMember. Sostituiscila con l\'ultima, una chiave si un\'unica riga', 'You have no permissions to perform requested operation' => 'Non hai il permesso di fare questa operazione', 'You have not added any products, your signup forms will not work until you createRecord($row) : null; } // --------- ------------- -------------- -------------- ---------------/ function deleteByFields($name,$day=null){ $this->_db->query("DELETE FROM ?_email_template WHERE name=? {AND day=?}", $name, $day!="" ? $day : DBSIMPLE_SKIP ); } /** * Find exact template by criteria * @return EmailTemplate */ function getExact($name, $lang=null, $day=null) { $row = $this->getDi()->db->selectRow("SELECT * FROM ?_email_template WHERE name=? {AND lang=?} {AND day=?}", $name, is_null($lang) ? DBSIMPLE_SKIP : $lang, is_null($day) ? DBSIMPLE_SKIP : $day); return $row ? $this->createRecord($row) : null; } /** * Search available days options by criteria * @return array of int (available days) */ function getDays($name, $exclude=null){ return $this->getDi()->db->selectCol("SELECT DISTINCT day FROM ?_email_template WHERE name=? AND day IS NOT NULL {AND day<>?} ORDER BY day", $name, is_null($exclude) ? 0 : $exclude ); } public function getLanguages($name, $day=null, $exclude=null){ return $this->_db->selectCol("SELECT DISTINCT lang as ARRAY_KEY, lang FROM ?_email_template WHERE name=? {AND day=?} {AND lang<>?}", $name, is_null($day) ? DBSIMPLE_SKIP : $day, is_null($exclude) ? DBSIMPLE_SKIP : $exclude ); } public function sendProductWelcomeEmails(User $user, $invoiceOrAccess = null) { $product_ids = array(); if($invoiceOrAccess instanceof Access) { $product_ids[] = $invoiceOrAccess->product_id; } elseif($invoiceOrAccess instanceof Invoice) { $payment = current($invoiceOrAccess->getPaymentRecords()); $invoice = $invoiceOrAccess; $product_ids = $this->getDi()->db->selectCol('SELECT product_id from ?_access where invoice_id = ?',$invoiceOrAccess->invoice_id); } if (!count($product_ids)) return; $product_id = $product_ids[0]; $product = $this->getDi()->productTable->load($product_id); foreach ($this->getDi()->resourceAccessTable->getProductWelcomeEmails($product_ids) as $et) { // check if no matching not_conditions if (!$et->checkNotConditions($user)) continue; $recipients = array(); if($et->recipient_user) { $recipients[] = $user; } if ($et->recipient_aff && $user->aff_id && ($aff = $this->getDi()->userTable->load($user->aff_id, false))) { $recipients[] = $aff; } if($et->recipient_admin) { $recipients[] = Am_Mail_Template::TO_ADMIN; } if($et->recipient_emails) { foreach (array_map('trim', explode(',', $et->recipient_emails)) as $email) if($email) $recipients[] = $email; } $tpl = Am_Mail_Template::createFromEmailTemplate($et); $tpl->setLast_product_title($product->getTitle()); $tpl->setUser($user); if (isset($payment)) { $tpl->setPayment($payment); } if (isset($invoice)) { $tpl->setInvoice($invoice); } foreach ($recipients as $recipient) { $tpl->send($recipient); } } } /** * @link Invoice->start */ public function sendZeroAutoresponders(User $user, $invoiceOrAccess = null) { $this->sendProductWelcomeEmails($user, $invoiceOrAccess); foreach ($this->getDi()->resourceAccessTable-> getAllowedResources($user, ResourceAccess::EMAILTEMPLATE) as $et) { if (($et->name != EmailTemplate::AUTORESPONDER) || ($et->day != 1)) continue; // check if no matching not_conditions if (!$et->checkNotConditions($user)) continue; // don't send same e-mail twice $sent = (array)$user->data()->get('zero-autoresponder-sent'); if (in_array($et->pk(), $sent)) continue; $sent[] = $et->pk(); /// $recipients = array(); if($et->recipient_user) { $recipients[] = $user; } if ($et->recipient_aff && $user->aff_id && ($aff = $this->getDi()->userTable->load($user->aff_id, false))) { $recipients[] = $aff; } if($et->recipient_admin) { $recipients[] = Am_Mail_Template::TO_ADMIN; } if($et->recipient_emails) { foreach (array_map('trim', explode(',', $et->recipient_emails)) as $email) if($email) $recipients[] = $email; } $tpl = Am_Mail_Template::createFromEmailTemplate($et); if (!is_null($invoiceOrAccess)) { if($invoiceOrAccess instanceof Invoice) $tpl->setInvoice($invoiceOrAccess); $tpl->setLast_product_title($this->getLastProductTitle($et->fn_id, $invoiceOrAccess)); } $tpl->setUser($user); foreach ($recipients as $recipient) { $tpl->send($recipient); } // store sent emails $user->data()->set('zero-autoresponder-sent', $sent)->update(); } } public function sendZeroPayments(User $user, InvoicePayment $payment) { $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $invoice = $payment->getInvoice(); $product_ids = array_filter(array_map(function($el) { return $el->item_type == 'product' ? $el->item_id : null; }, $invoice->getItems())); if (!$product_ids) return; foreach ($this->getDi()->resourceAccessTable->getPaymentEmails($product_ids) as $et) { if (($et->name != EmailTemplate::PAYMENT) || ($et->day != 0)) continue; // check if no matching not_conditions if (!$et->checkNotConditions($user)) continue; $recipients = array(); if($et->recipient_user) { $recipients[] = $user; } if ($et->recipient_aff && $user->aff_id && ($aff = $this->getDi()->userTable->load($user->aff_id, false))) { $recipients[] = $aff; } if($et->recipient_admin) { $recipients[] = Am_Mail_Template::TO_ADMIN; } if($et->recipient_emails) { foreach (array_map('trim', explode(',', $et->recipient_emails)) as $email) if($email) $recipients[] = $email; } $tpl = Am_Mail_Template::createFromEmailTemplate($et); $tpl->setPayment($payment); $tpl->setInvoice($invoice = $payment->getInvoice()); $tpl->setInvoice_text($invoice->render('', $payment)); $tpl->setInvoice_html($invoice->renderHtml($payment)); $tpl->setUser($user); $tpl->setInvoice_items($invoice->getItems()); $tpl->setProduct($invoice->getItem(0)->tryLoadProduct()); if ($et->attach_pdf_invoice) { try{ $pdf = Am_Pdf_Invoice::create($payment); $pdf->setDi($this->getDi()); $tpl->getMail()->createAttachment( $pdf->render(), 'application/pdf', Zend_Mime::DISPOSITION_ATTACHMENT, Zend_Mime::ENCODING_BASE64, $pdf->getFileName() ); } catch(Exception $e) { $this->getDi()->errorLogTable->logException($e); } } foreach ($recipients as $recipient) { $tpl->send($recipient); } } } protected function getLastProductTitle($fn_id, $invoiceOrAccessOrUser) { if ($fn_id['fn'] == 'product_id') return $this->getDi()->productTable->load($fn_id['id'])->title; if ($invoiceOrAccessOrUser instanceof Invoice) return $this->getDi()->db->selectCell(" SELECT p.title FROM ?_invoice_item ii LEFT JOIN ?_product_product_category ppc ON (ppc.product_id = ii.item_id) LEFT JOIN ?_product p ON (p.product_id = ii.item_id) WHERE ii.invoice_id = ?d {AND ppc.product_category_id = ?d} ", $invoiceOrAccessOrUser->pk(), $fn_id['id'] != -1 ? $fn_id['id'] : DBSIMPLE_SKIP); if ($invoiceOrAccessOrUser instanceof Access) return $this->getDi()->db->selectCell(" SELECT p.title FROM ?_access a LEFT JOIN ?_product p ON (p.product_id = a.product_id) WHERE a.access_id = ?d ", $invoiceOrAccessOrUser->pk()); // only cron autoresponder if ($invoiceOrAccessOrUser instanceof User) { return $this->getDi()->db->selectCell(" SELECT title FROM ?_product WHERE product_id = ( SELECT a.product_id FROM ?_access a WHERE begin_date <= ? AND a.user_id = ?d AND a.product_id IN ( SELECT us.product_id FROM ?_user_status us {LEFT JOIN ?_product_product_category ppc ON (ppc.product_id = us.product_id)} WHERE us.user_id=?d AND us.status=?d {AND ppc.product_category_id = ?d} ) ORDER BY begin_date DESC LIMIT 1 ) ", $this->getDi()->sqlDate ,$invoiceOrAccessOrUser->pk(), $invoiceOrAccessOrUser->pk(), User::STATUS_ACTIVE, $fn_id['id'] != -1 ? $fn_id['id'] : DBSIMPLE_SKIP, $fn_id['id'] != -1 ? $fn_id['id'] : DBSIMPLE_SKIP); } return ''; } static function onInvoiceStarted(Am_Event_InvoiceStarted $event) { $invoice = $event->getInvoice(); $event->getDi()->emailTemplateTable->sendZeroAutoresponders($invoice->getUser(), $invoice); if ($event->getDi()->config->get('send_free_payment_admin') && floatval($invoice->first_total) == 0) { if ($et = Am_Mail_Template::load('send_free_payment_admin')) { $et->setUser($event->getUser()) ->setInvoice($invoice) ->setPayment($event->getPayment()) ->setInvoice_text($invoice->render()) ->setInvoice_html($invoice->renderHtml()); $et->send(Am_Mail_Template::TO_ADMIN); } } } static function onPaymentWithAccessAfterInsert(Am_Event_PaymentWithAccessAfterInsert $event) { /** * This e-mail is sent for first payment in invoice only * another template must be used for the following payments */ // if ($event->getInvoice()->getPaymentsCount() != 1) return; $event->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $products = array(); foreach ($event->getInvoice()->getProducts() as $product) $products[] = $product->getTitle(); if ($event->getDi()->config->get('send_payment_mail')) { $et = Am_Mail_Template::load('send_payment_mail', $event->getUser()->lang); if ($et && (($event->getPayment()->amount > 0))) { $et->setUser($event->getUser()) ->setInvoice($event->getInvoice()) ->setPayment($event->getPayment()) ->setInvoice_items($event->getInvoice()->getItems()) ->setInvoice_text($event->getInvoice()->render('', $event->getPayment())) ->setInvoice_html($event->getInvoice()->renderHtml($event->getPayment())) ->setProduct_title(implode (", ", $products)); if ($event->getDi()->config->get('send_pdf_invoice') && $event->getDi()->config->get('pdf_invoice_sent_user')) { try{ $event->getDi()->locale->changeLanguageTo($event->getUser()->lang); $invoice = Am_Pdf_Invoice::create($event->getPayment()); $invoice->setDi(Am_Di::getInstance()); $et->getMail()->createAttachment( $invoice->render(), 'application/pdf', Zend_Mime::DISPOSITION_ATTACHMENT, Zend_Mime::ENCODING_BASE64, $invoice->getFileName() ); $event->getDi()->locale->restoreLanguage(); } catch(Exception $e) { Am_Di::getInstance()->errorLogTable->logException($e); } } $et->send($event->getUser()); } } if ($event->getDi()->config->get('send_payment_admin')) { $et = Am_Mail_Template::load('send_payment_admin', $event->getUser()->lang); if ($et && (($event->getPayment()->amount > 0))) { $et->setUser($event->getUser()) ->setInvoice($event->getInvoice()) ->setPayment($event->getPayment()) ->setInvoice_items($event->getInvoice()->getItems()) ->setInvoice_text($event->getInvoice()->render('', $event->getPayment())) ->setInvoice_html($event->getInvoice()->renderHtml($event->getPayment())) ->setProduct_title(implode (", ", $products)); if ($event->getDi()->config->get('send_pdf_invoice', false) && $event->getDi()->config->get('pdf_invoice_sent_admin')) { try{ $invoice = Am_Pdf_Invoice::create($event->getPayment()); $invoice->setDi(Am_Di::getInstance()); $et->getMail()->createAttachment( $invoice->render(), 'application/pdf', Zend_Mime::DISPOSITION_ATTACHMENT, Zend_Mime::ENCODING_BASE64, $invoice->getFileName() ); } catch(Exception $e) { Am_Di::getInstance()->errorLogTable->logException($e); } } $et->send(Am_Mail_Template::TO_ADMIN); } } $event->getDi()->emailTemplateTable->sendZeroPayments($event->getUser(), $event->getPayment()); } protected function isNotificationRuleMatch(EmailTemplate $tmpl, Invoice $invoice) { if (!$tmpl->conditions) return true; $conds = array(); foreach(explode(',', $tmpl->conditions) as $item) { preg_match('/([A-Z]*)-(.*)/', $item, $match); $conds[$match[1]][] = $match[2]; } //check product conditions $product_ids = array(); if (isset($conds['CATEGORY'])) { $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts(); foreach ($conds['CATEGORY'] as $cat_id) { if (isset($catProducts[$cat_id])) $product_ids = array_merge($product_ids, $catProducts[$cat_id]); } } if (isset($conds['PRODUCT'])) { $product_ids = array_merge($product_ids, $conds['PRODUCT']); } if (!count($product_ids) && isset($conds['CATEGORY'])) { //user set up categories without products return false; } if (count($product_ids)) { $invoice_product_id = array_map(function($a) {return $a->pk();}, $invoice->getProducts()); if (!array_intersect($product_ids, $invoice_product_id)) return false; } //check paysystem conditions if (isset($conds['PAYSYSTEM']) && !in_array($invoice->paysys_id, $conds['PAYSYSTEM'])) return false; return true; } /** * * @param string $name * @return array array day => array(templates for day) */ protected function findPendingNotificationRules($name) { $templates = $this->findByName($name); $days = array(); foreach ($templates as $tpl) { $dd = array_filter(explode(',', $tpl->days), function($a) {return $a!=="";}); foreach ($dd as $d) { $days[$d][] = $tpl; } } return $days; } protected function sendPendingNotifications($day, $invoices, $tpls, $sendCallback) { foreach ($invoices as $invoice) { $user = $invoice->getUser(); if (!$user) continue; foreach ($tpls as $tpl) { if ($this->isNotificationRuleMatch($tpl, $invoice)) { if (!empty($this->_pendingSent[$sendCallback[1]][$invoice->getUser()->pk()])) continue; $mailTpl = Am_Mail_Template::createFromEmailTemplate($tpl); $mailTpl->setUser($invoice->getUser()); $mailTpl->setInvoice($invoice); $mailTpl->setInvoice_text($invoice->render()); $mailTpl->setInvoice_html($invoice->renderHtml()); if ($invoice->due_date < sqlDate('+ 7 days')) { $invoice->updateQuick('due_date', sqlDate('+ 7 days')); } $mailTpl->setPaylink($this->getDi()->url('pay/' . $invoice->getSecureId('payment-link'),false,null)); $mailTpl->setDay($day); $products = array(); foreach ($invoice->getProducts() as $product) $products[] = $product->getTitle(); $mailTpl->setProduct_title(implode (", ", $products)); call_user_func($sendCallback, $mailTpl, $invoice); $this->_pendingSent[$sendCallback[1]][$invoice->getUser()->pk()] = true; break; } } } } protected function sendPendingNotificationToUser(Am_Mail_Template $mailTpl, Invoice $invoice) { $user = $invoice->getUser(); if ($user->unsubscribed) return; $mailTpl->send($user); } protected function sendPendingNotificationToAdmin(Am_Mail_Template $mailTpl, Invoice $invoice) { $mailTpl->sendAdmin(); } protected function _sendCronPendingNotifications($name, $sendCallback) { $days = $this->findPendingNotificationRules($name); unset($days[0]); //it should been send on invoice created foreach ($days as $d => $tpls) { if (substr($d, -1) == 'h') continue; //it should been send on hourly cron $date = $this->getDi()->dateTime; $date->modify('-' . $d . ' days'); $end_date = $date->format('Y-m-d H:i:59'); $date->modify('- 23 hours'); $date->modify('- 59 minutes'); $begin_date = $date->format('Y-m-d H:i:00'); $this->_sendCronPendingNotificationsByPeriod($d, $tpls, $sendCallback, array( $begin_date, $end_date )); } } protected function _sendCronHourlyPendingNotifications($name, $sendCallback) { $days = $this->findPendingNotificationRules($name); unset($days[0]); //it should been send on invoice created foreach ($days as $d => $tpls) { if (substr($d, -1) != 'h') continue; //it should been send on daily cron $d = str_replace('h', '', $d); $date = $this->getDi()->dateTime; $date->modify('-' . $d . ' hours'); $end_date = $date->format('Y-m-d H:i:59'); $date->modify('- 59 minutes'); $begin_date = $date->format('Y-m-d H:i:00');; $this->_sendCronPendingNotificationsByPeriod(0, $tpls, $sendCallback, array( $begin_date, $end_date )); } } protected function _sendCronPendingNotificationsByPeriod($d, $tpls, $sendCallback, $period) { list($begin_date, $end_date) = $period; $query = new Am_Query($this->getDi()->invoiceTable); $query = $query->addWhere('status=?', Invoice::PENDING) ->addWhere('tm_added>?', $begin_date) ->addWhere('tm_addedgetAlias(); $query->addWhere("NOT EXISTS (SELECT * FROM ?_invoice_payment ip WHERE ip.user_id = $t.user_id AND ip.dattm>=? AND ip.dattmgetFoundRows()) { $invoices = $query->selectPageRecords(0, $count); $this->sendPendingNotifications($d, $invoices, $tpls, $sendCallback); } } protected function _sendZeroPendingNotifications($name, $sendCallback, Invoice $invoice) { $days = $this->findPendingNotificationRules($name); if (isset($days[0])) { $tpls = $days[0]; $this->sendPendingNotifications(0, array($invoice), $tpls, $sendCallback); } } public function sendCronPendingNotifications() { $this->_sendCronPendingNotifications('pending_to_user', array($this, 'sendPendingNotificationToUser')); $this->_sendCronPendingNotifications('pending_to_admin', array($this, 'sendPendingNotificationToAdmin')); } public function sendCronHourlyPendingNotifications() { $this->_sendCronHourlyPendingNotifications('pending_to_user', array($this, 'sendPendingNotificationToUser')); $this->_sendCronHourlyPendingNotifications('pending_to_admin', array($this, 'sendPendingNotificationToAdmin')); } public function onInvoiceAfterInsert(Am_Event $event) { $invoice = $event->getInvoice(); if ($invoice->data()->get('added-by-admin')) return; // do not send automatic e-mails if invoice added by admin $this->_sendZeroPendingNotifications('pending_to_user', array($this, 'sendPendingNotificationToUser'), $invoice); $this->_sendZeroPendingNotifications('pending_to_admin', array($this, 'sendPendingNotificationToAdmin'), $invoice); } public function sendCronPayments() { $this->getDi()->plugins_payment->loadEnabled()->getAllEnabled(); $mails = $this->findBy(array('name' => EmailTemplate::PAYMENT)); if (!$mails) return; // nothing to send $byDatePayment = $byDateInvoice = array(); // templates by expiration date foreach ($mails as $et) { $et->_productIds = $et->findMatchingProductIds(); if ($et->day > 0) { $date = date('Y-m-d', strtotime("+{$et->day} days", $this->getDi()->time)); $byDateInvoice[$date][] = $et; } elseif($et->day < 0) { $date = date('Y-m-d', strtotime("{$et->day} days", $this->getDi()->time)); $byDatePayment[$date][] = $et; } } if(count($byDatePayment)) { $q = $this->getDi()->db->queryResultOnly("SELECT ip.*, GROUP_CONCAT(ii.item_id) as _product_id FROM ?_invoice_payment ip LEFT JOIN ?_invoice_item ii ON (ip.invoice_id = ii.invoice_id AND ii.item_type = 'product') WHERE DATE(dattm) IN (?a) GROUP BY ip.invoice_payment_id", array_keys($byDatePayment)); while ($row = $this->_db->fetchRow($q)) { $payment = $this->getDi()->invoicePaymentTable->createRecord($row); $invoice = $payment->getInvoice(); $user = $payment->getUser(); $this->_sendCronPayments($byDatePayment[sqlDate($payment->dattm)], explode(',', $row['_product_id']), $user, $payment, $invoice); } } if(count($byDateInvoice)) { $q = $this->getDi()->db->queryResultOnly("SELECT i.*, GROUP_CONCAT(ii.item_id) as _product_id FROM ?_invoice i LEFT JOIN ?_invoice_item ii ON (i.invoice_id = ii.invoice_id AND ii.item_type = 'product') WHERE i.rebill_date IN (?a) GROUP BY i.invoice_id", array_keys($byDateInvoice)); $maxPaymentId = $this->_db->selectCell("SELECT IFNULL(MAX(invoice_payment_id), 0)+1 FROM ?_invoice_payment"); while ($row = $this->_db->fetchRow($q)) { $invoice = $this->getDi()->invoiceTable->createRecord($row); $payment = $this->getDi()->invoicePaymentRecord; $payment->toggleFrozen(true); $payment->receipt_id = 'NOT PAID'; $payment->display_invoice_id = 'NOT PAID'; $payment->dattm = $invoice->rebill_date; $payment->amount = $invoice->second_total; $payment->invoice_payment_id = $maxPaymentId; $payment->invoice_id = $invoice->pk(); $payment->_setInvoice($invoice); $user = $invoice->getUser(); $this->_sendCronPayments($byDateInvoice[$invoice->rebill_date], explode(',', $row['_product_id']), $user, $payment, $invoice); } } } protected function _sendCronPayments($tmpls, $pids, $user, $payment, $invoice) { if ($user->unsubscribed||!$user->is_approved) return; foreach ($tmpls as $et) { if ($et->_productIds == ResourceAccess::ANY_PRODUCT || (array_intersect($pids, $et->_productIds))) { // check if no matching not_conditions if (!$et->checkNotConditions($user)) continue; $recipients = array(); if($et->recipient_user) { $recipients[] = $user; } if ($et->recipient_aff && $user->aff_id && ($aff = $this->getDi()->userTable->load($user->aff_id, false))) { $recipients[] = $aff; } if($et->recipient_admin) { $recipients[] = Am_Mail_Template::TO_ADMIN; } if($et->recipient_emails) { foreach (array_map('trim', explode(',', $et->recipient_emails)) as $email) if($email) $recipients[] = $email; } $tpl = Am_Mail_Template::createFromEmailTemplate($et); $tpl->setUser($user); $tpl->setPayment($payment); $tpl->setInvoice($invoice); $tpl->setInvoice_text($invoice->render('', $payment)); $tpl->setInvoice_html($invoice->renderHtml($payment)); $tpl->setInvoice_items($invoice->getItems()); $tpl->setProduct($invoice->getItem(0)->tryLoadProduct()); if ($et->attach_pdf_invoice) { try{ $pdf = Am_Pdf_Invoice::create($payment); $pdf->setDi($this->getDi()); $tpl->getMail()->createAttachment( $pdf->render(), 'application/pdf', Zend_Mime::DISPOSITION_ATTACHMENT, Zend_Mime::ENCODING_BASE64, $pdf->getFileName() ); } catch(Exception $e) { $this->getDi()->errorLogTable->logException($e); } } foreach ($recipients as $recipient) { $tpl->send($recipient); } } } } public function sendCronAutoresponders() { $userTable = $this->getDi()->userTable; $etCache = array(); $db = $this->getDi()->db; $q = $this->getDi()->resourceAccessTable->getResourcesForMembers(ResourceAccess::EMAILTEMPLATE)->query(); while ($res = $db->fetchRow($q)) { $user = $userTable->load($res['user_id'], false); if ($user->unsubscribed) continue; if (!$user) continue; // no user found if (!array_key_exists($res['resource_id'], $etCache)) $etCache[$res['resource_id']] = $this->load($res['resource_id'], false); if (!$etCache[$res['resource_id']]) continue; // no template found //do not send zero autoresponder second time if($etCache[$res['resource_id']]->day==1) if (in_array($res['resource_id'], (array)$user->data()->get('zero-autoresponder-sent'))) continue; if (($etCache[$res['resource_id']]->name != EmailTemplate::AUTORESPONDER)) continue; // check if no matching not_conditions if (!$etCache[$res['resource_id']]->checkNotConditions($user)) continue; $recipients = array(); if($etCache[$res['resource_id']]->recipient_user) { $recipients[] = $user; } if($etCache[$res['resource_id']]->recipient_aff && $user->aff_id && ($aff = $this->getDi()->userTable->load($user->aff_id, false))) { $recipients[] = $aff; } if($etCache[$res['resource_id']]->recipient_admin) { $recipients[] = Am_Mail_Template::TO_ADMIN; } if($etCache[$res['resource_id']]->recipient_emails) { foreach (array_map('trim', explode(',', $etCache[$res['resource_id']]->recipient_emails)) as $email) if($email) $recipients[] = $email; } $tpl = Am_Mail_Template::createFromEmailTemplate($etCache[$res['resource_id']]); $tpl->setLast_product_title($this->getLastProductTitle(array('fn' => $res['fn'], 'id' => $res['fn_id']), $user)); $tpl->setUser($user); foreach ($recipients as $recipient) { $tpl->send($recipient); } } } /** * @return PDOStatement */ public function sendCronExpires() { $mails = $this->findBy(array('name' => EmailTemplate::EXPIRE)); if (!$mails) return; // nothing to send $byDate = array(); // templates by expiration date foreach ($mails as $et) { $et->_productIds = $et->findMatchingProductIds(); /// $day = - $et->day; $string = $day . ' days'; if ($day >= 0) $string = "+$string"; if ($day == 0) $string = 'today'; $date = date('Y-m-d', strtotime($string, $this->getDi()->time)); $byDate[$date][] = $et; } $userTable = $this->getDi()->userTable; // now query expirations $q = $this->getDi()->accessTable->queryExpirations(array_keys($byDate)); $sent = array(); // user_id => array('tpl_id') while ($row = $this->_db->fetchRow($q)) { $user = $userTable->createRecord($row); if ($user->unsubscribed||!$user->is_approved) continue; foreach ($byDate[$row['_expire_date']] as $et) { if ($row['_recurring'] && !$et->recurring) continue; // do not send same template agian to the same user if (!empty($sent[$user->user_id]) && array_search($et->pk(), $sent[$user->user_id]) !== false) continue; if ($et->_productIds == ResourceAccess::ANY_PRODUCT || (in_array($row['_product_id'], $et->_productIds))) { // check if no matching not_conditions if (!$et->checkNotConditions($user)) continue; $recipients = array(); if($et->recipient_user) { $recipients[] = $user; } if ($et->recipient_aff && $user->aff_id && ($aff = $this->getDi()->userTable->load($user->aff_id, false))) { $recipients[] = $aff; } if($et->recipient_admin) { $recipients[] = Am_Mail_Template::TO_ADMIN; } if($et->recipient_emails) { foreach (array_map('trim', explode(',', $et->recipient_emails)) as $email) if($email) $recipients[] = $email; } $tpl = Am_Mail_Template::createFromEmailTemplate($et); $tpl->setUser($user); $tpl->setExpires(amDate($row['_expire_date'])); $tpl->setProduct_title($this->getDi()->productTable->load($row['_product_id'])->title); $tpl->setInvoice($row['_invoice_id'] ? $this->getDi()->invoiceTable->load($row['_invoice_id']) : array()); foreach ($recipients as $recipient) { $tpl->send($recipient); } $sent[$user->user_id][] = $et->pk(); } } } } } PK\A default/models/Video.phpnu[mime == 'audio/mpeg' ? 'audio' : 'video'; return $this->getDi()->url("$type/p/id/" . $this->video_id,null,false); } } class VideoTable extends ResourceAbstractTable { protected $_key = 'video_id'; protected $_table = '?_video'; protected $_recordClass = 'Video'; public function getAccessType() { return ResourceAccess::VIDEO; } public function getAccessTitle() { return ___('Video'); } public function getPageId() { return 'video'; } } PK\mdefault/models/User.phpnu[email, Am_Mail::LINK_USER); return null; } function __isset($name) { return ($name == 'unsubscribe_link'); } function delete() { if ($this->user_id <= 0) throw new Am_Exception_InternalError('Could not delete user, user_id is null'); $this->getDi()->hook->call(Am_Event::USER_BEFORE_DELETE, array('user' => $this)); $this->getDi()->invoiceTable->deleteByUserId($this->user_id); $this->getDi()->accessTable->deleteByUserId($this->user_id); $this->checkSubscriptions(false); $this->getDi()->hook->call(new Am_Event_SubscriptionRemoved($this)); parent::delete(); foreach (array('?_access_log', '?_access_cache', '?_user_status', '?_user_user_group') as $table) $this->getAdapter()->query("DELETE FROM $table WHERE user_id=?", $this->user_id); $this->getDi()->couponBatchTable->deleteByUserId($this->user_id); foreach ($this->getDi()->uploadTable->findBy(array( 'prefix' => Am_CustomFieldUpload::UPLOAD_PREFIX, 'user_id' => $this->user_id)) as $upload) { $upload->delete(); } $this->getDi()->hook->call(new Am_Event_UserAfterDelete($this)); } function insert($reload = true) { if (!isset($this->is_approved)) $this->is_approved = !$this->getDi()->config->get('manually_approve'); if (empty($this->remote_addr)) $this->remote_addr = htmlentities(@$_SERVER['REMOTE_ADDR']); if (empty($this->user_agent)) $this->user_agent = @$_SERVER['HTTP_USER_AGENT']; if (empty($this->added)) $this->added = $this->getDi()->sqlDateTime; $this->getDi()->hook->call(new Am_Event_UserBeforeInsert($this)); $ret = parent::insert($reload); if ($this->_passwordChanged) { $event = new Am_Event_SetPassword($this, $this->getPlaintextPass()); $this->getDi()->savedPassTable->setPass($event); $this->getDi()->hook->call($event); } if ($this->_passwordGenerated) { $c = new Am_Crypt_Aes128($this->getDi()->security->siteKey()); $pg = $c->encrypt($this->getPlaintextPass()); $this->getDi()->store->set('pass-generated-' . $this->pk(), $pg, '+6 hours'); } $this->getDi()->hook->call(new Am_Event_UserAfterInsert($this)); $this->_passwordChanged = false; return $ret; } function update() { $oldU = new stdclass; $oldU->user_id = null; if ($this->getDi()->hook->have(array( 'userBeforeUpdate', 'userAfterUpdate', 'subscriptionUpdated')) || $this->getDi()->config->get('manually_approve') ) { // do loading only if hooks are set $oldU = $this->getTable()->load($this->user_id, false); if (!$oldU) $oldU = new self; // avoid errors here $this->getDi()->hook->call(new Am_Event_UserBeforeUpdate($this, $oldU)); } $ret = parent::update(); if ($this->_passwordChanged) { $this->data()->set(self::NEED_SESSION_REFRESH, true)->update(); $event = new Am_Event_SetPassword($this, $this->getPlaintextPass()); $this->getDi()->savedPassTable->setPass($event); $this->getDi()->hook->call($event); $this->sendChangepassEmail(); } if ($oldU->user_id) { if ($this->is_approved && !$oldU->is_approved) $this->approve(); $this->getDi()->hook->call(new Am_Event_UserAfterUpdate($this, $oldU)); } if ($this->status && $oldU->user_id) { $this->getDi()->hook->call(new Am_Event_SubscriptionUpdated($this, $oldU)); } $this->_passwordChanged = false; return $ret; } function approve() { foreach ($this->getDi()->invoiceTable->findByUserId($this->pk()) as $invoice) $invoice->approve(); if (!$this->is_approved) { $this->is_approved = 1; $this->save(); } $this->sendSignupEmailIfNecessary(); } protected function _prepareForSet(&$vars) { if (isset($vars['pass'])) unset($vars['pass']); return parent::_prepareForSet($vars); } /** * @param string submitted password * @return bool true if ok, false if not */ function checkPassword($pass) { if (!strlen($pass) || !isset($this->pass) || !strlen($this->pass)) { return false; } $ph = new PasswordHash(8, true); return $ph->CheckPassword($pass, $this->pass); } /** * Set new password * (important! - it does not save the password!) */ function setPass($pass, $quick = false) { $this->_plaintextPass = $pass; $this->_passwordChanged = true; $this->pass = self::cryptPass($pass, $quick); $this->pass_dattm = $this->getDi()->sqlDateTime; return $this; } static function cryptPass($pass, $quick = false) { $ph = new PasswordHash($quick ? 4 : 8, true); return $ph->HashPassword($pass); } /** It is only exists after call of @method setPass() */ function getPlaintextPass() { return $this->_plaintextPass; } function getSavedPass() { return $this->getDi()->savedPassTable->findByUserId($this->pk()); } /** * Load generated password in plain-text format * it is only available 6 hours after signup and * supposed to be displayed on thanks page * * @return string|null */ function getStoredPlaintextPassword() { $pg = $this->getDi()->store->get('pass-generated-' . $this->pk()); if (!$pg) return null; $c = new Am_Crypt_Aes128($this->getDi()->security->siteKey()); return $c->decrypt($pg); } function getLoginCookie() { if (!$this->remember_key) { $this->updateQuick('remember_key', sha1(rand())); } return sha1($this->user_id . $this->login . md5($this->pass) . $this->remember_key); } function generateLogin() { // usernames to try $try = array(); if (!empty($this->email) && preg_match("/^([a-zA-Z0-9_]+)\@/", $this->email, $regs)) $try[] = $regs[1]; $fn = strtolower(preg_replace('/[^\w\d_]/', '', @$this->name_f)); $ln = strtolower(preg_replace('/[^\w\d_]/', '', @$this->name_l)); if ($fn || $ln) { if ($fn && $ln) { $try[] = $fn . '_' . $ln; } else { $try[] = $fn . $ln; } $try[] = $try[count($try) - 1] . rand(100, 999); } $e = new Am_Event(Am_Event::GENERATE_LOGIN, array('user' => $this)); $e->setReturn($try); $this->getDi()->hook->call($e); $try = $e->getReturn(); foreach ($try as $login) { if (strlen($login) > $this->getDi()->config->get('login_max_length')) $login = substr($login, 0, $this->getDi()->config->get('login_max_length')); if ((strlen($login) >= $this->getDi()->config->get('login_min_length')) && $this->getDi()->userTable->checkUniqLogin($login) && !$this->getDi()->banTable->findBan(array('login' => $login))) { $this->login = $login; return $this; } } // will generate it // a bit of configuration $min_length = $this->getDi()->config->get('login_min_length') < 4 ? 4 : $this->getDi()->config->get('login_min_length'); $max_length = $this->getDi()->config->get('login_max_length') > 10 ? 10 : $this->getDi()->config->get('login_max_length'); /// let's go do { $pass = $this->getDi()->security->randomString(rand($min_length, $max_length), "qwertyuiopasdfghjklzxcvbnm"); } while (!$this->getDi()->userTable->checkUniqLogin($pass)); $this->login = $pass; return $this; } function generatePassword() { // a bit of configuration $min_length = max($this->getDi()->config->get('pass_min_length', 8), 8); $max_length = min($this->getDi()->config->get('pass_max_length', 12), 14); $all_g = "aeiyo"; $all_gn = $all_g . "1234567890"; $all_s = "bcdfghjkmnpqrstwxz"; /// let's go $pass = ""; $length = rand($min_length, $max_length); for ($i = 0; $i < $length; $i++) { if ($i % 2) if ($i < $min_length) $pass .= $all_g[rand(0, strlen($all_g) - 1)]; else $pass .= $all_gn[rand(0, strlen($all_gn) - 1)]; else $pass .= $all_s[rand(0, strlen($all_s) - 1)]; } $this->_passwordGenerated = true; $this->setPass($pass); return $this; } private function _trueIfActive($v) { return $v == self::STATUS_ACTIVE; } private function _trueIfExpired($v) { return $v == self::STATUS_EXPIRED; } function checkSubscriptions($updateCache = false) { if (!$this->user_id) throw new Am_Exception_InternalError("Could not do User->checkSubscriptions() : user_id is empty"); if ($updateCache) $this->getDi()->resourceAccessTable->updateCache($this->user_id); $newStatus = $this->getDi()->accessTable->getStatusByUserId($this->user_id); $active = array_keys(array_filter($newStatus, array($this, '_trueIfActive'))); $oldStatus = $this->getProductsStatus(); $saved = array_keys(array_filter($oldStatus, array($this, '_trueIfActive'))); $merged = array_unique(array_merge($active, $saved)); $added = array_diff($merged, $saved); $deleted = array_diff($merged, $active); if ($active) $newUserStatus = self::STATUS_ACTIVE; elseif (array_filter($newStatus, array($this, '_trueIfExpired'))) $newUserStatus = self::STATUS_EXPIRED; else $newUserStatus = self::STATUS_PENDING; $statusChanged = ($newUserStatus != @$this->status); if ($statusChanged) { $this->updateQuick('status', $newUserStatus); } if ($added || $deleted || array_diff_assoc($newStatus, $oldStatus) || array_diff_assoc($oldStatus, $newStatus)) { $this->data()->set(self::NEED_SESSION_REFRESH, true)->update(); $this->getDi()->userStatusTable->setByUserId($this->user_id, $newStatus); foreach ($added as $product_id) { $e = new Am_Event_SubscriptionAdded($this, $this->getDi()->productTable->load($product_id)); $this->getDi()->hook->call($e); } foreach ($deleted as $product_id) { $e = new Am_Event_SubscriptionDeleted($this, $this->getDi()->productTable->load($product_id)); $this->getDi()->hook->call($e); } $e = new Am_Event_SubscriptionChanged($this, $added, $deleted); $this->getDi()->hook->call($e); } if ($statusChanged) { $this->sendSignupEmailIfNecessary(); } } /** * This function is called upon completion of payment * If user signup e-mail was not set before, it will be sent from there * It checks if : * - email is enabled in config * - user has at least one completed payment * - the e-mail was not sent before * - customer was approved */ function sendSignupEmailIfNecessary(InvoicePayment $p = null) { if (!$this->getDi()->config->get('send_signup_mail')) return; if ($this->data()->get('signup_email_sent')) return; // was already sent if (!$this->isApproved()) return; // is not yet approved $this->sendSignupEmail($p); } function sendSignupEmail(InvoicePayment $p = null) { if ($et = Am_Mail_Template::load('send_signup_mail', $this->lang)) { $et->setUser($this); //%password% placeholder will be available only in case auto_create //mode in payment system (user and payment created during same request) $pass = $this->getPlaintextPass(); $et->setPassword($pass ? $pass : ___('what you entered when creating your account')); if (empty($p)) $p = $this->getDi()->invoicePaymentTable->findFirstByUserId($this->user_id); if ($p) $et->setPayment($p); $et->send($this); $this->data()->set('signup_email_sent', 1)->update(); } } function sendRegistrationToAdminEmail() { if ($et = Am_Mail_Template::load('registration_mail_admin')) { $et->setUser($this); $et->setPassword($this->getPlaintextPass()); $et->sendAdmin(); } } function sendRegistrationEmail() { if ($et = Am_Mail_Template::load('registration_mail', $this->lang)) { $et->setUser($this); $et->setPassword($this->getPlaintextPass()); $et->send($this); } } function sendChangepassEmail() { if ($this->getDi()->config->get('changepass_mail') && ($et = Am_Mail_Template::load('changepass_mail', $this->lang))) { $et->setUser($this); $et->setPassword($this->getPlaintextPass()); $et->send($this); } } function sendNotApprovedEmail() { if ($et = Am_Mail_Template::load('manually_approve', $this->lang)) { $et->setUser($this); $et->send($this); } if ($et = Am_Mail_Template::load('manually_approve_admin')) { $et->setUser($this); $et->send(Am_Mail_Template::TO_ADMIN); } } /** * @return bool true if user have any active subscriptions */ function isActive() { return $this->status == self::STATUS_ACTIVE; } /** * Return true if customer paid at least once * @return bool */ function isPaid() { return (bool) $this->getAdapter()->selectCell( "SELECT SUM(amount)>0 FROM ?_invoice_payment p WHERE user_id=?d" , $this->user_id); } /** * @return true if user is approved */ function isApproved() { return!empty($this->is_approved) && ($this->is_approved > 0); } function isLocked() { return!empty($this->is_locked) && ($this->is_locked > 0); } function lock($flag = true) { $this->is_locked = (int)$flag; $this->save(); } /** * @return array of Access objects */ function getAccessRecords() { return $this->getDi()->accessTable->findByUserId($this->user_id); } function getActiveProducts() { return $this->getDi()->productTable->selectObjects("SELECT p.* FROM ?_user_status us " . "LEFT JOIN ?_product p USING(product_id) WHERE user_id=?d " . "AND status=?d " . "AND p.product_id IS NOT NULL " . "ORDER BY sort_order", $this->user_id, self::STATUS_ACTIVE); } function getExpiredProducs() { return $this->getDi()->productTable->loadIds($this->getExpiredProductIds()); } function getFutureProducts() { return $this->getDi()->productTable->loadIds($this->getFutureProductIds()); } /** * Returns max expiration date * if product or array of products are specified, returns it * for given products only */ function getExpire($productIdOrIds = array()) { $productIdOrIds = (array) $productIdOrIds; $productIdOrIds = array_filter(array_map('intval', $productIdOrIds)); return $this->getDi()->db->selectCell("SELECT MAX(expire_date) FROM ?_access WHERE user_id=?d { AND product_id IN (?a) }", $this->pk(), $productIdOrIds ? $productIdOrIds : DBSIMPLE_SKIP ); } function getBegin($productIdOrIds = array()) { $productIdOrIds = (array) $productIdOrIds; $productIdOrIds = array_filter(array_map('intval', $productIdOrIds)); return $this->getDi()->db->selectCell("SELECT MIN(begin_date) FROM ?_access WHERE user_id=?d AND begin_date > ? { AND product_id IN (?a) }", $this->pk(), sqlDate('now'), $productIdOrIds ? $productIdOrIds : DBSIMPLE_SKIP ); } function getRebill($productIdOrIds = array()) { $productIdOrIds = (array) $productIdOrIds; $productIdOrIds = array_filter(array_map('intval', $productIdOrIds)); return $this->getDi()->db->selectCell("SELECT MIN(i.rebill_date) FROM ?_access a LEFT JOIN ?_invoice_item ii ON a.invoice_id = ii.invoice_id AND a.product_id = ii.item_id AND ii.item_type = 'product' LEFT JOIN ?_invoice i ON a.invoice_id = i.invoice_id WHERE a.user_id=?d AND i.rebill_date IS NOT NULL AND i.status = ? AND i.rebill_date > ? AND ii.second_total > 0 {AND a.product_id IN (?a)}", $this->pk(), Invoice::RECURRING_ACTIVE, sqlDate('now'), $productIdOrIds ? $productIdOrIds : DBSIMPLE_SKIP ); } function getActiveProductsExpiration() { $ret = array(); foreach ($this->getActiveProductIds() as $pid) { $ret[$pid] = $this->getExpire($pid); } return $ret; } function getActiveCategoriesExpiration() { $p_map = $this->getActiveProductsExpiration(); $cp_map = $this->getDi()->productCategoryTable->getCategoryProducts(); $out = array_combine(array_keys($cp_map), array_fill(0, count($cp_map), null)); foreach ($cp_map as $cip => $pids) { foreach ($pids as $pid) { if (isset($p_map[$pid])) { $out[$cip] = max($out[$cip], $p_map[$pid]); } } } return array_filter($out); } function getFutureProductsBeginning() { $ret = array(); foreach ($this->getFutureProductIds() as $pid) { $ret[$pid] = $this->getBegin($pid); } return $ret; } function getActiveProductsRebill() { $ret = array(); foreach ($this->getActiveProductIds() as $pid) { $ret[$pid] = $this->getRebill($pid); } return $ret; } /** @return array of int active product# */ function getActiveProductIds() { return $this->getAdapter()->selectCol("SELECT product_id FROM ?_user_status WHERE user_id=?d AND status=?d", $this->user_id, self::STATUS_ACTIVE); } /** @return array of int expired product# */ function getExpiredProductIds() { return $this->getAdapter()->selectCol("SELECT product_id FROM ?_user_status WHERE user_id=?d AND status=?d", $this->user_id, self::STATUS_EXPIRED); } /** @return array of int future product# */ function getFutureProductIds() { return $this->getAdapter()->selectCol("SELECT DISTINCT a.product_id FROM ?_access a LEFT JOIN ?_user_status us USING(user_id,product_id) WHERE a.user_id = ? AND a.begin_date>? AND (us.status IS NULL OR us.status<>?)", $this->user_id, sqlDate('now'), self::STATUS_ACTIVE); } /** * @return array product_id => status (@see self::STATUS_ACTIVE, ... constants) */ function getProductsStatus() { return $this->getDi()->userStatusTable->getByUserId($this->user_id); } /// -- implementing IMailReceiver interface */ public function getEmail() { return $this->email; } public function getName() { return trim(@$this->name_f . ' ' . @$this->name_l); } public function isUnsubscribed() { return (bool) $this->unsubscribed; } public function canUnsubscribe() { return true; } /** param array $groups - array of id# */ function setGroups(array $groups) { $this->getAdapter()->query("DELETE FROM ?_user_user_group WHERE user_id=?d {AND user_group_id NOT IN (?a)}", $this->user_id, $groups ? $groups : DBSIMPLE_SKIP); if ($groups) { $vals = array(); foreach ($groups as $id) $vals[] = sprintf("(%d,%d)", $this->user_id, $id); $this->getAdapter()->query("INSERT IGNORE INTO ?_user_user_group (user_id, user_group_id) VALUES " . implode(", ", $vals)); } $this->checkSubscriptions(true); return $this; } /** @return array of id# */ function getGroups() { if (empty($this->user_id)) return array(); return $this->getAdapter()->selectCol( "SELECT DISTINCT user_group_id FROM ?_user_user_group WHERE user_id=?d", $this->user_id); } } /** * @method findFirstByLogin($login) * @method findFirstByEmail($login) */ class UserTable extends Am_Table_WithData { protected $_key = 'user_id'; protected $_table = '?_user'; protected $_recordClass = 'User'; protected $sort_order = array(); protected $_customFieldsConfigKey = 'member_fields'; public function clearPending($date, $incl_aff = false) { $q = $this->_db->queryResultOnly("SELECT u.* FROM ?_user u LEFT JOIN ?_access a ON a.user_id = u.user_id LEFT JOIN ?_invoice_payment ip ON ip.user_id = u.user_id WHERE u.status = 0 {AND IFNULL(u.is_affiliate,0)=?} AND a.access_id IS NULL AND ip.invoice_payment_id is NULL AND u.added < ? GROUP BY u.user_id", ($incl_aff ? DBSIMPLE_SKIP : 0), sqlTime($date)); while ($r = $this->_db->fetchRow($q)) { $u = $this->createRecord($r); $u->delete(); } } public function clearExpired($date, $incl_aff = false) { // this function deletes only 500 records at time, to do not work over limits $q = $this->_db->queryResultOnly("SELECT u.* FROM ?_user u LEFT JOIN ?_access a ON a.user_id = u.user_id LEFT JOIN ?_invoice_payment ip ON ip.user_id = u.user_id WHERE u.status = 2 {AND IFNULL(u.is_affiliate,0)=?} GROUP BY u.user_id HAVING GREATEST( IFNULL(MAX(ip.dattm), '2000-01-01'), IFNULL(MAX(a.expire_date), '2000-01-01')) < ? LIMIT 500 ", ($incl_aff ? DBSIMPLE_SKIP : 0), sqlTime($date)); while ($r = $this->_db->fetchRow($q)) { $u = $this->createRecord($r); $u->delete(); } } function getLoginRegex() { $regexp = $this->getDi()->config->get('login_disallow_spaces') ? '/^[-0-9a-zA-Z_]+$/D' : '/^([-0-9a-zA-Z_][-0-9a-zA-Z_ ]+[-0-9a-zA-Z_]|[-0-9a-zA-Z_]+)$/D'; $event = new Am_Event(Am_Event::GET_LOGIN_REGEX, array( 'login_disallow_spaces' => $this->getDi()->config->get('login_disallow_spaces') )); $event->setReturn($regexp); $this->getDi()->hook->call($event); return $event->getReturn(); } function getStrongPasswordRegex() { $regexp = '/^(?=.*[0-9].*[0-9])(?=.*[-!@#$%^&*().,=+`~{}\?].*[-!@#$%^&*().,=+`~{}\?])(?=.*[A-Z].*[A-Z])/'; $event = new Am_Event(Am_Event::GET_STRONG_PASSWORD_REGEX); $event->setReturn($regexp); $this->getDi()->hook->call($event); return $event->getReturn(); } /** * Check for username iniqueness only * @param string $login * @return bool True if record unique (no such login exists), false if not-unique */ function checkUniqLogin($login, $user_id = null) { $u = $this->_db->selectCell("SELECT user_id FROM ?_user WHERE login=? { AND user_id <> ?d}", $login, $user_id ? $user_id : DBSIMPLE_SKIP); if ($u) return 0; $event = $this->getDi()->hook->call(new Am_Event_CheckUniqLogin(null, array('login' => $login, 'userId' => $user_id))); return $event->isUnique() ? -1 : false; } /** * Check for username iniqueness only * @param string $login * @return bool True if record unique (no such login exists), false if not-unique */ function checkUniqEmail($email, $user_id = null) { $u = $this->_db->selectCell("SELECT user_id FROM ?_user WHERE email=? { AND user_id <> ?d}", $email, $user_id ? $user_id : DBSIMPLE_SKIP); if ($u) return 0; $event = $this->getDi()->hook->call(new Am_Event_CheckUniqEmail(null, array('email' => $email, 'userId' => $user_id))); return $event->isUnique() ? -1 : false; } function checkAllSubscriptionsFindChanged($limit = null) { $db = $this->_db; // update resource_access_cache $this->getDi()->resourceAccessTable->updateCache(); $db->query("DELETE FROM ?_user_status WHERE user_id NOT IN (SELECT user_id FROM ?_user)"); $db->query("DELETE FROM ?_access WHERE user_id NOT IN (SELECT user_id FROM ?_user)"); $db->query("DROP TABLE IF EXISTS ?_user_status_temp"); $db->query("CREATE TEMPORARY TABLE ?_user_status_temp ( user_id int not null, product_id int not null, status tinyint not null, INDEX(user_id,product_id)) "); // create table with calculated records from "access" $db->query(" INSERT INTO ?_user_status_temp SELECT a.user_id,a.product_id, CASE WHEN SUM(IF(a.expire_date>=?, 1, 0)) THEN 1 WHEN SUM(IF(a.expire_date< ?, 1, 0)) THEN 2 ELSE 0 END as status FROM ?_access a WHERE a.begin_date<=? GROUP BY user_id,product_id ", $this->getDi()->sqlDate, $this->getDi()->sqlDate, $this->getDi()->sqlDate); // now select differences $ids0 = $db->selectCol(" SELECT DISTINCT ms.user_id FROM ?_user_status ms LEFT JOIN ?_user_status_temp mst ON ms.user_id =mst.user_id AND ms.product_id=mst.product_id AND ms.status =mst.status WHERE mst.user_id IS NULL GROUP BY ms.user_id,ms.product_id {LIMIT ?d}", is_null($limit) ? DBSIMPLE_SKIP : $limit); if (!is_null($limit)) $limit = $limit - count($ids0); // select if there is no such a record in user_status table $ids1 = $db->selectCol("SELECT DISTINCT mst.user_id FROM ?_user_status_temp mst LEFT JOIN ?_user_status ms ON ms.user_id =mst.user_id AND ms.product_id=mst.product_id AND ms.status =mst.status WHERE ms.user_id IS NULL GROUP BY mst.user_id,mst.product_id {LIMIT ?d}", is_null($limit) ? DBSIMPLE_SKIP : $limit); if (!is_null($limit)) $limit = $limit - count($ids1); // select if user record has different "status" value $ids2 = $db->selectCol("SELECT DISTINCT m.user_id, CASE WHEN SUM(IF(mst.status=1, 1, 0)) THEN 1 WHEN SUM(IF(mst.status=2, 1, 0)) THEN 2 ELSE 0 END AS calcStatus, m.status FROM ?_user m LEFT JOIN ?_user_status_temp mst USING (user_id) GROUP BY m.user_id HAVING IFNULL(calcStatus,0) <> IFNULL(m.status, 0) {LIMIT ?d}", is_null($limit) ? DBSIMPLE_SKIP : $limit); return array_unique(array_merge($ids0, $ids1, $ids2)); } /** * If this function changed, check also AdminRebuildController - it must be changed too */ function checkAllSubscriptions() { while ($changed = $this->checkAllSubscriptionsFindChanged(1000)) { foreach ($changed as $user_id) { $u = $this->load($user_id, false); if ($u) $u->checkSubscriptions(false); // checked in checkAllSubscriptionsFindChanged } } } /** * Find user record by email (if $login looks like an email) * or by username * @param string $login e-mail or username * @return User|null */ function getByLoginOrEmail($login) { if (!strlen($login)) return null; if (strpos($login, '@') !== false) return $this->findFirstByEmail($login); else return $this->findFirstByLogin($login); } /** * Find record by login, check password and return it if all OK * with login/password * sets $resultCode from Am_Auth_Result * @return User */ function getAuthenticatedRow($login, $pass, & $code = null) { if (empty($login) || empty($pass)) { $code = Am_Auth_Result::INVALID_INPUT; return; } $u = $this->getByLoginOrEmail($login); if (!$u) { $code = Am_Auth_Result::USER_NOT_FOUND; return; } if (!$u->checkPassword($pass)) { $code = Am_Auth_Result::WRONG_CREDENTIALS; return; } $code = Am_Auth_Result::SUCCESS; return $u; } function getAuthenticatedCookieRow($cLogin, $cPass, & $code = null) { if (empty($cLogin) || empty($cPass)) { $code = Am_Auth_Result::INVALID_INPUT; return null; } $u = $this->getByLoginOrEmail($cLogin); if (!$u) { $code = Am_Auth_Result::USER_NOT_FOUND; return; } if ($u->getLoginCookie() !== $cPass) { $code = Am_Auth_Result::WRONG_CREDENTIALS; return null; } $code = Am_Auth_Result::SUCCESS; return $u; } function selectLast($num, $dateThreshold = null) { return $this->selectObjects("SELECT m.*, ROUND(SUM((p.amount - IFNULL(p.refund_amount, 0))/p.base_currency_multi), 2) AS paid, COUNT(p.invoice_payment_id) AS payments_count, sf.title AS saved_form_title FROM ?_user m LEFT JOIN ?_invoice_payment p USING (user_id) LEFT JOIN ?_saved_form sf ON m.saved_form_id=sf.saved_form_id {WHERE added > ?} GROUP BY m.user_id ORDER BY m.user_id DESC LIMIT ?d", $dateThreshold ?: DBSIMPLE_SKIP, $num); } }PK\Nzdddefault/models/SavedReport.phpnu[getDi()->adminTable->findBy() as $admin) { $frequency = $admin->getPref(Admin::PREF_REPORTS_SEND_FREQUENCY); if ($frequency == $event->getId()) { $content = ''; foreach($this->findByAdminId($admin->pk()) as $report) { $r = Am_Report_Abstract::createById($report->report_id); $r->applyConfigForm(new Am_Mvc_Request(unserialize($report->request))); $result = $r->getReport(); $output = new Am_Report_Text($result); $content .= $report->title . "\n----------------------------\n"; $content .= $output->render() . "\n"; } if ($content) { $mail = $this->getDi()->mail; $mail->addTo($admin->email); $mail->setSubject($this->getDi()->config->get('site_title') . ': Reports'); $mail->setBodyText($content); $mail->send(); } } } } } PK\Rdefault/models/Page.phpnu[path ? $this->getDi()->url("page/" . urlencode($this->path), null, false) : $this->getDi()->url("content/p/id/" . $this->page_id."/",null,false); } public function render(Am_View $view, $user = null, $use_layout = true) { $html = $this->html; $t = new Am_SimpleTemplate(); if ($user) $t->assign('user', $user); $t->assignStdVars(); $e = new Am_Event(Am_Event::PAGE_BEFORE_RENDER, array( 'template' => $t, 'user' => $user, 'page' => $this, 'html' => $html )); $this->getDi()->hook->call($e); $html = $t->render($e->getHtml()); if ($use_layout && $this->use_layout) { $view->content = '
      ' . $html . '
      '; $view->title = $this->title; $view->meta_title = $this->meta_title ? $this->meta_title : $this->title; if ($this->meta_keywords) $view->headMeta()->setName('keywords', $this->meta_keywords); if ($this->meta_description) $view->headMeta()->setName('description', $this->meta_description); if ($this->meta_robots) $view->headMeta()->setName('robots', $this->meta_robots); return $view->render($this->tpl ? $this->tpl : 'layout.phtml'); } else return $html; } } class PageTable extends ResourceAbstractTable { protected $_key = 'page_id'; protected $_table = '?_page'; protected $_recordClass = 'Page'; public function getAccessType() { return ResourceAccess::PAGE; } public function getAccessTitle() { return ___('Pages'); } public function getPageId() { return 'pages'; } } PK\40default/models/Folder.phpnu[url; } public function getLinkTitle() { return $this->title ? $this->title : ___("Link"); } } class FolderTable extends ResourceAbstractTable { protected $_key = 'folder_id'; protected $_table = '?_folder'; protected $_recordClass = 'Folder'; public function getAccessType() { return ResourceAccess::FOLDER; } public function getAccessTitle() { return ___('Folders'); } public function getPageId() { return 'folders'; } } PK\f`Qdefault/models/Link.phpnu[url; } } class LinkTable extends ResourceAbstractTable { protected $_key = 'link_id'; protected $_table = '?_link'; protected $_recordClass = 'Link'; public function getAccessType() { return ResourceAccess::LINK; } public function getAccessTitle() { return ___('Links'); } public function getPageId() { return 'links'; } } PK\Vdefault/models/Ban.phpnu[ 'xx', 'email'=>'xx', * 'login' => 'xxx') * @return array() if ok, array of keys matched like array('ip','login') */ function findBan(array $params) { $db = $this->_db; $where = array(); foreach ($params as $k => $v) $where[] = sprintf("(`type` = %s AND %s LIKE `value` )", $db->escape($k), $db->escape($v)); if (!$where) return array(); $arr = $db->selectCol($sql = "SELECT DISTINCT `type` FROM ?_ban WHERE " . join(" OR ", $where)); return $arr; } /** * Function suitable to use as "callback2" function in the Am_Form * it returns null if all ok, and dies or returns error message if banned action found * @param array $params * @return type */ function checkBan(array $params) { $foundBan = $this->findBan($params); foreach ($foundBan as $key) { $this->getDi()->errorLogTable->log("Attempt to signup from denied [$key]: " . htmlentities($params[$key])); if ($this->getDi()->config->get("ban.{$key}_action")=="die") { header("HTTP/1.0 500 Internal Error"); header("Status: 500 Internal Error"); exit(); } else { return ___("This %s is blocked. Please contact site support to find out why", $key); } return; ___('email'); ___('login'); ___('ip'); } } } PK\͢I I default/models/AccessLog.phpnu[getDi()->sqlDateTime; return parent::insert($values, $returnInserted); } /** @access private */ function _resetOnce($flag) { $this->_logged = (bool)$flag; } function clearOld($date) { $this->_db->query("DELETE FROM ?_access_log WHERE `time` < ? ", $date . ' 00:00:00'); } function logOnce($user_id=null, $ip=null, $url=null, $referer=null) { if ($this->_logged) return; $this->log($user_id, $ip, $url, $referer); $this->_logged = true; } function log($user_id=null, $ip=null, $url=null, $referer=null) { $this->_db->query("INSERT INTO ?_access_log (time, user_id, remote_addr, url, referrer) VALUES (?, ?d, ?, ?, ?)" , $this->getDi()->sqlDateTime, get_first($user_id, $this->getDi()->auth->getUserId ()), get_first($ip, $_SERVER['REMOTE_ADDR']), get_first($url, $_SERVER['REQUEST_URI']), get_first($referer, @$_SERVER['HTTP_REFERER'])); } function isIpCountExceeded($user_id, $ip) { if (!$this->getDi()->config->get('max_ip_count')) return; $octets = 4 - $this->getDi()->config->get('max_ip_octets'); if ($octets < 1) $octets = 4; if ($octets == 4) { $ipCount = $this->_db->selectCell("SELECT COUNT(DISTINCT remote_addr) FROM ?_access_log WHERE user_id=?d AND time BETWEEN (? - INTERVAL ?d MINUTE) AND ? AND remote_addr <> ?", $user_id, $this->getDi()->sqlDateTime, $this->getDi()->config->get('max_ip_period', 10), $this->getDi()->sqlDateTime, $ip); } else { $ip_oct = implode(".", array_slice(explode(".", $ip), 0, $octets)); $ipCount = $this->_db->selectCell("SELECT COUNT(DISTINCT SUBSTRING_INDEX(remote_addr,'.',?d)) FROM ?_access_log WHERE user_id=?d AND time BETWEEN (? - INTERVAL ?d MINUTE) AND ? AND remote_addr NOT LIKE ?", $octets, $user_id, $this->getDi()->sqlDateTime, $this->getDi()->config->get('max_ip_period', 10), $this->getDi()->sqlDateTime, $ip_oct . '%'); } return $ipCount >= $this->getDi()->config->get('max_ip_count'); } } PK\޼8.ii!default/models/ResourceAccess.phpnu[id; } public function getClass() { return $this->fn; } public function getClassTitle() { switch ($this->fn) { case self::FN_FREE : return ___('Free'); case self::FN_FREE_WITHOUT_LOGIN : return ___('Free'); case self::FN_CATEGORY : return ___('Category'); case self::FN_PRODUCT : return ___('Product'); case self::FN_USER_GROUP : return ___('User Group'); default: return $this->fn; }; } public function getTitle() { if ($this->fn == self::FN_FREE) return ___('Free Access'); if ($this->fn == self::FN_FREE_WITHOUT_LOGIN) return ___('Free Access without log-in'); $pr = null; if ($this->id) { if ($this->fn == self::FN_PRODUCT) $pr = $this->getDi()->productTable->load($this->id, false); elseif ($this->fn == self::FN_CATEGORY) { if ($this->id == self::ANY_PRODUCT) return ___('Any product'); else $pr = $this->getDi()->productCategoryTable->load($this->id, false); } elseif ($this->fn == self::FN_USER_GROUP) { $pr = $this->getDi()->userGroupTable->load($this->id, false); } } if (!$pr) return sprintf('(%s #%d)', $this->getClass(), $this->getId()); return sprintf('(%d) %s', $pr->pk(), $pr->title); } public function getStart() { if ($this->start_payments) return "{$this->start_payments}p"; return strlen($this->start_days) ? "{$this->start_days}d" : null; } public function getStop($parse_forever = true) { if ($this->stop_days == -1 && $parse_forever) return "forever"; return strlen($this->stop_days) ? "{$this->stop_days}d" : null; } public function hasCustomStartStop() { return strlen($this->stop_day) || strlen($this->start_day); } public function isAnyProducts() { return empty($this->product_id) && @$this->product_category_id <= 0; } public function isFree() { return ($this->fn == self::FN_FREE) || ($this->fn == self::FN_FREE_WITHOUT_LOGIN); } } class ResourceAccessTable extends Am_Table { protected $_key = 'resource_access_id'; protected $_table = '?_resource_access'; protected $_recordClass = 'ResourceAccess'; protected $_types = array(); /** * @return Am_Query */ protected function _getBaseQuery($joinConditions = "") { if ($joinConditions) $joinConditions = "(" . $joinConditions . ") AND "; $q = new Am_Query($this, 'r'); $q->clearFields(); $q->addField('DISTINCT r.resource_id', 'resource_id'); $q->addField('resource_type', 'resource_type'); $q->addField("fn", 'fn'); $q->addField("id", 'fn_id'); $q->leftJoin("?_access_cache", "c", " $joinConditions (((c.fn = r.fn) AND (c.id = r.id)) OR (r.fn='product_category_id' AND r.id=-1)) AND ( (c.status='active' AND r.start_days IS NULL AND r.stop_days IS NULL AND r.start_payments = 0) OR (c.status='active' AND c.days BETWEEN IFNULL(r.start_days,0) AND IFNULL(r.stop_days, 90000) AND c.payments_count >= IFNULL(r.start_payments,0)) OR (c.days >= IFNULL(r.start_days,0) AND r.stop_days = -1 AND c.payments_count >= IFNULL(r.start_payments,0)) )"); // is available if free, or if user has equal subscription record in access_cache $q->addWhere("(r.fn IN ('free', 'free_without_login') OR c.user_id IS NOT NULL)"); $q->addOrderRaw("(SELECT ras.sort_order FROM ?_resource_access_sort ras WHERE ras.resource_id=r.resource_id AND ras.resource_type=r.resource_type LIMIT 1), r.resource_id, r.resource_type"); return $q; } /** * Return resources currently allowed for user * @param User $user * @param array|single type constant from ResourceAccess $types * @return array of records (as array) */ function selectAllowedResources(User $user, $types = null) { // select product_id/product_category_id, type, number of days $q = $this->_getBaseQuery("c.user_id=".intval($user->pk())); if ($types !== null) $q->addWhere("resource_type IN (?a)", is_array($types) ? $types : array($types)); return $this->_db->fetchRows($q->query()); } /** * Return allowed product emails as objects * @return array of ResourceAbstract * @see self::selectAllowedResources */ function getProductWelcomeEmails($product_ids) { $ret = array(); $groups = $this->getDi()->db->selectCol("SELECT product_category_id from ?_product_product_category where product_id IN (?a)",$product_ids); $groups[]= -1; $q = new Am_Query($this, 'r'); $q->clearFields(); $q->addField('DISTINCT r.resource_id', 'resource_id'); $q->leftJoin('?_email_template', 'et', '(r.resource_id = et.email_template_id)'); $q->addWhere("resource_type = ?", ResourceAccess::EMAILTEMPLATE); $q->addWhere("(r.fn = 'product_id' AND r.id IN (?a) ) OR (r.fn = 'product_category_id' AND r.id IN (?a) )",$product_ids,$groups); $q->addWhere('et.name=?',EmailTemplate::PRODUCTWELCOME); $q->groupBy('resource_id'); $res = $this->_db->fetchRows($q->query()); $ret = array(); foreach ($res as $r) $ret[] = $this->getDi()->emailTemplateTable->load($r['resource_id']); return $ret; } /** * Return allowed product emails as objects * @return array of ResourceAbstract * @see self::selectAllowedResources */ function getPaymentEmails($product_ids) { $ret = array(); $groups = $this->getDi()->db->selectCol("SELECT product_category_id from ?_product_product_category where product_id IN (?a)",$product_ids); $groups[]= -1; $q = new Am_Query($this, 'r'); $q->clearFields(); $q->addField('DISTINCT r.resource_id', 'resource_id'); $q->leftJoin('?_email_template', 'et', '(r.resource_id = et.email_template_id)'); $q->addWhere("resource_type = ?", ResourceAccess::EMAILTEMPLATE); $q->addWhere("(r.fn = 'product_id' AND r.id IN (?a) ) OR (r.fn = 'product_category_id' AND r.id IN (?a) )",$product_ids,$groups); $q->addWhere('et.name=?',EmailTemplate::PAYMENT); $q->groupBy('resource_id'); $res = $this->_db->fetchRows($q->query()); $ret = array(); foreach ($res as $r) $ret[] = $this->getDi()->emailTemplateTable->load($r['resource_id']); return $ret; } /** * Return allowed resources as objects * @return array of ResourceAbstract * @see self::selectAllowedResources */ function getAllowedResources(User $user, $types = null, $groupByType = true) { $ret = array(); $res = $this->selectAllowedResources($user, $types = $this->getResourceTypes($types)); $ids = array(); $order = array(); $i = 0; foreach ($res as $k => $r) { // $ids[$r['resource_type']][$r['resource_id']] = $k; $ids[$r['resource_type']][$r['resource_id']] = array('fn' => $r['fn'], 'id' => $r['fn_id']); $order[$r['resource_type'].'_'.$r['resource_id']] = $i++; } $ret = array(); foreach ($ids as $resource_type => & $container) { $table = $this->getDi()->getService(lcfirst(toCamelCase($resource_type)) . 'Table'); /* @var $table Am_Table */ foreach ($table->loadIds(array_keys($container)) as $rec) { $id = $rec->pk(); if (isset($container[$id])) { $k = $order[$resource_type.'_'.$id]; // get position in result $rec->fn_id = $container[$id]; // assign product_title to email template $ret[$k] = $rec; } else { throw new Am_Exception_InternalError("->loadIds returned id[$id] not specified in request " . implode(",", array_keys($container))); } } } $event = new Am_Event(Am_Event::GET_ALLOWED_RESOURCES, array( 'user' => $user, 'types' => $types )); $event->setReturn($ret); $this->getDi()->hook->call($event); $ret = $event->getReturn(); ksort($ret); return $ret; } /** * Expand types constant to list of resource types * * @param string|array|null|enum(ResourceAccess::USER_VISIBLE_TYPES, ResourceAccess::USER_VISIBLE_PAGES) $types * @return array|null * @see Am_Event::GET_RESOURCE_TYPES */ protected function getResourceTypes($types) { if (is_null($types) || is_array($types) || !in_array($types, array(ResourceAccess::USER_VISIBLE_TYPES, ResourceAccess::USER_VISIBLE_PAGES))) return $types; if (isset($this->_types[$types])) return $this->_types[$types]; $res = array(); if ($types === ResourceAccess::USER_VISIBLE_TYPES) $res = array( ResourceAccess::FOLDER, ResourceAccess::FILE, ResourceAccess::PAGE, ResourceAccess::LINK, ResourceAccess::VIDEO, ); elseif ($types === ResourceAccess::USER_VISIBLE_PAGES) $res = array( ResourceAccess::FOLDER, ResourceAccess::PAGE, ResourceAccess::LINK, ); $event = new Am_Event(Am_Event::GET_RESOURCE_TYPES, array( 'type' => $types )); $event->setReturn($res); $this->getDi()->hook->call($event); $res = $event->getReturn(); $this->_types[$types] = $res; return $res; } function userHasAccess(User $user, $id, $type) { $q = $this->_getBaseQuery("c.user_id=".intval($user->pk())); $q->addWhere("resource_type=?", $type); $q->addWhere("resource_id=?", $id); $ret = (bool)$q->selectPageRecords(0, 1); $e = new Am_Event(Am_Event::USER_HAS_ACCESS, array( 'resource_id' => $id, 'resource_type' => $type, 'user' => $user )); $e->setReturn($ret); $this->getDi()->hook->call($e); return $e->getReturn(); } /** * Return true if not logged-in visitor has access * to the resource */ function guestHasAccess($id, $type) { $ret = (bool)$this->_db->selectCell("SELECT resource_access_id FROM {$this->_table} WHERE resource_type=? AND resource_id=? AND fn=?", $type, floatval($id), ResourceAccess::FN_FREE_WITHOUT_LOGIN); $e = new Am_Event(Am_Event::GUEST_HAS_ACCESS, array( 'resource_id' => $id, 'resource_type' => $type )); $e->setReturn($ret); $this->getDi()->hook->call($e); return $e->getReturn(); } function updateCache($userId = null) { if ($userId === null) { $this->_db->query("ALTER TABLE ?_access_cache DISABLE KEYS"); $this->_db->query("TRUNCATE TABLE ?_access_cache"); } else $this->_db->query("DELETE FROM ?_access_cache {WHERE user_id=?d}", $userId ? $userId : DBSIMPLE_SKIP); $productCatsCache = $this->getDi()->productCategoryTable->getCategoryProducts(); $dat = $this->getDi()->sqlDate; $today = $this->getDi()->sqlDate; $q = $this->_db->queryResultOnly(" SELECT user_id, product_id, UNIX_TIMESTAMP(begin_date) AS begin_date, UNIX_TIMESTAMP(LEAST(?, expire_date)) AS expire_date ,begin_date AS sql_begin_date ,expire_date AS sql_expire_date FROM ?_access WHERE {user_id = ?d AND } begin_date <= ? ORDER BY user_id ", $this->getDi()->sqlDate, $userId ? $userId : DBSIMPLE_SKIP, $this->getDi()->sqlDate); $rows = array(); $insert = array(); $lastUserId = null; while ($r = $this->_db->fetchRow($q)) { if (($r['user_id'] != $lastUserId) && $rows) { $insert = array_merge($insert, $this->_updateCacheUser($rows, $productCatsCache, $dat, $today)); if (count($insert) > 100) { $this->_insertCache($insert); $insert = array(); } $rows = array(); } $rows[] = $r; $lastUserId = $r['user_id']; } $this->_db->freeResult($q); if ($rows) $insert = array_merge($insert, $this->_updateCacheUser($rows, $productCatsCache, $dat, $today)); if ($insert) $this->_insertCache($insert); $this->_db->query("INSERT INTO ?_access_cache (user_id, fn, id, days, begin_date, expire_date, payments_count, status) SELECT user_id, 'user_group_id', user_group_id, NULL, NULL, NULL, 0, 'active' FROM ?_user_user_group WHERE 1 {AND user_id=?}", $userId === null ? DBSIMPLE_SKIP : $userId); if ($userId === null) { $this->_db->query("ALTER TABLE ?_access_cache ENABLE KEYS"); } $this->_db->query("UPDATE ?_access_cache ac SET payments_count = (SELECT COUNT(invoice_payment_id) FROM ?_invoice_payment ip INNER JOIN ?_invoice_item ii USING (invoice_id) WHERE ip.user_id = ac.user_id AND ii.item_id=ac.id) WHERE {ac.user_id=?d AND } ac.fn = 'product_id' ", $userId === null ? DBSIMPLE_SKIP : $userId); } function _insertCache(array $insert) { // todo - direct query : disable _expandPlaceholdersCallback $prefix = $this->_db->getPrefix(); $this->_db->queryQuick("INSERT IGNORE INTO {$prefix}access_cache (user_id, fn, id, days, begin_date, expire_date, status) VALUES\n" . implode(",", $insert)); } function _updateCacheUser(array $rows, array $productCatsCache, $dat, $today) { $active = $insert = array(); $min = $max = array(); foreach ($rows as $r) { $pid = $r['product_id']; $dates[$pid][] = array($r['begin_date']+43200, 0); $dates[$pid][] = array($r['expire_date']+43200, 1); if (empty($min[$pid]) || ($min[$pid] > $r['sql_begin_date'])) $min[$pid] = $r['sql_begin_date']; if (empty($max[$pid]) || ($max[$pid] < $r['sql_expire_date'])) $max[$pid] = $r['sql_expire_date']; if (($r['sql_begin_date'] <= $today) && ($today <= $r['sql_expire_date'])) { $active[$r['product_id']] = "active"; } elseif (empty($active[$r['product_id']])) { $active[$r['product_id']] = "expired"; } } $len = array(); foreach ($dates as $pid => $d) { sort($dates[$pid]); $len[$pid] = $this->_calcKleeLen($dates[$pid]); $insert[] = sprintf("(%d,'product_id',%d,%d,'%s','%s','%s')", $r['user_id'], $pid, $len[$pid], $min[$pid], $max[$pid], $active[$pid] ); } foreach ($productCatsCache as $pc => $pids) { $catDates = array(); $catActive = 'expired'; $catMax = $catMin = array(); foreach ($pids as $pid) { if (!empty($dates[$pid])) { $catDates = array_merge($catDates, $dates[$pid]); if ($active[$pid] == 'active') $catActive = 'active'; $catMin[$pid] = $min[$pid]; $catMax[$pid] = $max[$pid]; } } if (!$catDates) continue; if (count($catMax) == 1) // if there's only one product found { $pid = key($catMax); $insert[] = sprintf("(%d,'product_category_id',%d,%d,'%s','%s','%s')", $r['user_id'], $pc, $len[$pid], $min[$pid], $max[$pid], $active[$pid]); } else { sort($catDates); $insert[] = sprintf("(%d,'product_category_id',%d,%d,'%s','%s','%s')", $r['user_id'], $pc, $this->_calcKleeLen($catDates), min($catMin), max($catMax), $catActive ); } } return $insert; } function _calcKleeLen($datesArray) { $len = 0; $c = 0; foreach ($datesArray as $i => $v) { if ($c && $i) // count only inside an interval { $len += $v[0] - $datesArray[$i-1][0]; } if ($v[1]) // if end --$c; // we have finished an interval else { if (!$c) // opens new interval $len += 86400; ++$c; // we have started a new interval } } return round($len/86400); } /** * select resource accessible for customers using * records (user_id, resource_id, resource_type, login, email) * @return Am_Query */ function getResourcesForMembers($types = null, $condition="1=1") { if ($types && !is_array($types)) $types = (array)$types; $qfree = new Am_Query($this, 'rfree'); $qfree->crossJoin('?_user', 'u') ->clearFields() ->addField('u.user_id') ->addField('rfree.resource_id') ->addField('rfree.resource_type') ->addField('u.login') ->addField('u.email') ->addField("rfree.fn", 'fn') ->addField("rfree.id", 'fn_id') ->groupBy('user_id, resource_id, resource_type', 'u') ->addWhere("rfree.fn IN ('free', 'free_without_login')") ->addWhere("( (rfree.start_days IS NULL AND rfree.stop_days IS NULL) OR (CEIL((UNIX_TIMESTAMP() - UNIX_TIMESTAMP(u.added))/86400) BETWEEN IFNULL(rfree.start_days,0) AND IFNULL(rfree.stop_days, 90000)) OR (CEIL((UNIX_TIMESTAMP() - UNIX_TIMESTAMP(u.added))/86400) >= IFNULL(rfree.start_days,0) AND rfree.stop_days = -1) )"); if ($types) $qfree->addWhere('rfree.resource_type IN (?a) AND ' . $condition, $types); $q = $this->_getBaseQuery(); $q->clearFields(); $q->clearOrder(); $q->addField('DISTINCT c.user_id') ->addField('r.resource_id') ->addField('r.resource_type') ->addField('u.login') ->addField('u.email') ->addField("r.fn", 'fn') ->addField("r.id", 'fn_id') ->leftJoin('?_user', 'u', 'u.user_id=c.user_id') ->addOrder('user_id') // yes we need that subquery in subquery to mask field names // to get access of fields of main query (!) ->addOrderRaw("(SELECT _sort_order FROM ( SELECT sort_order as _sort_order, resource_type as _resource_type, resource_id as _resource_id FROM ?_resource_access_sort ras) AS _ras WHERE _resource_id=resource_id AND _resource_type=resource_type LIMIT 1), resource_id, resource_type") ->groupBy('user_id, resource_id, resource_type', 'c') // we will use separate query for free records ->addWhere("r.fn NOT IN ('free', 'free_without_login')") ->addUnion($qfree); if ($types) $q->addWhere('r.resource_type IN (?a) AND ' . $condition, $types); return $q; } function getFnValues() { return array( ResourceAccess::FN_CATEGORY, ResourceAccess::FN_PRODUCT, ResourceAccess::FN_USER_GROUP, ResourceAccess::FN_FREE, ResourceAccess::FN_FREE_WITHOUT_LOGIN, ); } /** * Return available types of resources * @return array * key: type * value: ResourceAccessTable */ function getAccessTables() { if (empty($this->_accessTables)) { $di = $this->getDi(); foreach(array( $di->folderTable, $di->fileTable, $di->pageTable, $di->integrationTable, $di->emailTemplateTable, $di->linkTable, $di->videoTable, ) as $t) $this->registerAccessTable($t); $di->hook->call(Am_Event::INIT_ACCESS_TABLES, array('registry' => $this)); } return $this->_accessTables; } function registerAccessTable(ResourceAbstractTable $t) { $this->_accessTables[$t->getAccessType()] = $t; } function syncSortOrder() { $db = $this->getDi()->db; // foreach ($this->getAccessTables() as $k => $t) { // delete records that are not found in master table $db->query("DELETE FROM ?_resource_access_sort WHERE resource_type=? AND NOT EXISTS ( SELECT * FROM ?# t WHERE t.?#=resource_id LIMIT 1 ) ", $k, $t->getName(), $t->getKeyField()); // add records that present in master table $x = (int)$db->selectCell("SELECT MAX(sort_order) FROM ?_resource_access_sort"); if (!$x) $x = 3000; $key = $t->getKeyField(); $db->query("INSERT IGNORE INTO ?_resource_access_sort SELECT null, $key as resource_id, '$k' as resource_type, $key + $x as sort_order FROM ?# {WHERE name IN (?a) } ", $t->getName(), $t instanceof EmailTemplateTable ? array(EmailTemplate::AUTORESPONDER, EmailTemplate::EXPIRE) : DBSIMPLE_SKIP); } } function clearAccess($id, $type) { return $this->getDi()->resourceAccessTable->deleteBy( array('resource_type' => $type, 'resource_id' => $id) ); } /** * Add a resource access record * @param int $recordId * @param enum $recordType * @param int $itemId product# or category# or -1 * @param string $startString 1d or 3m or 0d - for zero autoresponder * @param string $stopString * @param bool $isProduct is a product or category * @return ResourceAccess */ public function addAccessListItem($recordId, $recordType, $itemId, $startString, $stopString, $fn) { $fa = $this->getDi()->resourceAccessRecord; $fa->resource_type = $recordType; $fa->resource_id = $recordId; $fa->fn = $fn; $fa->id = $itemId; $fa->start_days = null; $fa->start_payments = 0; $fa->stop_days = null; if (preg_match('/^(\d+)p$/', strtolower($startString), $regs)) { $fa->start_payments = $regs[1]; } elseif (preg_match('/^(-?\d+)(\w+)$/', strtolower($startString), $regs)) { $fa->start_days = $regs[1]; } if (preg_match('/^(-?\d+)(\w+)$/', strtolower($stopString), $regs)) { $fa->stop_days = $regs[1]; } $fa->insert(); return $fa; } public function setAccess($recordId, $recordType, $access) { $this->clearAccess($recordId, $recordType); foreach(array( 'free' => ResourceAccess::FN_FREE, 'free_without_login' => ResourceAccess::FN_FREE_WITHOUT_LOGIN, 'product_id' => ResourceAccess::FN_PRODUCT, 'product_category_id' => ResourceAccess::FN_CATEGORY, 'user_group_id' => ResourceAccess::FN_USER_GROUP) as $key => $rtype) { if(!empty($access[$key])) { foreach ($access[$key] as $id => $params) { if (!is_array($params)) $params = json_decode($params, true); $this->addAccessListItem($recordId, $recordType, $id, $params['start'], $params['stop'], $rtype); } } } } public function getAccessList($recordId, $recordType) { return $this->findBy(array( 'resource_type' => $recordType, 'resource_id' => $recordId)); } }PK\l46IIdefault/models/CouponBatch.phpnu[deleteFromRelatedTable('?_coupon'); parent::delete(); } function generateCoupons($count, $minLen, $maxLen) { $table = $this->getDi()->couponTable; for ($i=0; $i<$count; $i++){ $coupon = $this->getDi()->couponRecord; $coupon->code = $table->generateCouponCode($minLen, $maxLen); $coupon->batch_id = $this->pk(); $coupon->insert(); } } /** * Retrive array of product ids coupon can be applied for * * @return array|null null in case of there is not any restriction */ function getApplicableProductIds() { //return null in case this field is empty if (!$this->product_ids) return null; $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts(); $res = array_filter(explode(',',$this->product_ids)); foreach ($res as $k => $g) { if (preg_match('/CATEGORY-(\d*)/', $g, $match)) { unset($res[$k]); $catId = $match[1]; foreach ($catProducts[$catId] as $prId) { $res[] = $prId; } } } return $res; } function getOnlyApplicableProductIds() { $res = array_filter(explode(',',$this->product_ids)); $result = array(); foreach ($res as $k => $g) { if (!preg_match('/CATEGORY-(\d*)/', $g, $match)) { $result[] = $g; } } return $result; } function getOnlyApplicableCategoryIds() { $res = array_filter(explode(',',$this->product_ids)); $result = array(); foreach ($res as $k => $g) { if (preg_match('/CATEGORY-(\d*)/', $g, $match)) { $result[] = $match[1]; } } return $result; } function getRequireProduct() { return array_unique(array_filter($this->parseRequirementsGroup($this->require_product))); } function getPreventIfProduct() { return array_unique(array_filter($this->parseRequirementsGroup($this->prevent_if_product))); } /** * @param string $req * @return array */ protected function parseRequirementsGroup($req) { $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts(); $res = array_filter(explode(',',$req)); foreach ($res as $k => $g) { if (preg_match('/CATEGORY-(\w*)-(\d*)/', $g, $match)) { unset($res[$k]); $status = $match[1]; $catId = $match[2]; foreach ($catProducts[$catId] as $prId) { $res[] = sprintf('%s-%d', $status, $prId); } } } return $res; } } class CouponBatchTable extends Am_Table { protected $_key = 'batch_id'; protected $_table = '?_coupon_batch'; protected $_recordClass = 'CouponBatch'; function deleteByUserId($user_id){ if (!$user_id) throw new Am_Exception_InternalError("user_id is empty in " . __METHOD__); $list = $this->_db->selectCol("SELECT batch_id FROM ?_coupon_batch WHERE user_id=?d", $user_id); if ($list) $this->_db->query("DELETE FROM ?_coupon_batch, ?_coupon WHERE batch_id IN (?a)", $list); } function getOptions($onlyEnabled = true) { return array_map(array('Am_Html', 'escape'), $this->_db->selectCol("SELECT batch_id as ARRAY_KEY, CONCAT('#', batch_id, ' ', IF(comment<>'', comment, CONCAT(discount, IF(discount_type='percent', '%', '$'), IF(begin_date, CONCAT(' (', begin_date, ' - ', expire_date, ')'), '')))) FROM ?_coupon_batch {WHERE is_disabled = ?}", $onlyEnabled ? 0 : DBSIMPLE_SKIP)); } } PK\e Ydefault/models/UserNote.phpnu[selectObjects("SELECT n.*, u.name_f, u.name_l, u.login, u.email, a.login AS a_login, a.name_f AS a_name_f, a.name_l AS a_name_l FROM ?_user_note n LEFT JOIN ?_user u ON n.user_id = u.user_id LEFT JOIN ?_admin a ON n.admin_id = a.admin_id {WHERE n.dattm > ?} ORDER BY n.dattm DESC LIMIT ?d", $dateThreshold ?: DBSIMPLE_SKIP, $num); } }PK\Œ^'default/models/ResourceAbstractFile.phpnu[isLocal() ? (($upload = $this->getUpload()) ? $upload->name : basename($this->getFullPath())) : basename($this->path); } /** @return Am_Storage_File */ protected function getStorageFile() { if (!$this->_storageItem) $this->_storageItem = $this->getDi()->plugins_storage->getFile($this->path); return $this->_storageItem; } function isLocal() { return (bool)$this->getStorageFile()->getLocalPath(); } function getStorageId() { return $this->getStorageFile()->getStorageId(); } function getProtectedUrl($exptime, $force_download = true) { return $this->getStorageFile()->getUrl($exptime, $force_download); } function getFullPath() { return $this->getStorageFile()->getLocalPath(); } /** @return Upload|null */ function getUpload() { if ($this->_upload && $this->_upload->upload_id == $this->path) return $this->_upload; return ($this->path > 0) ? $this->_upload = $this->getDi()->uploadTable->load($this->path) : null; } function isExists() { return file_exists($this->getFullPath()); } function getMime() { return $this->mime ? $this->mime : 'application/octet-stream'; } function getSize() { return $this->isLocal() ? filesize($this->getFullPath()) : @$this->size; } function getName() { $upload = $this->getUpload(); return $upload ? $upload->getName() : $this->title; } }PK\.I4default/models/SavedPass.phpnu[getTable()->getPasswordFormats(); $callback = $formats[$this->format]; $salt = $this->salt ?: $this->pass; $arr = array($pass, & $salt, null); $hash = $callback ? call_user_func_array($callback, $arr) : SavedPassTable::crypt($pass, $this->format, $salt, null); return $pass && ($hash == $this->pass); } } class SavedPassTable extends Am_Table { const PASSWORD_PLAIN = 'plain'; const PASSWORD_MD5 = 'md5'; const PASSWORD_SHA1 = 'sha1'; const PASSWORD_CRYPT = 'crypt'; const PASSWORD_MD5_MD5_PASS_SALT = 'md5(md5(pass).salt)'; const PASSWORD_MD5_SALT_MD5_PASS = 'md5(salt.md5(pass))'; const PASSWORD_SHA1_SHA1_PASS_SALT = 'sha1(sha1(pass).salt)'; const PASSWORD_SHA256_SHA256_PASS_SALT = 'sha256(sha256(pass).salt)'; const PASSWORD_PHPASS = 'phpass'; const PASSWORD_PASSWORD_HASH = 'password_hash'; protected $_key = 'saved_pass_id'; protected $_table = '?_saved_pass'; protected $_recordClass = 'SavedPass'; /** @return SavedPass|null */ function findSaved(User $user, $format) { if ($format === SavedPassTable::PASSWORD_PHPASS) { $row = array( 'saved_pass_id' => 0, 'user_id' => $user->user_id, 'format' => $format, 'pass' => $user->pass, 'salt' => null, 'time' => null, ); } else { $row = $this->_db->selectRow( "SELECT * FROM ?_saved_pass WHERE user_id=?d AND format=?", $user->user_id, $format); } if ($row) return $this->createRecord()->fromRow($row); } function setPass(Am_Event_SetPassword $event) { $user = $event->getUser(); $pass = $event->getPassword(); $sql = array(); //// $obj = $this->getDi()->savedPassRecord; $obj->format = self::PASSWORD_PHPASS; $obj->pass = $user->pass; $obj->salt = null; $obj->toggleFrozen(true); $event->addSaved($obj); //// foreach ($this->getPasswordFormats() as $format => $callback) { $salt = null; $arr = array($pass, & $salt, $user); $password = $callback ? call_user_func_array($callback, $arr) : self::crypt($pass, $format, $salt, $user); $sql[] = $this->_db->expandPlaceholders( array("(?d, ?, ?, ?)", $user->user_id, $format, $password, $salt) ); $obj = $this->getDi()->savedPassRecord; $obj->format = $format; $obj->pass = $password; $obj->salt = $salt; $obj->toggleFrozen(true); $event->addSaved($obj); } if ($sql) $this->_db->query("INSERT INTO ?_saved_pass (user_id, format, pass, salt) VALUES " . implode(",", $sql) . " ON DUPLICATE KEY UPDATE pass=VALUES(pass), salt=VALUES(salt)"); } /** @return array of array(type, [optional]callback) */ function getPasswordFormats() { $types = array( self::PASSWORD_MD5_MD5_PASS_SALT => null, self::PASSWORD_CRYPT => null, self::PASSWORD_PASSWORD_HASH => null ); foreach ($this->getDi()->plugins_protect->loadEnabled()->getAllEnabled() as $pl) { $format = $pl->getPasswordFormat(); if ($format === null) continue; if ($format === self::PASSWORD_PHPASS) continue; if ($format === self::PASSWORD_PASSWORD_HASH) continue; $types[$format] = array($pl, 'cryptPassword'); } $e = new Am_Event(Am_Event::GET_PASSWORD_FORMATS); $e->setReturn($types); $this->getDi()->hook->call($e); return $e->getReturn(); } static function crypt($pass, $methodConst, & $salt = null, User $user = null) { switch ($methodConst) { case self::PASSWORD_PHPASS: $ph = new PasswordHash(8, true); // validation request if ($salt && $ph->CheckPassword($pass, $salt)) return $salt; // new password return $ph->HashPassword($pass); case self::PASSWORD_PASSWORD_HASH : if($salt && password_verify($pass, $salt)){ return $salt; } return password_hash($pass, PASSWORD_DEFAULT); case self::PASSWORD_PLAIN: return $pass; case self::PASSWORD_MD5: return md5($pass); case self::PASSWORD_SHA1: return sha1($pass); case self::PASSWORD_CRYPT: if (empty($salt)) { if (version_compare(PHP_VERSION, '5.5.0')>0) $salt = password_hash($pass, PASSWORD_BCRYPT); // avoid warning else $salt = crypt($pass); return $salt; } return crypt($pass, $salt); case self::PASSWORD_MD5_MD5_PASS_SALT: if (empty($salt)) $salt = Am_Di::getInstance()->security->randomString(3); return md5(md5($pass) . $salt); case self::PASSWORD_MD5_SALT_MD5_PASS: if (empty($salt)) $salt = Am_Di::getInstance()->security->randomString(3); return md5($salt . md5($pass)); case self::PASSWORD_SHA1_SHA1_PASS_SALT: if (empty($salt)) $salt = Am_Di::getInstance()->security->randomString(3); return sha1(sha1($pass) . $salt); case self::PASSWORD_SHA256_SHA256_PASS_SALT: if (empty($salt)) $salt = Am_Di::getInstance()->security->randomString(3); return hash('sha256', hash('sha256', $pass) . $salt); default: throw new Am_Exception_InternalError("Unknown crypt method passed: [" . htmlentities($methodConst) . "]"); } } }PK\Dt default/models/UserGroup.phpnu[_childNodes; } function createChildNode() { $c = new self; $c->parent_id = $this->pk(); if (!$c->parent_id) throw new Am_Exception_InternalError("Could not add child node to not-saved object in ".__METHOD__); $this->_childNodes[] = $c; return $c; } public function fromRow(array $vars) { if (isset($vars['childNodes'])) { foreach ($vars['childNodes'] as $row) { $r = new self($this->getTable()); $r->fromRow($row); $this->_childNodes[] = $r; } unset($vars['childNodes']); } return parent::fromRow($vars); } public function delete() { $ret = parent::delete(); $this->getTable()->getAdapter()->query("DELETE FROM ?_resource_access WHERE fn='user_group_id' AND id=?d", $this->pk()); return $ret; } } class UserGroupTable extends Am_Table { protected $_key = 'user_group_id'; protected $_table = '?_user_group'; protected $_recordClass = 'UserGroup'; /** * @return ProductCategory */ function getTree() { $ret = array(); foreach ($this->_db->select("SELECT user_group_id AS ARRAY_KEY, parent_id AS PARENT_KEY, pc.* FROM ?_user_group AS pc ORDER BY 0+sort_order") as $r) { $ret[] = $this->createRecord($r); } return $ret; } function getSelectOptions(array $options = array()) { $ret = array(); $sql = "SELECT user_group_id AS ARRAY_KEY, parent_id, title FROM ?_user_group ORDER BY parent_id, 0+sort_order"; $rows = $this->_db->select($sql); foreach ($rows as $id => $r){ $parent_id_used = array( $id ); $title = $r['title']; $parent_id = $r['parent_id']; while ($parent_id) { // protect against endless cycle if (in_array($parent_id, $parent_id_used)) break; if (empty($rows[$parent_id])) break; $parent = $rows[$parent_id]; $title = $parent['title'] . '/' . $title; $parent_id = $parent['parent_id']; } $ret [ $id ] = $title; } return $ret; } function getOptions() { return $this->getSelectOptions(); } function moveNodes($fromId, $toId) { $this->_db->query("UPDATE {$this->_table} SET parent_id=?d WHERE parent_id=?d", $toId, $fromId); } public function delete($key) { parent::delete($key); $this->_db->query("DELETE FROM ?_user_user_group WHERE user_group_id=?d", $key); } } PK\o<#default/models/CurrencyExchange.phpnu[_db->selectCell( "SELECT rate FROM ?_currency_exchange WHERE currency=? AND `date`<=? ORDER BY `date` DESC LIMIT 1", $currency, $date); if (empty($ret)) $ret = 1.00; return $ret; } } PK\>MuBBdefault/models/Upload.phpnu[name; } function setName($name){ $x=preg_split('/[\\\\\/]/', $name); $this->name = array_pop($x); return $this; } function getPrefix() { return $this->prefix; } /** Get full pathname to file */ function getPath(){ return $this->path; } function setPath($path){ $this->path = $path; return $this;} /** Return file size as received from upload */ function getSize(){ return $this->_size ? $this->_size : $this->_size = @filesize($this->getFullPath()); } function setSize($size){ $this->_size = $size; return $this;} function getSizeReadable(){ return Am_Storage_File::getSizeReadable($this->getSize()); } /** Return file mime type as submitted by user */ function getType(){ return $this->mime; } function setType($type){ $this->mime = $type; return $this;} /** Return filename without dir path */ function getFilename() { return basename($this->path); } /** For internal usage only */ function setFrom_FILES($record, $k = null) { $this->setName($k === null ? $record['name'] : $record['name'][$k]); $this->mime = self::getMimeType($this->getName()); $this->_tmp_name = $k === null ? $record['tmp_name'] : $record['tmp_name'][$k]; $this->_error = $k === null ? @$record['error'] : @$record['error'][$k]; $this->_size = filesize($this->_tmp_name); } protected function moveUploadedFile($source, $target) { return defined('AM_TEST') ? rename($source, $target) : move_uploaded_file($source, $target); } function moveUploaded($tempSeconds = null){ $this->delete = $tempSeconds > 0 ? $this->getDi()->time+$tempSeconds : null; if (!$this->isLoaded()) { //for re-upload do { $this->path = '.'.$this->prefix.'.'.uniqid(); $fullPath = $this->getFullPath(); } while (file_exists($fullPath)); } $fullPath = $this->getFullPath(); if (!$this->moveUploadedFile($this->_tmp_name, $fullPath)){ throw new Am_Exception_InternalError("Could not move uploaded file [$this->_tmp_name] to [$fullPath]"); } $this->save(); unset($this->_tmp_name); unset($this->_error); } function delete(){ $fullPath = $this->getFullPath(); if (file_exists($fullPath)) if (!unlink($fullPath)) throw new Am_Exception_InternalError("Could not delete [$fullPath], and corresponding database records also is not deleted"); parent::delete(); } function getStoreFolder() { return Am_Di::getInstance()->data_dir; } function getFullPath() { return $this->getTable()->getRoot() . DIRECTORY_SEPARATOR . @$this->path; } /** * Determine mime type by file extension * @return string, application/octet-stream if unknown */ static function getMimeType($filename){ $common_mime_types = array( "exe" => "application/octet-stream", "class" => "application/octet-stream", "so" => "application/octet-stream", "dll" => "application/octet-stream", "oda" => "application/oda", "hqx" => "application/mac-binhex40", "cpt" => "application/mac-compactpro", "doc" => "application/msword", "bin" => "application/octet-stream", "dms" => "application/octet-stream", "lha" => "application/octet-stream", "lzh" => "application/octet-stream", "pdf" => "application/pdf", "ai" => "application/postscript", "eps" => "application/postscript", "ps" => "application/postscript", "smi" => "application/smil", "smil" => "application/smil", "bcpio" => "application/x-bcpio", "wbxml" => "application/vnd.wap.wbxml", "wmlc" => "application/vnd.wap.wmlc", "wmlsc" => "application/vnd.wap.wmlscriptc", "ogx" => "application/ogg", "anx" => "application/annodex", "xspf" => "application/xspf+xml", "vcd" => "application/x-cdlink", "pgn" => "application/x-chess-pgn", "cpio" => "application/x-cpio", "csh" => "application/x-csh", "dcr" => "application/x-director", "dir" => "application/x-director", "dxr" => "application/x-director", "dvi" => "application/x-dvi", "spl" => "application/x-futuresplash", "gtar" => "application/x-gtar", "hdf" => "application/x-hdf", "skp" => "application/x-koan", "skd" => "application/x-koan", "js" => "application/x-javascript", "skt" => "application/x-koan", "skm" => "application/x-koan", "latex" => "application/x-latex", "nc" => "application/x-netcdf", "cdf" => "application/x-netcdf", "sh" => "application/x-sh", "shar" => "application/x-shar", "swf" => "application/x-shockwave-flash", "sit" => "application/x-stuffit", "sv4cpio" => "application/x-sv4cpio", "sv4crc" => "application/x-sv4crc", "tar" => "application/x-tar", "tcl" => "application/x-tcl", "tex" => "application/x-tex", "texinfo" => "application/x-texinfo", "texi" => "application/x-texinfo", "t" => "application/x-troff", "tr" => "application/x-troff", "roff" => "application/x-troff", "man" => "application/x-troff-man", "me" => "application/x-troff-me", "ms" => "application/x-troff-ms", "ustar" => "application/x-ustar", "src" => "application/x-wais-source", "xhtml" => "application/xhtml+xml", "xht" => "application/xhtml+xml", "zip" => "application/zip", "au" => "audio/basic", "snd" => "audio/basic", "mid" => "audio/midi", "midi" => "audio/midi", "kar" => "audio/midi", "mpga" => "audio/mpeg", "mp2" => "audio/mpeg", "mp3" => "audio/mpeg", "oga" => "audio/ogg", "ogg" => "audio/ogg", "spx" => "audio/ogg", "flac" => "audio/flac", "axa" => "audio/annodex", "aif" => "audio/x-aiff", "aiff" => "audio/x-aiff", "aifc" => "audio/x-aiff", "m3u" => "audio/x-mpegurl", "ram" => "audio/x-pn-realaudio", "rm" => "audio/x-pn-realaudio", "rpm" => "audio/x-pn-realaudio-plugin", "ra" => "audio/x-realaudio", "wav" => "audio/x-wav", "pdb" => "chemical/x-pdb", "xyz" => "chemical/x-xyz", "bmp" => "image/bmp", "gif" => "image/gif", "ief" => "image/ief", "jpeg" => "image/jpeg", "jpg" => "image/jpeg", "jpe" => "image/jpeg", "png" => "image/png", "tiff" => "image/tiff", "tif" => "image/tif", "djvu" => "image/vnd.djvu", "djv" => "image/vnd.djvu", "wbmp" => "image/vnd.wap.wbmp", "ras" => "image/x-cmu-raster", "pnm" => "image/x-portable-anymap", "pbm" => "image/x-portable-bitmap", "pgm" => "image/x-portable-graymap", "ppm" => "image/x-portable-pixmap", "rgb" => "image/x-rgb", "xbm" => "image/x-xbitmap", "xpm" => "image/x-xpixmap", "xwd" => "image/x-windowdump", "igs" => "model/iges", "iges" => "model/iges", "msh" => "model/mesh", "mesh" => "model/mesh", "silo" => "model/mesh", "wrl" => "model/vrml", "vrml" => "model/vrml", "mpeg" => "video/mpeg", "mpg" => "video/mpeg", "mpe" => "video/mpeg", "mp4" => "video/mp4", "qt" => "video/quicktime", "mov" => "video/quicktime", "mxu" => "video/vnd.mpegurl", "ogv" => "video/ogg", "axv" => "video/annodex", "webm" => "video/webm", "3gp" => "video/3gp", "avi" => "video/x-msvideo", "flv" => "video/x-flv", "f4v" => "video/x-f4v", "movie" => "video/x-sgi-movie", "css" => "text/css", "asc" => "text/plain", "txt" => "text/plain", "rtx" => "text/richtext", "rtf" => "text/rtf", "sgml" => "text/sgml", "sgm" => "text/sgml", "tsv" => "text/tab-seperated-values", "wml" => "text/vnd.wap.wml", "wmls" => "text/vnd.wap.wmlscript", "etx" => "text/x-setext", "xml" => "text/xml", "xsl" => "text/xml", "htm" => "text/html", "html" => "text/html", "shtml" => "text/html", "csv" => "text/csv" ); $ext = explode('.', $filename); $ext = strtolower(array_pop($ext)); if (array_key_exists($ext, $common_mime_types)) return $common_mime_types[$ext]; else return 'application/octet-stream'; } /** @return bool */ function isValid() { return file_exists($this->getFullPath()); } /** @return bool */ function isInsideStoreFolder() { $p = realpath($this->getFullPath()); $f = realpath($this->getTable()->getRoot()); return strlen($f) && (strpos($p, $f) === 0); } function insert($reload = true) { $this->uploaded = $this->getDi()->time; return parent::insert($reload); } } class UploadTable extends Am_Table_WithData { protected $_key = 'upload_id'; protected $_table = '?_upload'; protected $_recordClass = 'Upload'; const STORE_FIELD = 'field'; const STORE_SERIALIZE = 'serialize'; const STORE_IMPLODE = 'implode'; const STORE_DATA_BLOB_SERIALIZE = 'data-serialize'; protected $_usage = array(); protected $_root; public function init() { parent::init(); $this->_root = Am_Di::getInstance()->data_dir; $this->defineUsage('downloads', 'file', 'path', UploadTable::STORE_FIELD, "Protected File [%title%]", '/default/admin-content/p/files/index?_files_a=edit&_files_id=%file_id%'); $this->defineUsage('emailtemplate', 'email_template', 'attachments', UploadTable::STORE_IMPLODE, "Email Template [%name%, %lang%]", '/admin-setup/email'); $this->defineUsage('email-pending', 'email_template', 'attachments', UploadTable::STORE_IMPLODE, "Pending Notification Template [%email_template_id%]", '/admin-setup/email'); $this->defineUsage('email-messages', 'email_template', 'attachments', UploadTable::STORE_IMPLODE, "Autoresponder or Expiration E-Mail Template", '/default/admin-content/p/emails/index?_emails_a=edit&_emails_id=%email_template_id%'); $this->defineUsage('video', 'video', 'path', UploadTable::STORE_FIELD, "Protected Video [%title%]", '/default/admin-content/p/video/index?_video_a=edit&_video_id=%video_id%'); $this->defineUsage('email', 'email_sent', 'files', UploadTable::STORE_IMPLODE, "Sent email [%subject%, %desc_users%]", '/admin-email'); $this->defineUsage('user_note', 'helpdesk_note', 'attachments', UploadTable::STORE_IMPLODE, "User Note [%user_id%]", '/admin-user-note/index/user_id/%user_id%'); } function findByDelete($tm) { return $this->selectObjects("SELECT * FROM ?_upload WHERE `delete`>0 AND `delete`selectObjects( "SELECT * FROM ?_upload WHERE upload_id IN (?a) { AND prefix = ?}", $ids, $prefix === null ? DBSIMPLE_SKIP : $prefix); } function cleanUp() { $time = $this->getDi()->time; foreach ($this->findByDelete($time) as $upload) { try { if ($upload->isInsideStoreFolder()) $upload->delete(); } catch (Am_Exception_InternalError $e) { $this->getDi()->errorLogTable->logException($e); } } } /** * set store folder * @param string $dir */ function setRoot($dir) { $this->_root = $dir; return $this; } function getRoot() { return $this->_root; } /** * * @param string $prefix * @param string $table * @param string $field * @param string $store_type enum(self::STORE_FIELD, STORE_SERIALIZE, STORE_IMPLODE, STORE_DATA_BLOB_SERIALIZE) * @param string $msg usage description, %feld_name% placeholders expanded * @param string $link relative link to page where usage can be found, %feld_name% placeholders expanded */ public function defineUsage($prefix, $table, $field, $store_type, $msg, $link='') { $this->_usage[$prefix][] = array ( 'table' => $table, 'field' => $field, 'store_type' => $store_type, 'msg' => $msg, 'link' => $link ); } /** * * @param Upload $upload * @return array [(title, link)] */ public function findUsage(Upload $upload) { $res = array(); foreach ($this->_usage[$upload->prefix] as $u) { $res = array_merge($res, $this->_checkUsage($upload, $u)); } return $res; } protected function _checkUsage(Upload $upload, $usage) { $rows = array(); switch ($usage['store_type']) { case self::STORE_FIELD: $rows = $this->getDi()->db->query("SELECT * FROM ?_{$usage['table']} WHERE ?#=?", $usage['field'], $upload->pk()); break; case self::STORE_SERIALIZE: $len = strlen($upload->pk()); $rows = $this->getDi()->db->query("SELECT * FROM ?_{$usage['table']} WHERE (?# LIKE ? OR ?# LIKE ?)", $usage['field'], '%i:' . $upload->pk() . ';%', $usage['field'], '%s:' . $len . ':"' . $upload->pk() . '";%'); break; case self::STORE_IMPLODE: $rows = $this->getDi()->db->query("SELECT * FROM ?_{$usage['table']} WHERE ?#=? OR ?# LIKE ? OR ?# LIKE ? OR ?# LIKE ?", $usage['field'], $upload->pk(), $usage['field'], $upload->pk() . ',%', $usage['field'], '%,' . $upload->pk(), $usage['field'], '%,' . $upload->pk() . ',%'); break; case self::STORE_DATA_BLOB_SERIALIZE : $len = strlen($upload->pk()); $tbl = $usage['table'] . 'Table'; $keyField = $this->getDi()->{$tbl}->getKeyField(); $rows = $this->getDi()->db->query("SELECT t.* FROM ?_{$usage['table']} t LEFT JOIN ?_data d ON d.`table` = ? AND d.`id`=t.?# WHERE d.`key`=? AND (d.`blob` LIKE ? OR d.`blob` LIKE ?)", $usage['table'], $keyField, $usage['field'], '%i:' . $upload->pk() . ';%', '%s:' . $len . ':"' . $upload->pk() . '";%'); break; } if (empty($rows)) return array(); $result = array(); foreach ($rows as $row) { $result[] = array( 'title' => $this->_expandPlaceholders($usage['msg'], $row), 'link' => $this->_expandPlaceholders($usage['link'], $row) ); } return $result; } protected function _expandPlaceholders($str, $vars) { foreach ($vars as $k => $val) { $str = str_replace('%' . $k . '%', $val, $str); } return $str; } } PK\F"ppdefault/models/Admin.phpnu[name_f . ' ' . $this->name_l; } public function checkPassword($pass) { $ph = new PasswordHash(8, true); return $pass && $ph->CheckPassword($pass, $this->pass); } public function setPass($pass) { $ph = new PasswordHash(12, true); $this->pass = $ph->HashPassword($pass); } public function hasPermission($perm, $priv = null) { if ($this->isSuper()) return true; if (empty($this->perms)) return false; $perms = $this->getPermissions(); if (empty($perms[$perm])) return false; if ($priv === null) return true; if (is_array($perms[$perm]) && empty($perms[$perm][$priv])) return false; return true; } public function checkPermission($perm, $priv = null) { if (!$this->hasPermission($perm, $priv)) throw new Am_Exception_AccessDenied(___("You have no permissions to perform requested operation")); } public function isAllowed($role = null, $resource = null, $privilege = null) { return $this->hasPermission($resource, $privilege); } public function setPermissions($perms) { $this->perms = json_encode($perms); $this->_perms = null; } public function getPermissions() { return json_decode($this->get('perms'), true); } public function setPreferences(array $prefs) { $this->prefs = serialize($prefs); } public function getPreferences() { return unserialize($this->prefs); } public function getPref($prefId, $default = null) { $prefs = $this->getPreferences(); return (isset($prefs[$prefId]) ? $prefs[$prefId] : $default); } public function setPref($prefId, $value) { $prefs = $this->getPreferences(); $prefs[$prefId] = $value; $this->setPreferences($prefs); $this->save(); } public function isSuper() { return (bool) $this->super_user; } public function delete() { parent::delete(); $this->getDi()->hook->call(Am_Event::ADMIN_AFTER_DELETE, array('admin'=>$this)); } } class AdminTable extends Am_Table_WithData { protected $_key = 'admin_id'; protected $_table = '?_admin'; protected $_recordClass = 'Admin'; function getAuthenticatedRow($login, $pass, & $code) { if (empty($login) || empty($pass)) { $code = Am_Auth_Result::INVALID_INPUT; return; } $u = $this->findFirstByLogin($login); if (!$u) { $code = Am_Auth_Result::USER_NOT_FOUND; return; } if (!$u->checkPassword($pass)) { $code = Am_Auth_Result::WRONG_CREDENTIALS; return; } $code = Am_Auth_Result::SUCCESS; return $u; } } PK\\<\ default/models/FileDownload.phpnu[download_limit) return true; //no limits at all list($limit, $period) = explode(':', $file->download_limit); $cond = array( 'user_id' => $user->pk(), 'file_id' => $file->pk() ); if ($period != self::PERIOD_ALL) { $begin_date = $this->getDi()->dateTime; $begin_date->modify('-' . $period . ' seconds'); $begin_date = $begin_date->format('Y-m-d H:i:s'); $cond['dattm'] = '>' . $begin_date; } $count = $this->countBy($cond); return $limit > $count; } function logDownload(User $user, File $file, $ip = '') { $begin_date = $this->getDi()->dateTime; $begin_date->modify('-' . self::TOLERANCE . ' seconds'); $begin_date = $begin_date->format('Y-m-d H:i:s'); $count = $this->countBy(array( 'user_id' => $user->pk(), 'file_id' => $file->pk(), 'dattm' => '>' . $begin_date )); if (!$count) { $this->insert(array( 'user_id' => $user->pk(), 'file_id' => $file->pk(), 'dattm' => $this->getDi()->sqlDateTime, 'remote_addr' => $ip )); } } function selectLast($num, $dateThreshold = null) { return $this->selectObjects("SELECT t.dattm, f.title, f.file_id, t.user_id, u.login, u.email, CONCAT(u.name_f, ' ', u.name_l) AS name, u.name_f, u.name_l FROM ?_file_download t LEFT JOIN ?_user u ON t.user_id = u.user_id LEFT JOIN ?_file f ON t.file_id = f.file_id {WHERE t.dattm > ?} ORDER BY t.dattm DESC LIMIT ?d", $dateThreshold ?: DBSIMPLE_SKIP, $num); } }PK\default/models/Integration.phpnu[getDi()->resourceAccessTable ->getAllowedResources($user, ResourceAccess::INTEGRATION) as $r) if ($r->plugin == $pluginId) $ret[] = $r; return $ret; } } PK\  "default/models/ProductCategory.phpnu[_childNodes; } function createChildNode() { $c = new self($this->getTable()); $c->parent_id = $this->pk(); if (!$c->parent_id) throw new Am_Exception_InternalError("Could not add child node to not-saved object in ".__METHOD__); $this->_childNodes[] = $c; return $c; } public function fromRow(array $vars) { if (isset($vars['childNodes'])) { foreach ($vars['childNodes'] as $row) { $r = new self($this->getTable()); $r->fromRow($row); $this->_childNodes[] = $r; } unset($vars['childNodes']); } return parent::fromRow($vars); } } class ProductCategoryTable extends Am_Table { protected $_key = 'product_category_id'; protected $_table = '?_product_category'; protected $_recordClass = 'ProductCategory'; const COUNT = 'count'; const ROOT = 'root'; /** * Do not include categories that do not have products. */ const EXCLUDE_EMPTY = 'exclude_empty'; /** * Do not include hidden categories. */ const EXCLUDE_HIDDEN = 'exclude_hidden'; /** * array of ctegory codes to include to list */ const INCLUDE_HIDDEN = 'include_hidden'; const ADMIN = 1; const USER = 2; protected $categoryProductsCache = null; /** * @todo protect against endless cycle (child[parent_id] <-> parent[parent_id]) * @return ProductCategory */ function getTree($cast_objects = true) { $ret = array(); foreach ($this->_db->select("SELECT product_category_id AS ARRAY_KEY, parent_id AS PARENT_KEY, pc.* FROM ?_product_category AS pc ORDER BY 0+sort_order") as $r) { $ret[] = $cast_objects ? $this->createRecord($r) : $r; } return $ret; } function getUserSelectOptions($options = array()) { return $this->getSelectOptions(self::USER, $options); } function getAdminSelectOptions($options = array()) { return $this->getSelectOptions(self::ADMIN, $options); } function getSelectOptions($type, array $options) { $ret = array(); $do_count = !empty($options[self::COUNT]); $exclude_empty = !empty($options[self::EXCLUDE_EMPTY]); $exclude_hidden = !empty($options[self::EXCLUDE_HIDDEN]); $include_hidden = isset($options[self::INCLUDE_HIDDEN]) ? $options[self::INCLUDE_HIDDEN] : array(); $root = (isset($options[self::ROOT]) && $options[self::ROOT]) ? $options[self::ROOT] : false; $exclude_disabled = $type == self::USER ? true : false; if ($do_count || $exclude_empty) $sql = "SELECT pc.product_category_id AS ARRAY_KEY, pc.parent_id AS PARENT_KEY, pc.product_category_id, pc.title, pc.code, COUNT(DISTINCT p.product_id) as `count` FROM ?_product_category pc LEFT JOIN ?_product_product_category ppc USING (product_category_id) LEFT JOIN ?_product p ON p.product_id = ppc.product_id AND p.is_archived=0 ".($exclude_disabled ? " AND p.is_disabled=0 " : "")." GROUP BY pc.product_category_id ORDER BY parent_id, 0+pc.sort_order"; else $sql = "SELECT product_category_id AS ARRAY_KEY, parent_id AS PARENT_KEY, product_category_id, title, code FROM ?_product_category ORDER BY parent_id, 0+sort_order"; $rows = $this->_db->select($sql); if ($root) { $rows = $this->extractSubtree($rows, $root); } foreach ($rows as $id => $r){ $this->renderNode($r, $id, $type, $options, '', $ret); } return $ret; } function getOptions() { return $this->getAdminSelectOptions(); } function getSubCategoryIds($cat_id) { $res = array(); $childNodes = $this->extractSubtree($this->getTree(false), $cat_id); while($node = array_shift($childNodes)) { array_push($res, $node['product_category_id']); foreach ($node['childNodes'] as $n) { array_push($childNodes, $n); } } return $res; } protected function extractSubtree($rows, $root) { $childNodes = $rows; while($node = array_shift($childNodes)) { if ($node['product_category_id'] == $root) return $node['childNodes']; foreach ($node['childNodes'] as $n) { array_push($childNodes, $n); } } return array(); } protected function renderNode($r, $id, $type, array $options, $title, &$ret) { $do_count = !empty($options[self::COUNT]); $exclude_empty = !empty($options[self::EXCLUDE_EMPTY]); $exclude_hidden = !empty($options[self::EXCLUDE_HIDDEN]); $include_hidden = isset($options[self::INCLUDE_HIDDEN]) ? $options[self::INCLUDE_HIDDEN] : array(); $exclude_disabled = self::USER ? true : false; $title .= ($title ? '/' : '') . $r['title']; $ctitle = $title; if($exclude_empty && !$r['count']) { foreach($r['childNodes'] as $cid => $c) $this->renderNode($c, $cid, $type, $options, $ctitle, $ret); return; } if($exclude_hidden && !(empty($r['code']) || in_array($r['code'], $include_hidden))) //assume to do not show child if parent is hidden return; if ($do_count) $title .= sprintf(' (%d)', $r['count']); $ret [ (($type == self::ADMIN) || !$r['code'] ? $id : $r['code']) ] = $title; foreach($r['childNodes'] as $cid => $c) $this->renderNode($c, $cid, $type, $options, $ctitle, $ret); } /** * Try to find by code and by id * if found by id, checks that code is empty */ function findByCodeThenId($codeOrId) { $r = $this->selectObjects("SELECT * FROM ?_product_category WHERE code=? OR (IFNULL(code,'')='' AND product_category_id=?) ORDER BY code=? DESC LIMIT 1", $codeOrId, $codeOrId, $codeOrId); if (!$r) return; $record = $r[0]; if ($record->code && ($record->code != $codeOrId)) throw new Am_Exception_InputError("Category #$record->product_category_id could not be accessed by id#"); return $record; } function moveNodes($fromId, $toId) { $this->_db->query("UPDATE {$this->_table} SET parent_id=?d WHERE parent_id=?d", $toId, $fromId); } public function delete($key) { parent::delete($key); $this->_db->query("DELETE FROM ?_product_product_category WHERE product_category_id=?d", $key); } /** * @return array { category_id => [product_id1, product_id2, ...] } */ public function getCategoryProducts($useCache = true) { if (!$useCache || ($this->categoryProductsCache === null)) { $this->categoryProductsCache = $this->_db->selectCol(" SELECT pc.product_category_id as ARRAY_KEY, GROUP_CONCAT(ppc.product_id) FROM ?_product_category AS pc LEFT JOIN ?_product_product_category AS ppc USING (product_category_id) GROUP BY pc.product_category_id"); foreach ($this->categoryProductsCache as & $prList) $prList = array_filter(explode(',', $prList)); } return $this->categoryProductsCache; } } PK\37jjdefault/models/BillingPlan.phpnu[currency)) $this->currency = Am_Currency::getDefault(); } /** @return Product */ public function getProduct() { if ($this->_product && $this->_product->product_id == $this->product_id) return $this->_product; $this->_product = $this->getDi()->productTable->load($this->product_id, true); $this->_product->setBillingPlan($this); return $this->_product; } public function _setProduct(Product $p) { $this->_product = $p; } /** @return string saved or caclulated billing terms */ public function getTerms() { return $this->terms ? $this->terms : $this->getTermsText(); } /** @return string caclulated billing terms */ public function getTermsText() { $tt = new Am_TermsText($this); return $tt->getString(); } public function getCurrency($value = null) { $c = new Am_Currency($this->currency); if ($value) $c->setValue($value); return $c; } public function isFree() { return !$this->first_price && !$this->second_price; } public function delete() { parent::delete(); $this->_table->getAdapter()->query("DELETE FROM ?_product_upgrade WHERE to_billing_plan_id=?d OR from_billing_plan_id=?d", $this->plan_id, $this->plan_id); } } /** * @package Am_Invoice */ class BillingPlanTable extends Am_Table_WithData { protected $_key = 'plan_id'; protected $_table = '?_billing_plan'; protected $_recordClass = 'BillingPlan'; protected $productCache = array(); protected $useProductCache = true; // disable in admin cp function toggleProductCache($flag) { $this->useProductCache = (bool)$flag; } function getForProduct($product_id, $limit = null, $onlyEnabled = false) { if ($this->useProductCache) { $key = "$product_id-$limit-$onlyEnabled"; if (array_key_exists($key, $this->productCache)) return $this->productCache[$key]; } $ret = $this->selectObjects( "SELECT * FROM ?_billing_plan WHERE product_id=?d {AND (disabled IS NULL OR disabled = ?d )} ORDER BY sort_order, plan_id {LIMIT ?d}", $product_id, !$onlyEnabled ? DBSIMPLE_SKIP : 0, $limit === null ? DBSIMPLE_SKIP : $limit ); if ($this->useProductCache) $this->productCache[$key] = $ret; return $ret; } /** * Select All billing plans respecting sort preferencies from aMember CP -> Manage products */ function selectAllSorted() { return $this->selectObjects("SELECT bp.*, p.title as product_title FROM $this->_table bp INNER JOIN ?_product p USING (product_id) WHERE p.is_archived=0 ORDER BY 0+p.sort_order,p.title"); } /** * return array of product_id-billing_plan_id => Product Title (billing plan terms) */ public function getProductPlanOptions() { $ret = array(); foreach ($this->selectAllSorted() as $p) { $ret[ $p->product_id . '-' . $p->plan_id ] = $p->product_title . ' (' . $p->getTerms() . ')'; } return $ret; } }PK\ں&default/models/EmailTemplateLayout.phpnu[getAdapter()->query('UPDATE ?_email_template SET email_template_layout_id = NULL WHERE email_template_layout_id=?', $this->pk()); return parent::delete(); } } class EmailTemplateLayoutTable extends Am_Table { protected $_key = 'email_template_layout_id'; protected $_table = '?_email_template_layout'; protected $_recordClass = 'EmailTemplateLayout'; function getOptions() { return $this->_db->selectCol("SELECT email_template_layout_id as ARRAY_KEY, name FROM ?_email_template_layout ORDER BY name"); } }PK\9!default/models/InvoicePayment.phpnu[getInvoice()->first_total == 0) return false; // if there is free trial return ! $this->getAdapter()->selectCell(" SELECT COUNT(*) FROM ?_invoice_payment WHERE invoice_id=?d AND invoice_payment_id <> ?d AND dattm <= ? AND invoice_payment_id < ?d", $this->invoice_id, $this->invoice_payment_id, $this->dattm, $this->invoice_payment_id); } public function setFromTransaction(Invoice $invoice, Am_Paysystem_Transaction_Interface $transaction) { $this->dattm = $transaction->getTime()->format('Y-m-d H:i:s'); $this->invoice_id = $invoice->invoice_id; $this->invoice_public_id = $invoice->public_id; $this->user_id = $invoice->user_id; $this->currency = $invoice->currency; $this->paysys_id = $transaction->getPaysysId(); $this->receipt_id = $transaction->getReceiptId(); $this->transaction_id = $transaction->getUniqId(); /// get from invoice $isFirst = ! ((doubleval($invoice->first_total) === 0.0) || $invoice->getPaymentsCount()); $amount = $transaction->getAmount(); if ($amount<=0) $amount = $isFirst ? $invoice->first_total : $invoice->second_total; $this->amount = (double)$amount; $this->discount = $isFirst ? $invoice->first_discount : $invoice->second_discount; $this->tax = $isFirst ? $invoice->first_tax : $invoice->second_tax; $this->shipping = $isFirst ? $invoice->first_shipping : $invoice->second_shipping; return $this; } public function fromRow(array $vars) { if (!empty($vars['refund_dattm']) && $vars['refund_dattm'] == '0000-00-00 00:00:00') $vars['refund_dattm'] = null; return parent::fromRow($vars); } public function isRefunded(){ return !is_null($this->refund_dattm); } public function isFullRefunded() { return $this->amount <= $this->refund_amount; } public function refund(InvoiceRefund $r){ $this->updateQuick(array( 'refund_dattm' => $this->refund_dattm ?: $r->dattm, 'refund_amount' => $this->refund_amount + $r->amount )); } public function insert($reload = true) { if ($this->currency == Am_Currency::getDefault()) $this->base_currency_multi = 1.0; else $this->base_currency_multi = $this->getDi()->currencyExchangeTable->getRate($this->currency, sqlDate($this->dattm)); $this->getDi()->hook->call(new Am_Event(Am_Event::PAYMENT_BEFORE_INSERT, array('payment' => $this, 'invoice' => $this->getInvoice(), 'user' => $this->getInvoice()->getUser()))); parent::insert($reload); $this->setDisplayInvoiceId(); $this->getDi()->hook->call(new Am_Event_PaymentAfterInsert(null, array('payment' => $this, 'invoice' => $this->getInvoice(), 'user' => $this->getInvoice()->getUser()))); return $this; } /** * @return InvoiceRefund|null */ public function getRefund(){ if (!$this->isRefunded()) return null; if (empty($this->_refund)) $this->_refund = $this->getDi()->invoiceRefundTable->findFirstBy(array( 'invoice_payment_id' => $this->pk())); return $this->_refund; } /** * @return User */ public function getUser(){ if (empty($this->_user)) $this->_user = $this->getDi()->userTable->load($this->user_id); return $this->_user; } /** * @return Invoice */ public function getInvoice(){ if (empty($this->_invoice)) $this->_invoice = $this->getDi()->invoiceTable->load($this->invoice_id); return $this->_invoice; } public function _setInvoice(Invoice $invoice) { $this->_invoice = $invoice; return $this; } /** * @return Am_Currency */ function getCurrency($value = null) { $c = new Am_Currency($this->currency); if ($value) $c->setValue($value); return $c; } /** * * Set Invoice ID wich will be displayed in pdf invoice */ protected function setDisplayInvoiceId() { $e = new Am_Event(Am_Event::SET_DISPLAY_INVOICE_PAYMENT_ID,array('record'=>$this)); $e->setReturn($this->getInvoice()->public_id . '/' . $this->getInvoice()->getPaymentsCount()); $this->getDi()->hook->call($e); $this->display_invoice_id = $e->getReturn(); $this->updateSelectedFields('display_invoice_id'); } function getDisplayInvoiceId() { return $this->display_invoice_id ? $this->display_invoice_id : ($this->getInvoice()->public_id . '/' . $this->receipt_id); } } /** * @package Am_Invoice */ class InvoicePaymentTable extends Am_Table_WithData { protected $_key = 'invoice_payment_id'; protected $_table = '?_invoice_payment'; protected $_recordClass = 'InvoicePayment'; function getPaymentsCount($invoiceId){ ///// NEED REAL ATTENTON HERE: Added to handle imported payments correctly. ///// Import3 script create payments with zero amount, and these payments are counted as real payments ///// so updateRebillDate does not work if imported invoice have free trial period. return $this->_db->selectCell("SELECT COUNT(*) FROM ?_invoice_payment WHERE invoice_id=?d and amount>0", $invoiceId); } /** @return string */ function getLastReceiptId($invoiceId) { return $this->_db->selectCell("SELECT receipt_id FROM ?_invoice_payment WHERE invoice_id=?d ORDER BY dattm DESC LIMIT 1", $invoiceId); } public function insert(array $values, $returnInserted = false) { if (empty($values['dattm'])) $values['dattm'] = $this->getDi()->sqlDateTime; return parent::insert($values, $returnInserted); } function selectLast($num, $dateThreshold = null) { return $this->selectObjects("SELECT ip.*, refund_amount, refund_dattm, i.coupon_code, (SELECT GROUP_CONCAT(item_title SEPARATOR ', ') FROM ?_invoice_item WHERE invoice_id=ip.invoice_id) AS items, u.login, u.email, CONCAT(u.name_f, ' ', u.name_l) AS name, u.name_f, u.name_l, u.added, ip.invoice_public_id AS public_id FROM ?_invoice_payment ip LEFT JOIN ?_user u USING (user_id) LEFT JOIN ?_invoice i ON ip.invoice_id = i.invoice_id {WHERE ip.dattm > ?} ORDER BY ip.dattm DESC LIMIT ?d", $dateThreshold ?: DBSIMPLE_SKIP, $num); } } PK\-99default/models/Country.phpnu[status = self::STATUS_ADDED; parent::insert($reload); } function update() { $this->status = get_first($this->status, self::STATUS_CHANGED); parent::update(); } } class CountryTable extends Am_Table { protected $_key = 'country_id'; protected $_table = '?_country'; protected $_recordClass = 'Country'; function sortByTagAndTitle($a, $b) { if($a['tag'] != $b['tag']) return ($a['tag'] > $b['tag'] ? -1 : 1); return strcmp($a['title'], $b['title']); } function getTitleByCode($code) { return $this->_db->selectCell("SELECT title FROM ?_country WHERE country=?", $code); } function getOptions($addEmpty = false) { //if admin show all countries, if user show only active countries $where = defined('AM_ADMIN') ? '' : 'WHERE tag>=0'; $res = $this->_db->select("SELECT country as ARRAY_KEY, CASE WHEN tag<0 THEN CONCAT(title, ' (disabled)') ELSE title END AS title , tag FROM ?_country $where ORDER BY tag DESC, title"); if (strpos($this->getDi()->app->getDefaultLocale(), 'en')!==0) { $tr = $this->getDi()->locale->getTerritoryNames(); foreach ($res as $k => $v) if (array_key_exists($k, $tr)) $res[$k]['title'] = $tr[$k]; } uasort($res, array($this, 'sortByTagAndTitle')); $res = array_map(function($l) {return $l["title"];}, $res); if ($res && $addEmpty) { $res = array_merge(array('' => ___('[Select country]')), $res); } return $res; } }PK\mdefault/models/Charge.phpnu[amount = $amount; $this->currency = $currency; $this->title = $title; $this->desc = $desc; $this->tax_group = $tax_group; } function getProductId() { return null; } function getType() { return 'charge'; } function getTitle() { return $this->title; } function getDescription() { return $this->desc; } function getFirstPrice() { return $this->amount; } function getFirstPeriod() { return Am_Period::MAX_SQL_DATE; } function getRebillTimes() { return 0; } function getSecondPrice() { return null; } function getSecondPeriod() { return null; } function getCurrencyCode() { return $this->currency; } function getTaxGroup() { return $this->tax_group; } function getIsTangible() { return false; } function getIsCountable() { return false; } function getQty() { return 1; } function getIsVariableQty() { return false; } function getBillingPlanId() { return null; } function getBillingPlanData() { return array(); } public function getOptions() { return null; } public function setOptions(array $options) { //nop } function calculateStartDate($paymentDate, Invoice $invoice) { return $paymentDate; } function findItem(array $existingInvoiceItems) { return null; } function addQty($requestedQty, $itemQty) { return 1; } }PK\iс>#default/models/ResourceCategory.phpnu[_childNodes; } function removeChildNode(ResourceCategory $node) { foreach ($this->_childNodes as $k => $n) { if ($n == $node) unset($this->_childNodes[$k]); } } function createChildNode() { $c = new self($this->getTable()); $c->parent_id = $this->pk(); if (!$c->parent_id) throw new Am_Exception_InternalError("Could not add child node to not-saved object in " . __METHOD__); $this->_childNodes[] = $c; return $c; } public function fromRow(array $vars) { if (isset($vars['childNodes'])) { foreach ($vars['childNodes'] as $row) { $r = new self($this->getTable()); $r->fromRow($row); $this->_childNodes[] = $r; } unset($vars['childNodes']); } return parent::fromRow($vars); } function getAllowedResources(User $user) { $res = array(); foreach ($this->getDi()->resourceAccessTable->getAllowedResources($user, ResourceAccess::USER_VISIBLE_TYPES) as $r) { if (in_array($this->pk(), $r->getCategories())) { $res[] = $r; } } return $res; } function _getAllowedResources(User $user, $resources) { $res = array(); foreach ($resources as $r) { if (isset($r->_categories[$this->pk()])) { $res[] = $r; } } return $res; } } class ResourceCategoryTable extends Am_Table { protected $_key = 'resource_category_id'; protected $_table = '?_resource_category'; protected $_recordClass = 'ResourceCategory'; const COUNT = 'count'; /** * Do not include categories that do not have products. */ const EXCLUDE_EMPTY = 'exclude_empty'; /** * @todo protect against endless cycle (child[parent_id] <-> parent[parent_id]) * @return ResourceCategory */ function getTree($cast_objects = true) { $ret = array(); foreach ($this->_db->select("SELECT resource_category_id AS ARRAY_KEY, parent_id AS PARENT_KEY, pc.* FROM ?_resource_category AS pc ORDER BY 0+sort_order") as $r) { $ret[] = $cast_objects ? $this->createRecord($r) : $r; } return $ret; } /** * retrieve category tree with access check * skip empty branches * * @param User $user */ function getAllowedTree(User $user) { $tree = $this->getTree(true); $this->_resources = $this->getDi()->resourceAccessTable->getAllowedResources($user, ResourceAccess::USER_VISIBLE_TYPES); $rc = $this->getAdapter()->selectCol("SELECT GROUP_CONCAT(resource_category_id), CONCAT(resource_id, '-', resource_type) AS ARRAY_KEY " . "FROM ?_resource_resource_category GROUP BY ARRAY_KEY;"); foreach($this->_resources as $k => $r) { $this->_resources[$k]->_categories = isset($rc[$r->pk() . '-' . $r->getAccessType()]) ? array_combine($_ = explode(',', $rc[$r->pk() . '-' . $r->getAccessType()]), $_) : array(); } foreach ($tree as $k => $node) { $node->cnt = $this->_calcCntAndFilterEmpty($node, $user); if (!$node->cnt) unset($tree[$k]); } return $tree; } protected function _calcCntAndFilterEmpty(ResourceCategory $node, User $user) { $res = $node->self_cnt = count($node->_getAllowedResources($user,$this->_resources)); foreach ($node->getChildNodes() as $n) { $n->cnt = $this->_calcCntAndFilterEmpty($n, $user); if (!$n->cnt) $node->removeChildNode($n); $res += $n->cnt; } return $res; } function getOptions() { $ret = array(); $rows = $this->_db->select("SELECT resource_category_id AS ARRAY_KEY, parent_id AS PARENT_KEY, resource_category_id, title FROM ?_resource_category ORDER BY parent_id, 0+sort_order"); foreach ($rows as $id => $r) { $this->renderNode($r, $id, '', array(), '', $ret); } return $ret; } protected function renderNode($r, $id, $type, array $options, $title, &$ret) { $do_count = !empty($options[self::COUNT]); $exclude_empty = !empty($options[self::EXCLUDE_EMPTY]); $title .= ( $title ? '/' : '') . $r['title']; $ctitle = $title; if ($exclude_empty && !$r['count']) { foreach ($r['childNodes'] as $cid => $c) $this->renderNode($c, $cid, $type, $options, $ctitle, $ret); return; } if ($do_count) $title .= sprintf(' (%d)', $r['count']); $ret[$id] = $title; foreach ($r['childNodes'] as $cid => $c) $this->renderNode($c, $cid, $type, $options, $ctitle, $ret); } function moveNodes($fromId, $toId) { $this->_db->query("UPDATE {$this->_table} SET parent_id=?d WHERE parent_id=?d", $toId, $fromId); } public function delete($key) { parent::delete($key); $this->_db->query("DELETE FROM ?_resource_resource_category WHERE resource_category_id=?d", $key); } } PK\<**default/models/SavedForm.phpnu[getTable()->getTypeDef($this->type); } public function isSignup() { $typeDef = $this->getTypeDef(); return isset($typeDef['isSignup']) && $typeDef['isSignup']; } public function isCart() { return $this->type == self::T_CART; } public function isProfile() { return $this->type == self::T_PROFILE; } public function getDefaultFor() { return array_filter(explode(',',$this->default_for)); } public function setDefaultFor(array $values) { return $this->default_for = implode(',', array_unique(array_filter(array_map('filterId', $values)))); } public function addDefaultFor($d) { $def = $this->getDefaultFor(); $def[] = $d; $this->setDefaultFor($def); return $this; } public function delDefaultFor($d) { $def = $this->getDefaultFor(); array_remove_value($def, $d); $this->setDefaultFor($def); return $this; } public function isDefault($dConst) { return in_array($dConst, $this->getDefaultFor()); } public function getUrl($baseUrl) { $type = $this->getTypeDef(); if (empty($type['urlTemplate'])) return; if (is_array($type['urlTemplate'])) $add = call_user_func($type['urlTemplate'], $this); else $add = $type['urlTemplate']; return $baseUrl . $add; } /** @return Am_Form_Bricked */ public function createForm() { $type = $this->getTypeDef(); if (!$type['class']) throw new Am_Exception("Could not instantiate form - empty class in typeDef"); return new $type['class']; } public function generateCode() { do { $this->code = $this->getDi()->security->randomString(rand(8,9)); } while ($this->getTable()->findFirstByCode($this->code)); } function getFields() { return (array)json_decode($this->fields, true); } function setFields(array $fields) { $this->fields = json_encode($fields); } /** @return array of Am_Form_Brick */ function getBricks() { static $ret = null; if (is_null($ret)) { $ret = array(); foreach ($this->getFields() as $brickConfig) { if (strpos($brickConfig['id'],'PageSeparator')===0) continue; $b = Am_Form_Brick::createFromRecord($brickConfig); if (!$b) continue; $ret[] = $b; } $event = new Am_Event(Am_Event::SAVED_FORM_GET_BRICKS, array( 'type' => $this->type, 'code' => $this->code, 'savedForm' => $this )); $event->setReturn($ret); $this->getDi()->hook->call($event); $ret = $event->getReturn(); foreach ($ret as $brick) $brick->init(); } return $ret; } function isSingle() { $typeDef = $this->getTypeDef(); return isset($typeDef['isSingle']) && $typeDef['isSingle']; } function canDelete() { if (!$this->type) return true; $typeDef = $this->getTypeDef(); if (!empty($typeDef['noDelete'])) return false; if (!empty($this->default_for)) return false; return true; } public function setDefaultBricks() { $value = array(); foreach ($this->createForm()->getDefaultBricks() as $brick) $value[] = $brick->getRecord(); $this->setFields($value); return $this; } public function setDefaults() { if (empty($this->type)) throw new Am_Exception_InternalError("Error in ".__METHOD__." could not set defaults without type"); $typeDef = $this->getTypeDef(); if (!empty($typeDef['generateCode']) && empty($this->code)) $this->generateCode(); if (empty($this->title) && !empty($typeDef['defaultTitle'])) $this->title = $typeDef['defaultTitle']; if (empty($this->comment) && !empty($typeDef['defaultComment'])) $this->comment = $typeDef['defaultComment']; $this->setDefaultBricks(); return $this; } function findBrickConfigs($class, $id = null) { $ret = array(); foreach ($this->getFields() as $row) { if (empty($row['class']) || ($row['class'] != $class)) continue; if (($id === null) || ($row['id'] == $id)) $ret[] = $row; } return $ret; } function addBrickConfig($row) { $fields = $this->getFields(); $fields[] = $row; $this->setFields($fields); return $this; } function removeBrickConfig($class, $id = null) { $fields = $this->getFields(); $count = 0; foreach ($fields as $k => $row) { if ($row['class'] != $class) continue; if (($id !== null) && ($row['id'] == $id)) { $count++; unset($fields[$k]); } } if ($count) $this->setFields($fields); return $this; } /** * @return array|null */ function findBrickById($id) { $fields = $this->getFields(); foreach ($fields as $k => $row) { if (($id !== null) && ($row['id'] == $id)) { return $row; } } } public function insert($reload = true) { $table_name = $this->getTable()->getName(); $max = $this->getAdapter()->selectCell("SELECT MAX(sort_order) FROM {$table_name}"); $this->sort_order = $max + 1; return parent::insert($reload); } } /** * @package Am_SavedForm */ class SavedFormTable extends Am_Table { protected $_key = 'saved_form_id'; protected $_table = '?_saved_form'; protected $_recordClass = 'SavedForm'; protected $_eventCalled = false; private $types = array( SavedForm::T_SIGNUP => array( 'type' => SavedForm::T_SIGNUP, 'class' => 'Am_Form_Signup', 'title' => 'Signup Form', 'defaultTitle' => 'Signup Form', 'defaultComment' => 'customer signup/payment form', 'isSignup' => true, 'generateCode' => true, 'urlTemplate' => array('Am_Form_Signup', 'getSavedFormUrl'), ), SavedForm::T_PROFILE => array( 'type' => SavedForm::T_PROFILE, 'class' => 'Am_Form_Profile', 'title' => 'Profile Form', 'defaultTitle' => 'Customer Profile', 'defaultComment' => 'customer profile form', 'isSingle' => false, 'isSignup' => false, 'generateCode' => true, 'urlTemplate' => array('Am_Form_Profile', 'getSavedFormUrl'), ), ); public function getOptions($type = null) { return $this->_db->selectCol("SELECT saved_form_id as ARRAY_KEY, concat(title, ' (', comment, ')') FROM {$this->_table} {WHERE type=?} ORDER BY title", $type ? $type : DBSIMPLE_SKIP); } /** * @param int $d_const one from SavedForm::D_xxx constant * @return SavedForm|null */ function getDefault($dConst) { $row = $this->_db->selectRow(" SELECT * FROM ?_saved_form WHERE FIND_IN_SET(?, default_for) LIMIT 1", $dConst); if ($row) return $this->createRecord($row); } /** * @param string $type * @return SavedForm */ function getByType($type) { return $this->findFirstByType($type); } function addTypeDef(array $typeDef) { $this->types[$typeDef['type']] = $typeDef; return $this; } /** @return array typedef * @throws exception if not found */ function getTypeDef($type) { $this->runEventOnce(); if (empty($this->types[$type])) throw new Am_Exception_InternalError("Could not get typeDef for type [$type]"); return $this->types[$type]; } final public function getTypeDefs() { $this->runEventOnce(); return $this->types; } protected function runEventOnce() { if (!$this->_eventCalled) { $this->_eventCalled = true; $this->getDi()->hook->call(Am_Event::SAVED_FORM_TYPES, array('table' => $this)); } } function getTypeOptions() { foreach ($this->getTypeDefs() as $t) $ret[$t['type']] = $t['title']; return $ret; } function setDefault($d, $saved_form_id) { switch ($d) { case SavedForm::D_SIGNUP: case SavedForm::D_MEMBER: case SavedForm::D_PROFILE: $f = $this->load($saved_form_id); if ($f->type != SavedForm::T_SIGNUP && $f->type != SavedForm::T_PROFILE) throw new Am_Exception_InputError("Could not set default form - it has no 'signup' or 'profile' type"); $f->addDefaultFor($d)->update(); // now remove default from all other forms, there should not be too many foreach ($this->selectObjects(" SELECT * FROM ?_saved_form WHERE saved_form_id<>?d AND FIND_IN_SET(?, default_for)", $saved_form_id, $d) as $f) $f->delDefaultFor($d)->update(); break; default: throw new Am_Exception_InputError("Could not ".__METHOD__." for " . $d->$saved_form_id); } } public function getExistingTypes() { return $this->_db->selectCol("SELECT DISTINCT `type` FROM ?_saved_form WHERE type <> ''"); } } PK\c:edefault/models/File.phpnu[getDi()->url("content/f/id/{$this->file_id}", false); } public function renderLink() { list($type, $subtype) = explode('/', $this->mime); $prefix = "am-resource-" . $this->getTable()->getAccessType(); return preg_replace('/(class="[-_a-zA-Z]*?)(")/', "$1 $prefix-$type $prefix-$type-$subtype$2", parent::renderLink()); } } class FileTable extends ResourceAbstractTable { protected $_key = 'file_id'; protected $_table = '?_file'; protected $_recordClass = 'File'; public function getAccessType() { return ResourceAccess::FILE; } public function getAccessTitle() { return ___('Files'); } public function getPageId() { return 'files'; } }PK\ b:ȳ default/models/ErrorLog.phpnu[_db->query("DELETE FROM ?_error_log WHERE `time` < ? ", $date . ' 00:00:00'); } static function backtraceToString(array $trace) { $out = ""; foreach ($trace as $t) { if (isset($t['class'])) { $out .= $t['class'] . $t['type'] . $t['function']; } else { $out .= $t['function']; } if (!empty($t['file'])) { $file = str_replace(@ROOT_DIR . DIRECTORY_SEPARATOR, '', $t['file']); $out .= " [ $file"; if (!empty($t['line'])) $out .= " : {$t['line']}"; $out .= " ]"; } $out .= "\n"; } return $out; } function logException($e) { $error = $e->getMessage(); if (defined('AM_TEST') && AM_TEST) return false; $values = array( 'time' => $this->getDi()->sqlDateTime, 'user_id' => $this->getDi()->auth->getUserId(), 'remote_addr' => @$_SERVER['REMOTE_ADDR'], 'url' => htmlentities(@$_SERVER['REQUEST_URI']), 'referrer' => htmlentities(@$_SERVER['HTTP_REFERER']), 'error' => $error, 'trace' => "Exception " . get_class($e) . PHP_EOL . self::backtraceToString($e->getTrace()) ); if ($e instanceof Am_Exception_Db) { @$this->insert($values, false); } else { $this->insert($values, false); } } /** * Log a message * @param string $error */ function log($error) { if ($error instanceof Exception) return $this->logException($error); if (defined('AM_TEST') && AM_TEST) return false; if (!$this->getDi()->getService('db') || !@$this->getDi()->db || !$this->getDi()->db->_isConnected()) return; $trace = debug_backtrace(false); array_shift($trace); // remove ErrorLog->log entry array_shift($trace); // remove ErrorLog->log entry try { // necessary to avoid errors if init is not finished $user_id = $this->getDi()->auth->getUserId(); } catch (Exception $e) { $user_id = null; } $values = array( 'time' => $this->getDi()->sqlDateTime, 'user_id' => $user_id, 'remote_addr' => @$_SERVER['REMOTE_ADDR'], 'url' => htmlentities(@$_SERVER['REQUEST_URI']), 'referrer' => htmlentities(@$_SERVER['HTTP_REFERER']), 'error' => $error, 'trace' => self::backtraceToString($trace) ); $this->insert($values, false); } }PK\uggdefault/models/Product.phpnu[getBillingPlan()->rebill_times; } /** * Run htmlspecialchars(strip_tags()) for the string * It is useful for strings that may contain html entities but we would * not want to see it here, for example: product title or description * @param string string to escape * @return string escaped string */ static function stripEscape($string){ return htmlspecialchars(strip_tags($string), null, 'UTF-8', false); } /** * Return title of product */ function getTitle($escaped=true){ $title = ___($this->title); return $escaped ? $this->stripEscape($title) : str_ireplace('

      getHelp(); ?> PK\ 7DDidefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/includes/controller.phpnu[preDispatch()) return ; $this->dispatch(false, $action); $this->postDispatch(); } function dispatch($isAjax=false,$directAction=''){ $action = $directAction ? $directAction : am4Request::getWord($this->_action_field); if(!$action) $action = $this->_default_action; $method = $isAjax ? 'doAjax'.ucfirst($action) : 'do'.ucfirst($action); if(method_exists($this,$method)){ call_user_func(array($this,$method)); }else{ throw new Exception('Action not defined:'.$action); } } function doIndex(){ throw new Exception('Not Implemented!'); } function preDispatch(){ return true; } function postDispatch(){ } function preAjaxDispatch(){ if(!check_ajax_referer($this->getAjaxActionValue(get_class($this)), 'action_security')){ throw new Exception("Security check failed"); } return true; } function postAjaxDispatch(){ } function run($is_ajax=false){ if($is_ajax == self::AJAX){ if(!$this->preAjaxDispatch()) return; $this->dispatch(self::AJAX); $this->postAjaxDispatch(); exit; }else{ if(!$this->preDispatch()) return ; $this->dispatch(); $this->postDispatch(); } } function runAjax(){ $this->run(self::AJAX); } function actionInput($action, $ret=false){ $i = ""; if($ret) return $i; else print $i; } function createView($view){ return new am4View($view, $this); } static function getAjaxActionValue($cname){ if(!$cname) throw Exception('No class passed for getAjaxActionValue'); return am4_from_camel($cname); } function amPostScript(){ ?> validate($options)) !== true){ $this->doIndex($options, $errors); }else{ $this->saveForm($options); $this->doIndex(); } } function saveForm($options){ } function validate($options){ return true; } function getProtectionDefaults(){ return array( 'user_action' => 'login', 'guest_action' =>'login', 'user_action_search' => 'hide', 'guest_action_search' => 'hide', 'guest_action_menu' => 'hide', 'user_action_menu' => 'hide', 'include_in_rss' => 'hide' ); } function getCatProtectionDefaults(){ return array( 'user_action_cat' => 'login', 'guest_action_cat' => 'login', 'user_action_cat_menu' => 'hide', 'guest_action_cat_menu' => 'hide' ); } /** * * @return am4_Settings_Abstract|null */ function getOptions(){ return null; } function getViewName(){ $cname = get_class($this); preg_match('/\S+_(\S+)/', $cname, $regs); return $regs[1]; } function doIndex($options=null, $errors=array(),$vars=array()){ $view = $this->createView($this->getViewName()); $view->options = $options ? $options : $this->getOptions(); $view->errors = $errors; $view->vars = $vars; $view->render(); } function preDispatch(){ parent::preDispatch(); if(!current_user_can("manage_options")) return false; return true; } }PK\ Dedefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/includes/access.phpnu[fromArray($record); } function checkAccess(am4AccessCacheRecord $a) { // Check record type; if (($this->id != am4Access::ANY_PRODUCT) && ($this->type != $a->type)) return false; // Check record id; -1 means any; if ($this->id != am4Access::ANY_PRODUCT && $this->id != $a->id) return false; // Check status; if (!in_array($a->status, $this->status)) return false; // Check period; if ($this->startType == 'd' && $a->days < $this->start) return false; if ($this->startType == 'p' && $a->payments_count < $this->start) return false; if ($a->days > $this->stop) return false; return true; } static function createRequirements() { $req = array(); $args = func_get_args(); foreach((array)$args as $records) foreach((array)$records as $type => $r){ foreach((array)$r as $id => $v){ $req[] = new self(array( 'type' => $type, 'id' => $id, 'start' => $v['start'], 'stop' => $v['stop'])); } } return $req; } function toArray() { throw new Exception("Not implemented!"); } function fromArray($record) { $this->id = $record['id']; $this->type = $record['type']; if (preg_match('/([0-9]+)(d|p)/', $record['start'], $m)) { $this->start = intval($m[1]); $this->startType = $m[2]; } else { $this->start = intval($record['start']); $this->startType = 'd'; } $this->stop = intval($record['stop']); if($this->stop == -1) { $this->status = array(am4Access::ACTIVE, am4Access::EXPIRED); } else { $this->status = array(am4Access::ACTIVE); } if($this->stop <= 0) $this->stop = PHP_INT_MAX; } function __toString() { $value = ''; if($this->id){ switch($this->type){ case am4Access::PRODUCT : $titles = am4PluginsManager::getAMProducts(); break; case am4Access::CATEGORY : $titles = am4PluginsManager::getAMCategories(); break; default: throw new Exception('Unknown record type!'); } if($this->id == -1) { $value = ""._('Any Product')." "; } else { $value = "".@$titles[$this->id]." "; } $value .= _(' from ').($this->start==0 ? _('start') : $this->start.$this->startType)._(' to ').(in_array(am4Access::EXPIRED, $this->status) ? _(' forever ') : ($this->stop == PHP_INT_MAX ? _('expiration') : $this->stop.'d')); return $value; } return $value; } } class am4AccessCacheRecord { public $id; public $type; public $days; public $status; function __construct(array $record) { $this->id = $record['id']; $this->type = $record['type']; $this->days = $record['days']; $this->payments_count = $record['payments_count']; $this->status = $record['status']; } } // User access class. All cache records that user have. class am4Access { private $cache = array(); const PRODUCT = 'product'; const CATEGORY = 'category'; const FOREVER = -1; const EXPIRATION = 0; const START = 0; const ANY_PRODUCT = -1; const ACTIVE = 'active'; const EXPIRED = 'expired'; function addRecord(am4AccessCacheRecord $c) { $this->cache[] = $c; } function getRecords() { return $this->cache; } function checkRequirement(am4AccessRequirement $r) { foreach($this->getRecords() as $a){ if($r->checkAccess($a)) return true; } return false; } // return true when all requirements are true; function allTrue(Array $req) { $ret = true; foreach($req as $r){ $ret = $ret && $this->checkRequirement($r); } return $ret; } // return true when all requirements are false; function allFalse(Array $req) { $ret = false; foreach($req as $r){ $ret = $ret || $this->checkRequirement($r); } return !$ret; } // return true when any requirement is true; function anyTrue(Array $req) { foreach($req as $r){ if($this->checkRequirement($r)) return true; } return false; } //return false when any requirement is false; function anyFalse(Array $req) { foreach($req as $r){ if(!$this->checkRequirement($r)) return true; } } } class am4UserAccess extends am4Access { private $user_id; static $_cache = null; function __construct() { if($this->isLoggedIn()){ foreach((array)$this->getAccessCache() as $a){ $this->addRecord(new am4AccessCacheRecord(array( 'type' => ($a['fn'] == 'product_id' ? self::PRODUCT : self::CATEGORY), 'days' => $a['days'], 'payments_count' => $a['payments_count'], 'id' => $a['id'], 'status' => $a['status']))); } } } function isLoggedIn() { return am4PluginsManager::getAPI()->isLoggedIn(); } function isAffiliate() { $user = am4PluginsManager::getAPI()->getUser(); return ($user['is_affiliate'] > 0); } function getAccessCache() { if (is_null(self::$_cache)) { self::$_cache = am4PluginsManager::getAPI()->getAccessCache(); } return self::$_cache; } }PK\Azwz&z&cdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/includes/view.phpnu[_fname = $fname; $this->_controller = $controller; $this->_type = $type; } static function init($name, am4PageController $controller=null, $type = self::TYPE_HTML){ return new self($name, $controller,$type); } function showErrors(){ if($this->errors){ foreach($this->errors as $e){ ?>
      $name = $value; } function get($name){ return $this->$name; } function __get($name){ if(!array_key_exists($name, $this->_v)) return null; return $this->_v[$name]; } function __set($name,$value){ $this->_v[$name] = $value; } function fetch(){ foreach((array)$this->_v as $k=>$v){ $$k = $v; } ob_start(); $_info = pathinfo($this->_fname); $_fname = $_info['basename']; $templates = new am4_Settings_Templates(); if($templates->{$_fname}){ try{ eval("?>".$templates->{$_fname}); }catch(Exception $e){ print "Error in template: ".$e->getMessage(); } }else{ require($this->_fname); } $ret = ob_get_contents(); ob_end_clean(); switch($this->_type){ case self::TYPE_CSS : $ret = ""; break; case self::TYPE_JS : $ret = ""; break; case self::TYPE_HTML : default : break; } return $ret; } function render(){ echo $this->fetch(); } function fetchTemplateCode($path){ $info = pathinfo($path); $fname = $info['basename']; $templates = new am4_Settings_Templates(); if($templates->{$fname}){ eval("?>".$templates->{$fname}); }else{ require($path); } } function escape($subj, $esc_type=self::ESC_HTML){ if(is_array($subj)){ foreach($subj as $k=>$v){ $subj[$k] = $this->escape($v); } return $subj; } switch ($esc_type) { case self::ESC_HTML : return htmlspecialchars($subj, ENT_QUOTES); case self::HTMLALL : return htmlentities($subj, ENT_QUOTES); case self::URL : return urlencode($subj); case self::ESC_QUOTES : // escape unescaped single quotes return preg_replace("%(?'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n')); default: return $subj; } } function e($string, $esc_type=self::ESC_HTML){ echo $this->escape($string, $esc_type); } function getController(){ return $this->_controller; } function _action($ret=false){ if($ret) return $this->getController()->actionField(); print $this->getController()->actionField(); } function options(Array $options, $selected=false, $ret = false){ $o = ''; foreach($options as $k=>$v){ $o .= ""; } if($ret) return $o; print $o; } function pagesOptions($selected, $ret=false){ $pages = get_pages(); $o = array(); foreach($pages as $p){ $o[$p->ID] = $p->post_title; } return $this->options($o, $selected, $ret); } function checkboxes($name, Array $values, $selected, $ret=false){ if(!is_array($selected)) $selected = array($selected); $o = ''; foreach($values as $k=>$v){ $o .= "
      "; } if($ret) return $o; print $o; } function addProductTitle($access){ $products = am4PluginsManager::getAMProducts(); $categories = am4PluginsManager::getAMCategories(); if($access){ foreach((array)$access as $t => $l){ foreach((array)$l as $id => $a){ $name = ($t == am4Access::CATEGORY ? @$categories[$id] : @$products[$id]); if($name) $access[$t][$id]['title'] = $name; } } } return $access; } function resourceAccess($id, $access=array(), $varname='access',$text=null, $without_period=false){ if(!$text) $text = __('Choose Products and/or Product Categories that allows access', 'am4-plugin'); $uniqid = uniqid('amw-'); ?>

      ' />

      initActions(); $this->initFilters(); return $this; } } class am4Basic extends am4Plugin { function action_AdminInit(){ wp_register_script("dirbrowser", plugins_url("/js/dirbrowser.js", dirname(__FILE__))); wp_register_script('amember-jquery-outerclick', plugins_url("/views/jquery.outerClick.js", dirname(__FILE__))); wp_register_script('amember-jquery-tabby', plugins_url("/views/jquery.textarea.js", dirname(__FILE__))); wp_register_script('amember-resource-access', plugins_url("/views/resourceaccess.js", dirname(__FILE__))); wp_register_style( 'jquery-style', '//ajax.googleapis.com/ajax/libs/jqueryui/1.8.12/themes/redmond/jquery-ui.css', true); wp_register_style('amember-style', plugins_url("/views/admin_styles.css", dirname(__FILE__))); } function action_AdminPrintStyles(){ if(strstr(am4_get_current_screen()->id, 'am4-settings')!==false) wp_enqueue_style('jquery-style'); wp_enqueue_style('amember-style'); wp_enqueue_style("wp-jquery-ui-dialog"); } function action_AdminPrintScripts(){ wp_enqueue_script("amember-resource-access"); wp_enqueue_script("dirbrowser"); wp_enqueue_script('amember-jquery-outerclick'); wp_enqueue_script('amember-jquery-tabby'); wp_enqueue_script("jquery-ui-dialog"); } function action_WpLogout(){ header("Location: ".am4PluginsManager::getAPI()->getLogoutURL()); exit; } function filter_AdminUrl($url, $path){ if((strpos($path, 'profile.php') !== false) && !am4PluginsManager::skipProtection() && am4PluginsManager::getOption('profile_redirect')) { return am4PluginsManager::getAPI()->getProfileURL(); } return $url; } }PK\XK ddefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/includes/utils.phpnu[_data = $arr; } function setError($str){ $this->_data['error'] = $str; } function send(){ echo $this->__toString(); } function __get($name) { if(array_key_exists($name, $this->_data)) return $this->_data[$name]; else return false; } function __set($name, $value) { $this->_data[$name] = $value; } function __toString() { return json_encode($this->_data); } static function init($arr){ return new self($arr); } } class aMemberJsonError extends aMemberJson { function __construct($error){ $this->setError($error); } } class am4Request{ static $vars = array(); static $post = array(); static $get = array(); static $method = "GET"; const VARS = 'vars'; const GET = 'get'; const POST = 'post'; static function get($k,$default=''){ if(!array_key_exists($k, self::$vars)) return $default; return self::$vars[$k] ? self::$vars[$k] : 'default'; } static function getWord($k,$default=''){ $r = self::get($k, $default); return preg_replace('/[^a-zA-Z0-9]/', '', $r); } static function getInt($k,$default=''){ return intval(self::get($k,$default)); } static function defined($k){ return array_key_exists($k, self::$vars); } static function init(){ foreach($_GET as $k=>$v){ self::$vars[$k] = $v; self::$get[$k] = $v; } foreach($_POST as $k=>$v){ self::$vars[$k] = $v; self::$post[$k] = $v; } self::$method = $_SERVER['REQUEST_METHOD']; } } am4Request::init(); function strleft($s1, $s2) { return substr($s1, 0, strpos($s1, $s2)); }PK\}7_fdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/includes/options.phpnu[load(); $this->rewind(); } public function get($key, $default = null) { if($this->isEmpty()) return $default; if(array_key_exists($key, $this->settings)) return $this->settings[$key]; return $default; } function __get($name){ return $this->get($name); } function __set($key, $value){ return $this->set($key, $value); } public function set($key, $value){ if (is_null($key)) { $this->settigns[] = $value; } else { $this->settings[$key] = $value; } return $this; } abstract public function save(); abstract public function load(); function isEmpty(){ return empty($this->settings); } function loadFromArray(Array $array){ $this->settings = $array; return $this; } function loadDefaults(Array $array){ foreach($array as $k =>$v){ $this->set($k, $v); } return $this; } function delete($key){ if(array_key_exists($key, $this->settings)) unset($this->settings[$key]); return $this; } public function offsetSet($offset, $value) { if (is_null($offset)) { $this->settigns[] = $value; } else { $this->settings[$offset] = $value; } } public function offsetExists($offset) { return isset($this->settings[$offset]); } public function offsetUnset($offset) { unset($this->settigns[$offset]); } public function offsetGet($offset) { $val = (isset($this->settings[$offset]) ? $this->settings[$offset] : null); return $val; } function rewind() { if(is_array($this->settings)) { reset($this->settings); $this->position = key($this->settings); } } function current() { return current($this->settings); } function key() { return key($this->settings); } function next() { next($this->settings); $this->position = key($this->settings); } function valid() { return isset($this->settings[$this->position]); } } class am4_Settings_Config extends am4_Settings_Abstract { /** * Name of option in database; */ protected $name = 'am4options'; function __construct($name=null){ if(!empty($name)) $this->name=$name; parent::__construct(); } public function save() { update_option($this->name, $this->settings); } public function load() { $this->settings = get_option($this->name, array()); return $this; } } class am4_Settings_Post_Meta extends am4_Settings_Abstract{ protected $name= 'am4options'; protected $post_id; public function __construct($post_id=null){ $this->setPostId($post_id); parent::__construct(); } public function load() { if($this->post_id){ $this->settings = get_post_meta($this->post_id, $this->name, true); if(!is_array($this->settings)) $this->settings = array(); } } public function save() { if(empty($this->post_id)) throw new Exception('Post ID is empty. Nothing to save!'); update_post_meta($this->post_id, $this->name, $this->settings); } function setPostId($post_id){ $this->post_id = $post_id; return $this; } } class am4_Settings_Category extends am4_Settings_Abstract { /** * Name of option in database; */ protected $name = 'am4catoptions'; protected $category; /** * * @var am4_Settings_Config */ protected $config; function __construct($category) { $this->category = $category; $this->config = new am4_Settings_Config($this->name); parent::__construct(); } public function save() { $this->config->set($this->category, $this->settings); $this->config->save(); } public function load() { $this->settings = $this->config->get($this->category, array()); return $this; } } class am4_Settings_Error extends am4_Settings_Config{ /** * Name of option in database; */ protected $name = 'am4errors'; function getTextByName($name){ foreach($this->settings as $k=>$v){ if(is_array($v) && array_key_exists("name", $v) && $v['name'] == $name) return @$v['text']; } return null; } function add(Array $value){ $this->settings[] = $value; return $this; } } class am4_Settings_Templates extends am4_Settings_Config { /** * Name of option in database; */ protected $name = 'am4styles'; } PK\U㦈 edefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/img/ajax-loader.gifnu[GIF89a {{{222PPPհ! NETSCAPE2.0!Created with ajaxload.info! , IiabK$F RAT,2S*05//mp!z0;$0C.I*!HC(A@o!39T5\8) `dwxG=Y gwHbvA=0 V\\; ;H0t%HsrY'e$"\#E1CnĎ~J,,AaUw^4I%Pu Q33{0i1TGgwy}%%'R  = 3G%p0 JRo5Ȇ0IĦmykxT_}(^yKs>i_%n=q4e-M¤D! , I)*')Ed]PR A:!zrbw %6"G(d$["JFhaQP`p%†/BFP\cU ?TtW/pG&OtDa_sylD'M q tc b2DM : d% 4%s) uE3 YUtږD$JiM^%o/rvl9'L;99% i9 C "B BDs ^Xf}$P {L?P O4 E咛V$dJ#)pV$! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'Kw}?Kiz6:xKAC&}9tz\ \D5;x Qd( KW  MBIڈM=ˤs⸽8DaJ`@LG! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'KGziz68}z~%XK9:0}% tz\Blc LbQ   lj ųKň x(țPX ,ւ|/"! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'KGziz68}z~%:A/ C} u\ h}b D]=  V)  ڊ9CDK Ku *00StD! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6Ib H8 B; "'ZtbK#C'KGz z5 C: A/ C}u\ Eh}b6[=Wx&)I9Ԭ@oCT?Kd]B76ЫD! , IiRͧ"Jd] RZN*P*;$P{*N\EА!1UO2D _r6I ƀH03hոaj U {CIkmbK#cK8 {a8nV:/q:M Cu~Ehk6 [_6P.]6!)V! , IiRͧ"Jd]U RZN JjN2sK6 dI)  LHWG 6 KX젱.6d~zhuur/6 X5I;_t O#E {O9V94;VC/ 6Ø~*'MonbX:~]+V*mK_OrKN@.d~qЦDB֋ 5D;PK\ K^default/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/img/lock.pngnu[PNG  IHDRasRGBbKGD pHYs  tIME 0t=;wIDAT8ekU$3&q`(ɴZQqق ҅ѝ+qQ dS d[ąn ҀNjb|PR4xM=<Ͻ2+faf]UlthoF9==Mwg0ptt}?@ݞ4Vk1!^3\.3;; C3{kuuufܢ(H%󅭭?b4EUyv|֨Z"r}ii`&z<`&@pUuOD!`f3`;y(%!(;;\߸ RⓏ##d|AyH`iڵfL> Y6 ^jS7bw\O^I*xt;?s߸wI2^k?f)I(@ % ˯f slhgetAll() as $n){ echo "

      amember4 plugin: ".$n."

      "; } } function getAll() { return $this->_notifications; } function add($notice) { $this->_notifications[] = $notice; } function init(){ parent::init(); foreach(get_class_methods($this) as $m){ if(preg_match("/^notification.*/", $m)){ $r = call_user_func(array($this, $m)); if($r) $this->add($r); } } } function notification_Suhosin(){ /* if(ini_get('suhosin.session.encrypt')) return __('IMPORTANT: Your system have suhosin.session.encrypt setting set to On in php.ini. This setting must be disabled!').'
      '. __('Add this line to your public_html/.htaccess file: php_flag suhosin.session.encrypt Off in order to disable it').'
      '. __('Or contact hosting support if this does not help'); */ } function notification_PDO(){ if(!class_exists('PDO')){ return __('PHP on your webhosting has no [pdo] extension enabled. Please ask the webhosting support to install it'); } } }PK\slug,'','',self::POSTION); foreach(get_declared_classes() as $c){ if(preg_match('/am4MenuPage_(\S+)/',$c,$regs)){ $this->addMenuItem("am4-".strtolower($regs[1]), $c); } } } function addMenuItem($slug, $class) { $title = call_user_func(array($class, 'getTitle')); $a = add_submenu_page($this->slug, $title, $title,'administrator', $slug, am4PluginsManager::createController($class)); if(method_exists($class, 'staticAction')){ add_action('load-'.$a, array($class, 'staticAction')); } } } class am4MenuPageController extends am4FormController { static function getTitle() { throw new Exception("getTitle should be overriden in childs"); } function preDispatch(){} } class am4MenuPageFormController extends am4MenuPageController { function preDispatch() { parent::preDispatch(); if(!current_user_can('manage_options')) return ''; // Verify nonce if(am4Request::$method=='POST' && !check_admin_referer(get_class())){ throw new Exception('Security check!'); } $this->amPostScript(); ?>

      getTitle());?>

      actionInput("save"); ?>
      {'user_action'} || !$options->{'guest_action'}) $options->loadDefaults($this->getProtectionDefaults()); if(!$options->{'disable_protection'}) $options->{'disable_protection'} = array('administrator'); return $options; } function saveForm($post) { $options = new am4_Settings_Config(); $options->loadFromArray($post)->save(); } function validate($options) { try{ am4PluginsManager::initAPI(@$options['path']); }catch(Exception $ex){ return $ex->getMessage(); } return true; } static function staticAction() { if(am4Request::$method!='POST') return; if(!current_user_can('manage_options')) return; if(!check_admin_referer('am4MenuPageFormController')){ throw new Exception('Security check!'); } $options = get_magic_quotes_gpc() ? stripslashes_deep(am4Request::get('options')) : am4Request::get('options'); try { am4PluginsManager::initAPI(@$options['path']); } catch (Exception $e) {} } function doAjaxValidate() { if (($err = $this->validate(array('path' => am4Request::get('path')))) === true){ $am = Am_Lite::getInstance(); $e = new aMemberJson(); $e->valid=1; $e->url = $am->getRootURL(); echo $e; } else { $e = new aMemberJsonError($err); echo $e; } } function doAjaxBrowse() { $dirOrig = am4Request::get('dir', ABSPATH); $dirOrig = is_dir($dirOrig) ? $dirOrig : ABSPATH; $selected = am4Request::get('selected', false); $dir = ($selected) ? dirname($dirOrig) : $dirOrig; $dir = realpath($dir); if (!is_dir($dir)) { $dir = ABSPATH; } $dirList = $this->getDirList($dir); if ($selected) { foreach ($dirList as $k => $dirDescription) { if ($dirDescription['path'] == $dirOrig) { $dirList[$k]['selected'] = true; break; } } } $currentDir = $this->getCurrentDir($dir); $prevDir = $this->getPrevDir($dir); $result = array( 'dirList' => $dirList, 'currentDir' => $currentDir, 'prevDir' => $prevDir, 'separator' => DIRECTORY_SEPARATOR ); aMemberJson::init($result)->send(); } protected function getCurrentDir($dir) { $result = array(); $dirParts = explode(DIRECTORY_SEPARATOR, $dir); $path = array(); foreach ($dirParts as $part) { $path[]= $part; $part_path = implode(DIRECTORY_SEPARATOR, $path); $dir = array ( 'name' => $part, 'path' => ($this->checkChRoot($part_path) ? $part_path : null ) ); $result[] = $dir; } return $result; } protected function getPrevDir($dir) { $prevDir = null; $prevDirPath = dirname($dir); //root of file system if ($prevDirPath == $dir) return null; $dirParts = explode(DIRECTORY_SEPARATOR, $prevDirPath); $prevDirName = end($dirParts); if (is_dir( $prevDirPath ) ) { $prevDir = array ( 'name' => $prevDirName, 'path' => ($this->checkChRoot($prevDirPath) ? $prevDirPath : null) ); } return $prevDir; } protected function getDirList($dir) { $result = array(); $dirName = $dir; $dirHandler = opendir($dirName); while(false !== ($fn = readdir($dirHandler))) { if (is_dir($dirName . DIRECTORY_SEPARATOR . $fn) && !in_array($fn, array('..', '.'))) { $result[] = $this->getDirRecord($dirName, $fn); } } closedir($dirHandler); usort($result, function($a, $b) {return strcmp($a["name"], $b["name"]);}); return $result; } protected function getDirRecord($dirName, $fn) { $stat = stat($dirName . DIRECTORY_SEPARATOR . $fn); $dir = array( 'name' => $fn, 'path' => $dirName . DIRECTORY_SEPARATOR . $fn, 'url' => $this->guessUrl($dirName . DIRECTORY_SEPARATOR . $fn), 'perm' => $this->formatPermissions($stat['mode']), 'created' => $this->formatDate($stat['ctime']), 'selected' => false ); return $dir; } public function guessUrl($dir) { $documentRootFixed = str_replace('/', DIRECTORY_SEPARATOR, $_SERVER['DOCUMENT_ROOT']); //check if it is possible to calculate url if (strpos($dir, $documentRootFixed) !== 0) return false; $rootUrlMeta = parse_url(get_option('blog_url')); //combine url return sprintf('%s://%s%s/%s', @$rootUrlMeta['scheme'], @$rootUrlMeta['host'], (isset($rootUrlMeta['port']) ? ':' . @$rootUrlMeta['port'] : ''), trim(str_replace(DIRECTORY_SEPARATOR, '/', str_replace($documentRootFixed, '', $dir)), '/') ); } protected function formatPermissions($p){ $res = ''; $res .= ($p & 256) ? 'r' : '-'; $res .= ($p & 128) ? 'w' : '-'; $res .= ($p & 64) ? 'x' : '-'; $res .= ' '; $res .= ($p & 32) ? 'r' : '-'; $res .= ($p & 16) ? 'w' : '-'; $res .= ($p & 8) ? 'x' : '-'; $res .= ' '; $res .= ($p & 4) ? 'r' : '-'; $res .= ($p & 2) ? 'w' : '-'; $res .= ($p & 1) ? 'x' : '-'; return $res; } protected function formatDate($tm) { return strftime("%m/%d/%Y %H:%M:%S", $tm); } protected function checkChRoot($dir) { if (!is_null($this->chroot) && strpos($dir, $this->chroot)!==0) { return false; } else { return true; } } } /* class am4MenuPage_styles extends am4MenuPageFormController{ protected $styles = array('widget_login_form.phtml', 'widget_after_login.phtml'); static function getTitle(){ return __('Templates', 'am4-plugin'); } function saveForm($options){ foreach($options as $k=>$v){ if(!in_array($k,$this->styles)) unset($options[$k]); } foreach($this->styles as $f){ $file = file_get_contents(AM4_PLUGIN_DIR."/views/".$f); if(strcmp(trim($file), trim($options[$f]))=== 0) unset($options[$f]); } if($options){ $templates = new am4_Settings_Templates(); $templates->loadFromArray($options)->save(); } } function getOptions(){ $templates = new am4_Settings_Templates(); foreach($this->styles as $s){ if(!$templates->get($s)){ $templates->set($s, file_get_contents(AM4_PLUGIN_DIR."/views/".$s)); } } return $templates; } } */ class am4MenuPage_errormessages extends am4MenuPageFormController { protected $simple; function __construct($simple = false) { $this->simple = $simple; } static function getTitle() { return __('Error Messages', 'am4-plugin'); } function isSimple() { return $this->simple; } function postDispatch() { return; // doNothing; } function saveForm($options) { $errors = $this->getOptions(); if (isset($options['id']) && ($options['id']!== '')) { $errors->set(intval($options['id']), $options); } else { $errors->add($options); } $errors->save(); } function getOptions() { $errors = new am4_Settings_Error(); return $errors; } function doAjaxDelete() { $id = am4Request::getInt('id'); $errors = $this->getOptions(); $errors->delete($id)->save(); } }PK\:^default/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/amember4.phpnu[ Author URI: http://www.amember.com/ */ define("AM4_PLUGIN_DIR", WP_PLUGIN_DIR."/amember4"); define("AM4_PLUGIN_URL", site_url("/wp-content/plugins/amember4")); define("AM4_INCLUDES", AM4_PLUGIN_DIR."/includes"); if(!defined('DIRECTORY_SEPARATOR')) define('DIRECTORY_SEPARATOR', '/'); //register_activation_hook(AM4_PLUGIN_DIR."/amember4.php", "amember4_plugin_activated"); //register_deactivation_hook(AM4_PLUGIN_DIR."/amember4.php", "amember4_plugin_deactivated"); class am4PluginsManager { private static $__plugins = array(); private static $cache = array(); private static $api = null; /** * @var am4_Settings_Config */ private static $settings; static function get($name){ if(array_key_exists($name, self::$__plugins)) return self::$__plugins[$name]; return null; } static function getPlugin($name){ return self::get($name); } static function initPlugin($name){ // Check if plugin exists already; if(($plugin = self::get($name)) !== null) return $plugin; if(!class_exists($cname = "am4".ucfirst($name)) && is_file($plugin_file = dirname(__FILE__)."/".$name.".php")){ require_once($plugin_file); } if(class_exists($cname = "am4".ucfirst($name))){ $plugin = new $cname(); $plugin->init(); self::$__plugins[$name] = $plugin; return $plugin; } return null; } static function includes(){ include_once(AM4_INCLUDES . "/utils.php"); include_once(AM4_INCLUDES . "/plugin.php"); include_once(AM4_INCLUDES . "/controller.php"); include_once(AM4_INCLUDES . "/view.php"); include_once(AM4_INCLUDES . "/access.php"); include_once(AM4_INCLUDES . "/options.php"); } static function init() { load_plugin_textdomain('am4-plugin', false, basename(dirname(__FILE__)).'/languages'); self::includes(); self::initPlugin("basic"); self::initPlugin('notifications'); if(!self::checkDependencies()) return; self::initPlugin("menu"); if(self::isConfigured()){ self::initPlugin("protection"); self::initPlugin("shortcodes"); self::initPlugin("widgets"); self::initPlugin('tinymce'); } self::initAjaxActions(); } static function checkDependencies() { if(!class_exists('PDO')) { return false; } return true; } static function createController($name, $is_ajax=false){ $f = function() use ($name, $is_ajax) {$class = new $name; $class->{'run' . ($is_ajax ? 'Ajax' : '')}();}; return $f; } static function runController($name, $is_ajax=false){ call_user_func(self::createController($name, $is_ajax)); } static function initAjaxActions(){ foreach(get_declared_classes() as $cname){ if(is_subclass_of($cname, 'am4PageController')){ foreach(get_class_methods($cname) as $m){ if(preg_match("/^doAjax(.*)/", $m, $r)){ $hook = "wp_ajax_".am4PageController::getAjaxActionValue($cname); add_action($hook, self::createController($cname, am4PageController::AJAX)); break; } } } } } static function getOption($option){ if(empty(self::$settings)) self::$settings = new am4_Settings_Config (); return self::$settings->get($option); } static function getAmemberPath(){ return self::getOption("path"); } static function getAmemberURL(){ return self::getOption("url"); } static function selfURL($encode = true){ if(defined('DOING_AJAX')){ $url = $_SERVER['HTTP_REFERER']; }else{ if(!isset($_SERVER['REQUEST_URI'])){ $serverrequri = $_SERVER['PHP_SELF']; }else{ $serverrequri = $_SERVER['REQUEST_URI']; } $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : ""; $protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s; $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]); $url = $protocol."://".$_SERVER['SERVER_NAME'].$port.$serverrequri; } return ($encode ? base64_encode($url) : $url); } static function getLoginURL($redirect_back = true){ if($redirect_back){ $params = array( '_amember_redirect_url' => self::selfURL() ); $params = http_build_query($params, '', '&'); } return self::getAPI()->getLoginURL().($params ? "?".$params : ""); } static function initAPI($path=''){ $path = $path ? $path : self::getAmemberPath(); if($path === false) throw new Exception(__('aMember path is empty', 'am4-plugin')); if(!is_file($lite = $path.'/library/Am/Lite.php')) { throw new Exception(__('Specified path is not an aMember installation', 'am4-plugin')); } if(!class_exists('Am_Lite'))require_once($lite); } /** * * @return Am_Lite */ static function getAPI(){ if(!self::$api){ try{ self::initAPI(); self::$api = Am_Lite::getInstance(); }catch(Exception $e){ return false; } } return self::$api; } static function isConfigured(){ if(!self::getAPI()) return false; else return true; } static function getAMProducts(){ if(!array_key_exists("products", self::$cache)){ self::$cache['products'] = self::getAPI()->getProducts(false); foreach (self::$cache['products'] as $id => $title) self::$cache['products'][$id] = sprintf('(%d) %s', $id, $title); } return self::$cache['products']; } static function getAMCategories(){ if(!array_key_exists("categories", self::$cache)){ self::$cache['categories'] = self::getAPI()->getCategories(); } return self::$cache['categories']; } static function getWpRoles($skip_admin=false){ $roles = new WP_Roles; $ret = array(); foreach($roles->roles as $k=>$v){ if($skip_admin && ($k == 'administrator')) continue; $ret[$k] = @$v['name']; } return $ret; } static function skipProtection(){ // Fix for NextGen plugin if(!function_exists('wp_get_current_user')) return false; $current_user = wp_get_current_user(); if(!$current_user) return false; $master_roles = self::getOption('disable_protection'); $master_roles = array_merge((array) $master_roles, array('administrator')); if(array_intersect($master_roles, $current_user->roles)) return true; return false; } } //if(!defined('AM_VERSION')) am4PluginsManager::init();PK\.8.8]default/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/widgets.phpnu[ jQuery(document).ready(function($){ $('.am4-ajax-widget').each(function(){ $(this).load('{$ajax_url}', { action: 'am4-show-widget', id: $(this).attr('id') }); }); }); CUT; }); } function showWidget() { list(,$id) = explode('-', sanitize_key(@$_POST['id'])); if($id){ $settings = get_option('widget_am4login'); if(isset($settings[$id]) && is_array($settings[$id])){ echo the_widget('am4Widget_login', $settings[$id]); } } exit; } function action_WidgetsInit() { foreach(get_declared_classes() as $c) { if (preg_match("/am4Widget_\S+/", $c)) { register_widget($c); } } } function showWidgetProtectionBlock($widget, $instance) { $view = new am4View("widget_protection"); $view->assign("instance", $instance); $view->assign("widget", $widget); $view->render(); } function isWidgetAvailable($widget, $instance) { $api = am4PluginsManager::getAPI(); // Allow to see all widgets for admin users; if(am4PluginsManager::skipProtection()) return true; if(in_array('guest', (array)$instance['access'])){ return $api->isLoggedIn() ? false : true; } // Check access options; $access = new am4UserAccess(); $not_have = true; if (in_array('not_have', (array)$instance['access'])) { if ($access->allFalse(am4AccessRequirement::createRequirements($instance['not_have']))) { $not_have = true; } else { $not_have = false; } } $have = true; if (in_array('have', (array)$instance['access'])) { if ($access->anyTrue(am4AccessRequirement::createRequirements($instance['have']))){ $have = true; } else { $have = false; } } return $have && $not_have; } } class am4Widget_login extends WP_Widget { protected $elements; function __construct() { parent::__construct(false, __("aMember Widget", 'am4-plugin'),array('classname' => 'widget_text', 'description' => __('Login form and aMember subscriptions links', 'am4-plugin'))); $this->addFormElement("text", 'welcome_title', __('Welcome Title:', 'am4-plugin'), __('Welcome', 'am4-plugin')); $this->addFormElement("text", 'before_login_title', __('Before Login Title:', 'am4-plugin'), __('Login', 'am4-plugin')); $this->addFormElement("text", 'after_login_title', __('After Login Title:', 'am4-plugin'), __('Your Subscriptions', 'am4-plugin')); $this->addFormElement("text", 'password_title', __('Password Title', 'am4-plugin'), __('Password', 'am4-plugin')); $this->addFormElement("text", 'username_title', __('Username Title:', 'am4-plugin'), __('Login', 'am4-plugin')); $this->addFormElement("text", 'login_button_title', __('Login Button Title:', 'am4-plugin'), __('Login', 'am4-plugin')); $this->addFormElement("text", 'register_link_title', __('Register Link Title:', 'am4-plugin') , __('Signup Here', 'am4-plugin')); $this->addFormElement("text", 'lost_password_title', __('Lost Password Title:', 'am4-plugin'), __('Lost Password', 'am4-plugin')); $this->addFormElement("text", 'renew_subscription_title', __('Renew Subscription Title:', 'am4-plugin'),__('Renew Subscription', 'am4-plugin')); $this->addFormElement("text", 'dashboard_title', __('Dashboard Link Title:', 'am4-plugin'),__('Dashboard', 'am4-plugin')); $this->addFormElement("text", 'payment_history_title', __('Payment History Title:', 'am4-plugin'), __('Payment History', 'am4-plugin')); $this->addFormElement("text", 'logout_title', __('Logout Title:', 'am4-plugin'), __('Logout', 'am4-plugin')); $this->addFormElement("text", 'change_profile_title', __('Change Profile Title:', 'am4-plugin'), __('Edit Profile', 'am4-plugin')); $this->addFormElement("text", 'signup_page_url', __('Signup Page URL', 'am4-plugin') , am4PluginsManager::getAPI()->getSignupURL()); $this->addFormElement("text", 'renewal_page_url', __('Renewal Page URL', 'am4-plugin') , am4PluginsManager::getAPI()->getSignupURL()); $this->addFormElement("text", 'dashboard_page_url', __('Dashboard Page URL', 'am4-plugin') , am4PluginsManager::getAmemberURL()."/member"); $this->addFormElement("text", 'lost_password_page_url', __('Lost Password Page URL', 'am4-plugin'), am4PluginsManager::getAPI()->getSendpassURL()); $this->addFormElement("text", 'profile_page_url', __('Profile Page URL', 'am4-plugin') , am4PluginsManager::getAPI()->getProfileURL()); $this->addFormElement("text", 'history_page_url', __('Payment History Page URL', 'am4-plugin'), am4PluginsManager::getAmemberURL()."/member/payment-history"); $this->addFormElement("text", 'logout_page_url', __('Logout page URL', 'am4-plugin') , am4PluginsManager::getAPI()->getLogoutURL()); $this->addFormElement("checkbox",'amember_links', __('Active Subscriptions Links', 'am4-plugin'), 1); $this->addFormElement("checkbox",'renew_subscription_link', __('Renew subscription Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'dashboard_link', __('Member Dashboard Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'payment_history_link', __('Payment History Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'logout_link', __('Logout Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'register_link', __('Register Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'forgot_password_link', __('Forgot Password Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'change_profile_link', __('Change Profile Link', 'am4-plugin'), 1); $this->addFormElement("checkbox",'follow_amember_redirect_rules', __('Follow aMember redirect Rules', 'am4-plugin'),0); $this->addFormElement('checkbox', 'ajax_widget', __('Show ajax version of widget', 'am4-plugin'), 0); } function addFormElement($type, $name, $title, $default) { $this->elements[$type][$name] = array('type'=>$type, 'name'=>$name,'title'=>$title, 'default'=>$default); } function showElements($instance, $type) { foreach ($this->elements[$type] as $k=>$v){ switch ($type) { case 'text': $this->form_text_element($instance, $v['name'], $v['title']); break; case 'checkbox': $this->form_checkbox_element($instance, $v['name'], $v['title']); break; default: throw new Exception('Unknown element type: '.$type); } } } // Get string if defained; function load_defaults($instance) { $_d = array(); foreach ($this->elements as $v){ foreach ($v as $elem) { $_d[$elem['name']] = $elem['default']; } } $instance = array_merge($_d, $instance); foreach($instance as $k=>$v){ $instance[$k] = is_string($v) ? esc_attr($v) : $v; } return $instance; } function form_text_element($instance, $name, $text) { ?>


      load_defaults($instance); $this->showElements($instance, "text"); ?>


      showElements($instance, "checkbox"); ?>
      load_defaults($instance); $api = am4PluginsManager::getAPI(); extract($args); $before_login_title = apply_filters('widget_title', $instance['before_login_title']); $after_login_title = apply_filters('widget_title', $instance['after_login_title']); if ($api->isLoggedIn()) { $title = $after_login_title; } else { $title = $before_login_title; } $ajax_widget = @$instance['ajax_widget']; if($ajax_widget) $before_widget = preg_replace('/class="/', "class=\"am4-ajax-widget ", $before_widget, 1); if(!defined('DOING_AJAX')) print $before_widget; if(!$ajax_widget || defined('DOING_AJAX')) { print $before_title.$title.$after_title; if($api->isLoggedIn()) $this->after_login_widget($instance); else $this->before_login_widget($instance); } if(!defined('DOING_AJAX')) print $after_widget; } function before_login_widget($instance) { // Login form here $view = new am4View("widget_login_form"); $view->assign("instance",$instance); $view->render(); } function after_login_widget($instance) { global $current_user; // Get current user's subscription and show usefull links; $amember_api = am4PluginsManager::getAPI(); $view = new am4View("widget_after_login"); $view->assign("instance",$instance); if($amember_api->isLoggedIn()){ $view->assign("user", $amember_api->getUser()); $view->assign("links", array_filter((array)$amember_api->getUserLinks())); } $view->assign('isLoggedIn', $amember_api->isLoggedIn()); $view->render(); } } include_once ABSPATH . WPINC . "/default-widgets.php"; class am4Widget_text extends WP_Widget_Text { function __construct() { $widget_ops = array('classname' => 'widget_text', 'description' => __('Arbitrary text or HTML', 'am4-plugin')); $control_ops = array('width' => 400, 'height' => 350); WP_Widget::__construct('amember_text', __('aMember Text Widget', 'am4-plugin'),$widget_ops, $control_ops); } function form($instance) { parent::form($instance); am4PluginsManager::get('widgets')->showWidgetProtectionBlock($this, $instance); } function update($new_instance, $old_instance) { $instance = parent::update($new_instance, $old_instance); $instance['access'] = $new_instance['access']; $instance['have'] = $new_instance['have']; $instance['not_have'] = $new_instance['not_have']; return $instance; } function get_field_name($field_name,$is_array=false) { if ($is_array) { return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . '][]'; } else { return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']'; } } function widget($args, $instance) { global $current_user; if(am4PluginsManager::get("widgets")->isWidgetAvailable($this, $instance)){ $instance['text'] = do_shortcode($instance['text']); return parent::widget($args, $instance); } } } class am4Widget_menu extends WP_Nav_Menu_Widget { function __construct() { $widget_ops = array('description' => __('Custom Menu with aMember protection settings', 'am4-plugin')); WP_Widget::__construct('amember_menu', __('aMember menu Widget', 'am4-plugin'), $widget_ops); } function form($instance) { parent::form($instance); am4PluginsManager::get('widgets')->showWidgetProtectionBlock($this, $instance); } function update($new_instance, $old_instance) { $instance = parent::update($new_instance, $old_instance); $instance['access'] = $new_instance['access']; $instance['have'] = $new_instance['have']; $instance['not_have'] = $new_instance['not_have']; return $instance; } function get_field_name($field_name,$is_array=false) { if ($is_array) { return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . '][]'; } else { return 'widget-' . $this->id_base . '[' . $this->number . '][' . $field_name . ']'; } } function widget($args, $instance) { global $current_user; if(am4PluginsManager::get("widgets")->isWidgetAvailable($this, $instance)){ return parent::widget($args, $instance); } } }PK\7$##bdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/js/dirbrowser.jsnu[ /* * DirBrowser * * directory browser, this plugin should be used with input elements only * works together with dirbrowser.php * * @param urlField The jQuery selector for another field * that is to be updated with the url of selected folder from the DirBrowser * */ ;(function($) { $.fn.dirBrowser = function(inParam) { return this.each(function(){ var browser = this; if ($(browser).data('initialized')) { return; } else { if (this.type != 'text') { throw new Error('Element should be input-text to use browser for it'); } $(browser).data('initialized', 1); } var param = $.extend({ urlField : '', rootUrl : window.rootUrl }, inParam); /* * Store response from server side script here, * use this array while handling rearrange action */ var dirData = new Array; var sortDir = 'asc'; var sortField = null; var $div = $('
      ').hide() $(browser).after( $div ) function loadDirs(dir, selected) { $div.html('
      '); v = {}; if (dir) { v['dir'] = dir; if (selected) { v['selected'] = selected; } } am_post( 'browse', v, function(data, textStatus){ dirData = $.parseJSON(data); $div.empty().append( drawBrowser(dirData) ) } ); } function drawCurrentDir(currentDir, separator) { var $div = $('
      ').addClass('path'); var $a = $('').attr('href', 'javascript:;'); var $el; for(var i in currentDir) { if (i>0) { $div.append(' ' + separator + ' '); } if (currentDir[i].path) { $el = $a.clone().append(currentDir[i].name).data('path', currentDir[i].path).click(function(){ loadDirs($(this).data('path')) }) } else { $el = $(document.createTextNode(currentDir[i].name)) } $div.append($el) } return $div; } function drawBrowser(data) { return $('
      ').append( drawCurrentDir(data.currentDir, data.separator) ).append( drawDirList(data.dirList, data.prevDir) ).addClass('dir-browser').append($('
      Click radio-button to choose a directory')); } function drawHeaderCell(title, name, isSortable) { if (isSortable) { out = $('').attr({ href : 'javascript:;' }).append(title).addClass('a-sort').data('name', name); if (sortField == name) { out.addClass('sorted-' + sortDir); out.data('sortDir', sortDir); } out.click(function(){ if ($(this).data('sortDir') == 'asc') { $(this).data('sortDir', 'desc'); sortDir = 'desc'; } else { $(this).data('sortDir', 'asc'); sortDir = 'asc'; } sortField = $(this).data('name'); $div.empty().append( drawBrowser(dirData) ) }) } else { out = title; } return out; } function drawDirList(files, prevDir) { $table = $('
      ').css({width:'100%', overflow: 'auto'}); $table.addClass('grid'); $tr = $(''); $th = $(''); $td = $(''); $radio = $('').attr({ name : '___browser___', type : 'radio' }); $a = $('').attr({ href : 'javascript:;' }); $table.append( $tr.clone().append( $th.clone() ).append( $th.clone().append( drawHeaderCell('Name', 'name', true) ) ).append( $th.clone().append( drawHeaderCell('Mode', 'perm', false) ) ).append( $th.clone().append( drawHeaderCell('Created', 'created', true) ) ) ); var $el; if (prevDir) { $el = $(document.createTextNode( prevDir.name ? 'Previous Directory ' + '(' + prevDir.name + ')' : 'Root' )); if (prevDir.path) { $el = $a.clone().append( $el.clone() ).click(function(){ loadDirs($(this).closest('tr').data('path')); }); } $table.append( $tr.clone().data('path', prevDir.path).append( $td.clone().attr('colspan', 4).append( $el ) ) ) } if (sortField!==null) { files.sort(function(a,b){ if (a[sortField] > b[sortField]) { return sortDir == 'asc' ? 1 : -1; } if (a[sortField] < b[sortField]) { return sortDir == 'asc' ? -1 : 1; } return 0; }); } for (var i in files) { $f_radio = $radio.clone().click(function(){ $(browser).val($(this).closest('tr').data('path')); $(browser).change(); if (param.urlField) { var url = $(this).closest('tr').data('url'); if (url) { $(param.urlField).val(url).addClass('disabled');//.attr('disabled', 'disabled'); } else { $(param.urlField).val('').removeClass('disabled');//.removeAttr('disabled'); } } $div.dialog('close'); }); if (files[i].selected) { $f_radio.prop('checked', true); } $table.append( $tr.clone().data('path', files[i].path).data('url', files[i].url).append( $td.clone().attr('width', '1%').append( $f_radio ) ).append( $td.clone().append( $a.clone().append(files[i].name) ).click(function(){ loadDirs($(this).closest('tr').data('path')); }) ).append( $td.clone().append(files[i].perm) ).append( $td.clone().append(files[i].created) ) ); } return $table; } $link = $('browse...').attr('href', 'javascript:;'); $(browser).after($link); $link.before(' '); $link.click(function(){ $div.dialog({ modal : true, title : "Directory Browser", width : 600, height: 500, position : ['center', 100], buttons : { Cancel : function(){ $(this).dialog("close") } }, open : function(){ loadDirs($(browser).val(), true); }, close : function() { $div.empty(); } }); }) }) } })(jQuery);PK\_default/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/js/tinymce.jsnu[(function(){ tinymce.create('tinymce.plugins.am4plugin', { init : function(ed, url){ ed.addCommand('amInsertaMemberShortcodeWindow', function(){ /////// Now open php file var win = window.dialogArguments || opener || parent || top; r = ed.windowManager.open({ url : url+'/../shortcode_select.php', width : 800, height : 500, inline : 1 }); }); ed.addButton('am4button', { title : 'aMember shortcodes', image : '../wp-content/plugins/amember4/img/lock.png', cmd : "amInsertaMemberShortcodeWindow" }); } }); // Register plugin with a short name tinymce.PluginManager.add('am4plugin', tinymce.plugins.am4plugin); })(); PK\e F@@ndefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/js/jquery.ui.autocomplete.jsnu[/* * jQuery UI Autocomplete 1.8.16 * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Autocomplete * * Depends: * jquery.ui.core.js * jquery.ui.widget.js * jquery.ui.position.js */ (function( $, undefined ) { // used to prevent race conditions with remote data sources var requestIndex = 0; $.widget( "ui.autocomplete", { options: { appendTo: "body", autoFocus: false, delay: 300, minLength: 1, position: { my: "left top", at: "left bottom", collision: "none" }, source: null }, pending: 0, _create: function() { var self = this, doc = this.element[ 0 ].ownerDocument, suppressKeyPress; this.element .addClass( "ui-autocomplete-input" ) .attr( "autocomplete", "off" ) // TODO verify these actually work as intended .attr({ role: "textbox", "aria-autocomplete": "list", "aria-haspopup": "true" }) .bind( "keydown.autocomplete", function( event ) { if ( self.options.disabled || self.element.propAttr( "readOnly" ) ) { return; } suppressKeyPress = false; var keyCode = $.ui.keyCode; switch( event.keyCode ) { case keyCode.PAGE_UP: self._move( "previousPage", event ); break; case keyCode.PAGE_DOWN: self._move( "nextPage", event ); break; case keyCode.UP: self._move( "previous", event ); // prevent moving cursor to beginning of text field in some browsers event.preventDefault(); break; case keyCode.DOWN: self._move( "next", event ); // prevent moving cursor to end of text field in some browsers event.preventDefault(); break; case keyCode.ENTER: case keyCode.NUMPAD_ENTER: // when menu is open and has focus if ( self.menu.active ) { // #6055 - Opera still allows the keypress to occur // which causes forms to submit suppressKeyPress = true; event.preventDefault(); } //passthrough - ENTER and TAB both select the current element case keyCode.TAB: if ( !self.menu.active ) { return; } self.menu.select( event ); break; case keyCode.ESCAPE: self.element.val( self.term ); self.close( event ); break; default: // keypress is triggered before the input value is changed clearTimeout( self.searching ); self.searching = setTimeout(function() { // only search if the value has changed if ( self.term != self.element.val() ) { self.selectedItem = null; self.search( null, event ); } }, self.options.delay ); break; } }) .bind( "keypress.autocomplete", function( event ) { if ( suppressKeyPress ) { suppressKeyPress = false; event.preventDefault(); } }) .bind( "focus.autocomplete", function() { if ( self.options.disabled ) { return; } self.selectedItem = null; self.previous = self.element.val(); }) .bind( "blur.autocomplete", function( event ) { if ( self.options.disabled ) { return; } clearTimeout( self.searching ); // clicks on the menu (or a button to trigger a search) will cause a blur event self.closing = setTimeout(function() { self.close( event ); self._change( event ); }, 150 ); }); this._initSource(); this.response = function() { return self._response.apply( self, arguments ); }; this.menu = $( "
        " ) .addClass( "ui-autocomplete" ) .appendTo( $( this.options.appendTo || "body", doc )[0] ) // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown) .mousedown(function( event ) { // clicking on the scrollbar causes focus to shift to the body // but we can't detect a mouseup or a click immediately afterward // so we have to track the next mousedown and close the menu if // the user clicks somewhere outside of the autocomplete var menuElement = self.menu.element[ 0 ]; if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { setTimeout(function() { $( document ).one( 'mousedown', function( event ) { if ( event.target !== self.element[ 0 ] && event.target !== menuElement && !$.ui.contains( menuElement, event.target ) ) { self.close(); } }); }, 1 ); } // use another timeout to make sure the blur-event-handler on the input was already triggered setTimeout(function() { clearTimeout( self.closing ); }, 13); }) .menu({ focus: function( event, ui ) { var item = ui.item.data( "item.autocomplete" ); if ( false !== self._trigger( "focus", event, { item: item } ) ) { // use value to match what will end up in the input, if it was a key event if ( /^key/.test(event.originalEvent.type) ) { self.element.val( item.value ); } } }, selected: function( event, ui ) { var item = ui.item.data( "item.autocomplete" ), previous = self.previous; // only trigger when focus was lost (click on menu) if ( self.element[0] !== doc.activeElement ) { self.element.focus(); self.previous = previous; // #6109 - IE triggers two focus events and the second // is asynchronous, so we need to reset the previous // term synchronously and asynchronously :-( setTimeout(function() { self.previous = previous; self.selectedItem = item; }, 1); } if ( false !== self._trigger( "select", event, { item: item } ) ) { self.element.val( item.value ); } // reset the term after the select event // this allows custom select handling to work properly self.term = self.element.val(); self.close( event ); self.selectedItem = item; }, blur: function( event, ui ) { // don't set the value of the text field if it's already correct // this prevents moving the cursor unnecessarily if ( self.menu.element.is(":visible") && ( self.element.val() !== self.term ) ) { self.element.val( self.term ); } } }) .zIndex( this.element.zIndex() + 1 ) // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781 .css({ top: 0, left: 0 }) .hide() .data( "menu" ); if ( $.fn.bgiframe ) { this.menu.element.bgiframe(); } }, destroy: function() { this.element .removeClass( "ui-autocomplete-input" ) .removeAttr( "autocomplete" ) .removeAttr( "role" ) .removeAttr( "aria-autocomplete" ) .removeAttr( "aria-haspopup" ); this.menu.element.remove(); $.Widget.prototype.destroy.call( this ); }, _setOption: function( key, value ) { $.Widget.prototype._setOption.apply( this, arguments ); if ( key === "source" ) { this._initSource(); } if ( key === "appendTo" ) { this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] ) } if ( key === "disabled" && value && this.xhr ) { this.xhr.abort(); } }, _initSource: function() { var self = this, array, url; if ( $.isArray(this.options.source) ) { array = this.options.source; this.source = function( request, response ) { response( $.ui.autocomplete.filter(array, request.term) ); }; } else if ( typeof this.options.source === "string" ) { url = this.options.source; this.source = function( request, response ) { if ( self.xhr ) { self.xhr.abort(); } self.xhr = $.ajax({ url: url, data: request, dataType: "json", autocompleteRequest: ++requestIndex, success: function( data, status ) { if ( this.autocompleteRequest === requestIndex ) { response( data ); } }, error: function() { if ( this.autocompleteRequest === requestIndex ) { response( [] ); } } }); }; } else { this.source = this.options.source; } }, search: function( value, event ) { value = value != null ? value : this.element.val(); // always save the actual value, not the one passed as an argument this.term = this.element.val(); if ( value.length < this.options.minLength ) { return this.close( event ); } clearTimeout( this.closing ); if ( this._trigger( "search", event ) === false ) { return; } return this._search( value ); }, _search: function( value ) { this.pending++; this.element.addClass( "ui-autocomplete-loading" ); this.source( { term: value }, this.response ); }, _response: function( content ) { if ( !this.options.disabled && content && content.length ) { content = this._normalize( content ); this._suggest( content ); this._trigger( "open" ); } else { this.close(); } this.pending--; if ( !this.pending ) { this.element.removeClass( "ui-autocomplete-loading" ); } }, close: function( event ) { clearTimeout( this.closing ); if ( this.menu.element.is(":visible") ) { this.menu.element.hide(); this.menu.deactivate(); this._trigger( "close", event ); } }, _change: function( event ) { if ( this.previous !== this.element.val() ) { this._trigger( "change", event, { item: this.selectedItem } ); } }, _normalize: function( items ) { // assume all items have the right format when the first item is complete if ( items.length && items[0].label && items[0].value ) { return items; } return $.map( items, function(item) { if ( typeof item === "string" ) { return { label: item, value: item }; } return $.extend({ label: item.label || item.value, value: item.value || item.label }, item ); }); }, _suggest: function( items ) { var ul = this.menu.element .empty() .zIndex( this.element.zIndex() + 1 ); this._renderMenu( ul, items ); // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate this.menu.deactivate(); this.menu.refresh(); // size and position menu ul.show(); this._resizeMenu(); ul.position( $.extend({ of: this.element }, this.options.position )); if ( this.options.autoFocus ) { this.menu.next( new $.Event("mouseover") ); } }, _resizeMenu: function() { var ul = this.menu.element; ul.outerWidth( Math.max( ul.width( "" ).outerWidth(), this.element.outerWidth() ) ); }, _renderMenu: function( ul, items ) { var self = this; $.each( items, function( index, item ) { self._renderItem( ul, item ); }); }, _renderItem: function( ul, item) { return $( "
      • " ) .data( "item.autocomplete", item ) .append( $( "" ).text( item.label ) ) .appendTo( ul ); }, _move: function( direction, event ) { if ( !this.menu.element.is(":visible") ) { this.search( null, event ); return; } if ( this.menu.first() && /^previous/.test(direction) || this.menu.last() && /^next/.test(direction) ) { this.element.val( this.term ); this.menu.deactivate(); return; } this.menu[ direction ]( event ); }, widget: function() { return this.menu.element; } }); $.extend( $.ui.autocomplete, { escapeRegex: function( value ) { return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }, filter: function(array, term) { var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); return $.grep( array, function(value) { return matcher.test( value.label || value.value || value ); }); } }); }( jQuery )); /* * jQuery UI Menu (not officially released) * * This widget isn't yet finished and the API is subject to change. We plan to finish * it for the next release. You're welcome to give it a try anyway and give us feedback, * as long as you're okay with migrating your code later on. We can help with that, too. * * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) * Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license * * http://docs.jquery.com/UI/Menu * * Depends: * jquery.ui.core.js * jquery.ui.widget.js */ (function($) { $.widget("ui.menu", { _create: function() { var self = this; this.element .addClass("ui-menu ui-widget ui-widget-content ui-corner-all") .attr({ role: "listbox", "aria-activedescendant": "ui-active-menuitem" }) .click(function( event ) { if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) { return; } // temporary event.preventDefault(); self.select( event ); }); this.refresh(); }, refresh: function() { var self = this; // don't refresh list items that are already adapted var items = this.element.children("li:not(.ui-menu-item):has(a)") .addClass("ui-menu-item") .attr("role", "menuitem"); items.children("a") .addClass("ui-corner-all") .attr("tabindex", -1) // mouseenter doesn't work with event delegation .mouseenter(function( event ) { self.activate( event, $(this).parent() ); }) .mouseleave(function() { self.deactivate(); }); }, activate: function( event, item ) { this.deactivate(); if (this.hasScroll()) { var offset = item.offset().top - this.element.offset().top, scroll = this.element.scrollTop(), elementHeight = this.element.height(); if (offset < 0) { this.element.scrollTop( scroll + offset); } else if (offset >= elementHeight) { this.element.scrollTop( scroll + offset - elementHeight + item.height()); } } this.active = item.eq(0) .children("a") .addClass("ui-state-hover") .attr("id", "ui-active-menuitem") .end(); this._trigger("focus", event, { item: item }); }, deactivate: function() { if (!this.active) { return; } this.active.children("a") .removeClass("ui-state-hover") .removeAttr("id"); this._trigger("blur"); this.active = null; }, next: function(event) { this.move("next", ".ui-menu-item:first", event); }, previous: function(event) { this.move("prev", ".ui-menu-item:last", event); }, first: function() { return this.active && !this.active.prevAll(".ui-menu-item").length; }, last: function() { return this.active && !this.active.nextAll(".ui-menu-item").length; }, move: function(direction, edge, event) { if (!this.active) { this.activate(event, this.element.children(edge)); return; } var next = this.active[direction + "All"](".ui-menu-item").eq(0); if (next.length) { this.activate(event, next); } else { this.activate(event, this.element.children(edge)); } }, // TODO merge with previousPage nextPage: function(event) { if (this.hasScroll()) { // TODO merge with no-scroll-else if (!this.active || this.last()) { this.activate(event, this.element.children(".ui-menu-item:first")); return; } var base = this.active.offset().top, height = this.element.height(), result = this.element.children(".ui-menu-item").filter(function() { var close = $(this).offset().top - base - height + $(this).height(); // TODO improve approximation return close < 10 && close > -10; }); // TODO try to catch this earlier when scrollTop indicates the last page anyway if (!result.length) { result = this.element.children(".ui-menu-item:last"); } this.activate(event, result); } else { this.activate(event, this.element.children(".ui-menu-item") .filter(!this.active || this.last() ? ":first" : ":last")); } }, // TODO merge with nextPage previousPage: function(event) { if (this.hasScroll()) { // TODO merge with no-scroll-else if (!this.active || this.first()) { this.activate(event, this.element.children(".ui-menu-item:last")); return; } var base = this.active.offset().top, height = this.element.height(); result = this.element.children(".ui-menu-item").filter(function() { var close = $(this).offset().top - base + height - $(this).height(); // TODO improve approximation return close < 10 && close > -10; }); // TODO try to catch this earlier when scrollTop indicates the last page anyway if (!result.length) { result = this.element.children(".ui-menu-item:first"); } this.activate(event, result); } else { this.activate(event, this.element.children(".ui-menu-item") .filter(!this.active || this.first() ? ":last" : ":first")); } }, hasScroll: function() { return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]("scrollHeight"); }, select: function( event ) { this._trigger("selected", event, { item: this.active }); } }); }(jQuery)); PK\2TKKfdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/settings.phtmlnu[

        checkboxes('options[disable_protection][]', am4PluginsManager::getWpRoles(true) ,$options['disable_protection']);?>

        >

        PK\85"5"idefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/resourceaccess.jsnu[/* * To change this template, choose Tools | Templates * and open the template in the editor. */ /* * Folder Access editor JS code * includes LGPL outerClick library to speedup loading - you can use it for free according to LGPL * @author Alex Scott alex@cgi-central.net * @license for this JS file - LGPL */ ;(function($) { $.fn.resourceAccess = function(param) { return this.each(function(){ var without_period = param.without_period ; var resourceAccess = { mainDiv: this, currentEditor: null, currentEditorType: null, // 'start' or 'stop' startText : "start", stopText : "expiration", foreverText : "forever", getVarName : function(){ return $(this.mainDiv).data('varname'); }, textCallback : function (id, text, cl, start, stop){ var startText = start ? start : resourceAccess.startText; var stopText = (parseInt(stop) == -1 ? resourceAccess.foreverText : (stop ? stop : resourceAccess.stopText)); // encode text var div = document.createElement('div'); div.appendChild(document.createTextNode(text)); var encodedText = div.innerHTML; var divcont = $("
        "); var closelink = $("[X]").click(this.onXClickedRemoveLine); divcont.append(closelink); var clText = cl.charAt(0).toUpperCase() + cl.substr(1); divcont.append(" "+clText+" "+text+""); if(!without_period){ var astart = $(""+startText+"").click(this.onLinkClickedShowEditor); var astop = $(""+stopText+"").click(this.onLinkClickedShowEditor); divcont.append(document.createTextNode(" from "), astart, document.createTextNode(" to "), astop); } // Hiddens; divcont.append(""); divcont.append(""); divcont.append(""); return divcont; }, onPeriodChange: function() { if ($(this).val() == '' || $(this).val()==-1) { $(this).prev("input#resourceaccess-count").hide(); } else { $(this).prev("input#resourceaccess-count").show(); } }, hideEditor: function() { if (!resourceAccess.currentEditor) return; var isStart = $(resourceAccess.currentEditor).hasClass('resourceaccess-start'); resourceAccess.setCurrentEditorHidden( isStart, $(".resourceaccess-edit #resourceaccess-count",this.mainDiv).val(), $(".resourceaccess-edit #resourceaccess-unit",this.mainDiv).val() ); $(".resourceaccess-edit #resourceaccess-unit", this.mainDiv).change(); resourceAccess.setLinkTextBasedOnHidden($(resourceAccess.currentEditor)); $('.resourceaccess-edit',this.mainDiv).remove(); $(resourceAccess.currentEditor).show(); resourceAccess.currentEditor = null; }, openEditor: function(editor) { var p = $(editor).parent(".resourceaccess-item"); editor.parentDiv = p; var isStart = $(editor).hasClass('resourceaccess-start'); resourceAccess.currentEditor = editor; resourceAccess.currentEditorType = isStart ? 'start' : 'stop'; var text = $(""); var select = $(""); select.append(new Option(isStart ? resourceAccess.startText : resourceAccess.stopText, '')); select.append(new Option('-th day', 'd')); if (isStart) { var opt = new Option('-nd payment', 'p'); if (p.data('item_type') != 'product') $(opt).attr("disabled", true); // allow to select -nd payment only for products not cats select.append(opt); } if(!isStart) select.append(new Option('forever', '-1')); var span = $(""); span.append(text); span.append(select); span.bind("outerClick", resourceAccess.hideEditor); text.hide(); var val = resourceAccess.getCurrentEditorHidden(isStart); text.val(val[0]); select.val(val[1]); select.change(resourceAccess.onPeriodChange).change(); $(editor).hide().after(span); }, onSelectChangeAddOption: function(){ if (this.selectedIndex<=0) return; var selectedOption = this.options[this.selectedIndex]; if (!selectedOption || !selectedOption.value) return; var cl = $(selectedOption).closest("optgroup").attr("class").replace(/^(a-zA-Z0-9)+/, '$1'); resourceAccess.addItem(cl, selectedOption.value, selectedOption.text, "", ""); this.selectedIndex = null; }, addItem: function(cl, id, value, start, stop) { var div = resourceAccess.textCallback(id, value, cl, start, stop); div.data("item_id", id); div.data("item_type", cl); $("."+cl+"-list", resourceAccess.mainDiv).append(div); $("select.category optgroup."+ cl +" option[value='"+id+"']", resourceAccess.mainDiv).attr('disabled', 'disabled'); }, onXClickedRemoveLine: function(){ var item = $(this).parent("div.resourceaccess-item"); $("."+item.data('item_type')+" option[value='"+item.data('item_id')+"']", resourceAccess.mainDiv).attr('disabled', ''); item.remove(); }, onLinkClickedShowEditor: function(e){ e.stopPropagation(); if (resourceAccess.currentEditor != this) { resourceAccess.hideEditor(); resourceAccess.openEditor(this); } }, init: function() { $(this.mainDiv).on("change", "select.category", this.onSelectChangeAddOption); var stored = {'product' : {}, 'category' : {}}; eval('stored = ' + $(".resourceaccess-init", this.mainDiv).val()); for (cl in stored) for (id in stored[cl]) { var item = stored[cl][id]; this.addItem(cl, id, item.title, item.start, item.stop); } }, /** return array [count:{'',0-9+}, unit:{'','d', 'm}] */ getCurrentEditorHidden: function(forStart) { var hiddenVal = $(".resourceaccess-hidden[name$='["+(forStart?'start':'stop')+"]']", this.currentEditor.parentDiv).val(); var ret = [ isNaN(parseInt(hiddenVal)) ? 0 : (parseInt(hiddenVal) == -1 ? '' : parseInt(hiddenVal)), hiddenVal.replace(/^[0-9]+/, '') ]; return ret; }, setCurrentEditorHidden: function(forStart, count, unit) { var el = $(".resourceaccess-hidden[name$='["+(forStart?'start':'stop')+"]']", this.currentEditor.parentDiv); var set = ''; if (unit != '') { if (isNaN(parseInt(count))) { flashError("Incorrect integer value entered: please repeat input"); return false; } set = (unit == '-1' ? '-1' : "" + parseInt(count) + "" + unit); } el.val(set); }, setLinkTextBasedOnHidden: function(link) { var link = $(resourceAccess.currentEditor); var isStart = link.hasClass('resourceaccess-start'); var text = resourceAccess.getCurrentEditorHidden(isStart).join(''); if(parseInt(text) == -1) text = resourceAccess.foreverText; else if (text == '0') text = isStart ? resourceAccess.startText : resourceAccess.stopText; link.text(text); } }; resourceAccess.init(); }); } })(jQuery); PK\ڟvaEEmdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcodes_help.phtmlnu[getShortcodes() as $s) : ?>
        getDescription();?>
        getHelp();?>
        render(); ?> PK\У++hdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/admin_styles.cssnu[/* Document : admin-styles Created on : Apr 14, 2011, 3:42:29 PM Author : alexander Description: Will be included on all admin pages; */ /* TODO customize this sample style Syntax recommendation http://www.w3.org/TR/REC-CSS2/ */ .amember_error{ color : red; font-weight: bold; } #am-protection-error { color: red; font-weight: bold; } .amember-protection-block{ } .am4-additional-setting{ padding-left: 20px; } /* Shortcode styles */ .am4shortcode-block{ border-spacing: 4px; } .am4shortcode-block td{ padding: 0px 2px 0px 2px; align: left; vertical-align: top; height: 2.5em; font-size: 100%; } td.am4shortcode-syntax{ font-weight: bold; font-size: 100%; width:40% } td.am4shortcode-short{ font-size: 100%; width:60% } tr.am4shortcode-help{ display:none; } td.am4shortcode-help{ padding: 10px 10px 10px 40px; } .am4shortcode-help table{ border-spacing: 2px 10px; } .am4shortcode-help td,th{ vertical-align: top; text-align: left; font-size: 100%; } div.am4shortcode-help{ line-height: 120%; } .am4shortcode-help div{ margin-bottom : 2px; } div.am4show-build{ border: 1px solid black; padding: 3px 3px 3px 3px; } .am4shortcode { font-weight: bold; } PK\}yddefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/styles.phtmlnu[$value) : ?>

        PK\dȝodefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/widget_protection.phtmlnu[
        " value="guest" >
        " value="not_have" >
        resourceAccess($widget->id."not_have", @$instance['not_have'], $widget->get_field_name('not_have'), __('Select Products that user should not have', 'am4-plugin'), self::RESOURCE_ACCESS_SKIP_PERIOD);?>
        " value="have" >
        resourceAccess($widget->id."have", @$instance['have'], $widget->get_field_name('have'), __('Select Products that user should have', 'am4-plugin'),false);?>
        PK\v||odefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode_am4user.phtmlnu[

        [am4user]John Doe
        [am4user var=user_id]1
        [am4user var=login]johndoe
        [am4user var=email]johndoe@example.com
        [am4user var=name_f]John
        [am4user var=name_l]Doe
        [am4user var=city]New York
        [am4user var=state]NY
        [am4user var=zip]12334
        [am4user var=country]US
        [am4user var=phone]123-123-1234
        PK\V\4 4 ldefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/jquery.outerClick.jsnu[/** * jQuery custom event "outerClick". * @author David Brockman Smoliansky http://littleroom.se/ * @license GNU Lesser General Public License: http://creativecommons.org/licenses/LGPL/2.1/ * @version 1.1 * 2009/02/27 * * The outerClick event is fired when an element outside of the target element is clicked. * * Usage: * $(selector).bind("outerClick", fn); // Bind the function fn to the outerClick event on each of the matched elements. * $(selector).outerClick(fn); // Bind the function fn to the outerClick event on each of the matched elements. * $(selector).trigger("outerClick"); // Trigger the outerClick event on each of the matched elements. * $(selector).outerClick(); // Trigger the outerClick event on each of the matched elements. * $(selector).unbind("outerClick", fn); // Unbind the function fn from the outerClick event on each of the matched elements. * $(selector).unbind("outerClick"); // Unbind all outerClick events from each of the matched elements. */ /*global jQuery */ (function ($, elements, OUTER_CLICK) { /** * Check if the event should be fired. * @param {Object} event The click event. * @private */ function check(event) { for (var i = 0, l = elements.length, target = event.target, el; i < l; i++) { el = elements[i]; if (el !== target && !(el.contains ? el.contains(target) : el.compareDocumentPosition ? el.compareDocumentPosition(target) & 16 : 1)) { $.event.trigger(OUTER_CLICK, event, el); } } } $.event.special[OUTER_CLICK] = { setup: function () { var i = elements.length; if (!i) { $.event.add(document, 'click', check); } if ($.inArray(this, elements) < 0) { elements[i] = this; } }, teardown: function () { var i = $.inArray(this, elements); if (i >= 0) { elements.splice(i, 1); if (!elements.length) { $.event.remove(document, 'click', check); } } } }; /** * Event helper outerClick * * @param {Function} [fn] A function to bind to the outerClick event on each of the matched elements. * If fn is omitted the event is triggered. * @return {jQuery} Returns the jQuery object. */ $.fn[OUTER_CLICK] = function (fn) { return fn ? this.bind(OUTER_CLICK, fn) : this.trigger(OUTER_CLICK); }; })(jQuery, [], 'outerClick');PK\ܟf fdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/category.phtmlnu[
        name="options[_action_cat]" value="show">
        name="options[_action_cat]" value="page">
        name="options[_action_cat]" value="redirect">
        name="options[_action_cat]" value="login">

        name="options[_action_cat_menu]" value="hide">
        name="options[_action_cat_menu]" value="show">
        PK\u% ddefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode.jsnu[jQuery(document).ready(function(){ jQuery('.am4shortcode').shortcodemenu(); }); ;(function($) { $.fn.shortcodemenu = function(param) { return this.each(function(){ var menu = { state : false, show : function(){ if(jQuery(this).find('.am4shortcode-menu').length) return; var s = jQuery(this).find('.am4shortcode'); var d = jQuery("
        "); d.appendTo(this); var ins = jQuery("insert"); var copy = jQuery("copy"); var open = jQuery("open"); d.append(ins, " | ", copy); if(s.hasClass("expandable")){ d.append(" | ", open); open.click(menu.open); } ins.click(menu.insert); copy.click(menu.copy); }, hide : function(){ jQuery('.am4shortcode-menu').remove(); }, open : function(e){ e.preventDefault(); jQuery('tr.am4shortcode-help').hide(); jQuery(this).parents('tr').next('tr').show(); }, copy : function(e){ }, insert : function(e){ e.preventDefault(); var win = window.dialogArguments || opener || parent || top; var s = jQuery(this).parent().prev('.am4shortcode'); menu.send_to_editor(s.html()); }, send_to_editor : function(text){ var ed; var win = window.dialogArguments || opener || parent || top; var reg = /(.*)(\[\/\w+\])$/; var close_tag = text.match(reg); if ( typeof win.tinyMCE != 'undefined' && ( ed = win.tinyMCE.activeEditor ) && !ed.isHidden() ) { // restore caret position on IE if(ed.selection && (content = ed.selection.getContent())&&close_tag){ ed.selection.setContent(close_tag[1]+content+close_tag[2]); }else{ ed.execCommand('mceInsertContent', false, text); } } else if ( typeof edInsertContent == 'function' ) { edInsertContent(edCanvas, text); } else { jQuery( edCanvas ).val( jQuery( edCanvas ).val() + text ); } } } jQuery(this).parent().hover(menu.show, menu.hide); jQuery(this).click(menu.open); }); } })(jQuery); PK\eI^USSfdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/bulk_action.jsnu[function bulk_post(action, form){ am_post(action, {data : jQuery(form).serialize()}, function (){ jQuery("#am-protection-settings, #am-remove-protection").hide(200); jQuery("#am-protection-error").html("Setings updated").show(800); jQuery("#am-block").hide(2000); window.location.reload(); }); } jQuery(document).ready(function(){ var amember_block = jQuery("#am-block, #am-remove-protection"); var form = jQuery("#posts-filter"); a = amember_block.appendTo(form); jQuery('.wp-list-table input[type="checkbox"]').change(function (){ setTimeout(function(){ if(jQuery('.wp-list-table input[name^="post"]:checked').length) amember_block.show(); else amember_block.hide(); },100); }); jQuery('#am4-update-btn').click(function (e){ e.preventDefault(); bulk_post('save', this.form); }); jQuery("#am-remove-protection-link").click(function(e){ e.preventDefault(); bulk_post('remove', jQuery(this).parents("form").get()); }) });PK\&eeodefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/widget_login_form.phtmlnu[




        PK\ppdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode_am4guest.phtmlnu[


        [am4guest] [am4info var=loginurl] [/am4guest]

        PK\eWK&&hdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/protection.phtmlnu[
        style="display:none;">
        >
        getController())$controller->actionInput("save"); ?> PK\>mdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/bulk_protection.phtmlnu[ PK\d;kdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/errormessages.phtmlnu[getController()->isSimple();?>

        $option) : ?>
               


        getController()->actionInput('save');?>

        PK\ް++jdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/jquery.textarea.jsnu[/* * Tabby jQuery plugin version 0.12 * * Ted Devito - http://teddevito.com/demos/textarea.html * * Copyright (c) 2009 Ted Devito * * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following * conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ // create closure (function($) { // plugin definition $.fn.tabby = function(options) { //debug(this); // build main options before element iteration var opts = $.extend({}, $.fn.tabby.defaults, options); var pressed = $.fn.tabby.pressed; // iterate and reformat each matched element return this.each(function() { $this = $(this); // build element specific options var options = $.meta ? $.extend({}, opts, $this.data()) : opts; $this.bind('keydown',function (e) { var kc = $.fn.tabby.catch_kc(e); if (16 == kc) pressed.shft = true; /* because both CTRL+TAB and ALT+TAB default to an event (changing tab/window) that will prevent js from capturing the keyup event, we'll set a timer on releasing them. */ if (17 == kc) {pressed.ctrl = true; setTimeout("jQuery.fn.tabby.pressed.ctrl = false;",1000);} if (18 == kc) {pressed.alt = true; setTimeout("jQuery.fn.tabby.pressed.alt = false;",1000);} if (9 == kc && !pressed.ctrl && !pressed.alt) { e.preventDefault; // does not work in O9.63 ?? pressed.last = kc; setTimeout("jQuery.fn.tabby.pressed.last = null;",0); process_keypress ($(e.target).get(0), pressed.shft, options); return false; } }).bind('keyup',function (e) { if (16 == $.fn.tabby.catch_kc(e)) pressed.shft = false; }).bind('blur',function (e) { // workaround for Opera -- http://www.webdeveloper.com/forum/showthread.php?p=806588 if (9 == pressed.last) $(e.target).one('focus',function (e) {pressed.last = null;}).get(0).focus(); }); }); }; // define and expose any extra methods $.fn.tabby.catch_kc = function(e) { return e.keyCode ? e.keyCode : e.charCode ? e.charCode : e.which; }; $.fn.tabby.pressed = {shft : false, ctrl : false, alt : false, last: null}; // private function for debugging function debug($obj) { if (window.console && window.console.log) window.console.log('textarea count: ' + $obj.size()); }; function process_keypress (o,shft,options) { var scrollTo = o.scrollTop; //var tabString = String.fromCharCode(9); // gecko; o.setSelectionRange is only available when the text box has focus if (o.setSelectionRange) gecko_tab (o, shft, options); // ie; document.selection is always available else if (document.selection) ie_tab (o, shft, options); o.scrollTop = scrollTo; } // plugin defaults $.fn.tabby.defaults = {tabString : String.fromCharCode(9)}; function gecko_tab (o, shft, options) { var ss = o.selectionStart; var es = o.selectionEnd; // when there's no selection and we're just working with the caret, we'll add/remove the tabs at the caret, providing more control if(ss == es) { // SHIFT+TAB if (shft) { // check to the left of the caret first if ("\t" == o.value.substring(ss-options.tabString.length, ss)) { o.value = o.value.substring(0, ss-options.tabString.length) + o.value.substring(ss); // put it back together omitting one character to the left o.focus(); o.setSelectionRange(ss - options.tabString.length, ss - options.tabString.length); } // then check to the right of the caret else if ("\t" == o.value.substring(ss, ss + options.tabString.length)) { o.value = o.value.substring(0, ss) + o.value.substring(ss + options.tabString.length); // put it back together omitting one character to the right o.focus(); o.setSelectionRange(ss,ss); } } // TAB else { o.value = o.value.substring(0, ss) + options.tabString + o.value.substring(ss); o.focus(); o.setSelectionRange(ss + options.tabString.length, ss + options.tabString.length); } } // selections will always add/remove tabs from the start of the line else { // split the textarea up into lines and figure out which lines are included in the selection var lines = o.value.split("\n"); var indices = new Array(); var sl = 0; // start of the line var el = 0; // end of the line var sel = false; for (var i in lines) { el = sl + lines[i].length; indices.push({start: sl, end: el, selected: (sl <= ss && el > ss) || (el >= es && sl < es) || (sl > ss && el < es)}); sl = el + 1;// for "\n" } // walk through the array of lines (indices) and add tabs where appropriate var modifier = 0; for (var i in indices) { if (indices[i].selected) { var pos = indices[i].start + modifier; // adjust for tabs already inserted/removed // SHIFT+TAB if (shft && options.tabString == o.value.substring(pos,pos+options.tabString.length)) { // only SHIFT+TAB if there's a tab at the start of the line o.value = o.value.substring(0,pos) + o.value.substring(pos + options.tabString.length); // omit the tabstring to the right modifier -= options.tabString.length; } // TAB else if (!shft) { o.value = o.value.substring(0,pos) + options.tabString + o.value.substring(pos); // insert the tabstring modifier += options.tabString.length; } } } o.focus(); var ns = ss + ((modifier > 0) ? options.tabString.length : (modifier < 0) ? -options.tabString.length : 0); var ne = es + modifier; o.setSelectionRange(ns,ne); } } function ie_tab (o, shft, options) { var range = document.selection.createRange(); if (o == range.parentElement()) { // when there's no selection and we're just working with the caret, we'll add/remove the tabs at the caret, providing more control if ('' == range.text) { // SHIFT+TAB if (shft) { var bookmark = range.getBookmark(); //first try to the left by moving opening up our empty range to the left range.moveStart('character', -options.tabString.length); if (options.tabString == range.text) { range.text = ''; } else { // if that didn't work then reset the range and try opening it to the right range.moveToBookmark(bookmark); range.moveEnd('character', options.tabString.length); if (options.tabString == range.text) range.text = ''; } // move the pointer to the start of them empty range and select it range.collapse(true); range.select(); } else { // very simple here. just insert the tab into the range and put the pointer at the end range.text = options.tabString; range.collapse(false); range.select(); } } // selections will always add/remove tabs from the start of the line else { var selection_text = range.text; var selection_len = selection_text.length; var selection_arr = selection_text.split("\r\n"); var before_range = document.body.createTextRange(); before_range.moveToElementText(o); before_range.setEndPoint("EndToStart", range); var before_text = before_range.text; var before_arr = before_text.split("\r\n"); var before_len = before_text.length; // - before_arr.length + 1; var after_range = document.body.createTextRange(); after_range.moveToElementText(o); after_range.setEndPoint("StartToEnd", range); var after_text = after_range.text; // we can accurately calculate distance to the end because we're not worried about MSIE trimming a \r\n var end_range = document.body.createTextRange(); end_range.moveToElementText(o); end_range.setEndPoint("StartToEnd", before_range); var end_text = end_range.text; // we can accurately calculate distance to the end because we're not worried about MSIE trimming a \r\n var check_html = $(o).html(); $("#r3").text(before_len + " + " + selection_len + " + " + after_text.length + " = " + check_html.length); if((before_len + end_text.length) < check_html.length) { before_arr.push(""); before_len += 2; // for the \r\n that was trimmed if (shft && options.tabString == selection_arr[0].substring(0,options.tabString.length)) selection_arr[0] = selection_arr[0].substring(options.tabString.length); else if (!shft) selection_arr[0] = options.tabString + selection_arr[0]; } else { if (shft && options.tabString == before_arr[before_arr.length-1].substring(0,options.tabString.length)) before_arr[before_arr.length-1] = before_arr[before_arr.length-1].substring(options.tabString.length); else if (!shft) before_arr[before_arr.length-1] = options.tabString + before_arr[before_arr.length-1]; } for (var i = 1; i < selection_arr.length; i++) { if (shft && options.tabString == selection_arr[i].substring(0,options.tabString.length)) selection_arr[i] = selection_arr[i].substring(options.tabString.length); else if (!shft) selection_arr[i] = options.tabString + selection_arr[i]; } if (1 == before_arr.length && 0 == before_len) { if (shft && options.tabString == selection_arr[0].substring(0,options.tabString.length)) selection_arr[0] = selection_arr[0].substring(options.tabString.length); else if (!shft) selection_arr[0] = options.tabString + selection_arr[0]; } if ((before_len + selection_len + after_text.length) < check_html.length) { selection_arr.push(""); selection_len += 2; // for the \r\n that was trimmed } before_range.text = before_arr.join("\r\n"); range.text = selection_arr.join("\r\n"); var new_range = document.body.createTextRange(); new_range.moveToElementText(o); if (0 < before_len) new_range.setEndPoint("StartToEnd", before_range); else new_range.setEndPoint("StartToStart", before_range); new_range.setEndPoint("EndToEnd", range); new_range.select(); } } } // end of closure })(jQuery); PK\ndefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode_am4aff.phtmlnu[

        [am4aff] [/am4aff]

        PK\Vmdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/page_protection.phtmlnu[
        >
        >
        >
        PK\D llmdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/post_protection.phtmlnu[
        >
        >
        PK\pdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/widget_after_login.phtmlnu[
        !
        PK\?I=rdefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode_am4afflink.phtmlnu[



        [am4afflink id ='1' title='Your Affiliate Link']

        PK\71Wc!c!odefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode_am4show.phtmlnu[

        resourceAccess("not_have", '', 'not_have', __('Select Products that user should not have', 'am4-plugin'), self::RESOURCE_ACCESS_SKIP_PERIOD);?>

        resourceAccess("have", '', 'have', __('Select Products that user should have', 'am4-plugin'));?>

        errorMessageSelect("","guest_error");?>

        errorMessageSelect("","user_error");?>
        notactive
        Example:
        [am4show notactive=0]content[/am4show] is equivalent to [am4guest]content[/am4guest]
        have
        have='p2;g1' -
        have='p1,0,10;p2,30,60' -
        have='p1,10;p2'
        have='p1,0,-1' -
        have='p=-1,10,20' -
        not_have
        not_have='p1;p2' -
        user_error
        guest_error
        [am4show have='p1' user_error='amember_error' guest_error='amember_guest_error'] [/am4show]
        [am4show not_have='g1'] [/am4show]
        [am4show] [/am4show]
        PK\1odefault/plugins/protect/wordpress/upload_to_wordpress/wp-content/plugins/amember4/views/shortcode_am4info.phtmlnu[


        [am4info var=signupurl]http://localhost/amember/signup
        [am4info var=loginurl]http://localhost/amember/login
        [am4info var=logouturl]http://localhost/amember/logout
        [am4info var=renewurl]http://localhost/amember/member/renew
        [am4info var=renewurl title="Renew Your Membership"]<a href='http://localhost/amember/member/renew'>Renew Your Membership</a>
        PK\ҴQoo4default/plugins/protect/wordpress/Nexus/layout.phtmlnu[plugins_protect->get('wordpress')->startLayout($this, $title, true); get_header(); ?>
        misc.personal-content.notify_user 1 en text %site_title%: New file(s) uploaded to your account New file(s) uploaded to your account: %files% CUT; } function init() { parent::init(); $this->getDi()->uploadTable->defineUsage(self::UPLOAD_PREFIX, 'user', 'personal_content', UploadTable::STORE_DATA_BLOB_SERIALIZE, "Personal User Download [%login%, %name_f% %name_l%]", '/admin-users?_u_a=edit&_u_id=%user_id%'); } function _initSetupForm(Am_Form_Setup $form) { $form->setTitle(___('Personal Content')); $form->addElement('email_checkbox', 'notify_user') ->setLabel(___('Notify User about new file upload')); } function onSetupEmailTemplateTypes(Am_Event $event) { $event->addReturn(array( 'id' => 'misc.personal-content.notify_user', 'title' => 'Notify User about new file upload', 'mailPeriodic' => Am_Mail::REGULAR, 'vars' => array('user', 'files' => 'Name of uploaded files'), ), 'misc.personal-content.notify_user'); } function onGetUploadPrefixList(Am_Event $event) { $event->addReturn(array( Am_Upload_Acl::IDENTITY_TYPE_ADMIN => array( 'grid_u[edit]' => Am_Upload_Acl::ACCESS_ALL) ), "personal-content"); } function onGridUserInitForm(Am_Event $event) { if (!$this->hasPermission()) return; $gr = $event->getGrid()->getForm() ->addAdvFieldset('personal_content') ->setLabel(___('Personal Content')); $gr->addUpload('_personal_content', array('multiple' => 1), array('prefix' => self::UPLOAD_PREFIX)) ->setLabel(___("Personal Content\n" . 'These files will be available for downloads only for this user on his dashboard')); } function onGridUserBeforeSave(Am_Event $event) { if (!$this->hasPermission()) return; $notify = $this->getConfig('notify_user'); $user = $event->getGrid()->getRecord(); $val = $event->getGrid()->getForm()->getValue(); $pc = isset($val['_personal_content']) ? array_filter($val['_personal_content']) : array(); $pc_before = array(); if ($notify && ($personal_content = $user->data()->getBlob('personal_content'))) { $pc_before = unserialize($personal_content); } $user->data()->setBlob('personal_content', $pc ? serialize($pc) : null); if (!$user->unsubscribed && $notify && ($diff = array_diff($pc, $pc_before))) { $files = array(); foreach ($diff as $d) { $f = $this->getDi()->plugins_storage->getFile($d); $files[] = $f->getName(); } $files = implode(', ', $files); if($et = Am_Mail_Template::load('misc.personal-content.notify_user', $user->lang)) { $et->setUser($user); $et->setFiles($files); $et->send($user); } } } public function onAdminMenu(Am_Event $e) { if ($page = $e->getMenu()->findOneBy('id', 'users')) { $page->addPage(array( 'id' => 'personal-content', 'action' => 'upload', 'label' => ___('Personal Content'), 'route' => 'misc', 'params' => array( 'plugin_id' => $this->getId() ), 'resource' => self::ADMIN_PERM_ID )); } } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $action = $request->getActionName(); switch ($action) { case 'upload': return $this->uploadAction($request); break; default: $user = $this->getDi()->user; $path = $request->getParam('path'); if (!in_array($path, unserialize($user->data()->getBlob('personal_content')))) { throw new Am_Exception_AccessDenied(); } $f = $this->getDi()->plugins_storage->getFile($path); if ($path = $f->getLocalPath()) { @ini_set('zlib.output_compression', 'Off'); // for IE $helper = new Am_Mvc_Controller_Action_Helper_SendFile(); $helper->sendFile($path, $f->getMime(), array( //'cache'=>array('max-age'=>3600), 'filename' => $f->getName(), )); } else { $response->redirectLocation($f->getUrl(600)); } } } function uploadAction(Am_Mvc_Request $request) { if (!$this->getDi()->authAdmin->getUserId()) { throw new Am_Exception_AccessDenied; } $this->getDi()->authAdmin->getUser()->checkPermission(self::ADMIN_PERM_ID); $form = new Am_Form_Admin; $form->addMagicSelect('access') ->setLabel(___('Upload File to Active Users of')) ->loadOptions($this->getDi()->productTable->getProductOptions()) ->addRule('required'); $form->addUpload('_personal_content', array('multiple' => 1), array('prefix' => self::UPLOAD_PREFIX)) ->setLabel(___("Personal Content\n" . 'These files will be available for downloads only for this user on his dashboard')); $gr = $form->addGroup(); $gr->setSeparator(' '); $gr->addAdvCheckbox('notify_user'); $gr->addElement('email_link', 'misc.personal-content.notify_user'); $gr->setLabel(___('Notify User about new file upload')); $form->addSaveButton('Upload'); if ($form->isSubmitted() && $form->validate()) { $var = $form->getValue(); $q = $this->getDi()->db->queryResultOnly("SELECT DISTINCT u.* FROM ?_user u LEFT JOIN ?_access a USING (user_id) WHERE a.product_id IN (?a) AND a.begin_date<=? AND a.expire_date>=?", $this->getDi()->productTable->extractProductIds($var['access']), sqlDate('now'), sqlDate('now')); while ($row = $this->getDi()->db->fetchRow($q)) { $user = $this->getDi()->userRecord; $user->fromRow($row); $pc = $user->data()->getBlob('personal_content'); $pc = $pc ? unserialize($pc) : array(); $diff = array_diff($var['_personal_content'], $pc); $pc = array_unique(array_filter(array_merge($pc, $var['_personal_content']))); $user->data()->setBlob('personal_content', $pc ? serialize($pc) : null); $user->save(); if (!$user->unsubscribed && $diff && $var['notify_user']) { $files = array(); foreach ($diff as $d) { $f = $this->getDi()->plugins_storage->getFile($d); $files[] = $f->getName(); } $files = implode(', ', $files); $et = Am_Mail_Template::load('misc.personal-content.notify_user', $user->lang); $et->setUser($user); $et->setFiles($files); $et->send($user); } } $view = $this->getDi()->view; $view->title = ___('Personal Content: Upload File'); $view->content = ___("Files were uploaded! %sBack%s", '', ''); $view->display('admin/layout.phtml'); } else { $view = $this->getDi()->view; $view->title = ___('Personal Content: Upload File'); $view->content = (string) $form; $view->display('admin/layout.phtml'); } } function onGridUserValuesToForm(Am_Event $event) { if (!$this->hasPermission()) return; $args = $event->getArgs(); $values = $args[0]; $user = $event->getGrid()->getRecord(); if ($personal_content = $user->data()->getBlob('personal_content')) { $values['_personal_content'] = unserialize($personal_content); $event->setArg(0, $values); } } function onInitFinished() { if (($user = $this->getDi()->auth->getUser()) && $user->data()->getBlob('personal_content')) { $this->getDi()->blocks->add(new Am_Block('member/main/right', ___('Your Personal Downloads'), 'personal-content', $this, array($this, 'renderBlock'))); } } function renderBlock(Am_View $view) { $content = unserialize($this->getDi()->auth->getUser()->data()->getBlob('personal_content')); $out = ''; foreach ($content as $path) { if (!$path) continue; $file = $this->getDi()->plugins_storage->getFile($path); $vars = array( 'path' => $path ); $out .= sprintf('
      • %s
      • ', $view->url('misc/personal-content', $vars), $view->escape($file->getName())); } return sprintf('
          %s
        ', $out); } function onGetPermissionsList(Am_Event $event) { $event->addReturn(___('Personal Content'), self::ADMIN_PERM_ID); } function hasPermission() { return $this->getDi()->authAdmin->getUser()->hasPermission(self::ADMIN_PERM_ID); } function getReadme() { return <<Plugin Features 1. This plugin allow you to upload some files to specific user accounts. You can do it from admin interface in user profile at aMember CP -> Users -> Browse Users -> (edit) in section 'Personal Content' 2. You can upload same file to multiple user accouns in batch (based on user access). You can do it at aMember CP -> Users -> Personal Content User in his dashboard will see new widget with files available for his account. CUT; } }PK\j;/K#K#)default/plugins/misc/google-analytics.phpnu[id = $di->config->get('google_analytics'); parent::__construct($di, $config); } public function isConfigured() { return !empty($this->id); } function onSetupForms(Am_Event_SetupForms $forms) { $form = new Am_Form_Setup('google_analytics'); $form->setTitle("Google Analytics"); $forms->addForm($form); $form->addText('google_analytics') ->setLabel("Google Analytics Account ID\n" . 'To enable automatic sales and hits tracking with GA, enter Google Analytics cAccount ID into this field. Where can I find my tracking ID? The tracking ID will look like UA-1231231-1. Please note - this tracking is only for pages displayed by aMember, pages that are just protected by aMember, cannot be tracked. Use '. 'GA instructions how to add tracking code to your own pages. '); $form->addAdvCheckbox("google_analytics_only_sales_code") ->setLabel("Include only sales code\n" . "Enable this if you already have tracking code in template"); $form->addAdvCheckbox("google_analytics_track_free_signups") ->setLabel("Track free signups"); $form->addSelect("analytics_version") ->setLabel("Analytics Version") ->loadOptions(array( 'google' => 'Google Analytics', 'universal' => 'Universal Analytics', )); } function onAfterRender(Am_Event_AfterRender $event) { if ($this->done) return; if (preg_match('/thanks\.phtml$/', $event->getTemplateName()) && $event->getView()->invoice && $event->getView()->payment) { $this->done += $event->replace("||i", $this->getHeader() . $this->getSaleCode($event->getView()->invoice, $event->getView()->payment) . "", 1); if ($this->done) { $payment = $event->getView()->payment; $payment->data()->set(self::TRACKED_DATA_KEY, 1); $payment->save(); } } elseif (preg_match('/signup\/signup.*\.phtml$/', $event->getTemplateName())) { $this->done += $event->replace("||i", $this->getHeader() . $this->getTrackingCode(). $this->getSignupCode(). "", 1); } else { if ($user_id = $this->getDi()->auth->getUserId()) { $payments = $this->getDi()->invoicePaymentTable->findBy(array( 'user_id' => $user_id, 'dattm' => '>' . sqlTime('-5 days') )); foreach ($payments as $payment) { if ($payment->data()->get(self::TRACKED_DATA_KEY)) continue; $this->done += $event->replace("||i", $this->getHeader() . $this->getSaleCode($payment->getInvoice(), $payment) . "", 1); if ($this->done) { $payment->data()->set(self::TRACKED_DATA_KEY, 1); $payment->save(); } break; } } if (!$this->done && !(defined('AM_ADMIN') && AM_ADMIN) && !$this->getDi()->config->get("google_analytics_only_sales_code")) { $this->done += $event->replace("||i", $this->getHeader() . $this->getTrackingCode() . "", 1); } } } function getTrackingCode() { if($this->getDi()->config->get('analytics_version', 'google') == 'universal') { return << ga('create', '{$this->id}', 'auto'); ga('send', 'pageview'); CUT; } return << if (typeof(_gaq)=='object') { // sometimes google-analytics can be blocked and we will avoid error _gaq.push(['_setAccount', '{$this->id}']); _gaq.push(['_trackPageview']); } CUT; } function getSignupCode() { } function getSaleCode(Invoice $invoice, InvoicePayment $payment) { if($this->getDi()->config->get('analytics_version', 'google') == 'universal') { $out = << ga('create', '{$this->id}', 'auto'); ga('send', 'pageview'); CUT; } else { $out = << if (typeof(_gaq)=='object') { // sometimes google-analytics can be blocked and we will avoid error _gaq.push(['_setAccount', '{$this->id}']); _gaq.push(['_trackPageview']); } CUT; } if (empty($payment->amount) && !$this->getDi()->config->get('google_analytics_track_free_signups')) { return $out; } elseif (empty($payment->amount)) { $a = array( $invoice->public_id, $this->getDi()->config->get('site_title'), 0, 0, 0, $invoice->getCity(), $invoice->getState(), $invoice->getCountry(), ); } else { $a = array( $payment->transaction_id, $this->getDi()->config->get('site_title'), $payment->amount - $payment->tax - $payment->shipping, (float)$payment->tax, (float)$payment->shipping, $invoice->getCity(), $invoice->getState(), $invoice->getCountry(), ); } $a = implode(",\n", array_map('json_encode', $a)); $items = ""; foreach ($invoice->getItems() as $item) { if($this->getDi()->config->get('analytics_version', 'google') == 'universal') { $it = json_encode(array( 'id' => $payment->transaction_id, 'name' => $item->item_title, 'sku' => $item->item_id, 'price' => moneyRound($item->first_total/$item->qty), 'quantity' => $item->qty, )); $items .= "ga('ecommerce:addItem', $it);\n"; } else { $items .= "['_addItem', '$payment->transaction_id', '$item->item_id', '$item->item_title','', $item->first_total, $item->qty],"; } } if($this->getDi()->config->get('analytics_version', 'google') == 'universal') { $tr = json_encode(array( 'id' => $payment->transaction_id, 'affiliation' => $this->getDi()->config->get("site_title"), 'revenue' => empty($payment->amount) ? 0 : ($payment->amount - $payment->tax - $payment->shipping), 'shipping' => empty($payment->amount) ? 0 : $payment->shipping, 'tax' => empty($payment->amount) ? 0 : $payment->tax, )); return $out . << ga('require', 'ecommerce'); ga('ecommerce:addTransaction', $tr); $items ga('ecommerce:send'); CUT; } return $out . << if (typeof(_gaq)=='object') { // sometimes google-analytics can be blocked and we will avoid error _gaq.push( ['_addTrans', $a], $items ['_trackTrans'] ); } CUT; } function getHeader() { if($this->getDi()->config->get('analytics_version', 'google') == 'universal') { return << CUT; } return << CUT; } }PK\.+default/plugins/misc/misc-plugin-readme.txtnu[ PLUGIN INSTALLATION 1. Upload plugin code to folder 'amember/application/default/plugins/misc' 2. Enable plugin at aMember CP -> Configuration -> Setup/Configuration -> Plugins (Other Plugins) 3. Visit plugin configuration section aMember CP -> Configuration -> Setup/Configuration -> [Plugin Name] to configure plugin. Plugin-specific readme is displayed this page at bottom. PK\B6++-default/plugins/misc/single-login-session.phpnu[db->query("CREATE TABLE ?_login_session ( login_session_id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, user_id INT UNSIGNED NOT NULL, remote_addr varchar(39) NOT NULL, session_id varchar(255) NOT NULL, modified datetime NOT NULL, need_logout TINYINT NOT NULL, INDEX user_id (user_id) ) CHARACTER SET utf8 COLLATE utf8_general_ci"); } catch (Am_Exception_Db $e) { } $di = Am_Di::getInstance(); $name = 'misc.single-login-session.notify_admin'; $body = <<db->selectCell("SELECT COUNT(*) AS cnt FROM ?_email_template WHERE name = ?", $name); if (!$cnt) { $di->db->query("INSERT INTO ?_email_template (name,lang,format,subject,txt) VALUES (?,?,?,?,?)", $name, 'en', 'text', 'Simultaneous login detected [%user.login%]', $body); } $name = 'misc.single-login-session.notify_user'; $body = <<db->selectCell("SELECT COUNT(*) AS cnt FROM ?_email_template WHERE name = ?", $name); if (!$cnt) { $di->db->query("INSERT INTO ?_email_template (name,lang,format,subject,txt) VALUES (?,?,?,?,?)", $name, 'en', 'text', 'Simultaneous login detected [%user.login%]', $body); } } function _initSetupForm(Am_Form_Setup $form) { $form->setTitle(___('Single Login Session')); $form->addText('timeout', array('size'=>4)) ->setLabel(___('Session Timeout, min')); $form->setDefault('timeout', 5); $form->addSelect('action') ->setId('form-action') ->setLabel(___('Action on Simultaneous Login Attempt')) ->loadOptions(array( self::ACTION_LOGIN_REJECT => ___('Show error and do not allow to login until session timeout'), self::ACTION_LOGOUT_OTHER => ___('Delete other session when user try to login from new one'), self::ACTION_NOTHING => ___('Nothing, allow simultaneous login for same user from different computers') )); $form->addTextarea('error', array('class' => 'el-wide')) ->setId('form-error') ->setLabel(___('Error Message')); $form->setDefault('error', 'There is already exits active login session for your account. Simultaneous login from different computers is not allowed.'); $error = self::ACTION_LOGIN_REJECT; $form->addScript() ->setScript(<<addElement('email_checkbox', 'notify_admin') ->setLabel(___('Notify Admin on Simultaneous Login')); $form->addElement('email_checkbox', 'notify_user') ->setLabel(___('Notify User on Simultaneous Login')); } function onSetupEmailTemplateTypes(Am_Event $event) { $event->addReturn(array( 'id' => 'misc.single-login-session.notify_admin', 'title' => ___('Notify Admin on Simultaneous Login'), 'mailPeriodic' => Am_Mail::PRIORITY_LOW, 'isAdmin' => true, 'vars' => array('user'), ), 'misc.single-login-session.notify_admin'); $event->addReturn(array( 'id' => 'misc.single-login-session.notify_user', 'title' => ___('Notify User on Simultaneous Login'), 'mailPeriodic' => Am_Mail::PRIORITY_LOW, 'vars' => array('user'), ), 'misc.single-login-session.notify_user'); } function onAuthAfterLogout(Am_Event_AuthAfterLogout $event) { $user = $event->getUser(); $this->getDi()->loginSessionTable->deleteBy(array( 'user_id' => $user->pk(), 'session_id' => Zend_Session::getId() )); } function onAuthAfterLogin(Am_Event_AuthAfterLogin $event) { $user = $event->getUser(); $this->getDi()->loginSessionTable->insert(array( 'user_id' => $user->pk(), 'session_id' => Zend_Session::getId(), 'need_logout' => 0, 'modified' => sqlTime('now'), 'remote_addr' => $_SERVER['REMOTE_ADDR'] )); } function onAuthCheckUser(Am_Event $event) { /* @var $user User */ $user = $event->getUser(); $recs = $this->getDi()->loginSessionTable->findBy(array( 'user_id' => $user->pk(), 'session_id' => '<>' . Zend_Session::getId(), 'modified' => '>' . sqlTime(sprintf('-%d minutes', $this->getConfig('timeout', 5))), 'need_logout' => 0)); if ($recs) { switch ($this->getConfig('action', self::ACTION_LOGIN_REJECT)) { case self::ACTION_LOGIN_REJECT: $event->setReturn(new Am_Auth_Result(-100, $this->getConfig('error', 'There is already exits active login session for your account. Simultaneous login from different computers is not allowed.'))); $event->stop(); break; case self::ACTION_LOGOUT_OTHER : foreach ($recs as $rec) $rec->updateQuick('need_logout', 1); break; case self::ACTION_NOTHING : break; } if ($this->getConfig('notify_admin') && !$this->getDi()->store->get('single-login-session-detected-' . $user->pk())) { $this->getDi()->store->set('single-login-session-detected-' . $user->pk(), 1, '+20 minutes'); if ($et = Am_Mail_Template::load('misc.single-login-session.notify_admin')) { $et->setUser($user); $et->sendAdmin(); } } if ($this->getConfig('notify_user') && !$this->getDi()->store->get('single-login-session-detected-user-' . $user->pk())) { $this->getDi()->store->set('single-login-session-detected-user-' . $user->pk(), 1, '+20 minutes'); if ($et = Am_Mail_Template::load('misc.single-login-session.notify_user')) { $et->setUser($user); $et->send($user); } } } } function onInitFinished() { if ($user_id = $this->getDi()->auth->getUserId()) { $rec = $this->getDi()->loginSessionTable->findFirstBy(array( 'user_id' => $user_id, 'session_id' => Zend_Session::getId() )); if (!$rec) { $rec = $this->getDi()->loginSessionRecord; $rec->user_id = $user_id; $rec->session_id = Zend_Session::getId(); $rec->need_logout = 0; } if ($rec->need_logout) { $rec->delete(); $this->getDi()->auth->logout(); } else { $rec->modified = sqlTime('now'); $rec->remote_addr = $_SERVER['REMOTE_ADDR']; $rec->save(); } } } function onDaily() { $this->getDi()->loginSessionTable->deleteBy(array( 'modified' => '<' . sqlTime(sprintf('-%d minutes', $this->getConfig('timeout', 5))) )); } function onGridUserInitForm(Am_Event $event) { $user = $event->getGrid()->getRecord(); if ($user->isLoaded()) { $recs = $this->getDi()->loginSessionTable->findBy(array( 'user_id' => $user->pk(), 'modified' => '>' . sqlTime(sprintf('-%d minutes', $this->getConfig('timeout', 5))), 'need_logout' => 0)); if ($recs) { $ips = array(); foreach ($recs as $r) $ips[] = $r->remote_addr; $login = $event->getGrid()->getForm()->getElementById('login'); $static = new Am_Form_Element_Html(); $static->setHtml(sprintf('
        %s
        ', ___('There is %d active login session for this ' . 'user from following IP address(es): %s', count($recs), implode(', ', $ips)))); $login->getContainer()->insertBefore($static, $login); } } } function onGridUserOnBeforeRun(Am_Event $event) { /* @var $grid Am_Grid_Editable */ $grid = $event->getGrid(); /* @var $query Am_Query_User */ $query = $grid->getDataSource(); $date = sqlTime(sprintf('-%d minutes', $this->getConfig('timeout', 5))); $query->leftJoin('?_login_session', 'ls', 'u.user_id=ls.user_id') ->addField("SUM(IF(modified>'$date' AND need_logout=0, 1, 0))", 'login_session_cnt'); $loginIndicator = new Am_Grid_Field('login_indicator', ___('Login Indicator'), false); $loginIndicator->setRenderFunction(array($this, 'renderLoginIndicator')); $action = $grid->actionGet('customize'); $action->addField($loginIndicator); } function renderLoginIndicator(Am_Record $rec) { $res = $rec->last_login ? '' . amDatetime($rec->last_login) . '' : '' . ___('Never') . ''; if ($rec->login_session_cnt) $res = '' . ___('Online') . (($rec->login_session_cnt > 1) ? sprintf(' (%d)', $rec->login_session_cnt) : '') . ''; return sprintf('%s', $res); } function getReadme() { return <<id = $di->config->get('getclicky_id'); parent::__construct($di, $config); } public function isConfigured() { return !empty($this->id); } function onSetupForms(Am_Event_SetupForms $forms) { $form = new Am_Form_Setup('getclicky'); $form->setTitle("GetClicky"); $forms->addForm($form); $form->addInteger('getclicky_id') ->setLabel(___("GetClicky Site Id\n" . "GetClicky Account -> Preferences -> Info")); } function onAfterRender(Am_Event_AfterRender $event) { if ($this->done) return; if (preg_match('/thanks\.phtml$/', $event->getTemplateName())) { $this->done += $event->replace("||i", $this->getSaleCode($event->getView()->invoice, $event->getView()->payment) . $this->getTrackingCode() . "", 1); } elseif (!preg_match('/\badmin\b/', $t = $event->getTemplateName())) { $this->done += $event->replace("||i", $this->getTrackingCode() . "", 1); } } function getTrackingCode() { return << Real Time Analytics CUT; } function getSaleCode(Invoice $invoice, InvoicePayment $payment) { if (empty($payment->amount)) { $goal = array('name' => 'Free Signup'); } else { $goal = array('name' => 'Purchase', 'revenue' => $payment->amount); } $goal = json_encode($goal); return << var clicky_custom = {}; clicky_custom.goal = $goal; CUT; } }PK\UED..+default/plugins/misc/subscription-limit.phpnu[ misc.subscription-limit.notify_oos_admin 2 en text %site_title%: Out of stock - %product.title% %product.title% is out of stock. misc.subscription-limit.notify_ls_admin 2 en text %site_title%: Low stock - %product.title% (%qty%) %product.title% is low stock. Remaining quantity is %qty% CUT; } function onSetupEmailTemplateTypes(Am_Event $event) { $event->addReturn(array( 'id' => 'misc.subscription-limit.notify_oos_admin', 'title' => ___('Out of Stock Notification to Admin'), 'mailPeriodic' => Am_Mail::ADMIN_REQUESTED, 'isAdmin' => true, 'vars' => array('product.title' => ___('Product Title')), ), 'misc.subscription-limit.notify_oos_admin'); $event->addReturn(array( 'id' => 'misc.subscription-limit.notify_ls_admin', 'title' => ___('Low Stock Notification to Admin'), 'mailPeriodic' => Am_Mail::ADMIN_REQUESTED, 'isAdmin' => true, 'vars' => array( 'product.title' => ___('Product Title'), 'qty' => ___('Remaining quantity')), ), 'misc.subscription-limit.notify_ls_admin'); } function init() { $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldText('subscription_limit', ___('Subscription limit'), ___('limit amount of subscription for this product, keep empty if you do not want to limit amount of subscriptions'))); $this->getDi()->productTable->customFields() ->add(new Am_CustomFieldText('subscription_user_limit', ___('Subscription limit for each user'), ___('limit amount of subscription for this product per user, keep empty if you do not want to limit amount of subscriptions'))); } function _initSetupForm(Am_Form_Setup $form) { $form->setTitle(___('Subscription Limit')); $form->addElement('email_checkbox', 'notify_oos_admin') ->setLabel(___('Out of Stock Notification')); $form->addElement('email_checkbox', 'notify_ls_admin') ->setLabel(___('Low Stock Notification')); $form->addText('low_stock_threshold', array('size'=>3, 'placeholder'=>'3', 'id' => 'ls-threshold')) ->setLabel(___('Low Stock Threshold')); $form->addScript() ->setScript(<<getInvoice(); $user = $invoice->getUser(); foreach ($invoice->getItems() as $item) { if ($item->item_type != 'product') continue; $product = $this->getDi()->productTable->load($item->item_id); if (($limit = $product->data()->get('subscription_limit')) && $limit < $item->qty) { throw new Am_Exception_InputError(___('There is not such amount (%d) of product %s', $item->qty, $item->item_title)); } $count = $this->getDI()->db->selectCell(" SELECT SUM(ii.qty) FROM ?_invoice_item ii LEFT JOIN ?_invoice i ON ii.invoice_id = i.invoice_id WHERE i.user_id = ? and ii.item_id=? and i.status<>0 ", $user->pk(), $product->pk()); if (($limit = $product->data()->get('subscription_user_limit')) && $limit < ($item->qty + $count)) { throw new Am_Exception_InputError(___('There is not such amount (%d) of product %s you can purchase only %s items.', $item->qty, $item->item_title, $limit)); } } } function onInvoiceStarted(Am_Event_InvoiceStarted $event) { $invoice = $event->getInvoice(); foreach ($invoice->getItems() as $item) { if ($item->item_type != 'product') continue; $product = $this->getDi()->productTable->load($item->item_id); if ($limit = $product->data()->get('subscription_limit')) { $limit -= $item->qty; $product->data()->set('subscription_limit', $limit); if ($limit && $limit<=$this->getConfig('low_stock_threshold', 3) && $this->getConfig('notify_ls_admin')) { $et = Am_Mail_Template::load('misc.subscription-limit.notify_ls_admin'); $et->setProduct($product); $et->setQty($limit); $et->sendAdmin(); } if (!$limit) { if ($this->getConfig('notify_oos_admin')) { $et = Am_Mail_Template::load('misc.subscription-limit.notify_oos_admin'); $et->setProduct($product); $et->sendAdmin(); } $product->is_disabled = 1; } $product->save(); } } } function onGridProductInitGrid(Am_Event_Grid $event) { $grid = $event->getGrid(); $grid->addField(new Am_Grid_Field('subscription_limit', ___('Limit'), false))->setRenderFunction(array($this, 'renderLimit')); } function renderLimit(Product $product) { return '' . ( ($limit = $product->data()->get('subscription_limit')) ? $limit : '–') . ''; } function getReadme() { return << Products -> Manage Products -> Edit (Subscription limit) CUT; } }PK\w} %default/plugins/misc/notification.phpnu[
        CUT; } function init() { $this->getDi()->router->addRoute('notification', new Am_Mvc_Router_Route( 'misc/notification/:action/:id', array( 'module' => 'default', 'controller' => 'direct', 'action' => 'index', 'type' => 'misc', 'plugin_id' => 'notification'))); } function renderNotification() { $root = preg_replace('/https?:/', '', ROOT_URL); return <<
        CUT; } function onAdminMenu(Am_Event $event) { $event->getMenu()->addPage(array( 'id' => 'notification', 'module' => 'default', 'controller' => 'admin-notification', 'action' => 'index', 'label' => ___('Notifications'), 'resource' => self::ADMIN_PERM_ID )); } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $user = $this->getDi()->user; switch ($request->getActionName()) { case 'c' : $id = $this->getDi()->security->reveal($request->getFiltered('id')); //actualy it is notification_id $notification = $this->getDi()->notificationTable->load($id); $this->getDi()->notificationClickTable->log($user, $notification); $tpl = new Am_SimpleTemplate(); $tpl->assign('user', $this->getDi()->auth->getUser()); return $response->redirectLocation($tpl->render($notification->url)); break; case 'get' : if (!$user) { $response->ajaxResponse(array()); } else { $items = $this->getDi()->notificationTable->getNotificationsForUser($this->getDi()->auth->getUser()); $dismiss = $user->data()->getBlob('notification.dismiss'); $tpl = new Am_SimpleTemplate(); $tpl->assign('user', $this->getDi()->auth->getUser()); if (!$dismiss) { $dismiss = array(); } else { $dismiss = unserialize($dismiss); } $out = array(); foreach ($items as $item) { $display = $user->data()->get('notification.display.' . $item->pk()); if ($item->limit && $display >= $item->limit) continue; if (in_array($item->notification_id, $dismiss)) continue; $user->data()->set('notification.display.' . $item->pk(), ++$display); $n = new stdClass; $n->id = $this->getDi()->app->obfuscate($item->notification_id); $n->content = $tpl->render($item->content); $n->is_custom = $item->is_custom ? true : false; $n->is_blank = $item->is_blank ? true : false; $n->link = $tpl->render($item->url); $n->dont_close = $item->data()->get('dont_close'); $out[] = $n; } $user->save(); $response->ajaxResponse($out); } break; case 'js' : $response->setHeader('Content-Type', 'application/x-javascript; charset=utf-8'); echo $this->getJs(); break; case 'd' : $id = $this->getDi()->security->reveal($request->getFiltered('id')); if ($user && $id) { $dismiss = $user->data()->getBlob('notification.dismiss'); if (!$dismiss) { $dismiss = array(); } else { $dismiss = unserialize($dismiss); } $dismiss[] = $id; $user->data()->setBlob('notification.dismiss', serialize($dismiss)); $user->data()->update(); } break; default : throw new Am_Exception_InternalError('Unknown Action'); } } function getJs() { $root = preg_replace('/https?:/', '', ROOT_URL); return <<'); var n=data[i]; cont.attr('id', 'am-notification-'+n.id); if(options.class && !n.is_custom) { cont.addClass(options.class); } else if(!n.is_custom) { cont.css({ 'background-color': '#FFFFCF', 'border-color': '#545454', 'color': '#454430', 'border-radius': '10px', 'margin-bottom': '1em', 'padding': '0.5em 1em', 'border': '1px solid' }); } cont.append(n.content); if(n.link){ var l = jQuery(""+options.link_text+""); cont.append(" "); cont.append(l); } var link = jQuery(""); if(!n.dont_close) cont.prepend(link); \$this.append(cont); link.on('click', function(e){ e.preventDefault(); var id = jQuery(this).closest('div').attr('id').substr(16); jQuery.get("{$root}/misc/notification/d/"+id, function(){ jQuery('#am-notification-'+id).hide(options.animation); jQuery('#am-notification-'+id).remove(); }); }); } }); }); } })(jQuery); CUT; } function onGetPermissionsList(Am_Event $event) { $event->addReturn(___('Can Operate with Notifications'), self::ADMIN_PERM_ID); } function onInitFinished(Am_Event $e) { $this->getDi()->blocks->add(new Am_Block('member/main/top', null, 'notification', null, array($this, 'renderNotification'))); } function getReadme() { $root = preg_replace('/https?:/', '', ROOT_URL); $script = << EOT; $script = Am_Html::escape($script); return <<_simpleSort(Am_Di::getInstance()->notificationTable, $item, $after, $before); } } class AdminNotificationController extends Am_Mvc_Controller_Grid { function init() { parent::init(); include_once dirname(__FILE__) . "/../../controllers/AdminContentController.php"; } function preDispatch() { parent::preDispatch(); $this->view->headScript()->appendFile($this->view->_scriptJs("resourceaccess.js")); } function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Plugin_Notification::ADMIN_PERM_ID); } function clickAction() { $ds = new Am_Query($this->getDi()->notificationClickTable); $ds->leftJoin('?_user', 'u', 't.user_id=u.user_id') ->addField('COUNT(t.notification_click_id)', 'cnt') ->addField('u.*') ->addField("CONCAT(u.name_f, ' ', u.name_l)", 'name') ->groupBy('user_id', 'u') ->addWhere('notification_id=?', $this->getParam('id')); $grid = new Am_Grid_ReadOnly('_n_c', ___('Statistics'), $ds, $this->getRequest(), $this->getView(), $this->getDi()); $userUrl = new Am_View_Helper_UserUrl(); $grid->addField('login', ___('Username')) ->addDecorator(new Am_Grid_Field_Decorator_Link($userUrl->userUrl('{user_id}'), '_top')); $grid->addField('name', ___('Name')); $grid->addField('email', ___('E-Mail Address')); $grid->addField('cnt', ___('Clicks'), null, null, null, '1%'); $grid->runWithLayout($this->layout); } function createGrid() { $ds = new Am_Query($this->getDi()->notificationTable); $ds->leftJoin('?_notification_click', 'nc', 't.notification_id=nc.notification_id') ->addField('COUNT(nc.notification_click_id)', 'cnt') ->addOrder('sort_order'); $grid = new Am_Grid_Editable('_notification', ___('Notifications'), $ds, $this->_request, $this->view, $this->getDi()); $grid->setPermissionId(Am_Plugin_Notification::ADMIN_PERM_ID); $grid->addField('content', ___('Content')); $grid->addField('url', ___('Link')); $grid->addField(new Am_Grid_Field_Date('begin', ___('Begin'))) ->setFormatDate(); $grid->addField(new Am_Grid_Field_Date('expire', ___('Expire'))) ->setFormatDate(); $grid->addField('cnt', ___('Clicks'), true, null, null, '1%') ->setRenderFunction(array($this, 'renderClicks')); $grid->addField(new Am_Grid_Field_IsDisabled()); $grid->setForm(array($this, 'createForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_FROM_FORM, array($this, 'valuesFromForm')); $grid->actionAdd(new Am_Grid_Action_Group_Delete()); $grid->actionAdd(new Am_Grid_Action_Sort_Notification()); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_STATIC, array($this, 'renderStatic')); $grid->addCallback(Am_Grid_ReadOnly::CB_RENDER_CONTENT, array($this, 'renderContent')); $grid->setFilter(new Am_Grid_Filter_Text(___('Filter by Content or Link'), array( 'content' => 'LIKE', 'url' => 'LIKE' ))); $grid->setRecordTitle(___('Notification')); return $grid; } function renderContent(& $out) { $readme = $this->getDi()->plugins_misc->loadGet('notification')->getReadme(); $out .= <<
        $readme
        CUT; } function renderStatic(& $out) { $title = ___('Statistics'); $out .= << jQuery(document).on('click', '.notification-click', function(){ var div = jQuery('
        '); div.load(amUrl("/admin-notification/click/?id=") + jQuery(this).data('notification_id'), function(){ div.dialog({ autoOpen: true ,width: 800 ,buttons: {} ,closeOnEscape: true ,title: "$title" ,modal: true ,open: function(){ div.ngrid(); } }); }); }) CUT; } function renderClicks($rec) { return $rec->cnt ? sprintf('%d', $rec->pk(), $rec->cnt) : ''; } function valuesToForm(array & $values, Notification $record) { $values['_dont_close'] = $record->data()->get('dont_close'); @$values['filter_products'] = explode(',', $values['filter_products']); $is_custom = isset($values['is_custom']) && $values['is_custom']; @$values['_content_html'] = $is_custom ? $values['content'] : ''; @$values['_content_text'] = $is_custom ? '' : $values['content']; foreach ((array) $record->_access as $access) { switch ($access->fn) { case 'free' : $values['_target'][] = 'free'; break; case 'user_id' : $values['_target'][] = 'user_id'; $ids = array(); foreach ($record->_access as $r) if ($r->fn == 'user_id') $ids[] = $r->id; $users = array(); foreach ($this->getDi()->userTable->loadIds($ids) as $user) { $users[] = $user->login; } $values['_savedLoginOrEmail'] = implode(',', $users); break; case 'user_group_id' : $values['_access'][] = $access; case 'product_id': case 'product_category_id': $values['_raccess'][] = $access; break; } } } function valuesFromForm(array & $values, Notification $record) { $access = array(); $record->data()->set('dont_close', @$values['_dont_close']); foreach ($values['_target'] as $v) { switch ($v) { case 'free' : $rec = $this->getDi()->notificationAccessRecord; $rec->fn = 'free'; $rec->id = null; $access[] = $rec; break; case 'user_id' : $rec = $this->getDi()->notificationAccessRecord; $user_ids = array(); foreach ($_REQUEST['_loginOrEmail'] as $loginOrEmail) { $user = $this->getDi()->userTable->findFirstByLogin($loginOrEmail); if (!$user) $user = $this->getDi()->userTable->findFirstByEmail($loginOrEmail); if ($user) $user_ids[] = $user->pk(); } $user_ids = array_filter($user_ids); foreach ($user_ids as $uid) { $rec = $this->getDi()->notificationAccessRecord; $rec->fn = 'user_id'; $rec->id = $uid; $access[] = $rec; } break; default: preg_match('/(user_group_id)-([0-9]+)/i', $v, $match); $rec = $this->getDi()->notificationAccessRecord; $rec->fn = $match[1]; $rec->id = $match[2]; $access[] = $rec; } } foreach (array( 'product_id' => ResourceAccess::FN_PRODUCT, 'product_category_id' => ResourceAccess::FN_CATEGORY) as $key => $rtype) { if (!empty($values['_raccess'][$key])) { foreach ($values['_raccess'][$key] as $id => $params) { if (!is_array($params)) $params = json_decode($params, true); $fa = $this->getDi()->notificationAccessRecord; $fa->fn = $rtype; $fa->id = $id; $fa->start_days = null; $fa->stop_days = null; if (preg_match('/^(-?\d+)(\w+)$/', strtolower($params['start']), $regs)) { $fa->start_days = $regs[1]; } if (preg_match('/^(-?\d+)(\w+)$/', strtolower($params['stop']), $regs)) { $fa->stop_days = $regs[1]; } $access[] = $fa; } } } if (!$values['expire']) $values['expire'] = null; if (!$values['begin']) $values['begin'] = null; if (!$values['url']) $values['url'] = null; if (!$values['limit']) $values['limit'] = null; $values['filter_products'] = empty($values['filter_products']) ? null : implode(',', $values['filter_products']); $record->_access = $access; $values['content'] = $values['is_custom'] ? $values['_content_html'] : $values['_content_text']; } function createForm() { $form = new Am_Form_Admin(); $form->addAdvRadio('is_custom') ->loadOptions(array( 0 => ___('Use Pre-Defined Template'), 1 => ___('Define Custom Html Message') ))->setValue(0); $form->addTextarea('_content_text', array('rows' => '7', 'rel' => 'form-pre-defined', 'class' => 'row-wide el-wide')) ->setLabel(___("Content\n" . 'You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.')); $placeholder_items = &$options['placeholder_items']; foreach ($this->getUserTagOptions() as $k => $v) { $placeholder_items[] = array($v, $k); } $form->addHtmlEditor('_content_html', array('rel' => 'form-html'), array('showInPopup' => true)) ->setLabel(___("Content\n" . 'You can use all user specific placeholders here eg. %user.login%, %user.name_f%, %user.name_l% etc.')) ->setMceOptions($options); $form->addText('url', array('class' => 'el-wide', 'rel' => 'form-pre-defined')) ->setLabel(___('Link')); $form->addAdvcheckbox('is_blank', array('rel' => 'form-pre-defined')) ->setLabel(___('Open Link in New Window')); $form->addScript() ->setScript(<<addMagicSelect('_target') ->setLabel(___('Target By User')); $cats = $pr = $gr = array(); foreach ($this->getDi()->userGroupTable->getSelectOptions() as $k => $v) $gr['user_group_id-' . $k] = 'Group: ' . $v; $options = array( 'free' => ___('All'), 'user_id' => ___('Specific User') ) + ($cats ? array(___('Product Categories') => $cats) : array()) + ($gr ? array(___('User Groups') => $gr) : array()) + ($pr ? array(___('Products') => $pr) : array()); $sel->loadOptions($options); //$sel->addRule('required'); $sel->setJsOptions('{onChange:function(val){ jQuery("input[name^=_loginOrEmail]").closest(\'.row\').toggle(val.hasOwnProperty("user_id")); }}'); $loginGroup = $form->addGroup(''); $loginGroup ->setLabel(___('Username/Email')); $loginGroup->addHidden('_savedLoginOrEmail')->setValue(''); $login = $loginGroup->addText('_loginOrEmail[]'); $label_add_user = ___('Add User'); $loginGroup->addHtml() ->setHtml(<<$label_add_user CUT ); $form->addElement(new Am_Form_Element_ResourceAccess('_raccess', array('without_free' => true)))->setLabel('Target By Product'); $pr = $cats = array(); foreach ($this->getDi()->productCategoryTable->getOptions() as $k => $v) $cats['category-' . $k] = ___('Category') . ' : ' . $v; foreach ($this->getDi()->productTable->getOptions() as $k => $v) $pr['product-' . $k] = ___('Product') . ' : ' . $v; $sel = $form->addMagicSelect('filter_products')->setLabel("Show notification only if user doesn't have"); $sel->loadOptions( array( ___('Product Categories') => $cats, ___('Products') => $pr, ___('User Groups') => $gr )); $gr = $form->addGroup() ->setSeparator(' ') ->setLabel(___("Dates\n" . 'date range when notification is shown')); $gr->addDate('begin', array('placeholder' => ___('Begin Date'))); $gr->addDate('expire', array('placeholder' => ___('Expire Date'))); $form->addScript('script')->setScript(<<getDi()->view->icon('delete'); $form->addScript('script2')->setScript(<<'); jQuery(context).before('
        '); jQuery(context).before(\$field); jQuery(context).before('$delIcon'); jQuery(context).before('
        '); \$field.autocomplete({ minLength: 2, source: amUrl("/admin-users/autocomplete") }); return \$field; } jQuery('#target-user_id-add').click(function(){ addEmailOrLogin(this); }) CUT ); $form->addText('limit', array('size' => 8, 'placeholder' => ___('Unlimited'))) ->setLabel(___("Limit Number of Display per User\n" . 'keep it empty for unlimited')); $form->addAdvcheckbox('_dont_close') ->setLabel(___('Does not allow to close notification')); return $form; } function getUserTagOptions() { $tagOptions = array( '%user.name_f%' => 'User First Name', '%user.name_l%' => 'User Last Name', '%user.login%' => 'Username', '%user.email%' => 'E-Mail', '%user.user_id%' => 'User Internal ID#', '%user.street%' => 'User Street', '%user.street2%' => 'User Street (Second Line)', '%user.city%' => 'User City', '%user.state%' => 'User State', '%user.zip%' => 'User ZIP', '%user.country%' => 'User Country', '%user.status%' => 'User Status (0-pending, 1-active, 2-expired)' ); foreach ($this->getDi()->userTable->customFields()->getAll() as $field) { if (@$field->sql && @$field->from_config) { $tagOptions['%user.' . $field->name . '%'] = 'User ' . $field->title; } } return $tagOptions; } } /** * @property int $notification_id * @property string $content * @property string $url * @property string $fn * @property int $id * @property string $expire */ class Notification extends Am_Record_WithData { function __get($name) { if (!$this->isLoaded()) return null; if ($name == '_access') { $this->_access = $this->getDi()->notificationAccessTable->findBy(array('notification_id' => $this->pk())); return $this->_access; } throw new Am_Exception_InternalError('No variable ' . $name . ' defined in ' . __CLASS__); } function __isset($name) { return $name == '_access'; } function update() { $ret = parent::update(); $this->saveAccess($this->_access); return $ret; } function insert($reload = true) { $table_name = $this->getTable()->getName(); $this->getAdapter()->query("UPDATE {$table_name} SET sort_order=sort_order+1"); $this->sort_order = 1; $ret = parent::insert($reload); $this->saveAccess($this->_access); return $ret; } function delete() { $ret = parent::delete(); $this ->deleteFromRelatedTable('?_notification_access') ->deleteFromRelatedTable('?_notification_click'); $table_name = $this->getTable()->getName(); $this->getAdapter()->query("UPDATE {$table_name} SET sort_order=sort_order-1 WHERE sort_order>?", $this->sort_order); return $ret; } protected function saveAccess($access) { if (!$this->isLoaded()) return; $this->getDi()->notificationAccessTable->deleteBy(array('notification_id' => $this->pk())); foreach ($access as $v) { $v->notification_access_id = null; $v->notification_id = $this->pk(); $v->insert(); } } function isAvailableForUser(User $user) { // Check products; if ($this->filter_products) $filter_products = explode(',', $this->filter_products); $active_products = $user->getActiveProductIds(); $categories = array(); foreach ($this->getDi()->productCategoryTable->getCategoryProducts() as $cat_id => $products) if (array_intersect($active_products, $products)) $categories[] = $cat_id; $groups = $user->getGroups(); foreach ($filter_products as $expr) { list($type, $id) = explode('-', $expr); switch ($type) { case 'category' : if (in_array($id, $categories)) return false; break; case 'product' : if (in_array($id, $active_products)) return false; break; case 'user_group_id' : if (in_array($id, $groups)) return false; break; } } return true; } } class NotificationTable extends Am_Table_WithData { protected $_table = '?_notification'; protected $_recordClass = 'Notification'; protected $_key = 'notification_id'; function getNotificationsForUser(User $user) { return $this->getDi()->notificationAccessTable->getNotificationsForUser($user); } } class NotificationAccessTable extends ResourceAccessTable { protected $_table = '?_notification_access'; protected $_recordClass = 'NotificationAccess'; protected $_key = 'notification_access_id'; function getNotificationsByTargetUser(User $user) { $user_group_ids = $user->getGroups(); array_push($user_group_ids, '-1'); //to avoide SQL error return $this->getDi()->db->selectCol(" SELECT notification_id FROM ?_notification WHERE notification_id IN ( SELECT notification_id FROM ?_notification_access WHERE (fn=? AND id = ?) OR (fn=?) OR (fn=? AND id IN (?a)) ) AND (begin IS NULL OR begin<=?) AND (expire IS NULL OR expire>=?) AND is_disabled=0 ", 'user_id', $user->pk(), 'free', 'user_group_id', $user_group_ids, sqlDate('now'), sqlDate('now')); } function getNotificationsByTargetProduct(User $user) { return $this->getDi()->db->selectCol("SELECT notification_id FROM ?_notification n WHERE n.notification_id in ( SELECT DISTINCT r.notification_id FROM ?_notification_access r LEFT JOIN ?_access_cache c ON c.user_id=? AND (((c.fn = r.fn) AND (c.id = r.id)) OR (r.fn='product_category_id' AND r.id=-1)) AND ((c.status='active' AND r.start_days IS NULL AND r.stop_days IS NULL) OR (c.status='active' AND c.days BETWEEN IFNULL(r.start_days,0) AND IFNULL(r.stop_days, 90000)) OR (c.days >= IFNULL(r.start_days,0) AND r.stop_days = -1)) WHERE c.user_id IS NOT NULL) AND (n.begin IS NULL OR n.begin<=?) AND (n.expire IS NULL OR n.expire>=?) AND is_disabled=0 ", $user->pk(), sqlDate('now'), sqlDate('now')); } function getNotificationsForUser(User $user) { $ids = array_filter( array_unique( array_merge( $a = $this->getNotificationsByTargetUser($user), $b = $this->getNotificationsByTargetProduct($user) ) ) ); return $ids ? array_filter( $this->getDi()->notificationTable->selectObjects("SELECT * FROM ?_notification WHERE notification_id IN (?a) ORDER BY sort_order", $ids), function(Notification $notification) use ($user) { return $notification->isAvailableForUser($user); } ) : array(); } } /** * @property int $notification_id * @property string $content * @property string $url * @property string $fn * @property int $id * @property string $expire */ class NotificationAccess extends ResourceAccess { } class NotificationClick extends Am_Record { } class NotificationClickTable extends Am_Table { protected $_table = '?_notification_click'; protected $_key = 'notification_click_id'; protected $_recordClass = 'NotificationClick'; function log(Am_Record $user, Am_Record $notification) { $this->_db->query("INSERT INTO ?_notification_click SET ?a", array( 'user_id' => $user->pk(), 'dattm' => sqlDate('now'), 'notification_id' => $notification->pk() )); } }PK\X2default/plugins/misc/facebook/facebook-connect.pngnu[PNG  IHDRk6UsRGBIDATh[l3sffoԘ182`bօ4}phP iiҪHI[EiB6K R+.p=;H*87;&V0Y$.j֤a2b)@R,qDGSx2Ҷ5%V&k,6Peˋs fOJ[鹫Hȷh"5-Ωϯ4=0m xxE0#-XYJGgqBRWĔUSsW);ߺԠ(2h7 gv6,jacסx4gw}=T3ޕ{,|Jbg$ eu$ 9ɓe]mUF^}c[Z'a! k02wJXV] WXMt>.M(BxxE~{) a>r]B5mVNE4ڻbfdg"^ֿ >${g"GdEiqM8&AuTd4MT_!&LXOgr` BT_,EHcm̞' 'Յ(T{,::n"Y=HV2DPlG%D߅((%TEGJUCUtI k"Ya GAN5Sd vh2y6YB/v`>"=.Bd In!FꃒF'T[J<i `}">Ɍ𜌭r(Dou*LVشsL)3hXdBmaM be5XdVg_?̔<ר{&[ڨBZjIENDB`PK\ Hdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookPageTabHelper.phpnu[ */ class FacebookPageTabHelper extends FacebookCanvasLoginHelper { /** * @var array|null */ protected $pageData; /** * Initialize the helper and process available signed request data. * * @param string|null $appId * @param string|null $appSecret */ public function __construct($appId = null, $appSecret = null) { parent::__construct($appId, $appSecret); if (!$this->signedRequest) { return; } $this->pageData = $this->signedRequest->get('page'); } /** * Returns a value from the page data. * * @param string $key * @param mixed|null $default * * @return mixed|null */ public function getPageData($key, $default = null) { if (isset($this->pageData[$key])) { return $this->pageData[$key]; } return $default; } /** * Returns true if the page is liked by the user. * * @return boolean */ public function isLiked() { return $this->getPageData('liked') === true; } /** * Returns true if the user is an admin. * * @return boolean */ public function isAdmin() { return $this->getPageData('admin') === true; } /** * Returns the page id if available. * * @return string|null */ public function getPageId() { return $this->getPageData('id'); } } PK\a @default/plugins/misc/facebook/sdk/src/Facebook/GraphLocation.phpnu[ * @author David Poll */ class GraphLocation extends GraphObject { /** * Returns the street component of the location * * @return string|null */ public function getStreet() { return $this->getProperty('street'); } /** * Returns the city component of the location * * @return string|null */ public function getCity() { return $this->getProperty('city'); } /** * Returns the state component of the location * * @return string|null */ public function getState() { return $this->getProperty('state'); } /** * Returns the country component of the location * * @return string|null */ public function getCountry() { return $this->getProperty('country'); } /** * Returns the zipcode component of the location * * @return string|null */ public function getZip() { return $this->getProperty('zip'); } /** * Returns the latitude component of the location * * @return float|null */ public function getLatitude() { return $this->getProperty('latitude'); } /** * Returns the street component of the location * * @return float|null */ public function getLongitude() { return $this->getProperty('longitude'); } }PK\k}Wdefault/plugins/misc/facebook/sdk/src/Facebook/HttpClients/FacebookStreamHttpClient.phpnu[requestHeaders[$key] = $value; } /** * The headers returned in the response * * @return array */ public function getResponseHeaders() { return $this->responseHeaders; } /** * The HTTP status response code * * @return int */ public function getResponseHttpStatusCode() { return $this->responseHttpStatusCode; } /** * Sends a request to the server * * @param string $url The endpoint to send the request to * @param string $method The request method * @param array $parameters The key value pairs to be sent in the body * * @return string Raw response from the server * * @throws \Facebook\FacebookSDKException */ public function send($url, $method = 'GET', $parameters = array()) { $options = array( 'http' => array( 'method' => $method, 'timeout' => 60, 'ignore_errors' => true ), 'ssl' => array( 'verify_peer' => true, 'verify_peer_name' => true, 'allow_self_signed' => true, // All root certificates are self-signed 'cafile' => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem', ), ); if ($parameters) { $options['http']['content'] = http_build_query($parameters, null, '&'); $this->addRequestHeader('Content-type', 'application/x-www-form-urlencoded'); } $options['http']['header'] = $this->compileHeader(); self::$facebookStream->streamContextCreate($options); $rawResponse = self::$facebookStream->fileGetContents($url); $rawHeaders = self::$facebookStream->getResponseHeaders(); if ($rawResponse === false || !$rawHeaders) { throw new FacebookSDKException('Stream returned an empty response', 660); } $this->responseHeaders = self::formatHeadersToArray($rawHeaders); $this->responseHttpStatusCode = self::getStatusCodeFromHeader($this->responseHeaders['http_code']); return $rawResponse; } /** * Formats the headers for use in the stream wrapper * * @return string */ public function compileHeader() { $header = []; foreach($this->requestHeaders as $k => $v) { $header[] = $k . ': ' . $v; } return implode("\r\n", $header); } /** * Converts array of headers returned from the wrapper into * something standard * * @param array $rawHeaders * * @return array */ public static function formatHeadersToArray(array $rawHeaders) { $headers = array(); foreach ($rawHeaders as $line) { if (strpos($line, ':') === false) { $headers['http_code'] = $line; } else { list ($key, $value) = explode(': ', $line); $headers[$key] = $value; } } return $headers; } /** * Pulls out the HTTP status code from a response header * * @param string $header * * @return int */ public static function getStatusCodeFromHeader($header) { preg_match('|HTTP/\d\.\d\s+(\d+)\s+.*|', $header, $match); return (int) $match[1]; } } PK\ܪR""Udefault/plugins/misc/facebook/sdk/src/Facebook/HttpClients/FacebookCurlHttpClient.phpnu[facebookCurl = $facebookCurl ?: new FacebookCurl(); self::$disableIPv6 = self::$disableIPv6 ?: false; } /** * Disable IPv6 resolution */ public static function disableIPv6() { self::$disableIPv6 = true; } /** * The headers we want to send with the request * * @param string $key * @param string $value */ public function addRequestHeader($key, $value) { $this->requestHeaders[$key] = $value; } /** * The headers returned in the response * * @return array */ public function getResponseHeaders() { return $this->responseHeaders; } /** * The HTTP status response code * * @return int */ public function getResponseHttpStatusCode() { return $this->responseHttpStatusCode; } /** * Sends a request to the server * * @param string $url The endpoint to send the request to * @param string $method The request method * @param array $parameters The key value pairs to be sent in the body * * @return string Raw response from the server * * @throws \Facebook\FacebookSDKException */ public function send($url, $method = 'GET', $parameters = array()) { $this->openConnection($url, $method, $parameters); $this->tryToSendRequest(); if ($this->curlErrorCode) { throw new FacebookSDKException($this->curlErrorMessage, $this->curlErrorCode); } // Separate the raw headers from the raw body list($rawHeaders, $rawBody) = $this->extractResponseHeadersAndBody(); $this->responseHeaders = self::headersToArray($rawHeaders); $this->closeConnection(); return $rawBody; } /** * Opens a new curl connection * * @param string $url The endpoint to send the request to * @param string $method The request method * @param array $parameters The key value pairs to be sent in the body */ public function openConnection($url, $method = 'GET', array $parameters = array()) { $options = array( CURLOPT_URL => $url, CURLOPT_CONNECTTIMEOUT => 10, CURLOPT_TIMEOUT => 60, CURLOPT_RETURNTRANSFER => true, // Follow 301 redirects CURLOPT_HEADER => true, // Enable header processing CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_SSL_VERIFYPEER => true, CURLOPT_CAINFO => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem', ); if ($method !== 'GET') { $options[CURLOPT_POSTFIELDS] = !$this->paramsHaveFile($parameters) ? http_build_query($parameters, null, '&') : $parameters; } if ($method === 'DELETE' || $method === 'PUT') { $options[CURLOPT_CUSTOMREQUEST] = $method; } if (count($this->requestHeaders) > 0) { $options[CURLOPT_HTTPHEADER] = $this->compileRequestHeaders(); } if (self::$disableIPv6) { $options[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; } $this->facebookCurl->init(); $this->facebookCurl->setopt_array($options); } /** * Closes an existing curl connection */ public function closeConnection() { $this->facebookCurl->close(); } /** * Try to send the request */ public function tryToSendRequest() { $this->sendRequest(); $this->curlErrorMessage = $this->facebookCurl->error(); $this->curlErrorCode = $this->facebookCurl->errno(); $this->responseHttpStatusCode = $this->facebookCurl->getinfo(CURLINFO_HTTP_CODE); } /** * Send the request and get the raw response from curl */ public function sendRequest() { $this->rawResponse = $this->facebookCurl->exec(); } /** * Compiles the request headers into a curl-friendly format * * @return array */ public function compileRequestHeaders() { $return = array(); foreach ($this->requestHeaders as $key => $value) { $return[] = $key . ': ' . $value; } return $return; } /** * Extracts the headers and the body into a two-part array * * @return array */ public function extractResponseHeadersAndBody() { $headerSize = self::getHeaderSize(); $rawHeaders = mb_substr($this->rawResponse, 0, $headerSize); $rawBody = mb_substr($this->rawResponse, $headerSize); return array(trim($rawHeaders), trim($rawBody)); } /** * Converts raw header responses into an array * * @param string $rawHeaders * * @return array */ public static function headersToArray($rawHeaders) { $headers = array(); // Normalize line breaks $rawHeaders = str_replace("\r\n", "\n", $rawHeaders); // There will be multiple headers if a 301 was followed // or a proxy was followed, etc $headerCollection = explode("\n\n", trim($rawHeaders)); // We just want the last response (at the end) $rawHeader = array_pop($headerCollection); $headerComponents = explode("\n", $rawHeader); foreach ($headerComponents as $line) { if (strpos($line, ': ') === false) { $headers['http_code'] = $line; } else { list ($key, $value) = explode(': ', $line); $headers[$key] = $value; } } return $headers; } /** * Return proper header size * * @return integer */ private function getHeaderSize() { $headerSize = $this->facebookCurl->getinfo(CURLINFO_HEADER_SIZE); // This corrects a Curl bug where header size does not account // for additional Proxy headers. if ( $this->needsCurlProxyFix() ) { // Additional way to calculate the request body size. if (preg_match('/Content-Length: (\d+)/', $this->rawResponse, $m)) { $headerSize = mb_strlen($this->rawResponse) - $m[1]; } elseif (stripos($this->rawResponse, self::CONNECTION_ESTABLISHED) !== false) { $headerSize += mb_strlen(self::CONNECTION_ESTABLISHED); } } return $headerSize; } /** * Detect versions of Curl which report incorrect header lengths when * using Proxies. * * @return boolean */ private function needsCurlProxyFix() { $ver = $this->facebookCurl->version(); $version = $ver['version_number']; return $version < self::CURL_PROXY_QUIRK_VER; } /** * Detect if the params have a file to upload. * * @param array $params * * @return boolean */ private function paramsHaveFile(array $params) { foreach ($params as $value) { if ($value instanceof \CURLFile) { return true; } } return false; } } PK\ Mdefault/plugins/misc/facebook/sdk/src/Facebook/HttpClients/FacebookStream.phpnu[stream = stream_context_create($options); } /** * The response headers from the stream wrapper * * @return array|null */ public function getResponseHeaders() { return $this->responseHeaders; } /** * Send a stream wrapped request * * @param string $url * * @return mixed */ public function fileGetContents($url) { $rawResponse = file_get_contents($url, false, $this->stream); $this->responseHeaders = $http_response_header; return $rawResponse; } } PK\KrrWdefault/plugins/misc/facebook/sdk/src/Facebook/HttpClients/FacebookGuzzleHttpClient.phpnu[requestHeaders[$key] = $value; } /** * The headers returned in the response * * @return array */ public function getResponseHeaders() { return $this->responseHeaders; } /** * The HTTP status response code * * @return int */ public function getResponseHttpStatusCode() { return $this->responseHttpStatusCode; } /** * Sends a request to the server * * @param string $url The endpoint to send the request to * @param string $method The request method * @param array $parameters The key value pairs to be sent in the body * * @return string Raw response from the server * * @throws \Facebook\FacebookSDKException */ public function send($url, $method = 'GET', $parameters = array()) { $options = array(); if ($parameters) { $options = array('body' => $parameters); } $options['verify'] = __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem'; $request = self::$guzzleClient->createRequest($method, $url, $options); foreach($this->requestHeaders as $k => $v) { $request->setHeader($k, $v); } try { $rawResponse = self::$guzzleClient->send($request); } catch (RequestException $e) { if ($e->getPrevious() instanceof AdapterException) { throw new FacebookSDKException($e->getMessage(), $e->getCode()); } $rawResponse = $e->getResponse(); } $this->responseHttpStatusCode = $rawResponse->getStatusCode(); $this->responseHeaders = $rawResponse->getHeaders(); return $rawResponse->getBody(); } } PK\_Odefault/plugins/misc/facebook/sdk/src/Facebook/HttpClients/FacebookHttpable.phpnu[curl === null) { $this->curl = curl_init(); } } /** * Set a curl option * * @param $key * @param $value */ public function setopt($key, $value) { curl_setopt($this->curl, $key, $value); } /** * Set an array of options to a curl resource * * @param array $options */ public function setopt_array(array $options) { curl_setopt_array($this->curl, $options); } /** * Send a curl request * * @return mixed */ public function exec() { return curl_exec($this->curl); } /** * Return the curl error number * * @return int */ public function errno() { return curl_errno($this->curl); } /** * Return the curl error message * * @return string */ public function error() { return curl_error($this->curl); } /** * Get info from a curl reference * * @param $type * * @return mixed */ public function getinfo($type) { return curl_getinfo($this->curl, $type); } /** * Get the currently installed curl version * * @return array */ public function version() { return curl_version(); } /** * Close the resource connection to curl */ public function close() { curl_close($this->curl); // closed handle has to be initialized again $this->curl = null; } } PK\aQ WWbdefault/plugins/misc/facebook/sdk/src/Facebook/HttpClients/certs/DigiCertHighAssuranceEVRootCA.pemnu[-----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep +OkuE6N36B9K -----END CERTIFICATE----- PK\Jdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookClientException.phpnu[ * @author David Poll */ class FacebookCanvasLoginHelper extends FacebookSignedRequestFromInputHelper { /** * Returns the app data value. * * @return mixed|null */ public function getAppData() { return $this->signedRequest ? $this->signedRequest->get('app_data') : null; } /** * Get raw signed request from POST. * * @return string|null */ public function getRawSignedRequest() { $rawSignedRequest = $this->getRawSignedRequestFromPost(); if ($rawSignedRequest) { return $rawSignedRequest; } return null; } } PK\o0 Cdefault/plugins/misc/facebook/sdk/src/Facebook/GraphSessionInfo.phpnu[ * @author David Poll */ class GraphSessionInfo extends GraphObject { /** * Returns the application id the token was issued for. * * @return string|null */ public function getAppId() { return $this->getProperty('app_id'); } /** * Returns the application name the token was issued for. * * @return string|null */ public function getApplication() { return $this->getProperty('application'); } /** * Returns the date & time that the token expires. * * @return \DateTime|null */ public function getExpiresAt() { $stamp = $this->getProperty('expires_at'); if ($stamp) { return (new \DateTime())->setTimestamp($stamp); } else { return null; } } /** * Returns whether the token is valid. * * @return boolean */ public function isValid() { return $this->getProperty('is_valid'); } /** * Returns the date & time the token was issued at. * * @return \DateTime|null */ public function getIssuedAt() { $stamp = $this->getProperty('issued_at'); if ($stamp) { return (new \DateTime())->setTimestamp($stamp); } else { return null; } } /** * Returns the scope permissions associated with the token. * * @return array */ public function getScopes() { return $this->getPropertyAsArray('scopes'); } /** * Returns the login id of the user associated with the token. * * @return string|null */ public function getId() { return $this->getProperty('user_id'); } }PK\ix.Bdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookRequest.phpnu[ * @author David Poll */ class FacebookRequest { /** * @const string Version number of the Facebook PHP SDK. */ const VERSION = '4.0.23'; /** * @const string Default Graph API version for requests */ const GRAPH_API_VERSION = 'v2.3'; /** * @const string Graph API URL */ const BASE_GRAPH_URL = 'https://graph.facebook.com'; /** * @const string Graph API URL */ const BASE_VIDEO_GRAPH_URL = 'https://graph-video.facebook.com'; /** * @var FacebookSession The session used for this request */ private $session; /** * @var string The HTTP method for the request */ private $method; /** * @var string The path for the request */ private $path; /** * @var array The parameters for the request */ private $params; /** * @var string The Graph API version for the request */ private $version; /** * @var string ETag sent with the request */ private $etag; /** * @var FacebookHttpable HTTP client handler */ private static $httpClientHandler; /** * @var int The number of calls that have been made to Graph. */ public static $requestCount = 0; /** * getSession - Returns the associated FacebookSession. * * @return FacebookSession */ public function getSession() { return $this->session; } /** * getPath - Returns the associated path. * * @return string */ public function getPath() { return $this->path; } /** * getParameters - Returns the associated parameters. * * @return array */ public function getParameters() { return $this->params; } /** * getMethod - Returns the associated method. * * @return string */ public function getMethod() { return $this->method; } /** * getETag - Returns the ETag sent with the request. * * @return string */ public function getETag() { return $this->etag; } /** * setHttpClientHandler - Returns an instance of the HTTP client * handler * * @param \Facebook\HttpClients\FacebookHttpable */ public static function setHttpClientHandler(FacebookHttpable $handler) { static::$httpClientHandler = $handler; } /** * getHttpClientHandler - Returns an instance of the HTTP client * data handler * * @return FacebookHttpable */ public static function getHttpClientHandler() { if (static::$httpClientHandler) { return static::$httpClientHandler; } return function_exists('curl_init') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient(); } /** * FacebookRequest - Returns a new request using the given session. optional * parameters hash will be sent with the request. This object is * immutable. * * @param FacebookSession $session * @param string $method * @param string $path * @param array|null $parameters * @param string|null $version * @param string|null $etag */ public function __construct( FacebookSession $session, $method, $path, $parameters = null, $version = null, $etag = null ) { $this->session = $session; $this->method = $method; $this->path = $path; if ($version) { $this->version = $version; } else { $this->version = static::GRAPH_API_VERSION; } $this->etag = $etag; $params = ($parameters ?: array()); if ($session && ! isset($params['access_token'])) { $params['access_token'] = $session->getToken(); } if (! isset($params['appsecret_proof']) && FacebookSession::useAppSecretProof()) { $params['appsecret_proof'] = $this->getAppSecretProof( $params['access_token'] ); } $this->params = $params; } /** * Returns the base Graph URL. * * @return string */ protected function getRequestURL() { $pathElements = explode('/', $this->path); $lastInPath = end($pathElements); if ($lastInPath == 'videos' && $this->method === 'POST') { $baseUrl = static::BASE_VIDEO_GRAPH_URL; } else { $baseUrl = static::BASE_GRAPH_URL; } return $baseUrl . '/' . $this->version . $this->path; } /** * execute - Makes the request to Facebook and returns the result. * * @return FacebookResponse * * @throws FacebookSDKException * @throws FacebookRequestException */ public function execute() { $url = $this->getRequestURL(); $params = $this->getParameters(); if ($this->method === 'GET') { $url = self::appendParamsToUrl($url, $params); $params = array(); } $connection = self::getHttpClientHandler(); $connection->addRequestHeader('User-Agent', 'fb-php-' . self::VERSION); $connection->addRequestHeader('Accept-Encoding', '*'); // Support all available encodings. // ETag if (null !== $this->etag) { $connection->addRequestHeader('If-None-Match', $this->etag); } // Should throw `FacebookSDKException` exception on HTTP client error. // Don't catch to allow it to bubble up. $result = $connection->send($url, $this->method, $params); static::$requestCount++; $etagHit = 304 === $connection->getResponseHttpStatusCode(); $headers = $connection->getResponseHeaders(); $etagReceived = isset($headers['ETag']) ? $headers['ETag'] : null; $decodedResult = json_decode($result); if ($decodedResult === null) { $out = array(); parse_str($result, $out); return new FacebookResponse($this, $out, $result, $etagHit, $etagReceived); } if (isset($decodedResult->error)) { throw FacebookRequestException::create( $result, $decodedResult->error, $connection->getResponseHttpStatusCode() ); } return new FacebookResponse($this, $decodedResult, $result, $etagHit, $etagReceived); } /** * Generate and return the appsecret_proof value for an access_token * * @param string $token * * @return string */ public function getAppSecretProof($token) { return hash_hmac('sha256', $token, FacebookSession::_getTargetAppSecret()); } /** * appendParamsToUrl - Gracefully appends params to the URL. * * @param string $url * @param array $params * * @return string */ public static function appendParamsToUrl($url, array $params = array()) { if (!$params) { return $url; } if (strpos($url, '?') === false) { return $url . '?' . http_build_query($params, null, '&'); } list($path, $query_string) = explode('?', $url, 2); parse_str($query_string, $query_array); // Favor params from the original URL over $params $params = array_merge($params, $query_array); return $path . '?' . http_build_query($params, null, '&'); } } PK\Jjo<default/plugins/misc/facebook/sdk/src/Facebook/GraphPage.phpnu[ */ class GraphPage extends GraphObject { /** * Returns the ID for the user's page as a string if present. * * @return string|null */ public function getId() { return $this->getProperty('id'); } /** * Returns the Category for the user's page as a string if present. * * @return string|null */ public function getCategory() { return $this->getProperty('category'); } /** * Returns the Name of the user's page as a string if present. * * @return string|null */ public function getName() { return $this->getProperty('name'); } }PK\hqrKdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookRequestException.phpnu[ * @author David Poll */ class FacebookRequestException extends FacebookSDKException { /** * @var int Status code for the response causing the exception */ private $statusCode; /** * @var string Raw response */ private $rawResponse; /** * @var array Decoded response */ private $responseData; /** * Creates a FacebookRequestException. * * @param string $rawResponse The raw response from the Graph API * @param array $responseData The decoded response from the Graph API * @param int $statusCode */ public function __construct($rawResponse, $responseData, $statusCode) { $this->rawResponse = $rawResponse; $this->statusCode = $statusCode; $this->responseData = self::convertToArray($responseData); parent::__construct( $this->get('message', 'Unknown Exception'), $this->get('code', -1), null ); } /** * Process an error payload from the Graph API and return the appropriate * exception subclass. * * @param string $raw the raw response from the Graph API * @param array $data the decoded response from the Graph API * @param int $statusCode the HTTP response code * * @return FacebookRequestException */ public static function create($raw, $data, $statusCode) { $data = self::convertToArray($data); if (!isset($data['error']['code']) && isset($data['code'])) { $data = array('error' => $data); } $code = (isset($data['error']['code']) ? (int) $data['error']['code'] : null); if (isset($data['error']['error_subcode'])) { switch ($data['error']['error_subcode']) { // Other authentication issues case 458: case 459: case 460: case 463: case 464: case 467: return new FacebookAuthorizationException($raw, $data, $statusCode); break; } } switch ($code) { // Login status or token expired, revoked, or invalid case 100: case 102: case 190: return new FacebookAuthorizationException($raw, $data, $statusCode); break; // Server issue, possible downtime case 1: case 2: return new FacebookServerException($raw, $data, $statusCode); break; // API Throttling case 4: case 17: case 341: return new FacebookThrottleException($raw, $data, $statusCode); break; // Duplicate Post case 506: return new FacebookClientException($raw, $data, $statusCode); break; } // Missing Permissions if ($code === 10 || ($code >= 200 && $code <= 299)) { return new FacebookPermissionException($raw, $data, $statusCode); } // OAuth authentication error if (isset($data['error']['type']) and $data['error']['type'] === 'OAuthException') { return new FacebookAuthorizationException($raw, $data, $statusCode); } // All others return new FacebookOtherException($raw, $data, $statusCode); } /** * Checks isset and returns that or a default value. * * @param string $key * @param mixed $default * * @return mixed */ private function get($key, $default = null) { if (isset($this->responseData['error'][$key])) { return $this->responseData['error'][$key]; } return $default; } /** * Returns the HTTP status code * * @return int */ public function getHttpStatusCode() { return $this->statusCode; } /** * Returns the sub-error code * * @return int */ public function getSubErrorCode() { return $this->get('error_subcode', -1); } /** * Returns the error type * * @return string */ public function getErrorType() { return $this->get('type', ''); } /** * Returns the raw response used to create the exception. * * @return string */ public function getRawResponse() { return $this->rawResponse; } /** * Returns the decoded response used to create the exception. * * @return array */ public function getResponse() { return $this->responseData; } /** * Converts a stdClass object to an array * * @param mixed $object * * @return array */ private static function convertToArray($object) { if ($object instanceof \stdClass) { return get_object_vars($object); } return $object; } }PK\\Pdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookJavaScriptLoginHelper.phpnu[ * @author David Poll */ class FacebookJavaScriptLoginHelper extends FacebookSignedRequestFromInputHelper { /** * Get raw signed request from the cookie. * * @return string|null */ public function getRawSignedRequest() { return $this->getRawSignedRequestFromCookie(); } } PK\1on  Fdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookPermissions.phpnu[rawSignedRequest = $rawSignedRequest; $this->payload = static::parse($rawSignedRequest, $state, $appSecret); } /** * Returns the raw signed request data. * * @return string|null */ public function getRawSignedRequest() { return $this->rawSignedRequest; } /** * Returns the parsed signed request data. * * @return array|null */ public function getPayload() { return $this->payload; } /** * Returns a property from the signed request data if available. * * @param string $key * @param mixed|null $default * * @return mixed|null */ public function get($key, $default = null) { if (isset($this->payload[$key])) { return $this->payload[$key]; } return $default; } /** * Returns user_id from signed request data if available. * * @return string|null */ public function getUserId() { return $this->get('user_id'); } /** * Checks for OAuth data in the payload. * * @return boolean */ public function hasOAuthData() { return isset($this->payload['oauth_token']) || isset($this->payload['code']); } /** * Creates a signed request from an array of data. * * @param array $payload * @param string|null $appSecret * * @return string */ public static function make(array $payload, $appSecret = null) { $payload['algorithm'] = 'HMAC-SHA256'; $payload['issued_at'] = time(); $encodedPayload = static::base64UrlEncode(json_encode($payload)); $hashedSig = static::hashSignature($encodedPayload, $appSecret); $encodedSig = static::base64UrlEncode($hashedSig); return $encodedSig.'.'.$encodedPayload; } /** * Validates and decodes a signed request and returns * the payload as an array. * * @param string $signedRequest * @param string|null $state * @param string|null $appSecret * * @return array */ public static function parse($signedRequest, $state = null, $appSecret = null) { list($encodedSig, $encodedPayload) = static::split($signedRequest); // Signature validation $sig = static::decodeSignature($encodedSig); $hashedSig = static::hashSignature($encodedPayload, $appSecret); static::validateSignature($hashedSig, $sig); // Payload validation $data = static::decodePayload($encodedPayload); static::validateAlgorithm($data); if ($state) { static::validateCsrf($data, $state); } return $data; } /** * Validates the format of a signed request. * * @param string $signedRequest * * @throws FacebookSDKException */ public static function validateFormat($signedRequest) { if (strpos($signedRequest, '.') !== false) { return; } throw new FacebookSDKException( 'Malformed signed request.', 606 ); } /** * Decodes a raw valid signed request. * * @param string $signedRequest * * @returns array */ public static function split($signedRequest) { static::validateFormat($signedRequest); return explode('.', $signedRequest, 2); } /** * Decodes the raw signature from a signed request. * * @param string $encodedSig * * @returns string * * @throws FacebookSDKException */ public static function decodeSignature($encodedSig) { $sig = static::base64UrlDecode($encodedSig); if ($sig) { return $sig; } throw new FacebookSDKException( 'Signed request has malformed encoded signature data.', 607 ); } /** * Decodes the raw payload from a signed request. * * @param string $encodedPayload * * @returns array * * @throws FacebookSDKException */ public static function decodePayload($encodedPayload) { $payload = static::base64UrlDecode($encodedPayload); if ($payload) { $payload = json_decode($payload, true); } if (is_array($payload)) { return $payload; } throw new FacebookSDKException( 'Signed request has malformed encoded payload data.', 607 ); } /** * Validates the algorithm used in a signed request. * * @param array $data * * @throws FacebookSDKException */ public static function validateAlgorithm(array $data) { if (isset($data['algorithm']) && $data['algorithm'] === 'HMAC-SHA256') { return; } throw new FacebookSDKException( 'Signed request is using the wrong algorithm.', 605 ); } /** * Hashes the signature used in a signed request. * * @param string $encodedData * @param string|null $appSecret * * @return string * * @throws FacebookSDKException */ public static function hashSignature($encodedData, $appSecret = null) { $hashedSig = hash_hmac( 'sha256', $encodedData, FacebookSession::_getTargetAppSecret($appSecret), $raw_output = true ); if ($hashedSig) { return $hashedSig; } throw new FacebookSDKException( 'Unable to hash signature from encoded payload data.', 602 ); } /** * Validates the signature used in a signed request. * * @param string $hashedSig * @param string $sig * * @throws FacebookSDKException */ public static function validateSignature($hashedSig, $sig) { $intSignatureLength = mb_strlen($sig); if (mb_strlen($hashedSig) === $intSignatureLength) { $validate = 0; for ($i = 0; $i < $intSignatureLength; $i++) { $validate |= ord($hashedSig[$i]) ^ ord($sig[$i]); } if ($validate === 0) { return; } } throw new FacebookSDKException( 'Signed request has an invalid signature.', 602 ); } /** * Validates a signed request against CSRF. * * @param array $data * @param string $state * * @throws FacebookSDKException */ public static function validateCsrf(array $data, $state) { if (isset($data['state'])) { $savedLen = strlen($state); $givenLen = strlen($data['state']); if ($savedLen == $givenLen) { $result = 0; for ($i = 0; $i < $savedLen; $i++) { $result |= ord($state[$i]) ^ ord($data['state'][$i]); } if ($result === 0) { return; } } } throw new FacebookSDKException( 'Signed request did not pass CSRF validation.', 604 ); } /** * Base64 decoding which replaces characters: * + instead of - * / instead of _ * @link http://en.wikipedia.org/wiki/Base64#URL_applications * * @param string $input base64 url encoded input * * @return string decoded string */ public static function base64UrlDecode($input) { $urlDecodedBase64 = strtr($input, '-_', '+/'); static::validateBase64($urlDecodedBase64); return base64_decode($urlDecodedBase64); } /** * Base64 encoding which replaces characters: * + instead of - * / instead of _ * @link http://en.wikipedia.org/wiki/Base64#URL_applications * * @param string $input string to encode * * @return string base64 url encoded input */ public static function base64UrlEncode($input) { return strtr(base64_encode($input), '+/', '-_'); } /** * Validates a base64 string. * * @param string $input base64 value to validate * * @throws FacebookSDKException */ public static function validateBase64($input) { $pattern = '/^[a-zA-Z0-9\/\r\n+]*={0,2}$/'; if (preg_match($pattern, $input)) { return; } throw new FacebookSDKException( 'Signed request contains malformed base64 encoding.', 608 ); } } PK\;q&&Gdefault/plugins/misc/facebook/sdk/src/Facebook/Entities/AccessToken.phpnu[accessToken = $accessToken; if ($expiresAt) { $this->setExpiresAtFromTimeStamp($expiresAt); } $this->machineId = $machineId; } /** * Setter for expires_at. * * @param int $timeStamp */ protected function setExpiresAtFromTimeStamp($timeStamp) { $dt = new \DateTime(); $dt->setTimestamp($timeStamp); $this->expiresAt = $dt; } /** * Getter for expiresAt. * * @return \DateTime|null */ public function getExpiresAt() { return $this->expiresAt; } /** * Getter for machineId. * * @return string|null */ public function getMachineId() { return $this->machineId; } /** * Determines whether or not this is a long-lived token. * * @return bool */ public function isLongLived() { if ($this->expiresAt) { return $this->expiresAt->getTimestamp() > time() + (60 * 60 * 2); } return false; } /** * Checks the validity of the access token. * * @param string|null $appId Application ID to use * @param string|null $appSecret App secret value to use * @param string|null $machineId * * @return boolean */ public function isValid($appId = null, $appSecret = null, $machineId = null) { $accessTokenInfo = $this->getInfo($appId, $appSecret); $machineId = $machineId ?: $this->machineId; return static::validateAccessToken($accessTokenInfo, $appId, $machineId); } /** * Ensures the provided GraphSessionInfo object is valid, * throwing an exception if not. Ensures the appId matches, * that the machineId matches if it's being used, * that the token is valid and has not expired. * * @param GraphSessionInfo $tokenInfo * @param string|null $appId Application ID to use * @param string|null $machineId * * @return boolean */ public static function validateAccessToken(GraphSessionInfo $tokenInfo, $appId = null, $machineId = null) { $targetAppId = FacebookSession::_getTargetAppId($appId); $appIdIsValid = $tokenInfo->getAppId() == $targetAppId; $machineIdIsValid = $tokenInfo->getProperty('machine_id') == $machineId; $accessTokenIsValid = $tokenInfo->isValid(); $accessTokenIsStillAlive = true; // Not all access tokens return an expiration. E.g. an app access token. if ($tokenInfo->getExpiresAt() instanceof \DateTime) { $accessTokenIsStillAlive = $tokenInfo->getExpiresAt()->getTimestamp() >= time(); } return $appIdIsValid && $machineIdIsValid && $accessTokenIsValid && $accessTokenIsStillAlive; } /** * Get a valid access token from a code. * * @param string $code * @param string|null $appId * @param string|null $appSecret * @param string|null $machineId * * @return AccessToken */ public static function getAccessTokenFromCode($code, $appId = null, $appSecret = null, $machineId = null) { $params = array( 'code' => $code, 'redirect_uri' => '', ); if ($machineId) { $params['machine_id'] = $machineId; } return static::requestAccessToken($params, $appId, $appSecret); } /** * Get a valid code from an access token. * * @param AccessToken|string $accessToken * @param string|null $appId * @param string|null $appSecret * * @return AccessToken */ public static function getCodeFromAccessToken($accessToken, $appId = null, $appSecret = null) { $accessToken = (string) $accessToken; $params = array( 'access_token' => $accessToken, 'redirect_uri' => '', ); return static::requestCode($params, $appId, $appSecret); } /** * Exchanges a short lived access token with a long lived access token. * * @param string|null $appId * @param string|null $appSecret * * @return AccessToken */ public function extend($appId = null, $appSecret = null) { $params = array( 'grant_type' => 'fb_exchange_token', 'fb_exchange_token' => $this->accessToken, ); return static::requestAccessToken($params, $appId, $appSecret); } /** * Request an access token based on a set of params. * * @param array $params * @param string|null $appId * @param string|null $appSecret * * @return AccessToken * * @throws FacebookRequestException */ public static function requestAccessToken(array $params, $appId = null, $appSecret = null) { $response = static::request('/oauth/access_token', $params, $appId, $appSecret); $data = $response->getResponse(); /** * @TODO fix this malarkey - getResponse() should always return an object * @see https://github.com/facebook/facebook-php-sdk-v4/issues/36 */ if (is_array($data)) { if (isset($data['access_token'])) { $expiresAt = isset($data['expires']) ? time() + $data['expires'] : 0; return new static($data['access_token'], $expiresAt); } } elseif($data instanceof \stdClass) { if (isset($data->access_token)) { $expiresAt = isset($data->expires_in) ? time() + $data->expires_in : 0; $machineId = isset($data->machine_id) ? (string) $data->machine_id : null; return new static((string) $data->access_token, $expiresAt, $machineId); } } throw FacebookRequestException::create( $response->getRawResponse(), $data, 401 ); } /** * Request a code from a long lived access token. * * @param array $params * @param string|null $appId * @param string|null $appSecret * * @return string * * @throws FacebookRequestException */ public static function requestCode(array $params, $appId = null, $appSecret = null) { $response = static::request('/oauth/client_code', $params, $appId, $appSecret); $data = $response->getResponse(); if (isset($data->code)) { return (string) $data->code; } throw FacebookRequestException::create( $response->getRawResponse(), $data, 401 ); } /** * Send a request to Graph with an app access token. * * @param string $endpoint * @param array $params * @param string|null $appId * @param string|null $appSecret * * @return \Facebook\FacebookResponse * * @throws FacebookRequestException */ protected static function request($endpoint, array $params, $appId = null, $appSecret = null) { $targetAppId = FacebookSession::_getTargetAppId($appId); $targetAppSecret = FacebookSession::_getTargetAppSecret($appSecret); if (!isset($params['client_id'])) { $params['client_id'] = $targetAppId; } if (!isset($params['client_secret'])) { $params['client_secret'] = $targetAppSecret; } // The response for this endpoint is not JSON, so it must be handled // differently, not as a GraphObject. $request = new FacebookRequest( FacebookSession::newAppSession($targetAppId, $targetAppSecret), 'GET', $endpoint, $params ); return $request->execute(); } /** * Get more info about an access token. * * @param string|null $appId * @param string|null $appSecret * * @return GraphSessionInfo */ public function getInfo($appId = null, $appSecret = null) { $params = array('input_token' => $this->accessToken); $request = new FacebookRequest( FacebookSession::newAppSession($appId, $appSecret), 'GET', '/debug_token', $params ); $response = $request->execute()->getGraphObject(GraphSessionInfo::className()); // Update the data on this token if ($response->getExpiresAt()) { $this->expiresAt = $response->getExpiresAt(); } return $response; } /** * Returns the access token as a string. * * @return string */ public function __toString() { return $this->accessToken; } /** * Returns true if the access token is an app session token. * * @return bool */ public function isAppSession() { return strpos($this->accessToken, '|') !== false; } } PK\gNdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookPermissionException.phpnu[ * @author David Poll */ class FacebookSession { /** * @var string */ private static $defaultAppId; /** * @var string */ private static $defaultAppSecret; /** * @var AccessToken The AccessToken entity for this connection. */ private $accessToken; /** * @var SignedRequest */ private $signedRequest; /** * @var bool */ protected static $useAppSecretProof = true; /** * When creating a Session from an access_token, use: * var $session = new FacebookSession($accessToken); * This will validate the token and provide a Session object ready for use. * It will throw a SessionException in case of error. * * @param AccessToken|string $accessToken * @param SignedRequest $signedRequest The SignedRequest entity */ public function __construct($accessToken, SignedRequest $signedRequest = null) { $this->accessToken = $accessToken instanceof AccessToken ? $accessToken : new AccessToken($accessToken); $this->signedRequest = $signedRequest; } /** * Returns the access token. * * @return string */ public function getToken() { return (string) $this->accessToken; } /** * Returns the access token entity. * * @return AccessToken */ public function getAccessToken() { return $this->accessToken; } /** * Returns the SignedRequest entity. * * @return SignedRequest */ public function getSignedRequest() { return $this->signedRequest; } /** * Returns the signed request payload. * * @return null|array */ public function getSignedRequestData() { return $this->signedRequest ? $this->signedRequest->getPayload() : null; } /** * Returns a property from the signed request data if available. * * @param string $key * * @return null|mixed */ public function getSignedRequestProperty($key) { return $this->signedRequest ? $this->signedRequest->get($key) : null; } /** * Returns user_id from signed request data if available. * * @return null|string */ public function getUserId() { return $this->signedRequest ? $this->signedRequest->getUserId() : null; } // @TODO Remove getSessionInfo() in 4.1: can be accessed from AccessToken directly /** * getSessionInfo - Makes a request to /debug_token with the appropriate * arguments to get debug information about the sessions token. * * @param string|null $appId * @param string|null $appSecret * * @return GraphSessionInfo */ public function getSessionInfo($appId = null, $appSecret = null) { return $this->accessToken->getInfo($appId, $appSecret); } // @TODO Remove getLongLivedSession() in 4.1: can be accessed from AccessToken directly /** * getLongLivedSession - Returns a new Facebook session resulting from * extending a short-lived access token. If this session is not * short-lived, returns $this. * * @param string|null $appId * @param string|null $appSecret * * @return FacebookSession */ public function getLongLivedSession($appId = null, $appSecret = null) { $longLivedAccessToken = $this->accessToken->extend($appId, $appSecret); return new static($longLivedAccessToken, $this->signedRequest); } // @TODO Remove getExchangeToken() in 4.1: can be accessed from AccessToken directly /** * getExchangeToken - Returns an exchange token string which can be sent * back to clients and exchanged for a device-linked access token. * * @param string|null $appId * @param string|null $appSecret * * @return string */ public function getExchangeToken($appId = null, $appSecret = null) { return AccessToken::getCodeFromAccessToken($this->accessToken, $appId, $appSecret); } // @TODO Remove validate() in 4.1: can be accessed from AccessToken directly /** * validate - Ensures the current session is valid, throwing an exception if * not. Fetches token info from Facebook. * * @param string|null $appId Application ID to use * @param string|null $appSecret App secret value to use * @param string|null $machineId * * @return boolean * * @throws FacebookSDKException */ public function validate($appId = null, $appSecret = null, $machineId = null) { if ($this->accessToken->isValid($appId, $appSecret, $machineId)) { return true; } // @TODO For v4.1 this should not throw an exception, but just return false. throw new FacebookSDKException( 'Session has expired, or is not valid for this app.', 601 ); } // @TODO Remove validateSessionInfo() in 4.1: can be accessed from AccessToken directly /** * validateTokenInfo - Ensures the provided GraphSessionInfo object is valid, * throwing an exception if not. Ensures the appId matches, * that the token is valid and has not expired. * * @param GraphSessionInfo $tokenInfo * @param string|null $appId Application ID to use * @param string|null $machineId * * @return boolean * * @throws FacebookSDKException */ public static function validateSessionInfo(GraphSessionInfo $tokenInfo, $appId = null, $machineId = null) { if (AccessToken::validateAccessToken($tokenInfo, $appId, $machineId)) { return true; } // @TODO For v4.1 this should not throw an exception, but just return false. throw new FacebookSDKException( 'Session has expired, or is not valid for this app.', 601 ); } /** * newSessionFromSignedRequest - Returns a FacebookSession for a * given signed request. * * @param SignedRequest $signedRequest * * @return FacebookSession */ public static function newSessionFromSignedRequest(SignedRequest $signedRequest) { if ($signedRequest->get('code') && !$signedRequest->get('oauth_token')) { return self::newSessionAfterValidation($signedRequest); } $accessToken = $signedRequest->get('oauth_token'); $expiresAt = $signedRequest->get('expires', 0); $accessToken = new AccessToken($accessToken, $expiresAt); return new static($accessToken, $signedRequest); } /** * newSessionAfterValidation - Returns a FacebookSession for a * validated & parsed signed request. * * @param SignedRequest $signedRequest * * @return FacebookSession */ protected static function newSessionAfterValidation(SignedRequest $signedRequest) { $code = $signedRequest->get('code'); $accessToken = AccessToken::getAccessTokenFromCode($code); return new static($accessToken, $signedRequest); } /** * newAppSession - Returns a FacebookSession configured with a token for the * application which can be used for publishing and requesting app-level * information. * * @param string|null $appId Application ID to use * @param string|null $appSecret App secret value to use * * @return FacebookSession */ public static function newAppSession($appId = null, $appSecret = null) { $targetAppId = static::_getTargetAppId($appId); $targetAppSecret = static::_getTargetAppSecret($appSecret); return new FacebookSession( $targetAppId . '|' . $targetAppSecret ); } /** * setDefaultApplication - Will set the static default appId and appSecret * to be used for API requests. * * @param string $appId Application ID to use by default * @param string $appSecret App secret value to use by default */ public static function setDefaultApplication($appId, $appSecret) { self::$defaultAppId = $appId; self::$defaultAppSecret = $appSecret; } /** * _getTargetAppId - Will return either the provided app Id or the default, * throwing if neither are populated. * * @param string $appId * * @return string * * @throws FacebookSDKException */ public static function _getTargetAppId($appId = null) { $target = ($appId ?: self::$defaultAppId); if (!$target) { throw new FacebookSDKException( 'You must provide or set a default application id.', 700 ); } return $target; } /** * _getTargetAppSecret - Will return either the provided app secret or the * default, throwing if neither are populated. * * @param string $appSecret * * @return string * * @throws FacebookSDKException */ public static function _getTargetAppSecret($appSecret = null) { $target = ($appSecret ?: self::$defaultAppSecret); if (!$target) { throw new FacebookSDKException( 'You must provide or set a default application secret.', 701 ); } return $target; } /** * Enable or disable sending the appsecret_proof with requests. * * @param bool $on */ public static function enableAppSecretProof($on = true) { static::$useAppSecretProof = ($on ? true : false); } /** * Get whether or not appsecret_proof should be sent with requests. * * @return bool */ public static function useAppSecretProof() { return static::$useAppSecretProof; } } PK\ܕVGdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookSDKException.phpnu[ */ class GraphAlbum extends GraphObject { /** * Returns the ID for the album. * * @return string|null */ public function getId() { return $this->getProperty('id'); } /** * Returns whether the viewer can upload photos to this album. * * @return boolean|null */ public function canUpload() { return $this->getProperty('can_upload'); } /** * Returns the number of photos in this album. * * @return int|null */ public function getCount() { return $this->getProperty('count'); } /** * Returns the ID of the album's cover photo. * * @return string|null */ public function getCoverPhoto() { return $this->getProperty('cover_photo'); } /** * Returns the time the album was initially created. * * @return \DateTime|null */ public function getCreatedTime() { $value = $this->getProperty('created_time'); if ($value) { return new \DateTime($value); } return null; } /** * Returns the time the album was updated. * * @return \DateTime|null */ public function getUpdatedTime() { $value = $this->getProperty('updated_time'); if ($value) { return new \DateTime($value); } return null; } /** * Returns the description of the album. * * @return string|null */ public function getDescription() { return $this->getProperty('description'); } /** * Returns profile that created the album. * * @return GraphUser|null */ public function getFrom() { return $this->getProperty('from', GraphUser::className()); } /** * Returns a link to this album on Facebook. * * @return string|null */ public function getLink() { return $this->getProperty('link'); } /** * Returns the textual location of the album. * * @return string|null */ public function getLocation() { return $this->getProperty('location'); } /** * Returns the title of the album. * * @return string|null */ public function getName() { return $this->getProperty('name'); } /** * Returns the privacy settings for the album. * * @return string|null */ public function getPrivacy() { return $this->getProperty('privacy'); } /** * Returns the type of the album. enum{profile, mobile, wall, normal, album} * * @return string|null */ public function getType() { return $this->getProperty('type'); } //TODO: public function getPlace() that should return GraphPage } PK\''Ndefault/plugins/misc/facebook/sdk/src/Facebook/FacebookRedirectLoginHelper.phpnu[ * @author David Poll */ class FacebookRedirectLoginHelper { /** * @var string The application id */ private $appId; /** * @var string The application secret */ private $appSecret; /** * @var string The redirect URL for the application */ private $redirectUrl; /** * @var string Prefix to use for session variables */ private $sessionPrefix = 'FBRLH_'; /** * @var string State token for CSRF validation */ protected $state; /** * @var boolean Toggle for PHP session status check */ protected $checkForSessionStatus = true; /** * Constructs a RedirectLoginHelper for a given appId and redirectUrl. * * @param string $redirectUrl The URL Facebook should redirect users to * after login * @param string $appId The application id * @param string $appSecret The application secret */ public function __construct($redirectUrl, $appId = null, $appSecret = null) { $this->appId = FacebookSession::_getTargetAppId($appId); $this->appSecret = FacebookSession::_getTargetAppSecret($appSecret); $this->redirectUrl = $redirectUrl; } /** * Stores CSRF state and returns a URL to which the user should be sent to * in order to continue the login process with Facebook. The * provided redirectUrl should invoke the handleRedirect method. * * @param array $scope List of permissions to request during login * @param string $version Optional Graph API version if not default (v2.0) * @param boolean $displayAsPopup Indicate if the page will be displayed as a popup * @param bool|string $authType 'reauthenticate' or 'https', true is equivalent to 'reauthenticate', * false or invalid value will not add auth type parameter * * @return string */ public function getLoginUrl(array $scope = array(), $version = null, $displayAsPopup = false, $authType = false) { $version = ($version ?: FacebookRequest::GRAPH_API_VERSION); $this->state = $this->random(16); $this->storeState($this->state); $params = array( 'client_id' => $this->appId, 'redirect_uri' => $this->redirectUrl, 'state' => $this->state, 'sdk' => 'php-sdk-' . FacebookRequest::VERSION, 'scope' => implode(',', $scope) ); if (in_array($authType, array(true, 'reauthenticate', 'https'), true)) { $params['auth_type'] = $authType === true ? 'reauthenticate' : $authType; } if ($displayAsPopup) { $params['display'] = 'popup'; } return 'https://www.facebook.com/' . $version . '/dialog/oauth?' . http_build_query($params, null, '&'); } /** * Returns a URL to which the user should be sent to re-request permissions. * * @param array $scope List of permissions to re-request * @param string $version Optional Graph API version if not default (v2.0) * * @return string */ public function getReRequestUrl(array $scope = array(), $version = null) { $version = ($version ?: FacebookRequest::GRAPH_API_VERSION); $this->state = $this->random(16); $this->storeState($this->state); $params = array( 'client_id' => $this->appId, 'redirect_uri' => $this->redirectUrl, 'state' => $this->state, 'sdk' => 'php-sdk-' . FacebookRequest::VERSION, 'auth_type' => 'rerequest', 'scope' => implode(',', $scope) ); return 'https://www.facebook.com/' . $version . '/dialog/oauth?' . http_build_query($params, null, '&'); } /** * Returns the URL to send the user in order to log out of Facebook. * * @param FacebookSession $session The session that will be logged out * @param string $next The url Facebook should redirect the user to after * a successful logout * * @return string * * @throws FacebookSDKException */ public function getLogoutUrl(FacebookSession $session, $next) { if ($session->getAccessToken()->isAppSession()) { throw new FacebookSDKException( 'Cannot generate a Logout URL with an App Session.', 722 ); } $params = array( 'next' => $next, 'access_token' => $session->getToken() ); return 'https://www.facebook.com/logout.php?' . http_build_query($params, null, '&'); } /** * Handles a response from Facebook, including a CSRF check, and returns a * FacebookSession. * * @return FacebookSession|null */ public function getSessionFromRedirect() { if ($this->isValidRedirect()) { $params = array( 'client_id' => FacebookSession::_getTargetAppId($this->appId), 'redirect_uri' => $this->redirectUrl, 'client_secret' => FacebookSession::_getTargetAppSecret($this->appSecret), 'code' => $this->getCode() ); $response = (new FacebookRequest( FacebookSession::newAppSession($this->appId, $this->appSecret), 'GET', '/oauth/access_token', $params ))->execute()->getResponse(); // Graph v2.3 and greater return objects on the /oauth/access_token endpoint $accessToken = null; if (is_object($response) && isset($response->access_token)) { $accessToken = $response->access_token; } elseif (is_array($response) && isset($response['access_token'])) { $accessToken = $response['access_token']; } if (isset($accessToken)) { return new FacebookSession($accessToken); } } return null; } /** * Check if a redirect has a valid state. * * @return bool */ protected function isValidRedirect() { $savedState = $this->loadState(); if (!$this->getCode() || !isset($_GET['state'])) { return false; } $givenState = $_GET['state']; $savedLen = mb_strlen($savedState); $givenLen = mb_strlen($givenState); if ($savedLen !== $givenLen) { return false; } $result = 0; for ($i = 0; $i < $savedLen; $i++) { $result |= ord($savedState[$i]) ^ ord($givenState[$i]); } return $result === 0; } /** * Return the code. * * @return string|null */ protected function getCode() { return isset($_GET['code']) ? $_GET['code'] : null; } /** * Stores a state string in session storage for CSRF protection. * Developers should subclass and override this method if they want to store * this state in a different location. * * @param string $state * * @throws FacebookSDKException */ protected function storeState($state) { if ($this->checkForSessionStatus === true && session_status() !== PHP_SESSION_ACTIVE) { throw new FacebookSDKException( 'Session not active, could not store state.', 720 ); } $_SESSION[$this->sessionPrefix . 'state'] = $state; } /** * Loads a state string from session storage for CSRF validation. May return * null if no object exists. Developers should subclass and override this * method if they want to load the state from a different location. * * @return string|null * * @throws FacebookSDKException */ protected function loadState() { if ($this->checkForSessionStatus === true && session_status() !== PHP_SESSION_ACTIVE) { throw new FacebookSDKException( 'Session not active, could not load state.', 721 ); } if (isset($_SESSION[$this->sessionPrefix . 'state'])) { $this->state = $_SESSION[$this->sessionPrefix . 'state']; return $this->state; } return null; } /** * Generate a cryptographically secure pseudrandom number * * @param integer $bytes - number of bytes to return * * @return string * * @throws FacebookSDKException * * @todo Support Windows platforms */ public function random($bytes) { if (!is_numeric($bytes)) { throw new FacebookSDKException( 'random() expects an integer' ); } if ($bytes < 1) { throw new FacebookSDKException( 'random() expects an integer greater than zero' ); } $buf = ''; // http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ if (!ini_get('open_basedir') && is_readable('/dev/urandom')) { $fp = fopen('/dev/urandom', 'rb'); if ($fp !== FALSE) { $buf = fread($fp, $bytes); fclose($fp); if($buf !== FALSE) { return bin2hex($buf); } } } if (function_exists('mcrypt_create_iv')) { $buf = mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); if ($buf !== FALSE) { return bin2hex($buf); } } while (strlen($buf) < $bytes) { $buf .= md5(uniqid(mt_rand(), true), true); // We are appending raw binary } return bin2hex(substr($buf, 0, $bytes)); } /** * Disables the session_status() check when using $_SESSION */ public function disableSessionStatusCheck() { $this->checkForSessionStatus = false; } } PK\$Ldefault/plugins/misc/facebook/sdk/src/Facebook/FacebookThrottleException.phpnu[ */ class GraphUserPage extends GraphObject { /** * Returns the ID for the user's page as a string if present. * * @return string|null */ public function getId() { return $this->getProperty('id'); } /** * Returns the Category for the user's page as a string if present. * * @return string|null */ public function getCategory() { return $this->getProperty('category'); } /** * Returns the Name of the user's page as a string if present. * * @return string|null */ public function getName() { return $this->getProperty('name'); } /** * Returns the Access Token used to access the user's page as a string if present. * * @return string|null */ public function getAccessToken() { return $this->getProperty('access_token'); } /** * Returns the Permissions for the user's page as an array if present. * * @return array|null */ public function getPermissions() { return $this->getProperty('perms'); } }PK\ <Cdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookResponse.phpnu[ * @author David Poll */ class FacebookResponse { /** * @var FacebookRequest The request which produced this response */ private $request; /** * @var array The decoded response from the Graph API */ private $responseData; /** * @var string The raw response from the Graph API */ private $rawResponse; /** * @var bool Indicates whether sent ETag matched the one on the FB side */ private $etagHit; /** * @var string ETag received with the response. `null` in case of ETag hit. */ private $etag; /** * Creates a FacebookResponse object for a given request and response. * * @param FacebookRequest $request * @param array $responseData JSON Decoded response data * @param string $rawResponse Raw string response * @param bool $etagHit Indicates whether sent ETag matched the one on the FB side * @param string|null $etag ETag received with the response. `null` in case of ETag hit. */ public function __construct($request, $responseData, $rawResponse, $etagHit = false, $etag = null) { $this->request = $request; $this->responseData = $responseData; $this->rawResponse = $rawResponse; $this->etagHit = $etagHit; $this->etag = $etag; } /** * Returns the request which produced this response. * * @return FacebookRequest */ public function getRequest() { return $this->request; } /** * Returns the decoded response data. * * @return array */ public function getResponse() { return $this->responseData; } /** * Returns the raw response * * @return string */ public function getRawResponse() { return $this->rawResponse; } /** * Returns true if ETag matched the one sent with a request * * @return bool */ public function isETagHit() { return $this->etagHit; } /** * Returns the ETag * * @return string */ public function getETag() { return $this->etag; } /** * Gets the result as a GraphObject. If a type is specified, returns the * strongly-typed subclass of GraphObject for the data. * * @param string $type * * @return mixed */ public function getGraphObject($type = 'Facebook\GraphObject') { return (new GraphObject($this->responseData))->cast($type); } /** * Returns an array of GraphObject returned by the request. If a type is * specified, returns the strongly-typed subclass of GraphObject for the data. * * @param string $type * * @return mixed */ public function getGraphObjectList($type = 'Facebook\GraphObject') { $out = array(); $data = $this->responseData->data; $dataLength = count($data); for ($i = 0; $i < $dataLength; $i++) { $out[] = (new GraphObject($data[$i]))->cast($type); } return $out; } /** * If this response has paginated data, returns the FacebookRequest for the * next page, or null. * * @return FacebookRequest|null */ public function getRequestForNextPage() { return $this->handlePagination('next'); } /** * If this response has paginated data, returns the FacebookRequest for the * previous page, or null. * * @return FacebookRequest|null */ public function getRequestForPreviousPage() { return $this->handlePagination('previous'); } /** * Returns the FacebookRequest for the previous or next page, or null. * * @param string $direction * * @return FacebookRequest|null */ private function handlePagination($direction) { if (isset($this->responseData->paging->$direction)) { $url = parse_url($this->responseData->paging->$direction); parse_str($url['query'], $params); if (isset($params['type']) && strpos($this->request->getPath(), $params['type']) !== false){ unset($params['type']); } return new FacebookRequest( $this->request->getSession(), $this->request->getMethod(), $this->request->getPath(), $params ); } else { return null; } } } PK\ * @author David Poll */ class GraphUser extends GraphObject { /** * Returns the ID for the user as a string if present. * * @return string|null */ public function getId() { return $this->getProperty('id'); } /** * Returns the name for the user as a string if present. * * @return string|null */ public function getName() { return $this->getProperty('name'); } public function getEmail() { return $this->getProperty('email'); } /** * Returns the first name for the user as a string if present. * * @return string|null */ public function getFirstName() { return $this->getProperty('first_name'); } /** * Returns the middle name for the user as a string if present. * * @return string|null */ public function getMiddleName() { return $this->getProperty('middle_name'); } /** * Returns the last name for the user as a string if present. * * @return string|null */ public function getLastName() { return $this->getProperty('last_name'); } /** * Returns the gender for the user as a string if present. * * @return string|null */ public function getGender() { return $this->getProperty('gender'); } /** * Returns the Facebook URL for the user as a string if available. * * @return string|null */ public function getLink() { return $this->getProperty('link'); } /** * Returns the users birthday, if available. * * @return \DateTime|null */ public function getBirthday() { $value = $this->getProperty('birthday'); if ($value) { return new \DateTime($value); } return null; } /** * Returns the current location of the user as a FacebookGraphLocation * if available. * * @return GraphLocation|null */ public function getLocation() { return $this->getProperty('location', GraphLocation::className()); } /** * Returns the timezone for the user as a int if present. * * @return string|null */ public function getTimezone() { return $this->getProperty('timezone'); } } PK\U{{>default/plugins/misc/facebook/sdk/src/Facebook/GraphObject.phpnu[ * @author David Poll */ class GraphObject { /** * @var array - Holds the raw associative data for this object */ protected $backingData; /** * Creates a GraphObject using the data provided. * * @param array $raw */ public function __construct($raw) { if ($raw instanceof \stdClass) { $raw = get_object_vars($raw); } $this->backingData = $raw; if (isset($this->backingData['data']) && count($this->backingData) === 1) { if ($this->backingData['data'] instanceof \stdClass) { $this->backingData = get_object_vars($this->backingData['data']); } else { $this->backingData = $this->backingData['data']; } } } /** * cast - Return a new instance of a FacebookGraphObject subclass for this * objects underlying data. * * @param string $type The GraphObject subclass to cast to * * @return GraphObject * * @throws FacebookSDKException */ public function cast($type) { if ($this instanceof $type) { return $this; } if (is_subclass_of($type, GraphObject::className())) { return new $type($this->backingData); } else { throw new FacebookSDKException( 'Cannot cast to an object that is not a GraphObject subclass', 620 ); } } /** * asArray - Return a key-value associative array for the given graph object. * * @return array */ public function asArray() { return $this->backingData; } /** * getProperty - Gets the value of the named property for this graph object, * cast to the appropriate subclass type if provided. * * @param string $name The property to retrieve * @param string $type The subclass of GraphObject, optionally * * @return mixed */ public function getProperty($name, $type = 'Facebook\GraphObject') { if (isset($this->backingData[$name])) { $value = $this->backingData[$name]; if (is_scalar($value)) { return $value; } else { return (new GraphObject($value))->cast($type); } } else { return null; } } /** * getPropertyAsArray - Get the list value of a named property for this graph * object, where each item has been cast to the appropriate subclass type * if provided. * * Calling this for a property that is not an array, the behavior * is undefined, so don’t do this. * * @param string $name The property to retrieve * @param string $type The subclass of GraphObject, optionally * * @return array */ public function getPropertyAsArray($name, $type = 'Facebook\GraphObject') { $target = array(); if (isset($this->backingData[$name]['data'])) { $target = $this->backingData[$name]['data']; } else if (isset($this->backingData[$name]) && !is_scalar($this->backingData[$name])) { $target = $this->backingData[$name]; } $out = array(); foreach ($target as $key => $value) { if (is_scalar($value)) { $out[$key] = $value; } else { $out[$key] = (new GraphObject($value))->cast($type); } } return $out; } /** * getPropertyNames - Returns a list of all properties set on the object. * * @return array */ public function getPropertyNames() { return array_keys($this->backingData); } /** * Returns the string class name of the GraphObject or subclass. * * @return string */ public static function className() { return get_called_class(); } }PK\n3qWdefault/plugins/misc/facebook/sdk/src/Facebook/FacebookSignedRequestFromInputHelper.phpnu[appId = FacebookSession::_getTargetAppId($appId); $this->appSecret = FacebookSession::_getTargetAppSecret($appSecret); $this->instantiateSignedRequest(); } /** * Instantiates a new SignedRequest entity. * * @param string|null $rawSignedRequest */ public function instantiateSignedRequest($rawSignedRequest = null) { $rawSignedRequest = $rawSignedRequest ?: $this->getRawSignedRequest(); if (!$rawSignedRequest) { return; } $this->signedRequest = new SignedRequest($rawSignedRequest, $this->state, $this->appSecret); } /** * Instantiates a FacebookSession from the signed request from input. * * @return FacebookSession|null */ public function getSession() { if ($this->signedRequest && $this->signedRequest->hasOAuthData()) { return FacebookSession::newSessionFromSignedRequest($this->signedRequest); } return null; } /** * Returns the SignedRequest entity. * * @return \Facebook\Entities\SignedRequest|null */ public function getSignedRequest() { return $this->signedRequest; } /** * Returns the user_id if available. * * @return string|null */ public function getUserId() { return $this->signedRequest ? $this->signedRequest->getUserId() : null; } /** * Get raw signed request from input. * * @return string|null */ abstract public function getRawSignedRequest(); /** * Get raw signed request from GET input. * * @return string|null */ public function getRawSignedRequestFromGet() { if (isset($_GET['signed_request'])) { return $_GET['signed_request']; } return null; } /** * Get raw signed request from POST input. * * @return string|null */ public function getRawSignedRequestFromPost() { if (isset($_POST['signed_request'])) { return $_POST['signed_request']; } return null; } /** * Get raw signed request from cookie set from the Javascript SDK. * * @return string|null */ public function getRawSignedRequestFromCookie() { $strCookieKey = 'fbsr_' . $this->appId; if (isset($_COOKIE[$strCookieKey])) { return $_COOKIE[$strCookieKey]; } return null; } } PK\:c .default/plugins/misc/facebook/sdk/autoload.phpnu[_api_loaded) return true; try { include_once __DIR__ . "/sdk/autoload.php"; FacebookSession::setDefaultApplication($this->getConfig(self::FB_APP_ID), $this->getConfig(self::FB_APP_SECRET)); $this->_api_loaded = true; } catch (Exception $ex) { $this->_api_error = $ex->getMessage(); } return $this->_api_loaded; } public function onAdminWarnings(Am_Event $event) { if (!$this->_api_loaded) { $event->addReturn(___('Facebook SDK was not loaded. Got an error: %s', $this->_api_error)); } else { parent::onAdminWarnings($event); } } public function isConfigured() { return $this->getConfig(self::FB_APP_ID) && $this->getConfig(self::FB_APP_SECRET) && $this->loadAPI(); } function onSetupForms(Am_Event_SetupForms $event) { $form = new Am_Form_Setup('facebook'); $form->setTitle('Facebook'); $fs = $form->addFieldset()->setLabel(___('FaceBook Application')); $fs->addText(self::FB_APP_ID)->setLabel(___('FaceBook App ID')); $fs->addText(self::FB_APP_SECRET, array('size' => 40))->setLabel(___('Facebook App Secret')); $fs = $form->addFieldset()->setLabel(___('Features')); $size = array('icon', 'small', 'medium', 'large', 'xlarge'); $fs->addSelect('size') ->setLabel(___('Login Button Size')) ->loadOptions(array_combine($size, $size)); $fs->addAdvCheckbox('no_signup') ->setLabel(___('Do not add to Signup Form')); $fs->addAdvCheckbox('no_login') ->setLabel(___('Do not add to Login Form')); $gr = $fs->addGroup() ->setLabel(___('Add "Like" button')); $gr->addAdvCheckbox('like', array('id' => 'like-settings')); $gr->addStatic()->setContent(' ' . ___('Like Url') . ' '); $gr->addText('likeurl', array('size' => 40)); $layout = array('standard', 'button_count', 'button', 'box_count'); $fs->addSelect('layout', array('rel' => 'like-settings')) ->setLabel(___('Like Button Layout')) ->loadOptions(array_combine($layout, $layout)); $action = array('like', 'recommend'); $fs->addSelect('action', array('rel' => 'like-settings')) ->setLabel(___('Like Button Action')) ->loadOptions(array_combine($action, $action)); $form->addScript() ->setScript(<<setDefault('likeurl', ROOT_URL); $fs->addSelect('add_access', null, array( 'options' => array('' => '-- Do not add access --') + $this->getDi()->productTable->getOptions() )) ->setLabel(___("Add free access to a product\n" . "if user signup from Facebook")); $form->addFieldsPrefix('misc.facebook.'); $this->_afterInitSetupForm($form); $event->addForm($form); } function onInitFinished(Am_Event $event) { $blocks = $this->getDi()->blocks; if (!$this->getConfig('no_login')) $blocks->add( new Am_Block('login/form/after', null, 'fb-login', $this, 'fb-login.phtml')); if (!$this->getConfig('no_signup')) $blocks->add( new Am_Block('signup/form/before', null, 'fb-signup', $this, 'fb-signup.phtml')); if ($this->getConfig('like')) $blocks->add( new Am_Block('member/main/right/bottom', null, 'fb-like', $this, 'fb-like.phtml')); } function onSignupUserAdded(Am_Event $event) { $user = $event->getUser(); // validate if user is logged-in to Facebook if ($fbuid = $this->getFbUid()) { $user->data()->set(self::FACEBOOK_UID, $fbuid)->update(); } } function includeJSSDK() { $locale = $this->getDi()->locale->getId(); echo << CUT; } function includeLoginJS() { echo << function facebook_login_login() { var loginRedirect = function(){ var href = window.location.href; if (href.indexOf('?') < 0) href += '?fb_login=1'; else href += '&fb_login=1'; window.location.href=href; } FB.getLoginStatus(function(response) { if(response.status == 'connected') loginRedirect(); else FB.login(function(response) { if (response.status=='connected') loginRedirect(); }, {scope: 'email'}); }); } OUT; } /** * return FacebookSession $session; */ function getFacebookJsSession() { if (is_null($this->session)) { try { $helper = new FacebookJavaScriptLoginHelper; $this->session = $helper->getSession(); } catch (Exception $e) { return null; } } return $this->session; } /** * Create account in aMember for user who is logged in facebook. */ function createAccount() { /* Search for account by email address */ $user = $this->getDi()->userTable->findFirstByEmail($this->getFbProfile('email')); if (empty($user)) { // Create account for user; $user = $this->getDi()->userRecord; $user->email = $this->getFbProfile('email'); $user->name_f = $this->getFbProfile('first_name'); $user->name_l = $this->getFbProfile('last_name'); $user->generateLogin(); $user->generatePassword(); $user->insert(); } if(!$user->data()->get(self::FACEBOOK_UID) && ($product_id = $this->getConfig('add_access'))) { $product = $this->getDi()->productTable->load($product_id); $billingPlan = $this->getDi()->billingPlanTable->load($product->default_billing_plan_id); $access = $this->getDi()->accessRecord; $access->product_id = $product_id; $access->begin_date = $this->getDi()->sqlDate; $period = new Am_Period($billingPlan->first_period); $access->expire_date = $period->addTo($access->begin_date); $access->user_id = $user->pk(); $access->insert(); } $user->data()->set(self::FACEBOOK_UID, $this->getFbProfile('id'))->update(); return $user; } function onAuthCheckLoggedIn(Am_Event_AuthCheckLoggedIn $event) { $status = $this->getStatus(); if ($status == self::LOGGED_AND_LINKED) { $event->setSuccessAndStop($this->linkedUser); } elseif ($status == self::LOGGED_OUT && !empty($_GET['fb_login'])) { $this->linkedUser->data()->set(self::FACEBOOK_LOGOUT, null)->update(); $event->setSuccessAndStop($this->linkedUser); } elseif ($status == self::LOGGED_IN && $this->getDi()->request->get('fb_login')) { $this->linkedUser = $this->createAccount(); $event->setSuccessAndStop($this->linkedUser); } } function onAuthAfterLogout(Am_Event_AuthAfterLogout $event) { $domain = $this->getDi()->request->getHttpHost(); Am_Cookie::set('fbsr_' . $this->getConfig('app_id'), null, time() - 3600 * 24, "/"); Am_Cookie::set('fbm_' . $this->getConfig('app_id'), null, time() - 3600 * 24, "/"); Am_Cookie::set('fbsr_' . $this->getConfig('app_id'), null, time() - 3600 * 24, "/", $domain, false); Am_Cookie::set('fbm_' . $this->getConfig('app_id'), null, time() - 3600 * 24, "/", $domain, false); $event->getUser()->data()->set(self::FACEBOOK_LOGOUT, true)->update(); } function onAuthAfterLogin(Am_Event_AuthAfterLogin $event) { if (($this->getStatus() == self::LOGGED_IN) && $this->getFbUid()) { $event->getUser()->data()->set(self::FACEBOOK_UID, $this->getFbUid())->update(); } } function getStatus() { if ($this->status !== null) return $this->status; $this->linkedUser = null; if ($id = $this->getFbUid()) { $user = $this->getDi()->userTable->findFirstByData(self::FACEBOOK_UID, $id); if ($user) { $this->linkedUser = $user; if ($user->data()->get(self::FACEBOOK_LOGOUT)) { $this->status = self::LOGGED_OUT; } else { $this->status = self::LOGGED_AND_LINKED; } } else { $this->status = self::LOGGED_IN; } } else { $this->status = self::NOT_LOGGED_IN; } return $this->status; } /** @return User */ function getLinkedUser() { return $this->linkedUser; } /** @return int FbUid */ function getFbUid() { $session = $this->getFacebookJsSession(); if (is_null($session)) return null; return $session->getUserId(); } /** @return facebook info */ function getFbProfile($fieldName) { if (is_null($this->fbProfile) && $this->getFbUid()) { $session = $this->getFacebookJsSession(); $fbReq = new FacebookRequest( $session, 'GET', '/me?fields=email,first_name,last_name' ); try { $user_profile = $fbReq->execute()->getGraphObject(GraphUser::className()); $this->fbProfile = $user_profile; } catch (Exception $e) { return null; } } return $this->fbProfile->getProperty($fieldName); } function getReadme() { return << Setup -> Plugins and enable facebook plugin; * If you have not done it before, you need to register your Application on Facebook. Go to https://developers.facebook.com/apps and click Create New App button * Enter App Display Name - it will be displayed to customer when he is asked to grant access to information during login, and click Continue * Enter your Contact Email * Enter your domain name (without www) into App Domain field * In the Select how your app integrates with Facebook, click on Website * Finally, press Save Changes * Copy & paste App ID and App Secret. You will need these values on the next step * Return back to aMember Cp -> Setup -> Facebook and insert App ID and App Secret values into corresponding fields. Optionally, you can add Like button into members area. Usually it points to your site homepage url : http://www.example.com/ CUT; } }PK\޵m2default/plugins/misc/facebook/blocks/fb-like.phtmlnu[includeJSSDK(); ?>
        PK\>e;zz3default/plugins/misc/facebook/blocks/fb-login.phtmlnu[includeJSSDK(); $plugin->includeLoginJS(); ?> PK\_4default/plugins/misc/facebook/blocks/fb-signup.phtmlnu[di->auth->getUserId() && ($_SERVER['REQUEST_METHOD'] != 'POST') && (empty($_GET['_qf_EmailCode_display']))): // skip this block if user is logged-in ?> includeJSSDK(); $plugin->includeLoginJS(); ?> PK\qww&default/plugins/misc/plugin-readme.txtnu[ PLUGIN INSTALLATION 1. Upload plugin code to folder 'amember/application/default/plugins/protect' 2. Enable plugin at aMember CP -> Configuration -> Setup/Configuration -> Plugins 3. Visit plugin configuration section aMember CP -> Configuration -> Setup/Configuration -> [Module Name] to configure plugin. Plugin-specific readme is displayed this page at bottom. PK\^SSdefault/plugins/misc/oto.phpnu[
        CUT; } public function getTitle() { return ___('One Time Offer'); } public function onAdminMenu(Am_Event $event) { $event->getMenu()->addPage(array( 'id' => 'oto', 'module' => 'default', 'controller' => 'admin-one-time-offer', 'action' => 'index', 'label' => ___('One Time Offer'), 'resource' => self::ADMIN_PERM_ID )); } public function init() { parent::init(); $this->getDi()->front->registerPlugin(new Am_Mvc_Controller_Plugin_Oto()); $this->getDi()->hook->prepend(Am_Event::THANKS_PAGE, array($this, '_onThanksPage')); } /** * Special handle for offline plugin * * show oto on first login after purchase instead of * thank you page * * @param Am_Event $event */ public function onInvoiceStarted(Am_Event $event) { /* @var $invoice Invoice */ $invoice = $event->getInvoice(); if ($invoice->paysys_id == 'offline') { $oto = $this->getDi()->otoTable->findUpsell($invoice->getProducts()); if ($oto) { $user = $invoice->getUser(); $user->data()->set(self::NEED_SHOW_OTO, $invoice->pk())->update(); } } } function _onThanksPage(Am_Event $event) { /* @var $invoice Invoice */ $invoice = $event->getInvoice(); /* @var $controller ThanksController */ $controller = $event->getController(); if (!$invoice || !$invoice->tm_started) return; // invoice is not yet paid $this->getDi()->blocks ->add(new Am_Block('thanks/success', 'Parent Invoices', 'oto-parents', $this, array($this, 'renderParentInvoices'))); if ($invoice->data()->get(self::LAST_OTO_YES)) return; // find first matching upsell $oto = $this->getDi()->otoTable->findUpsell($invoice->getProducts()); if ($controller->getRequest()->get('oto') == 'no') { $oto = $this->getDi()->otoTable->findDownsell($invoice->data()->get(self::LAST_OTO_SHOWN)); } if (!$oto) return; if ($controller->getRequest()->get('oto') == 'yes') { $event->stop(); return $this->yesOto($controller, $invoice, $this->getDi()->otoTable->load($invoice->data()->get(self::LAST_OTO_SHOWN))); } if ($oto->pk() == $invoice->data()->get(self::LAST_OTO_SHOWN)) return; $event->stop(); $invoice->data()->set(self::LAST_OTO_SHOWN, $oto->pk())->update(); $html = $oto->render(); $controller->getResponse()->setBody($html); throw new Am_Exception_Redirect; } function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if (!$this->getDi()->auth->getUserId() || !($invoice_id = $this->getDi()->auth->getUser()->data()->get(self::NEED_SHOW_OTO))) throw new Am_Exception_InternalError(); $user = $this->getDi()->auth->getUser(); $invoice = $this->getDi()->invoiceTable->load($invoice_id); $controller = new Am_Mvc_Controller($request, $response, $invokeArgs); // find first matching upsell $oto = $this->getDi()->otoTable->findUpsell($invoice->getProducts()); if ($controller->getRequest()->get('oto') == 'no') { $oto = $this->getDi()->otoTable->findDownsell($invoice->data()->get(self::LAST_OTO_SHOWN)); } if (!$oto) { $user->data()->set(self::NEED_SHOW_OTO, null)->update(); return $response->redirectLocation($this->getDi()->url('',null,false)); } if ($controller->getRequest()->get('oto') == 'yes') { $user->data()->set(self::NEED_SHOW_OTO, null)->update(); return $this->yesOto($controller, $invoice, $this->getDi()->otoTable->load($invoice->data()->get(self::LAST_OTO_SHOWN))); } if ($oto->pk() == $invoice->data()->get(self::LAST_OTO_SHOWN)) { $user->data()->set(self::NEED_SHOW_OTO, null)->update(); return $response->redirectLocation($this->getDi()->url('',null,false)); } $invoice->data()->set(self::LAST_OTO_SHOWN, $oto->pk())->update(); $html = $oto->render(); $controller->getResponse()->setBody($html); throw new Am_Exception_Redirect; } // called when user agreed to OTO function yesOto(Am_Mvc_Controller $controller, Invoice $invoice, Oto $oto) { $invoice->data()->set(self::LAST_OTO_YES, $oto->pk())->update(); $inv = $this->getDi()->invoiceTable->createRecord(); /* @var $inv Invoice */ $inv->data()->set('oto_parent', $invoice->pk()); $inv->user_id = $invoice->user_id; $inv->add($oto->getProduct()); $coupon = $oto->getCoupon(); if ($coupon) $inv->setCoupon($coupon); $inv->calculate(); if ($inv->isZero()) {// free invoice $inv->paysys_id = 'free'; } elseif ($oto->getPaysysId()) { // configured $inv->paysys_id = $oto->getPaysysId(); } elseif ($invoice->paysys_id != 'free') {// not free? take from invoice $inv->paysys_id = $invoice->paysys_id; } else { // was free, now paid, take first public $paysystems = Am_Di::getInstance()->paysystemList->getAllPublic(); $inv->paysys_id = $paysystems[0]->paysys_id; } $inv->insert(); $payProcess = new Am_Paysystem_PayProcessMediator($controller, $inv); $result = $payProcess->process(); // we decided to ignore failures here... } function renderParentInvoices(Am_View $view) { $invoice = $view->invoice; $out = null; while ($parent_invoice_id = $invoice->data()->get('oto_parent')) { $invoice = $this->getDi()->invoiceTable->load($parent_invoice_id); $v = $view->di->view; $v->invoice = $invoice; $out .= "

        Related Order Reference: $invoice->public_id

        "; $out .= $v->render('_receipt.phtml'); } echo $out; } function onGetPermissionsList(Am_Event $event) { $event->addReturn(___('Can Operate with OTO'), self::ADMIN_PERM_ID); } } class AdminOneTimeOfferController extends Am_Mvc_Controller_Grid { protected $_defaultHtml = '

        This text will be displayed before the buttons. Describe your offer here. The following tags "yes" and "no" will be automatically replaced to buttons. Please do not touch or remove them.

        %yes% %no%

        This text will be displayed after "yes" and "no" buttons, you may remove or customize it

        '; public function checkAdminPermissions(Admin $admin) { return $admin->hasPermission(Am_Plugin_Oto::ADMIN_PERM_ID); } public function previewAction() { $id = $this->_request->getInt('id'); if (!$id) throw new Am_Exception_InputError("Empty id passed"); $oto = $this->getDi()->otoTable->load($id); echo $oto->render(); } public function createGrid() { $ds = new Am_Query($this->getDi()->otoTable); $grid = new Am_Grid_Editable('_oto', ___('One Time Offer'), $ds, $this->_request, $this->view, $this->getDi()); $grid->setPermissionId(Am_Plugin_Oto::ADMIN_PERM_ID); $grid->addField('comment', ___('Comment')); $grid->addField(new Am_Grid_Field_IsDisabled()); $grid->setForm(array($this, 'createForm')); $grid->setFormValueCallback('conditions', array('RECORD', 'getConditions'), array('RECORD', 'setConditions')); $grid->setFormValueCallback('view', array('RECORD', 'getView'), array('RECORD', 'setView')); $grid->actionGet('edit')->setTarget('_top'); $grid->addCallback(Am_Grid_Editable::CB_VALUES_TO_FORM, array($this, 'valuesToForm')); $grid->addCallback(Am_Grid_Editable::CB_VALUES_FROM_FORM, array($this, 'valuesFromForm')); $grid->actionAdd(new Am_Grid_Action_Url('preview', ___('Preview'), '__ROOT__/admin-one-time-offer/preview?id=__ID__'))->setTarget('_blank'); $grid->actionAdd(new Am_Grid_Action_CopyOto())->setTarget('_top'); $grid->actionAdd(new Am_Grid_Action_Group_Callback('disable', ___('Disable'), array($this, 'disableOto'))); $grid->actionAdd(new Am_Grid_Action_Group_Callback('enable', ___('Enable'), array($this, 'enableOto'))); $grid->actionAdd(new Am_Grid_Action_Group_Delete()); $grid->actionAdd(new Am_Grid_Action_LiveEdit('comment')); $grid->setRecordTitle(___('One Time Offer')); return $grid; } public function disableOto($id, Oto $oto) { $oto->updateQuick('is_disabled', 1); } public function enableOto($id, Oto $oto) { $oto->updateQuick('is_disabled', 0); } public function valuesFromForm(& $values) { list($product_id, $bp_id) = explode('-', $values['product_id']); $values['product_id'] = $product_id; $values['bp_id'] = $bp_id; } public function valuesToForm(array & $values, Oto $record) { if ($record->isLoaded()) { //backward workaround if (!$record->bp_id) { /* @var $product Product */ $product = $this->getDi()->productTable->load($record->product_id); $plan = $product->getBillingPlan(); $record->bp_id = $plan->pk(); } $values['product_id'] = "{$record->product_id}-{$record->bp_id}"; } if (empty($values['view'])) { $values['view'] = array( 'title' => 'One Time Offer', 'html' => $this->_defaultHtml, 'yes' => array('label' => 'Yes, Add To Card'), 'no' => array('label' => 'No, Thank You'), 'no_layout' => 0, ); } } function createForm() { $form = new Am_Form_Admin(); $form->addText('comment', array('class' => 'el-wide')) ->setLabel(___("Comment\n" . 'for your reference')) ->addRule('required'); $sel = $form->addMagicSelect('conditions[product]') ->setLabel(___("Conditions\n" . 'After actual payment aMember will check user invoice and in case ' . 'of it contains one of defined product or product from defined ' . 'product category this OTO will be shown for him instead of ' . 'ordinary thank you page. In case of you use OTO (Downsell) ' . 'condition it will be matched if user click NO link in defined ' . 'offer and this OTO will be shown for user')); $cats = $pr = $oto = array(); foreach ($this->getDi()->productCategoryTable->getAdminSelectOptions() as $k => $v) $cats['category-' . $k] = ___('Category') . ':' . $v; foreach ($this->getDi()->productTable->getOptions() as $k => $v) $pr['product-' . $k] = ___('Product') . ':' . $v; foreach ($this->getDi()->otoTable->getOptions() as $k => $v) $oto['oto-' . $k] = ___('OTO') . ':' . $v; $options = array(___('Categories') => $cats) + ($pr ? array(___('Products') => $pr) : array()) + ($oto ? array(___('OTO (Downsell)') => $oto) : array()); $sel->loadOptions($options); $sel->addRule('required'); $bpOptions = array(); foreach ($this->getDi()->productTable->findBy(array('is_archived' => 0)) as $product) { /* @var $product Product */ foreach ($product->getBillingOptions() as $bp_id => $title) { $bpOptions[$product->pk() . '-' . $bp_id] = sprintf('(%d) %s (%s)', $product->pk(), $product->title, $title); } } $form->addSelect('product_id')->setLabel('Product to Offer') ->loadOptions($bpOptions) ->addRule('required'); $coupons = array('' => ''); foreach ($this->getDi()->db->selectCol(" SELECT c.coupon_id as ARRAY_KEY, CONCAT(c.code, ' - ' , b.comment) FROM ?_coupon c LEFT JOIN ?_coupon_batch b USING (batch_id) ORDER BY c.code ") as $k => $v) $coupons[$k] = $v; $form->addSelect('coupon_id')->setLabel(___('Apply Coupon (optional)')) ->loadOptions($coupons); $psList = array('' => '') + $this->getDi()->paysystemList->getOptionsPublic(); $form->addSelect('view[paysys_id]')->setLabel(___('Paysystem (optional)')) ->loadOptions($psList); $fs = $form->addFieldSet()->setLabel(___('Offer Page Settings')); $fs->addText('view[title]', array('class' => 'el-wide'))->setLabel(___('Title')); $fs->addHtmlEditor('view[html]')->setLabel("Offer Text\nuse %yes% and %no% to insert buttons"); $fs->addHtmlEditor('view[yes][label]')->setLabel('[Yes] button text'); $fs->addHtmlEditor('view[no][label]')->setLabel('[No] button code'); $fs->addAdvCheckbox('view[no_layout]')->setLabel(___("Avoid using standard layout\nyou have to design entire page in the 'Offer Text' field")); return $form; } } class OtoTable extends Am_Table { protected $_table = '?_oto'; protected $_recordClass = 'Oto'; protected $_key = 'oto_id'; /** * @param array $products * @return Oto */ function findUpsell(array $products) { if ($products && current($products) instanceof Product) { foreach ($products as $k => $p) $products[$k] = $p->product_id; } foreach ($this->findBy(array('is_disabled' => 0)) as $oto) { /* @var $oto Oto */ if ($oto->matchProducts($products)) return $oto; } } /** * @param int $oto_id * @return Oto */ function findDownsell($oto_id) { foreach ($this->findBy(array('is_disabled' => 0)) as $oto) { /* @var $oto Oto */ if ($oto->matchOto($oto_id)) return $oto; } } function getOptions() { return array_map(array('Am_Html', 'escape'), $this->_db->selectCol("SELECT oto_id as ARRAY_KEY, comment FROM ?_oto ORDER BY comment")); } } /** * @property int $oto_id * @property string $comment * @property string $conditions * @property string $view * @property int $product_id * @property int $coupon_id */ class Oto extends Am_Record { function matchProducts(array $product_ids) { $cats = $this->getDi()->productCategoryTable->getCategoryProducts(); // $cats set to category_id => array(product_ids) $cond = $this->getConditions(); foreach ($cond['product'] as $s) { if (preg_match('/product-(\d+)/', $s, $regs)) { if (in_array($regs[1], $product_ids)) return true; } elseif (preg_match('/category-(\d+)/', $s, $regs)) { if (array_intersect(@$cats[$regs[1]], $product_ids)) return true; } } return false; } function matchOto($oto_id) { $cond = $this->getConditions(); foreach ($cond['product'] as $s) { if (preg_match('/oto-(\d+)/', $s, $regs) && ($regs[1] == $oto_id)) return true; } return false; } protected function _getJson($fn) { $v = $this->get($fn); if (empty($v)) return array(); return json_decode($v, true); } protected function _setJson($fn, array $v) { $this->{$fn} = json_encode($v); return $this->{$fn}; } function getConditions() { return $this->_getJson('conditions'); } function setConditions(array $conditions) { return $this->_setJson('conditions', $conditions); } function getView() { return $this->_getJson('view'); } function setView(array $view) { return $this->_setJson('view', $view); } /** @return Coupon|null */ function getCoupon() { if ($this->coupon_id) return $this->getDi()->couponTable->load($this->coupon_id); } /** @return Product */ function getProduct() { /* @var $product Product */ $product = $this->getDi()->productTable->load($this->product_id); if ($this->bp_id) { $product->setBillingPlan($this->bp_id); } return $product; } /** @return PaysysId */ function getPaysysId() { $viewVars = $this->getView(); if (isset($viewVars['paysys_id'])) return $viewVars['paysys_id']; } function render() { $view = $this->getView(); $html = $view['html']; $id = $this->getDi()->security->obfuscate($this->pk()); $html = str_replace('%yes%', '', $html); $html = str_replace('%no%', '' . $view['no']['label'] . '', $html); if ($view['no_layout']) { $title = Am_Html::escape($view['title']); $html = strpos($html, 'html') === false ? "\n$title" . $html . "" : $html; } else { $v = $this->getDi()->view; $v->title = $view['title']; $v->content = $html; $v->layoutNoMenu = $v->layoutNoLang = $v->layoutNoTitle = true; $html = $v->render('layout.phtml'); } return $html; } } class Am_Mvc_Controller_Plugin_Oto extends Zend_Controller_Plugin_Abstract { public function preDispatch(Zend_Controller_Request_Abstract $request) { if (stripos($this->getRequest()->getControllerName(), 'admin') === 0) return; //exception for admin $di = Am_Di::getInstance(); if ($di->auth->getUserId() && $di->auth->getUser()->data()->get(Am_Plugin_Oto::NEED_SHOW_OTO)) { $request->setControllerName('direct') ->setActionName('index') ->setModuleName('default') ->setParam('type', 'misc') ->setParam('plugin_id', 'oto'); } } } class Am_Grid_Action_CopyOto extends Am_Grid_Action_Abstract { protected $id = 'copy'; protected $privilege = 'insert'; public function run() { $record = $this->grid->getRecord(); $vars = $record->toRow(); unset($vars['oto_id']); $vars['comment'] = ___('Copy of') . ' ' . $record->comment; $vars['view'] = json_decode($vars['view'], true); $vars['conditions'] = json_decode($vars['conditions'], true); $back = @$_SERVER['HTTP_X_REQUESTED_WITH']; $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $request = new Am_Mvc_Request($vars + array($this->grid->getId() . '_a' => 'insert', $this->grid->getId() . '_b' => $this->grid->getBackUrl()), Am_Mvc_Request::METHOD_POST); $request->setModuleName('default') ->setControllerName('admin-one-time-offfer') ->setActionName('index') ->setDispatched(true); $controller = new AdminOneTimeOfferController_Copy($request, new Am_Mvc_Response(), array('di' => Am_Di::getInstance())); $controller->dispatch('indexAction'); $response = $controller->getResponse(); $response->sendResponse(); $_SERVER['HTTP_X_REQUESTED_WITH'] = $back; } } class AdminOneTimeOfferController_Copy extends AdminOneTimeOfferController { public function valuesToForm(array & $values, Oto $record) { //nop } }PK\!default/plugins/misc/donation.phpnu[Donation plugin readme
        1. Create special product for donations and make this product hidden or disabled. (Product First & Second prices really doesn't matter, plugin will replace these values automatically.) If you want to enable recurring donations, configure product to be recurring as well. 2. In aMember CP -> Forms Editor -> Edit Signup form add donation brick to signup form and configure it. EOT; } } __halt_compiler(); class Am_Form_Brick_Donation extends Am_Form_Brick { protected static $brickPosition = 900; protected $hideIfLoggedInPossible = self::HIDE_DONT; protected $labels = array( 'Make a Donation', 'Support Us!', 'Make donation recurring', 'Please specifiy donation amount', 'Please enter correct amount', 'The minimum donation amount is %s' ); const RECURRING_NONE = 0; const RECURRING_OPTION = 1; const RECURRING_FORCE = 2; public function init() { if ($this->getConfig('product')) Am_Di::getInstance()->hook->add(Am_Event::INVOICE_BEFORE_PAYMENT_SIGNUP, array($this, 'handleDonation')); } function handleDonation(Am_Event $e) { /* @var $invoice Invoice */ $invoice = $e->getInvoice(); $vars = $e->getVars(); $p_id = $this->getConfig('product'); foreach ($invoice->getItems() as $item) { if ($item->item_type == 'product' && $item->item_id == $p_id) { if (!$vars['donation'][$p_id]) { $invoice->deleteItem($item); } else { $item->first_price = $vars['donation'][$p_id]; $item->data()->set('orig_first_price', $item->first_price); if ($this->getConfig('recurring') == self::RECURRING_FORCE || (isset($vars['recurring'][$p_id]) && $vars['recurring'][$p_id])) { $item->second_price = $item->first_price; $item->data()->set('orig_second_price', $item->second_price); } else { $item->rebill_times = 0; $item->second_price = 0; $item->second_period = null; $item->data()->set('orig_second_price', $item->second_price); } } $invoice->calculate(); $invoice->save(); break; } } } function initConfigForm(Am_Form $form) { $form->addSelect('product') ->setLabel(___("Donation Product\n". "Product which will be added to user's account")) ->loadOptions(array('' => '') + Am_Di::getInstance()->productTable->getOptions()); $form->addSelect('recurring') ->setLabel(___("Recurring?\n" . "Product must be recurring as well, First & Second periods will be taken from product config")) ->loadOptions(array( self::RECURRING_NONE => ___('Not Recurring'), self::RECURRING_OPTION => ___('User can choose to make donation recurring'), self::RECURRING_FORCE => ___('Recurring') )); $form->addAdvCheckbox('is_required') ->setLabel(___('Is Donation Required?')); $form->addText('amount_min') ->setLabel(___("Minimum amount of donation\n" . "keep it empty if there is not any limit")); } function isAcceptableForForm(Am_Form_Bricked $form) { return $form instanceof Am_Form_Signup; } public function insertBrick(HTML_QuickForm2_Container $form) { if (!$this->getConfig('product')) { Am_Di::getInstance()->errorLogTable->log('Donation brick is not configured. Skipped...'); return; } $name = self::$brickPosition ? 'product_id_' . self::$brickPosition : 'product_id'; self::$brickPosition++; $gr = $form->addGroup('') ->setLabel(array($this->___('Make a Donation'), $this->___('Support Us!'))); $product = Am_Di::getInstance()->productTable->load($this->getConfig('product')); $bp = $product->getBillingPlans(); $pid = $product->product_id . '-' . $bp[0]->plan_id; $id = $name . '-donation'; $form->addHidden($name) ->setId($id) ->setValue($pid) ->setAttribute('data-first_price', 0) ->setAttribute('data-second_price', 0); $form->addScript() ->setScript(<<addText('donation[' . $product->product_id . ']', array('size' => 3, 'id' => $id . '-amount')); if($this->getConfig('is_required')) $dfield->addRule('required', $this->___('Please specifiy donation amount')); if ($min = $this->getConfig('amount_min')) { $dfield->addRule('gte', $this->___('The minimum donation amount is %s', $min), $min); } $dfield->addRule('regex', $this->___("Please enter correct amount"), '/^\d+(|\.\d+)$/');; if ($this->getConfig('recurring') == self::RECURRING_OPTION) { $gr->addHTML()->setHTML('  ' . $this->___('Make donation recurring') . ' '); $gr->addCheckbox('recurring[' . $product->product_id . ']'); } } public function isMultiple() { return true; } }PK\cc(default/plugins/misc/thanks-redirect.phpnu[getGrid()->getForm()->getAdditionalFieldSet() ->addText('_thanks_redirect_url', array('class' => 'el-wide')) ->setLabel(___("After Purchase Redirect User to this URL\ninstead of thanks page\n" . 'You can use %root_url%, %root_surl%, %invoice.%, %product.% and %user.% variables in url eg: %user.login%, %user.email%, %invoice.public_id% etc.')); } function onGridProductValuesFromForm(Am_Event_Grid $e) { $args = $e->getArgs(); $product = $args[1]; $product->data()->set('thanks_redirect_url', @$args[0]['_thanks_redirect_url']); } function onGridProductValuesToForm(Am_Event_Grid $e) { $args = $e->getArgs(); $product = $args[1]; $args[0]['_thanks_redirect_url'] = $product->data()->get('thanks_redirect_url'); } function onThanksPage(Am_Event $e) { if(!$e->getInvoice()) return; $url = null; foreach ($e->getInvoice()->getProducts() as $pr) { if ($url = $pr->data()->get('thanks_redirect_url')) break; } $t = new Am_SimpleTemplate(); $t->assignStdVars(); $t->assign('invoice', $e->getInvoice()); $t->assign('user', $e->getInvoice()->getUser()); if ($product = $e->getInvoice()->getItem(0)->tryLoadProduct()) { $t->assign('product', $product); } if ($url = $t->render($url)) { Am_Mvc_Response::redirectLocation($url); } } }PK\m/Wrr5default/plugins/payment/multisafepay/multisafepay.phpnu[addText("account_id")->setLabel('Account ID'); $form->addText("site_id")->setLabel('Site ID'); $form->addText("site_code")->setLabel('Site Code'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } function getSupportedCurrencies() { return array('USD','GBP','EUR'); } public function createMSP() { require_once dirname(__FILE__) . '/MultiSafepay.class.php'; $msp = new MultiSafepay(); $msp->test = (bool)$this->getConfig('testing'); $msp->merchant['account_id'] = $this->getConfig('account_id'); $msp->merchant['site_id'] = $this->getConfig('site_id'); $msp->merchant['site_code'] = $this->getConfig('site_code'); return $msp; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $msp = $this->createMSP(); $msp->merchant['notification_url'] = $this->getPluginUrl('ipn'); $msp->merchant['cancel_url'] = $this->getCancelUrl(); $msp->merchant['redirect_url'] = $this->getReturnUrl(); $msp->customer['locale'] = 'en'; $msp->customer['firstname'] = $u->name_f; $msp->customer['lastname'] = $u->name_l; $msp->customer['zipcode'] = $u->zip; $msp->customer['city'] = $u->city; $msp->customer['country'] = $u->country; $msp->customer['email'] = $u->email; $msp->parseCustomerAddress($member['street']); /* * Transaction Details */ $msp->transaction['id'] = $invoice->public_id; // generally the shop's order ID is used here $msp->transaction['currency'] = $invoice->currency; $msp->transaction['amount'] = $invoice->first_total * 100; // cents $msp->transaction['description'] = $invoice->getLineDescription(); $out = ''; foreach ($invoice->getItems() as $item) $out .= sprintf('
      • %s
      • ', htmlspecialchars($item->item_title)); $msp->transaction['items'] = sprintf('
          %s
        ', $out); $url = $msp->startTransaction(); if ($msp->error){ $result->setFailed(___('Error happened during payment process. ').' ('.$msp->error_code . ": " . $msp->error.')'); return; } $a = new Am_Paysystem_Action_Redirect($url); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Multisafepay($this, $request, $response, $invokeArgs); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Multisafepay_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } } class Am_Paysystem_Transaction_Multisafepay_Thanks extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('transactionid'); } public function getUniqId() { return $_SERVER['REMOTE_ADDR'] . '-' . $this->getPlugin()->getDi()->time; } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function getInvoice() { return $this->invoice; } } class Am_Paysystem_Transaction_Multisafepay extends Am_Paysystem_Transaction_Incoming { protected $msp; public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $this->msp = $plugin->createMSP(); $this->msp->transaction['id'] = $request->get('transactionid'); parent::__construct($plugin, $request, $response, $invokeArgs); } public function findInvoiceId() { return $this->request->get('transactionid'); } public function getUniqId() { return $_SERVER['REMOTE_ADDR'] . '-' . $this->getPlugin()->getDi()->time; } public function validateSource() { return true; } public function validateStatus() { return true; //return $this->msp->error; } public function validateTerms() { return true; } public function processValidated() { switch ($this->msp->getStatus()) { case "completed": $this->invoice->addPayment($this); break; case "refunded": $this->invoice->addRefund($this,$this->invoice->first_total); break; default: break; } } }PK\GJPJP;default/plugins/payment/multisafepay/MultiSafepay.class.phpnu[ '', // required 'site_id' => '', // required 'site_code' => '', // required 'notification_url' => '', 'cancel_url' => '', 'redirect_url' => '', 'close_window' => '', ); // customer data var $customer = array( 'locale' => '', // advised 'ipaddress' => '', 'forwardedip' => '', 'firstname' => '', 'lastname' => '', 'address1' => '', 'address2' => '', 'housenumber' => '', 'zipcode' => '', 'city' => '', 'state' => '', 'country' => '', 'phone' => '', 'email' => '', // advised ); // transaction data var $transaction = array( 'id' => '', // required 'currency' => '', // required 'amount' => '', // required 'description' => '', // required 'var1' => '', 'var2' => '', 'var3' => '', 'items' => '', 'manual' => 'false', 'gateway' => '', 'daysactive' => '', ); // signature var $signature; // return vars var $api_url; var $request_xml; var $reply_xml; var $payment_url; var $status; var $error_code; var $error; var $parsed_xml; var $parsed_root; /* * Check the settings before using them */ function checkSettings(){ // trim any spaces $this->merchant['account_id'] = trim($this->merchant['account_id']); $this->merchant['site_id'] = trim($this->merchant['site_id']); $this->merchant['site_code'] = trim($this->merchant['site_code']); } /* * Starts a transaction and returns the payment url */ function startTransaction(){ $this->checkSettings(); $this->setIp(); $this->createSignature(); // create request $this->request_xml = $this->createTransactionRequest(); // post request and get reply $this->api_url = $this->getApiUrl(); $this->reply_xml = $this->xmlPost($this->api_url, $this->request_xml); // communication error if (!$this->reply_xml) return false; // parse xml $rootNode = $this->parseXmlResponse($this->reply_xml); if (!$rootNode) return false; // return payment url $this->payment_url = $this->xmlUnescape($rootNode['transaction']['payment_url']['VALUE']); return $this->payment_url; } /* * Return the status for the specified transactionid */ function getStatus(){ $this->checkSettings(); // generate request $this->request_xml = $this->createStatusRequest(); // post request and get reply $this->api_url = $this->getApiUrl(); $this->reply_xml = $this->xmlPost($this->api_url, $this->request_xml); // communication error if (!$this->reply_xml) return false; // parse xml $rootNode = $this->parseXmlResponse($this->reply_xml); if (!$rootNode) return false; // return status $this->status = $rootNode['ewallet']['status']['VALUE']; return $this->status; } /* * Returns an associative array with the ids and the descriptions of the available gateways */ function getGateways(){ $this->checkSettings(); // generate request $this->request_xml = $this->createGatewaysRequest(); // post request and get reply $this->api_url = $this->getApiUrl(); $this->reply_xml = $this->xmlPost($this->api_url, $this->request_xml); // communication error if (!$this->reply_xml) return false; // parse xml $rootNode = $this->parseXmlResponse($this->reply_xml); if (!$rootNode) return false; // get gatesways $gateways = array(); foreach($rootNode['gateways']['gateway'] as $xml_gateway){ $gateway = array(); $gateway['id'] = $xml_gateway['id']['VALUE']; $gateway['description'] = $xml_gateway['description']['VALUE']; // issuers if (isset($xml_gateway['issuers'])){ $issuers = array(); foreach($xml_gateway['issuers']['issuer'] as $xml_issuer){ $issuer = array(); $issuer['id'] = $xml_issuer['id']['VALUE']; $issuer['description'] = $xml_issuer['description']['VALUE']; $issuers[$issuer['id']] = $issuer; } $gateway['issuers'] = $issuers; } $gateways[$gateway['id']] = $gateway; } // return return $gateways; } /* * Create the transaction request xml */ function createTransactionRequest(){ // issuer attribute $issuer = ""; if (!empty($this->issuer)){ $issuer =' issuer="'.$this->xmlEscape($this->issuer).'"'; } $request = ' ' . $this->xmlEscape($this->merchant['account_id']) . ' ' . $this->xmlEscape($this->merchant['site_id']) . ' ' . $this->xmlEscape($this->merchant['site_code']) . ' ' . $this->xmlEscape($this->merchant['notification_url']) . ' ' . $this->xmlEscape($this->merchant['cancel_url']) . ' ' . $this->xmlEscape($this->merchant['redirect_url']) . ' ' . $this->xmlEscape($this->merchant['close_window']) . ' ' . $this->xmlEscape($this->customer['locale']) . ' ' . $this->xmlEscape($this->customer['ipaddress']) . ' ' . $this->xmlEscape($this->customer['forwardedip']) . ' ' . $this->xmlEscape($this->customer['firstname']) . ' ' . $this->xmlEscape($this->customer['lastname']) . ' ' . $this->xmlEscape($this->customer['address1']) . ' ' . $this->xmlEscape($this->customer['address2']) . ' ' . $this->xmlEscape($this->customer['housenumber']) . ' ' . $this->xmlEscape($this->customer['zipcode']) . ' ' . $this->xmlEscape($this->customer['city']) . ' ' . $this->xmlEscape($this->customer['state']) . ' ' . $this->xmlEscape($this->customer['country']) . ' ' . $this->xmlEscape($this->customer['phone']) . ' ' . $this->xmlEscape($this->customer['email']) . ' ' . $this->xmlEscape($this->transaction['id']) . ' ' . $this->xmlEscape($this->transaction['currency']) . ' ' . $this->xmlEscape($this->transaction['amount']) . ' ' . $this->xmlEscape($this->transaction['description']) . ' ' . $this->xmlEscape($this->transaction['var1']) . ' ' . $this->xmlEscape($this->transaction['var2']) . ' ' . $this->xmlEscape($this->transaction['var3']) . ' ' . $this->xmlEscape($this->transaction['items']) . ' ' . $this->xmlEscape($this->transaction['manual']) . ' '.$this->xmlEscape($this->transaction['gateway']) . ' ' . $this->xmlEscape($this->signature) . ' '; return $request; } /* * Create the status request xml */ function createStatusRequest(){ $request = ' ' . $this->xmlEscape($this->merchant['account_id']) . ' ' . $this->xmlEscape($this->merchant['site_id']) . ' ' . $this->xmlEscape($this->merchant['site_code']) . ' ' . $this->xmlEscape($this->transaction['id']) . ' '; return $request; } /* * Create the gateway request xml */ function createGatewaysRequest(){ $request = ' ' . $this->xmlEscape($this->merchant['account_id']) . ' ' . $this->xmlEscape($this->merchant['site_id']) . ' ' . $this->xmlEscape($this->merchant['site_code']) . ' ' . $this->xmlEscape($this->transaction['id']) . ' '; return $request; } /* * Creates the signature */ function createSignature(){ $this->signature = md5( $this->transaction['amount'] . $this->transaction['currency'] . $this->merchant['account_id'] . $this->merchant['site_id'] . $this->transaction['id'] ); } /* * Sets the customers ip variables */ function setIp(){ $this->customer['ipaddress'] = $_SERVER['REMOTE_ADDR']; if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])){ $this->customer['forwardedip'] = $_SERVER['HTTP_X_FORWARDED_FOR']; } } /* * Parses and sets customer address */ function parseCustomerAddress($street_address){ list($address, $apartment) = $this->parseAddress($street_address); $this->customer['address1'] = $address; $this->customer['housenumber'] = $apartment; } /* * Parses and splits up an address in street and housenumber */ function parseAddress($street_address){ $address = $street_address; $apartment = ""; $offset = strlen($street_address); while (($offset = $this->rstrpos($street_address, ' ', $offset)) !== false) { if ($offset < strlen($street_address)-1 && is_numeric($street_address[$offset + 1])) { $address = trim(substr($street_address, 0, $offset)); $apartment = trim(substr($street_address, $offset + 1)); break; } } if (empty($apartment) && strlen($street_address) > 0 && is_numeric($street_address[0])) { $pos = strpos($street_address, ' '); if ($pos !== false) { $apartment = trim(substr($street_address, 0, $pos), ", \t\n\r\0\x0B"); $address = trim(substr($street_address, $pos + 1)); } } return array($address, $apartment); } /* * Returns the api url */ function getApiUrl(){ if ($this->test){ return "https://testapi.multisafepay.com/ewx/"; }else{ return "https://api.multisafepay.com/ewx/"; } } /* * Parse an xml response */ function parseXmlResponse($response){ // strip xml line $response = preg_replace('#]*>#is', '', $response); // parse $parser = new msp_gc_xmlparser($response); $this->parsed_xml = $parser->GetData(); $this->parsed_root = $parser->GetRoot(); $rootNode = $this->parsed_xml[$this->parsed_root]; // check if valid response? // check for error $result = $this->parsed_xml[$this->parsed_root]['result']; if ($result != "ok"){ $this->error_code = $rootNode['error']['code']['VALUE']; $this->error = $rootNode['error']['description']['VALUE']; return false; } return $rootNode; } /* * Returns the string escaped for use in XML documents */ function xmlEscape($str){ return htmlspecialchars($str,ENT_COMPAT, "UTF-8"); } /* * Returns the string with all XML escaping removed */ function xmlUnescape($str){ return html_entity_decode($str,ENT_COMPAT, "UTF-8"); } /* * Post the supplied XML data and return the reply */ function xmlPost($url, $request_xml, $verify_peer = false){ $curl_available = extension_loaded("curl"); // generate request $header = array(); if (!$curl_available) { $url = parse_url($url); if (empty($url['port'])) { $url['port'] = $url['scheme'] == "https" ? 443 : 80; } $header[] = "POST " . $url['path'] . "?" . $url['query'] . " HTTP/1.1"; $header[] = "Host: " . $url['host'] . ":" . $url['port']; $header[] = "Content-Length: " . strlen($request_xml); } $header[] = "Content-Type: text/xml"; $header[] = "Connection: close"; // issue request if ($curl_available) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POSTFIELDS, $request_xml); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $verify_peer); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false); curl_setopt($ch, CURLOPT_MAXREDIRS, 5); curl_setopt($ch, CURLOPT_HEADER, true); //curl_setopt($ch, CURLOPT_HEADER_OUT, true); $reply_data = curl_exec($ch); } else { $request_data = implode("\r\n", $header); $request_data .= "\r\n\r\n"; $request_data .= $request_xml; $reply_data = ""; $errno = 0; $errstr = ""; $fp = fsockopen(($url['scheme'] == "https" ? "ssl://" : "") . $url['host'], $url['port'], $errno, $errstr, 30); if ($fp) { if (function_exists("stream_context_set_params")) { stream_context_set_params($fp, array( 'ssl' => array( 'verify_peer' => $verify_peer, 'allow_self_signed' => $verify_peer ) )); } fwrite($fp, $request_data); fflush($fp); while (!feof($fp)) { $reply_data .= fread($fp, 1024); } fclose($fp); } } // check response if ($curl_available) { if (curl_errno($ch)) { $this->error_code = -1; $this->error = "curl error: " . curl_errno($ch); return false; } $reply_info = curl_getinfo($ch); curl_close($ch); } else { if ($errno) { $this->error_code = -1; $this->error = "connection error: " . $errno; return false; } $header_size = strpos($reply_data, "\r\n\r\n"); $header_data = substr($reply_data, 0, $header_size); $header = explode("\r\n", $header_data); $status_line = explode(" ", $header[0]); $content_type = "application/octet-stream"; foreach ($header as $header_line) { $header_parts = explode(":", $header_line); if (strtolower($header_parts[0]) == "content-type") { $content_type = trim($header_parts[1]); break; } } $reply_info = array( 'http_code' => (int) $status_line[1], 'content_type' => $content_type, 'header_size' => $header_size + 4 ); } if ($reply_info['http_code'] != 200) { $this->error_code = -1; $this->error = "http error: " . $reply_info['http_code']; return false; } if (strstr($reply_info['content_type'], "/xml") === false) { $this->error_code = -1; $this->error = "content type error: " . $reply_info['content_type']; return false; } // split header and body $reply_header = substr($reply_data, 0, $reply_info['header_size'] - 4); $reply_xml = substr($reply_data, $reply_info['header_size']); if (empty($reply_xml)){ $this->error_code = -1; $this->error = "received empty response"; return false; } return $reply_xml; } // From http://www.php.net/manual/en/function.strrpos.php#78556 function rstrpos($haystack, $needle, $offset = null){ $size = strlen($haystack); if (is_null($offset)) { $offset = $size; } $pos = strpos(strrev($haystack), strrev($needle), $size - $offset); if ($pos === false) { return false; } return $size - $pos - strlen($needle); } } /** * Classes used to parse xml data */ class msp_gc_xmlparser { var $params = array(); //Stores the object representation of XML data var $root = NULL; var $global_index = -1; var $fold = false; /* Constructor for the class * Takes in XML data as input( do not include the tag */ function msp_gc_xmlparser($input, $xmlParams=array(XML_OPTION_CASE_FOLDING => 0)) { // XML PARSE BUG: http://bugs.php.net/bug.php?id=45996 $input = str_replace('&', '[msp-amp]', $input); // $xmlp = xml_parser_create(); foreach($xmlParams as $opt => $optVal) { switch( $opt ) { case XML_OPTION_CASE_FOLDING: $this->fold = $optVal; break; default: break; } xml_parser_set_option($xmlp, $opt, $optVal); } if(xml_parse_into_struct($xmlp, $input, $vals, $index)) { $this->root = $this->_foldCase($vals[0]['tag']); $this->params = $this->xml2ary($vals); } xml_parser_free($xmlp); } function _foldCase($arg) { return( $this->fold ? strtoupper($arg) : $arg); } /* * Credits for the structure of this function * http://mysrc.blogspot.com/2007/02/php-xml-to-array-and-backwards.html * * Adapted by Ropu - 05/23/2007 * */ function xml2ary($vals) { $mnary=array(); $ary=&$mnary; foreach ($vals as $r) { $t=$r['tag']; if ($r['type']=='open') { if (isset($ary[$t]) && !empty($ary[$t])) { if (isset($ary[$t][0])){ $ary[$t][]=array(); } else { $ary[$t]=array($ary[$t], array()); } $cv=&$ary[$t][count($ary[$t])-1]; } else { $cv=&$ary[$t]; } $cv=array(); if (isset($r['attributes'])) { foreach ($r['attributes'] as $k=>$v) { $cv[$k]=$v; } } $cv['_p']=&$ary; $ary=&$cv; } else if ($r['type']=='complete') { if (isset($ary[$t]) && !empty($ary[$t])) { // same as open if (isset($ary[$t][0])) { $ary[$t][]=array(); } else { $ary[$t]=array($ary[$t], array()); } $cv=&$ary[$t][count($ary[$t])-1]; } else { $cv=&$ary[$t]; } if (isset($r['attributes'])) { foreach ($r['attributes'] as $k=>$v) { $cv[$k]=$v; } } $cv['VALUE'] = (isset($r['value']) ? $r['value'] : ''); // XML PARSE BUG: http://bugs.php.net/bug.php?id=45996 $cv['VALUE'] = str_replace('[msp-amp]', '&', $cv['VALUE']); // } elseif ($r['type']=='close') { $ary=&$ary['_p']; } } $this->_del_p($mnary); return $mnary; } // _Internal: Remove recursion in result array function _del_p(&$ary) { foreach ($ary as $k=>$v) { if ($k==='_p') { unset($ary[$k]); } else if(is_array($ary[$k])) { $this->_del_p($ary[$k]); } } } /* Returns the root of the XML data */ function GetRoot() { return $this->root; } /* Returns the array representing the XML data */ function GetData() { return $this->params; } }PK\+o33%default/plugins/payment/justclick.phpnu[billingPlanTable->customFields()->add( new Am_CustomFieldText( 'justclick_id', "Justclick product ID")); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function _initSetupForm(Am_Form_Setup $form) { $form->addPassword('user_rps_key')->setLabel('Secret key'); $form->addText('domain') ->setLabel(___("Your sales domain in justclick\n" . "eg. username.justclick.ru")); } public function isConfigured() { return (bool) $this->getConfig('user_rps_key'); } function getConfig($key = null, $default = null) { switch ($key) { case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } public function isNotAcceptableForInvoice(Invoice $invoice) { $items = $invoice->getItems(); if (count($items) > 1) return 'Justclick can not process invoices with more than one item'; /* @var $item InvoiceItem */ if (!$items[0]->getBillingPlanData('justclick_id')) return "item [" . $item->item_title . "] has no related Justclick product configured"; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $item = $invoice->getItem(0); $action = new Am_Paysystem_Action_Redirect(sprintf('http://%s/order/%s', $this->getConfig('domain'), $item->getBillingPlanData('justclick_id'))); $result->setAction($action); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Justclick($this, $request, $response, $invokeArgs); } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<$url as "URL для оповещений по API об оплаченном заказе" for your products in justclick 2. Go to aMember CP- > Products -> Manage Products -> Edit and set "Justclick product ID" for necessary products CUT; } } class Am_Paysystem_Transaction_Justclick extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name_f' => 'first_name', 'name_l' => 'last_name', 'email' => 'email', 'phone' => 'phone', 'state' => 'region', 'country' => 'country', 'zip' => 'postalcode', 'city' => 'city', 'user_external_id' => 'email', 'invoice_external_id' => 'id', ); public function autoCreateGetProducts() { $products = array(); foreach ((array) $this->request->get('items') as $l) { $pl = Am_Di::getInstance()->billingPlanTable->findFirstByData('justclick_id', $l['id']); if (!$pl) continue; $p = $pl->getProduct(); if ($p) $products[] = $p; } return $products; } public function getUniqId() { return $this->request->getFiltered('id'); } public function findInvoiceId() { return null; } public function validateSource() { $hash = $this->request->getParam('hash'); $h = md5( $this->request->getParam('id') . $this->request->getParam('email') . $this->request->getParam('paid') . $this->getPlugin()->getConfig('user_rps_key')); return $hash == $h; } public function validateStatus() { return!is_null($this->request->getFiltered('paid')); } public function validateTerms() { return true; } }PK\xֽTT)default/plugins/payment/gourl/gourl.phtmlnu[headMeta()->setName('robots', 'noindex,nofollow'); ?> setLayout('layout.phtml'); $this->layoutNoMenu = true; ?> _script('_receipt.phtml'); ?>

        PK\g'default/plugins/payment/gourl/gourl.phpnu[addText('public_key', array('class' => 'el-wide')) ->setLabel("Public Key"); $form->addPassword('private_key', array('class' => 'el-wide')) ->setLabel("Private Key"); } function isConfigured() { return $this->getConfig('public_key') && $this->getConfig('private_key'); } function getBoxId() { preg_match('/^([0-9]+)AA/', $this->getConfig('public_key'), $m); return $m[1]; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_HtmlTemplate_Gourl(dirname(__FILE__), 'gourl.phtml'); $a->boxID = $this->getBoxId(); $a->coinName = 'bitcoin'; $a->public_key = $this->getConfig('public_key'); $a->amount = $invoice->currency == 'BTC' ? $invoice->first_total : 0; $a->amountUSD = $invoice->currency == 'BTC' ? 0 : $invoice->first_total; $a->period = '1 HOUR'; $a->language = $this->getDi()->locale->getLanguage(); $a->iframeID = 'am-gourl-widget'; $a->userID = $invoice->getUser()->pk(); $a->userFormat = 'MANUAL'; $a->orderID = $invoice->public_id; $a->cookieName = ''; $a->webdev_key = ''; $a->width = 530; $a->height = 230; $a->hash = $this->getHash($a->getVars()); foreach (array_map('json_encode', $a->getVars()) as $k => $v) { $a->$k = $v; } $a->invoice = $invoice; $a->return_url = $this->getReturnUrl(); $a->check_url = $this->getPluginUrl('check') . '?' . http_build_query(array( 'id' => $invoice->getSecureId('CHECK-STATUS') )); $result->setAction($a); } public function directAction($request, $response, $invokeArgs) { if ($request->getActionName() == 'check') { $invoice = $this->getDi()->invoiceTable->findBySecureId($request->getParam('id'), 'CHECK-STATUS'); return $this->getDi()->response->ajaxResponse($invoice->status <> Invoice::PENDING); } else { parent::directAction($request, $response, $invokeArgs); } } protected function getHash($a) { extract($a); return md5($boxID . $coinName . $public_key . $this->getConfig('private_key') . $webdev_key . $amount . $period . $amountUSD . $language . $amount . $iframeID . $amountUSD . $userID . $userFormat . $orderID . $width . $height); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if ($request->isGet()) { echo "Only POST Data Allowed"; throw new Am_Exception_Redirect; } return new Am_Paysystem_Transaction_Gourl($this, $request, $response, $invokeArgs); } function getReadme() { $ipn = $this->getPluginUrl('ipn'); return <<$ipn Fill in form above with proper value for your payment box. CUT; } } class Am_Paysystem_Transaction_Gourl extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getParam('tx'); } public function validateSource() { return $this->request->getParam('private_key') == $this->plugin->getConfig('private_key'); } public function validateStatus() { return $this->request->getParam('status') == 'payment_received'; } public function validateTerms() { return true; } public function findInvoiceId() { return $this->request->getParam('order'); } public function processValidated() { parent::processValidated(); echo "cryptobox_newrecord"; throw new Am_Exception_Redirect; } } class Am_Paysystem_Action_HtmlTemplate_Gourl extends Am_Paysystem_Action_HtmlTemplate { protected $_template; protected $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addScriptPath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } }PK\EqY&&!default/plugins/payment/payza.phpnu[getConfig('testing') ? "https://sandbox.payza.com/sandbox/payprocess.aspx" : "https://secure.payza.com/checkout"; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText('merchant', array('size' => 20)) ->setLabel('Payza Account'); $form->addText('api_password')->setLabel('The API password you created in the API setup section of your Payza account'); $form->addAdvCheckbox('testing') ->setLabel('Sandbox testing'); } public function getSupportedCurrencies() { //https://dev.payza.com/resources/references/currency-codes return array('AUD', 'BGN', 'CAD', 'CHF', 'CZK', 'DKK', 'EEK', 'EUR', 'GBP', 'HKD', 'HUF', 'INR', 'LTL', 'MYR', 'MKD', 'NOK', 'NZD', 'PLN', 'RON', 'SEK', 'SGD', 'USD', 'ZAR'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect($this->getURL()); $a->ap_merchant = $this->getConfig('merchant'); $a->ap_itemname = $invoice->getLineDescription(); $a->ap_currency = $invoice->currency; $a->apc_1 = $invoice->public_id; $invoice->second_total > 0 ? $this->buildSubscriptionParams($a, $invoice) : $this->buildItemParams($a, $invoice); $a->ap_returnurl = $this->getReturnUrl(); $a->ap_cancelurl = $this->getCancelUrl(); $a->ap_ipnversion = 2; $a->ap_alerturl = $this->getPluginUrl('ipn'); ; $result->setAction($a); } protected function buildSubscriptionParams(Am_Paysystem_Action_Redirect $a, Invoice $invoice) { $a->ap_purchasetype = 'subscription'; $a->ap_trialamount = $invoice->first_total; $period = new Am_Period(); $period->fromString($invoice->first_period); $a->ap_trialtimeunit = $this->translatePeriodUnit($period->getUnit()); $a->ap_trialperiodlength = $period->getCount(); $a->ap_amount = $invoice->second_total; $period = new Am_Period(); $period->fromString($invoice->second_period); $a->ap_timeunit = $this->translatePeriodUnit($period->getUnit()); $a->ap_periodlength = $period->getCount(); $a->ap_periodcount = $invoice->rebill_times == IProduct::RECURRING_REBILLS ? 0 : $invoice->rebill_times; } protected function buildItemParams(Am_Paysystem_Action_Redirect $a, Invoice $invoice) { $a->ap_purchasetype = 'item'; $a->ap_amount = $invoice->first_total; } protected function translatePeriodUnit($unit) { switch ($unit) { case Am_Period::DAY : return 'Day'; case Am_Period::MONTH : return 'Month'; case Am_Period::YEAR : return 'Year'; default: throw new Am_Exception_InternalError(sprintf('Unknown period unit type [%s] in %s->%s', $unit, __CLASS__, __METHOD__)); } } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $ipn = $this->getPluginUrl('ipn'); return << Setup -> Payza CUT; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Payza($this, $request, $response, $invokeArgs); } /** * * @returnAm_HttpRequest $req; */ function createRequest($method, $vars) { $req = new Am_HttpRequest(self::API_URL . '/' . $method, Am_HttpRequest::METHOD_POST); foreach ($vars as $k => $v) { $req->addPostParameter($k, $v); } return $req; } function apiRequest($method, $vars, Invoice $invoice = null) { $log = Am_Di::getInstance()->invoiceLogRecord; $log->title = $method; $log->paysys_id = $this->getId(); $req = $this->createRequest($method, $vars); $resp = $req->send(); if ($resp->getStatus() != '200') throw new Am_Exception_InternalError('Payza API: Response code is not 200'); $ret = array(); parse_str($resp->getBody(), $ret); $log->add(array('request' => $vars, 'response' => $ret)); if ($invoice) $log->setInvoice($invoice); $log->save(); if (@$ret['RETURNCODE'] != 100) throw new Am_Exception_InternalError("Payza API: " . $ret['DESCRIPTION']); return $ret; } function getSubscriptionId(Invoice $invoice) { $payments = $invoice->getPaymentRecords(); if (!$payments) throw new Am_Exception_InternalError("Invoice doesn't have payments, unable to get transaction info"); $lastPayment = array_pop($payments); $ret = $this->apiRequest( 'gettransactioninfo', array( 'USER' => $this->getConfig('merchant'), 'PASSWORD' => $this->getConfig('api_password'), 'TRANSACTIONREFERENCE' => $lastPayment->receipt_id, 'TESTMODE' => $this->getConfig('testing') ), $invoice ); return @$ret['SUBSCRIPTIONNUMBER_0']; } function cancelAction(\Invoice $invoice, $actionName, \Am_Paysystem_Result $result) { $this->apiRequest('CancelSubscription', array( 'USER' => $this->getConfig('merchant'), 'PASSWORD' => $this->getConfig('api_password'), 'SUBSCRIPTIONREFERENCE' => (($subscr_id = $invoice->data()->get(self::SUBSCR_ID)) ? $subscr_id : $this->getSubscriptionId($invoice)), 'TESTMODE' => $this->getConfig('testing') ), $invoice); $invoice->setCancelled(true); $result->setSuccess(); } function processRefund(\InvoicePayment $payment, \Am_Paysystem_Result $result, $amount) { $this->apiRequest('RefundTansaction', array( 'USER' => $this->getConfig('merchant'), 'PASSWORD' => $this->getConfig('api_password'), 'TRANSACTIONREFERENCE' => $payment->receipt_id, 'TESTMODE' => $this->getConfig('testing') ), $payment->getInvoice()); $result->setSuccess(); } } class Am_Paysystem_Transaction_Payza extends Am_Paysystem_Transaction_Incoming { const INVALID_TOKEN = 'INVALID TOKEN'; protected $ipnData = null; protected function getIPN2HandlerURL() { return $this->getPlugin()->getConfig('testing') ? "https://sandbox.Payza.com/sandbox/IPN2.ashx" : "https://secure.payza.com/ipn2.ashx"; } public function validateSource() { $token = $this->request->getParam('token'); $request = new Am_HttpRequest($this->getIPN2HandlerURL(), Am_HttpRequest::METHOD_POST); $request->addPostParameter('token', $token); $response = $request->send(); $body = $response->getBody(); if ($body == self::INVALID_TOKEN) throw new Am_Exception_Paysystem_TransactionInvalid(sprintf("Invalid Token [%s] passed.", $token)); parse_str(urldecode($body), $this->ipnData); $this->log->add($this->ipnData); return true; } public function validateStatus() { return true; } public function validateTerms() { $amount = $this->ipnData['ap_trialamount'] ? $this->ipnData['ap_trialamount'] : $this->ipnData['ap_amount']; return $amount == $this->invoice->first_total; } public function findInvoiceId() { return $this->ipnData['apc_1']; } public function getUniqId() { return $this->ipnData['ap_referencenumber']; } function processValidated() { switch ($this->ipnData['ap_status']) { case 'Success' : case 'Subscription-Payment-Success' : $this->invoice->addPayment($this); break; case 'Subscription-Canceled' : $this->invoice->setCancelled(true); break; } if ($subscr_id = $this->request->get('ap_subscriptionreferencenumber')) $this->invoice->data()->set(Am_Paysystem_Payza::SUBSCR_ID, $subscr_id)->update(); } } PK\G (&(&$default/plugins/payment/paypoint.phpnu[addText('merchant', array('size' => 20)) ->setLabel('PayPoint Username'); $form->addText('remote_password', array('size' => 30)) ->setLabel("Remote Password\n" . 'Please see readme below'); $form->addText('digestkey', array('size' => 30)) ->setLabel("Digest Key\n" . 'Created from within the PayPoint.net Merchant Extranet'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } function calculateDigest(Am_Paysystem_Action_Redirect $a) { $d = md5($s = $a->trans_id . $a->amount . $this->getConfig('remote_password')); return $d; } function getPeriod($period) { $p = new Am_Period($period); switch ($p->getUnit()) { case Am_Period::DAY: if ($p->getCount() == 1) return 'daily'; if ($p->getCount() == 7) return 'weekly'; break; case Am_Period::MONTH: if ($p->getCount() == 1) return 'monthly'; if ($p->getCount() == 3) return 'quarterly'; if ($p->getCount() == 6) return 'half-yearly'; break; case Am_Period::YEAR: if ($p->getCount() == 1) return 'yearly'; default: // nop. exception } throw new Am_Exception_Paysystem_NotConfigured( "Unable to convert period [$period] to PayPoint-compatible." . "Please contact webmaster for more information about this issue"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->merchant = $this->getConfig('merchant'); $a->trans_id = $invoice->public_id; $a->amount = $invoice->first_total; $a->callback = $this->getPluginUrl('thanks'); $a->digest = $this->calculateDigest($a); $a->bill_addr_1 = $invoice->getStreet(); $a->bill_city = $invoice->getCity(); $a->bill_country = $invoice->getCountry(); $a->bill_email = $invoice->getEmail(); $a->bill_name = $invoice->getName(); $a->bill_post_code = $invoice->getZip(); $a->bill_state = $invoice->getState(); $a->bill_tel = $invoice->getPhone(); $a->currency = $invoice->currency; $a->options = "cb_post=true,md_flds=trans_id:amount:callback"; if ($invoice->rebill_times) { // Recurring payment; $a->repeat = sprintf("%s/%s/%s:%s", gmdate('Ymd', strtotime($invoice->calculateRebillDate(1))), $this->getPeriod($invoice->second_period), ($invoice->rebill_times == IProduct::RECURRING_REBILLS ? '-1' : $invoice->rebill_times), $invoice->second_total ); $a->repeat_callback = $a->callback; } if ($this->getConfig('testing')) $a->test_status = 'true'; $result->setAction($a); } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); $transaction = $this->createTransaction($request, $response, $invokeArgs); if (!$transaction) { throw new Am_Exception_InputError("Request not handled - createTransaction() returned null"); } $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); } catch (Exception $e) { if ($invoiceLog) $invoiceLog->add($e); throw new Am_Exception_InputError($e->getMessage()); } if ($invoiceLog) $invoiceLog->setProcessed(); //show thanks page without redirect //if ($transaction->isFirst()) $this->displayThanks($request, $response, $invokeArgs, $transaction->getInvoice()); } function isNotAcceptableForInvoice(Invoice $invoice) { if (!$invoice->first_total) return "Free trials are not supported!"; if ($invoice->rebill_times) { try { $this->getPeriod($invoice->second_period); } catch (Exception $e) { return $e->getMessage(); } } return parent::isNotAcceptableForInvoice($invoice); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paypoint($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function isConfigured() { return $this->getConfig('merchant') > ''; } function getReadme() { return <<Note: The remote password can be configured from within the PayPoint.net Merchant Extranet (Click on "Change Remote Passwords" and select Remote from the drop down list). When the POST request from your server is received by PayPoint.net, the same process takes place to build the MD5 encrypted string. If the string created by PayPoint.net matches the string sent by you in the value of the digest request parameter, then we know that the request came from you and that none of the data used to create the digest was altered in transit, therefore the transaction is permitted to proceed as normal. Ensuring PayPoint.net Checks for Authentication In order to ensure that PayPoint.net knows to check the request from your application for authentication, you have to have asked us to set this up on your account. This is not in place by default. Once you have tested your integration to be sure that the digest key is being submitted correctly, please ask for this to be done by emailing gatewaysupport@paypoint.net, quoting your PayPoint.net account ID and requesting that the ‘req_digest=true’ option be added to your account. IMPORTANT INFORMATION ABOUT RECURRING BILLING SUPPORT Paypoint hosted gateway supports only these recurring periods: daily - 1D weekly - 7D monthly - 1M quarterly - 3M half-yearly - 6M yearly - 1Y All other values of second period will generate an exception. First Period can be set to any value though. EOT; } } class Am_Paysystem_Transaction_Paypoint extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { list($invoice, ) = explode('_', $this->request->getFiltered('trans_id')); return $invoice; } public function getUniqId() { return $this->request->get('auth_code'); } public function validateSource() { try { $invoice = $this->loadInvoice($this->findInvoiceId()); } catch (Exception $e) { Am_Exception_Paysystem_TransactionSource($e->getMessage()); } if ($this->request->isPost()){ if($invoice->first_total && !$invoice->getPaymentsCount()) $valid = (md5($s = http_build_query(array( 'trans_id' => $invoice->public_id, 'amount' => $invoice->first_total, 'callback' => $this->getPlugin()->getPluginUrl('thanks') ), '', '&') . "&" . $this->getPlugin()->getConfig('digestkey') ) == $this->request->get('hash')); else //do not urlencode $valid = (md5('trans_id=' . $this->request->get('trans_id') . '&amount=' . $this->request->get('amount') . "&" . $this->getPlugin()->getConfig('digestkey') ) == $this->request->get('hash')); } else { $uri = substr($this->request->getRequestUri(), -37); $valid = md5($s = $uri . $this->getPlugin()->getConfig('digestkey')); } if ($this->request->get('valid') != 'true') throw new Am_Exception_Paysystem_TransactionInvalid('Invalid transaction received'); if (($this->request->get('auth_code') == 9999) && !$this->getPlugin()->getConfig('testing')) throw new Am_Exception_Paysystem_TransactionInvalid('Test transaction received, but test mode is disabled'); if ($this->request->get('code') != 'A') throw new Am_Exception_Paysystem_TransactionInvalid('transaction was not authorized'); return $valid; } public function validateStatus() { return true; } public function validateTerms() { if ($this->invoice->status == Invoice::PENDING) return $this->invoice->first_total == $this->request->get('amount'); else return $this->invoice->second_total == $this->request->get('amount'); } } PK\l +default/plugins/payment/bankart/bankart.phpnu[ '978', 'USD' => '840'); var $key = array (1416130419, 1696626536, 1864396914, 1868981619, 1931506799, 543580534, 1869967904, 1718773093, 1685024032, 1634624544, 2036692000, 1684369522, 1701013857, 1952784481, 1734964321, 1953066862, 543257189, 544040302, 544696431, 544694638, 1948283489, 1768824951, 1769236591, 1970544756, 1752526436, 1701978209, 1852055660, 1768384628, 1852403303); public function _initSetupForm(Am_Form_Setup $form) { $form->addText('terminal_id', array('size' => 20)) ->setLabel('Terminal Alias'); } function odpakiraj($stringData) { while (strlen($stringData) % 4 != 0) $stringData .= ' '; for ($i = 0, $j = 0; $i < strlen($stringData); $i = $i + 4, $j++) { $y = unpack("Nx", substr($stringData, $i, 4)); $data[$j] = $y["x"]; } return $data; } function simpleXOR($byteInput) { $k = 0; for ($m = 0; $m < count($byteInput); $m++) { if ($k >= count($this->key)) $k = 0; $result[$m] = $byteInput[$m] ^ $this->key[$k]; $k++; } return $result; } function zapakiraj($data) { $stringData = ''; for ($i = 0; $i < count($data); $i++) { $bin = pack("N", $data[$i]); $stringData = $stringData.$bin; } return $stringData; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $encoded = file_get_contents(dirname(__FILE__).'/resource.cgn'); $decoded = $this->zapakiraj($this->simpleXOR($this->odpakiraj($encoded))); $temp = tempnam(DATA_DIR,'bnk'); file_put_contents($temp, $decoded); $zipFile = zip_open($temp); while ($zipEntry = zip_read($zipFile)) { if (zip_entry_name($zipEntry) == $this->getConfig('terminal_id').'.xml') { $zip_entry_exist = true; if (zip_entry_open($zipFile, $zipEntry)) { $readStream = zip_entry_read($zipEntry); $data = unpack("N*", $readStream); for ($i=1; $isimpleXOR($data1); $bin = null; for ($i=0; $igetDi()->errorLogTable->log("BANKART API ERROR : terminal xml file is not found in cgn file"); throw new Am_Exception_InputError(___('Error happened during payment process. ')); } //for some reasone xml is broken in bankart cgn file $strData = preg_replace("/\<\/term[a-z]+$/",'',$strData); $terminal = new SimpleXMLElement($strData); $port = (string)$terminal->port[0]; $context = (string)$terminal->context[0]; if($port == "443" ) $url = "https://"; else $url = "http://"; $url.=(string)$terminal->webaddress[0]; if(strlen($port) > 0) $url.= ":" . $port; if(strlen($context) > 0) { if ($context[0] != "/") $url.="/"; $url.=$context; if (!$context[strlen($context)-1] != "/") $url.="/"; } else { $url.="/"; } $url.="servlet/PaymentInitHTTPServlet"; $vars = array( 'id' => (string)$terminal->id[0], 'password' => (string)$terminal->password[0], 'passwordhash' => (string)$terminal->passwordhash[0], 'action' => 4, 'amt' => $invoice->first_total, 'currency' => $this->currency_codes[$invoice->currency], 'responseURL' => $this->getPluginUrl('ipn'), //strange bankart requirements 'errorURL' => $this->getRootUrl() . "/cancel", 'trackId' => $invoice->public_id, 'udf1' => $invoice->public_id, ); $req = new Am_HttpRequest($url, Am_HttpRequest::METHOD_POST); $req->addPostParameter($vars); $res = $req->send(); $body = $res->getBody(); if(strpos($body, 'ERROR')>0) { $this->getDi()->errorLogTable->log("BANKART API ERROR : $body"); throw new Am_Exception_InputError(___('Error happened during payment process. ')); } list($payment_id,$url) = explode(':', $body, 2); $invoice->data()->set('bankart_payment_id', $payment_id)->update(); $a = new Am_Paysystem_Action_Redirect($url. '?PaymentID=' .$payment_id); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->get('Error') || $request->get('result') != 'APPROVED') { $invoice = $this->getDi()->invoiceTable->findFirstByData('bankart_payment_id', $request->get('paymentid')); echo "REDIRECT=".$this->getRootUrl() . "/cancel?id=" . $invoice->getSecureId("CANCEL"); die; } return new Am_Paysystem_Transaction_Bankart($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } public function getSupportedCurrencies() { return array_keys($this->currency_codes); } public function getReadme() { $rootURL = $this->getDi()->config->get('root_url'); return <<Bankart payment plugin configuration 1. Enable "bankart" payment plugin at aMember CP->Setup->Plugins 2. Configure "Bankart" payment plugin at aMember CP -> Setup/Configuration -> Bankart 3. Download resource.cgn from your Bankart merchant account and upload it into /amember/application/default/plugins/payment/bankart CUT; } } class Am_Paysystem_Transaction_Bankart extends Am_Paysystem_Transaction_Incoming { public function findInvoiceId() { return $this->request->get('udf1'); } public function getUniqId() { return $this->request->get('paymentid'); } public function validateSource() { return true; } public function validateStatus() { return ($this->request->get('result') == 'APPROVED'); } public function validateTerms() { return true; } public function processValidated() { parent::processValidated(); echo "REDIRECT=".$this->plugin->getRootUrl() . "/thanks?id=" . $this->invoice->getSecureId("THANKS"); } }PK\HR*33+default/plugins/payment/myshortcart-bca.phpnu[addText('account_id')->setLabel('Merchant Account Id'); $form->addText('secret')->setLabel('Merchant Secret Key'); $sel = $form->addSelect('mode') ->setLabel('Mode') ->loadOptions(array('TEST' => 'Test mode','LIVE' => 'Live mode')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Form(self::LIVE_URL); $a->account_id = $this->getConfig('account_id'); $a->return_url = $this->getPluginUrl('thanks').'?DR={DR}'; $a->mode = $this->getConfig('mode'); $a->reference_no = $invoice->public_id; $a->amount = $invoice->first_total; $a->description = $invoice->getLineDescription(); $a->name = $u->name_f.' '.$u->name_l; $a->address = $u->street; $a->city = $u->city; $a->state = $u->state; $a->postal_code = $u->zip; $a->country = $u->country; $a->phone = $u->phone; $a->email = $u->email; $a->secure_hash = md5($this->getConfig('secret',"ebskey")."|".$a->account_id."|".$a->amount."|".$a->reference_no."|".$a->return_url."|".$a->mode); $a->filterEmpty(); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ebs($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Ebs extends Am_Paysystem_Transaction_Incoming { public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $DR = preg_replace("/\s/","+",$request->get('DR', $_GET['DR'])); $rc4 = new Crypt_RC4($plugin->getConfig('secret','ebskey')); $QueryString = base64_decode($DR); $rc4->decrypt($QueryString); $QueryString = explode('&',$QueryString); foreach($QueryString as $param){ $param = explode('=',$param); $request->setParam($param[0], $param[1]); } parent::__construct($plugin,$request,$request,$invokeArgs); } public function getUniqId() { return $this->request->get('PaymentID'); } public function validateSource() { return true; } public function validateStatus() { return ($this->request->get('ResponseCode') == 0); } public function validateTerms() { return (floatval($this->request->get('Amount')) == floatval($this->invoice->first_total)); } public function findInvoiceId() { return $this->request->get('MerchantRefNo'); } public function getInvoice() { return $this->invoice; } } class Crypt_RC4 { /** * Real programmers... * @var array */ var $s= array(); /** * Real programmers... * @var array */ var $i= 0; /** * Real programmers... * @var array */ var $j= 0; /** * Key holder * @var string */ var $_key; /** * Constructor * Pass encryption key to key() * * @see key() * @param string key - Key which will be used for encryption * @return void * @access public */ function __construct($key = null) { if ($key != null) { $this->setKey($key); } } function setKey($key) { if (strlen($key) > 0) $this->_key = $key; } /** * Assign encryption key to class * * @param string key - Key which will be used for encryption * @return void * @access public */ function key(&$key) { $len= strlen($key); for ($this->i = 0; $this->i < 256; $this->i++) { $this->s[$this->i] = $this->i; } $this->j = 0; for ($this->i = 0; $this->i < 256; $this->i++) { $this->j = ($this->j + $this->s[$this->i] + ord($key[$this->i % $len])) % 256; $t = $this->s[$this->i]; $this->s[$this->i] = $this->s[$this->j]; $this->s[$this->j] = $t; } $this->i = $this->j = 0; } /** * Encrypt function * * @param string paramstr - string that will encrypted * @return void * @access public */ function crypt(&$paramstr) { //Init key for every call, Bugfix 22316 $this->key($this->_key); $len= strlen($paramstr); for ($c= 0; $c < $len; $c++) { $this->i = ($this->i + 1) % 256; $this->j = ($this->j + $this->s[$this->i]) % 256; $t = $this->s[$this->i]; $this->s[$this->i] = $this->s[$this->j]; $this->s[$this->j] = $t; $t = ($this->s[$this->i] + $this->s[$this->j]) % 256; $paramstr[$c] = chr(ord($paramstr[$c]) ^ $this->s[$t]); } } /** * Decrypt function * * @param string paramstr - string that will decrypted * @return void * @access public */ function decrypt(&$paramstr) { //Decrypt is exactly the same as encrypting the string. Reuse (en)crypt code $this->crypt($paramstr); } } //end of RC4 classPK\$@337default/plugins/payment/bitpay/Bitpay/BillInterface.phpnu[phone; } /** * @param string $phone * * @return UserInterface */ public function setPhone($phone) { if (!empty($phone) && is_string($phone) && ctype_print($phone)) { $this->phone = trim($phone); } return $this; } /** * @inheritdoc */ public function getEmail() { return $this->email; } /** * @param string $email * * @return UserInterface */ public function setEmail($email) { if (!empty($email) && is_string($email) && ctype_print($email)) { $this->email = trim($email); } return $this; } /** * @inheritdoc */ public function getFirstName() { return $this->firstName; } /** * @param string $firstName * * @return UserInterface */ public function setFirstName($firstName) { if (!empty($firstName) && is_string($firstName) && ctype_print($firstName)) { $this->firstName = trim($firstName); } return $this; } /** * @inheritdoc */ public function getLastName() { return $this->lastName; } /** * @param string $lastName * * @return UserInterface */ public function setLastName($lastName) { if (!empty($lastName) && is_string($lastName) && ctype_print($lastName)) { $this->lastName = trim($lastName); } return $this; } /** * @inheritdoc */ public function getAddress() { return $this->address; } /** * @param array $address * * @return UserInterface */ public function setAddress(array $address) { if (!empty($address) && is_array($address)) { $this->address = $address; } return $this; } /** * @inheritdoc */ public function getCity() { return $this->city; } /** * @param string $city * * @return UserInterface */ public function setCity($city) { if (!empty($city) && is_string($city) && ctype_print($city)) { $this->city = trim($city); } return $this; } /** * @inheritdoc */ public function getState() { return $this->state; } /** * @param string $state * * @return UserInterface */ public function setState($state) { if (!empty($state) && is_string($state) && ctype_print($state)) { $this->state = trim($state); } return $this; } /** * @inheritdoc */ public function getZip() { return $this->zip; } /** * @param string $zip * * @return UserInterface */ public function setZip($zip) { if (!empty($zip) && is_string($zip) && ctype_print($zip)) { $this->zip = trim($zip); } return $this; } /** * @inheritdoc */ public function getCountry() { return $this->country; } /** * @param string $country * * @return UserInterface */ public function setCountry($country) { if (!empty($country) && is_string($country) && ctype_print($country)) { $this->country = trim($country); } return $this; } /** * @param bool $boolvalue * * @return User */ public function setAgreedToTOSandPP($boolvalue) { if (!empty($boolvalue)) { $this->agreedToTOSandPP = $boolvalue; } return $this; } /** * @return bool */ public function getAgreedToTOSandPP() { return $this->agreedToTOSandPP; } } PK\#I==5default/plugins/payment/bitpay/Bitpay/Application.phpnu[users = array(); $this->orgs = array(); } /** * @inheritdoc */ public function getUsers() { return $this->users; } /** * @inheritdoc */ public function getOrgs() { return $this->orgs; } /** * Add user to stack * * @param UserInterface $user * * @return ApplicationInterface */ public function addUser(UserInterface $user) { if (!empty($user)) { $this->users[] = $user; } return $this; } /** * Add org to stack * * @param OrgInterface $org * * @return ApplicationInterface */ public function addOrg(OrgInterface $org) { if (!empty($org)) { $this->orgs[] = $org; } return $this; } } PK\5m442default/plugins/payment/bitpay/Bitpay/Currency.phpnu[setCode($code); } $this->payoutEnabled = false; $this->payoutFields = array(); } /** * @inheritdoc */ public function getCode() { return $this->code; } /** * This will change the $code to all uppercase * * @param string $code The Currency Code to use, ie USD * @throws Exception Throws an exception if the Currency Code is not supported * @return CurrencyInterface */ public function setCode($code) { if (null !== $code && !in_array(strtoupper($code), self::$availableCurrencies)) { throw new \Bitpay\Client\ArgumentException( sprintf('The currency code "%s" is not supported.', $code) ); } $this->code = strtoupper($code); return $this; } /** * @inheritdoc */ public function getSymbol() { return $this->symbol; } /** * @param string $symbol * * @return CurrencyInterface */ public function setSymbol($symbol) { if (!empty($symbol) && ctype_print($symbol)) { $this->symbol = trim($symbol); } return $this; } /** * @inheritdoc */ public function getPrecision() { return $this->precision; } /** * @param integer $precision * * @return CurrencyInterface */ public function setPrecision($precision) { if (!empty($precision) && ctype_digit(strval($precision))) { $this->precision = (int) $precision; } return $this; } /** * @inheritdoc */ public function getExchangePctFee() { return $this->exchangePercentageFee; } /** * @param string $fee * * @return CurrencyInterface */ public function setExchangePctFee($fee) { if (!empty($fee) && ctype_print($fee)) { $this->exchangePercentageFee = trim($fee); } return $this; } /** * @inheritdoc */ public function isPayoutEnabled() { return $this->payoutEnabled; } /** * @param boolean $enabled * * @return CurrencyInterface */ public function setPayoutEnabled($enabled) { $this->payoutEnabled = (boolean) $enabled; return $this; } /** * @inheritdoc */ public function getName() { return $this->name; } /** * @param string $name * * @return CurrencyInterface */ public function setName($name) { if (!empty($name) && ctype_print($name)) { $this->name = trim($name); } return $this; } /** * @inheritdoc */ public function getPluralName() { return $this->pluralName; } /** * @param string $pluralName * * @return CurrencyInterface */ public function setPluralName($pluralName) { if (!empty($pluralName) && ctype_print($pluralName)) { $this->pluralName = trim($pluralName); } return $this; } /** * @inheritdoc */ public function getAlts() { return $this->alts; } /** * @param array $alts * * @return CurrencyInterface */ public function setAlts($alts) { $this->alts = $alts; return $this; } /** * @inheritdoc */ public function getPayoutFields() { return $this->payoutFields; } /** * @param array $payoutFields * * @return CurrencyInterface */ public function setPayoutFields(array $payoutFields) { $this->payoutFields = $payoutFields; return $this; } } PK\ ACDdefault/plugins/payment/bitpay/Bitpay/PayoutInstructionInterface.phpnu[ 0) { $q = Math::div($dec, 16); $rem = Math::mod($dec, 16); $dec = $q; $hex = substr(self::HEX_CHARS, intval($rem), 1).$hex; } return $hex; } /** * Decodes a hexadecimal value into decimal. * * @param string $hex * @return string */ public static function decodeHex($hex) { if (!is_string($hex) || !ctype_xdigit($hex) && '0x' != substr($hex, 0, 2)) { throw new \Exception('Argument must be a string of hex digits.'); } $hex = strtolower($hex); // if it has a prefix of 0x this needs to be trimed if (substr($hex, 0, 2) == '0x') { $hex = substr($hex, 2); } $hexLen = strlen($hex); for ($dec = '0', $i = 0; $i < $hexLen; $i++) { $current = strpos(self::HEX_CHARS, $hex[$i]); $dec = Math::add(Math::mul($dec, 16), $current); } return $dec; } public static function doubleAndAdd($hex, PointInterface $point, CurveParameterInterface $parameters = null) { if (null === $parameters) { $parameters = new Secp256k1(); } $tmp = self::decToBin($hex); $n = strlen($tmp) - 1; $S = new Point(PointInterface::INFINITY, PointInterface::INFINITY); while ($n >= 0) { $S = self::pointDouble($S); if ($tmp[$n] == 1) { $S = self::pointAdd($S, $point); } $n--; } return new Point($S->getX(), $S->getY()); } /** * This method returns a binary string representation of * the decimal number. Used for the doubleAndAdd() method. * * @see http://php.net/manual/en/function.decbin.php but for large numbers * * @param string * @return string */ public static function decToBin($dec) { if (substr(strtolower($dec), 0, 2) == '0x') { $dec = self::decodeHex(substr($dec, 2)); } $bin = ''; while (Math::cmp($dec, '0') > 0) { if (Math::mod($dec, 2) == '1') { $bin .= '1'; } else { $bin .= '0'; } $dec = Math::div($dec, 2); } return $bin; } /** * Point multiplication method 2P = R where * s = (3xP2 + a)/(2yP) mod p * xR = s2 - 2xP mod p * yR = -yP + s(xP - xR) mod p * * @param PointInterface $point * @param CurveParameterInterface * @return PointInterface */ public static function pointDouble(PointInterface $point, CurveParameterInterface $parameters = null) { if ($point->isInfinity()) { return $point; } if (null === $parameters) { $parameters = new Secp256k1(); } $p = $parameters->pHex(); $a = $parameters->aHex(); $s = 0; $R = array( 'x' => 0, 'y' => 0, ); // Critical math section try { $m = Math::add(Math::mul(3, Math::mul($point->getX(), $point->getX())), $a); $o = Math::mul(2, $point->getY()); $n = Math::invertm($o, $p); $n2 = Math::mod($o, $p); $st = Math::mul($m, $n); $st2 = Math::mul($m, $n2); $s = Math::mod($st, $p); $s2 = Math::mod($st2, $p); $xmul = Math::mul(2, $point->getX()); $smul = Math::mul($s, $s); $xsub = Math::sub($smul, $xmul); $xmod = Math::mod($xsub, $p); $R['x'] = $xmod; $ysub = Math::sub($point->getX(), $R['x']); $ymul = Math::mul($s, $ysub); $ysub2 = Math::sub(0, $point->getY()); $yadd = Math::add($ysub2, $ymul); $R['y'] = Math::mod($yadd, $p); } catch (\Exception $e) { throw new \Exception('Error in Util::pointDouble(): '.$e->getMessage()); } return new Point($R['x'], $R['y']); } /** * Point addition method P + Q = R where: * s = (yP - yQ)/(xP - xQ) mod p * xR = s2 - xP - xQ mod p * yR = -yP + s(xP - xR) mod p * * @param PointInterface * @param PointInterface * * @return PointInterface */ public static function pointAdd(PointInterface $P, PointInterface $Q) { if ($P->isInfinity()) { return $Q; } if ($Q->isInfinity()) { return $P; } if ($P->getX() == $Q->getX() && $P->getY() == $Q->getY()) { return self::pointDouble(new Point($P->getX(), $P->getY())); } $p = '0x'.Secp256k1::P; $a = '0x'.Secp256k1::A; $s = 0; $R = array( 'x' => 0, 'y' => 0, 's' => 0, ); // Critical math section try { $m = Math::sub($P->getY(), $Q->getY()); $n = Math::sub($P->getX(), $Q->getX()); $o = Math::invertm($n, $p); $st = Math::mul($m, $o); $s = Math::mod($st, $p); $R['x'] = Math::mod( Math::sub( Math::sub( Math::mul($s, $s), $P->getX() ), $Q->getX() ), $p ); $R['y'] = Math::mod( Math::add( Math::sub( 0, $P->getY() ), Math::mul( $s, Math::sub( $P->getX(), $R['x'] ) ) ), $p ); $R['s'] = $s; } catch (Exception $e) { throw new \Exception('Error in Util::pointAdd(): '.$e->getMessage()); } return new Point($R['x'], $R['y']); } /** * Converts hex value into octet (byte) string * * @param string * * @return string */ public static function binConv($hex) { $rem = ''; $dv = ''; $byte = ''; $digits = array(); for ($x = 0; $x < 256; $x++) { $digits[$x] = chr($x); } if (substr(strtolower($hex), 0, 2) != '0x') { $hex = '0x'.strtolower($hex); } while (Math::cmp($hex, 0) > 0) { $dv = Math::div($hex, 256); $rem = Math::mod($hex, 256); $hex = $dv; $byte = $byte.$digits[$rem]; } return strrev($byte); } /** * Checks dependencies for the library * * @return array list of each requirement, boolean true if met, string error message if not as value */ public static function checkRequirements() { $requirements = array(); // PHP Version if (!defined('PHP_VERSION_ID')) { $version = explode('.', PHP_VERSION); define('PHP_VERSION_ID', ($version[0] * 10000 + $version[1] * 100 + $version[2])); } if (PHP_VERSION_ID < 50400) { $requirements['PHP'] = 'Your PHP version, ' . PHP_VERSION . ', is too low. PHP version >= 5.4 is required.'; } else { $requirements['PHP'] = true; } // Mcrypt Extension if (!extension_loaded('mcrypt')) { $requirements['Mcrypt'] = 'The Mcrypt PHP extension could not be found.'; } else { $requirements['Mcrypt'] = true; } // OpenSSL Extension if (!extension_loaded('openssl')) { $requirements['OpenSSL'] = 'The OpenSSL PHP extension could not be found.'; } else { $requirements['OpenSSL'] = true; } // JSON Extension if (!extension_loaded('json')) { $requirements['JSON'] = 'The JSON PHP extension could not be found.'; } else { $requirements['JSON'] = true; } // cURL Extension if (!extension_loaded('curl')) { $requirements['cURL'] = 'The cURL PHP extension could not be found.'; } else { $requirements['cURL'] = true; $curl_version = curl_version(); $ssl_supported = ($curl_version['features'] & CURL_VERSION_SSL); if (!$ssl_supported) { $requirements['cURL.SSL'] = 'The cURL PHP extension does not have SSL support.'; } else { $requirements['cURL.SSL'] = true; } } // Math if (!extension_loaded('bcmath') && !extension_loaded('gmp')) { $requirements['Math'] = 'Either the BC Math or GMP PHP extension is required. Neither could be found.'; } else { $requirements['Math'] = true; } return $requirements; } } PK\a8default/plugins/payment/bitpay/Bitpay/Util/Secp256k1.phpnu[ 0) { $q = Math::div($x, 58); $r = Math::mod($x, 58); $output_string .= substr($code_string, intval($r), 1); $x = $q; } for ($i = 0; $i < $dataLen && substr($data, $i, 2) == '00'; $i += 2) { $output_string .= substr($code_string, 0, 1); } $output_string = strrev($output_string); return $output_string; } /** * Decodes $data from BASE-58 format * * @param string $data * * @return string */ public static function decode($data) { $dataLen = strlen($data); for ($return = '0', $i = 0; $i < $dataLen; $i++) { $current = strpos(self::BASE58_CHARS, $data[$i]); $return = Math::mul($return, '58'); $return = Math::add($return, $current); } $return = Util::encodeHex($return); for ($i = 0; $i < $dataLen && substr($data, $i, 1) == '1'; $i++) { $return = '00'.$return; } if (strlen($return) % 2 != 0) { $return = '0'.$return; } return $return; } } PK\`mm4default/plugins/payment/bitpay/Bitpay/Util/Error.phpnu[= 4.3.0, PHP 5) * * @param bool * @param bool * @param int * @return array|void */ final public function backtrace($print = false, $options = false, $limit = 0) { if ($print == true) { return debug_print_backtrace($options, $limit); } else { return debug_backtrace($options, $limit); } } /** * Get the last occurred error and returns an associative * array describing the last error with keys "type", "message", * "file" and "line". If the error has been caused by a PHP * internal function then the "message" begins with its name. * Returns NULL if there hasn't been an error yet. * (PHP 5 >= 5.2.0) * * @param void * @return array */ final public function last() { return error_get_last(); } /** * Send an error message to the defined error handling * routines. Returns true on success or false on failure. * The possible values for $message_type are: 0 = system log, * 1 = email to $destination, 2 = depricated, 3 = appended * to file $destination, 4 = sent to SAPI log handler. * (PHP 4, PHP 5) * * @param string * @param int * @param string * @param string */ final public function log($message, $message_type = 0, $destination = '', $extra_headers = '') { return error_log((string) $message, $message_type = 0, $destination = '', $extra_headers = ''); } /** * Sets which PHP errors are reported or returns the old * error_reporting level or the current level if no level * parameter is given. * (PHP 4, PHP 5) * * @param bool * @return int */ final public function reporting($level = false) { if ($level !== false) { return error_reporting($level); } else { return error_reporting(); } } /** * Sets or restores either the error or exception handler * based on the $type and $action parameters. * (PHP 4 >= 4.0.1, PHP 5) * * @param string * @param string * @param mixed * @param int * return mixed */ final public function handler($type = 'error', $action = 'restore', $callable_handler = false, $error_types = null) { if (empty($error_types)) { $error_types = E_ALL | E_STRICT; } switch (strtolower($type)) { case 'error': switch (strtolower($action)) { case 'restore': return restore_error_handler(); break; case 'set': return set_error_handler($callable_handler, $error_types); break; default: return false; } break; case 'exception': switch (strtolower($action)) { case 'restore': return restore_exception_handler(); break; case 'set': return set_exception_handler($callable_handler); break; default: return false; } break; default: return false; } } /** * Generates a user-level error/warning/notice message. * This function returns FALSE if wrong $error_type is * specified, TRUE otherwise. The $error_msg param is * limited to 1024 bytes. * (PHP 4 >= 4.0.1, PHP 5) * * @param string * @param int * @return bool */ final public function raise($error_msg, $error_type = E_USER_NOTICE) { return trigger_error($error_msg, $error_type); } } PK\Fdefault/plugins/payment/bitpay/Bitpay/Util/CurveParameterInterface.phpnu[ $v) { if (in_array(strtolower($k), $serverVariables)) { self::$sigData[] = $v; } } self::$sigData[] = phpversion(); self::$sigData[] = get_current_user(); self::$sigData[] = php_uname('s').php_uname('n').php_uname('m').PHP_OS.PHP_SAPI.ICONV_IMPL.ICONV_VERSION; self::$sigData[] = sha1_file(__FILE__); self::$finHash = implode(self::$sigData); self::$finHash = sha1(str_ireplace(' ', '', self::$finHash).strlen(self::$finHash).metaphone(self::$finHash)); self::$finHash = sha1(self::$finHash); return self::$finHash; } } PK\NV0default/plugins/payment/bitpay/Bitpay/Bitpay.phpnu[container = $container; if (is_null($container)) { $this->initializeContainer($config); } } /** * Initialize the container */ protected function initializeContainer($config) { $this->container = $this->buildContainer($config); $this->container->compile(); } /** * Build the container of services and parameters */ protected function buildContainer($config) { $container = new ContainerBuilder(new ParameterBag($this->getParameters())); $this->prepareContainer($container); $this->getContainerLoader($container)->load($config); return $container; } protected function getParameters() { return array( 'bitpay.root_dir' => realpath(__DIR__.'/..'), ); } /** */ private function prepareContainer(ContainerInterface $container) { foreach ($this->getDefaultExtensions() as $ext) { $container->registerExtension($ext); $container->loadFromExtension($ext->getAlias()); } } /** * @param ContainerInterface $container * @return LoaderInterface */ private function getContainerLoader(ContainerInterface $container) { $locator = new FileLocator(); $resolver = new LoaderResolver( array( new ArrayLoader($container), new YamlFileLoader($container, $locator), ) ); return new DelegatingLoader($resolver); } /** * Returns an array of the default extensions * * @return array */ private function getDefaultExtensions() { return array( new BitpayExtension(), ); } /** * @return ContainerInterface */ public function getContainer() { return $this->container; } /** * @return mixed */ public function get($service) { return $this->container->get($service); } } PK\}?8default/plugins/payment/bitpay/Bitpay/BuyerInterface.phpnu[policies = array(); } /** * @return string */ public function __toString() { return (string) $this->getToken(); } /** * @return string */ public function getToken() { return $this->token; } public function setToken($token) { $this->token = $token; return $this; } /** * @return string */ public function getResource() { return $this->resource; } public function setResource($resource) { $this->resource = $resource; return $this; } /** * @return string */ public function getFacade() { return $this->facade; } public function setFacade($facade) { $this->facade = $facade; return $this; } /** * @return \DateTime */ public function getCreatedAt() { return $this->createdAt; } public function setCreatedAt(\DateTime $createdAt) { $this->createdAt = $createdAt; return $this; } /** * @return array */ public function getPolicies() { return $this->policies; } public function setPolicies($policies) { $this->policies = $policies; return $this; } /** * @return string */ public function getPairingCode() { return $this->pairingCode; } public function setPairingCode($pairingCode) { $this->pairingCode = $pairingCode; return $this; } /** * @return \DateTime */ public function getPairingExpiration() { return $this->pairingExpiration; } public function setPairingExpiration(\DateTime $pairingExpiration) { $this->pairingExpiration = $pairingExpiration; return $this; } } PK\^~1##0default/plugins/payment/bitpay/Bitpay/Payout.phpnu[id; } /** * Set the batch ID as assigned from bitpay. * * @param $id * @return $this */ public function setId($id) { if (!empty($id) && ctype_print($id)) { $this->id = trim($id); } return $this; } /** * @inheritdoc */ public function getAccountId() { return $this->account_id; } /** * Set Account Id - Bitpays account ID for the payout. * * @param $id * @return $this */ public function setAccountId($id) { if (!empty($id) && ctype_print($id)) { $this->account_id = $id; } return $this; } /** * @inheritdoc */ public function getAmount() { return $this->amount; } /** * Sets the amount for this payout. * @param $amount * @return $this */ public function setAmount($amount) { if (!empty($amount)) { $this->amount = $amount; } return $this; } /** * @interitdoc */ public function getCurrency() { return $this->currency; } /** * Set Currency * @param CurrencyInterface $currency * @return $this */ public function setCurrency(CurrencyInterface $currency) { if (!empty($currency)) { $this->currency = $currency; } return $this; } /** * @inheritdoc */ public function getEffectiveDate() { return $this->effectiveDate; } /** * Set Effective date - date payout should be given to employees. * @param $effectiveDate * @return $this */ public function setEffectiveDate($effectiveDate) { if (!empty($effectiveDate)) { $this->effectiveDate = $effectiveDate; } return $this; } /** * Get rate assigned to payout at effectiveDate */ public function getRate() { return $this->rate; } /** * Set the rate in bitcoin for the payouts of this transaction. * @param $rate * @return $this */ public function setRate($rate) { if (!empty($rate)) { $this->rate = $rate; } return $this; } /** * @inheritdoc */ public function getBtcAmount() { return $this->btc; } /** * Set the Bitcoin amount for this payout, once set by Bitpay. * @param $amount * @return $this */ public function setBtcAmount($amount) { if (!empty($amount)) { $this->btc = $amount; } return $this; } /** * @inheritdoc */ public function getRequestDate() { return $this->requestDate; } /** * Set */ public function setRequestDate($requestDate) { if (!empty($requestDate)) { $this->requestDate = $requestDate; } return $this; } /** * @inheritdoc */ public function getInstructions() { return $this->instructions; } /** * Add Instruction of PayoutInstructionInterface type * Increases $this->amount by value. * * @param PayoutInstructionInterface $instruction * @return $this */ public function addInstruction(PayoutInstructionInterface $instruction) { if (!empty($instruction)) { $this->instructions[] = $instruction; } return $this; } /** * Update Instruction - Supply an index of the instruction to update, * plus the function and single argument, to do something to an instruction. * * @param $index * @param $function * @param $argument * @return $this */ public function updateInstruction($index, $function, $argument) { if (!empty($argument) && ctype_print($argument)) { $this->instructions[$index]->$function($argument); } return $this; } /** * @inheritdoc */ public function getStatus() { return $this->status; } /** * Sets the status for the current payout request * @param $status * @return $this */ public function setStatus($status) { if (!empty($status) && ctype_print($status)) { $this->status = trim($status); } return $this; } /** * @inheritdoc */ public function getToken() { return $this->token; } /** * Set the token to authorize this request. * @param TokenInterface $token * @return $this */ public function setToken(TokenInterface $token) { if (!empty($token)) { $this->token = $token; } return $this; } /** * @inheritdoc */ public function getResponseToken() { return $this->responseToken; } /** * Set Response Token - returned by Bitpay when payout request is created * * @param $responseToken * @return $this */ public function setResponseToken($responseToken) { if (!empty($responseToken)) { $this->responseToken = trim($responseToken); } return $this; } /** * @inheritdoc */ public function getPricingMethod() { return $this->pricingMethod; } /** * Set the pricing method for this payout request * @param $pricingMethod * @return $this */ public function setPricingMethod($pricingMethod) { if (!empty($pricingMethod) && ctype_print($pricingMethod)) { $this->pricingMethod = trim($pricingMethod); } return $this; } /** * @inheritdoc */ public function getReference() { return $this->reference; } /** * Set the payroll providers reference for this payout * * @param $reference * @return $this */ public function setReference($reference) { if (!empty($reference) && ctype_print($reference)) { $this->reference = trim($reference); } return $this; } /** * @inheritdoc */ public function getNotificationEmail() { return $this->notificationEmail; } /** * Set an email address where updates to payout status should be sent. * * @param $notificationEmail * @return $this */ public function setNotificationEmail($notificationEmail) { if (!empty($notificationEmail) && ctype_print($notificationEmail)) { $this->notificationEmail = trim($notificationEmail); } return $this; } /** * @inheritdoc */ public function getNotificationUrl() { return $this->notificationUrl; } /** * Set a notification url - where updated Payout objects will be sent * * @param $notificationUrl * @return $this */ public function setNotificationUrl($notificationUrl) { if (!empty($notificationUrl) && ctype_print($notificationUrl)) { $this->notificationUrl = trim($notificationUrl); } return $this; } } PK\-:_4default/plugins/payment/bitpay/Bitpay/Autoloader.phpnu[host_url = $url; $this->host_port = $port; $this->isPortRequiredInUrl = $isPortRequiredInUrl; } public function getName() { return 'Custom Network'; } public function getAddressVersion() { return 0x00; } public function getApiHost() { return $this->host_url; } public function getApiPort() { return $this->host_port; } } PK\W׵Gdefault/plugins/payment/bitpay/Bitpay/Network/NetworkAwareInterface.phpnu[+ >default/plugins/payment/bitpay/Bitpay/Network/NetworkAware.phpnu[network = $network; } } PK\-t((4default/plugins/payment/bitpay/Bitpay/PrivateKey.phpnu[hex; } /** * @return PublicKey */ public function getPublicKey() { if (null === $this->publicKey) { $this->publicKey = new PublicKey(); $this->publicKey->setPrivateKey($this); $this->publicKey->generate(); } return $this->publicKey; } /** * Generates an EC private key * * @return \Bitpay\PrivateKey */ public function generate() { if (!empty($this->hex)) { return $this; } do { $privateKey = \Bitpay\Util\SecureRandom::generateRandom(32); $this->hex = strtolower(bin2hex($privateKey)); } while (Math::cmp('0x'.$this->hex, '1') <= 0 || Math::cmp('0x'.$this->hex, '0x'.Secp256k1::N) >= 0); $this->dec = Util::decodeHex($this->hex); return $this; } /** * Checks to see if the private key value is not empty and * the hex form only contains hexits and the decimal form * only contains devimal digits. * * @return boolean */ public function isValid() { return ($this->hasValidDec() && $this->hasValidHex()); } /** * @return boolean */ public function hasValidHex() { return (!empty($this->hex) || ctype_xdigit($this->hex)); } /** * @return boolean */ public function hasValidDec() { return (!empty($this->dec) || ctype_digit($this->dec)); } /** * Creates an ECDSA signature of $message * * @return string */ public function sign($data) { if (!ctype_xdigit($this->hex)) { throw new \Exception('The private key must be in hex format.'); } if (empty($data)) { throw new \Exception('You did not provide any data to sign.'); } $e = Util::decodeHex(hash('sha256', $data)); do { if (substr(strtolower($this->hex), 0, 2) != '0x') { $d = '0x'.$this->hex; } else { $d = $this->hex; } $k = SecureRandom::generateRandom(32); $k_hex = '0x'.strtolower(bin2hex($k)); $n_hex = '0x'.Secp256k1::N; $Gx = '0x'.substr(Secp256k1::G, 2, 64); $Gy = '0x'.substr(Secp256k1::G, 66, 64); $P = new Point($Gx, $Gy); // Calculate a new curve point from Q=k*G (x1,y1) $R = Util::doubleAndAdd($k_hex, $P); $Rx_hex = Util::encodeHex($R->getX()); $Rx_hex = str_pad($Rx_hex, 64, '0', STR_PAD_LEFT); // r = x1 mod n $r = Math::mod('0x'.$Rx_hex, $n_hex); // s = k^-1 * (e+d*r) mod n $edr = Math::add($e, Math::mul($d, $r)); $invk = Math::invertm($k_hex, $n_hex); $kedr = Math::mul($invk, $edr); $s = Math::mod($kedr, $n_hex); // The signature is the pair (r,s) $signature = array( 'r' => Util::encodeHex($r), 's' => Util::encodeHex($s), ); $signature['r'] = str_pad($signature['r'], 64, '0', STR_PAD_LEFT); $signature['s'] = str_pad($signature['s'], 64, '0', STR_PAD_LEFT); } while (Math::cmp($r, '0') <= 0 || Math::cmp($s, '0') <= 0); $sig = array( 'sig_rs' => $signature, 'sig_hex' => self::serializeSig($signature['r'], $signature['s']), ); return $sig['sig_hex']['seq']; } /** * ASN.1 DER encodes the signature based on the form: * 0x30 + size(all) + 0x02 + size(r) + r + 0x02 + size(s) + s * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf * * @param string * @param string * @return string */ public static function serializeSig($r, $s) { $dec = ''; $byte = ''; $seq = ''; $digits = array(); $retval = array(); for ($x = 0; $x < 256; $x++) { $digits[$x] = chr($x); } $dec = Util::decodeHex($r); while (Math::cmp($dec, '0') > 0) { $dv = Math::div($dec, '256'); $rem = Math::mod($dec, '256'); $dec = $dv; $byte = $byte.$digits[$rem]; } $byte = strrev($byte); // msb check if (Math::cmp('0x'.bin2hex($byte[0]), '0x80') >= 0) { $byte = chr(0x00).$byte; } $retval['bin_r'] = bin2hex($byte); $seq = chr(0x02).chr(strlen($byte)).$byte; $dec = Util::decodeHex($s); $byte = ''; while (Math::cmp($dec, '0') > 0) { $dv = Math::div($dec, '256'); $rem = Math::mod($dec, '256'); $dec = $dv; $byte = $byte.$digits[$rem]; } $byte = strrev($byte); // msb check if (Math::cmp('0x'.bin2hex($byte[0]), '0x80') >= 0) { $byte = chr(0x00).$byte; } $retval['bin_s'] = bin2hex($byte); $seq = $seq.chr(0x02).chr(strlen($byte)).$byte; $seq = chr(0x30).chr(strlen($seq)).$seq; $retval['seq'] = bin2hex($seq); return $retval; } /** * Decodes PEM data to retrieve the keypair. * * @param string $pem_data The data to decode. * @return array The keypair info. */ public function pemDecode($pem_data) { $beg_ec_text = '-----BEGIN EC PRIVATE KEY-----'; $end_ec_text = '-----END EC PRIVATE KEY-----'; $decoded = ''; $ecpemstruct = array(); $pem_data = str_ireplace($beg_ec_text, '', $pem_data); $pem_data = str_ireplace($end_ec_text, '', $pem_data); $pem_data = str_ireplace("\r", '', trim($pem_data)); $pem_data = str_ireplace("\n", '', trim($pem_data)); $pem_data = str_ireplace(' ', '', trim($pem_data)); $decoded = bin2hex(base64_decode($pem_data)); if (strlen($decoded) < 230) { throw new \Exception('Invalid or corrupt secp256k1 key provided. Cannot decode the supplied PEM data.'); } $ecpemstruct = array( 'oct_sec_val' => substr($decoded, 14, 64), 'obj_id_val' => substr($decoded, 86, 10), 'bit_str_val' => substr($decoded, 106), ); if ($ecpemstruct['obj_id_val'] != '2b8104000a') { throw new \Exception('Invalid or corrupt secp256k1 key provided. Cannot decode the supplied PEM data.'); } $private_key = $ecpemstruct['oct_sec_val']; $public_key = $ecpemstruct['bit_str_val']; if (strlen($private_key) < 64 || strlen($public_key) < 128) { throw new \Exception('Invalid or corrupt secp256k1 key provided. Cannot decode the supplied PEM data.'); } $this->pemDecoded = array('private_key' => $private_key, 'public_key' => $public_key); return $this->pemDecoded; } /** * Encodes keypair data to PEM format. * * @param array $keypair The keypair info. * @return string The data to decode. */ public function pemEncode($keypair) { if (is_array($keypair) && (strlen($keypair[0]) < 64 || strlen($keypair[1]) < 128)) { throw new \Exception('Invalid or corrupt secp256k1 keypair provided. Cannot decode the supplied PEM data.'); } $dec = ''; $byte = ''; $beg_ec_text = ''; $end_ec_text = ''; $ecpemstruct = array(); $digits = array(); for ($x = 0; $x < 256; $x++) { $digits[$x] = chr($x); } $ecpemstruct = array( 'sequence_beg' => '30', 'total_len' => '74', 'int_sec_beg' => '02', 'int_sec_len' => '01', 'int_sec_val' => '01', 'oct_sec_beg' => '04', 'oct_sec_len' => '20', 'oct_sec_val' => $keypair[0], 'a0_ele_beg' => 'a0', 'a0_ele_len' => '07', 'obj_id_beg' => '06', 'obj_id_len' => '05', 'obj_id_val' => '2b8104000a', 'a1_ele_beg' => 'a1', 'a1_ele_len' => '44', 'bit_str_beg' => '03', 'bit_str_len' => '42', 'bit_str_val' => '00'.$keypair[1], ); $beg_ec_text = '-----BEGIN EC PRIVATE KEY-----'; $end_ec_text = '-----END EC PRIVATE KEY-----'; $dec = trim(implode($ecpemstruct)); if (strlen($dec) < 230) { throw new \Exception('Invalid or corrupt secp256k1 keypair provided. Cannot encode the supplied data.'); } $dec = Util::decodeHex('0x'.$dec); while (Math::cmp($dec, '0') > 0) { $dv = Math::div($dec, '256'); $rem = Math::mod($dec, '256'); $dec = $dv; $byte = $byte.$digits[$rem]; } $byte = $beg_ec_text."\r\n".chunk_split(base64_encode(strrev($byte)), 64).$end_ec_text; $this->pemEncoded = $byte; return $byte; } } PK\G`>default/plugins/payment/bitpay/Bitpay/ApplicationInterface.phpnu[x)) { return ''; } if (Math::mod('0x'.$this->y, '0x02') == '1') { return sprintf('03%s', $this->x); } else { return sprintf('02%s', $this->x); } } /** * @param PrivateKey */ public static function createFromPrivateKey(PrivateKey $private) { $public = new self(); $public->setPrivateKey($private); return $public; } /** * @return KeyInterface */ public function setPrivateKey(PrivateKey $privateKey) { $this->privateKey = $privateKey; return $this; } /** * Generates an uncompressed and compressed EC public key. * * @param \Bitpay\PrivateKey $privateKey * * @return Bitpay\PublicKey */ public function generate(PrivateKey $privateKey = null) { if ($privateKey instanceof PrivateKey) { $this->setPrivateKey($privateKey); } if (!empty($this->hex)) { return $this; } if (is_null($this->privateKey)) { throw new \Exception('Please `setPrivateKey` before you generate a public key'); } if (!$this->privateKey->isGenerated()) { $this->privateKey->generate(); } if (!$this->privateKey->isValid()) { throw new \Exception('Private Key is invalid and cannot be used to generate a public key'); } $point = new Point( '0x'.substr(Secp256k1::G, 2, 64), '0x'.substr(Secp256k1::G, 66, 64) ); $R = Util::doubleAndAdd( '0x'.$this->privateKey->getHex(), $point ); $RxHex = Util::encodeHex($R->getX()); $RyHex = Util::encodeHex($R->getY()); $RxHex = str_pad($RxHex, 64, '0', STR_PAD_LEFT); $RyHex = str_pad($RyHex, 64, '0', STR_PAD_LEFT); $this->x = $RxHex; $this->y = $RyHex; $this->hex = sprintf('%s%s', $RxHex, $RyHex); $this->dec = Util::decodeHex($this->hex); return $this; } /** * Checks to see if the public key is not blank and contains * valid decimal and hex valules for this->hex & this->dec * * @return boolean */ public function isValid() { return ((!empty($this->hex) && ctype_xdigit($this->hex)) && (!empty($this->dec) && ctype_digit($this->dec))); } /** * @return SinKey */ public function getSin() { if (empty($this->hex)) { $this->generate(); } if (null === $this->sin) { $this->sin = new SinKey(); $this->sin->setPublicKey($this); $this->sin->generate(); } return $this->sin; } } PK\(w</default/plugins/payment/bitpay/Bitpay/Buyer.phpnu[storage = $storage; } /** * @param KeyInterface $key */ public function persist(KeyInterface $key) { $this->storage->persist($key); } /** * @return KeyInterface */ public function load($id) { return $this->storage->load($id); } } PK\SL-default/plugins/payment/bitpay/Bitpay/Key.phpnu[id = $id; } /** * @return string */ public function getId() { return $this->id; } /** * Returns a new instance of self. * * @param string $id * @return \Bitpay\KeyInterface */ public static function create($id = null) { $class = get_called_class(); return new $class($id); } /** * @return string */ public function getHex() { return $this->hex; } /** * @return string */ public function getDec() { return $this->dec; } /** * @inheritdoc */ public function serialize() { return serialize( array( $this->id, $this->x, $this->y, $this->hex, $this->dec, ) ); } /** * @inheritdoc */ public function unserialize($data) { list( $this->id, $this->x, $this->y, $this->hex, $this->dec ) = unserialize($data); } /** * @return boolean */ public function isGenerated() { return (!empty($this->hex)); } } PK\:a;default/plugins/payment/bitpay/Bitpay/ScheduleInterface.phpnu[invoiceLog = $invoiceLog; } /** * The network is either livenet or testnet and tells the client where to * send the requests. * * @param NetworkInterface */ public function setNetwork(NetworkInterface $network) { $this->network = $network; } /** * Set the Public Key to use to help identify who you are to BitPay. Please * note that you must first pair your keys and get a token in return to use. * * @param PublicKey $key */ public function setPublicKey(PublicKey $key) { $this->publicKey = $key; } /** * Set the Private Key to use, this is used when signing request strings * * @param PrivateKey $key */ public function setPrivateKey(PrivateKey $key) { $this->privateKey = $key; } /** * @param AdapterInterface $adapter */ public function setAdapter(AdapterInterface $adapter) { $this->adapter = $adapter; } /** * @param TokenInterface $token * @return ClientInterface */ public function setToken(TokenInterface $token) { $this->token = $token; return $this; } /** * @inheritdoc */ public function createInvoice(InvoiceInterface $invoice) { $request = $this->createNewRequest(); $request->setMethod(Request::METHOD_POST); $request->setPath('invoices'); $currency = $invoice->getCurrency(); $item = $invoice->getItem(); $buyer = $invoice->getBuyer(); $buyerAddress = $buyer->getAddress(); $this->checkPriceAndCurrency($item->getPrice(), $currency->getCode()); $body = array( 'price' => $item->getPrice(), 'currency' => $currency->getCode(), 'posData' => $invoice->getPosData(), 'notificationURL' => $invoice->getNotificationUrl(), 'transactionSpeed' => $invoice->getTransactionSpeed(), 'fullNotifications' => $invoice->isFullNotifications(), 'notificationEmail' => $invoice->getNotificationEmail(), 'redirectURL' => $invoice->getRedirectUrl(), 'orderID' => $invoice->getOrderId(), 'itemDesc' => $item->getDescription(), 'itemCode' => $item->getCode(), 'physical' => $item->isPhysical(), 'buyerName' => trim(sprintf('%s %s', $buyer->getFirstName(), $buyer->getLastName())), 'buyerAddress1' => isset($buyerAddress[0]) ? $buyerAddress[0] : '', 'buyerAddress2' => isset($buyerAddress[1]) ? $buyerAddress[1] : '', 'buyerCity' => $buyer->getCity(), 'buyerState' => $buyer->getState(), 'buyerZip' => $buyer->getZip(), 'buyerCountry' => $buyer->getCountry(), 'buyerEmail' => $buyer->getEmail(), 'buyerPhone' => $buyer->getPhone(), 'guid' => Util::guid(), 'nonce' => Util::nonce(), 'token' => $this->token->getToken(), ); $request->setBody(json_encode($body)); $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->request = $request; $this->response = $this->sendRequest($request); $body = json_decode($this->response->getBody(), true); $error_message = false; $error_message = (!empty($body['error'])) ? $body['error'] : $error_message; $error_message = (!empty($body['errors'])) ? $body['errors'] : $error_message; $error_message = (is_array($error_message)) ? implode("\n", $error_message) : $error_message; if (false !== $error_message) { throw new \Exception($error_message); } $data = $body['data']; $invoiceToken = new \Bitpay\Token(); $invoice ->setToken($invoiceToken->setToken($data['token'])) ->setId($data['id']) ->setUrl($data['url']) ->setStatus($data['status']) ->setBtcPrice($data['btcPrice']) ->setPrice($data['price']) ->setInvoiceTime($data['invoiceTime']) ->setExpirationTime($data['expirationTime']) ->setCurrentTime($data['currentTime']) ->setBtcPaid($data['btcPaid']) ->setRate($data['rate']) ->setExceptionStatus($data['exceptionStatus']); return $invoice; } /** * @inheritdoc */ public function getCurrencies() { $this->request = $this->createNewRequest(); $this->request->setMethod(Request::METHOD_GET); $this->request->setPath('currencies'); $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); if (empty($body['data'])) { throw new \Exception('Error with request: no data returned'); } $currencies = $body['data']; array_walk($currencies, function (&$value, $key) { $currency = new \Bitpay\Currency(); $currency ->setCode($value['code']) ->setSymbol($value['symbol']) ->setPrecision($value['precision']) ->setExchangePctFee($value['exchangePctFee']) ->setPayoutEnabled($value['payoutEnabled']) ->setName($value['name']) ->setPluralName($value['plural']) ->setAlts($value['alts']) ->setPayoutFields($value['payoutFields']); $value = $currency; }); return $currencies; } /** * @inheritdoc */ public function createPayout(PayoutInterface $payout) { $request = $this->createNewRequest(); $request->setMethod($request::METHOD_POST); $request->setPath('payouts'); $amount = $payout->getAmount(); $currency = $payout->getCurrency(); $effectiveDate = $payout->getEffectiveDate(); $token = $payout->getToken(); $body = array( 'token' => $token->getToken(), 'amount' => $amount, 'currency' => $currency->getCode(), 'instructions' => array(), 'effectiveDate' => $effectiveDate, 'pricingMethod' => $payout->getPricingMethod(), 'guid' => Util::guid(), 'nonce' => Util::nonce() ); // Optional foreach (array('reference','notificationURL','notificationEmail') as $value) { $function = 'get' . ucfirst($value); if ($payout->$function() != null) { $body[$value] = $payout->$function(); } } // Add instructions foreach ($payout->getInstructions() as $instruction) { $body['instructions'][] = array( 'label' => $instruction->getLabel(), 'address' => $instruction->getAddress(), 'amount' => $instruction->getAmount() ); } $request->setBody(json_encode($body)); $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->request = $request; $this->response = $this->sendRequest($request); $body = json_decode($this->response->getBody(), true); $error_message = false; $error_message = (!empty($body['error'])) ? $body['error'] : $error_message; $error_message = (!empty($body['errors'])) ? $body['errors'] : $error_message; $error_message = (is_array($error_message)) ? implode("\n", $error_message) : $error_message; if (false !== $error_message) { throw new \Exception($error_message); } $data = $body['data']; $payout ->setId($data['id']) ->setAccountId($data['account']) ->setResponseToken($data['token']) ->setStatus($data['status']); foreach ($data['instructions'] as $c => $instruction) { $payout->updateInstruction($c, 'setId', $instruction['id']); } return $payout; } /** * @inheritdoc */ public function getPayouts($status = null) { $request = $this->createNewRequest(); $request->setMethod(Request::METHOD_GET); $path = 'payouts?token=' . $this->token->getToken() . (($status == null) ? '' : '&status=' . $status); $request->setPath($path); $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->request = $request; $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); $error_message = false; $error_message = (!empty($body['error'])) ? $body['error'] : $error_message; $error_message = (!empty($body['errors'])) ? $body['errors'] : $error_message; $error_message = (is_array($error_message)) ? implode("\n", $error_message) : $error_message; if (false !== $error_message) { throw new \Exception($error_message); } $payouts = array(); array_walk($body['data'], function ($value, $key) use (&$payouts) { $payout = new \Bitpay\Payout(); $payout ->setId($value['id']) ->setAccountId($value['account']) ->setCurrency(new \Bitpay\Currency($value['currency'])) ->setEffectiveDate($value['effectiveDate']) ->setRequestdate($value['requestDate']) ->setPricingMethod($value['pricingMethod']) ->setStatus($value['status']) ->setAmount($value['amount']) ->setResponseToken($value['token']) ->setRate(@$value['rate']) ->setBtcAmount(@$value['btc']) ->setReference(@$value['reference']) ->setNotificationURL(@$value['notificationURL']) ->setNotificationEmail(@$value['notificationEmail']); array_walk($value['instructions'], function ($value, $key) use (&$payout) { $instruction = new \Bitpay\PayoutInstruction(); $instruction ->setId($value['id']) ->setLabel($value['label']) ->setAddress($value['address']) ->setAmount($value['amount']) ->setStatus($value['status']); array_walk($value['transactions'], function ($value, $key) use (&$instruction) { $transaction = new \Bitpay\PayoutTransaction(); $transaction ->setTransactionId($value['txid']) ->setAmount($value['amount']) ->setDate($value['date']); $instruction->addTransaction($transaction); }); $payout->addInstruction($instruction); }); $payouts[] = $payout; }); return $payouts; } /** * @inheritdoc */ public function deletePayout(PayoutInterface $payout) { $request = $this->createNewRequest(); $request->setMethod(Request::METHOD_DELETE); $request->setPath(sprintf('payouts/%s?token=%s', $payout->getId(), $payout->getResponseToken())); $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->request = $request; $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); if (empty($body['data'])) { throw new \Exception('Error with request: no data returned'); } $data = $body['data']; $payout->setStatus($data['status']); return $payout; } /** * @inheritdoc */ public function getPayout($payoutId) { $request = $this->createNewRequest(); $request->setMethod(Request::METHOD_GET); $request->setPath(sprintf('payouts/%s?token=%s', $payoutId, $this->token->getToken())); $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->request = $request; $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); if (empty($body['data'])) { throw new \Exception('Error with request: no data returned'); } $data = $body['data']; $payout = new \Bitpay\Payout(); $payout ->setId($data['id']) ->setAccountId($data['account']) ->setStatus($data['status']) ->setCurrency(new \Bitpay\Currency($data['currency'])) ->setRate(@$data['rate']) ->setAmount($data['amount']) ->setBtcAmount(@$data['btc']) ->setPricingMethod(@$data['pricingMethod']) ->setReference(@$data['reference']) ->setNotificationEmail(@$data['notificationEmail']) ->setNotificationUrl(@$data['notificationURL']) ->setRequestDate($data['requestDate']) ->setEffectiveDate($data['effectiveDate']) ->setResponseToken($data['token']); array_walk($data['instructions'], function ($value, $key) use (&$payout) { $instruction = new \Bitpay\PayoutInstruction(); $instruction ->setId($value['id']) ->setLabel($value['label']) ->setAddress($value['address']) ->setStatus($value['status']) ->setAmount($value['amount']) ->setBtc($value['btc']); array_walk($value['transactions'], function ($value, $key) use (&$instruction) { $transaction = new \Bitpay\PayoutTransaction(); $transaction ->setTransactionId($value['txid']) ->setAmount($value['amount']) ->setDate($value['date']); $instruction->addTransaction($transaction); }); $payout->addInstruction($instruction); }); return $payout; } /** * @inheritdoc */ public function getTokens() { $request = $this->createNewRequest(); $request->setMethod(Request::METHOD_GET); $request->setPath('tokens'); $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->request = $request; $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); if (empty($body['data'])) { throw new \Exception('Error with request: no data returned'); } $tokens = array(); array_walk($body['data'], function ($value, $key) use (&$tokens) { $key = current(array_keys($value)); $value = current(array_values($value)); $token = new \Bitpay\Token(); $token ->setFacade($key) ->setToken($value); $tokens[$token->getFacade()] = $token; }); return $tokens; } /** * @inheritdoc */ public function createToken(array $payload = array()) { if (isset($payload['pairingCode']) && 1 !== preg_match('/^[a-zA-Z0-9]{7}$/', $payload['pairingCode'])) { throw new ArgumentException("pairing code is not legal"); } $this->request = $this->createNewRequest(); $this->request->setMethod(Request::METHOD_POST); $this->request->setPath('tokens'); $payload['guid'] = Util::guid(); $this->request->setBody(json_encode($payload)); $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); if (isset($body['error'])) { throw new \Bitpay\Client\BitpayException($this->response->getStatusCode().": ".$body['error']); } $tkn = $body['data'][0]; $createdAt = new \DateTime(); $pairingExpiration = new \DateTime(); $token = new \Bitpay\Token(); $token ->setPolicies($tkn['policies']) ->setToken($tkn['token']) ->setFacade($tkn['facade']) ->setCreatedAt($createdAt->setTimestamp(floor($tkn['dateCreated']/1000))); if (isset($tkn['resource'])) { $token->setResource($tkn['resource']); } if (isset($tkn['pairingCode'])) { $token->setPairingCode($tkn['pairingCode']); $token->setPairingExpiration($pairingExpiration->setTimestamp(floor($tkn['pairingExpiration']/1000))); } return $token; } /** * Returns the Response object that BitPay returned from the request that * was sent * * @return ResponseInterface */ public function getResponse() { return $this->response; } /** * Returns the request object that was sent to BitPay * * @return RequestInterface */ public function getRequest() { return $this->request; } /** * @inheritdoc */ public function getInvoice($invoiceId) { $this->request = $this->createNewRequest(); $this->request->setMethod(Request::METHOD_GET); if ($this->token->getFacade() === 'merchant') { $this->request->setPath(sprintf('invoices/%s?token=%s', $invoiceId, $this->token->getToken())); $this->addIdentityHeader($this->request); $this->addSignatureHeader($this->request); } else { $this->request->setPath(sprintf('invoices/%s', $invoiceId)); } $this->response = $this->sendRequest($this->request); $body = json_decode($this->response->getBody(), true); if (isset($body['error'])) { throw new \Exception($body['error']); } $data = $body['data']; $invoice = new \Bitpay\Invoice(); $invoiceToken = new \Bitpay\Token(); $invoice ->setToken($invoiceToken->setToken($data['token'])) ->setUrl($data['url']) ->setPosData($data['posData']) ->setStatus($data['status']) ->setBtcPrice($data['btcPrice']) ->setPrice($data['price']) ->setCurrency(new \Bitpay\Currency($data['currency'])) ->setOrderId($data['orderId']) ->setInvoiceTime($data['invoiceTime']) ->setExpirationTime($data['expirationTime']) ->setCurrentTime($data['currentTime']) ->setId($data['id']) ->setBtcPaid($data['btcPaid']) ->setRate($data['rate']) ->setExceptionStatus($data['exceptionStatus']); return $invoice; } /** * @param RequestInterface $request * @return ResponseInterface */ public function sendRequest(RequestInterface $request) { if (null === $this->adapter) { // Uses the default adapter $this->adapter = new \Bitpay\Client\Adapter\CurlAdapter(); } if($this->invoiceLog) $this->invoiceLog->add($request); $response = $this->adapter->sendRequest($request); if($this->invoiceLog) $this->invoiceLog->add($response); return $response; } /** * @param RequestInterface $request */ protected function addIdentityHeader(RequestInterface $request) { if (null === $this->publicKey) { throw new \Exception('Please set your Public Key.'); } $request->setHeader('x-identity', (string) $this->publicKey); } /** * @param RequestInterface $request */ protected function addSignatureHeader(RequestInterface $request) { if (null === $this->privateKey) { throw new \Exception('Please set your Private Key'); } if (true == property_exists($this->network, 'isPortRequiredInUrl')) { if ($this->network->isPortRequiredInUrl === true) { $url = $request->getUriWithPort(); } else { $url = $request->getUri(); } } else { $url = $request->getUri(); } $message = sprintf( '%s%s', $url, $request->getBody() ); $signature = $this->privateKey->sign($message); $request->setHeader('x-signature', $signature); } /** * @return RequestInterface */ protected function createNewRequest() { $request = new Request(); $request->setHost($this->network->getApiHost()); $request->setPort($this->network->getApiPort()); $this->prepareRequestHeaders($request); return $request; } /** * Prepares the request object by adding additional headers * * @param RequestInterface $request */ protected function prepareRequestHeaders(RequestInterface $request) { // @see http://en.wikipedia.org/wiki/User_agent $request->setHeader( 'User-Agent', sprintf('%s/%s (PHP %s)', self::NAME, self::VERSION, phpversion()) ); $request->setHeader('X-BitPay-Plugin-Info', sprintf('%s/%s', self::NAME, self::VERSION)); $request->setHeader('Content-Type', 'application/json'); $request->setHeader('X-Accept-Version', '2.0.0'); } protected function checkPriceAndCurrency($price, $currency) { $decimalPosition = strpos($price, '.'); if ($decimalPosition == 0) { $decimalPrecision = 0; } else { $decimalPrecision = strlen(substr($price, $decimalPosition + 1)); } if (($decimalPrecision > 2 && $currency != 'BTC') || $decimalPrecision > 6) { throw new \Exception('Incorrect price format or currency type.'); } } public function createSchedule(\Bitpay\ScheduleInterface $schedule) { $request = $this->createNewRequest(); $request->setMethod(Request::METHOD_POST); $request->setPath('subscriptions'); $schedule->token = $this->token->getToken(); $bodyIn = array( 'schedule' => $schedule->getSchedule(), 'token' => $this->token->getToken(), 'billData' => $schedule->getBillData() ); $request->setBody(json_encode($bodyIn)); $this->request = $request; $this->addIdentityHeader($request); $this->addSignatureHeader($request); $this->response = $this->sendRequest($request); $body = json_decode($this->response->getBody(), true); $error_message = false; $error_message = (!empty($body['error'])) ? $body['error'] : $error_message; $error_message = (!empty($body['errors'])) ? $body['errors'] : $error_message; $error_message = (is_array($error_message)) ? implode("\n", $error_message) : $error_message; if (false !== $error_message) { throw new \Exception($error_message); } return $schedule; } } PK\B,,Bdefault/plugins/payment/bitpay/Bitpay/Client/Adapter/ca-bundle.crtnu[## ## Bundle of CA Root Certificates ## ## Certificate data from Mozilla downloaded on: Thu Sep 4 06:31:22 2014 ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates ## file (certdata.txt). This file can be found in the mozilla source tree: ## http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## ## Conversion done with mk-ca-bundle.pl verison 1.22. ## SHA1: c4540021427a6fa29e5f50db9f12d48c97d33889 ## GTE CyberTrust Global Root ========================== -----BEGIN CERTIFICATE----- MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ -----END CERTIFICATE----- Thawte Server CA ================ -----BEGIN CERTIFICATE----- MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl /Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= -----END CERTIFICATE----- Thawte Premium Server CA ======================== -----BEGIN CERTIFICATE----- MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf 8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t UCemDaYj+bvLpgcUQg== -----END CERTIFICATE----- Equifax Secure CA ================= -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW 8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 70+sB3c4 -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority - G2 ============================================================ -----BEGIN CERTIFICATE----- MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT 1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 -----END CERTIFICATE----- GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- GlobalSign Root CA - R2 ======================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- Verisign Class 4 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM 8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== -----END CERTIFICATE----- Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= -----END CERTIFICATE----- Baltimore CyberTrust Root ========================= -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- Equifax Secure Global eBusiness CA ================================== -----BEGIN CERTIFICATE----- MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV -----END CERTIFICATE----- Equifax Secure eBusiness CA 1 ============================= -----BEGIN CERTIFICATE----- MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ 1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ KpYrtWKmpj29f5JZzVoqgrI3eQ== -----END CERTIFICATE----- AddTrust Low-Value Services Root ================================ -----BEGIN CERTIFICATE----- MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= -----END CERTIFICATE----- AddTrust External Root ====================== -----BEGIN CERTIFICATE----- MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- AddTrust Public Services Root ============================= -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL +YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= -----END CERTIFICATE----- AddTrust Qualified Certificates Root ==================================== -----BEGIN CERTIFICATE----- MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx 64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= -----END CERTIFICATE----- Entrust Root Certification Authority ==================================== -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- RSA Security 2048 v3 ==================== -----BEGIN CERTIFICATE----- MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP +Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj 0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA pKnXwiJPZ9d37CAFYd4= -----END CERTIFICATE----- GeoTrust Global CA ================== -----BEGIN CERTIFICATE----- MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm Mw== -----END CERTIFICATE----- GeoTrust Global CA 2 ==================== -----BEGIN CERTIFICATE----- MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF H4z1Ir+rzoPz4iIprn2DQKi6bA== -----END CERTIFICATE----- GeoTrust Universal CA ===================== -----BEGIN CERTIFICATE----- MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI P/rmMuGNG2+k5o7Y+SlIis5z/iw= -----END CERTIFICATE----- GeoTrust Universal CA 2 ======================= -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- America Online Root Certification Authority 1 ============================================= -----BEGIN CERTIFICATE----- MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP 8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft 3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 -----END CERTIFICATE----- America Online Root Certification Authority 2 ============================================= -----BEGIN CERTIFICATE----- MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn 6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p +DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh 1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= -----END CERTIFICATE----- Visa eCommerce Root =================== -----BEGIN CERTIFICATE----- MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt 398znM/jra6O1I7mT1GvFpLgXPYHDw== -----END CERTIFICATE----- Certum Root CA ============== -----BEGIN CERTIFICATE----- MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== -----END CERTIFICATE----- Comodo AAA Services root ======================== -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- Comodo Secure Services root =========================== -----BEGIN CERTIFICATE----- MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP 9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm 4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H RR3B7Hzs/Sk= -----END CERTIFICATE----- Comodo Trusted Services root ============================ -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y /9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O 9y5Xt5hwXsjEeLBi -----END CERTIFICATE----- QuoVadis Root CA ================ -----BEGIN CERTIFICATE----- MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi 5nrQNiOKSnQ2+Q== -----END CERTIFICATE----- QuoVadis Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- QuoVadis Root CA 3 ================== -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- Security Communication Root CA ============================== -----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi FL39vmwLAw== -----END CERTIFICATE----- Sonera Class 2 Root CA ====================== -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH llpwrN9M -----END CERTIFICATE----- Staat der Nederlanden Root CA ============================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== -----END CERTIFICATE----- UTN DATACorp SGC Root CA ======================== -----BEGIN CERTIFICATE----- MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA 9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv 33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI -----END CERTIFICATE----- UTN USERFirst Hardware Root CA ============================== -----BEGIN CERTIFICATE----- MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 nfhmqA== -----END CERTIFICATE----- Camerfirma Chambers of Commerce Root ==================================== -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 erfutGWaIZDgqtCYvDi1czyL+Nw= -----END CERTIFICATE----- Camerfirma Global Chambersign Root ================================== -----BEGIN CERTIFICATE----- MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- NetLock Notary (Class A) Root ============================= -----BEGIN CERTIFICATE----- MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC /tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM 8CgHrTwXZoi1/baI -----END CERTIFICATE----- XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- Go Daddy Class 2 CA =================== -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b vZ8= -----END CERTIFICATE----- Starfield Class 2 CA ==================== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- StartCom Certification Authority ================================ -----BEGIN CERTIFICATE----- MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro g14= -----END CERTIFICATE----- Taiwan GRCA =========== -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS -----END CERTIFICATE----- Swisscom Root CA 1 ================== -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4 MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn 7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5 haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9 MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3 1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW NY6E0F/6MBr1mmz0DlP5OlvRHA== -----END CERTIFICATE----- DigiCert Assured ID Root CA =========================== -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- DigiCert Global Root CA ======================= -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- DigiCert High Assurance EV Root CA ================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K -----END CERTIFICATE----- Certplus Class 2 Primary CA =========================== -----BEGIN CERTIFICATE----- MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 l7+ijrRU -----END CERTIFICATE----- DST Root CA X3 ============== -----BEGIN CERTIFICATE----- MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- DST ACES CA X6 ============== -----BEGIN CERTIFICATE----- MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 oKfN5XozNmr6mis= -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 1 ============================================== -----BEGIN CERTIFICATE----- MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ 8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 2 ============================================== -----BEGIN CERTIFICATE----- MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr 5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P 9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 UrbnBEI= -----END CERTIFICATE----- SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- SwissSign Silver CA - G2 ======================== -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- GeoTrust Primary Certification Authority ======================================== -----BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= -----END CERTIFICATE----- thawte Primary Root CA ====================== -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== -----END CERTIFICATE----- VeriSign Class 3 Public Primary Certification Authority - G5 ============================================================ -----BEGIN CERTIFICATE----- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq -----END CERTIFICATE----- SecureTrust CA ============== -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- Secure Global CA ================ -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- COMODO Certification Authority ============================== -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== -----END CERTIFICATE----- Network Solutions Certificate Authority ======================================= -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- WellsSecure Public Root Certificate Authority ============================================= -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ tylv2G0xffX8oRAHh84vWdw+WNs= -----END CERTIFICATE----- COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- IGC/A ===== -----BEGIN CERTIFICATE----- MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF 0mBWWg== -----END CERTIFICATE----- Security Communication EV RootCA1 ================================= -----BEGIN CERTIFICATE----- MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 -----END CERTIFICATE----- OISTE WISeKey Global Root GA CA =============================== -----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= -----END CERTIFICATE----- Microsec e-Szigno Root CA ========================= -----BEGIN CERTIFICATE----- MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA 4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a 86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= -----END CERTIFICATE----- Certigna ======== -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- TC TrustCenter Class 2 CA II ============================ -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB 7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk vQ== -----END CERTIFICATE----- TC TrustCenter Class 3 CA II ============================ -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo 6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk 2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB 7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal 092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc 5A== -----END CERTIFICATE----- TC TrustCenter Universal CA I ============================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG 1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a 7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY -----END CERTIFICATE----- Deutsche Telekom Root CA 2 ========================== -----BEGIN CERTIFICATE----- MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- ComSign Secured CA ================== -----BEGIN CERTIFICATE----- MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs 49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH 7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP 51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== -----END CERTIFICATE----- Cybertrust Global Root ====================== -----BEGIN CERTIFICATE----- MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW WL1WMRJOEcgh4LMRkWXbtKaIOM5V -----END CERTIFICATE----- ePKI Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 ============================================================================================================================= -----BEGIN CERTIFICATE----- MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= -----END CERTIFICATE----- Buypass Class 2 CA 1 ==================== -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV 1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt 7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- Buypass Class 3 CA 1 ==================== -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c 1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 -----END CERTIFICATE----- EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 ========================================================================== -----BEGIN CERTIFICATE----- MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK 1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt 2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT -----END CERTIFICATE----- certSIGN ROOT CA ================ -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD -----END CERTIFICATE----- CNNIC ROOT ========== -----BEGIN CERTIFICATE----- MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m mxE= -----END CERTIFICATE----- ApplicationCA - Japanese Government =================================== -----BEGIN CERTIFICATE----- MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g /DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL rosot4LKGAfmt1t06SAZf7IbiVQ= -----END CERTIFICATE----- GeoTrust Primary Certification Authority - G3 ============================================= -----BEGIN CERTIFICATE----- MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt -----END CERTIFICATE----- thawte Primary Root CA - G2 =========================== -----BEGIN CERTIFICATE----- MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== -----END CERTIFICATE----- thawte Primary Root CA - G3 =========================== -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= -----END CERTIFICATE----- GeoTrust Primary Certification Authority - G2 ============================================= -----BEGIN CERTIFICATE----- MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 npaqBA+K -----END CERTIFICATE----- VeriSign Universal Root Certification Authority =============================================== -----BEGIN CERTIFICATE----- MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 mJO37M2CYfE45k+XmCpajQ== -----END CERTIFICATE----- VeriSign Class 3 Public Primary Certification Authority - G4 ============================================================ -----BEGIN CERTIFICATE----- MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== -----END CERTIFICATE----- NetLock Arany (Class Gold) Főtanúsítvány ============================================ -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- Staat der Nederlanden Root CA - G2 ================================== -----BEGIN CERTIFICATE----- MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm 66+KAQ== -----END CERTIFICATE----- CA Disig ======== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA 4Z7CRneC9VkGjCFMhwnN5ag= -----END CERTIFICATE----- Juur-SK ======= -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC +Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 yyqcjg== -----END CERTIFICATE----- Hongkong Post Root CA 1 ======================= -----BEGIN CERTIFICATE----- MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== -----END CERTIFICATE----- SecureSign RootCA11 =================== -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= -----END CERTIFICATE----- ACEDICOM Root ============= -----BEGIN CERTIFICATE----- MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA== -----END CERTIFICATE----- Microsec e-Szigno Root CA 2009 ============================== -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi LXpUq3DDfSJlgnCW -----END CERTIFICATE----- E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi =================================================== -----BEGIN CERTIFICATE----- MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY 8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk 9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX -----END CERTIFICATE----- GlobalSign Root CA - R3 ======================= -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r kpeDMdmztcpHWD9f -----END CERTIFICATE----- Autoridad de Certificacion Firmaprofesional CIF A62634068 ========================================================= -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -----END CERTIFICATE----- Izenpe.com ========== -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- Chambers of Commerce Root - 2008 ================================ -----BEGIN CERTIFICATE----- MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ -----END CERTIFICATE----- Global Chambersign Root - 2008 ============================== -----BEGIN CERTIFICATE----- MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B -----END CERTIFICATE----- Go Daddy Root Certificate Authority - G2 ======================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 -----END CERTIFICATE----- Starfield Root Certificate Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- Starfield Services Root Certificate Authority - G2 ================================================== -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 -----END CERTIFICATE----- AffirmTrust Commercial ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- AffirmTrust Networking ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- AffirmTrust Premium =================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== -----END CERTIFICATE----- AffirmTrust Premium ECC ======================= -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM eQ== -----END CERTIFICATE----- Certum Trusted Network CA ========================= -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- Certinomis - Autorité Racine ============================= -----BEGIN CERTIFICATE----- MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ vgt2Fl43N+bYdJeimUV5 -----END CERTIFICATE----- Root CA Generalitat Valenciana ============================== -----BEGIN CERTIFICATE----- MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt +GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= -----END CERTIFICATE----- A-Trust-nQual-03 ================ -----BEGIN CERTIFICATE----- MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 ahq97BvIxYSazQ== -----END CERTIFICATE----- TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- Security Communication RootCA2 ============================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- EC-ACC ====== -----BEGIN CERTIFICATE----- MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D 5EI= -----END CERTIFICATE----- Hellenic Academic and Research Institutions RootCA 2011 ======================================================= -----BEGIN CERTIFICATE----- MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 -----END CERTIFICATE----- Actalis Authentication Root CA ============================== -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- Trustis FPS Root CA =================== -----BEGIN CERTIFICATE----- MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl iB6XzCGcKQENZetX2fNXlrtIzYE= -----END CERTIFICATE----- StartCom Certification Authority ================================ -----BEGIN CERTIFICATE----- MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= -----END CERTIFICATE----- StartCom Certification Authority G2 =================================== -----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm obp573PYtlNXLfbQ4ddI -----END CERTIFICATE----- Buypass Class 2 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN rJgWVqA= -----END CERTIFICATE----- Buypass Class 3 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi Cp/HuZc= -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 3 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== -----END CERTIFICATE----- EE Certification Centre Root CA =============================== -----BEGIN CERTIFICATE----- MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM dcGWxZ0= -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 2007 ================================================= -----BEGIN CERTIFICATE----- MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK poRq0Tl9 -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 2009 ============================== -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- D-TRUST Root Class 3 CA 2 EV 2009 ================================= -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv w9y4AyHqnxbxLFS1 -----END CERTIFICATE----- PSCProcert ========== -----BEGIN CERTIFICATE----- MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/ AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km -----END CERTIFICATE----- China Internet Network Information Center EV Certificates Root ============================================================== -----BEGIN CERTIFICATE----- MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV 98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23 KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC 7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5 0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM 7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0 5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8= -----END CERTIFICATE----- Swisscom Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2 MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3 qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ 82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o +sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX 5OfNeOI5wSsSnqaeG8XmDtkx2Q== -----END CERTIFICATE----- Swisscom Root EV CA 2 ===================== -----BEGIN CERTIFICATE----- MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/ BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7 XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH 59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/ 23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc= -----END CERTIFICATE----- CA Disig Root R1 ================ -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ a7+h89n07eLw4+1knj0vllJPgFOL -----END CERTIFICATE----- CA Disig Root R2 ================ -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV 7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- ACCVRAIZ1 ========= -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p EfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- TWCA Global Root CA =================== -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= -----END CERTIFICATE----- TeliaSonera Root CA v1 ====================== -----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- E-Tugra Certification Authority =============================== -----BEGIN CERTIFICATE----- MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G C7TbO6Orb1wdtn7os4I07QZcJA== -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 2 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== -----END CERTIFICATE----- Atos TrustedRoot 2011 ===================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- QuoVadis Root CA 1 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV hMJKzRwuJIczYOXD -----END CERTIFICATE----- QuoVadis Root CA 2 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr O3jtZsSOeWmD3n+M -----END CERTIFICATE----- QuoVadis Root CA 3 G3 ===================== -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- DigiCert Assured ID Root G2 =========================== -----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- DigiCert Assured ID Root G3 =========================== -----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy 1vUhZscv6pZjamVFkpUBtA== -----END CERTIFICATE----- DigiCert Global Root G2 ======================= -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- DigiCert Global Root G3 ======================= -----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 VOKa5Vt8sycX -----END CERTIFICATE----- DigiCert Trusted Root G4 ======================== -----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP 82Z+ -----END CERTIFICATE----- WoSign ====== -----BEGIN CERTIFICATE----- MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/ EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w== -----END CERTIFICATE----- WoSign China ============ -----BEGIN CERTIFICATE----- MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO kI26oQ== -----END CERTIFICATE----- PK\DIdefault/plugins/payment/bitpay/Bitpay/Client/Adapter/AdapterInterface.phpnu[curlOptions = $curlOptions; } /** * Returns an array of curl settings to use * * @return array */ public function getCurlOptions() { return $this->curlOptions; } /** * @inheritdoc */ public function sendRequest(RequestInterface $request) { $curl = curl_init(); $default_curl_options = $this->getCurlDefaultOptions($request); foreach ($this->getCurlOptions() as $curl_option_key => $curl_option_value) { if (!is_null($curl_option_value)) { $default_curl_options[$curl_option_key] = $curl_option_value; } } curl_setopt_array($curl, $default_curl_options); if (RequestInterface::METHOD_POST == $request->getMethod()) { curl_setopt_array( $curl, array( CURLOPT_POST => 1, CURLOPT_POSTFIELDS => $request->getBody(), ) ); } $raw = curl_exec($curl); if (false === $raw) { $errorMessage = curl_error($curl); curl_close($curl); throw new \Bitpay\Client\ConnectionException($errorMessage); } /** @var ResponseInterface */ $response = Response::createFromRawResponse($raw); curl_close($curl); return $response; } /** * Returns an array of default curl settings to use * * @param RequestInterface $request * @return array */ private function getCurlDefaultOptions(RequestInterface $request) { return array( CURLOPT_URL => $request->getUri(), CURLOPT_PORT => $request->getPort(), CURLOPT_CUSTOMREQUEST => $request->getMethod(), CURLOPT_HTTPHEADER => $request->getHeaderFields(), CURLOPT_TIMEOUT => 10, CURLOPT_SSL_VERIFYPEER => 1, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_CAINFO => __DIR__.'/ca-bundle.crt', CURLOPT_RETURNTRANSFER => true, CURLOPT_FORBID_REUSE => 1, CURLOPT_FRESH_CONNECT => 1, CURLOPT_HEADER => true, ); } } PK\(Adefault/plugins/payment/bitpay/Bitpay/Client/RequestInterface.phpnu[ $value array of http headers * * @return array */ public function getHeaders(); } PK\+   9default/plugins/payment/bitpay/Bitpay/Client/Response.phpnu[headers = array(); $this->raw = $raw; } /** * Returns the raw http response * * @return string */ public function __toString() { return (string) $this->raw; } /** */ public static function createFromRawResponse($rawResponse) { $response = new self($rawResponse); $lines = preg_split('/(\\r?\\n)/', $rawResponse); $linesLen = count($lines); for ($i = 0; $i < $linesLen; $i++) { if (0 == $i) { preg_match('/^HTTP\/(\d\.\d)\s(\d+)\s(.+)/', $lines[$i], $statusLine); $response->setStatusCode($statusCode = $statusLine[2]); continue; } if (empty($lines[$i])) { $body = array_slice($lines, $i + 1); $response->setBody(implode("\n", $body)); break; } if (strpos($lines[$i], ':')) { $headerParts = explode(':', $lines[$i]); $response->setHeader($headerParts[0], $headerParts[1]); } } return $response; } /** * @inheritdoc */ public function getStatusCode() { return $this->statusCode; } /** * @param integer * * @return ResponseInterface */ public function setStatusCode($statusCode) { $this->statusCode = (integer) $statusCode; return $this; } /** * @inheritdoc */ public function getBody() { return $this->body; } /** * Set the body of the response * * @param string $body */ public function setBody($body) { $this->body = $body; return $this; } /** * @inheritdoc */ public function getHeaders() { return $this->headers; } /** * @param string $header * @param string $value */ public function setHeader($header, $value) { $this->headers[$header] = $value; return $this; } } PK\sQ:*\\Ddefault/plugins/payment/bitpay/Bitpay/Client/ConnectionException.phpnu[uXX@default/plugins/payment/bitpay/Bitpay/Client/BitpayException.phpnu[ $value array of http headers * * @return array */ public function getHeaders(); } PK\!ZZBdefault/plugins/payment/bitpay/Bitpay/Client/ArgumentException.phpnu[headers = array( 'Content-Type' => 'application/json', 'X-BitPay-Plugin-Info' => null, ); $this->port = 443; // Default method is POST $this->method = self::METHOD_POST; } /** * Converts this request into a standard HTTP/1.1 message to be sent over * the wire * * @return string */ public function __toString() { $request = sprintf("%s %s HTTP/1.1\r\n", $this->getMethod(), $this->getUriWithPort()); $request .= $this->getHeadersAsString(); $request .= $this->getBody(); return trim($request); } /** * @inheritdoc */ public function isMethod($method) { return (strtoupper($method) == strtoupper($this->method)); } /** * @inheritdoc */ public function getPort() { return $this->port; } /** * This is called in the Adapter * * @inheritdoc */ public function setPort($port) { $this->port = $port; } /** * @inheritdoc */ public function getMethod() { return $this->method; } /** * Set the method of the request, for known methods see the * RequestInterface * * @param string $method */ public function setMethod($method) { $this->method = $method; } /** * @inheritdoc */ public function getSchema() { return 'https'; } /** * @inheritdoc */ public function getUri() { return sprintf( '%s://%s/%s', $this->getSchema(), $this->getHost(), $this->getPath() ); } /** * @inheritdoc */ public function getUriWithPort() { return sprintf( '%s://%s:%s/%s', $this->getSchema(), $this->getHost(), $this->getPort(), $this->getPath() ); } /** * @inheritdoc */ public function getHost() { return $this->host; } /** * Sets the host for the request * * @param string $host */ public function setHost($host) { $this->host = $host; return $this; } /** * @inheritdoc */ public function getHeaders() { // remove invalid headers $headers = $this->headers; foreach ($headers as $header => $value) { if (empty($header) || empty($value)) { unset($headers[$header]); } } return $headers; } public function getHeaderFields() { $fields = array(); foreach ($this->getHeaders() as $header => $value) { $fields[] = sprintf('%s: %s', $header, $value); } return $fields; } /** * @return string */ public function getHeadersAsString() { $headers = $this->getHeaders(); $return = ''; foreach ($headers as $h => $v) { $return .= sprintf("%s: %s\r\n", $h, $v); } return $return."\r\n"; } /** * Set a http header for the request * * @param string $header * @param string $value */ public function setHeader($header, $value) { if (is_array($value)) { throw new \Exception('Could not set the header: '.$header); } $this->headers[$header] = $value; } /** * @inheritdoc */ public function getBody() { return $this->body; } /** * The the body of the request * * @param string $body */ public function setBody($body) { $this->body = $body; $this->setHeader('Content-Length', strlen($body)); return $this; } /** * @inheritdoc */ public function getPath() { return $this->path; } /** * @param string $host */ public function setPath($path) { $this->path = $path; return $this; } } PK\߮;default/plugins/payment/bitpay/Bitpay/PayoutInstruction.phpnu[transactions = array(); } /** * @inheritdoc */ public function getId() { return $this->id; } /** * Set the Bitpay ID for this payout instruction * * @param $id * @return $this */ public function setId($id) { if (!empty($id)) { $this->id = trim($id); } return $this; } /** * @inheritdoc */ public function getLabel() { return $this->label; } /** * Set the employers label for this instruction. * @param $label * @return $this */ public function setLabel($label) { if (!empty($label)) { $this->label = trim($label); } return $this; } /** * @inheritdoc */ public function getAddress() { return $this->address; } /** * Set the bitcoin address for this instruction. * @param $address * @return $this */ public function setAddress($address) { if (!empty($address)) { $this->address = trim($address); } return $this; } /** * @inheritdoc */ public function getAmount() { return $this->amount; } /** * Set the amount for this instruction. * @param $amount * @return $this */ public function setAmount($amount) { if (!empty($amount)) { $this->amount = $amount; } return $this; } /** * @inheritdoc */ public function getBtc() { return $this->btc; } /** * Set BTC array (available once rates are set) * @param $btc * @return $this */ public function setBtc($btc) { if (!empty($btc) && is_array($btc)) { $this->btc = $btc; } return $this; } /** * @inheritdoc */ public function getStatus() { return $this->status; } /** * Set the status for this instruction * @param $status * @return $this */ public function setStatus($status) { if (!empty($status) && ctype_print($status)) { $this->status = trim($status); } return $this; } /** * @inheritdoc */ public function getTransactions() { return $this->transactions; } /** * Add payout transaction to the * @param PayoutTransactionInterface $transaction * @return $this */ public function addTransaction(PayoutTransactionInterface $transaction) { if (!empty($transaction)) { $this->transactions[] = $transaction; } return $this; } } PK\~|8default/plugins/payment/bitpay/Bitpay/Math/GmpEngine.phpnu[default/plugins/payment/bitpay/Bitpay/Math/EngineInterface.phpnu[input($a); $b = $this->input($b); return bcadd($a, $b); } /** * @param String $a Numeric String * @param String $b Numeric String */ public function cmp($a, $b) { $a = $this->input($a); $b = $this->input($b); return bccomp($a, $b); } /** * @param String $a Numeric String * @param String $b Numeric String */ public function div($a, $b) { $a = $this->input($a); $b = $this->input($b); return bcdiv($a, $b); } /** * Finds inverse number $inv for $num by modulus $mod, such as: * $inv * $num = 1 (mod $mod) * * @param string $num * @param string $mod * @return string * @access public */ public function invertm($num, $mod) { $num = $this->input($num); $mod = $this->input($mod); $x = '1'; $y = '0'; $num1 = $mod; do { $tmp = bcmod($num, $num1); $q = bcdiv($num, $num1); $num = $num1; $num1 = $tmp; $tmp = bcsub($x, bcmul($y, $q)); $x = $y; $y = $tmp; } while (bccomp($num1, '0')); if (bccomp($x, '0') < 0) { $x = bcadd($x, $mod); } if (substr($num, 0, 1) === '-') { $x = bcsub($mod, $x); } return $x; } /** * @param String $a Numeric String * @param String $b Numeric String */ public function mod($a, $b) { $a = $this->input($a); $b = $this->input($b); if (substr($a, 0, 1) === '-') { return bcadd(bcmod($a, $b), $b); } return bcmod($a, $b); } /** * @param String $a Numeric String * @param String $b Numeric String */ public function mul($a, $b) { $a = $this->input($a); $b = $this->input($b); return bcmul($a, $b); } /** * @param String $a Numeric String * @param String $b Numeric String */ public function pow($a, $b) { $a = $this->input($a); $b = $this->input($b); return bcpow($a, $b); } /** * @param String $a Numeric String * @param String $b Numeric String */ public function sub($a, $b) { $a = $this->input($a); $b = $this->input($b); return bcsub($a, $b); } public function input($x) { if (empty($x)) { return '0'; } $x = strtolower(trim($x)); if (preg_match('/^(-?)0x([0-9a-f]+)$/', $x, $matches)) { $sign = $matches[1]; $hex = $matches[2]; for ($dec = '0', $i = 0; $i < strlen($hex); $i++) { $current = strpos('0123456789abcdef', $hex[$i]); $dec = bcadd(bcmul($dec, 16), $current); } return $sign.$dec; } elseif (preg_match('/^-?[0-9]+$/', $x)) { return $x; } else { throw new \Exception("The input must be a numeric string in decimal or hexadecimal (with leading 0x) format.\n".var_export($x, true)); } } /** * Function to determine if two numbers are * co-prime according to the Euclidean algo. * * @param string $a First param to check. * @param string $b Second param to check. * @return bool Whether the params are cp. */ public function coprime($a, $b) { $small = 0; $diff = 0; while (bccomp($a, '0') > 0 && bccomp($b, '0') > 0) { if (bccomp($a, $b) == -1) { $small = $a; $diff = bcmod($b, $a); } if (bccomp($a, $b) == 1) { $small = $b; $diff = bcmod($a, $b); } if (bccomp($a, $b) == 0) { $small = $a; $diff = bcmod($b, $a); } $a = $small; $b = $diff; } if (bccomp($a, '1') == 0) { return true; } return false; } } PK\C`a!.default/plugins/payment/bitpay/Bitpay/Bill.phpnu[address = array(); $this->archived = false; $this->currency = new Currency(); $this->items = array(); } /** * @inheritdoc */ public function getItems() { return $this->items; } /** * @param ItemInterface $item * * @return BillInterface */ public function addItem(ItemInterface $item) { if (!empty($item)) { $this->items[] = $item; } return $this; } /** * @inheritdoc */ public function getCurrency() { return $this->currency; } /** * @param CurrencyInterface $currency * * @return BillInterface */ public function setCurrency(CurrencyInterface $currency) { if (!empty($currency)) { $this->currency = $currency; } return $this; } /** * @inheritdoc */ public function getName() { return $this->name; } /** * @param string $name * * @return BillInterface */ public function setName($name) { if (!empty($name) && ctype_print($name)) { $this->name = trim($name); } return $this; } /** * @inheritdoc */ public function getAddress() { return $this->address; } /** * @param array $address * * @return BillInterface */ public function setAddress($address) { if (!empty($address) && is_array($address)) { $this->address = $address; } return $this; } /** * @inheritdoc */ public function getCity() { return $this->city; } /** * @param string $city * * @return BillInterface */ public function setCity($city) { if (!empty($city) && ctype_print($city)) { $this->city = trim($city); } return $this; } /** * @inheritdoc */ public function getState() { return $this->state; } /** * @param string $state * * @return BillInterface */ public function setState($state) { if (!empty($state) && ctype_print($state)) { $this->state = trim($state); } return $this; } /** * @inheritdoc */ public function getZip() { return $this->zip; } /** * @param string $zip * * @return BillInterface */ public function setZip($zip) { if (!empty($zip) && ctype_print($zip)) { $this->zip = trim($zip); } return $this; } /** * @inheritdoc */ public function getCountry() { return $this->country; } /** * @param string $country * * @return BillInterface */ public function setCountry($country) { if (!empty($country) && ctype_print($country)) { $this->country = trim($country); } return $this; } /** * @inheritdoc */ public function getEmail() { return $this->email; } /** * @param string $email * * @return BillInterface */ public function setEmail($email) { if (!empty($email) && ctype_print($email)) { $this->email = trim($email); } return $this; } /** * @inheritdoc */ public function getPhone() { return $this->phone; } /** * @param string $phone * * @return BillInterface */ public function setPhone($phone) { if (!empty($phone) && ctype_print($phone)) { $this->phone = trim($phone); } return $this; } /** * @inheritdoc */ public function getStatus() { return $this->status; } /** * @param string $status * * @return BillInterface */ public function setStatus($status) { if (!empty($status) && ctype_print($status)) { $this->status = trim($status); } return $this; } /** * @inheritdoc */ public function getShowRate() { return $this->showRate; } /** * @param string $showRate * * @return BillInterface */ public function setShowRate($showRate) { if (!empty($showRate) && ctype_print($showRate)) { $this->showRate = trim($showRate); } return $this; } /** * @inheritdoc */ public function getArchived() { return $this->archived; } /** * @param boolean $archived * * @return BillInterface */ public function setArchived($archived) { $this->archived = (boolean) $archived; return $this; } } PK\6օ77@default/plugins/payment/bitpay/Bitpay/Crypto/CryptoInterface.phpnu[ $digest_alg, 'private_key_bits' => (int) $keybits, 'private_key_type' => OPENSSL_KEYTYPE_RSA, ); $resource = openssl_pkey_new($config); if (!$resource) { throw new \Exception('Error in generateOpenSSLKeypair: Could not create new OpenSSL resource.'); /* with the openssl extension, you also have it's own errors returned */ while ($msg = openssl_error_string()) { throw new \Exception('Error in generateOpenSSLKeypair: OpenSSL reported error: '.$msg); } return false; } if (openssl_pkey_export($resource, $keypair['pri'])) { $publickey = openssl_pkey_get_details($resource); $keypair['pub'] = $publickey['key']; } else { throw new \Exception('Error in generateOpenSSLKeypair: Private key could not be determined from OpenSSL key resource.'); while ($msg = openssl_error_string()) { throw new \Exception('Error in generateOpenSSLKeypair: OpenSSL reported error: '.$msg); } return false; } openssl_pkey_free($resource); return $keypair; } else { throw new \Exception('Error in generateOpenSSLKeypair: OpenSSL PHP extension missing. Cannot continue.'); return false; } } catch (Exception $e) { while ($msg = openssl_error_string()) { throw new \Exception('Error in generateOpenSSLKeypair: OpenSSL reported error: '.$msg); } throw $e; return false; } } /** * Generates a high-quality random number suitable for * use in cryptographic functions and returns hex value. * * @param int * @return string|bool */ final public function randomNumber($bytes = 32) { $random_data = openssl_random_pseudo_bytes($bytes, $cstrong); if (!$cstrong || !$random_data) { return false; } else { return bin2hex($random_data); } } /** * Returns the cipher length on success, or FALSE * on failure. (PHP 5 >= PHP 5.3.3) * * @param string * @return int|bool */ final public function cypherIVLength($cypher = '') { return openssl_cipher_iv_length($cypher); } /** * Takes the Certificate Signing Request represented * by $csr and saves it as ascii-armoured text into * the file named by $outfilename. * (PHP 4 >= 4.2.0, PHP 5) * * @param resource * @param string * @param bool * @return bool */ final public function saveCSRtoFile($csr, $outfilename, $notext = true) { if (!is_resource($csr)) { return false; } return openssl_csr_export_to_file($csr, $outfilename, $notext); } /** * Takes the Certificate Signing Request represented * by $csr and stores it as ascii-armoured text into * $out, which is passed by reference. * (PHP 4 >= 4.2.0, PHP 5) * * @param resource * @param string * @param bool * @return bool */ final public function saveCSRtoString($csr, $out, $notext = true) { if (!is_resource($csr)) { return false; } return openssl_csr_export($csr, $out, $notext); } } PK\$W;>default/plugins/payment/bitpay/Bitpay/Crypto/HashExtension.phpnu[= 5.1.2, PECL hash >= 1.1) * * @return array */ public function getAlgos() { return hash_algos(); } /** * Copy a hashing context. * (PHP 5 >= 5.3.0) * * @param resource * @return resource */ final public function copy($context) { if (!is_resource($context)) { return false; } return hash_copy($context); } /** * Compares two strings using the same time * whether they're equal or not. This function * should be used to mitigate timing attacks; * for instance, when testing crypt() password * hashes. * (PHP 5 >= 5.6.0) * * @param string * @param string */ public function equals($string1, $string2) { if (!is_string($string1) || !is_string($string2)) { return false; } return hash_equals($string1, $string2); } /** * Generate a hash value using the contents of * a given file. Returns a string containing * the calculated message digest as lowercase * hexits unless raw_output is set to true in * which case the raw binary representation of * the message digest is returned. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param string * @param string * @param bool * @return string */ public function file($algorithm, $filename, $raw_output = false) { return hash_file($algorithm, (string) $filename, $raw_output); } /** * Finalize an incremental hash and return * resulting digest. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param resource * @param bool * @return string */ public function finalize($context, $raw_output = false) { if (!is_resource($context)) { return false; } return hash_final($context, $raw_output); } /** * Generate a keyed hash value using the HMAC * method and the contents of a given file. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param string * @param string * @param string * @param bool * @return string */ public function hmacFile($algorithm, $filename, $key, $raw_output = false) { return hash_hmac_file($algorithm, $filename, $key, $raw_output); } /** * Generate a keyed hash value using the HMAC * method and the message passed via $data. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param string * @param string * @param string * @param bool * @return string */ public function hmac($algo, $data, $key, $raw_output = false) { return hash_hmac($algo, $data, $key, $raw_output); } /** * Initialize an incremental hashing context and * returns a Hashing Context resource for use with * hash_update(), hash_update_stream(), hash_update_file(), * and hash_final(). Note: the only option possible * for $options at this time is HASH_HMAC. When * this is specified, the key *must* be used as well. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param string * @param int * @param string * @return resource */ public function init($algorithm, $options = 0, $key = null) { return hash_init($algorithm, $options, $key); } /** * Generate a PBKDF2 key derivation of a supplied * password. An E_WARNING will be raised if the * algorithm is unknown, the iterations parameter * is less than or equal to 0, the length is less * than 0 or the salt is too long (greater than * INT_MAX - 4). The salt should be generated * randomly with openssl_ramdom_pseudo_bytes(). * (PHP 5 >= 5.5.0) * * @param string * @param string * @param string * @param int * @param int * @param bool * @return string */ public function pbkdf2($algo, $password, $salt, $iterations, $length = 0, $raw_output = false) { return hash_pbkdf2($algo, $password, $salt, $iterations, $length, $raw_output); } /** * Pump data into an active hashing context * from a file. Returns TRUE on success or * FALSE on failure. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param resource * @param string * @param resource * @return bool */ public function updateFile($hcontext, $filename, $scontext = null) { if (!is_resource($hcontext)) { return false; } return hash_update_file($hcontext, $filename, $scontext); } /** * Pump data into an active hashing context * from an open stream. Returns the actual * number of bytes added to the hashing * context from handle. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param resource * @param resource * @param int * @return int */ public function updateStream($context, $handle, $length = -1) { if (!is_resource($context) || !is_resource($handle)) { return false; } return hash_update_stream($context, $handle, $length); } /** * Pump data into an active hashing context. * The PHP function itself only returns true. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param resource * @param string * @return bool */ public function update($context, $data) { if (!is_resource($context)) { return false; } return hash_update($context, $data); } /** * Generate a hash value (message digest) * based on the request algorithm and the * provided data. Outputs hex unless the * $raw_output param is set to true. * (PHP 5 >= 5.1.2, PECL hash >= 1.1) * * @param string * @param string * @param bool * @return string */ public function generate($algo, $data, $raw_output = false) { if (empty($data)) { return false; } return hash($algo, $data, $raw_output); } } PK\J .default/plugins/payment/bitpay/Bitpay/Item.phpnu[physical = false; } /** * @inheritdoc */ public function getCode() { return $this->code; } /** * @param string $code * * @return ItemInterface */ public function setCode($code) { $this->code = $code; return $this; } /** * @inheritdoc */ public function getDescription() { return $this->description; } /** * @param string $description * * @return ItemInterface */ public function setDescription($description) { $this->description = $description; return $this; } /** * @inheritdoc * * @return float */ public function getPrice() { return $this->price; } /** * @param mixed $price A float, integer, or en_US formatted numeric string * * @return ItemInterface */ public function setPrice($price) { if (is_string($price)) { $this->checkPriceFormat($price); } $this->price = (float)$price; return $this; } /** * @inheritdoc */ public function getQuantity() { return $this->quantity; } /** * @param integer $quantity * * @return ItemInterface */ public function setQuantity($quantity) { $this->quantity = $quantity; return $this; } /** * @inheritdoc */ public function isPhysical() { return $this->physical; } /** * @param boolean $physical * * @return ItemInterface */ public function setPhysical($physical) { $this->physical = (boolean)$physical; return $this; } /** * Checks the new price to include BTC * values with more than 6 decimals. * * @param string $price The price value to check * @throws \Exception */ protected function checkPriceFormat($price) { if (preg_match('/^[0-9]+?[\.,][0-9]{1,6}?$/', $price) !== 1) { throw new \Bitpay\Client\ArgumentException("Price must be formatted as a float"); } } } PK\$?o7default/plugins/payment/bitpay/Bitpay/UserInterface.phpnu[schedule; } public function getBillData() { return array( 'currency' => $this->currency, 'price' => $this->price, 'quantity' => $this->quantity, 'dueDate' => $this->dueDate, 'token' => $this->token, 'items' => $this->items ); } } PK\'QDdefault/plugins/payment/bitpay/Bitpay/PayoutTransactionInterface.phpnu[default/plugins/payment/bitpay/Bitpay/Config/Configuration.phpnu[root('bitpay'); $rootNode ->children() ->scalarNode('public_key') ->info('Public Key Filename') ->defaultValue(getenv('HOME').'/.bitpay/api.pub') ->end() ->scalarNode('private_key') ->info('Private Key Filename') ->defaultValue(getenv('HOME').'/.bitpay/api.key') ->end() ->scalarNode('sin_key') ->info('Private Key Filename') ->defaultValue(getenv('HOME').'/.bitpay/api.sin') ->end() ->enumNode('network') ->values(array('livenet', 'testnet')) ->info('Network') ->defaultValue('livenet') ->end() ->enumNode('adapter') ->values(array('curl', 'mock')) ->info('Client Adapter') ->defaultValue('curl') ->end() ->append($this->addKeyStorageNode()) ->scalarNode('key_storage_password') ->info('Used to encrypt and decrypt keys when saving to filesystem') ->defaultNull() ->end() ->end(); return $treeBuilder; } /** * Adds the key_storage node with validation rules * * key_storage MUST: * * implement Bitpay\Storage\StorageInterface * * be a class that can be loaded */ protected function addKeyStorageNode() { $builder = new TreeBuilder(); $node = $builder->root('key_storage', 'scalar'); $node ->info('Class that is used to store your keys') ->defaultValue('Bitpay\Storage\EncryptedFilesystemStorage') ->validate() ->always() ->then(function ($value) { if (!class_exists($value)) { throw new \Exception( sprintf( 'Could not find class "%s".', $value ) ); } // requires PHP >= 5.3.7 if (!is_subclass_of($value, 'Bitpay\Storage\StorageInterface')) { throw new \Exception( sprintf( '"%s" does not implement "Bitpay\Storage\StorageInterface"', $value ) ); } return $value; }) ->end(); return $node; } } PK\"  5default/plugins/payment/bitpay/Bitpay/AccessToken.phpnu[useNonce = true; } /** * @param string $id * * @return AccessTokenInterface */ public function setId($id) { if (!empty($id) && is_string($id) && ctype_print($id)) { $this->id = trim($id); } return $this; } /** * @inheritdoc */ public function getId() { return $this->id; } /** * @param string $email * * @return AccessTokenInterface */ public function setEmail($email) { if (!empty($email) && is_string($email) && ctype_print($email)) { $this->email = trim($email); } return $this; } /** * @inheritdoc */ public function getEmail() { return $this->email; } /** * @param string $label * * @return AccessTokenInterface */ public function setLabel($label) { if (!empty($label) && is_string($label) && ctype_print($label)) { $this->label = trim($label); } return $this; } /** * @inheritdoc */ public function getLabel() { return $this->label; } /** * @inheritdoc */ public function isNonceDisabled() { return !($this->useNonce); } /** * Enable nonce usage * * @return AccessTokenInterface */ public function nonceEnable() { $this->useNonce = true; return $this; } /** * Disable nonce usage * * @return AccessTokenInterface */ public function nonceDisable() { $this->useNonce = false; return $this; } } PK\TCqq;default/plugins/payment/bitpay/Bitpay/PayoutTransaction.phpnu[txid; } /** * Set transaction ID for payout. * @param $txid * @return $this */ public function setTransactionId($txid) { if (!empty($txid)) { $this->txid = $txid; } return $this; } /** * @inheritdoc */ public function getAmount() { return $this->amount; } /** * Set the amount of bitcoin paid in the paout. * @param $amount * @return $this */ public function setAmount($amount) { if (!empty($amount)) { $this->amount = $amount; } return $this; } /** * @inheritdoc */ public function getDate() { return $this->date; } /** * Set the date and time of when the payment was sent. * @param $date * @return $this */ public function setDate($date) { if (!empty($date)) { $this->date = $date; } return $this; } } PK\v>;;Mdefault/plugins/payment/bitpay/Bitpay/DependencyInjection/BitpayExtension.phpnu[processConfiguration(new Configuration(), $configs); foreach (array_keys($config) as $key) { $container->setParameter('bitpay.'.$key, $config[$key]); } $loader = new XmlFileLoader($container, new FileLocator(__DIR__)); $loader->load('services.xml'); $container->setParameter('network.class', 'Bitpay\Network\\'.ContainerBuilder::camelize($config['network'])); $container->setParameter( 'adapter.class', 'Bitpay\Client\Adapter\\'.ContainerBuilder::camelize($config['adapter']).'Adapter' ); $container->setParameter('key_storage.class', $config['key_storage']); } /** * @codeCoverageIgnore */ public function getAlias() { return 'bitpay'; } /** * @codeCoverageIgnore */ public function getNamespace() { return 'http://example.org/schema/dic/bitpay'; } /** * @codeCoverageIgnore */ public function getXsdValidationBasePath() { return false; } } PK\lXFdefault/plugins/payment/bitpay/Bitpay/DependencyInjection/services.xmlnu[ Bitpay\Network\Livenet Bitpay\Client\Adapter\CurlAdapter Bitpay\KeyManager Bitpay\Storage\FilesystemStorage %bitpay.key_storage_password% %bitpay.public_key% %bitpay.private_key% PK\&1v Pdefault/plugins/payment/bitpay/Bitpay/DependencyInjection/Loader/ArrayLoader.phpnu[container = $container; } public function load($resource, $type = null) { // validation foreach (array_keys($resource) as $namespace) { if (in_array($namespace, array('imports', 'paramters', 'services'))) { continue; } if (!$this->container->hasExtension($namespace)) { $extensionNamespaces = array_filter( array_map( function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions() ) ); throw new InvalidArgumentException(sprintf( 'There is no extension able to load the configuration for "%s". Looked for namespace "%s", found %s', $namespace, $namespace, $extensionNamespaces ? sprintf('"%s"', implode('", "', $extensionNamespaces)) : 'none' )); } } // Set Paramters if (isset($resource['parameters'])) { foreach ($resource['parameters'] as $key => $value) { $this->container->setParameter($key, $value); } } // extensions foreach ($resource as $namespace => $values) { if (in_array($namespace, array('imports', 'parameters', 'services'))) { continue; } if (!is_array($values)) { $values = array(); } $this->container->loadFromExtension($namespace, $values); } } public function supports($resource, $type = null) { return is_array($resource); } } PK\cBdefault/plugins/payment/bitpay/Bitpay/Storage/StorageInterface.phpnu[getId(); file_put_contents($path, serialize($key)); } /** * @inheritdoc */ public function load($id) { if (!is_file($id)) { throw new \Exception(sprintf('Could not find "%s"', $id)); } if (!is_readable($id)) { throw new \Exception(sprintf('"%s" cannot be read, check permissions', $id)); } return unserialize(file_get_contents($id)); } } PK\#Ldefault/plugins/payment/bitpay/Bitpay/Storage/EncryptedFilesystemStorage.phpnu[password = $password; } /** * @inheritdoc */ public function persist(\Bitpay\KeyInterface $key) { $path = $key->getId(); $data = serialize($key); $encoded = bin2hex(openssl_encrypt( $data, self::METHOD, $this->password, 1, self::IV )); file_put_contents($path, $encoded); } /** * @inheritdoc */ public function load($id) { if (!is_file($id)) { throw new \Exception(sprintf('Could not find "%s"', $id)); } if (!is_readable($id)) { throw new \Exception(sprintf('"%s" cannot be read, check permissions', $id)); } $encoded = file_get_contents($id); $decoded = openssl_decrypt(\Bitpay\Util\Util::binConv($encoded), self::METHOD, $this->password, 1, self::IV); if (false === $decoded) { throw new \Exception('Could not decode key'); } return unserialize($decoded); } } PK\LΥ=default/plugins/payment/bitpay/Bitpay/Storage/MockStorage.phpnu[default/plugins/payment/bitpay/Bitpay/AccessTokenInterface.phpnu[transactionSpeed = self::TRANSACTION_SPEED_MEDIUM; $this->fullNotifications = false; } /** * @inheritdoc */ public function getPrice() { return $this->getItem()->getPrice(); } /** * @param float $price * * @return InvoiceInterface */ public function setPrice($price) { if (!empty($price)) { $this->getItem()->setPrice($price); } return $this; } /** * @inheritdoc */ public function getCurrency() { return $this->currency; } /** * @param CurrencyInterface $currency * * @return InvoiceInterface */ public function setCurrency(CurrencyInterface $currency) { if (!empty($currency)) { $this->currency = $currency; } return $this; } /** * @inheritdoc */ public function getItem() { // If there is not an item already set, we need to use a default item // so that some methods do not throw errors about methods and // non-objects. if (null == $this->item) { $this->item = new Item(); } return $this->item; } /** * @param ItemInterface $item * * @return InvoiceInterface */ public function setItem(ItemInterface $item) { if (!empty($item)) { $this->item = $item; } return $this; } /** * @inheritdoc */ public function getBuyer() { // Same logic as getItem method if (null == $this->buyer) { $this->buyer = new Buyer(); } return $this->buyer; } /** * @param BuyerInterface $buyer * * @return InvoiceInterface */ public function setBuyer(BuyerInterface $buyer) { if (!empty($buyer)) { $this->buyer = $buyer; } return $this; } /** * @inheritdoc */ public function getTransactionSpeed() { return $this->transactionSpeed; } /** * @param string $transactionSpeed * * @return InvoiceInterface */ public function setTransactionSpeed($transactionSpeed) { if (!empty($transactionSpeed) && ctype_print($transactionSpeed)) { $this->transactionSpeed = trim($transactionSpeed); } return $this; } /** * @inheritdoc */ public function getNotificationEmail() { return $this->notificationEmail; } /** * @param string $notificationEmail * * @return InvoiceInterface */ public function setNotificationEmail($notificationEmail) { if (!empty($notificationEmail) && ctype_print($notificationEmail)) { $this->notificationEmail = trim($notificationEmail); } return $this; } /** * @inheritdoc */ public function getNotificationUrl() { return $this->notificationUrl; } /** * @param string $notificationUrl * * @return InvoiceInterface */ public function setNotificationUrl($notificationUrl) { if (!empty($notificationUrl) && ctype_print($notificationUrl)) { $this->notificationUrl = trim($notificationUrl); } return $this; } /** * @inheritdoc */ public function getRedirectUrl() { return $this->redirectUrl; } /** * @param string $redirectUrl * * @return InvoiceInterface */ public function setRedirectUrl($redirectUrl) { if (!empty($redirectUrl) && ctype_print($redirectUrl)) { $this->redirectUrl = trim($redirectUrl); } return $this; } /** * @inheritdoc */ public function getPosData() { return $this->posData; } /** * @param string $posData * * @return InvoiceInterface */ public function setPosData($posData) { if (!empty($posData)) { $this->posData = $posData; } return $this; } /** * @inheritdoc */ public function getStatus() { return $this->status; } /** * @param string $status * * @return InvoiceInterface */ public function setStatus($status) { if (!empty($status) && ctype_print($status)) { $this->status = trim($status); } return $this; } /** * @inheritdoc */ public function isFullNotifications() { return $this->fullNotifications; } public function setFullNotifications($notifications) { $this->fullNotifications = (boolean) $notifications; return $this; } /** * @inheritdoc */ public function getId() { return $this->id; } /** * @param string $id * * @return InvoiceInterface */ public function setId($id) { if (!empty($id) && ctype_print($id)) { $this->id = trim($id); } return $this; } /** * @inheritdoc */ public function getUrl() { return $this->url; } /** * @param string $url * * @return InvoiceInterface */ public function setUrl($url) { if (!empty($url) && ctype_print($url)) { $this->url = trim($url); } return $this; } /** * @inheritdoc */ public function getBtcPrice() { return $this->btcPrice; } /** * @param float $btcPrice * * @return InvoiceInterface */ public function setBtcPrice($btcPrice) { if (!empty($btcPrice)) { $this->btcPrice = $btcPrice; } return $this; } /** * @inheritdoc */ public function getInvoiceTime() { return $this->invoiceTime; } /** * @param DateTime $invoiceTime * * @return InvoiceInterface */ public function setInvoiceTime($invoiceTime) { if (!empty($invoiceTime)) { $this->invoiceTime = $invoiceTime; } return $this; } /** * @inheritdoc */ public function getExpirationTime() { return $this->expirationTime; } /** * @param DateTime $expirationTime * * return InvoiceInterface */ public function setExpirationTime($expirationTime) { if (!empty($expirationTime)) { $this->expirationTime = $expirationTime; } return $this; } /** * @inheritdoc */ public function getCurrentTime() { return $this->currentTime; } /** * @param DateTime $currentTime * * @return InvoiceInterface */ public function setCurrentTime($currentTime) { if (!empty($currentTime)) { $this->currentTime = $currentTime; } return $this; } /** * @inheritdoc */ public function getOrderId() { return $this->orderId; } /** * @param string $orderId * * @return InvoiceInterface */ public function setOrderId($orderId) { if (!empty($orderId) && ctype_print($orderId)) { $this->orderId = trim($orderId); } return $this; } /** * @inheritdoc */ public function getItemDesc() { return $this->getItem()->getDescription(); } /** * @inheritdoc */ public function getItemCode() { return $this->getItem()->getCode(); } /** * @inheritdoc */ public function isPhysical() { return $this->getItem()->isPhysical(); } /** * @inheritdoc */ public function getBuyerName() { $firstName = $this->getBuyer()->getFirstName(); $lastName = $this->getBuyer()->getLastName(); return trim($firstName.' '.$lastName); } /** * @inheritdoc */ public function getBuyerAddress1() { $address = $this->getBuyer()->getAddress(); return $address[0]; } /** * @inheritdoc */ public function getBuyerAddress2() { $address = $this->getBuyer()->getAddress(); return $address[1]; } /** * @inheritdoc */ public function getBuyerCity() { return $this->getBuyer()->getCity(); } /** * @inheritdoc */ public function getBuyerState() { return $this->getBuyer()->getState(); } /** * @inheritdoc */ public function getBuyerZip() { return $this->getBuyer()->getZip(); } /** * @inheritdoc */ public function getBuyerCountry() { return $this->getBuyer()->getCountry(); } /** * @inheritdoc */ public function getBuyerEmail() { return $this->getBuyer()->getEmail(); } /** * @inheritdoc */ public function getBuyerPhone() { return $this->getBuyer()->getEmail(); } /** * @inheritdoc */ public function getExceptionStatus() { return $this->exceptionStatus; } /** * @param * * @return InvoiceInterface */ public function setExceptionStatus($exceptionStatus) { $this->exceptionStatus = $exceptionStatus; return $this; } /** * @param void * @return */ public function getBtcPaid() { return $this->btcPaid; } /** * @param * @return Invoice */ public function setBtcPaid($btcPaid) { if (isset($btcPaid)) { $this->btcPaid = $btcPaid; } return $this; } /** * @param void * @return Invoice */ public function getRate() { return $this->rate; } /** * @param * @return */ public function setRate($rate) { if (!empty($rate)) { $this->rate = $rate; } return $this; } /** * @return TokenInterface */ public function getToken() { return $this->token; } /** * @param TokenInterface $token * @return InvoiceInterface */ public function setToken(TokenInterface $token) { $this->token = $token; return $this; } } PK\؅ߙ6default/plugins/payment/bitpay/Bitpay/KeyInterface.phpnu[x = (string) $x; $this->y = (string) $y; } /** * @return string */ public function __toString() { if ($this->isInfinity()) { return self::INFINITY; } return sprintf('(%s, %s)', $this->x, $this->y); } /** * @return string */ public function getX() { return $this->x; } /** * @return string */ public function getY() { return $this->y; } /** * @return boolean */ public function isInfinity() { return (self::INFINITY == $this->x || self::INFINITY == $this->y); } /** * @inheritdoc */ public function serialize() { return serialize(array($this->x, $this->y)); } /** * @inheritdoc */ public function unserialize($data) { list( $this->x, $this->y ) = unserialize($data); } } PK\7<5jj0default/plugins/payment/bitpay/Bitpay/SinKey.phpnu[value; } /** * @param PublicKey * @return SinKey */ public function setPublicKey(PublicKey $publicKey) { $this->publicKey = $publicKey; return $this; } /** * Generates a Service Identification Number (SIN), see: * https://en.bitcoin.it/wiki/Identity_protocol_v1 * * @return SinKey */ public function generate() { if (is_null($this->publicKey)) { throw new \Exception('Public Key has not been set'); } $compressedValue = $this->publicKey; if (empty($compressedValue)) { throw new \Exception('The Public Key needs to be generated.'); } $step1 = Util::sha256(Util::binConv($compressedValue), true); $step2 = Util::ripe160($step1); $step3 = sprintf( '%s%s%s', self::SIN_VERSION, self::SIN_TYPE, $step2 ); $step4 = Util::twoSha256(Util::binConv($step3), true); $step5 = substr(bin2hex($step4), 0, 8); $step6 = $step3.$step5; $this->value = Base58::encode($step6); return $this; } /** * Checks to make sure that this SIN is a valid object. * * @return boolean */ public function isValid() { return (!is_null($this->value) && (substr($this->value, 0, 1) == 'T')); } } PK\G ||"default/plugins/payment/alipay.phpnu[addText('partner')->setLabel( "Partner ID\n" . "Composed of 16 digits beginning with 2088" ); $form->addText('private_key', "class='el-wide'")->setLabel("Private Key"); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } function getSupportedCurrencies() { return array( 'GBP', 'HKD', 'USD', 'CHF', 'SGD', 'SEK', 'DKK', 'NOK', 'JPY', 'CAD', 'AUD', 'EUR', 'NZD', 'KRW', 'THB', 'CNY' ); } function signOutgoing(&$a) { ksort($a); $preSign = array(); foreach ($a as $k => $v) { $preSign[] = sprintf('%s=%s', $k, $v); } $a['sign'] = md5(implode('&', $preSign) . $this->getConfig('private_key')); $a['sign_type'] = 'MD5'; } /** * * @param Invoice $invoice * @param type $request * @param Am_Paysystem_Result $result */ function _process($invoice, $request, $result) { $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::TEST_GATEWAY : self::LIVE_GATEWAY); $vars = array( 'service' => 'create_forex_trade', 'partner' => $this->getConfig('partner'), '_input_charset' => 'UTF-8', 'notify_url' => $this->getPluginUrl('ipn'), 'return_url' => $this->getPluginUrl('thanks'), 'subject' => $invoice->getLineDescription(), 'out_trade_no' => $invoice->public_id, 'currency' => $invoice->currency, ); $vars['total_fee'] = $invoice->first_total; $this->signOutgoing($vars); foreach ($vars as $k => $v) $a->{$k} = $v; $result->setAction($a); } function createThanksTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Alipay_Thanks($this, $request, $response, $invokeArgs); } function createTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Alipay_Incoming($this, $request, $response, $invokeArgs); } function allowPartialRefunds() { return true; } function processRefund(\InvoicePayment $payment, \Am_Paysystem_Result $result, $amount) { $vars = array( 'service' => 'forex_refund', 'partner' => $this->getConfig('partner'), '_input_charset' => 'UTF-8', 'out_return_no' => 'RFND-' . $invoice->public_id . '-' . rand(0, 100), 'out_trade_no' => $payment->receipt_id, 'return_amount' => $amount, 'currency' => $invoice->currency, 'gmt_return' => gmdate('YmdHis'), 'reason' => 'refund' ); $this->signOutgoing($vars); $req = new Am_HttpRequest(sprintf("%s?%s", $this->getConfig('testing') ? self::TEST_GATEWAY : self::LIVE_GATEWAY, http_build_query($vars))); $this->logRequest($req); $resp = $req->send(); $this->logResponse($resp); if ($resp->getStatus() !== '200') throw new Am_Exception_InternalError('Unable to contact Alipay API server'); $xml = $resp->getBody(); $xml = @simplexml_load_string($resp); if (!$xml) throw new Am_Exception_InternalError('Wrong response received!'); $result->setSuccess(); } function getReadme() { return <<Sandbox testing Merchant account on Sandbox: PID:2088101122136241 Email Account: overseas_kgtest@163.com MD5 KEY MD5:760bdzec6y9goq7ctyx96ezkz78287de Buyer Accounts: 1) douyufua@alitest.com 2) alipaytest20091@gmail.com Captcha Code: 8888 Login Password: 111111 Payment Password on Payment Page: 111111 CUT; } } class Am_Paysystem_Transaction_Alipay extends Am_Paysystem_Transaction_Incoming { function findInvoiceId() { return $this->request->get('out_trade_no'); } public function getUniqId() { return $this->request->get('trade_no'); } public function validateSource() { $vars = $this->request->getRequestOnlyParams(); $sign = $vars['sign']; unset($vars['sign']); unset($vars['sign_type']); $this->plugin->signOutgoing($vars); return ($vars['sign'] == $sign); } public function validateStatus() { return ($this->request->get('trade_status') == 'TRADE_FINISHED'); } public function validateTerms() { return ($this->request->get('total_fee') == $this->invoice->first_total); } } class Am_Paysystem_Transaction_Alipay_Incoming extends Am_Paysystem_Transaction_Alipay { function processValidated() { parent::processValidated(); print "Success"; } } class Am_Paysystem_Transaction_Alipay_Thanks extends Am_Paysystem_Transaction_Alipay { function process() { try { parent::process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { // do nothing if transaction is already handled } if (Am_Di::getInstance()->config->get('auto_login_after_signup')) Am_Di::getInstance()->auth->setUser($this->invoice->getUser(), $this->request->getClientIp()); } } PK\֣޹!default/plugins/payment/cashu.phpnu[addText('merchant_id')->setLabel('Merchant Id'); $form->addText('secret')->setLabel('Secret'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } public function getSupportedCurrencies() { return array('AED', 'GBP', 'EUR', 'USD'); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Cachu($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOTHING; } public function isConfigured() { return $this->getConfig('secret') && $this->getConfig('merchant_id'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $action = new Am_Paysystem_Action_Form; $action->setUrl('https://www.cashu.com/cgi-bin/pcashu.cgi'); $action->merchant_id = $this->getConfig('merchant_id'); $action->amount = $invoice->first_total; $action->currency = $invoice->currency; $action->language = 'en'; $action->display_text = $invoice->getLineDescription(); $action->token = md5(strtolower( $action->merchant_id . ":" . sprintf("%.2f",$action->amount) . ":" . $action->currency . ":" ). $this->getConfig('secret')); $action->txt1 = $invoice->getLineDescription(); $action->txt2 = $invoice->public_id; $action->test_mode = $this->getConfig('testing'); $result->setAction($action); } public function getReadme() { $rootUrl = ROOT_URL; return <<Setup->Plugins 2. Configure "CashU" payment plugin at aMember CP->Setup->CashU Set EXACTLY the same Encryption Keyword in aMember CP setup and CashU Merchants CP. 3. Inside the CashU merchant account using the tab "Encryption Information" set "Return URL" to $rootUrl/payment/cashu/thanks 4. Try your integration - go to aMember signup page, and try to make new signup. $rootUrl/signup CUT; } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Cashu($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_Cashu extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { $this->request->get('trn_id'); } public function findInvoiceId() { return $this->request->getFiltered('txt2'); } public function validateSource() { $token = $this->request->getFiltered('token'); if (!strlen($token)) throw new Am_Exception_InputError("This page must be open by payment system, and not just open in browser window"); $ourToken = md5(strtolower(implode(':', array( $this->plugin->getConfig('merchant_id'), $this->request->get('amount'), $this->request->get('currency'), ))) . ':' . $this->plugin->getConfig('secret') ); if ($token != $ourToken) { throw new Am_Exception_Paysystem_TransactionSource("Tokens do not match: [$token] != [$ourToken]"); } $verify = $this->request->getFiltered('verificationString'); $ourVerify = sha1(strtolower( $this->plugin->getConfig('merchant_id').':'. $this->request->get('trn_id').':' ) . $this->plugin->getConfig('secret')); if ($verify != $ourVerify) { throw new Am_Exception_Paysystem_TransactionSource("Verify string do not match: [$verify] != [$ourVerify]"); } return true; } public function validateStatus() { return true; } public function validateTerms() { return true; // terms are signed in the form, no need to validate again } } PK\X̲$default/plugins/payment/certopay.phpnu[addText('shop_id')->setLabel('Merchant Shop Id'); $form->addText('secret_key')->setLabel('Secret Key'); } public function init() { parent::init(); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $periods = array('y'=>'years','m'=>'months','d'=>'days','fixed' => 'years'); $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Form(self::LIVE_URL); $a->language = $this->getDi()->app->getDefaultLocale(); $order = array(); $a->__set('order[shop_id]',$this->getConfig('shop_id')); $a->__set('order[currency]',$invoice->currency); $a->__set('order[email]',$u->email); $a->__set('order[success_url]',$this->getReturnUrl($request)); $a->__set('order[cancel_url]',$this->getCancelUrl($request)); $a->__set('order[fail_url]',$this->getCancelUrl($request)); $a->__set('order[notification_url]',$this->getPluginUrl('ipn')); $a->__set('order[billing_address_attributes][first_name]',$u->name_f); $a->__set('order[billing_address_attributes][last_name]',$u->name_l); $a->__set('order[billing_address_attributes][address]',$u->street); $a->__set('order[billing_address_attributes][country]',$u->country); $a->__set('order[billing_address_attributes][city]',$u->city); $a->__set('order[billing_address_attributes][zip]',$u->zip); $a->__set('order[billing_address_attributes][state]',$u->state); $a->__set('order[billing_address_attributes][zip]',$u->zip); //recurring if(!is_null($invoice->second_period)){ $a->__set('order[subscription_attributes][description]',$invoice->getLineDescription()); $a->__set('order[subscription_attributes][trial_amount]',$invoice->first_total*100); $first_period = new Am_Period($invoice->first_period); $a->__set('order[subscription_attributes][trial_interval_unit]',$periods[$first_period->getUnit()]); $a->__set('order[subscription_attributes][trial_interval]',($first_period->getCount() == Am_Period::MAX_SQL_DATE) ? '25' : $first_period->getCount()); $a->__set('order[subscription_attributes][amount]',$invoice->second_total*100); $second_period = new Am_Period($invoice->second_period); $a->__set('order[subscription_attributes][interval_unit]',$periods[$second_period->getUnit()]); $a->__set('order[subscription_attributes][interval]',($second_period->getCount() == Am_Period::MAX_SQL_DATE) ? '25' : $second_period->getCount()); if($invoice->rebill_times) $a->__set('order[subscription_attributes][rebill_limit]',$invoice->rebill_times); } //not recurring else{ $a->__set('order[line_items_attributes][][name]',$invoice->getLineDescription()); $a->__set('order[line_items_attributes][][amount]',$invoice->first_total*100); $a->__set('order[line_items_attributes][][quantity]',1); $a->__set('order[tax_amount]',$invoice->first_tax*100); } $a->__set('order[tracking_params_attributes][][name]','invoice_id'); $a->__set('order[tracking_params_attributes][][value]',$invoice->public_id); $a->filterEmpty(); $a->__set('order[signature]', hash('sha256',($sha = $a->__get('order[subscription_attributes][trial_amount]'). $a->__get('order[line_items_attributes][][amount]'). $a->__get('order[cancel_url]'). $a->__get('order[currency]'). $a->__get('order[email]'). $a->__get('order[fail_url]'). $a->__get('order[success_url]'). $invoice->public_id. $a->__get('order[subscription_attributes][amount]'). $a->__get('order[subscription_attributes][description]'). $a->__get('order[subscription_attributes][interval]'). $a->__get('order[subscription_attributes][interval_unit]'). $a->__get('order[subscription_attributes][rebill_limit]'). $a->__get('order[subscription_attributes][trial_amount]'). $a->__get('order[subscription_attributes][trial_interval]'). $a->__get('order[subscription_attributes][trial_interval_unit]'). $this->getConfig('secret_key')))); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Certopay($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { return <<Certopay plugin installation 1. Configure plugin at aMember CP -> Setup/Configuration -> Certopay 2. Run a test transaction to ensure everything is working correctly. CUT; } } class Am_Paysystem_Transaction_Certopay extends Am_Paysystem_Transaction_Incoming{ protected $tracking_params,$billing_address,$subscription,$map; public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $this->tracking_params = $request->get("tracking_params"); $this->billing_address = $request->get("billing_address"); $this->subscription = $request->get("subscription"); parent::__construct($plugin, $request, $response, $invokeArgs); } public function getUniqId() { return $this->request->get("id"); } public function findInvoiceId() { return $this->tracking_params[1]['value']; } protected function _map($a) { foreach($a as $k => $v) if(is_array($v)) $this->_map($v); else $this->map[] = "$k$v"; } public function validateSource() { $this->_map($this->request->getPost()); sort($this->map); $sha = ''; foreach($this->map as $k) if(!preg_match('/^signature_v2/', $k)) $sha.=$k; $sha.=$this->getPlugin()->getConfig('secret_key'); $hash = hash('sha256',($sha)); if($hash != $this->request->get('signature_v2')) throw new Am_Exception_Paysystem_TransactionSource('Received security hash is not correct'); return true; } public function validateStatus() { if($this->request->get('status') != 'paid'){ return false; } return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); } }PK\[*default/plugins/payment/premiumwebcart.phpnu[addText('merchant_id') ->setLabel("Merchant ID\n" . 'Your PremiumWebCart Merchant ID'); $form->addText('api_signature', array('class' => 'el-wide')) ->setLabel("API Sinature\n" . 'You can get it from Home >> Cart Settings >> Advance Integration >> API Integration'); } public function init() { parent::init(); $this->getDi()->billingPlanTable->customFields() ->add(new Am_CustomFieldText('premiumwebcart_id', "Premium Web Cart Product Link ID", "This is the Product Link ID which is available in the Edit Product Screen.")); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_Redirect(self::URL); $a->con = 'my_cart'; $a->met = 'addToCart'; $a->pid = $invoice->getItem(0)->getBillingPlanData('premiumwebcart_id'); $a->pquantity = 1; $a->clearcart = 1; $a->action = 2; $a->fname = $invoice->getFirstName(); $a->lname = $invoice->getLastName(); $a->email = $invoice->getEmail(); $a->baddress1 = $invoice->getStreet(); $a->bcity = $invoice->getCity(); $a->bzip = $invoice->getZip(); $a->bstate = $invoice->getState(); $a->bcountry = $invoice->getCountry(); $a->custom1 = $invoice->public_id; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Premiumwebcart($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function apiRequest($method, $vars) { $req = new Am_HttpRequest(self::API_URL."/".$method.".html", Am_HttpRequest::METHOD_POST); $req->addPostParameter('merchantid', $this->getConfig('merchant_id')); $req->addPostParameter('signature', $this->getConfig('api_signature')); foreach($vars as $k=>$v){ $req->addPostParameter($k, $v); } $req->send(); $resp = $req->getBody(); if(!$resp) throw new Am_Exception_InputError('PWC: got empty response from API server'); $xml = simplexml_load_string($resp); if($xml->error) throw new Am_Exception_InputError('PWC: Got error from API: '.$xml->error->errortext); return $xml; } public function cancelAction(Invoice $invoice, $actionName, Am_Paysystem_Result $result) { $id = $invoice->data()->get(self::PROFILE_ID); if (!$id) throw new Am_Exception_InputError("No external id recorded for invoice [".$invoice->public_id."]"); $resp = $this->apiRequest('suspendSubscription', array('profileid'=>$id)); if($resp->recurring->status == 'suspended') echo "Order Cancelled"; else throw new Am_Exception_InputError("PWC: Unknown response from API"); } public function getReadme() { $thanks = $this->getDi()->url('thanks'); $ipn = Am_Html::escape($this->getPluginUrl('ipn')); return <<PremiumWebCart payment plugin configuration 1. Configure "premiumwebcart" payment plugin at aMember CP -> Setup/Configuration -> PremiumWebCart Make sure you set the same API Key in aMember CP and PWC Home >> Cart Settings >> Advance Integration >> API Integration 2. Create equivalents for all aMember products in PWC . Make sure it has the same subscription terms (period, price) as aMember Products. Set "Thanks URL" for all PWC products to $thanks Write down Product Link ID of all PWC products. 3. Visit aMember CP -> Manage Products, click "Edit" on each product and enter "PremiumWebCart Product Link ID" for each corresponding billing plan, then click "Save". 4. Set Premium Web Cart Instant Payment Notification URL to $ipn at Home >> Cart Settings >> Advance Integration >> PWC IPN 5. Try your integration - go to aMember signup page, and try to make new signup. CUT; } } class Am_Paysystem_Transaction_Premiumwebcart extends Am_Paysystem_Transaction_Incoming { const STATUS_SUCCESS ='success'; public function getUniqId() { return $this->request->get("order_unique_id"); } public function findInvoiceId() { return $this->request->get('custom1'); } public function validateSource() { $this->_checkIp('72.32.221.227'); return true; } public function validateStatus() { return ($this->request->get('txn_status') == self::STATUS_SUCCESS); } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); if($profile_id = $this->request->get('profile_id')) $this->invoice->data()->set(Am_Paysystem_PremiumWebCart::PROFILE_ID, $profile_id)->update(); } }PK\m@default/plugins/payment/quaderno-checkout/scripts/quaderno.phtmlnu[headMeta()->setName('robots', 'noindex,nofollow'); ?> setLayout('layout.phtml'); $this->layoutNoMenu = true; ?> _script('_receipt.phtml'); ?>
        PK\?default/plugins/payment/quaderno-checkout/quaderno-checkout.phpnu[ 'SHA256', 'HS512' => 'SHA512', 'HS384' => 'SHA384', ); public function init() { $this->getDi()->billingPlanTable->customFields()->add(new Am_CustomFieldText('stripe_plan', 'Stripe Billing Plan Id')); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getSupportedCurrencies() { return array('USD', 'CAD', 'GBP', 'EUR', 'CHF', 'AUD'); } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("public_key", array('class' => 'el-wide')) ->setLabel('Publishable key'); $form->addText("private_key", array('class' => 'el-wide')) ->setLabel('Private key'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $a = new Am_Paysystem_Action_HtmlTemplate_QuadernoCheckout(dirname(__FILE__), 'quaderno.phtml'); $a->plugin = $this; $a->invoice = $invoice; if (!(float)$invoice->second_total) { $a->charge = array( 'amount' => $invoice->first_total * 100, 'currency' => $invoice->currency, 'description' => $invoice->getLineDescription() ); $a->charge['charge'] = $this->jwtEncode($a->charge + array( 'iat' => $this->getDi()->time ), $this->getConfig('private_key')); $a->charge['type'] = 'charge'; $a->label = ___('Pay with Card'); } else { $a->charge = array( 'plan' => $invoice->getItem(0)->getBillingPlanData('stripe_plan'), 'amount' => $invoice->second_total * 100, 'description' => $invoice->getLineDescription() ); $a->label = ___('Subscribe Now'); } $result->setAction($a); } static function base64url_encode($data) { return str_replace('=', '', strtr(base64_encode($data), '+/', '-_')); } static function base64url_decode($data) { $remainder = strlen($data) % 4; if ($remainder) { $padlen = 4 - $remainder; $data .= str_repeat('=', $padlen); } return base64_decode(strtr($data, '-_', '+/')); } public function jwtEncode($payload, $key) { $alg = 'HS256'; $header = json_encode(array( 'alg' => $alg, 'typ' => "JWT" )); $payload = json_encode($payload); $sign = hash_hmac($this->algs_map[$alg], self::base64url_encode($header) . '.' . self::base64url_encode($payload), $key, true); return self::base64url_encode($header) . '.' . self::base64url_encode($payload) . '.' . self::base64url_encode($sign); } public function jwtDecode($jwt, $key) { list($header, $payload, $sign) = explode('.', $jwt); $_header = self::base64url_decode($header); $_payload = self::base64url_decode($payload); $_sign = self::base64url_decode($sign); $_header = json_decode($_header, true); if (hash_hmac($this->algs_map[$_header['alg']], $header . '.' . $payload, $key, true) != $_sign) return false; return json_decode($_payload, true); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_QuadernoCheckout($this, $request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_QuadernoCheckout_Ipn($this, $request, $response, $invokeArgs); } } class Am_Paysystem_Transaction_QuadernoCheckout_Ipn extends Am_Paysystem_Transaction_Incoming { public function validateSource() { return true; } public function validateTerms() { return true; } public function validateStatus() { return true; } public function getUniqId() { return true; } public function findInvoiceId() { return null; } public function processValidated() { switch ($this->type) { case 'rs' : break; } } } class Am_Paysystem_Transaction_QuadernoCheckout extends Am_Paysystem_Transaction_Incoming_Thanks { public function process() { $this->transactionDetails = $this->plugin->jwtDecode($this->request->getParam('transactionDetails'), $this->plugin->getConfig('private_key')); $this->log->add($this->transactionDetails); return parent::process(); } public function validateSource() { return (bool)$this->transactionDetails; } public function validateTerms() { return true; } public function validateStatus() { return true; } public function getUniqId() { return $this->transactionDetails['transaction']; } public function findInvoiceId() { return $this->request->get('id'); } } class Am_Paysystem_Action_HtmlTemplate_QuadernoCheckout extends Am_Paysystem_Action_HtmlTemplate { protected $_template; protected $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->view->assign($this->getVars()); $action->renderScript($this->_template); throw new Am_Exception_Redirect; } }PK\e@@!default/plugins/payment/e-ghl.phpnu[addText('ServiceID')->setLabel("Merchant Service ID\ngiven by eGHL"); $form->addPassword('password')->setLabel('Merchant Password'); $form->addAdvCheckbox('testing') ->setLabel("Is it a Sandbox (Testing) Account?"); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $user = $invoice->getUser(); $a = new Am_Paysystem_Action_Redirect($this->host()); $vars = array( 'TransactionType' => 'SALE', 'ServiceID' => $this->getConfig('ServiceID'), 'PaymentID' => $invoice->public_id, 'OrderNumber' => $invoice->public_id, 'PaymentDesc' => $invoice->getLineDescription(), 'MerchantReturnURL' => $this->getPluginUrl('thanks'), 'Amount' => $invoice->first_total, 'CurrencyCode' => $invoice->currency, 'CustIP' => $request->getClientIp(), 'CustName' => $user->getName(), 'CustEmail' => $user->email, 'CustPhone' => $user->phone, 'MerchantName' => $this->getDi()->config->get('site_title'), 'PageTimeout' => '3600' ); $a->HashValue = hash('sha256', $this->getConfig('password') . $vars['ServiceID'] . $vars['PaymentID'] . $vars['MerchantReturnURL'] . $vars['Amount'] . $vars['CurrencyCode'] . $vars['CustIP'] . $vars['PageTimeout']); foreach ($vars as $k => $v) { $a->$k = $v; } $result->setAction($a); } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_EGhl($this, $request, $response, $invokeArgs); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return null; } function host() { return $this->getConfig('testing') ? self::SANDBOX_URL : self::LIVE_URL; } public function getReadme() { return <<Phone and Name bricks to your signup form. eGHL requires customer phone number and name to process payment. CUT; } } class Am_Paysystem_Transaction_EGhl extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { return $this->request->getParam('TxnID'); } public function findInvoiceId() { return $this->request->getParam('OrderNumber'); } public function validateSource() { $msg = $this->plugin->getConfig('password'); foreach (array('TxnID', 'ServiceID', 'PaymentID', 'TxnStatus', 'Amount', 'CurrencyCode', 'AuthCode') as $key) { $msg .= $this->request->getParam($key); } $digest = hash('sha256', $msg); return $digest == $this->request->getParam('HashValue'); } public function validateStatus() { return $this->request->getParam('TxnStatus') == '0'; } public function validateTerms() { return $this->request->getParam('Amount') == $this->invoice->first_total && $this->request->getParam('CurrencyCode') == $this->invoice->currency; } }PK\tض+default/plugins/payment/officeautopilot.phpnu[paysystemList->getList() as $k => $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->billingPlanTable->customFields()->add( new Am_CustomFieldText( 'oap_prod_item', "OAP product ID", "" , array(/* ,'required' */) )); } function getConfig($key = null, $default = null) { switch ($key) { case 'testing' : return false; case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function _initSetupForm(Am_Form_Setup $form) { } public function getRecurringType() { return self::REPORTS_REBILL; } public function isNotAcceptableForInvoice(Invoice $invoice) { return; } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { // Nothing to do. } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Officeautopilot($this, $request, $response, $invokeArgs); } public function canAutoCreate() { return true; } public function getReadme() { $url = $this->getPluginUrl('ipn'); return <<Office Auto Pilot integration Ping URL for your OAP account be set to: $url CUT; } } class Am_Paysystem_Transaction_Officeautopilot extends Am_Paysystem_Transaction_Incoming { protected $_autoCreateMap = array( 'name_f' => 'firstname', 'name_l' => 'lastname', 'email' => 'email', 'user_external_id' => 'email', ); public function generateInvoiceExternalId() { return $this->request->get('product_ID') . '_' . $this->request->get('email'); } public function autoCreateGetProducts() { $item_name = $this->request->get('product_ID'); if (empty($item_name)) return; $billing_plan = $this->getPlugin()->getDi()->billingPlanTable->findFirstByData('oap_prod_item', $item_name); if ($billing_plan) return array($billing_plan->getProduct()); } public function getReceiptId() { return $this->request->get('transaction_id'); } public function getAmount() { return moneyRound($this->request->get('total_invoice_amount')); } public function getUniqId() { return @$this->request->get('transaction_id'); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { $this->invoice->addPayment($this); if ($pass = $this->request->get('password')) { $user = $this->invoice->getUser(); $user->setPass($pass); $user->update(); } } public function findInvoiceId() { return $this->request->get('transaction_id'); } }PK\j'j'(default/plugins/payment/sagepay-form.phpnu[addText('login')->setLabel('Your SagePay login'); $form->addPassword('pass')->setLabel('Your SagePay password'); $form->addAdvCheckbox('testing')->setLabel("Test Mode Enabled"); } public function getSupportedCurrencies() { return array('AUD', 'CAD', 'CHF', 'DKK', 'EUR', 'GBP', 'HKD', 'IDR', 'JPY', 'LUF', 'NOK', 'NZD', 'SEK', 'SGD', 'TRL', 'USD'); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $u = $invoice->getUser(); $a = new Am_Paysystem_Action_Form($this->getConfig('testing') ? self::TEST_URL : self::LIVE_URL); $a->VPSProtocol = '3.00'; $a->TxType = 'PAYMENT'; $a->Vendor = $this->getConfig('login'); $vars = array( 'VendorTxCode='.$invoice->public_id, 'Amount='.$invoice->first_total, 'Currency='.$invoice->currency, 'Description='.$invoice->getLineDescription(), 'SuccessURL='.$this->getPluginUrl('thanks'), 'FailureURL='.$this->getCancelUrl(), 'CustomerEmail='.$u->email, 'VendorEmail='.$this->getDi()->config->get('admin_email'), 'CustomerName='.$u->name_f . ' ' . $u->name_l, ); // New mandatory fields for 3.00 protocol // All mandatory fields must contain a value, apart from the BillingPostcode/DeliveryPostCode. $surname = ($u->name_l != '') ? $u->name_l : 'Surname'; $firstname = ($u->name_f != '') ? $u->name_f : 'Firstname'; $address = ($u->street != '') ? $u->street : 'Address'; $city = ($u->city != '') ? $u->city : 'City'; $country = ($u->country != '') ? $u->country : 'US'; $state = ($u->state != '') ? $u->state : 'AL'; $zip = ($u->zip != '') ? $u->zip : '12345'; $vars[] = 'BillingSurname='.$surname; $vars[] = 'BillingFirstnames='.$firstname; $vars[] = 'BillingAddress1='.$address; $vars[] = 'BillingCity='.$city; $vars[] = 'BillingPostCode='.$zip; $vars[] = 'BillingCountry='.$country; $vars[] = 'DeliverySurname='.$surname; $vars[] = 'DeliveryFirstnames='.$firstname; $vars[] = 'DeliveryAddress1='.$address; $vars[] = 'DeliveryCity='.$city; $vars[] = 'DeliveryPostCode='.$zip; $vars[] = 'DeliveryCountry='.$country; if ($country == 'US') { //becomes mandatory when the BillingCountry/DeliveryCountry is set to US $vars[] = 'BillingState='.$state; $vars[] = 'DeliveryState='.$state; } /* * Important – if your business is classed as Financial Institution (Merchant code – 6012) * there are 4 additional fields that will need to be included with the transaction post from your system. * FIRecipientAcctNumber * FIRecipientSurname * FIRecipientPostcode * FIRecipientDoB */ //$a->Crypt = base64_encode($this->sagepay_simple_xor(implode('&',$vars), $this->getConfig('pass'))); $a->Crypt = self::encryptAes(implode('&',$vars), $this->getConfig('pass')); $a->filterEmpty(); $result->setAction($a); } // public function sagepay_simple_xor($InString, $Key) { // // Initialise key array // $KeyList = array(); // // Initialise out variable // $output = ""; // // // Convert $Key into array of ASCII values // for($i = 0; $i < strlen($Key); $i++){ // $KeyList[$i] = ord(substr($Key, $i, 1)); // } // // // Step through string a character at a time // for($i = 0; $i < strlen($InString); $i++) { // // Get ASCII code from string, get ASCII code from key (loop through with MOD), XOR the two, get the character from the result // // % is MOD (modulus), ^ is XOR // $output.= chr(ord(substr($InString, $i, 1)) ^ ($KeyList[$i % strlen($Key)])); // } // // Return the result // return $output; // } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function createThanksTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_SagePayForm_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } /** * PHP's mcrypt does not have built in PKCS5 Padding, so we use this. * * @param string $input The input string. * * @return string The string with padding. */ static protected function addPKCS5Padding($input) { $blockSize = 16; $padd = ""; // Pad input to an even block size boundary. $length = $blockSize - (strlen($input) % $blockSize); for ($i = 1; $i <= $length; $i++) { $padd .= chr($length); } return $input . $padd; } /** * Remove PKCS5 Padding from a string. * * @param string $input The decrypted string. * * @return string String without the padding. * @throws Am_Exception_Paysystem */ static protected function removePKCS5Padding($input) { $blockSize = 16; $padChar = ord($input[strlen($input) - 1]); /* Check for PadChar is less then Block size */ if ($padChar > $blockSize) { throw new Am_Exception_Paysystem('Invalid encryption string'); } /* Check by padding by character mask */ if (strspn($input, chr($padChar), strlen($input) - $padChar) != $padChar) { throw new Am_Exception_Paysystem('Invalid encryption string'); } $unpadded = substr($input, 0, (-1) * $padChar); /* Chech result for printable characters */ if (preg_match('/[[:^print:]]/', $unpadded)) { throw new Am_Exception_Paysystem('Invalid encryption string'); } return $unpadded; } /** * Encrypt a string ready to send to SagePay using encryption key. * * @param string $string The unencrypyted string. * @param string $key The encryption key. * * @return string The encrypted string. */ static public function encryptAes($string, $key) { // AES encryption, CBC blocking with PKCS5 padding then HEX encoding. // Add PKCS5 padding to the text to be encypted. $string = self::addPKCS5Padding($string); // Perform encryption with PHP's MCRYPT module. $crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key); // Perform hex encoding and return. return "@" . strtoupper(bin2hex($crypt)); } /** * Decode a returned string from SagePay. * * @param string $strIn The encrypted String. * @param string $password The encyption password used to encrypt the string. * * @return string The unecrypted string. * @throws Am_Exception_Paysystem */ static public function decryptAes($strIn, $password) { // HEX decoding then AES decryption, CBC blocking with PKCS5 padding. // Use initialization vector (IV) set from $str_encryption_password. $strInitVector = $password; // Remove the first char which is @ to flag this is AES encrypted and HEX decoding. $hex = substr($strIn, 1); // Throw exception if string is malformed if (!preg_match('/^[0-9a-fA-F]+$/', $hex)) { throw new Am_Exception_Paysystem('Invalid encryption string'); } $strIn = pack('H*', $hex); // Perform decryption with PHP's MCRYPT module. $string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, $strIn, MCRYPT_MODE_CBC, $strInitVector); return self::removePKCS5Padding($string); } } class Am_Paysystem_Transaction_SagePayForm_Thanks extends Am_Paysystem_Transaction_Incoming { public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); // $s = base64_decode(str_replace(" ", "+", $request->get("Crypt",$request->get("crypt")))); // $s = $plugin->sagepay_simple_xor($s, $plugin->getConfig('pass')); $s = Am_Paysystem_SagepayForm::decryptAes($request->get("Crypt", $request->get("crypt")), $plugin->getConfig('pass')); parse_str($s, $this->vars); } public function getAmount() { return moneyRound($this->vars['Amount']); } public function getUniqId() { return $this->vars["VPSTxId"]; } public function findInvoiceId() { return $this->vars["VendorTxCode"]; } public function validateSource() { return true; } public function validateStatus() { return $this->vars['Status'] == 'OK'; } public function validateTerms() { return true; } function getInvoice() { return $this->loadInvoice($this->findInvoiceId()); } }PK\qRI55!default/plugins/payment/ogone.phpnu[addText('merchant_id', array('size' => 20))->setLabel('Your Merchant ID'); $form->addSelect('hashing_method')->setLabel('Hashing Method') ->loadOptions(array(0 => 'Main parameters only', 1 => 'Each parameter followed by the pass phrase')); $form->addText('secret', array('class' => 'el-wide'))->setLabel('SHA-IN Signature'); $form->addText('secret_ipn', array('class' => 'el-wide'))->setLabel('SHA-OUT Signature'); $form->addText('alias_usage', array('class' => 'el-wide'))->setLabel("Alias usage\n" . 'required for recurring only'); $form->addAdvcheckbox('testing')->setLabel('Testing mode'); } public function isConfigured() { return strlen($this->getConfig('merchant_id')) && strlen($this->getConfig('secret')); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { if($this->getConfig('hashing_method')) $utf='_utf8'; $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::SANDBOX_URL . @$utf . '.asp' : self::LIVE_URL . @$utf . '.asp'); $sha_id = $this->getConfig('secret'); $u = $invoice->getUser(); $vars = array( 'PSPID' => $this->getConfig('merchant_id'), 'AMOUNT' => $invoice->first_total * 100, 'CURRENCY' => $invoice->currency, 'LANGUAGE' => 'en_US', 'TITLE' => $invoice->getLineDescription(), 'ACCEPTURL' => $this->getReturnUrl(), 'DECLINEURL' => $this->getCancelUrl(), 'EXCEPTIONURL' => $this->getCancelUrl(), 'CANCELURL' => $this->getCancelUrl(), 'ORDERID' => $invoice->public_id, 'CN' => $u->getName(), 'OWNERADDRESS' => $u->street, 'OWNERCITY' => $u->city, 'OWNERZIP' => $u->zip, 'EMAIL' => $u->email, 'OPERATION' => "SAL", ); if($invoice->rebill_times) { $vars = array_merge($vars, array( 'ALIAS' => $this->getDi()->security->siteHash($invoice->public_id.$invoice->user_id), 'ALIASUSAGE' => $this->getConfig('alias_usage'), 'SUBSCRIPTION_ID' => $invoice->public_id, 'SUB_AMOUNT' => $invoice->second_total * 100, 'SUB_COM' => $invoice->getLineDescription(), 'SUB_ORDERID' => $invoice->public_id, 'SUB_STATUS' => 1, )); $period = new Am_Period($invoice->second_period); switch($period->getUnit()){ case Am_Period::DAY: $vars['SUB_PERIOD_UNIT'] = 'd'; break; case Am_Period::MONTH: $vars['SUB_PERIOD_UNIT'] = 'm'; break; case Am_Period::YEAR: $vars['SUB_PERIOD_UNIT'] = 'm'; break; } if($period->getUnit() == Am_Period::YEAR) $qty = 12; else $qty = 1; $vars['SUB_PERIOD_NUMBER'] = $qty * $period->getCount(); $start_date = $invoice->calculateRebillDate(1); if($period->getUnit() != Am_Period::DAY) { strtotime($vars); switch($period->getUnit()){ case Am_Period::MONTH: case Am_Period::YEAR: $vars['SUB_PERIOD_MOMENT'] = date('j',strtotime($start_date)); } } $vars['SUB_STARTDATE'] = $start_date; if($invoice->rebill_times != Product::RECURRING_REBILLS) $vars['SUB_ENDDATE'] = $invoice->calculateRebillDate($invoice->rebill_times); } $vars = array_filter($vars); ksort($vars); $tosha = ''; if($this->getConfig('hashing_method')) array_walk($vars, function(&$a, $b) use (&$tosha, $sha_id) {$tosha.=$b.'='.$a.$sha_id;}); else $tosha = $invoice->getLineDescription() . ($invoice->first_total * 100) . $invoice->currency . $this->getConfig('merchant_id') . 'SAL' . $sha_id; foreach($vars as $k => $v) $a->addParam ($k, $v); $a->SHASIGN = strtoupper(sha1($tosha)); $result->setAction($a); } public function isNotAcceptableForInvoice(Invoice $invoice) { if ($invoice->rebill_times) { if ($invoice->second_period == Am_Period::MAX_SQL_DATE) return ___('Can not handle this billing terms'); } return parent::isNotAcceptableForInvoice($invoice); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Ogone($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_REBILL; } public function getReadme() { $url = Am_Html::escape($this->getPluginUrl('ipn')); return << Technical information, set: 1. PostBack URL to $url 2. Make this request in background and differed. CUT; } } class Am_Paysystem_Transaction_Ogone extends Am_Paysystem_Transaction_Incoming { protected $vars; public function __construct($plugin, $request, $response, $invokeArgs) { parent::__construct($plugin, $request, $response, $invokeArgs); $this->vars = array(); foreach($this->request->getParams() as $k => $v) { if(preg_match('/(^plugin_id$)|(^action$)|(^module$)|(^controller$)|(^type$)/', $k)) { continue; } $this->vars[strtoupper($k)] = $v; } } public function getUniqId() { return $this->vars['PAYID']; } public function validateSource() { $vars = $this->vars; $hash = $vars['SHASIGN']; unset($vars['SHASIGN']); ksort($vars); $tosha = ''; $sha_id = $this->getPlugin()->getConfig('secret_ipn'); array_walk($vars, function(&$a, $b) use (&$tosha, $sha_id) {$tosha.=$b.'='.$a.$sha_id;}); return $hash == strtoupper(sha1($tosha)); } public function getAmount() { return $this->vars['AMOUNT']; } public function validateStatus() { return $this->vars['NCERROR'] == 0; } public function validateTerms() { $isFirst = $this->invoice->first_total && !$this->invoice->getPaymentsCount(); $expected = $isFirst ? $this->invoice->first_total : $this->invoice->second_total; return $expected <= $this->getAmount(); } public function findInvoiceId() { return $this->vars['ORDERID']; } public function processValidated() { switch ($this->vars['STATUS']) { case 5: case 9: $this->invoice->addPayment($this); break; case 7: case 8: $this->invoice->addRefund($this, $this->request->get('PAYID'), $this->getAmount()); break; } } }PK\<hAA2default/plugins/payment/paysafecard/Validators.phpnu[client = new SoapClient($endPoint); } catch (Exception $e) { throw new Exception('Error creating SoapClient: ' . $e->getMessage()); } } /** * Calls the CreateDisposition web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param amount * Amount to use for the web service call. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @param okUrl * OKUrl to use for the web service call. * @param nokUrl * NOKurl to use for the web service call. * @param merchantClientId * ID of the client to use for the web service call. This is * merchant's internal id to identify the client. The parameter is * optional and can be null. * @param pnUrl * Payment notification URL to use for the web service call. The * parameter is optional and can be null. * @param clientIp * IP address of the client to use for the web service call. This is * the IP of the client when connecting to the merchant. The * parameter is optional and can be null. * @return Response of the CreateDisposition web service call. The call was * successful if resultCode and errorCode of the response are 0. For * list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function createDisposition($username, $password, $mtid, $subId, $amount, $currency, $okUrl, $nokUrl, $merchantClientId, $pnUrl, $clientIp) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateStringNotNull($okUrl, 'okUrl'); Validators::validateStringNotNull($nokUrl, 'nokUrl'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subId'=>$subId, 'amount'=>$amount, 'currency'=>strtoupper($currency), 'okUrl'=>$okUrl, 'nokUrl'=>$nokUrl, 'merchantclientid'=>$merchantClientId, 'pnUrl'=>$pnUrl, 'clientIp'=>$clientIp); $response = $this->client->createDisposition($params); return $response->createDispositionReturn; } /** * Calls the AssignCardToDisposition web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param amount * Amount to use for the web service call. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @param pin * PIN number to use for the web service call. * @return Response of the AssignCardToDisposition web service call. The call * was successful if resultCode and errorCode of the response are 0. * For list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function assignCardToDisposition($username, $password, $mtid, $subId, $amount, $currency, $pin) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateStringNotNull($pin, 'pin'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subId'=>$subId, 'amount'=>$amount, 'currency'=>strtoupper($currency), 'pin'=>$pin); $response = $this->client->assignCardToDisposition($params); return $response->assignCardToDispositionReturn; } /** Calls the AssignCardsToDisposition web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param amount * Amount to use for the web service call. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @param cards * Card information (pin, password) to use for the web service call. * At least one (1) card and at most ten (10) cards can be present in * the request. Card passwords are optional and should be * null if no password is specified for the given card. * @param locale * Locale to use for the web service call. The parameter is optional * and can be null. * @param acceptingTerms * Integer value indicating if the user accepts Paysafecard's terms * of use. Value should be 1 if user accepts terms of use. * @return Response of the AssignCardToDisposition web service call. The call * was successful if resultCode and errorCode of the response are 0. * For list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function assignCardsToDisposition($username, $password, $mtid, $subId, $amount, $currency, $locale, $acceptingTerms, $cards) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateCurrency($currency); Validators::validateCards($cards); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subid'=>$subId, 'amount'=>$amount, 'currency'=>strtoupper($currency), 'locale'=>$locale, 'acceptingTerms'=>$acceptingTerms, 'cards'=>$cards); $response = $this->client->assignCardsToDisposition($params); return $response->assignCardsToDispositionReturn; } /** * Calls the ModifyDispositionValue web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param amount * Amount to use for the web service call. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @return Response of the ModifyDispositionValue web service call. The call * was successful if resultCode and errorCode of the response are 0. * For list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function modifyDispositionValue($username, $password, $mtid, $subId, $amount, $currency) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subid'=>$subId, 'amount'=>$amount, 'currency'=>strtoupper($currency)); $response = $this->client->modifyDispositionValue($params); return $response->modifyDispositionValueReturn; } /** * Calls the GetSerialNumbers web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @return Response of the GetSerialNumbers web service call. The call was * successful if resultCode and errorCode of the response are 0. For * list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function getSerialNumbers($username, $password, $mtid, $subId, $currency) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subid'=>$subId, 'currency'=>strtoupper($currency)); $response = $this->client->getSerialNumbers($params); return $response->getSerialNumbersReturn; } /** * Calls GetDispositionRawState web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @return Response of the GetDispositionRawState web service call. The call * was successful if resultCode and errorCode of the response are 0. * For list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function getDispositionRawState($username, $password, $mtid, $subId, $currency) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subid'=>$subId, 'currency'=>strtoupper($currency)); $response = $this->client->getDispositionRawState($params); return $response->getDispositionRawStateReturn; } /** * Calls ExecuteDebit web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param mtid * Merchant transaction id to use for the web service call. It must * be unique for each invocation. * @param subId * SubId to use for the web service call. The parameter is optional * and can be null. * @param amount * Amount to use for the web service call. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @param close * Close flag indicating if further debits will be executed or not. * If the close flag is 1 the disposition will be set to totally * consumed and no further debits are possible. * @param partialDebitId * PartialDebitId to use for the web service call. The parameter is * optional and can be null. * @ return Response of the ExecuteDebit web service call. The call was * successful if resultCode and errorCode of the response are 0. For * list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function executeDebit($username, $password, $mtid, $subId, $amount, $currency, $close, $partialDebitId) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateStringNotNull($mtid, 'mtid'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'mtid'=>$mtid, 'subid'=>$subId, 'amount'=>$amount, 'currency'=>strtoupper($currency), 'close'=>$close, 'partialDebitId'=>$partialDebitId); $response = $this->client->executeDebit($params); return $response->executeDebitReturn; } /** * Calls the GetMid SOPG web service method. * * @param username * Username to use for the web service call. * @param password * Password to use for the web service call. * @param currency * Currency to use for the web service call. It must contain a 3 * letter ISO 4217 currency code. * @return Response containing mid configured for the given currency. The call * was successful if resultCode and errorCode of the response are 0. * For list of possible error codes refer to merchant documentation. * @throws InvalidArgumentException * If required parameters are null or empty. */ public function getMid($username, $password, $currency) { Validators::validateStringNotNull($username, 'username'); Validators::validateStringNotNull($password, 'password'); Validators::validateCurrency($currency); $params = array('username'=>$username, 'password'=>$password, 'currency'=>strtoupper($currency)); $response = $this->client->getMid($params); return $response->getMidReturn; } } PK\NM$-$-3default/plugins/payment/paysafecard/paysafecard.phpnu[addText('login')->setLabel('paysafecard SOPG Login'); $form->addText('password')->setLabel('paysafecard SOPG Password'); $form->addAdvCheckbox('testing')->setLabel('Test Mode'); } function getSupportedCurrencies() { return array('USD', 'EUR', 'RON'); } function generateMtid() { $time = gettimeofday(); $mtid = $time['sec']; $mtid .= $time['usec']; return $mtid; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { if($request->getActionName() == 'cancelpaysafecart'){ // SEE par.3 @list($id, $code) = explode('-', filterId($request->getFiltered('id')), 2); $invoice = Am_Di::getInstance()->InvoiceTable->findFirstByPublicId(filterId($id)); if (!$invoice) throw new Am_Exception_InputError("No invoice found [$id]"); $invoice->setCancelled(true); $a = new Am_Paysystem_Action_HtmlTemplate_Paysafecard($this->getDir(), 'payment-paysafecard-cancel.phtml'); $a->process(new Am_Mvc_Controller($request, $response, $invokeArgs)); // see par.3 } else parent::directAction($request, $response, $invokeArgs); } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { include_once(dirname(__FILE__).'/SOPGClassicMerchantClient.php'); $client = new SOPGClassicMerchantClient($this->getConfig('testing') ? self::TEST_API_URL : self::LIVE_API_URL); $mtid = $invoice->public_id;//$this->generateMtid(); // SEE par.2 if ($invoice->first_total > 1000) throw new InvalidArgumentException('The maximum amount value of dispositions is 1000.00'); // see par.2 $request = array(//$username, $password, $mtid, $subId, $amount, $currency, $okUrl, $nokUrl, $merchantClientId, $pnUrl, $clientIp $this->getConfig('login'), $this->getConfig('password'), $mtid, null, sprintf('%.2f',$invoice->first_total), $invoice->currency, urlencode($this->getPluginUrl('thanks')."?mtid=".$invoice->public_id), // SEE par.3 urlencode($this->getPluginUrl('cancelpaysafecart'). "?id=" . $invoice->getSecureId('CANCEL')), //$this->getCancelUrl(), // see par.3 // SEE par.1 $invoice->getUserId(), //$invoice->public_id, // see par.1 urlencode($this->getPluginUrl()), null ); $this->logRequest($request); $response = call_user_func_array(array($client,'createDisposition'), $request); $this->logResponse(get_object_vars($response)); if($response->resultCode != 0 || $response->errorCode != 0) { // SEE par.4 $result->setErrorMessages(array('Transaction could not be initiated due to connection problems.')); //$result->setErrorMessages(array('Error during request to paysafecard server')); // see par.4 return; } $a = new Am_Paysystem_Action_Redirect($this->getConfig('testing') ? self::TEST_REDIRECT_URL : self::LIVE_REDIRECT_URL); $a->mid = $response->mid; $a->mtid = $mtid; $a->amount = sprintf('%.2f',$invoice->first_total); $a->currency = $invoice->currency; $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paysafecard($this, $request, $response, $invokeArgs); } function createThanksTransaction(\Am_Mvc_Request $request, \Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_Paysafecard_Thanks($this, $request, $response, $invokeArgs); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getReadme() { return <<request->get('mtid'); } public function getUniqId() { return $this->request->get('mtid'); } public function validateSource() { $mtid = $this->request->get('mtid'); //serialNumbers=0000000001200000;EUR;7.50;00002;0000000001300000;EUR;5.50;00002; // if(!$vars['serialNumbers']) // { // $this->getPlugin()->getDi()->errorLogTable->log('PSC: bad request from PSC server'); // throw new Am_Exception_Paysystem_TransactionSource('Incorrect transaction received. Please contact webmaster for details'); // } $invoice = $this->getPlugin()->getDi()->invoiceTable->findFirstByPublicId($mtid); if(!$invoice) { $this->getPlugin()->getDi()->errorLogTable->log('PSC: not found invoice by public_id [' . $mtid . ']'); throw new Am_Exception_Paysystem_TransactionSource('Incorrect transaction received. Please contact webmaster for details'); } include_once(dirname(__FILE__).'/SOPGClassicMerchantClient.php'); // getSerailNumbers // resultCode=0 errorCode=0 dispositionState = S | E -> executeDebit // dispositionState = O -> payment already done; return true; $client = new SOPGClassicMerchantClient($this->getPlugin()->getConfig('testing') ? Am_Paysystem_Paysafecard::TEST_API_URL : Am_Paysystem_Paysafecard::LIVE_API_URL); $request = array( $this->getPlugin()->getConfig('login'), $this->getPlugin()->getConfig('password'), $mtid, null, $invoice->currency ); $this->getPlugin()->logRequest($request); try { $serialsResponse = call_user_func_array(array($client,'getSerialNumbers'), $request); $this->getPlugin()->logResponse(get_object_vars($serialsResponse)); }catch(Exception $e) { $this->getPlugin()->getDi()->errorLogTable->logException($e); throw new Am_Exception_Paysystem_TransactionSource('Incorrect transaction received. Please contact webmaster for details'); } if($serialsResponse->resultCode == 0 && $serialsResponse->response->errorCode == 0){ switch($serialsResponse->dispositionState) { case 'S' : case 'E' : $request = array(//$username, $password, $mtid, $subId, $amount, $currency, $close, $partialDebitId $this->getPlugin()->getConfig('login'), $this->getPlugin()->getConfig('password'), $mtid, null, $invoice->first_total, //$this->subvars['2'], $invoice->currency, //$this->subvars['1'], 1, null ); $this->getPlugin()->logRequest($request); try { $this->response = call_user_func_array(array($client,'executeDebit'), $request); }catch(Exception $e) { $this->getPlugin()->getDi()->errorLogTable->logException($e); throw new Am_Exception_Paysystem_TransactionSource('Incorrect transaction received. Please contact webmaster for details'); } $this->getPlugin()->logResponse(get_object_vars($this->response)); if(($this->response->resultCode != 0) || ($this->response->errorCode != 0)) return false; case 'O' : return true; } } throw new Am_Exception_Paysystem_TransactionSource('Incorrect transaction received. Please contact webmaster for details'); } public function validateStatus() { // all checked at validateSource return true; } public function validateTerms() { // all checked at validateSource return true; } } class Am_Paysystem_Transaction_Paysafecard_Thanks extends Am_Paysystem_Transaction_Paysafecard { function process() { try { parent::process(); } catch (Am_Exception_Paysystem_TransactionAlreadyHandled $e) { // do nothing if transaction is already handled } if (Am_Di::getInstance()->config->get('auto_login_after_signup')) Am_Di::getInstance()->auth->setUser($this->invoice->getUser(), $this->request->getClientIp()); } } class Am_Paysystem_Action_HtmlTemplate_Paysafecard extends Am_Paysystem_Action_HtmlTemplate { protected $_template; protected $_path; public function __construct($path, $template) { $this->_template = $template; $this->_path = $path; } public function process(Am_Mvc_Controller $action = null) { $action->view->addBasePath($this->_path); $action->renderScript($this->_template); } } PK\sաLdefault/plugins/payment/paysafecard/scripts/payment-paysafecard-cancel.phtmlnu[setLayout('layout.phtml'); ?>
        PK\Z:99#default/plugins/payment/epay-bg.phpnu[ipn_url = $this->getPluginUrl('ipn'); $this->submit_url = $this->getConfig('testing') ? 'https://devep2.datamax.bg/ep2/epay2_demo/' : 'https://www.epay.bg/'; } public function _initSetupForm(Am_Form_Setup $form) { $form->addText("min", array('class' => 'el-wide')) ->setLabel("MIN\n" . "This value is provided by ePay.bg") ->addRule('regex', 'MIN must be 10 hexadecimal digits', '/^[A-F0-9]{10}$/') ->addRule('required'); $form->addPassword("secret", array('class' => 'el-wide')) ->setLabel("Secret\n" . "This value is provided by ePay.bg") ->addRule('required'); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox(Testing) Account?"); } public function isConfigured() { return $this->getConfig('min') && $this->getConfig('secret'); } function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $product = $invoice->getProducts()[0]; $secret = $this->config['secret']; $min = $this->config['min']; $invoice_id = $invoice->invoice_id; $sum = $invoice->first_total - $invoice->first_tax - $invoice->first_shipping; # XXX Expiration date '01.08.2020' $exp_date = strftime("%d.%m.%Y", time() + 7 * 24 * 3600); $descr = strip_tags($product->getDescription()); $data = "MIN={$min}\nINVOICE={$invoice_id}\nAMOUNT={$sum}\nEXP_TIME={$exp_date}\nDESCR={$descr}\nDATA"; $ENCODED = base64_encode($data); $CHECKSUM = $this->hmac('sha1', $ENCODED, $secret); $arr['PAGE'] = 'paylogin'; $arr['ENCODED'] = $ENCODED; $arr['CHECKSUM'] = $CHECKSUM; $arr['URL_OK'] = $this->getReturnUrl(); $arr['URL_CANCEL'] = $this->getCancelUrl(); $arr['AMOUNT'] = $sum; $action = new Am_Paysystem_Action_Form($this->submit_url); //$action->setAutoSubmit(false); foreach ($arr as $k => $v) { $action->$k = $v; } $result->setAction($action); } public function createTransaction($request, $response, array $invokeArgs) { return new Am_Paysystem_Transaction_EpayBg($this, $request, $response, $invokeArgs); } public function hmac($algo, $data, $passwd) { /* md5 and sha1 only */ $algo = strtolower($algo); $p = array('md5' => 'H32', 'sha1' => 'H40'); if (strlen($passwd) > 64) $passwd = pack($p[$algo], $algo($passwd)); if (strlen($passwd) < 64) $passwd = str_pad($passwd, 64, chr(0)); $ipad = substr($passwd, 0, 64) ^ str_repeat(chr(0x36), 64); $opad = substr($passwd, 0, 64) ^ str_repeat(chr(0x5C), 64); return($algo($opad . pack($p[$algo], $algo($ipad . $data)))); } public function getReadme() { return <<ePay payment plugin installation 1. Configure plugin at aMember CP -> Setup/Configuration -> ePay 2. Set PostBack URL in ePay control panel to $this->ipn_url CUT; } } class Am_Paysystem_Transaction_EpayBg extends Am_Paysystem_Transaction_Incoming { public function getUniqId() { $vars = $this->request->getPost(); return crc32($vars['encoded']); } public function process() { if ($this->request->getMethod() == Am_Mvc_Request::METHOD_GET) { return true; } $vars = $this->request->getPost(); $this->log->add( "ePay DEBUG: process_thanks \$vars=
        " . print_r($vars, true) ); $this->validateSource(); $data = base64_decode($vars['encoded']); $lines_arr = split("\n", $data); $info_data = ''; foreach ($lines_arr as $line) { if (preg_match( "/^INVOICE=(\d+):STATUS=(PAID|DENIED|EXPIRED)(:PAY_TIME=(\d+):STAN=(\d+):BCODE=([0-9a-zA-Z]+))?$/", $line, $regs)) { $invoice = $regs[1]; $status = $regs[2]; $pay_date = $regs[4]; # XXX if PAID $stan = $regs[5]; # XXX if PAID $bcode = $regs[6]; # XXX if PAID # XXX process $invoice, $status, $pay_date, $stan, $bcode here $paymentData = Am_Di::getInstance()->invoiceTable->load($invoice); if (!$paymentData) { $info_data .= "INVOICE=$invoice:STATUS=NO\n"; } elseif ('PAID' == $status && $paymentData->status != Invoice::PAID) { $err = $paymentData->addPayment($this); $info_data .= ($err) ? "INVOICE=$invoice:STATUS=OK\n" : "INVOICE=$invoice:STATUS=ERR\n"; } else if ('PAID' == $status && $paymentData->status == Invoice::PAID) { $info_data .= "INVOICE=$invoice:STATUS=OK\n"; } } } $this->log->add($info_data); $this->response->setBody($info_data . "\n"); } public function validateSource() { $vars = $this->request->getPost(); if (!$vars['encoded'] || !$vars['checksum']) { throw new Am_Exception_Paysystem_TransactionEmpty( "encoded or checksum are empty"); } $ENCODED = $vars['encoded']; $CHECKSUM = $vars['checksum']; $secret = $this->plugin->getConfig('secret'); $hmac = $this->plugin->hmac('sha1', $ENCODED, $secret); if ($hmac == $CHECKSUM) { return true; } else { $data = "Checksum comparision:\n"; $data .= $hmac . "\n"; $data .= $CHECKSUM; $this->plugin->logRequest($data); throw new Am_Exception_Paysystem_TransactionSource("" . "IPN seems to be received from unknown source, not from the paysystem
        " . "CHECKSUM: $CHECKSUM
        " . "RESULT: $hmac"); } } public function validateStatus() { return true; } public function validateTerms() { return true; } }PK\$(default/plugins/payment/pagseguro-v2.phpnu[addText('merchant')->setLabel('Merchant Email'); $form->addText('token')->setLabel('Security Token'); $form->addAdvCheckbox("testing") ->setLabel("Is it a Sandbox(Testing) Account?"); } function getSupportedCurrencies() { return array('BRL'); } public function getRecurringType() { return self::REPORTS_NOT_RECURRING; } function getHost() { return $this->getConfig('testing') ? self::SANDBOX_HOST : self::LIVE_HOST; } function getWsHost() { return $this->getConfig('testing') ? self::SANDBOX_WS_HOST : self::LIVE_WS_HOST; } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { $req = new Am_HttpRequest('https://' . $this->getWsHost() . '/v2/checkout', Am_HttpRequest::METHOD_POST); $p = array(); $p['email'] = $this->getConfig('merchant'); $p['token'] = $this->getConfig('token'); $p['currency'] = strtoupper($invoice->currency); $p['reference'] = $invoice->public_id; $p['receiverEmail'] = $this->getConfig('merchant'); $i = 1; foreach ($invoice->getItems() as $item) { $p['itemId' . $i] = $item->item_id; $p['itemDescription' . $i] = $item->item_title; $p['itemAmount' . $i] = $item->first_total; $p['itemQuantity' . $i] = $item->qty; $i++; } $p['senderEmail'] = $invoice->getUser()->email; $p['senderName'] = $invoice->getUser()->getName(); $p['redirectURL'] = $this->getReturnUrl(); $p['notificationURL'] = $this->getPluginUrl('ipn'); $p['maxUses'] = 1; $p['maxAge'] = 180; $req->addPostParameter($p); $this->logRequest($req); $res = $req->send(); $this->logResponse($res); if (!($xml = simplexml_load_string($res->getBody()))) { throw new Am_Exception('Incorrect XML recieved'); } if ($xml->getName() == 'errors') throw new Am_Exception(sprintf('%s: %s', $xml->errors[0]->code, $xml->errors[0]->message)); if ($res->getStatus() != 200) throw new Am_Exception_FatalError(sprintf('Incorrect Responce Status From Paysystem [%s]', $res->getStatus())); $code = (string) $xml->code; $a = new Am_Paysystem_Action_Redirect('https://' . $this->getHost() . '/v2/checkout/payment.html?code=' . $code); $result->setAction($a); } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { return new Am_Paysystem_Transaction_PagseguroV2($this, $request, $response, $invokeArgs); } function getReadme() { $url = Am_Html::escape($this->getPluginUrl('ipn')); return <<PagSecuro payment plugin configuration http://pagseguro.uol.com.br Activate "NOTIFICAÇÃO DE TRANSAÇÕES" at your PagSeguro merchant account: $url Also you must set up your account to only accept payment requisitions generated via API. CUT; } } class Am_Paysystem_Transaction_PagseguroV2 extends Am_Paysystem_Transaction_Incoming { const STATUS_PAY = 3; const STATUS_RETURNED = 6; protected $xml; public function findInvoiceId() { return (string) $this->xml->reference; } public function getUniqId() { return (string) $this->xml->code; } public function getAmount() { return (string) $this->xml->grossAmount; } public function validateSource() { $code = $this->request->getPost('notificationCode'); if (!$code) return false; $req = new Am_HttpRequest("https://" . $this->plugin->getWsHost() . "/v2/transactions/notifications/$code?" . http_build_query(array( 'email' => $this->plugin->getConfig('merchant'), 'token' => $this->plugin->getConfig('token') ))); $this->plugin->logRequest($req); $res = $req->send(); $this->plugin->logResponse($res); if ($res->getStatus() != 200) return false; $this->xml = simplexml_load_string($res->getBody()); if (!$this->xml) return false; return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } public function processValidated() { switch ((string) $this->xml->status) { case self::STATUS_PAY : $this->invoice->addPayment($this); break; case self::STATUS_RETURNED : $this->invoice->addRefund($this, (string) $this->xml->code); break; } } } PK\BN:default/plugins/payment/amazon-instant-access/AmLogger.phpnu[errorLogTable->log("[Amazon Istant Access " . strtoupper($level) . "-log]: $message."); } } PK\b__Jdefault/plugins/payment/amazon-instant-access/Psr/Log/LoggerAwareTrait.phpnu[logger = $logger; } } PK\ X1``Rdefault/plugins/payment/amazon-instant-access/Psr/Log/InvalidArgumentException.phpnu[log(LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * @return null */ public function alert($message, array $context = array()) { $this->log(LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * @return null */ public function critical($message, array $context = array()) { $this->log(LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * @return null */ public function error($message, array $context = array()) { $this->log(LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * @return null */ public function warning($message, array $context = array()) { $this->log(LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * @return null */ public function notice($message, array $context = array()) { $this->log(LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * @return null */ public function info($message, array $context = array()) { $this->log(LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * @return null */ public function debug($message, array $context = array()) { $this->log(LogLevel::DEBUG, $message, $context); } } PK\l$ӥ88Bdefault/plugins/payment/amazon-instant-access/Psr/Log/LogLevel.phpnu[log(LogLevel::EMERGENCY, $message, $context); } /** * Action must be taken immediately. * * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * * @param string $message * @param array $context * @return null */ public function alert($message, array $context = array()) { $this->log(LogLevel::ALERT, $message, $context); } /** * Critical conditions. * * Example: Application component unavailable, unexpected exception. * * @param string $message * @param array $context * @return null */ public function critical($message, array $context = array()) { $this->log(LogLevel::CRITICAL, $message, $context); } /** * Runtime errors that do not require immediate action but should typically * be logged and monitored. * * @param string $message * @param array $context * @return null */ public function error($message, array $context = array()) { $this->log(LogLevel::ERROR, $message, $context); } /** * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * * @param string $message * @param array $context * @return null */ public function warning($message, array $context = array()) { $this->log(LogLevel::WARNING, $message, $context); } /** * Normal but significant events. * * @param string $message * @param array $context * @return null */ public function notice($message, array $context = array()) { $this->log(LogLevel::NOTICE, $message, $context); } /** * Interesting events. * * Example: User logs in, SQL logs. * * @param string $message * @param array $context * @return null */ public function info($message, array $context = array()) { $this->log(LogLevel::INFO, $message, $context); } /** * Detailed debug information. * * @param string $message * @param array $context * @return null */ public function debug($message, array $context = array()) { $this->log(LogLevel::DEBUG, $message, $context); } /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * @return null */ abstract public function log($level, $message, array $context = array()); } PK\>Ddefault/plugins/payment/amazon-instant-access/Psr/Log/NullLogger.phpnu[logger) { }` * blocks. */ class NullLogger extends AbstractLogger { /** * Logs with an arbitrary level. * * @param mixed $level * @param string $message * @param array $context * @return null */ public function log($level, $message, array $context = array()) { // noop } } PK\U))Gdefault/plugins/payment/amazon-instant-access/amazon-instant-access.phpnu[paysystemList->getList() as $p) { if ($p->getId() == $this->getId()) $p->setPublic(false); } $di->productTable->customFields()->add( new Am_CustomFieldText( 'aic_product_id', "Amazon Instant Access Product Id", "" , array() )); } public function _initSetupForm(Am_Form_Setup $form) { $form->setTitle('Amazon Instant Access'); $form->addText('public_key', array('size' => 40)) ->setLabel('Your AIA Public Key') ->addRule('required'); $form->addText('private_key', array('size' => 40)) ->setLabel('Your AIA Provate Key') ->addRule('required'); } public function canAutoCreate() { return true; } protected function _afterInitSetupForm(Am_Form_Setup $form) { parent::_afterInitSetupForm($form); $form->removeElementByName($this->_configPrefix . $this->getId() . '.auto_create'); } public function getConfig($key = null, $default = null) { switch ($key) { case 'auto_create' : return true; default: return parent::getConfig($key, $default); } } public function isConfigured() { return (bool) ($this->getConfig('public_key') && $this->getConfig('private_key')); } public function isNotAcceptableForInvoice(Invoice $invoice) { } public function _process(Invoice $invoice, Am_Mvc_Request $request, Am_Paysystem_Result $result) { } public function getRecurringType() { return self::REPORTS_EOT; } public function directAction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { $this->loadAmazonLib(); Logger::setLogger(new AmLogger()); $credentialStore = new CredentialStore(); $credentialStore->load($this->getConfig('private_key') . " " . $this->getConfig('public_key')); $signer = new Signer(); if(!$signer->verify(new Request($_SERVER, $request->getRawBody()), $credentialStore)) { $response->setHeader("HTTP/1.1 403 Forbidden", 403, true); $response->setBody(''); return; } $post = json_decode($request->getRawBody(),true); $header = array( 'name' => "HTTP/1.1 500 Internal Server Error", 'value' => 500, 'replace' => true ); $out = ""; switch ($request->getActionName()) { case 'link': if($post['operation'] == 'GetUserId' && !empty($post['infoField1'])) { $header = array( 'name' => "HTTP/1.1 200 OK", 'value' => 200, 'replace' => true ); if($user = $this->getDi()->userTable->findFirstByEmail($post['infoField1'])) { $out = array('response' => 'OK', 'userId' => $user->pk()); } else { $out = array('response' => 'FAIL_ACCOUNT_INVALID'); } } break; case 'purchase': $invoiceLog = $this->_logDirectAction($request, $response, $invokeArgs); switch ($post['operation']) { case 'Purchase': $transaction = new Am_Paysystem_Transaction_AmazonInstantAccess_Purchase($this, $request, $response, $invokeArgs); break; case 'Revoke': $transaction = new Am_Paysystem_Transaction_AmazonInstantAccess_Revoke($this, $request, $response, $invokeArgs); break; case 'SubscriptionActivate': $transaction = new Am_Paysystem_Transaction_AmazonInstantAccess_SubsAct($this, $request, $response, $invokeArgs); break; case 'SubscriptionDeactivate': $transaction = new Am_Paysystem_Transaction_AmazonInstantAccess_SubsDeact($this, $request, $response, $invokeArgs); break; default: $transaction = null; break; } if($transaction) { $transaction->setInvoiceLog($invoiceLog); try { $transaction->process(); $invoiceLog->setProcessed(); } catch (Exception $e) { if ($invoiceLog) { $invoiceLog->add($e); } break; } $header = array( 'name' => "HTTP/1.1 200 OK", 'value' => 200, 'replace' => true ); $out = array('response' => 'OK'); } break; } $response->setHeader($header['name'], $header['value'], $header['replace']); $response->setBody(json_encode($out)); return; } protected function loadAmazonLib() { require_once __DIR__ . '/autoload.php'; require_once __DIR__ . '/AmLogger.php'; } public function createTransaction(Am_Mvc_Request $request, Am_Mvc_Response $response, array $invokeArgs) { } public function getReadme() { $u1 = $this->getPluginUrl('link'); $u2 = $this->getPluginUrl('purchase'); return <<$u1 Fulfillment API Endpoint $u2 CUT; } } abstract class Am_Paysystem_Transaction_AmazonInstantAccess extends Am_Paysystem_Transaction_Incoming { protected $post; public function __construct(Am_Paysystem_Abstract $plugin, Am_Mvc_Request $request, Am_Mvc_Response $response, $invokeArgs) { $this->post = json_decode($request->getRawBody(),true); parent::__construct($plugin, $request, $response, $invokeArgs); } public function getReceiptId() { return $this->getUniqId(); } public function validateSource() { return true; } public function validateStatus() { return true; } public function validateTerms() { return true; } protected function getAutoInvoice() { if (!($prId = $this->post['productId'])) return null; if( !($product = $this->plugin->getDi()->productTable->findFirstByData('aic_product_id', $prId)) && !($product = $this->plugin->getDi()->productTable->load($prId, false)) ) return null; if (!($uId = $this->post['userId'])) return null; if(!($user = $this->plugin->getDi()->userTable->load($uId, false))) return null; $invoice = $this->getPlugin()->getDi()->invoiceRecord; $invoice->setUser($user); $invoice->add($product); $invoice->calculate(); $invoice->paysys_id = $this->plugin->getId(); $invoice->insert(); if ($this->log) { $this->log->updateQuick(array( 'invoice_id' => $invoice->pk(), 'user_id' => $user->user_id, )); } return $invoice; } } class Am_Paysystem_Transaction_AmazonInstantAccess_Purchase extends Am_Paysystem_Transaction_AmazonInstantAccess { public function autoCreateInvoice() { $invoice = $this->getAutoInvoice(); $invoice->data()->set('purchaseToken', $this->getUniqId())->update(); return $invoice; } public function getUniqId() { return $this->post['purchaseToken']; } public function processValidated() { $this->invoice->addPayment($this); } public function findInvoiceId() { } } class Am_Paysystem_Transaction_AmazonInstantAccess_Revoke extends Am_Paysystem_Transaction_AmazonInstantAccess { public function getUniqId() { return $this->post['purchaseToken'] . "-refund"; } public function processValidated() { $this->invoice->addRefund($this, $this->post['purchaseToken']); } public function findInvoiceId() { if($invoice = $this->plugin->getDi()->invoiceTable->findFirstByData('purchaseToken', $this->post['purchaseToken'])) return $invoice->public_id; } } class Am_Paysystem_Transaction_AmazonInstantAccess_SubsAct extends Am_Paysystem_Transaction_AmazonInstantAccess { function autoCreateInvoice() { $invoice = $this->getAutoInvoice(); $invoice->data()->set('subscriptionId', $this->getUniqId())->update(); return $invoice; } public function getUniqId() { return $this->post['subscriptionId']; } public function processValidated() { $this->invoice->addPayment($this); } public function findInvoiceId() { } } class Am_Paysystem_Transaction_AmazonInstantAccess_SubsDeact extends Am_Paysystem_Transaction_AmazonInstantAccess { public function getUniqId() { return $this->post['subscriptionId'] . "-cancel"; } public function processValidated() { $this->invoice->stopAccess($this); $this->invoice->setCancelled(true); } public function findInvoiceId() { if($invoice = $this->plugin->getDi()->invoiceTable->findFirstByData('subscriptionId', $this->post['subscriptionId'])) return $invoice->public_id; } } PK\:default/plugins/payment/amazon-instant-access/autoload.phpnu[setPurchaseToken($jsonObject->purchaseToken); $newObject->setUserId($jsonObject->userId); $newObject->setProductId($jsonObject->productId); $newObject->setReason($jsonObject->reason); }; $object = parent::createFromJson($jsonString, $callback); return $object; } public function getPurchaseToken() { return $this->purchaseToken; } public function setPurchaseToken($purchaseToken) { $this->purchaseToken = $purchaseToken; return $this; } public function getUserId() { return $this->userId; } public function setUserId($userId) { $this->userId = $userId; return $this; } public function getProductId() { return $this->productId; } public function setProductId($productId) { $this->productId = $productId; return $this; } public function getReason() { return $this->reason; } /** * Set the request reason. * * @param string a string representation of the reason * * @see Amazon\InstantAccess\Serialization\Enums\FulfillPurchaseReasonValue For reason values */ public function setReason($reason) { if (!FulfillPurchaseReasonValue::isValid($reason)) { throw new \InvalidArgumentException(sprintf('Invalid reason value: %s', $reason)); } $this->reason = $reason; return $this; } } PK\A?(sdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/SubscriptionDeactivateResponse.phpnu[response = $response; return $this; } } PK\nI(C C idefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/InstantAccessRequest.phpnu[setOperation($jsonObject->operation); // and the specific fields if ($callback && is_callable($callback)) { $callback($newObject, $jsonObject); } } catch (\Exception $e) { throw new \InvalidArgumentException( sprintf('Unable to deserialized object: %s. %s', $type, $e->getMessage()) ); } return $newObject; } public function getOperation() { return $this->operation; } /** * Set the request operation * * @param string a string representation of the operation * * @see Amazon\InstantAccess\Serialization\Enums\InstantAccessOperationValue For operation values */ public function setOperation($operation) { if (!InstantAccessOperationValue::isValid($operation)) { throw new \InvalidArgumentException(sprintf('Invalid operation value: %s', $reason)); } $this->operation = $operation; return $this; } } PK\ZK K jdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/RevokePurchaseRequest.phpnu[setPurchaseToken($jsonObject->purchaseToken); $newObject->setUserId($jsonObject->userId); $newObject->setProductId($jsonObject->productId); $newObject->setReason($jsonObject->reason); }; $object = parent::createFromJson($jsonString, $callback); return $object; } public function getPurchaseToken() { return $this->purchaseToken; } public function setPurchaseToken($purchaseToken) { $this->purchaseToken = $purchaseToken; return $this; } public function getUserId() { return $this->userId; } public function setUserId($userId) { $this->userId = $userId; return $this; } public function getProductId() { return $this->productId; } public function setProductId($productId) { $this->productId = $productId; return $this; } public function getReason() { return $this->reason; } /** * Set the request reason * * @param string a string representation of the reason * * @see Amazon\InstantAccess\Serialization\Enums\RevokePurchaseReasonValue For reason values */ public function setReason($reason) { if (!RevokePurchaseReasonValue::isValid($reason)) { throw new \InvalidArgumentException(sprintf('Invalid reason value: %s', $reason)); } $this->reason = $reason; return $this; } } PK\gQ#qdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/SubscriptionActivateResponse.phpnu[response = $response; return $this; } } PK\^ rdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/SubscriptionDeactivateRequest.phpnu[setSubscriptionId($jsonObject->subscriptionId); $newObject->setReason($jsonObject->reason); $newObject->setPeriod($jsonObject->period); }; $object = parent::createFromJson($jsonString, $callback); return $object; } public function getSubscriptionId() { return $this->subscriptionId; } public function setSubscriptionId($subscriptionId) { $this->subscriptionId = $subscriptionId; return $this; } public function getReason() { return $this->reason; } /** * Set the request reason * * @param string a string representation of the reason * * @see Amazon\InstantAccess\Serialization\Enums\SubscriptionDeactivateReasonValue For reason values */ public function setReason($reason) { if (!SubscriptionDeactivateReasonValue::isValid($reason)) { throw new \InvalidArgumentException(sprintf('Invalid reason value: %s', $reason)); } $this->reason = $reason; return $this; } public function getPeriod() { return $this->period; } /** * Set the request period * * @param string a string representation of the period * * @see Amazon\InstantAccess\Serialization\Enums\SubscriptionDeactivatePeriodValue For period values */ public function setPeriod($period) { if (!SubscriptionDeactivatePeriodValue::isValid($period)) { throw new \InvalidArgumentException(sprintf('Invalid period value: %s', $reason)); } $this->period = $period; return $this; } } PK\getConstants(); } /** * Check if $name is a value supported by the enum * * @param string $name a string * @return boolean true if $name is a valid value in this enum, false otherwise */ public static function isValid($name) { return in_array($name, self::getConstants()); } } PK\qdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/Enums/GetUserIdResponseValue.phpnu[setInfoField1($jsonObject->infoField1); // optional field if (isset($jsonObject->infoField2)) { $newObject->setInfoField2($jsonObject->infoField2); } // optional field if (isset($jsonObject->infoField3)) { $newObject->setInfoField3($jsonObject->infoField3); } }; $object = parent::createFromJson($jsonString, $callback); return $object; } public function getInfoField1() { return $this->infoField1; } public function setInfoField1($infoField1) { $this->infoField1 = $infoField1; return $this; } public function getInfoField2() { return $this->infoField2; } public function setInfoField2($infoField2) { $this->infoField2 = $infoField2; return $this; } public function getInfoField3() { return $this->infoField3; } public function setInfoField3($infoField3) { $this->infoField3 = $infoField3; return $this; } } PK\B B pdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/SubscriptionActivateRequest.phpnu[setSubscriptionId($jsonObject->subscriptionId); $newObject->setProductId($jsonObject->productId); $newObject->setUserId($jsonObject->userId); }; $object = parent::createFromJson($jsonString, $callback); return $object; } public function getSubscriptionId() { return $this->subscriptionId; } public function setSubscriptionId($subscriptionId) { $this->subscriptionId = $subscriptionId; return $this; } public function getProductId() { return $this->productId; } public function setProductId($productId) { $this->productId = $productId; return $this; } public function getUserId() { return $this->userId; } public function setUserId($userId) { $this->userId = $userId; return $this; } } PK\Ǒttfdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/GetUserIdResponse.phpnu[response = $response; return $this; } public function getUserId() { return $this->userId; } public function setUserId($userId) { $this->userId = $userId; return $this; } } PK\_jdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/InstantAccessResponse.phpnu[response; } public function setResponse($response) { $this->response = $response; return $this; } } PK\kdefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/RevokePurchaseResponse.phpnu[response = $response; return $this; } } PK\?߉ldefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Serialization/FulfillPurchaseResponse.phpnu[response = $response; return $this; } } PK\8[default/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Signature/Credential.phpnu[secretKey = $secretKey; $this->publicKey = $publicKey; } /** * Gets the secret key. * * @return string the secret key */ public function getSecretKey() { return $this->secretKey; } /** * Gets the public key. * * @return string the public key */ public function getPublicKey() { return $this->publicKey; } } PK\dPddefault/plugins/payment/amazon-instant-access/Amazon/InstantAccess/Signature/AuthorizationHeader.phpnu[ * Authorization: ALGORITHM Credential=CREDENTIAL, SignedHeaders=SIGNED_HEADERS, Signature=SIGNATURE *