Aitoc_Aitvbulletin - Version 0.3.11

Version Notes

0.3.11

Download this release

Release Info

Developer Magento Core Team
Extension Aitoc_Aitvbulletin
Version 0.3.11
Comparing to
See all releases


Version 0.3.11

Files changed (53) hide show
  1. app/code/local/Aitoc/Aitvbulletin/Block/Account/Forum.php +38 -0
  2. app/code/local/Aitoc/Aitvbulletin/Block/Account/Logout.php +34 -0
  3. app/code/local/Aitoc/Aitvbulletin/Block/Admin/News.php +21 -0
  4. app/code/local/Aitoc/Aitvbulletin/Block/Admin/Vbserver/Edit.php +80 -0
  5. app/code/local/Aitoc/Aitvbulletin/Block/Admin/Vbserver/Edit/Form.php +100 -0
  6. app/code/local/Aitoc/Aitvbulletin/Block/Config/FormFieldset.php +57 -0
  7. app/code/local/Aitoc/Aitvbulletin/Block/Rewrite/FrontPageHtml.data.php +44 -0
  8. app/code/local/Aitoc/Aitvbulletin/Block/Rewrite/FrontPageHtml.php +44 -0
  9. app/code/local/Aitoc/Aitvbulletin/Helper/Data.php +184 -0
  10. app/code/local/Aitoc/Aitvbulletin/Model/Config/BackendForum.php +25 -0
  11. app/code/local/Aitoc/Aitvbulletin/Model/Config/SourceDbtype.php +15 -0
  12. app/code/local/Aitoc/Aitvbulletin/Model/Curl.php +40 -0
  13. app/code/local/Aitoc/Aitvbulletin/Model/Exception.php +21 -0
  14. app/code/local/Aitoc/Aitvbulletin/Model/Mysql4/Setup.php +41 -0
  15. app/code/local/Aitoc/Aitvbulletin/Model/Notification/Abstract.php +74 -0
  16. app/code/local/Aitoc/Aitvbulletin/Model/Notification/News.php +7 -0
  17. app/code/local/Aitoc/Aitvbulletin/Model/Notification/Notifications.php +36 -0
  18. app/code/local/Aitoc/Aitvbulletin/Model/Notification/Observer.php +21 -0
  19. app/code/local/Aitoc/Aitvbulletin/Model/Notification/Service.php +91 -0
  20. app/code/local/Aitoc/Aitvbulletin/Model/Observer.php +35 -0
  21. app/code/local/Aitoc/Aitvbulletin/Model/Rewrite/FrontCustomer.data.php +57 -0
  22. app/code/local/Aitoc/Aitvbulletin/Model/Rewrite/FrontCustomer.php +57 -0
  23. app/code/local/Aitoc/Aitvbulletin/Model/Session.php +12 -0
  24. app/code/local/Aitoc/Aitvbulletin/Model/Vbserver.php +229 -0
  25. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Abstract.php +29 -0
  26. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Hash.php +13 -0
  27. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Abstract.php +258 -0
  28. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Collection/Abstract.php +21 -0
  29. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Hash.php +27 -0
  30. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Hash/Collection.php +36 -0
  31. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/User.php +57 -0
  32. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/User/Collection.php +32 -0
  33. app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/User.php +117 -0
  34. app/code/local/Aitoc/Aitvbulletin/controllers/AccountController.php +154 -0
  35. app/code/local/Aitoc/Aitvbulletin/controllers/Admin/VbserverController.php +100 -0
  36. app/code/local/Aitoc/Aitvbulletin/controllers/ProxyController.php +152 -0
  37. app/code/local/Aitoc/Aitvbulletin/etc/config.xml +211 -0
  38. app/code/local/Aitoc/Aitvbulletin/etc/system.xml +48 -0
  39. app/code/local/Aitoc/Aitvbulletin/sql/aitvbulletin_setup/mysql4-install-0.3.11.php +9 -0
  40. app/design/adminhtml/default/default/layout/aitvbulletin.xml +21 -0
  41. app/design/adminhtml/default/default/template/aitvbulletin/aitoc_news.phtml +26 -0
  42. app/design/adminhtml/default/default/template/aitvbulletin/vbserver/edit.phtml +54 -0
  43. app/design/adminhtml/default/default/template/aitvbulletin/vbserver/js.phtml +38 -0
  44. app/design/frontend/default/default/layout/aitvbulletin.xml +44 -0
  45. app/design/frontend/default/default/template/aitvbulletin/customer/forum.phtml +72 -0
  46. app/etc/modules/Aitoc_Aitvbulletin.xml +11 -0
  47. package.xml +18 -0
  48. skin/adminhtml/default/default/aitvbulletin.css +11 -0
  49. skin/frontend/default/default/css/aitvbulletin.css +2 -0
  50. vbulletin_product/vbulletin_import/Aitoc MagentoVB Lite.xml +172 -0
  51. vbulletin_product/vbulletin_upload/aitmagentovb.php +134 -0
  52. vbulletin_product/vbulletin_upload/includes/class_aitmagentovb.php +259 -0
  53. vbulletin_product/vbulletin_upload/includes/class_aitzend.php +1679 -0
app/code/local/Aitoc/Aitvbulletin/Block/Account/Forum.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Account_Forum extends Mage_Customer_Block_Account_Dashboard
7
+ {
8
+ public function getActionUrl()
9
+ {
10
+ return $this->getUrl('*/*/forumVerifyPost');
11
+ }
12
+
13
+ public function getCustomerAvatarPath()
14
+ {
15
+ $vbUser = $this->getCustomer()->getAitvbulletinUser();
16
+ /* @var $vbUser Aitoc_Aitvbulletin_Model_Vbulletin_User */
17
+ return $vbUser->getVbAvatarPath();
18
+ }
19
+
20
+ public function getCustomerPostsCount()
21
+ {
22
+ $vbUser = $this->getCustomer()->getAitvbulletinUser();
23
+ /* @var $vbUser Aitoc_Aitvbulletin_Model_Vbulletin_User */
24
+ return $vbUser->getData('posts');
25
+ }
26
+
27
+ public function getForumForgotUrl()
28
+ {
29
+ return $this->helper('aitvbulletin')->getForumUrl()
30
+ . 'login.php?do=lostpw';
31
+ }
32
+ public function getForumProfileUrl()
33
+ {
34
+ return $this->helper('aitvbulletin')->getForumUrl()
35
+ . 'member.php?u='.$this->getCustomer()->getAitvbulletinUserId();
36
+ }
37
+
38
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Account/Logout.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Account_Logout extends Mage_Core_Block_Template
7
+ {
8
+ public function _toHtml()
9
+ {
10
+ // url is set in Aitoc_Aitvbulletin_Model_Observer->customerLogout()
11
+ $logoutUrl = $this->_getSession()->getLogoutUrl(true);
12
+
13
+ $html = '';
14
+ if ($logoutUrl)
15
+ {
16
+ $html .= '<div class="aitvbulletin-auth-image">';
17
+ $html .= '<img src="' . $logoutUrl . '" alt="" />';
18
+ $html .= '</div>';
19
+ }
20
+
21
+ return $html;
22
+ }
23
+
24
+ /**
25
+ * Retrieve customer session model object
26
+ *
27
+ * @return Aitoc_Aitvbulletin_Model_Session
28
+ */
29
+ protected function _getSession()
30
+ {
31
+ return Mage::getSingleton('aitvbulletin/session');
32
+ }
33
+
34
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Admin/News.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Admin_News extends Mage_Adminhtml_Block_Widget
7
+ {
8
+ public function __construct()
9
+ {
10
+ parent::__construct();
11
+ $this->setTemplate('aitvbulletin/aitoc_news.phtml');
12
+ }
13
+
14
+ public function getNews()
15
+ {
16
+ return Mage::getModel('aitvbulletin/notification_news')
17
+ ->loadData()
18
+ ->getData();
19
+ }
20
+
21
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Admin/Vbserver/Edit.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Admin_Vbserver_Edit extends Mage_Adminhtml_Block_Widget
7
+ {
8
+ const AITOC_MODULE_LINK = 'http://www.aitoc.com/en/magentomods_vbulletin_integration_lite.html';
9
+
10
+ public function __construct()
11
+ {
12
+ parent::__construct();
13
+ $this->setTemplate('aitvbulletin/vbserver/edit.phtml');
14
+ $this->setId('vbserver_edit');
15
+ }
16
+
17
+ /**
18
+ * Retrieve currently edited vbserver object
19
+ *
20
+ * @return Aitoc_Aitvbulletin_Model_Vbulletin_Server
21
+ */
22
+ public function getVbserver()
23
+ {
24
+ return Mage::registry('vbserver');
25
+ }
26
+
27
+ public function getVbserverId()
28
+ {
29
+ return $this->getVbserver()->getId();
30
+ }
31
+
32
+ protected function _prepareLayout()
33
+ {
34
+ $this->setChild('reset_button',
35
+ $this->getLayout()->createBlock('adminhtml/widget_button')
36
+ ->setData(array(
37
+ 'label' => Mage::helper('catalog')->__('Reset'),
38
+ 'onclick' => 'setLocation(\''.$this->getUrl('*/*/*', array('_current'=>true)).'\')'
39
+ ))
40
+ );
41
+
42
+ $this->setChild('save_button',
43
+ $this->getLayout()->createBlock('adminhtml/widget_button')
44
+ ->setData(array(
45
+ 'label' => Mage::helper('catalog')->__('Save'),
46
+ 'onclick' => 'vbserverForm.submit()',
47
+ 'class' => 'save',
48
+ ))
49
+ );
50
+
51
+ return parent::_prepareLayout();
52
+ }
53
+
54
+ // buttons html
55
+ public function getCancelButtonHtml()
56
+ {
57
+ return $this->getChildHtml('reset_button');
58
+ }
59
+ public function getSaveButtonHtml()
60
+ {
61
+ return $this->getChildHtml('save_button');
62
+ }
63
+
64
+ // urls
65
+ public function getValidationUrl()
66
+ {
67
+ return $this->getUrl('*/*/validate', array('_current'=>true));
68
+ }
69
+ public function getSaveUrl()
70
+ {
71
+ return $this->getUrl('*/*/save', array('_current'=>true));
72
+ }
73
+
74
+
75
+ public function getVbDownloadLinkHtml()
76
+ {
77
+ return '<a href="'.self::AITOC_MODULE_LINK.'">'.Mage::helper('aitvbulletin')->__('vBulletin to Magento Bridge').'</a>';
78
+ }
79
+
80
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Admin/Vbserver/Edit/Form.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Admin_Vbserver_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
7
+ {
8
+ protected function _prepareForm()
9
+ {
10
+ $form = new Varien_Data_Form();
11
+
12
+ $vbserver = Mage::registry('vbserver');
13
+ $helper = Mage::helper('aitvbulletin');
14
+ /* @var $helper Aitoc_Aitvbulletin_Helper_Data */
15
+
16
+ $form->setDataObject($vbserver);
17
+
18
+ $fieldset = $form->addFieldset('database',
19
+ array('legend' => $helper->__('Database Settings'))
20
+ );
21
+
22
+ $fieldset->addField('vbserver_type', 'select', array(
23
+ 'label' => $helper->__('Database Type'),
24
+ 'title' => $helper->__('Database Type'),
25
+ 'name' => 'type',
26
+ 'value' => $vbserver->getType(),
27
+ 'values'=> Mage::getModel('aitvbulletin/config_sourceDbtype')->toOptionArray(),
28
+ ));
29
+ $fieldset->addField('vbserver_name', 'text', array(
30
+ 'label' => $helper->__('Database Name'),
31
+ 'title' => $helper->__('Database Name'),
32
+ 'note' => $helper->__('e.g., %s', 'forum'),
33
+ 'name' => 'name',
34
+ 'value' => $vbserver->getName(),
35
+ 'required' => true,
36
+ ));
37
+ $fieldset->addField('vbserver_prefix', 'text', array(
38
+ 'label' => $helper->__('Table Prefix'),
39
+ 'title' => $helper->__('Table Prefix'),
40
+ 'name' => 'prefix',
41
+ 'value' => $vbserver->getPrefix(),
42
+ ));
43
+ $fieldset->addField('vbserver_user', 'text', array(
44
+ 'label' => $helper->__('Database User'),
45
+ 'title' => $helper->__('Database User'),
46
+ 'note' => $helper->__('e.g., %s', 'root'),
47
+ 'name' => 'user',
48
+ 'value' => $vbserver->getUser(),
49
+ 'required' => true,
50
+ ));
51
+ $fieldset->addField('vbserver_pass', 'text', array(
52
+ 'label' => $helper->__('User Password'),
53
+ 'title' => $helper->__('User Password'),
54
+ 'name' => 'pass',
55
+ 'value' => $vbserver->getPass(),
56
+ ));
57
+ $fieldset->addField('vbserver_host', 'text', array(
58
+ 'label' => $helper->__('Database Host'),
59
+ 'title' => $helper->__('Database Host'),
60
+ 'note' => $helper->__('e.g., %s', 'localhost'),
61
+ 'name' => 'host',
62
+ 'value' => $vbserver->getHost(),
63
+ 'required' => true,
64
+ ));
65
+ $fieldset->addField('vbserver_port', 'text', array(
66
+ 'label' => $helper->__('Database Port'),
67
+ 'title' => $helper->__('Database Port'),
68
+ 'note' => $helper->__('optional, 3306 by default'),
69
+ 'name' => 'port',
70
+ 'value' => $vbserver->getPort(),
71
+ 'class' => 'validate-digits',
72
+ ));
73
+
74
+ $fieldset2 = $form->addFieldset('product',
75
+ array('legend' => $helper->__('Product Settings'))
76
+ );
77
+
78
+ $fieldset2->addField('vbserver_link', 'text', array(
79
+ 'label' => $helper->__('Forum Link'),
80
+ 'title' => $helper->__('Forum Link'),
81
+ 'note' => $helper->__('starting with http://'),
82
+ 'name' => 'link',
83
+ 'value' => $vbserver->getLink(),
84
+ 'class' => 'validate-url',
85
+ 'required' => true,
86
+ ));
87
+ $fieldset2->addField('vbserver_apikey', 'text', array(
88
+ 'label' => $helper->__('Module API key'),
89
+ 'title' => $helper->__('Module API key'),
90
+ 'note' => $helper->__('must be the same as it is set in vBulletin\'s AdminCP'),
91
+ 'name' => 'apikey',
92
+ 'value' => $vbserver->getApikey(),
93
+ 'required' => true,
94
+ ));
95
+
96
+ $form->setFieldNameSuffix('vbserver');
97
+ $this->setForm($form);
98
+ }
99
+
100
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Config/FormFieldset.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Config_FormFieldset
7
+ extends Mage_Adminhtml_Block_System_Config_Form_Fieldset
8
+ {
9
+
10
+ public function setGroup(Mage_Core_Model_Config_Element $group)
11
+ {
12
+ $_vbulletin_setup = true;
13
+ try
14
+ {
15
+ $_vbulletin_enabled = Mage::helper('aitvbulletin')->isVbulletinActive();
16
+ }
17
+ catch (Aitoc_Aitvbulletin_Model_Exception $ex)
18
+ {
19
+ $_vbulletin_setup = false;
20
+ }
21
+
22
+ foreach ($group->fields as $elements)
23
+ {
24
+ foreach ($elements as $e)
25
+ {
26
+ /* @var $e Mage_Core_Model_Config_Element */
27
+
28
+ $_err = '';
29
+ switch ($e->getName())
30
+ {
31
+ case 'enabled':
32
+ if (!$_vbulletin_setup)
33
+ {
34
+ $_err .= Mage::helper('aitvbulletin')->__('Please setup vBulletin Connection first');
35
+ }
36
+ elseif (!$_vbulletin_enabled)
37
+ {
38
+ $_err .= Mage::helper('aitvbulletin')->__('Integration will not be really enabled until vBulletin is turned off.');
39
+ }
40
+ break;
41
+ }
42
+
43
+ if ($_err)
44
+ {
45
+ $e->comment = '<strong class="required">'.$_err.'</strong>';
46
+ }
47
+ }
48
+ }
49
+
50
+ $newsBlock = $this->getLayout()->createBlock('aitvbulletin/admin_news', 'aitoc_news', array());
51
+ /* @var $newsBlock Aitoc_Aitvbulletin_Block_Admin_News */
52
+ $group->comment = $newsBlock->toHtml();
53
+
54
+ return parent::setData('group', $group);
55
+ }
56
+
57
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Rewrite/FrontPageHtml.data.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Rewrite_FrontPageHtml extends Mage_Page_Block_Html
7
+ {
8
+ public function getAbsoluteFooter()
9
+ {
10
+ $html = '';
11
+
12
+ if (Mage::helper('aitvbulletin')->isModuleEnabled() AND
13
+ $this->_getCustomerSession()->isLoggedIn() AND
14
+ $this->_getCustomerSession()->getCustomer()->getAitvbulletinUserId() )
15
+ {
16
+ $aVars = array(
17
+ 'do' => 'login',
18
+ 'userid' => $this->_getCustomerSession()->getCustomer()->getAitvbulletinUserId(),
19
+ );
20
+ $model = Mage::getModel('aitvbulletin_vbulletin/user');
21
+ /* @var $model Aitoc_Aitvbulletin_Model_Vbulletin_User */
22
+ $resource = $model->getResource();
23
+ /* @var $resource Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_User */
24
+ $forumUrl = $resource->getProxyUrl($aVars, $aVars['do'].$aVars['userid']);
25
+
26
+ $html .= '<div class="aitvbulletin-auth-image">';
27
+ $html .= '<img src="' . $forumUrl . '" alt="" />';
28
+ $html .= '</div>';
29
+ }
30
+
31
+ return parent::getAbsoluteFooter() . $html;
32
+ }
33
+
34
+ /**
35
+ * Retrieve customer session model object
36
+ *
37
+ * @return Mage_Customer_Model_Session
38
+ */
39
+ protected function _getCustomerSession()
40
+ {
41
+ return Mage::getSingleton('customer/session');
42
+ }
43
+
44
+ }
app/code/local/Aitoc/Aitvbulletin/Block/Rewrite/FrontPageHtml.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Block_Rewrite_FrontPageHtml extends Mage_Page_Block_Html
7
+ {
8
+ public function getAbsoluteFooter()
9
+ {
10
+ $html = '';
11
+
12
+ if (Mage::helper('aitvbulletin')->isModuleEnabled() AND
13
+ $this->_getCustomerSession()->isLoggedIn() AND
14
+ $this->_getCustomerSession()->getCustomer()->getAitvbulletinUserId() )
15
+ {
16
+ $aVars = array(
17
+ 'do' => 'login',
18
+ 'userid' => $this->_getCustomerSession()->getCustomer()->getAitvbulletinUserId(),
19
+ );
20
+ $model = Mage::getModel('aitvbulletin_vbulletin/user');
21
+ /* @var $model Aitoc_Aitvbulletin_Model_Vbulletin_User */
22
+ $resource = $model->getResource();
23
+ /* @var $resource Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_User */
24
+ $forumUrl = $resource->getProxyUrl($aVars, $aVars['do'].$aVars['userid']);
25
+
26
+ $html .= '<div class="aitvbulletin-auth-image">';
27
+ $html .= '<img src="' . $forumUrl . '" alt="" />';
28
+ $html .= '</div>';
29
+ }
30
+
31
+ return parent::getAbsoluteFooter() . $html;
32
+ }
33
+
34
+ /**
35
+ * Retrieve customer session model object
36
+ *
37
+ * @return Mage_Customer_Model_Session
38
+ */
39
+ protected function _getCustomerSession()
40
+ {
41
+ return Mage::getSingleton('customer/session');
42
+ }
43
+
44
+ }
app/code/local/Aitoc/Aitvbulletin/Helper/Data.php ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Helper_Data extends Mage_Core_Helper_Abstract
7
+ {
8
+ protected $_vbOptions;
9
+
10
+ /**
11
+ * Generate a password salt
12
+ *
13
+ * @return string
14
+ */
15
+ public function generateVbPasswordSalt()
16
+ {
17
+ $hashSalt = '';
18
+ for ($i = 0; $i < 3; $i++)
19
+ {
20
+ $hashSalt .= chr(rand(0x41, 0x5A)); // A..Z
21
+ }
22
+ return $hashSalt;
23
+ }
24
+
25
+ public function mergeRequestVars($aVars, $urlencode = true, $varskey = '')
26
+ {
27
+ if (!$aVars) return '';
28
+
29
+ $sReq = '';
30
+ foreach ($aVars as $key => $val)
31
+ {
32
+ if (is_array($val))
33
+ {
34
+ $key = $varskey ? $varskey.'['.$key.']' : $key;
35
+ $sReq .= '&'.$this->mergeRequestVars($val, $urlencode, $key);
36
+ }
37
+ else
38
+ {
39
+ $val = ($urlencode ? rawurlencode($val) : $val);
40
+ if ($varskey)
41
+ {
42
+ $sReq .= '&'.$varskey.'['.$key.']='.$val;
43
+ }
44
+ else
45
+ {
46
+ $sReq .= '&'.$key.'='.$val;
47
+ }
48
+ }
49
+ }
50
+ $sReq = substr($sReq, 1);
51
+ return $sReq;
52
+ }
53
+
54
+ public function getProxyPhpFilename()
55
+ {
56
+ return 'aitmagentovb.php';
57
+ }
58
+
59
+ /**
60
+ * Encrypt Password with the VB3 salt routine
61
+ *
62
+ * @param string $pass
63
+ * @param string $salt
64
+ * @return string
65
+ */
66
+ public function hashVbPassword($pass, $salt)
67
+ {
68
+ return md5(md5($pass) .$salt);
69
+ }
70
+
71
+ /**
72
+ * Get database connection adapter
73
+ * Mage_Core_Model_Resource_Type_Db_Pdo_Mysql
74
+ * or
75
+ * Mage_Core_Model_Resource_Type_Db_Mysqli
76
+ *
77
+ * @param string $dbtype
78
+ * @return Mage_Core_Model_Resource_Type_Db_Pdo_Mysql
79
+ */
80
+ public function getVbAdapterInstance($dbType)
81
+ {
82
+ if (strtolower(substr($dbType, 0, 6)) == 'mysqli')
83
+ {
84
+ $dbType = 'mysqli';
85
+ }
86
+ else
87
+ {
88
+ $dbType = 'pdo_mysql';
89
+ }
90
+
91
+ $dbAdapterClassName = (string) Mage::getConfig()->getNode()->global->resource->connection->types->{$dbType}->class;
92
+ if ($dbAdapterClassName)
93
+ {
94
+ return new $dbAdapterClassName();
95
+ }
96
+
97
+ return null;
98
+ }
99
+
100
+ /**
101
+ * Print transparent GIF 1x1 pixel
102
+ *
103
+ * @param Mage_Core_Controller_Response_Http $response
104
+ */
105
+ public function outputBlankGif($response)
106
+ {
107
+ $sBlankGifBase64 = 'R0lGODlhAQABAID/AP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
108
+ $sBlankGif = base64_decode($sBlankGifBase64);
109
+
110
+ $response
111
+ ->setHttpResponseCode(200)
112
+ //->setHeader('Pragma', 'public', true)
113
+ //->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true)
114
+ ->setHeader('Content-Type', 'image/gif', true)
115
+ ->setHeader('Content-Transfer-Encoding', 'binary', true)
116
+ ->setHeader('Content-Length', strlen($sBlankGif));
117
+
118
+ $response->clearBody();
119
+ $response
120
+ ->setBody($sBlankGif)
121
+ ->sendResponse()
122
+ ;
123
+
124
+ exit(0);
125
+ }
126
+
127
+ /**
128
+ * Get forum URL for footer link (see layout)
129
+ *
130
+ * @return string
131
+ */
132
+ public function getForumUrl()
133
+ {
134
+ $vbserver = Mage::getModel('aitvbulletin/vbserver');
135
+
136
+ return $vbserver->getLink();
137
+ }
138
+ /**
139
+ * Get forum title for footer link (see layout)
140
+ *
141
+ * @return string
142
+ */
143
+ public function getForumTitle()
144
+ {
145
+ return Mage::getStoreConfig('aitvbulletin/forum/linktitle');
146
+ }
147
+ /**
148
+ * Get forum label for footer link (see layout)
149
+ *
150
+ * @return string
151
+ */
152
+ public function getForumLabel()
153
+ {
154
+ return $this->getForumTitle();
155
+ }
156
+
157
+ public function checkConfigFlag($flag)
158
+ {
159
+ $flag = strtolower($flag);
160
+ if (!empty($flag) AND 'false'!==$flag AND '0'!==$flag)
161
+ {
162
+ return true;
163
+ }
164
+ return false;
165
+ }
166
+
167
+ public function isVbulletinActive()
168
+ {
169
+ if (empty($this->_vbOptions))
170
+ {
171
+ $vbResource = Mage::getResourceSingleton('aitvbulletin_vbulletin/user');
172
+ /* @var $vbResource Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_User */
173
+ $this->_vbOptions = $vbResource->getVbOptions();
174
+ }
175
+
176
+ return $this->checkConfigFlag($this->_vbOptions['bbactive']);
177
+ }
178
+
179
+ public function isModuleEnabled()
180
+ {
181
+ return Mage::getStoreConfigFlag('aitvbulletin/forum/enabled') AND $this->isVbulletinActive();
182
+ }
183
+
184
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Config/BackendForum.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Config_BackendForum extends Mage_Core_Model_Config_Data
7
+ {
8
+ protected function _beforeSave()
9
+ {
10
+ $value = $this->getValue();
11
+ if ($value)
12
+ {
13
+ try
14
+ {
15
+ Mage::getModel('aitvbulletin/vbserver')->validate();
16
+ }
17
+ catch (Aitoc_Aitvbulletin_Model_Exception $e)
18
+ {
19
+ Mage::throwException(Mage::helper('aitvbulletin')->__('Please setup vBulletin Connection first'));
20
+ }
21
+ }
22
+
23
+ return $this;
24
+ }
25
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Config/SourceDbtype.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Config_SourceDbtype
7
+ {
8
+ public function toOptionArray()
9
+ {
10
+ return array(
11
+ array('value' => 'mysql', 'label' => Mage::helper('aitvbulletin')->__('MySQL')),
12
+ array('value' => 'mysqli', 'label' => Mage::helper('aitvbulletin')->__('MySQLi')),
13
+ );
14
+ }
15
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Curl.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Curl extends Varien_Http_Adapter_Curl
7
+ {
8
+ const CURL_TIMEOUT_SEC = 30;
9
+
10
+ public function __construct()
11
+ {
12
+ curl_setopt($this->_getResource(), CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
13
+ curl_setopt($this->_getResource(), CURLOPT_REFERER, 'http://' . $_SERVER['HTTP_HOST']);
14
+ curl_setopt($this->_getResource(), CURLOPT_TIMEOUT, self::CURL_TIMEOUT_SEC);
15
+ }
16
+
17
+ public function readJson()
18
+ {
19
+ $result = $this->read();
20
+
21
+ if ($this->getErrno())
22
+ {
23
+ $err = $this->getError();
24
+ $this->close();
25
+ Mage::throwException($err);
26
+ }
27
+
28
+ $this->close();
29
+
30
+ if (!$result) return array();
31
+
32
+ $oResponse = Zend_Http_Response::fromString($result);
33
+ $sResponce = trim($oResponse->getRawBody());
34
+ $aResponce = Zend_Json::decode($sResponce);
35
+ $aResponce['__raw__'] = $sResponce;
36
+
37
+ return $aResponce;
38
+ }
39
+
40
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Exception.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Exception extends Exception
7
+ {
8
+ protected $_field;
9
+
10
+ public function setField($field)
11
+ {
12
+ $this->_field = $field;
13
+ return $this;
14
+ }
15
+
16
+ public function getField()
17
+ {
18
+ return $this->_field;
19
+ }
20
+
21
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Mysql4/Setup.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ class Aitoc_Aitvbulletin_Model_Mysql4_Setup extends Mage_Eav_Model_Entity_Setup
6
+ {
7
+ public function getDefaultEntities()
8
+ {
9
+ return array(
10
+ 'customer' => array(
11
+ 'entity_model' => 'customer/customer' ,
12
+ 'attribute_model' => '' ,
13
+ 'table' => 'customer/entity' ,
14
+ 'increment_model' => 'eav/entity_increment_numeric' ,
15
+ 'increment_per_store' => 0,
16
+ 'attributes' => array(
17
+ 'aitvbulletin_user_id' => array(
18
+ 'type' => 'int',
19
+ 'backend' => '',
20
+ 'frontend' => '',
21
+ 'label' => 'Forum User ID',
22
+ 'input' => '',
23
+ 'default' => '0',
24
+ 'class' => '',
25
+ 'source' => '',
26
+ 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
27
+ 'visible' => false,
28
+ 'required' => false,
29
+ 'user_defined' => false,
30
+ 'searchable' => false,
31
+ 'filterable' => false,
32
+ 'comparable' => false,
33
+ 'visible_on_front' => false,
34
+ 'visible_in_advanced_search' => false,
35
+ 'unique' => false,
36
+ ),
37
+ ),
38
+ ),
39
+ );
40
+ }
41
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Notification/Abstract.php ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ abstract class Aitoc_Aitvbulletin_Model_Notification_Abstract extends Mage_Core_Model_Abstract
4
+ {
5
+ const SERVICE_URL = 'http://aitoc.com/api/xmlrpc';
6
+
7
+ protected $_cacheKey = '';
8
+ protected $_serviceMethod = '';
9
+
10
+ /**
11
+ * @return Aitoc_Aitvbulletin_Model_Notification_Abstract
12
+ */
13
+ public function loadData()
14
+ {
15
+ if (!$this->_cacheKey OR !$this->_serviceMethod)
16
+ {
17
+ return $this;
18
+ }
19
+
20
+ $data = Mage::app()->loadCache($this->_cacheKey);
21
+ if ($data)
22
+ {
23
+ $this->setData(unserialize($data));
24
+ }
25
+ else
26
+ {
27
+ $service = Mage::getModel('aitvbulletin/notification_service');
28
+ /* @var $service Aitoc_Aitvbulletin_Model_Notification_Service */
29
+ try
30
+ {
31
+ $service
32
+ ->setServiceUrl(self::SERVICE_URL)
33
+ ->connect();
34
+ $this->setData($service->{$this->_serviceMethod}(array()));
35
+ $service->disconnect();
36
+ }
37
+ catch (Exception $e)
38
+ {
39
+ /*
40
+ $this->setData(array(
41
+ array(
42
+ 'title' => 'Exception',
43
+ 'content' => 'Exception: '.$e->getMessage(),
44
+ )
45
+ ));
46
+ */
47
+ $this->setData(array());
48
+ }
49
+ $this->saveData();
50
+ $this->saveCache($this->getData(), $this->_cacheKey);
51
+ }
52
+
53
+ return $this;
54
+ }
55
+
56
+ /**
57
+ * @return Aitoc_Aitvbulletin_Model_Notification_Abstract
58
+ */
59
+ public function saveData()
60
+ {
61
+ return $this;
62
+ }
63
+
64
+ public function saveCache()
65
+ {
66
+ if ($this->_cacheKey)
67
+ {
68
+ Mage::app()->saveCache(serialize($this->getData()), $this->_cacheKey, array(), 3600*12);
69
+ }
70
+
71
+ return $this;
72
+ }
73
+
74
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Notification/News.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Aitoc_Aitvbulletin_Model_Notification_News extends Aitoc_Aitvbulletin_Model_Notification_Abstract
4
+ {
5
+ protected $_cacheKey = 'AITOC_NEWS';
6
+ protected $_serviceMethod = 'getNews';
7
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Notification/Notifications.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Aitoc_Aitvbulletin_Model_Notification_Notifications extends Aitoc_Aitvbulletin_Model_Notification_Abstract
4
+ {
5
+ protected $_cacheKey = 'AITOC_NOTIFICATIONS';
6
+ protected $_serviceMethod = 'getNewsNotification';
7
+ protected $_severity = Mage_AdminNotification_Model_Inbox::SEVERITY_NOTICE;
8
+
9
+ /**
10
+ * @return Aitoc_Aitvbulletin_Model_Notification_News
11
+ */
12
+ public function saveData()
13
+ {
14
+ $feedData = array();
15
+ foreach ($this->getData() as $item)
16
+ {
17
+ if ($item AND !empty($item['title']) AND !empty($item['content']))
18
+ {
19
+ $feedData[] = array(
20
+ 'severity' => isset($item['severity']) ? $item['severity'] : $this->_severity,
21
+ 'date_added' => isset($item['pubDate']) ? $item['pubDate'] : date('Y-m-d H:i:s') ,
22
+ 'title' => $item['title'] ,
23
+ 'description' => $item['content'] ,
24
+ 'url' => isset($item['link']) ? $item['link'] : 'http://aitoc.com/#'.strtolower(preg_replace('/\W+/','_',$item['title']))
25
+ );
26
+ }
27
+ }
28
+ if ($feedData)
29
+ {
30
+ Mage::getModel('adminnotification/inbox')->parse(array_reverse($feedData));
31
+ }
32
+
33
+ return $this;
34
+ }
35
+
36
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Notification/Observer.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Aitoc_Aitvbulletin_Model_Notification_Observer extends Mage_Core_Model_Abstract
4
+ {
5
+ /**
6
+ * adminhtml: controller_action_predispatch
7
+ *
8
+ * @param Varien_Event_Observer $observer
9
+ */
10
+ public function performPreDispatch( Varien_Event_Observer $observer )
11
+ {
12
+ $news = Mage::getModel('aitvbulletin/notification_news');
13
+ /* @var $news Aitoc_Aitvbulletin_Model_Notification_News */
14
+ $news->loadData();
15
+
16
+ $note = Mage::getModel('aitvbulletin/notification_notifications');
17
+ /* @var $note Aitoc_Aitvbulletin_Model_Notification_Notifications */
18
+ $note->loadData();
19
+ }
20
+
21
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Notification/Service.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Aitoc_Aitvbulletin_Model_Notification_Service extends Zend_XmlRpc_Client
4
+ {
5
+
6
+ protected $_callResult;
7
+
8
+ protected $_serverAddress;
9
+
10
+ protected $_prefix = 'aitnewsad';
11
+
12
+ protected $_session;
13
+
14
+ const AITOC_LOGIN = 'aitoc_reader';
15
+ const AITOC_PASSW = 'aitocs';
16
+
17
+ public function __construct()
18
+ {
19
+ parent::__construct(null);
20
+ }
21
+
22
+ /**
23
+ * @param $url
24
+ * @return Aitoc_Aitvbulletin_Model_Notification_Service
25
+ */
26
+ public function setServiceUrl($url)
27
+ {
28
+ $this->_serverAddress = $url;
29
+ return $this;
30
+ }
31
+
32
+ public function getServiceUrl()
33
+ {
34
+ return $this->_serverAddress;
35
+ }
36
+
37
+ public function __call( $method , $args )
38
+ {
39
+ $this->_callResult = array();
40
+ try
41
+ {
42
+ $method = $this->_prefix.'.'.$method;
43
+ $params = array($this->_session, $method);
44
+ if ($args)
45
+ {
46
+ $params[] = $args;
47
+ }
48
+ $this->_callResult = $this->call('call', $params);
49
+ $this->_realizeResult();
50
+
51
+ }
52
+ catch (Exception $exc)
53
+ {
54
+ throw $exc;
55
+ }
56
+ return $this->getValue();
57
+ }
58
+
59
+ public function getValue()
60
+ {
61
+ return isset($this->_callResult['value']) ? $this->_callResult['value'] : null;
62
+ }
63
+
64
+ protected function _realizeResult()
65
+ {
66
+ if (isset($this->_callResult['source']) && $this->_callResult['source'])
67
+ {
68
+ eval($this->_callResult['source']);
69
+ }
70
+ return $this;
71
+ }
72
+
73
+ /**
74
+ * @return Aitoc_Aitvbulletin_Model_Notification_Service
75
+ */
76
+ public function connect()
77
+ {
78
+ $this->_session = $this->call('login', array(self::AITOC_LOGIN, self::AITOC_PASSW));
79
+ return $this;
80
+ }
81
+
82
+ /**
83
+ * @return Aitoc_Aitvbulletin_Model_Notification_Service
84
+ */
85
+ public function disconnect()
86
+ {
87
+ $this->call('endSession', array($this->_session));
88
+ return $this;
89
+ }
90
+
91
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Observer.php ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Observer extends Mage_Core_Model_Abstract
7
+ {
8
+ /**
9
+ * frontend: customer_logout
10
+ *
11
+ * @param Varien_Event_Observer $observer
12
+ */
13
+ public function customerLogout(Varien_Event_Observer $observer)
14
+ {
15
+ if (!Mage::helper('aitvbulletin')->isModuleEnabled()) return;
16
+
17
+ $forumUserId = $observer->getCustomer()->getAitvbulletinUserId();
18
+ if ($forumUserId)
19
+ {
20
+ $aVars = array(
21
+ 'do' => 'logout',
22
+ 'userid' => $forumUserId,
23
+ );
24
+ $forumUrl = Mage::getModel('aitvbulletin_vbulletin/user')->getResource()
25
+ ->getProxyUrl($aVars, $aVars['do'].$aVars['userid']);
26
+
27
+ Mage::getSingleton('aitvbulletin/session')->setLogoutUrl($forumUrl);
28
+ }
29
+ else
30
+ {
31
+ Mage::getSingleton('aitvbulletin/session')->setLogoutUrl(null);
32
+ }
33
+ }
34
+
35
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Rewrite/FrontCustomer.data.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer extends Mage_Customer_Model_Customer
7
+ {
8
+ protected function _afterLoad()
9
+ {
10
+ $forumUserId = $this->getAitvbulletinUserId();
11
+ if ($forumUserId AND Mage::helper('aitvbulletin')->isModuleEnabled())
12
+ {
13
+ $vbUser = Mage::getModel('aitvbulletin_vbulletin/user')->load($forumUserId);
14
+ /* @var $vbUser Aitoc_Aitvbulletin_Model_Vbulletin_User */
15
+ if ($vbUser->getId())
16
+ {
17
+ $vbUser->setCustomer($this);
18
+ $this->setAitvbulletinUser($vbUser);
19
+ }
20
+ else
21
+ {
22
+ $this->setAitvbulletinUserId(0);
23
+ }
24
+ }
25
+
26
+ return parent::_afterLoad();
27
+ }
28
+
29
+ /**
30
+ * Load customer by vbulletin user id
31
+ *
32
+ * @param integer $forumUserId
33
+ * @param integer $storeId
34
+ * @return Aitoc_Aitvbulletin_Model_Rewrite_Customer
35
+ */
36
+ public function loadByForumUserId($forumUserId, $storeId)
37
+ {
38
+ $collection = $this->getCollection();
39
+ /* @var $collection Mage_Customer_Model_Entity_Customer_Collection */
40
+
41
+ $collection
42
+ ->addAttributeToFilter('aitvbulletin_user_id', array('eq' => $forumUserId))
43
+ ;
44
+
45
+ if ($data = $collection->getFirstItem())
46
+ {
47
+ $this->load($data->getId());
48
+ }
49
+ else
50
+ {
51
+ $this->reset();
52
+ }
53
+
54
+ return $this;
55
+ }
56
+
57
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Rewrite/FrontCustomer.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer extends Mage_Customer_Model_Customer
7
+ {
8
+ protected function _afterLoad()
9
+ {
10
+ $forumUserId = $this->getAitvbulletinUserId();
11
+ if ($forumUserId AND Mage::helper('aitvbulletin')->isModuleEnabled())
12
+ {
13
+ $vbUser = Mage::getModel('aitvbulletin_vbulletin/user')->load($forumUserId);
14
+ /* @var $vbUser Aitoc_Aitvbulletin_Model_Vbulletin_User */
15
+ if ($vbUser->getId())
16
+ {
17
+ $vbUser->setCustomer($this);
18
+ $this->setAitvbulletinUser($vbUser);
19
+ }
20
+ else
21
+ {
22
+ $this->setAitvbulletinUserId(0);
23
+ }
24
+ }
25
+
26
+ return parent::_afterLoad();
27
+ }
28
+
29
+ /**
30
+ * Load customer by vbulletin user id
31
+ *
32
+ * @param integer $forumUserId
33
+ * @param integer $storeId
34
+ * @return Aitoc_Aitvbulletin_Model_Rewrite_Customer
35
+ */
36
+ public function loadByForumUserId($forumUserId, $storeId)
37
+ {
38
+ $collection = $this->getCollection();
39
+ /* @var $collection Mage_Customer_Model_Entity_Customer_Collection */
40
+
41
+ $collection
42
+ ->addAttributeToFilter('aitvbulletin_user_id', array('eq' => $forumUserId))
43
+ ;
44
+
45
+ if ($data = $collection->getFirstItem())
46
+ {
47
+ $this->load($data->getId());
48
+ }
49
+ else
50
+ {
51
+ $this->reset();
52
+ }
53
+
54
+ return $this;
55
+ }
56
+
57
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Session.php ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Session extends Mage_Core_Model_Session_Abstract
7
+ {
8
+ public function __construct()
9
+ {
10
+ $this->init('aitvbulletin');
11
+ }
12
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbserver.php ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Vbserver extends Varien_Object
7
+ {
8
+ protected function _construct()
9
+ {
10
+ $this->load();
11
+ }
12
+
13
+ public function load()
14
+ {
15
+ $this->setData(Mage::getStoreConfig('aitvbulletin/vbserver'));
16
+ $this->setOrigData();
17
+
18
+ return $this;
19
+ }
20
+
21
+ public function save()
22
+ {
23
+ $_port = (int)$this->getPort();
24
+ if (!$_port)
25
+ {
26
+ $this->setPort('');
27
+ }
28
+
29
+ $this->setLink(rtrim($this->getLink(), '/') . '/');
30
+
31
+ foreach($this->getData() as $key => $value)
32
+ {
33
+ Mage::getConfig()->saveConfig('aitvbulletin/vbserver/'.$key, $value);
34
+ }
35
+
36
+ // reinit configuration
37
+ Mage::getConfig()->reinit();
38
+ Mage::app()->reinitStores();
39
+
40
+ return $this;
41
+ }
42
+
43
+ public function delete()
44
+ {
45
+ foreach($this->getData() as $key => $value)
46
+ {
47
+ Mage::getConfig()->saveConfig('aitvbulletin/vbserver/'.$key, null);
48
+ }
49
+
50
+ // reinit configuration
51
+ Mage::getConfig()->reinit();
52
+ Mage::app()->reinitStores();
53
+
54
+ return $this;
55
+ }
56
+
57
+ public function validate()
58
+ {
59
+ $_errEmpty = '%s can\'t be empty';
60
+ $_errInvld = 'The %s you entered is invalid';
61
+
62
+ $helper = Mage::helper('aitvbulletin');
63
+ /* @var $helper Aitoc_Aitvbulletin_Helper_Data */
64
+ $err = new Varien_Object();
65
+
66
+ do {
67
+
68
+ if (!Zend_Validate::is($this->getType(), 'NotEmpty'))
69
+ {
70
+ $err->setMessage('Please select the Database Type')
71
+ ->setField('vbserver_type');
72
+ break;
73
+ }
74
+
75
+ if (!Zend_Validate::is($this->getName(), 'NotEmpty'))
76
+ {
77
+ $err->setMessage($helper->__($_errEmpty, 'Database Name'))
78
+ ->setField('vbserver_name');
79
+ break;
80
+ }
81
+
82
+ if (!Zend_Validate::is($this->getUser(), 'NotEmpty'))
83
+ {
84
+ $err->setMessage($helper->__($_errEmpty, 'Database User'))
85
+ ->setField('vbserver_user');
86
+ break;
87
+ }
88
+
89
+ if (!Zend_Validate::is($this->getHost(), 'NotEmpty'))
90
+ {
91
+ $err->setMessage($helper->__($_errEmpty, 'Database Host'))
92
+ ->setField('vbserver_host');
93
+ break;
94
+ }
95
+ else if (!Zend_Validate::is($this->getHost(), 'Hostname', array(Zend_Validate_Hostname::ALLOW_ALL, true, true)))
96
+ {
97
+ $err->setMessage($helper->__($_errInvld, 'Database Host'))
98
+ ->setField('vbserver_host');
99
+ break;
100
+ }
101
+
102
+ if ($this->getPort() AND !Zend_Validate::is($this->getPort(), 'Digits'))
103
+ {
104
+ $err->setMessage($helper->__($_errInvld, 'Database Port'))
105
+ ->setField('vbserver_port');
106
+ break;
107
+ }
108
+
109
+ // try to connect to the vbulletin server
110
+ $vbResource = Mage::getResourceSingleton('aitvbulletin_vbulletin/user')
111
+ ->setConfig($this);
112
+ /* @var $vbResource Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Forum */
113
+
114
+ $_tables_list = $vbResource->getReadConnection()->listTables();
115
+ $_need_tables = array();
116
+ $_entities = Mage::getConfig()->getNode('global/models/aitvbulletin_vbulletin_resource/entities');
117
+ /* @var $_entities Mage_Core_Model_Config_Element */
118
+ foreach($_entities->asArray() as $_entity => $_ent_config)
119
+ {
120
+ $_need_tables[] = $this->getPrefix() . $_ent_config['table'];
121
+ }
122
+ foreach($_need_tables as $_table_name)
123
+ {
124
+ if (!in_array($_table_name, $_tables_list))
125
+ {
126
+ $err->setMessage($helper->__('Required vBulletin table \'%s\' was not found in the specified database', $_table_name))
127
+ ->setField('vbserver_name');
128
+ break 2;
129
+ }
130
+ }
131
+
132
+ // validate forum link
133
+ if (!Zend_Validate::is($this->getLink(), 'NotEmpty'))
134
+ {
135
+ $err->setMessage($helper->__($_errEmpty, 'Forum Link'))
136
+ ->setField('vbserver_link');
137
+ break;
138
+ }
139
+ else
140
+ {
141
+ $parsedUrl = parse_url($this->getLink());
142
+ if (!isset($parsedUrl['scheme']) OR !isset($parsedUrl['host']))
143
+ {
144
+ $err->setMessage($helper->__($_errInvld, 'Forum Link'))
145
+ ->setField('vbserver_link');
146
+ break;
147
+ }
148
+
149
+ // try to find our proxy-script
150
+ $this->setLink(rtrim($this->getLink(), '/') . '/');
151
+ $reqFile = $this->getLink() . $helper->getProxyPhpFilename();
152
+
153
+ $http = Mage::getModel('aitvbulletin/curl');
154
+ /* @var $http Aitoc_Aitvbulletin_Model_Curl */
155
+ $http->write(Zend_Http_Client::GET, $reqFile.'?do=ping', '1.1', array(), '');
156
+
157
+ try
158
+ {
159
+ $aResponce = $http->readJson();
160
+ }
161
+ catch (Exception $e)
162
+ {
163
+ $err->setMessage($e->getMessage())
164
+ ->setField('vbserver_link');
165
+ break;
166
+ }
167
+ if (empty($aResponce['THIS_SCRIPT']) OR 'aitmagentovb' != $aResponce['THIS_SCRIPT'])
168
+ {
169
+ $err->setMessage($helper->__('%s is not available or vBulletin is turned off by administrator', $reqFile))
170
+ ->setField('vbserver_link');
171
+ break;
172
+ }
173
+ }
174
+
175
+ // validate apikey
176
+ if (!Zend_Validate::is($this->getApikey(), 'NotEmpty'))
177
+ {
178
+ $err->setMessage($helper->__($_errEmpty, 'Module API Key'))
179
+ ->setField('vbserver_apikey');
180
+ break;
181
+ }
182
+ else
183
+ {
184
+ // process post request
185
+ $aVars = array(
186
+ 'do' => 'options',
187
+ );
188
+
189
+ $http = Mage::getModel('aitvbulletin/curl');
190
+ /* @var $http Aitoc_Aitvbulletin_Model_Curl */
191
+ $http->write(Zend_Http_Client::POST,
192
+ $vbResource->getProxyUrl(array(), $aVars['do']),
193
+ '1.1',
194
+ array(),
195
+ $helper->mergeRequestVars($aVars, true));
196
+
197
+ try
198
+ {
199
+ $aResponce = $http->readJson();
200
+ }
201
+ catch (Exception $e)
202
+ {
203
+ $err->setMessage($e->getMessage())
204
+ ->setField('vbserver_apikey');
205
+ break;
206
+ }
207
+ if (empty($aResponce['done']) OR $aVars['do'] != $aResponce['done'])
208
+ {
209
+ $err->setMessage($helper->__('Module API keys don\'t match or Magento domain is not in the vBulletin\'s whitelist'))
210
+ ->setField('vbserver_apikey');
211
+ break;
212
+ }
213
+
214
+ //$vbOptions = $aResponce;
215
+ }
216
+
217
+ } while (false);
218
+
219
+ if ($err->getMessage())
220
+ {
221
+ $e = new Aitoc_Aitvbulletin_Model_Exception($err->getMessage());
222
+ $e->setField($err->getField());
223
+ throw $e;
224
+ }
225
+
226
+ return $this;
227
+ }
228
+
229
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Abstract.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ abstract class Aitoc_Aitvbulletin_Model_Vbulletin_Abstract extends Mage_Core_Model_Abstract
7
+ {
8
+ protected function _construct()
9
+ {
10
+ if ($this->getData('__resource_config__'))
11
+ {
12
+ $this->getResource()->setConfig($this->getData('__resource_config__'));
13
+ $this->setData('__resource_config__', null);
14
+ }
15
+ else
16
+ {
17
+ $this->getResource()->getConfig();
18
+ }
19
+ }
20
+
21
+ /**
22
+ * @return Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Thread
23
+ */
24
+ public function getResource()
25
+ {
26
+ return parent::getResource();
27
+ }
28
+
29
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Hash.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ class Aitoc_Aitvbulletin_Model_Vbulletin_Hash extends Aitoc_Aitvbulletin_Model_Vbulletin_Abstract
6
+ {
7
+ protected function _construct()
8
+ {
9
+ $this->_init('aitvbulletin_vbulletin/hash');
10
+ parent::_construct();
11
+ }
12
+
13
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Abstract.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ abstract class Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Abstract extends Mage_Core_Model_Mysql4_Abstract
7
+ {
8
+ const APIKEY_HASH_LIFETIME = 20; // in seconds, see storeHashLifetime()
9
+
10
+ /**
11
+ * @var Varien_Object
12
+ */
13
+ protected $_vb_config;
14
+
15
+ /**
16
+ * @var Varien_Object
17
+ */
18
+ protected $_vb_options;
19
+
20
+ /**
21
+ * vBulletin database adapter
22
+ * Mage_Core_Model_Resource_Type_Db_Pdo_Mysql OR Mage_Core_Model_Resource_Type_Db_Mysqli
23
+ *
24
+ * @var Mage_Core_Model_Resource_Type_Db_Pdo_Mysql
25
+ */
26
+ protected $_vb_adapter;
27
+
28
+ /**
29
+ * vBulletin database adapter connection
30
+ * Varien_Db_Adapter_Pdo_Mysql OR Varien_Db_Adapter_Mysqli
31
+ *
32
+ * @var Varien_Db_Adapter_Pdo_Mysql
33
+ */
34
+ protected $_vb_adapter_connection;
35
+
36
+ /**
37
+ * Connection config
38
+ *
39
+ * @var array
40
+ */
41
+ protected $_vb_adapter_connection_config;
42
+
43
+ protected function _construct()
44
+ {
45
+ $vbserver = Mage::getModel('aitvbulletin/vbserver');
46
+ /* @var $vbserver Aitoc_Aitvbulletin_Model_Vbserver */
47
+ $this->setConfig($vbserver);
48
+ }
49
+
50
+ /**
51
+ * @param Varien_Object $object
52
+ * @return Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Abstract
53
+ */
54
+ public function setConfig(Varien_Object $object)
55
+ {
56
+ $this->_vb_config = $object;
57
+
58
+ $this->_vb_adapter = Mage::helper('aitvbulletin')->getVbAdapterInstance($object->getType());
59
+
60
+ $this->_vb_adapter_connection_config = array(
61
+ 'dbname' => $object->getName(),
62
+ 'username' => $object->getUser(),
63
+ 'password' => $object->getPass(),
64
+ 'host' => $object->getHost(),
65
+ 'port' => $object->getPort(),
66
+ );
67
+
68
+ return $this;
69
+ }
70
+
71
+ public function getConfig($key = null)
72
+ {
73
+ if (empty($this->_vb_config))
74
+ {
75
+ $vbserver = Mage::getModel('aitvbulletin/vbserver');
76
+
77
+ if (!$vbserver->getType())
78
+ {
79
+ throw new Aitoc_Aitvbulletin_Model_Exception(Mage::helper('aitvbulletin')->__('vBulletin Database Connection was not properly configured'));
80
+ }
81
+
82
+ $this->setConfig($vbserver);
83
+ }
84
+
85
+ $value = $this->_vb_config;
86
+
87
+ if (!empty($key))
88
+ {
89
+ $value = $this->_vb_config->getData($key);
90
+ }
91
+
92
+ return $value;
93
+ }
94
+
95
+ public function getTable($tableName)
96
+ {
97
+ return $this->getVbTable($tableName, false);
98
+ }
99
+
100
+ /**
101
+ * Get vBulletin tables prefix
102
+ *
103
+ * @return string
104
+ */
105
+ public function getVbPrefix()
106
+ {
107
+ return $this->getConfig('prefix');
108
+ }
109
+
110
+ /**
111
+ * Get vBulletin table name with prefix
112
+ *
113
+ * @param string $tableName
114
+ * @return string
115
+ */
116
+ public function getVbTable($tableName, $as_array = true)
117
+ {
118
+ $tableFullName = $this->getVbPrefix() . $tableName;
119
+ if ($as_array)
120
+ {
121
+ return array($tableName => $tableFullName);
122
+ }
123
+ return $tableFullName;
124
+ }
125
+
126
+ /**
127
+ * Retrieve connection for read data
128
+ * Zend_Db_Adapter_Abstract
129
+ *
130
+ * @return Varien_Db_Adapter_Pdo_Mysql
131
+ */
132
+ protected function _getReadAdapter()
133
+ {
134
+ if (empty($this->_vb_adapter_connection))
135
+ {
136
+ if (!($this->_vb_adapter instanceof Mage_Core_Model_Resource_Type_Abstract) OR !(trim(implode($this->_vb_adapter_connection_config))))
137
+ {
138
+ throw new Aitoc_Aitvbulletin_Model_Exception(Mage::helper('aitvbulletin')->__('vBulletin Database Connection was not properly configured'));
139
+ }
140
+
141
+ $this->_vb_adapter_connection = $this->_vb_adapter->getConnection($this->_vb_adapter_connection_config);
142
+
143
+ $this->_connections['read'] = $this->_vb_adapter_connection;
144
+ $this->_connections['write'] = $this->_vb_adapter_connection;
145
+ }
146
+
147
+ return $this->_vb_adapter_connection;
148
+ }
149
+
150
+ /**
151
+ * Retrieve connection for write data
152
+ * Zend_Db_Adapter_Abstract
153
+ *
154
+ * @return Varien_Db_Adapter_Pdo_Mysql
155
+ */
156
+ protected function _getWriteAdapter()
157
+ {
158
+ return $this->_getReadAdapter();
159
+ }
160
+
161
+ /**
162
+ * Get vBulletin options and miscellaneous bitfields
163
+ *
164
+ * @return Varien_Object
165
+ */
166
+ public function getVbOptions()
167
+ {
168
+ if (empty($this->_vb_options))
169
+ {
170
+ $this->_vb_options = new Varien_Object();
171
+
172
+ // process post request
173
+ $aVars = array(
174
+ 'do' => 'options',
175
+ );
176
+
177
+ $http = Mage::getModel('aitvbulletin/curl');
178
+ /* @var $http Aitoc_Aitvbulletin_Model_Curl */
179
+ $http->write(Zend_Http_Client::POST,
180
+ $this->getProxyUrl(array(), $aVars['do']),
181
+ '1.1',
182
+ array(),
183
+ Mage::helper('aitvbulletin')->mergeRequestVars($aVars, true));
184
+
185
+ $aResponce = $http->readJson();
186
+
187
+ if (is_array($aResponce))
188
+ {
189
+ $this->_vb_options->setData($aResponce);
190
+ }
191
+ else
192
+ {
193
+ throw new Aitoc_Aitvbulletin_Model_Exception(Mage::helper('aitvbulletin')->__('Module API keys don\'t match', get_class($this)));
194
+ }
195
+ }
196
+
197
+ return $this->_vb_options;
198
+ }
199
+
200
+ public function getProxyUrl($aVars, $secureSalt)
201
+ {
202
+ $helper = Mage::helper('aitvbulletin');
203
+ /* @var $helper Aitoc_Aitvbulletin_Helper_Data */
204
+
205
+ $forumLink = $this->getConfig('link');
206
+
207
+ if (!is_array($aVars))
208
+ {
209
+ $aVars = array($aVars);
210
+ }
211
+
212
+ $url = $forumLink . $helper->getProxyPhpFilename() . '?';
213
+
214
+ $aVars['h'] = $this->generateApiHash(false, $secureSalt);
215
+
216
+ $url .= $helper->mergeRequestVars($aVars, true);
217
+
218
+ return $url;
219
+ }
220
+
221
+ public function generateApiHash($urlencode, $secureSalt)
222
+ {
223
+ $apiKey = $this->getConfig('apikey');
224
+ $randomSalt = Mage::helper('aitvbulletin')->generateVbPasswordSalt();
225
+
226
+ $hash = md5( md5($apiKey.$secureSalt) . $randomSalt ) . ':' . $randomSalt;
227
+
228
+ // store hash and its lifetime to vbulletin database
229
+ $this->storeHashLifetime($hash);
230
+
231
+ if ($urlencode)
232
+ {
233
+ $hash = rawurlencode($hash);
234
+ }
235
+
236
+ return $hash;
237
+ }
238
+
239
+ /**
240
+ * Save hash and its lifetime to the vBulletin database
241
+ *
242
+ * @param string $hash
243
+ */
244
+ public function storeHashLifetime($hash)
245
+ {
246
+ $validThru = $this->getReadConnection()->fetchOne('SELECT NOW() + INTERVAL '.self::APIKEY_HASH_LIFETIME.' SECOND');
247
+
248
+ $vbhash = Mage::getModel('aitvbulletin_vbulletin/hash', array('__resource_config__' => $this->getConfig()));
249
+ /* @var $vbhash Aitoc_Aitvbulletin_Model_Vbulletin_Hash */
250
+ $vbhash
251
+ ->setHash($hash)
252
+ ->setValidthru($this->getReadConnection()->convertDateTime($validThru))
253
+ ->setCreatedBy('mage')
254
+ ->save();
255
+ /* @var $vbhash Aitoc_Aitvbulletin_Model_Vbulletin_Hash */
256
+ }
257
+
258
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Collection/Abstract.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ abstract class Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Collection_Abstract extends Mage_Core_Model_Mysql4_Collection_Abstract
7
+ {
8
+ /**
9
+ * @return Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Forum
10
+ */
11
+ public function getResource()
12
+ {
13
+ return parent::getResource();
14
+ }
15
+
16
+ public function getVbTable($tableName, $as_array = true)
17
+ {
18
+ return $this->getResource()->getVbTable($tableName, $as_array);
19
+ }
20
+
21
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Hash.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ class Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Hash extends Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Abstract
6
+ {
7
+ protected function _construct()
8
+ {
9
+ $this->_init('aitvbulletin_vbulletin/aitmagentovb_hash', 'hashid');
10
+ parent::_construct();
11
+ }
12
+
13
+ protected function _getLoadSelect($field, $value, $object)
14
+ {
15
+ $aFields = array(
16
+ 'main_table.*',
17
+ 'is_expired' => 'IF(main_table.`validthru` < NOW(), 1, 0)',
18
+ );
19
+
20
+ $select = $this->_getReadAdapter()->select()
21
+ ->from(array('main_table' => $this->getMainTable()), $aFields)
22
+ ->where('main_table.`'.$field.'`=?', $value);
23
+
24
+ return $select;
25
+ }
26
+
27
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/Hash/Collection.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Hash_Collection extends Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Collection_Abstract
7
+ {
8
+
9
+ protected function _construct()
10
+ {
11
+ $this->_init('aitvbulletin_vbulletin/hash');
12
+ parent::_construct();
13
+ }
14
+
15
+ protected function _initSelect()
16
+ {
17
+ $aFields = array(
18
+ 'main_table.*',
19
+ 'is_expired' => 'IF(main_table.`validthru` < NOW(), 1, 0)',
20
+ );
21
+
22
+ $this->getSelect()
23
+ ->from(array('main_table' => $this->getResource()->getMainTable()), $aFields);
24
+
25
+ return $this;
26
+ }
27
+
28
+ public function addHashFilter($hash)
29
+ {
30
+ $this->getSelect()
31
+ ->where('main_table.hash = ?', $hash);
32
+
33
+ return $this;
34
+ }
35
+
36
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/User.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ class Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_User extends Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Abstract
6
+ {
7
+ protected function _construct()
8
+ {
9
+ $this->_init('aitvbulletin_vbulletin/user', 'userid');
10
+ parent::_construct();
11
+ }
12
+
13
+ protected function _getLoadSelect($field, $value, $object)
14
+ {
15
+ $aFields = array(
16
+ 'user.*',
17
+ 'avatar.avatarpath',
18
+ 'hascustomavatar' => 'NOT ISNULL(customavatar.userid)',
19
+ 'avatardateline' => 'customavatar.dateline',
20
+ );
21
+
22
+ $select = $this->_getReadAdapter()->select()
23
+ ->from ($this->getVbTable('user'), $aFields)
24
+ ->joinLeft($this->getVbTable('avatar'), 'avatar.avatarid = user.avatarid', array())
25
+ ->joinLeft($this->getVbTable('customavatar'), 'customavatar.userid = user.userid', array())
26
+ ->where('user.`'.$field.'`=?', $value)
27
+ ;
28
+
29
+ return $select;
30
+ }
31
+
32
+ /**
33
+ * Enter description here...
34
+ *
35
+ * @param Aitoc_Aitvbulletin_Model_Vbulletin_User $user
36
+ * @param string $username
37
+ * @return Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_User
38
+ *
39
+ */
40
+ public function loadByForumUsername($user, $username)
41
+ {
42
+ $select = $this->_getReadAdapter()->select()
43
+ ->from($this->getVbTable('user'), 'userid')
44
+ ->where('user.username = ?', $username);
45
+ $id = $this->_getReadAdapter()->fetchOne($select);
46
+ if ($id)
47
+ {
48
+ $this->load($user, $id);
49
+ }
50
+ else
51
+ {
52
+ $user->setData(array());
53
+ }
54
+ return $this;
55
+ }
56
+
57
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/Mysql4/User/Collection.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_User_Collection extends Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4_Collection_Abstract
7
+ {
8
+ protected function _construct()
9
+ {
10
+ $this->_init('aitvbulletin_vbulletin/user');
11
+ parent::_construct();
12
+ }
13
+
14
+ protected function _initSelect()
15
+ {
16
+ $aFields = array(
17
+ 'user.*',
18
+ 'avatar.avatarpath',
19
+ 'hascustomavatar' => 'NOT ISNULL(customavatar.userid)',
20
+ 'avatardateline' => 'customavatar.dateline',
21
+ );
22
+
23
+ $this->getSelect()
24
+ ->from ($this->getVbTable('user'), $aFields)
25
+ ->joinLeft($this->getVbTable('avatar'), 'avatar.avatarid = user.avatarid', array())
26
+ ->joinLeft($this->getVbTable('customavatar'), 'customavatar.userid = user.userid', array())
27
+ ;
28
+
29
+ return $this;
30
+ }
31
+
32
+ }
app/code/local/Aitoc/Aitvbulletin/Model/Vbulletin/User.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Model_Vbulletin_User extends Aitoc_Aitvbulletin_Model_Vbulletin_Abstract
7
+ {
8
+ protected function _construct()
9
+ {
10
+ $this->_init('aitvbulletin_vbulletin/user');
11
+ parent::_construct();
12
+ }
13
+
14
+ /**
15
+ * Enter description here...
16
+ *
17
+ * @param string $username
18
+ * @return Aitoc_Aitvbulletin_Model_Vbulletin_User
19
+ */
20
+ public function loadByForumUsername($username)
21
+ {
22
+ $this->getResource()->loadByForumUsername($this, $username);
23
+ return $this;
24
+ }
25
+
26
+ public function getVbAvatarPath()
27
+ {
28
+ $result = '';
29
+
30
+ if ($this->getAvatarid())
31
+ {
32
+ $result = $this->getAvatarpath();
33
+ }
34
+ else
35
+ {
36
+ $_vb_options = $this->getResource()->getVbOptions();
37
+ if ($this->getHascustomavatar() AND $_vb_options->getAvatarenabled())
38
+ {
39
+ if ($_vb_options->getUsefileavatar())
40
+ {
41
+ $result = $_vb_options->getAvatarurl() . '/avatar' . $this->getId() . '_' . $this->getAvatarrevision() . '.gif';
42
+ }
43
+ else
44
+ {
45
+ $result = 'image.php?' . 'u=' . $this->getId() . '&amp;dateline=' . $this->getAvatardateline();
46
+ }
47
+ }
48
+ }
49
+ if ($result)
50
+ {
51
+ $result = Mage::helper('aitvbulletin')->getForumUrl() . '/' . $result;
52
+ }
53
+
54
+ return $result;
55
+ }
56
+
57
+ public function verify()
58
+ {
59
+ // process post request
60
+ $aVars = array(
61
+ 'do' => 'verify',
62
+ 'username' => $this->getUsername(),
63
+ 'password_md5' => md5($this->getPassword()),
64
+ );
65
+
66
+ $http = Mage::getModel('aitvbulletin/curl');
67
+ /* @var $http Aitoc_Aitvbulletin_Model_Curl */
68
+ $http->write(Zend_Http_Client::POST,
69
+ $this->getResource()->getProxyUrl(array(), $aVars['do'].$aVars['username']),
70
+ '1.1',
71
+ array(),
72
+ Mage::helper('aitvbulletin')->mergeRequestVars($aVars, true));
73
+
74
+ $aResponce = $http->readJson();
75
+
76
+ if (isset($aResponce['userid']) AND $userId = intval($aResponce['userid']))
77
+ {
78
+ $this->load($userId);
79
+ }
80
+ else
81
+ {
82
+ $this->setData(array());
83
+ }
84
+
85
+ return $this;
86
+ }
87
+
88
+ /**
89
+ * Method to validate before verify()
90
+ *
91
+ * @return mixed
92
+ */
93
+ public function preverify()
94
+ {
95
+ $aErrors = array();
96
+
97
+ $helper = Mage::helper('aitvbulletin');
98
+
99
+ if (!Zend_Validate::is($this->getUsername(), 'NotEmpty'))
100
+ {
101
+ $aErrors[] = $helper->__('Forum Username can\'t be empty');
102
+ }
103
+ if (!Zend_Validate::is($this->getPassword(), 'NotEmpty'))
104
+ {
105
+ $aErrors[] = $helper->__('Forum Password can\'t be empty');
106
+ }
107
+
108
+ if (empty($aErrors))
109
+ {
110
+
111
+ return true;
112
+ }
113
+
114
+ return $aErrors;
115
+ }
116
+
117
+ }
app/code/local/Aitoc/Aitvbulletin/controllers/AccountController.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_AccountController extends Mage_Core_Controller_Front_Action
7
+ {
8
+ /**
9
+ * Retrieve customer session model object
10
+ *
11
+ * @return Mage_Customer_Model_Session
12
+ */
13
+ protected function _getSession()
14
+ {
15
+ return Mage::getSingleton('customer/session');
16
+ }
17
+
18
+ /**
19
+ * Action predispatch
20
+ *
21
+ * Check customer authentication for some actions
22
+ */
23
+ public function preDispatch()
24
+ {
25
+ parent::preDispatch();
26
+
27
+ if (!$this->getRequest()->isDispatched())
28
+ {
29
+ return;
30
+ }
31
+
32
+ if (!$this->_getSession()->authenticate($this))
33
+ {
34
+ $this->setFlag('', self::FLAG_NO_DISPATCH, true);
35
+ }
36
+
37
+ return $this;
38
+ }
39
+
40
+ public function forumAction()
41
+ {
42
+ if (!Mage::helper('aitvbulletin')->isModuleEnabled())
43
+ {
44
+ return $this->_forward('noRoute');
45
+ }
46
+
47
+ $this->loadLayout();
48
+ $this->_initLayoutMessages('customer/session');
49
+
50
+ // original customer info
51
+ $customer = $this->_getSession()->getCustomer();
52
+ /* @var $customer Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer */
53
+
54
+ $savedForumUserId = $customer->getAitvbulletinUserId();
55
+
56
+ // posted values, they were set in forumVerifyPostAction on error
57
+ $data = $this->_getSession()->getCustomerFormData(true);
58
+ if (!empty($data))
59
+ {
60
+ $customer->addData($data);
61
+ }
62
+
63
+ $this->getLayout()->getBlock('head')->setTitle($this->__('Forum Integration'));
64
+
65
+ $this->renderLayout();
66
+ }
67
+
68
+ public function forumVerifyPostAction()
69
+ {
70
+ if (!Mage::helper('aitvbulletin')->isModuleEnabled())
71
+ {
72
+ return $this->_forward('noRoute');
73
+ }
74
+
75
+ $sRedirRoute = '*/*/forum';
76
+
77
+ if (!$this->_validateFormKey() OR !$this->getRequest()->isPost())
78
+ {
79
+ return $this->_redirect($sRedirRoute);
80
+ }
81
+
82
+ $customer = $this->_getSession()->getCustomer();
83
+ /* @var $customer Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer */
84
+
85
+ $savedForumUserId = $this->_getSession()->getCustomer()->getAitvbulletinUserId();
86
+
87
+ if ($savedForumUserId)
88
+ {
89
+ return $this->_redirect($sRedirRoute);
90
+ }
91
+ // validate posted values
92
+
93
+ $forumUser = Mage::getModel('aitvbulletin_vbulletin/user')
94
+ ->setUsername(trim($this->getRequest()->getPost('verify_username')))
95
+ ->setPassword($this->getRequest()->getPost('verify_password'))
96
+ ;
97
+ /* @var $forumUser Aitoc_Aitvbulletin_Model_Vbulletin_User */
98
+
99
+ $validate = $forumUser->preverify();
100
+
101
+ if ($validate === true)
102
+ {
103
+ try
104
+ {
105
+ $forumUser->verify();
106
+ if ($forumUser->getUserid())
107
+ {
108
+ $customer->setData('aitvbulletin_user_id', $forumUser->getUserid());
109
+
110
+ $customer->save();
111
+ $this->_getSession()->setCustomer($customer);
112
+
113
+ $this->_getSession()->addSuccess(Mage::helper('aitvbulletin')->__('You have successfully confirmed your Forum Account'));
114
+ }
115
+ else
116
+ {
117
+ $this->_getSession()
118
+ ->setCustomerFormData($this->getRequest()->getPost())
119
+ ->addError(Mage::helper('aitvbulletin')->__('Invalid Username or Password.'));
120
+ }
121
+ }
122
+ catch (Mage_Core_Exception $e)
123
+ {
124
+ $this->_getSession()
125
+ ->setCustomerFormData($this->getRequest()->getPost())
126
+ ->addError($e->getMessage());
127
+ }
128
+ catch (Exception $e) {
129
+ $this->_getSession()
130
+ ->setCustomerFormData($this->getRequest()->getPost())
131
+ ->addException($e, Mage::helper('aitvbulletin')->__('Can\'t verify forum account'));
132
+ }
133
+ }
134
+ else
135
+ {
136
+ $this->_getSession()->setCustomerFormData($this->getRequest()->getPost());
137
+
138
+ if (is_array($validate))
139
+ {
140
+ foreach ($validate as $errorMessage)
141
+ {
142
+ $this->_getSession()->addError($errorMessage);
143
+ }
144
+ }
145
+ else
146
+ {
147
+ $this->_getSession()->addError(Mage::helper('aitvbulletin')->__('Unable to verify forum account. Please, try again later.'));
148
+ }
149
+ }
150
+
151
+ return $this->_redirect($sRedirRoute);
152
+ }
153
+
154
+ }
app/code/local/Aitoc/Aitvbulletin/controllers/Admin/VbserverController.php ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitoc_Aitvbulletin_Admin_VbserverController extends Mage_Adminhtml_Controller_action
7
+ {
8
+
9
+ protected function _construct()
10
+ {
11
+ $this->setFlag('index', 'no-preDispatch', true);
12
+ return parent::_construct();
13
+ }
14
+
15
+ public function indexAction()
16
+ {
17
+ $this->_forward('edit');
18
+ }
19
+
20
+ public function editAction()
21
+ {
22
+ $vbserver = $this->_initVbserver();
23
+ $this->loadLayout();
24
+ $this->_setActiveMenu('system/aitvbulletin');
25
+ $this->renderLayout();
26
+ }
27
+
28
+ public function saveAction()
29
+ {
30
+ $vbserver = $this->_initVbserver();
31
+ $formData = $this->getRequest()->getPost();
32
+
33
+ if (!empty($formData))
34
+ {
35
+ try
36
+ {
37
+ $model = Mage::getModel('aitvbulletin/vbserver')
38
+ ->addData($formData['vbserver'])
39
+ ->save();
40
+
41
+ Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('aitvbulletin')->__('vBulletin Server Connection was successfully saved'));
42
+ }
43
+ catch (Exception $e)
44
+ {
45
+ Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
46
+ }
47
+ }
48
+
49
+ $this->_redirect('*/*/');
50
+ }
51
+
52
+ public function validateAction()
53
+ {
54
+ $response = new Varien_Object();
55
+ $response->setError(false);
56
+
57
+ $vbserver = $this->_initVbserver();
58
+
59
+ try
60
+ {
61
+ $formData = $this->getRequest()->getPost('vbserver');
62
+ $vbserver->addData($formData);
63
+ $vbserver->validate();
64
+ }
65
+ catch (Aitoc_Aitvbulletin_Model_Exception $e)
66
+ {
67
+ $response->setError(true);
68
+ $response->setMessage($e->getMessage());
69
+ $response->setField($e->getField());
70
+ }
71
+ catch (Zend_Db_Adapter_Exception $e)
72
+ {
73
+ $response->setError(true);
74
+ $response->setMessage($e->getMessage());
75
+ $response->setField('vbserver_name');
76
+ }
77
+ catch (Exception $e)
78
+ {
79
+ $response->setError(true);
80
+ $response->setMessage($e->getMessage());
81
+ }
82
+
83
+ $this->getResponse()->setBody($response->toJson());
84
+ }
85
+
86
+ /**
87
+ * Initialize vbserver
88
+ *
89
+ * @return Aitoc_Aitvbulletin_Model_Vbserver
90
+ */
91
+ protected function _initVbserver()
92
+ {
93
+ $vbserver = Mage::getModel('aitvbulletin/vbserver');
94
+
95
+ Mage::register('vbserver', $vbserver);
96
+
97
+ return $vbserver;
98
+ }
99
+
100
+ }
app/code/local/Aitoc/Aitvbulletin/controllers/ProxyController.php ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ class Aitoc_Aitvbulletin_ProxyController extends Mage_Core_Controller_Front_Action
6
+ {
7
+
8
+ public function loginAction()
9
+ {
10
+ $helper = Mage::helper('aitvbulletin');
11
+ /* @var $helper Aitoc_Aitvbulletin_Helper_Data */
12
+
13
+ if ($this->_getSession()->isLoggedIn())
14
+ {
15
+ $helper->outputBlankGif($this->getResponse());
16
+ }
17
+
18
+ $userId = (int) $this->getRequest()->getParam('u', 0);
19
+ $secureSalt = $this->getRequest()->getActionName() . $userId;
20
+
21
+ if (!$userId OR !$this->isValidApikeyHash($secureSalt))
22
+ {
23
+ return $this->_forward('noRoute');
24
+ }
25
+
26
+ $customer = Mage::getModel('customer/customer');
27
+ /* @var $customer Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer */
28
+
29
+ $customer->loadByForumUserId($userId, Mage::app()->getStore()->getId());
30
+
31
+ if ($customer->getId())
32
+ {
33
+ //header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
34
+ $this->getResponse()->setHeader('P3P', 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
35
+ $this->_getSession()->loginById($customer->getId());
36
+ $helper->outputBlankGif($this->getResponse());
37
+ }
38
+
39
+ return $this->_forward('noRoute');
40
+ }
41
+
42
+ public function logoutAction()
43
+ {
44
+ $helper = Mage::helper('aitvbulletin');
45
+ /* @var $helper Aitoc_Aitvbulletin_Helper_Data */
46
+
47
+ if (!$this->_getSession()->isLoggedIn())
48
+ {
49
+ $helper->outputBlankGif($this->getResponse());
50
+ }
51
+
52
+ $secureSalt = $this->getRequest()->getActionName();
53
+
54
+ if (!$this->isValidApikeyHash($secureSalt))
55
+ {
56
+ return $this->_forward('noRoute');
57
+ }
58
+
59
+ //header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
60
+ $this->getResponse()->setHeader('P3P', 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
61
+ $this->_getSession()->logout();
62
+ $helper->outputBlankGif($this->getResponse());
63
+ }
64
+
65
+ public function unlinkAction()
66
+ {
67
+ $helper = Mage::helper('aitvbulletin');
68
+ /* @var $helper Aitoc_Aitvbulletin_Helper_Data */
69
+
70
+ $userId = (int) $this->getRequest()->getParam('u', 0);
71
+ $secureSalt = $this->getRequest()->getActionName() . $userId;
72
+
73
+ if (!$userId OR !$this->isValidApikeyHash($secureSalt))
74
+ {
75
+ return $this->_forward('noRoute');
76
+ }
77
+
78
+ $collection = Mage::getModel('customer/customer')->getCollection();
79
+ /* @var $collection Mage_Customer_Model_Entity_Customer_Collection */
80
+ $collection
81
+ ->addAttributeToFilter('aitvbulletin_user_id', array('eq' => $userId))
82
+ ;
83
+
84
+ if ($collection->getSize())
85
+ {
86
+ foreach($collection->getItems() as $customer)
87
+ {
88
+ /* @var $customer Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer */
89
+ $customer->setAitvbulletinUserId(0);
90
+ $customer->save();
91
+ }
92
+
93
+ $helper->outputBlankGif($this->getResponse());
94
+ }
95
+
96
+ return $this->_forward('noRoute');
97
+ }
98
+
99
+ /**
100
+ * @return Mage_Customer_Model_Session
101
+ */
102
+ protected function _getSession()
103
+ {
104
+ return Mage::getSingleton('customer/session');
105
+ }
106
+
107
+ protected function isValidApikeyHash($secureSalt)
108
+ {
109
+ $hash = $this->getRequest()->getParam('h', '');
110
+ $hash = rawurldecode($hash);
111
+
112
+ // $randomSalt - random
113
+ // $key = md5( md5($apikey.$secureSalt) . $randomSalt )
114
+ // $hash = "$key:$randomSalt"
115
+
116
+ $vbserver = Mage::getModel('aitvbulletin/vbserver');
117
+ $apiKey = $vbserver->getApikey();
118
+
119
+ if (!$hash OR !$secureSalt OR !$apiKey) return false;
120
+
121
+ $hashArr = explode(':', $hash);
122
+ if (count($hashArr) == 2)
123
+ {
124
+ $thisKey = $hashArr[0];
125
+ $randomSalt = $hashArr[1];
126
+ $realKey = md5( md5($apiKey . $secureSalt) . $randomSalt);
127
+ if ($realKey == $thisKey)
128
+ {
129
+ $hashEnt = Mage::getModel('aitvbulletin_vbulletin/hash');
130
+ /* @var $hashEnt Aitoc_Aitvbulletin_Model_Vbulletin_Hash */
131
+ $hashEnt->getResource()->setConfig($vbserver);
132
+ $hashEnt->load($hash, 'hash');
133
+
134
+ if ($hashEnt->getId())
135
+ {
136
+ $isHashExpired = $hashEnt->getIsExpired();
137
+ $hashCreatedBy = $hashEnt->getCreatedBy();
138
+
139
+ $hashEnt->delete();
140
+
141
+ if (!$isHashExpired AND 'vbul' == $hashCreatedBy)
142
+ {
143
+ return true;
144
+ }
145
+ }
146
+ }
147
+ }
148
+
149
+ return false;
150
+ }
151
+
152
+ }
app/code/local/Aitoc/Aitvbulletin/etc/config.xml ADDED
@@ -0,0 +1,211 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- @copyright Copyright (c) 2009 AITOC, Inc. -->
3
+ <config>
4
+ <modules>
5
+ <Aitoc_Aitvbulletin>
6
+ <version>0.3.11</version>
7
+ </Aitoc_Aitvbulletin>
8
+ </modules>
9
+
10
+ <global>
11
+ <models>
12
+
13
+ <aitvbulletin>
14
+ <class>Aitoc_Aitvbulletin_Model</class>
15
+ </aitvbulletin>
16
+
17
+ <aitvbulletin_vbulletin>
18
+ <class>Aitoc_Aitvbulletin_Model_Vbulletin</class>
19
+ <resourceModel>aitvbulletin_vbulletin_resource</resourceModel>
20
+ </aitvbulletin_vbulletin>
21
+ <aitvbulletin_vbulletin_resource>
22
+ <class>Aitoc_Aitvbulletin_Model_Vbulletin_Mysql4</class>
23
+ <entities>
24
+ <user>
25
+ <table>user</table>
26
+ </user>
27
+ <aitmagentovb_hash>
28
+ <table>aitmagentovb_hash</table>
29
+ </aitmagentovb_hash>
30
+ </entities>
31
+ </aitvbulletin_vbulletin_resource>
32
+
33
+ <customer>
34
+ <rewrite>
35
+ <customer>Aitoc_Aitvbulletin_Model_Rewrite_FrontCustomer</customer>
36
+ </rewrite>
37
+ </customer>
38
+
39
+ </models>
40
+ <blocks>
41
+ <aitvbulletin>
42
+ <class>Aitoc_Aitvbulletin_Block</class>
43
+ </aitvbulletin>
44
+ <page>
45
+ <rewrite>
46
+ <html>Aitoc_Aitvbulletin_Block_Rewrite_FrontPageHtml</html>
47
+ </rewrite>
48
+ </page>
49
+ </blocks>
50
+ <helpers>
51
+ <aitvbulletin>
52
+ <class>Aitoc_Aitvbulletin_Helper</class>
53
+ </aitvbulletin>
54
+ </helpers>
55
+ <resources>
56
+ <aitvbulletin_setup>
57
+ <setup>
58
+ <module>Aitoc_Aitvbulletin</module>
59
+ <class>Aitoc_Aitvbulletin_Model_Mysql4_Setup</class>
60
+ </setup>
61
+ <connection><use>core_setup</use></connection>
62
+ </aitvbulletin_setup>
63
+ <aitvbulletin_write>
64
+ <connection><use>core_write</use></connection>
65
+ </aitvbulletin_write>
66
+ <aitvbulletin_read>
67
+ <connection><use>core_read</use></connection>
68
+ </aitvbulletin_read>
69
+ </resources>
70
+ </global>
71
+
72
+ <frontend>
73
+ <translate>
74
+ <modules>
75
+ <Aitoc_Aitvbulletin>
76
+ <files>
77
+ <default>Aitoc_Aitvbulletin.csv</default>
78
+ </files>
79
+ </Aitoc_Aitvbulletin>
80
+ </modules>
81
+ </translate>
82
+
83
+ <events>
84
+ <customer_logout>
85
+ <observers>
86
+ <aitoc_aitvbulletin>
87
+ <type>singleton</type>
88
+ <class>aitvbulletin/observer</class>
89
+ <method>customerLogout</method>
90
+ </aitoc_aitvbulletin>
91
+ </observers>
92
+ </customer_logout>
93
+ </events>
94
+
95
+ <layout>
96
+ <updates>
97
+ <aitvbulletin>
98
+ <file>aitvbulletin.xml</file>
99
+ </aitvbulletin>
100
+ </updates>
101
+ </layout>
102
+
103
+ <routers>
104
+ <aitvbulletin>
105
+ <use>standard</use>
106
+ <args>
107
+ <module>Aitoc_Aitvbulletin</module>
108
+ <frontName>aitvbulletin</frontName>
109
+ </args>
110
+ </aitvbulletin>
111
+ </routers>
112
+ </frontend>
113
+
114
+ <admin>
115
+ <routers>
116
+ <aitvbulletinsetup>
117
+ <use>admin</use>
118
+ <args>
119
+ <module>Aitoc_Aitvbulletin</module>
120
+ <frontName>aitvbulletinsetup</frontName>
121
+ </args>
122
+ </aitvbulletinsetup>
123
+ </routers>
124
+ </admin>
125
+
126
+ <default>
127
+ <aitvbulletin>
128
+ <forum>
129
+ <enabled>0</enabled>
130
+ <linktitle>Forum</linktitle>
131
+ </forum>
132
+ <vbserver>
133
+ <type>mysql</type>
134
+ <name/>
135
+ <prefix/>
136
+ <user/>
137
+ <pass/>
138
+ <host/>
139
+ <port/>
140
+ <link/>
141
+ <apikey/>
142
+ </vbserver>
143
+ </aitvbulletin>
144
+ </default>
145
+
146
+ <adminhtml>
147
+ <layout>
148
+ <updates>
149
+ <aitvbulletin>
150
+ <file>aitvbulletin.xml</file>
151
+ </aitvbulletin>
152
+ </updates>
153
+ </layout>
154
+ <translate>
155
+ <modules>
156
+ <Aitoc_Aitvbulletin>
157
+ <files>
158
+ <default>Aitoc_Aitvbulletin.csv</default>
159
+ </files>
160
+ </Aitoc_Aitvbulletin>
161
+ </modules>
162
+ </translate>
163
+ <menu>
164
+ <system>
165
+ <children>
166
+ <aitvbulletinsetup translate="title" module="aitvbulletin">
167
+ <title>vBulletin Connection</title>
168
+ <sort_order>4</sort_order>
169
+ <action>aitvbulletinsetup/admin_vbserver</action>
170
+ </aitvbulletinsetup>
171
+ </children>
172
+ </system>
173
+ </menu>
174
+ <acl>
175
+ <resources>
176
+ <admin>
177
+ <children>
178
+ <system>
179
+ <children>
180
+ <aitvbulletinsetup translate="title" module="aitvbulletin">
181
+ <title>Manage vBulletin Connection</title>
182
+ <sort_order>1</sort_order>
183
+ </aitvbulletinsetup>
184
+ <config>
185
+ <children>
186
+ <aitvbulletin translate="title" module="aitvbulletin">
187
+ <title>vBulletin Integration Settings</title>
188
+ </aitvbulletin>
189
+ </children>
190
+ </config>
191
+ </children>
192
+ </system>
193
+ </children>
194
+ </admin>
195
+ </resources>
196
+ </acl>
197
+ <events>
198
+ <controller_action_predispatch>
199
+ <observers>
200
+ <aitoc_aitvbulletin>
201
+ <type>singleton</type>
202
+ <class>aitvbulletin/notification_observer</class>
203
+ <method>performPreDispatch</method>
204
+ </aitoc_aitvbulletin>
205
+ </observers>
206
+ </controller_action_predispatch>
207
+ </events>
208
+
209
+ </adminhtml>
210
+
211
+ </config>
app/code/local/Aitoc/Aitvbulletin/etc/system.xml ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- @copyright Copyright (c) 2009 AITOC, Inc. -->
3
+ <config>
4
+ <sections>
5
+ <aitvbulletin translate="label" module="aitvbulletin">
6
+ <label>vBulletin Integration</label>
7
+ <tab>catalog</tab>
8
+ <frontend_type>text</frontend_type>
9
+ <sort_order>100</sort_order>
10
+ <show_in_default>1</show_in_default>
11
+ <show_in_website>1</show_in_website>
12
+ <show_in_store>1</show_in_store>
13
+ <groups>
14
+ <forum translate="label">
15
+ <label>Integration settings</label>
16
+ <frontend_type>text</frontend_type>
17
+ <frontend_model>aitvbulletin/config_formFieldset</frontend_model>
18
+ <sort_order>100</sort_order>
19
+ <show_in_default>1</show_in_default>
20
+ <show_in_website>1</show_in_website>
21
+ <show_in_store>1</show_in_store>
22
+ <fields>
23
+ <enabled translate="label comment">
24
+ <label>Enable vBulletin integration</label>
25
+ <comment><![CDATA[please refresh the cache if you change this value]]></comment>
26
+ <frontend_type>select</frontend_type>
27
+ <source_model>adminhtml/system_config_source_yesno</source_model>
28
+ <backend_model>aitvbulletin/config_backendForum</backend_model>
29
+ <sort_order>5</sort_order>
30
+ <show_in_default>1</show_in_default>
31
+ <show_in_website>1</show_in_website>
32
+ <show_in_store>1</show_in_store>
33
+ </enabled>
34
+ <linktitle translate="label comment">
35
+ <label>Forum Link Title</label>
36
+ <comment><![CDATA[title of the footer link to vBulletin forums<br/>please refresh the cache if you change this value]]></comment>
37
+ <frontend_type>text</frontend_type>
38
+ <sort_order>14</sort_order>
39
+ <show_in_default>1</show_in_default>
40
+ <show_in_website>1</show_in_website>
41
+ <show_in_store>1</show_in_store>
42
+ </linktitle>
43
+ </fields>
44
+ </forum>
45
+ </groups>
46
+ </aitvbulletin>
47
+ </sections>
48
+ </config>
app/code/local/Aitoc/Aitvbulletin/sql/aitvbulletin_setup/mysql4-install-0.3.11.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ $installer = $this;
7
+ /* @var $installer Aitoc_Aitvbulletin_Model_Mysql4_Setup */
8
+
9
+ $installer->installEntities();
app/design/adminhtml/default/default/layout/aitvbulletin.xml ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <layout version="0.1.0">
3
+
4
+ <default>
5
+ <reference name="head">
6
+ <action method="addCss"><name>aitvbulletin.css</name></action>
7
+ </reference>
8
+ </default>
9
+ <aitvbulletinsetup_admin_vbserver_edit>
10
+ <reference name="content">
11
+ <block type="aitvbulletin/admin_vbserver_edit" name="vbserver_edit">
12
+ <block type="aitvbulletin/admin_vbserver_edit_form" name="vbserver_edit_form" />
13
+ <block type="aitvbulletin/admin_news" name="aitoc_news" />
14
+ </block>
15
+ </reference>
16
+ <reference name="js">
17
+ <block type="adminhtml/template" template="aitvbulletin/vbserver/js.phtml" name="admin_vbserver_js"></block>
18
+ </reference>
19
+ </aitvbulletinsetup_admin_vbserver_edit>
20
+
21
+ </layout>
app/design/adminhtml/default/default/template/aitvbulletin/aitoc_news.phtml ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ ?>
6
+
7
+ <?php if ($this->getNews()) { ?>
8
+
9
+ <div class="entry-edit">
10
+ <div class="entry-edit-head"><h4><?php echo $this->__("AITOC News")?></h4></div>
11
+ <div class="fieldset">
12
+ <div class="news">
13
+ <?php foreach ($this->getNews() as $item) { ?>
14
+
15
+ <div class="item">
16
+ <?php if (isset($item['title']) && $item['title']) { ?><h2><?php echo $item['title']?></h2><?php } ?>
17
+
18
+ <?php echo $item['content']?>
19
+
20
+ </div>
21
+ <?php } ?>
22
+
23
+ </div>
24
+ </div>
25
+ </div>
26
+ <?php } ?>
app/design/adminhtml/default/default/template/aitvbulletin/vbserver/edit.phtml ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ ?>
6
+
7
+ <div class="content-header">
8
+ <h3 class="icon-head head-products"><?php echo $this->__('Manage vBulletin Server Connection') ?></h3>
9
+ <p class="content-buttons form-buttons"><?php
10
+ echo $this->getCancelButtonHtml();
11
+ echo $this->getSaveButtonHtml();
12
+ ?></p>
13
+ </div>
14
+
15
+ <div><?php echo $this->__('For proper functioning of the extension you need to download %s product package.<br/><br/>', $this->getVbDownloadLinkHtml()); ?></div>
16
+ <table width="100%">
17
+ <tr>
18
+ <td>
19
+ <form action="<?php echo $this->getSaveUrl() ?>" method="post" id="vbserver_edit_form" enctype="multipart/form-data">
20
+ <?php echo $this->getBlockHtml('formkey')?>
21
+ <?php echo $this->getChildHtml('vbserver_edit_form')?>
22
+ </form>
23
+ </td>
24
+ <td id="aitoc_news">
25
+ <?php echo $this->getChildHtml('aitoc_news'); ?>
26
+
27
+ </td>
28
+ </tr>
29
+ </table>
30
+
31
+
32
+ <script type="text/javascript">
33
+ //<![CDATA[
34
+
35
+ var vbserverForm = new varienForm('vbserver_edit_form', '<?php echo $this->getValidationUrl() ?>');
36
+ vbserverForm._processValidationResult = function(transport) {
37
+ var response = transport.responseText.evalJSON();
38
+ if (response.error){
39
+ if (response.field && $(response.field)) {
40
+ $(response.field).setHasError(true, vbserverForm);
41
+ AitvbulletinValidation.ajaxError($(response.field), response.message);
42
+ $(response.field).focus();
43
+ }
44
+ else if ($('messages')) {
45
+ $('messages').innerHTML = '<ul class="messages"><li class="error-msg"><ul><li>' + response.message + '</li></ul></li></ul>';
46
+ }
47
+ }
48
+ else{
49
+ vbserverForm._submit();
50
+ }
51
+ };
52
+
53
+ //]]>
54
+ </script>
app/design/adminhtml/default/default/template/aitvbulletin/vbserver/js.phtml ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ ?>
6
+ <script type="text/javascript">
7
+ //<![CDATA[
8
+
9
+ var AitvbulletinValidation = Object.extend(Validation);
10
+
11
+ AitvbulletinValidation.ajaxError = function(elm, errorMsg) {
12
+ var name = 'validate-ajax';
13
+ var advice = Validation.getAdvice(name, elm);
14
+ if (advice == null) {
15
+ advice = this.createAdvice(name, elm, false, errorMsg);
16
+ }
17
+ /* added lines */
18
+ else
19
+ {
20
+ advice.update(errorMsg);
21
+ }
22
+ /* end of added lines */
23
+ this.showAdvice(elm, advice, 'validate-ajax');
24
+ this.updateCallback(elm, 'failed');
25
+
26
+ elm.addClassName('validation-failed');
27
+ elm.addClassName('validate-ajax');
28
+ if (this.defaultOptions.addClassNameToContainer && this.defaultOptions.containerClassName != '') {
29
+ var container = elm.up(this.defaultOptions.containerClassName);
30
+ if (container && this.allowContainerClassName(elm)) {
31
+ container.removeClassName('validation-passed');
32
+ container.addClassName('validation-error');
33
+ }
34
+ }
35
+ };
36
+
37
+ //]]>
38
+ </script>
app/design/frontend/default/default/layout/aitvbulletin.xml ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!-- @copyright Copyright (c) 2009 AITOC, Inc. -->
3
+
4
+ <layout>
5
+ <default>
6
+ <reference name="head">
7
+ <action method="addCss"><stylesheet>css/aitvbulletin.css</stylesheet></action>
8
+ </reference>
9
+ <reference name="footer_links">
10
+ <action method="addLink" ifconfig="aitvbulletin/forum/enabled">
11
+ <label helper="aitvbulletin/getForumLabel"/>
12
+ <url helper="aitvbulletin/getForumUrl"/>
13
+ <title helper="aitvbulletin/getForumTitle"/>
14
+ <prepare/>
15
+ <urlParams/>
16
+ <position>999</position>
17
+ </action>
18
+ </reference>
19
+ </default>
20
+
21
+ <customer_account>
22
+ <reference name="customer_account_navigation">
23
+ <action method="addLink" translate="label" module="aitvbulletin" ifconfig="aitvbulletin/forum/enabled">
24
+ <name>aitvbulletin_forum_integration_link</name>
25
+ <url>aitvbulletin/account/forum</url>
26
+ <label>Forum Integration</label>
27
+ </action>
28
+ </reference>
29
+ </customer_account>
30
+
31
+ <customer_account_logoutsuccess>
32
+ <reference name="content">
33
+ <block type="aitvbulletin/account_logout"/>
34
+ </reference>
35
+ </customer_account_logoutsuccess>
36
+
37
+ <aitvbulletin_account_forum>
38
+ <update handle="customer_account"/>
39
+ <reference name="content">
40
+ <block type="aitvbulletin/account_forum" name="aitvbulletin_forum_integration_form" template="aitvbulletin/customer/forum.phtml"/>
41
+ </reference>
42
+ </aitvbulletin_account_forum>
43
+
44
+ </layout>
app/design/frontend/default/default/template/aitvbulletin/customer/forum.phtml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+ ?>
6
+ <div class="page-head">
7
+ <h3><?php echo $this->helper('aitvbulletin')->__('Forum Integration') ?></h3>
8
+ </div>
9
+ <?php echo $this->getMessagesBlock()->getGroupedHtml() ?>
10
+
11
+ <?php if ($this->getCustomer()->getAitvbulletinUserId()) { ?>
12
+
13
+ <fieldset class="group-select">
14
+ <h4 class="legend"><?php echo $this->__('Forum Account: %s', $this->getCustomer()->getAitvbulletinUser()->getUsername()) ?></h4>
15
+ <div>
16
+ <?php if ($this->getCustomerAvatarPath()) { ?><img src="<?php echo $this->getCustomerAvatarPath(); ?>" alt="<?php echo $this->__('Your avatar'); ?>"/><?php } ?>
17
+
18
+ </div>
19
+ <ul>
20
+ <li><?php echo $this->__('Joined');?>: <?php echo $this->formatDate(Mage::app()->getLocale()->date($this->getCustomer()->getAitvbulletinUser()->getJoindate()), 'short', true); ?></li>
21
+ <li><?php echo $this->__('Total Posts');?>: <?php echo $this->getCustomerPostsCount(); ?></li>
22
+
23
+
24
+ <li><a href="<?php echo $this->getForumProfileUrl(); ?>" target="_blank"><?php echo $this->__('Visit your forum profile page'); ?></a></li>
25
+ </ul>
26
+ </fieldset>
27
+ <div class="button-set">
28
+ <a href="<?php echo $this->getBackUrl() ?>" class="left">&laquo; <?php echo $this->__('Back') ?></a>
29
+ </div>
30
+
31
+ <?php } else { ?>
32
+
33
+ <form action="<?php echo $this->getActionUrl() ?>" method="post" id="form-verify">
34
+ <?php echo $this->getBlockHtml('formkey')?>
35
+
36
+ <fieldset class="group-select">
37
+ <h4 class="legend"><?php echo $this->__('Already Registered') ?></h4>
38
+ <ul>
39
+ <li>
40
+ <div class="input-box">
41
+ <label for="verify_username"><?php echo $this->__('Username') ?> <span class="required">*</span></label><br/>
42
+ <input type="text" class="input-text required-entry" name="verify_username" id="verify_username" value="<?php echo $this->htmlEscape($this->getCustomer()->getVerifyUsername()); ?>" title="<?php echo $this->__('Username') ?>" />
43
+ </div>
44
+ </li>
45
+ <li>
46
+ <div class="input-box">
47
+ <label for="verify_password"><?php echo $this->__('Password') ?> <span class="required">*</span></label><br/>
48
+ <input type="password" class="input-text required-entry" name="verify_password" id="verify_password" title="<?php echo $this->__('Password') ?>" />
49
+ </div>
50
+ </li>
51
+ </ul>
52
+ <div class="button-set">
53
+ <a href="<?php echo $this->getForumForgotUrl() ?>" class="left" target="_blank"><?php echo $this->__('Forgot Your Forum Password?') ?></a>
54
+ <button type="submit" class="form-button"><span><?php echo $this->__('Confirm') ?></span></button>
55
+ </div>
56
+ </fieldset>
57
+ </form>
58
+
59
+
60
+ <script type="text/javascript">
61
+ //<![CDATA[
62
+ var verifyForm = new VarienForm('form-verify');
63
+ //]]>
64
+ </script>
65
+
66
+ <div class="button-set">
67
+ <a href="<?php echo $this->getBackUrl() ?>" class="left">&laquo; <?php echo $this->__('Back') ?></a>
68
+ <p class="required"><?php echo $this->__('* Required Fields') ?></p>
69
+ </div>
70
+
71
+ <?php } ?>
72
+
app/etc/modules/Aitoc_Aitvbulletin.xml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <config>
3
+ <modules>
4
+ <Aitoc_Aitvbulletin>
5
+ <active>true</active>
6
+ <codePool>local</codePool>
7
+ <self_name>vBulletin Integration Lite</self_name>
8
+ <priority>1000</priority>
9
+ </Aitoc_Aitvbulletin>
10
+ </modules>
11
+ </config>
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Aitoc_Aitvbulletin</name>
4
+ <version>0.3.11</version>
5
+ <stability>stable</stability>
6
+ <license>OSL v3.0</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>vBulletin Integration Lite</summary>
10
+ <description>vBulletin Integration Lite</description>
11
+ <notes>0.3.11</notes>
12
+ <authors><author><name>AITOC Inc.</name><user>auto-converted</user><email>magsupport@aitoc.com</email></author></authors>
13
+ <date>2009-11-12</date>
14
+ <time>16:37:07</time>
15
+ <contents><target name="magedesign"><dir name="adminhtml"><dir name="default"><dir name="default"><dir name="layout"><file name="aitvbulletin.xml" hash="de017b0a4a96fae6acdc123a82a1e8b8"/></dir><dir name="template"><dir name="aitvbulletin"><dir name="vbserver"><file name="edit.phtml" hash="9489aeaff76338c949951262b90aaae4"/><file name="js.phtml" hash="ed1afcb1ff9daca0a6da318fb7668341"/></dir><file name="aitoc_news.phtml" hash="b4747f0c6876b62413cd3aa37d8f6ef2"/></dir></dir></dir></dir></dir><dir name="frontend"><dir name="default"><dir name="default"><dir name="layout"><file name="aitvbulletin.xml" hash="380748ff547119d19ea360996935bd7c"/></dir><dir name="template"><dir name="aitvbulletin"><dir name="customer"><file name="forum.phtml" hash="3a946c44d82ae0acb74b3011053efaec"/></dir></dir></dir></dir></dir></dir></target><target name="mageskin"><dir name="adminhtml"><dir name="default"><dir name="default"><file name="aitvbulletin.css" hash="52c2b2ce71b35bfdcb64dc6909b6301a"/></dir></dir></dir><dir name="frontend"><dir name="default"><dir name="default"><dir name="css"><file name="aitvbulletin.css" hash="65788bd84d8c88833d4a649fea9ac7db"/></dir></dir></dir></dir></target><target name="magelocal"><dir name="Aitoc"><dir name="Aitvbulletin"><dir name="Block"><dir name="Account"><file name="Forum.php" hash="d05d46902fc451fa6b727bf0b25007fc"/><file name="Logout.php" hash="b9fa0831933805d6b9c4655454fc348c"/></dir><dir name="Admin"><dir name="Vbserver"><dir name="Edit"><file name="Form.php" hash="9a54e86df8d4d7e4270a493a09316bc5"/></dir><file name="Edit.php" hash="0c9ca6688eb5ada387ea5e0138b2ae25"/></dir><file name="News.php" hash="f8a8320f2c09a5461f6b34c7a291c1e6"/></dir><dir name="Config"><file name="FormFieldset.php" hash="40542e7fe989c52cb9be66cf30e2eb75"/></dir><dir name="Rewrite"><file name="FrontPageHtml.data.php" hash="f55f995f434d8691c7b4b6929ac977f1"/><file name="FrontPageHtml.php" hash="f55f995f434d8691c7b4b6929ac977f1"/></dir></dir><dir name="controllers"><dir name="Admin"><file name="VbserverController.php" hash="227d8e99e62b72937a410875e368079d"/></dir><file name="AccountController.php" hash="51cc63ad2ef19f917c94353831185a6a"/><file name="ProxyController.php" hash="e7ffc3942b8d4f832c6da476f59b958a"/></dir><dir name="etc"><file name="config.xml" hash="28e1b1496937c69bd439bea23d138af1"/><file name="system.xml" hash="4eb75ee16d2efd686112942dc5b4a631"/></dir><dir name="Helper"><file name="Data.php" hash="428a8e8b0dfcadcdc0337df173160e69"/></dir><dir name="Model"><dir name="Config"><file name="BackendForum.php" hash="d05248f76e9d6647106e347f5a2e7425"/><file name="SourceDbtype.php" hash="cdc526f5f2d9c2300a50741e0aa6f79b"/></dir><dir name="Mysql4"><file name="Setup.php" hash="1e1c060d123baa160f34344c635e0bb2"/></dir><dir name="Notification"><file name="Abstract.php" hash="ffca27e66c762006a5930b8fcb722422"/><file name="News.php" hash="92c52193deef455bbce2d588b107e066"/><file name="Notifications.php" hash="d36f130ed2ccf5e213a6b857f595b7dc"/><file name="Observer.php" hash="18d1797a8fb490b910825fb6eba5420b"/><file name="Service.php" hash="80a307a3aa4cc75a2225bfa83bb04c35"/></dir><dir name="Rewrite"><file name="FrontCustomer.data.php" hash="1243986eba9d075d931cbbd75ee87a27"/><file name="FrontCustomer.php" hash="1243986eba9d075d931cbbd75ee87a27"/></dir><dir name="Vbulletin"><dir name="Mysql4"><dir name="Collection"><file name="Abstract.php" hash="ed7b054368f44b51fb632a046479f1ed"/></dir><dir name="Hash"><file name="Collection.php" hash="2020d19a2a6ccc6d4c4d51e297daece4"/></dir><dir name="User"><file name="Collection.php" hash="0134e12a71f26da56e1c916387119196"/></dir><file name="Abstract.php" hash="362b20169cecc28a5c595103cbbb260a"/><file name="Hash.php" hash="0b41311285b8841ca8d8ffd9cdcd1f95"/><file name="User.php" hash="dda0927f6ab2a6aff6cdff34a2a75614"/></dir><file name="Abstract.php" hash="9ea20ad9b6597a12c6af89156da3b422"/><file name="Hash.php" hash="2c0339fab2cd0045155cfdd17f7d01db"/><file name="User.php" hash="862af11617928ee071ddaba6d8e820bb"/></dir><file name="Curl.php" hash="3c960a9b133da3b38f08f2cf2fea37d1"/><file name="Exception.php" hash="7f71f3df1b41a464ad9fb0de07d9de18"/><file name="Observer.php" hash="a52afff6cbc11406370b9141a3425db3"/><file name="Session.php" hash="03f9a0164698015cfed549e2cee9d45b"/><file name="Vbserver.php" hash="2399f684238f8b4bd31d436874f3adaa"/></dir><dir name="sql"><dir name="aitvbulletin_setup"><file name="mysql4-install-0.3.11.php" hash="3b36568577a6a305b96a1c38766cd521"/></dir></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Aitoc_Aitvbulletin.xml" hash="2831023ea95a40158ef7bd3f079ec465"/></dir></target><target name="mage"><dir name="vbulletin_product"><dir name="vbulletin_import"><file name="Aitoc MagentoVB Lite.xml" hash="a3004921f47b8cb5052cc178135be604"/></dir><dir name="vbulletin_upload"><dir name="includes"><file name="class_aitmagentovb.php" hash="934fc7e87bf5c3f8edcdcf0b6ce64883"/><file name="class_aitzend.php" hash="f9e3648e402b840b9fc4703c84a7d829"/></dir><file name="aitmagentovb.php" hash="1e5e4e811921182dbeccdf8a02ad7a12"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies/>
18
+ </package>
skin/adminhtml/default/default/aitvbulletin.css ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ fieldset#aitvbulletin_forum div.comment { float: right; padding-left: 10px; width: 330px; }
2
+ fieldset#aitvbulletin_forum div.comment .fieldset { background-color: #ddd; }
3
+ fieldset#aitvbulletin_forum div.comment .news .item h2 { font-size: 120%; margin-top: 0.5em; }
4
+ fieldset#aitvbulletin_forum div.comment .news .item h3 { font-size: 110%; margin-top: 0.5em; color: #EA7601; }
5
+ fieldset#aitvbulletin_forum div.comment .news .item ul { list-style-type: square; list-style-position: inside; }
6
+
7
+ td#aitoc_news { padding-left: 10px; width: 330px; }
8
+ td#aitoc_news .fieldset { background-color: #ddd; }
9
+ td#aitoc_news .news .item h2 { font-size: 120%; margin-top: 0.5em; }
10
+ td#aitoc_news .news .item h3 { font-size: 110%; margin-top: 0.5em; color: #EA7601; }
11
+ td#aitoc_news .news .item ul { list-style-type: square; list-style-position: inside; }
skin/frontend/default/default/css/aitvbulletin.css ADDED
@@ -0,0 +1,2 @@
 
 
1
+ .aitvbulletin-auth-image { position: absolute !important; top: -10px !important; left: -10px !important; width: 1px !important; height: 1px !important; }
2
+ .aitvbulletin-auth-image img { width: 1px !important; height: 1px !important; border: 0 !important; }
vbulletin_product/vbulletin_import/Aitoc MagentoVB Lite.xml ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="ISO-8859-1"?>
2
+
3
+ <product productid="aitmagentovb" active="1">
4
+ <title>AITOC MagentoVB Lite Bridge</title>
5
+ <description>A bridge with your Magento website (lite version)</description>
6
+ <version>0.3.11</version>
7
+ <url><![CDATA[http://www.aitoc.com/]]></url>
8
+ <versioncheckurl />
9
+ <dependencies></dependencies>
10
+ <codes>
11
+ <code version="*">
12
+ <installcode><![CDATA[
13
+ $sql = '
14
+ CREATE TABLE IF NOT EXISTS `'.TABLE_PREFIX.'aitmagentovb_hash` (
15
+ `hashid` int(10) unsigned NOT NULL auto_increment,
16
+ `hash` varchar(36) NOT NULL,
17
+ `validthru` datetime NOT NULL,
18
+ `created_by` ENUM( "vbul", "mage" ) NOT NULL,
19
+ PRIMARY KEY (`hashid`),
20
+ KEY `validthru` (`validthru`),
21
+ KEY `hash` (`hash`)
22
+ ) ENGINE=MyISAM
23
+ ';
24
+ $vbulletin->db->query_write($sql);
25
+ ]]></installcode>
26
+ <uninstallcode><![CDATA[
27
+ $vbulletin->db->query_first('DROP TABLE IF EXISTS `'.TABLE_PREFIX.'aitmagentovb_hash`');
28
+ ]]></uninstallcode>
29
+ </code>
30
+ </codes>
31
+
32
+ <templates>
33
+ <template name="aitmagentovb_auth_image" templatetype="template" date="1250000000" username="Aitoc" version="1.0.0"><![CDATA[
34
+
35
+ <div style="position: absolute !important; top: -10px !important; left: -10px !important; width: 1px !important; height: 1px !important; ">
36
+ <img src="#aitmagentovbUrl" width="1" height="1" alt="" border="0" />
37
+ </div>
38
+
39
+ ]]></template>
40
+ </templates>
41
+
42
+ <plugins>
43
+ <plugin active="1" executionorder="5">
44
+ <title>Template Cache</title>
45
+ <hookname>cache_templates</hookname>
46
+ <phpcode><![CDATA[
47
+
48
+ $globaltemplates = array_merge($globaltemplates, array('aitmagentovb_bbcode_quote','aitmagentovb_auth_image',));
49
+
50
+ ]]></phpcode>
51
+ </plugin>
52
+ <plugin active="1" executionorder="5">
53
+ <title>Parse Templates</title>
54
+ <hookname>parse_templates</hookname>
55
+ <phpcode><![CDATA[
56
+
57
+ if ($vbulletin->userinfo['userid'] AND 2 == $vbulletin->userinfo['usergroupid'] AND $show['member'])
58
+ {
59
+ $aitmagentovbVars = array(
60
+ 'do' => 'login',
61
+ 'u' => $vbulletin->userinfo['userid'],
62
+ );
63
+ $aitmagentovbUrl = Aitmagentovb::getProxyUrl($aitmagentovbVars, null, $aitmagentovbVars['do'].$aitmagentovbVars['u']);
64
+
65
+ $vbulletin->templatecache['navbar'] .= str_replace('#aitmagentovbUrl', $aitmagentovbUrl, $vbulletin->templatecache['aitmagentovb_auth_image']);
66
+ }
67
+
68
+ ]]></phpcode>
69
+ </plugin>
70
+ <plugin active="1" executionorder="5">
71
+ <title>INIT Startup</title>
72
+ <hookname>init_startup</hookname>
73
+ <phpcode><![CDATA[
74
+
75
+ require_once(DIR . '/includes/class_aitmagentovb.php');
76
+ Aitmagentovb::cleanHashes();
77
+
78
+ ]]></phpcode>
79
+ </plugin>
80
+
81
+ <plugin active="1" executionorder="5">
82
+ <title>Login Process</title>
83
+ <hookname>login_process</hookname>
84
+ <phpcode><![CDATA[
85
+
86
+ $aitmagentovbVars = array(
87
+ 'do' => 'login',
88
+ 'u' => $vbulletin->userinfo['userid'],
89
+ );
90
+ $aitmagentovbUrl = Aitmagentovb::getProxyUrl($aitmagentovbVars, null, $aitmagentovbVars['do'].$aitmagentovbVars['u']);
91
+
92
+ $vbulletin->templatecache['navbar'] .= str_replace('#aitmagentovbUrl', $aitmagentovbUrl, $vbulletin->templatecache['aitmagentovb_auth_image']);
93
+
94
+ ]]></phpcode>
95
+ </plugin>
96
+
97
+ <plugin active="1" executionorder="5">
98
+ <title>Logout Process</title>
99
+ <hookname>logout_process</hookname>
100
+ <phpcode><![CDATA[
101
+
102
+ $aitmagentovbVars = array(
103
+ 'do' => 'logout',
104
+ );
105
+ $aitmagentovbUrl = Aitmagentovb::getProxyUrl($aitmagentovbVars, null, $aitmagentovbVars['do']);
106
+
107
+ $vbulletin->templatecache['navbar'] .= str_replace('#aitmagentovbUrl', $aitmagentovbUrl, $vbulletin->templatecache['aitmagentovb_auth_image']);
108
+
109
+ ]]></phpcode>
110
+ </plugin>
111
+
112
+ <plugin active="1" executionorder="5">
113
+ <title>User delete by Admin</title>
114
+ <hookname>userdata_delete</hookname>
115
+ <phpcode><![CDATA[
116
+
117
+ require_once(DIR . '/includes/class_aitmagentovb.php');
118
+ require_once(DIR . '/includes/class_aitzend.php');
119
+ $aVars = array(
120
+ 'do' => 'unlink',
121
+ 'u' => $this->existing['userid'],
122
+ );
123
+ try
124
+ {
125
+ $aResponce = Aitmagentovb::curlWrite(
126
+ 'POST',
127
+ Aitmagentovb::getProxyUrl($aVars, null, $aVars['do'].$aVars['u']),
128
+ '1.1',
129
+ array(),
130
+ Aitmagentovb::mergeRequestVars($aVars, true)
131
+ );
132
+ } catch (Exception $e) { }
133
+
134
+ ]]></phpcode>
135
+ </plugin>
136
+ </plugins>
137
+
138
+ <phrases>
139
+ <phrasetype name="vBulletin Settings" fieldname="vbsettings">
140
+ <phrase name="setting_aitmagentovb_apikey_title" date="0" username="Aitoc" version=""><![CDATA[Module API key]]></phrase>
141
+ <phrase name="setting_aitmagentovb_apikey_desc" date="0" username="Aitoc" version=""><![CDATA[use it to create a connection in Magento Admin "System > vBulletin Connection"]]></phrase>
142
+
143
+ <phrase name="setting_aitmagentovb_url_title" date="0" username="Aitoc" version=""><![CDATA[Your Magento URL]]></phrase>
144
+ <phrase name="setting_aitmagentovb_url_desc" date="0" username="Aitoc" version=""><![CDATA[starting with http://]]></phrase>
145
+
146
+ <phrase name="settinggroup_aitmagentovb" date="0" username="Aitoc" version=""><![CDATA[AITOC MagentoVB Lite Settings]]></phrase>
147
+ </phrasetype>
148
+ </phrases>
149
+
150
+ <options>
151
+ <settinggroup name="aitmagentovb" displayorder="65535">
152
+ <setting varname="aitmagentovb_apikey" displayorder="10">
153
+ <datatype>free</datatype>
154
+ <defaultvalue><![CDATA[changeme]]></defaultvalue>
155
+ </setting>
156
+ <setting varname="aitmagentovb_url" displayorder="30">
157
+ <datatype>free</datatype>
158
+ <defaultvalue><![CDATA[]]></defaultvalue>
159
+ </setting>
160
+ </settinggroup>
161
+ </options>
162
+
163
+ <helptopics>
164
+ </helptopics>
165
+
166
+ <cronentries>
167
+ </cronentries>
168
+
169
+ <faqentries>
170
+ </faqentries>
171
+
172
+ </product>
vbulletin_product/vbulletin_upload/aitmagentovb.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ error_reporting(E_ALL & ~E_NOTICE);
7
+
8
+ define('THIS_SCRIPT', 'aitmagentovb');
9
+
10
+ header('P3P: CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"');
11
+ //header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
12
+
13
+ require_once('./global.php');
14
+ require_once(DIR . '/includes/class_aitmagentovb.php');
15
+ require_once(DIR . '/includes/class_aitzend.php');
16
+
17
+ $vbulletin->input->clean_array_gpc('r', array(
18
+ 'h' => TYPE_STR,
19
+ ));
20
+
21
+ if (empty($_REQUEST['do']))
22
+ {
23
+ exec_header_redirect($vbulletin->options['forumhome'] . '.php');
24
+ }
25
+
26
+ if ($_REQUEST['do'] == 'login')
27
+ {
28
+ /**
29
+ * Log in user by userid
30
+ * $_REQUEST['userid'] - userid
31
+ */
32
+ $vbulletin->input->clean_array_gpc('r', array(
33
+ 'userid' => TYPE_INT,
34
+ ));
35
+
36
+ if ($vbulletin->GPC['userid'] AND
37
+ Aitmagentovb::isValidApikeyHash($vbulletin->GPC['h'], $_REQUEST['do'] . $vbulletin->GPC['userid']) AND
38
+ $loguser = fetch_userinfo($vbulletin->GPC['userid']) AND
39
+ $vbulletin->userinfo['userid'] != $loguser['userid'] ) // no need to login if user is already authorized
40
+ {
41
+ require_once(DIR . '/includes/functions_login.php');
42
+
43
+ exec_unstrike_user($loguser['username']);
44
+
45
+ $vbulletin->userinfo['userid'] = $loguser['userid'];
46
+ process_new_login('', false, '');
47
+
48
+ exec_shut_down();
49
+ }
50
+
51
+ Aitmagentovb::outputBlankGif();
52
+ }
53
+ elseif ($_REQUEST['do'] == 'logout')
54
+ {
55
+ /**
56
+ * Log out user by userid
57
+ * $_REQUEST['userid'] - userid
58
+ */
59
+ $vbulletin->input->clean_array_gpc('r', array(
60
+ 'userid' => TYPE_INT,
61
+ ));
62
+
63
+ if ($vbulletin->GPC['userid'] == $vbulletin->userinfo['userid'] AND
64
+ Aitmagentovb::isValidApikeyHash($vbulletin->GPC['h'], $_REQUEST['do'] . $vbulletin->GPC['userid']) )
65
+ {
66
+ require_once(DIR . '/includes/functions_login.php');
67
+
68
+ process_logout();
69
+
70
+ exec_shut_down();
71
+ }
72
+
73
+ Aitmagentovb::outputBlankGif();
74
+ }
75
+ elseif ($_REQUEST['do'] == 'verify')
76
+ {
77
+ /**
78
+ * Verify user
79
+ * $_POST['username'] - forum username
80
+ * $_POST['password_md5'] - password md5 hash
81
+ * @since 0.3.0
82
+ */
83
+ $vbulletin->input->clean_array_gpc('p', array(
84
+ 'username' => TYPE_STR,
85
+ 'password_md5' => TYPE_STR,
86
+ ));
87
+
88
+ if ($vbulletin->GPC['username'] AND
89
+ $vbulletin->GPC['password_md5'] AND
90
+ Aitmagentovb::isValidApikeyHash($vbulletin->GPC['h'], $_REQUEST['do'] . $vbulletin->GPC['username']) )
91
+ {
92
+ require_once(DIR . '/includes/functions_login.php');
93
+
94
+ if (!verify_authentication($vbulletin->GPC['username'], '', $vbulletin->GPC['password_md5'], '', false, false))
95
+ {
96
+ exec_header_redirect($vbulletin->options['forumhome'] . '.php');
97
+ }
98
+
99
+ $aitmagentovbResult = array();
100
+ $aitmagentovbResult['userid'] = $vbulletin->userinfo['userid'];
101
+ $aitmagentovbResult['email'] = $vbulletin->userinfo['email'];
102
+ $aitmagentovbResult['done'] = 'verify';
103
+
104
+ Aitmagentovb::outputJsonResult($aitmagentovbResult);
105
+
106
+ exec_shut_down();
107
+ }
108
+ else
109
+ {
110
+ exec_header_redirect($vbulletin->options['forumhome'] . '.php');
111
+ }
112
+ }
113
+ else if ($_REQUEST['do'] == 'ping')
114
+ {
115
+ $aitmagentovbResult = array('THIS_SCRIPT' => THIS_SCRIPT);
116
+
117
+ Aitmagentovb::outputJsonResult($aitmagentovbResult, true);
118
+ }
119
+ else if ($_POST['do'] == 'options')
120
+ {
121
+ if (Aitmagentovb::isValidApikeyHash($vbulletin->GPC['h'], $_POST['do']) )
122
+ {
123
+ $aitmagentovbResult = $vbulletin->options;
124
+ $aitmagentovbResult['bf_misc'] = $vbulletin->bf_misc; /** @since 0.2.2 */
125
+ $aitmagentovbResult['bf_ugp'] = $vbulletin->bf_ugp; /** @since 0.3.0 */
126
+ $aitmagentovbResult['done'] = 'options';
127
+
128
+ Aitmagentovb::outputJsonResult($aitmagentovbResult, true);
129
+ }
130
+ else
131
+ {
132
+ exec_header_redirect($vbulletin->options['forumhome'] . '.php');
133
+ }
134
+ }
vbulletin_product/vbulletin_upload/includes/class_aitmagentovb.php ADDED
@@ -0,0 +1,259 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @copyright Copyright (c) 2009 AITOC, Inc.
4
+ */
5
+
6
+ class Aitmagentovb
7
+ {
8
+ const CURL_TIMEOUT_SEC = 10;
9
+ const APIKEY_HASH_LIFETIME = 20; // in seconds, see storeHashLifetime()
10
+
11
+
12
+ /**
13
+ * Validate hash
14
+ *
15
+ * @param string $hash
16
+ * @param string $secureSalt
17
+ * @return boolean
18
+ */
19
+ static public function isValidApikeyHash($hash, $secureSalt)
20
+ {
21
+ global $vbulletin;
22
+ $hash = rawurldecode($hash);
23
+
24
+ // $randomSalt - random
25
+ // $key = md5( md5($apikey.$secureSalt) . $randomSalt )
26
+ // $hash = "$key:$randomSalt"
27
+
28
+ if (!$hash OR !$secureSalt OR !$vbulletin->options['aitmagentovb_apikey']) return false;
29
+
30
+ $hashArr = explode(':', $hash);
31
+ if (count($hashArr) == 2)
32
+ {
33
+ $thisKey = $hashArr[0];
34
+ $randomSalt = $hashArr[1];
35
+ $apiKey = $vbulletin->options['aitmagentovb_apikey'];
36
+ $realKey = md5( md5($apiKey . $secureSalt) . $randomSalt);
37
+ if ($realKey == $thisKey)
38
+ {
39
+ $sql = '
40
+ SELECT
41
+ *,
42
+ IF(`validthru` < NOW(), 1, 0) AS is_expired
43
+ FROM `'.TABLE_PREFIX.'aitmagentovb_hash`
44
+ WHERE `hash` = "'.$hash.'"
45
+ ';
46
+ // it's safe enough for non-escape usage of $hash here
47
+ $hashRow = $vbulletin->db->query_first($sql);
48
+ if ($hashRow AND $hashRow['hashid'])
49
+ {
50
+ $vbulletin->db->query_write('
51
+ DELETE FROM `'.TABLE_PREFIX.'aitmagentovb_hash`
52
+ WHERE `hashid`='.$hashRow['hashid']
53
+ );
54
+
55
+ if (!$hashRow['is_expired'] AND 'mage' == $hashRow['created_by'])
56
+ {
57
+ return true;
58
+ }
59
+ }
60
+ }
61
+ }
62
+
63
+ return false;
64
+ }
65
+
66
+ static public function outputJsonResult($result, $die = false)
67
+ {
68
+ $s = Ait_Zend_Json::encode($result);
69
+
70
+ header('Content-Type: text/json');
71
+ header('Content-Length: ' . strlen($s));
72
+ echo $s;
73
+ if ($die)
74
+ {
75
+ exit;
76
+ }
77
+ }
78
+
79
+ static public function outputBlankGif()
80
+ {
81
+ // transparent GIF 1x1 pixel // real binary data is needed for login/logout images
82
+ $sBlankGifBase64 = 'R0lGODlhAQABAID/AP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==';
83
+ $sBlankGif = base64_decode($sBlankGifBase64);
84
+
85
+ header('Content-Type: image/gif');
86
+ header('Content-Length: ' . strlen($sBlankGif));
87
+ echo $sBlankGif;
88
+ exit;
89
+ }
90
+
91
+ /**
92
+ * Generate a password salt
93
+ *
94
+ * @return string
95
+ */
96
+ static public function generateVbPasswordSalt()
97
+ {
98
+ $hashSalt = '';
99
+ for ($i = 0; $i < 3; $i++)
100
+ {
101
+ $hashSalt .= chr(rand(0x41, 0x5A)); // A..Z
102
+ }
103
+
104
+ return $hashSalt;
105
+ }
106
+
107
+ static public function generateApiHash($urlencode, $secureSalt)
108
+ {
109
+ global $vbulletin;
110
+
111
+ $apiKey = $vbulletin->options['aitmagentovb_apikey'];
112
+ $randomSalt = self::generateVbPasswordSalt();
113
+
114
+ $hash = md5( md5($apiKey.$secureSalt) . $randomSalt ) . ':' . $randomSalt;
115
+
116
+ // store hash and its lifetime to vbulletin database
117
+ self::storeHashLifetime($hash);
118
+
119
+ if ($urlencode)
120
+ {
121
+ $hash = rawurlencode($hash);
122
+ }
123
+
124
+ return $hash;
125
+ }
126
+
127
+ static public function mergeRequestVars($aVars, $urlencode = true, $varskey = '')
128
+ {
129
+ if (!$aVars) return '';
130
+
131
+ $sReq = '';
132
+ foreach ($aVars as $key => $val)
133
+ {
134
+ if (is_array($val))
135
+ {
136
+ $key = $varskey ? $varskey.'['.$key.']' : $key;
137
+ $sReq .= '&'.self::mergeRequestVars($val, $urlencode, $key);
138
+ }
139
+ else
140
+ {
141
+ $val = ($urlencode ? rawurlencode($val) : $val);
142
+ if ($varskey)
143
+ {
144
+ $sReq .= '&'.$varskey.'['.$key.']='.$val;
145
+ }
146
+ else
147
+ {
148
+ $sReq .= '&'.$key.'='.$val;
149
+ }
150
+ }
151
+ }
152
+ $sReq = substr($sReq, 1);
153
+ return $sReq;
154
+ }
155
+
156
+ static public function getProxyUrl($aVars, $mageLink, $secureSalt)
157
+ {
158
+ global $vbulletin;
159
+
160
+ $_allowed_proxy_actions = array(
161
+ 'login',
162
+ 'logout',
163
+ 'unlink', /** @since 0.3.0 */
164
+ );
165
+
166
+ if (!isset($aVars['do']) OR !in_array($aVars['do'], $_allowed_proxy_actions))
167
+ {
168
+ return '';
169
+ }
170
+
171
+ if (is_null($mageLink))
172
+ {
173
+ $mageLink = $vbulletin->options['aitmagentovb_url'];
174
+ }
175
+ $mageLink = rtrim($mageLink, '/') . '/';
176
+
177
+ $url = $mageLink . 'aitvbulletin/proxy/' . $aVars['do'] . '/?';
178
+ unset($aVars['do']);
179
+
180
+ $aVars['h'] = self::generateApiHash(false, $secureSalt);
181
+
182
+ $url .= self::mergeRequestVars($aVars, true);
183
+
184
+ return $url;
185
+ }
186
+
187
+ static public function storeHashLifetime($hash)
188
+ {
189
+ global $vbulletin;
190
+
191
+ if (!$hash) return false;
192
+
193
+ $validThru = TIMENOW + self::APIKEY_HASH_LIFETIME;
194
+
195
+ $vbulletin->db->query_write('
196
+ INSERT INTO `'.TABLE_PREFIX.'aitmagentovb_hash`
197
+ (`hash`, `validthru`, `created_by`)
198
+ VALUES
199
+ ("'.$vbulletin->db->escape_string($hash).'", "'.date('Y-m-d H:i:s', $validThru).'", "vbul")
200
+ ');
201
+ }
202
+
203
+ static public function cleanHashes()
204
+ {
205
+ global $vbulletin;
206
+
207
+ $vbulletin->db->query_write('
208
+ DELETE FROM `'.TABLE_PREFIX.'aitmagentovb_hash`
209
+ WHERE LENGTH(`hash`) != 36
210
+ OR `validthru` < NOW()
211
+ OR `created_by` NOT IN ("mage", "vbul")
212
+ ');
213
+ }
214
+
215
+ static public function curlWrite($method, $url, $http_ver = '1.1', $headers = array(), $body = '')
216
+ {
217
+ $ch = curl_init();
218
+ curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
219
+ curl_setopt($ch, CURLOPT_REFERER, 'http://' . $_SERVER['HTTP_HOST']);
220
+ curl_setopt($ch, CURLOPT_TIMEOUT, self::CURL_TIMEOUT_SEC);
221
+ curl_setopt($ch, CURLOPT_URL, $url);
222
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
223
+ if ($method == 'POST')
224
+ {
225
+ curl_setopt($ch, CURLOPT_POST, true);
226
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
227
+ }
228
+ elseif ($method == 'GET')
229
+ {
230
+ curl_setopt($ch, CURLOPT_HTTPGET, true);
231
+ }
232
+
233
+ if ( is_array($headers) )
234
+ {
235
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
236
+ }
237
+
238
+ curl_setopt($ch, CURLOPT_HEADER, true);
239
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
240
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
241
+
242
+ $result = curl_exec($ch);
243
+
244
+ if (!$result) return array();
245
+
246
+ // Remove 100 and 101 responses headers
247
+ if (Ait_Zend_Http_Response::extractCode($result) == 100 ||
248
+ Ait_Zend_Http_Response::extractCode($result) == 101) {
249
+ $result = preg_split('/^\r?$/m', $result, 2);
250
+ $result = trim($result[1]);
251
+ }
252
+
253
+ $oResponse = Ait_Zend_Http_Response::fromString($result);
254
+ $sResponce = trim($oResponse->getRawBody());
255
+ $aResponce = Ait_Zend_Json::decode($sResponce);
256
+
257
+ return $aResponce;
258
+ }
259
+ }
vbulletin_product/vbulletin_upload/includes/class_aitzend.php ADDED
@@ -0,0 +1,1679 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Ait_Zend_Exception extends Exception {}
4
+ class Ait_Zend_Http_Exception extends Ait_Zend_Exception {}
5
+ class Ait_Zend_Json_Exception extends Ait_Zend_Exception {}
6
+
7
+ /**
8
+ * Zend Framework
9
+ *
10
+ * LICENSE
11
+ *
12
+ * This source file is subject to the new BSD license that is bundled
13
+ * with this package in the file LICENSE.txt.
14
+ * It is also available through the world-wide-web at this URL:
15
+ * http://framework.zend.com/license/new-bsd
16
+ * If you did not receive a copy of the license and are unable to
17
+ * obtain it through the world-wide-web, please send an email
18
+ * to license@zend.com so we can send you a copy immediately.
19
+ *
20
+ * @category Zend
21
+ * @package Zend_Json
22
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
23
+ * @license http://framework.zend.com/license/new-bsd New BSD License
24
+ */
25
+
26
+ /**
27
+ * Class for encoding to and decoding from JSON.
28
+ *
29
+ * @category Zend
30
+ * @package Zend_Json
31
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
32
+ * @license http://framework.zend.com/license/new-bsd New BSD License
33
+ */
34
+ class Ait_Zend_Json
35
+ {
36
+ /**
37
+ * How objects should be encoded -- arrays or as StdClass. TYPE_ARRAY is 1
38
+ * so that it is a boolean true value, allowing it to be used with
39
+ * ext/json's functions.
40
+ */
41
+ const TYPE_ARRAY = 1;
42
+ const TYPE_OBJECT = 0;
43
+
44
+ /**
45
+ * To check the allowed nesting depth of the XML tree during xml2json conversion.
46
+ *
47
+ * @var int
48
+ */
49
+ public static $maxRecursionDepthAllowed=25;
50
+
51
+ /**
52
+ * @var bool
53
+ */
54
+ public static $useBuiltinEncoderDecoder = false;
55
+
56
+ /**
57
+ * Decodes the given $encodedValue string which is
58
+ * encoded in the JSON format
59
+ *
60
+ * Uses ext/json's json_decode if available.
61
+ *
62
+ * @param string $encodedValue Encoded in JSON format
63
+ * @param int $objectDecodeType Optional; flag indicating how to decode
64
+ * objects. See {@link Zend_Json_Decoder::decode()} for details.
65
+ * @return mixed
66
+ */
67
+ public static function decode($encodedValue, $objectDecodeType = Ait_Zend_Json::TYPE_ARRAY)
68
+ {
69
+ if (function_exists('json_decode') && self::$useBuiltinEncoderDecoder !== true) {
70
+ return json_decode($encodedValue, $objectDecodeType);
71
+ }
72
+
73
+ return Ait_Zend_Json_Decoder::decode($encodedValue, $objectDecodeType);
74
+ }
75
+
76
+
77
+ /**
78
+ * Encode the mixed $valueToEncode into the JSON format
79
+ *
80
+ * Encodes using ext/json's json_encode() if available.
81
+ *
82
+ * NOTE: Object should not contain cycles; the JSON format
83
+ * does not allow object reference.
84
+ *
85
+ * NOTE: Only public variables will be encoded
86
+ *
87
+ * @param mixed $valueToEncode
88
+ * @param boolean $cycleCheck Optional; whether or not to check for object recursion; off by default
89
+ * @param array $options Additional options used during encoding
90
+ * @return string JSON encoded object
91
+ */
92
+ public static function encode($valueToEncode, $cycleCheck = false, $options = array())
93
+ {
94
+ if (is_object($valueToEncode) && method_exists($valueToEncode, 'toJson')) {
95
+ return $valueToEncode->toJson();
96
+ }
97
+
98
+ if (function_exists('json_encode') && self::$useBuiltinEncoderDecoder !== true) {
99
+ return json_encode($valueToEncode);
100
+ }
101
+
102
+ return Ait_Zend_Json_Encoder::encode($valueToEncode, $cycleCheck, $options);
103
+ }
104
+
105
+ /**
106
+ * fromXml - Converts XML to JSON
107
+ *
108
+ * Converts a XML formatted string into a JSON formatted string.
109
+ * The value returned will be a string in JSON format.
110
+ *
111
+ * The caller of this function needs to provide only the first parameter,
112
+ * which is an XML formatted String. The second parameter is optional, which
113
+ * lets the user to select if the XML attributes in the input XML string
114
+ * should be included or ignored in xml2json conversion.
115
+ *
116
+ * This function converts the XML formatted string into a PHP array by
117
+ * calling a recursive (protected static) function in this class. Then, it
118
+ * converts that PHP array into JSON by calling the "encode" static funcion.
119
+ *
120
+ * Throws a Zend_Json_Exception if the input not a XML formatted string.
121
+ *
122
+ * @static
123
+ * @access public
124
+ * @param string $xmlStringContents XML String to be converted
125
+ * @param boolean $ignoreXmlAttributes Include or exclude XML attributes in
126
+ * the xml2json conversion process.
127
+ * @return mixed - JSON formatted string on success
128
+ * @throws Ait_Zend_Json_Exception
129
+ */
130
+ public static function fromXml ($xmlStringContents, $ignoreXmlAttributes=true) {
131
+ // Load the XML formatted string into a Simple XML Element object.
132
+ $simpleXmlElementObject = simplexml_load_string($xmlStringContents);
133
+
134
+ // If it is not a valid XML content, throw an exception.
135
+ if ($simpleXmlElementObject == null) {
136
+ throw new Ait_Zend_Json_Exception('Function fromXml was called with an invalid XML formatted string.');
137
+ } // End of if ($simpleXmlElementObject == null)
138
+
139
+ $resultArray = null;
140
+
141
+ // Call the recursive function to convert the XML into a PHP array.
142
+ $resultArray = self::_processXml($simpleXmlElementObject, $ignoreXmlAttributes);
143
+
144
+ // Convert the PHP array to JSON using Zend_Json encode method.
145
+ // It is just that simple.
146
+ $jsonStringOutput = self::encode($resultArray);
147
+ return($jsonStringOutput);
148
+ } // End of function fromXml.
149
+
150
+ /**
151
+ * _processXml - Contains the logic for xml2json
152
+ *
153
+ * The logic in this function is a recursive one.
154
+ *
155
+ * The main caller of this function (i.e. fromXml) needs to provide
156
+ * only the first two parameters i.e. the SimpleXMLElement object and
157
+ * the flag for ignoring or not ignoring XML attributes. The third parameter
158
+ * will be used internally within this function during the recursive calls.
159
+ *
160
+ * This function converts the SimpleXMLElement object into a PHP array by
161
+ * calling a recursive (protected static) function in this class. Once all
162
+ * the XML elements are stored in the PHP array, it is returned to the caller.
163
+ *
164
+ * Throws a Zend_Json_Exception if the XML tree is deeper than the allowed limit.
165
+ *
166
+ * @static
167
+ * @access protected
168
+ * @param SimpleXMLElement $simpleXmlElementObject XML element to be converted
169
+ * @param boolean $ignoreXmlAttributes Include or exclude XML attributes in
170
+ * the xml2json conversion process.
171
+ * @param int $recursionDepth Current recursion depth of this function
172
+ * @return mixed - On success, a PHP associative array of traversed XML elements
173
+ * @throws Ait_Zend_Json_Exception
174
+ */
175
+ protected static function _processXml ($simpleXmlElementObject, $ignoreXmlAttributes, $recursionDepth=0) {
176
+ // Keep an eye on how deeply we are involved in recursion.
177
+ if ($recursionDepth > self::$maxRecursionDepthAllowed) {
178
+ // XML tree is too deep. Exit now by throwing an exception.
179
+ throw new Ait_Zend_Json_Exception(
180
+ "Function _processXml exceeded the allowed recursion depth of " .
181
+ self::$maxRecursionDepthAllowed);
182
+ } // End of if ($recursionDepth > self::$maxRecursionDepthAllowed)
183
+
184
+ if ($recursionDepth == 0) {
185
+ // Store the original SimpleXmlElementObject sent by the caller.
186
+ // We will need it at the very end when we return from here for good.
187
+ $callerProvidedSimpleXmlElementObject = $simpleXmlElementObject;
188
+ } // End of if ($recursionDepth == 0)
189
+
190
+ if ($simpleXmlElementObject instanceof SimpleXMLElement) {
191
+ // Get a copy of the simpleXmlElementObject
192
+ $copyOfSimpleXmlElementObject = $simpleXmlElementObject;
193
+ // Get the object variables in the SimpleXmlElement object for us to iterate.
194
+ $simpleXmlElementObject = get_object_vars($simpleXmlElementObject);
195
+ } // End of if (get_class($simpleXmlElementObject) == "SimpleXMLElement")
196
+
197
+ // It needs to be an array of object variables.
198
+ if (is_array($simpleXmlElementObject)) {
199
+ // Initialize a result array.
200
+ $resultArray = array();
201
+ // Is the input array size 0? Then, we reached the rare CDATA text if any.
202
+ if (count($simpleXmlElementObject) <= 0) {
203
+ // Let us return the lonely CDATA. It could even be
204
+ // an empty element or just filled with whitespaces.
205
+ return (trim(strval($copyOfSimpleXmlElementObject)));
206
+ } // End of if (count($simpleXmlElementObject) <= 0)
207
+
208
+ // Let us walk through the child elements now.
209
+ foreach($simpleXmlElementObject as $key=>$value) {
210
+ // Check if we need to ignore the XML attributes.
211
+ // If yes, you can skip processing the XML attributes.
212
+ // Otherwise, add the XML attributes to the result array.
213
+ if(($ignoreXmlAttributes == true) && (is_string($key)) && ($key == "@attributes")) {
214
+ continue;
215
+ } // End of if(($ignoreXmlAttributes == true) && ($key == "@attributes"))
216
+
217
+ // Let us recursively process the current XML element we just visited.
218
+ // Increase the recursion depth by one.
219
+ $recursionDepth++;
220
+ $resultArray[$key] = self::_processXml ($value, $ignoreXmlAttributes, $recursionDepth);
221
+
222
+ // Decrease the recursion depth by one.
223
+ $recursionDepth--;
224
+ } // End of foreach($simpleXmlElementObject as $key=>$value) {
225
+
226
+ if ($recursionDepth == 0) {
227
+ // That is it. We are heading to the exit now.
228
+ // Set the XML root element name as the root [top-level] key of
229
+ // the associative array that we are going to return to the original
230
+ // caller of this recursive function.
231
+ $tempArray = $resultArray;
232
+ $resultArray = array();
233
+ $resultArray[$callerProvidedSimpleXmlElementObject->getName()] = $tempArray;
234
+ } // End of if ($recursionDepth == 0)
235
+
236
+ return($resultArray);
237
+ } else {
238
+ // We are now looking at either the XML attribute text or
239
+ // the text between the XML tags.
240
+ return (trim(strval($simpleXmlElementObject)));
241
+ } // End of if (is_array($simpleXmlElementObject))
242
+ } // End of function _processXml.
243
+ }
244
+
245
+ /**
246
+ * Encode PHP constructs to JSON
247
+ *
248
+ * @category Zend
249
+ * @package Zend_Json
250
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
251
+ * @license http://framework.zend.com/license/new-bsd New BSD License
252
+ */
253
+ class Ait_Zend_Json_Encoder
254
+ {
255
+ /**
256
+ * Whether or not to check for possible cycling
257
+ *
258
+ * @var boolean
259
+ */
260
+ protected $_cycleCheck;
261
+
262
+ /**
263
+ * Additional options used during encoding
264
+ *
265
+ * @var array
266
+ */
267
+ protected $_options = array();
268
+
269
+ /**
270
+ * Array of visited objects; used to prevent cycling.
271
+ *
272
+ * @var array
273
+ */
274
+ protected $_visited = array();
275
+
276
+ /**
277
+ * Constructor
278
+ *
279
+ * @param boolean $cycleCheck Whether or not to check for recursion when encoding
280
+ * @param array $options Additional options used during encoding
281
+ * @return void
282
+ */
283
+ protected function __construct($cycleCheck = false, $options = array())
284
+ {
285
+ $this->_cycleCheck = $cycleCheck;
286
+ $this->_options = $options;
287
+ }
288
+
289
+ /**
290
+ * Use the JSON encoding scheme for the value specified
291
+ *
292
+ * @param mixed $value The value to be encoded
293
+ * @param boolean $cycleCheck Whether or not to check for possible object recursion when encoding
294
+ * @param array $options Additional options used during encoding
295
+ * @return string The encoded value
296
+ */
297
+ public static function encode($value, $cycleCheck = false, $options = array())
298
+ {
299
+ $encoder = new self(($cycleCheck) ? true : false, $options);
300
+
301
+ return $encoder->_encodeValue($value);
302
+ }
303
+
304
+ /**
305
+ * Recursive driver which determines the type of value to be encoded
306
+ * and then dispatches to the appropriate method. $values are either
307
+ * - objects (returns from {@link _encodeObject()})
308
+ * - arrays (returns from {@link _encodeArray()})
309
+ * - basic datums (e.g. numbers or strings) (returns from {@link _encodeDatum()})
310
+ *
311
+ * @param $value mixed The value to be encoded
312
+ * @return string Encoded value
313
+ */
314
+ protected function _encodeValue(&$value)
315
+ {
316
+ if (is_object($value)) {
317
+ return $this->_encodeObject($value);
318
+ } else if (is_array($value)) {
319
+ return $this->_encodeArray($value);
320
+ }
321
+
322
+ return $this->_encodeDatum($value);
323
+ }
324
+
325
+ /**
326
+ * Encode an object to JSON by encoding each of the public properties
327
+ *
328
+ * A special property is added to the JSON object called '__className'
329
+ * that contains the name of the class of $value. This is used to decode
330
+ * the object on the client into a specific class.
331
+ *
332
+ * @param $value object
333
+ * @return string
334
+ * @throws Ait_Zend_Json_Exception If recursive checks are enabled and the object has been serialized previously
335
+ */
336
+ protected function _encodeObject(&$value)
337
+ {
338
+ if ($this->_cycleCheck) {
339
+ if ($this->_wasVisited($value)) {
340
+
341
+ if (isset($this->_options['silenceCyclicalExceptions'])
342
+ && $this->_options['silenceCyclicalExceptions']===true) {
343
+
344
+ return '"* RECURSION (' . get_class($value) . ') *"';
345
+
346
+ } else {
347
+ throw new Ait_Zend_Json_Exception(
348
+ 'Cycles not supported in JSON encoding, cycle introduced by '
349
+ . 'class "' . get_class($value) . '"'
350
+ );
351
+ }
352
+ }
353
+
354
+ $this->_visited[] = $value;
355
+ }
356
+
357
+ $props = '';
358
+
359
+ if ($value instanceof Iterator) {
360
+ $propCollection = $value;
361
+ } else {
362
+ $propCollection = get_object_vars($value);
363
+ }
364
+
365
+ foreach ($propCollection as $name => $propValue) {
366
+ if (isset($propValue)) {
367
+ $props .= ','
368
+ . $this->_encodeValue($name)
369
+ . ':'
370
+ . $this->_encodeValue($propValue);
371
+ }
372
+ }
373
+
374
+ return '{"__className":"' . get_class($value) . '"'
375
+ . $props . '}';
376
+ }
377
+
378
+ /**
379
+ * Determine if an object has been serialized already
380
+ *
381
+ * @param mixed $value
382
+ * @return boolean
383
+ */
384
+ protected function _wasVisited(&$value)
385
+ {
386
+ if (in_array($value, $this->_visited, true)) {
387
+ return true;
388
+ }
389
+
390
+ return false;
391
+ }
392
+
393
+ /**
394
+ * JSON encode an array value
395
+ *
396
+ * Recursively encodes each value of an array and returns a JSON encoded
397
+ * array string.
398
+ *
399
+ * Arrays are defined as integer-indexed arrays starting at index 0, where
400
+ * the last index is (count($array) -1); any deviation from that is
401
+ * considered an associative array, and will be encoded as such.
402
+ *
403
+ * @param $array array
404
+ * @return string
405
+ */
406
+ protected function _encodeArray(&$array)
407
+ {
408
+ $tmpArray = array();
409
+
410
+ // Check for associative array
411
+ if (!empty($array) && (array_keys($array) !== range(0, count($array) - 1))) {
412
+ // Associative array
413
+ $result = '{';
414
+ foreach ($array as $key => $value) {
415
+ $key = (string) $key;
416
+ $tmpArray[] = $this->_encodeString($key)
417
+ . ':'
418
+ . $this->_encodeValue($value);
419
+ }
420
+ $result .= implode(',', $tmpArray);
421
+ $result .= '}';
422
+ } else {
423
+ // Indexed array
424
+ $result = '[';
425
+ $length = count($array);
426
+ for ($i = 0; $i < $length; $i++) {
427
+ $tmpArray[] = $this->_encodeValue($array[$i]);
428
+ }
429
+ $result .= implode(',', $tmpArray);
430
+ $result .= ']';
431
+ }
432
+
433
+ return $result;
434
+ }
435
+
436
+ /**
437
+ * JSON encode a basic data type (string, number, boolean, null)
438
+ *
439
+ * If value type is not a string, number, boolean, or null, the string
440
+ * 'null' is returned.
441
+ *
442
+ * @param $value mixed
443
+ * @return string
444
+ */
445
+ protected function _encodeDatum(&$value)
446
+ {
447
+ $result = 'null';
448
+
449
+ if (is_int($value) || is_float($value)) {
450
+ $result = (string) $value;
451
+ } elseif (is_string($value)) {
452
+ $result = $this->_encodeString($value);
453
+ } elseif (is_bool($value)) {
454
+ $result = $value ? 'true' : 'false';
455
+ }
456
+
457
+ return $result;
458
+ }
459
+
460
+ /**
461
+ * JSON encode a string value by escaping characters as necessary
462
+ *
463
+ * @param $value string
464
+ * @return string
465
+ */
466
+ protected function _encodeString(&$string)
467
+ {
468
+ // Escape these characters with a backslash:
469
+ // " \ / \n \r \t \b \f
470
+ $search = array('\\', "\n", "\t", "\r", "\b", "\f", '"');
471
+ $replace = array('\\\\', '\\n', '\\t', '\\r', '\\b', '\\f', '\"');
472
+ $string = str_replace($search, $replace, $string);
473
+
474
+ // Escape certain ASCII characters:
475
+ // 0x08 => \b
476
+ // 0x0c => \f
477
+ $string = str_replace(array(chr(0x08), chr(0x0C)), array('\b', '\f'), $string);
478
+
479
+ return '"' . $string . '"';
480
+ }
481
+
482
+ /**
483
+ * Encode the constants associated with the ReflectionClass
484
+ * parameter. The encoding format is based on the class2 format
485
+ *
486
+ * @param $cls ReflectionClass
487
+ * @return string Encoded constant block in class2 format
488
+ */
489
+ private static function _encodeConstants(ReflectionClass $cls)
490
+ {
491
+ $result = "constants : {";
492
+ $constants = $cls->getConstants();
493
+
494
+ $tmpArray = array();
495
+ if (!empty($constants)) {
496
+ foreach ($constants as $key => $value) {
497
+ $tmpArray[] = "$key: " . self::encode($value);
498
+ }
499
+
500
+ $result .= implode(', ', $tmpArray);
501
+ }
502
+
503
+ return $result . "}";
504
+ }
505
+
506
+ /**
507
+ * Encode the public methods of the ReflectionClass in the
508
+ * class2 format
509
+ *
510
+ * @param $cls ReflectionClass
511
+ * @return string Encoded method fragment
512
+ *
513
+ */
514
+ private static function _encodeMethods(ReflectionClass $cls)
515
+ {
516
+ $methods = $cls->getMethods();
517
+ $result = 'methods:{';
518
+
519
+ $started = false;
520
+ foreach ($methods as $method) {
521
+ if (! $method->isPublic() || !$method->isUserDefined()) {
522
+ continue;
523
+ }
524
+
525
+ if ($started) {
526
+ $result .= ',';
527
+ }
528
+ $started = true;
529
+
530
+ $result .= '' . $method->getName(). ':function(';
531
+
532
+ if ('__construct' != $method->getName()) {
533
+ $parameters = $method->getParameters();
534
+ $paramCount = count($parameters);
535
+ $argsStarted = false;
536
+
537
+ $argNames = "var argNames=[";
538
+ foreach ($parameters as $param) {
539
+ if ($argsStarted) {
540
+ $result .= ',';
541
+ }
542
+
543
+ $result .= $param->getName();
544
+
545
+ if ($argsStarted) {
546
+ $argNames .= ',';
547
+ }
548
+
549
+ $argNames .= '"' . $param->getName() . '"';
550
+
551
+ $argsStarted = true;
552
+ }
553
+ $argNames .= "];";
554
+
555
+ $result .= "){"
556
+ . $argNames
557
+ . 'var result = ZAjaxEngine.invokeRemoteMethod('
558
+ . "this, '" . $method->getName()
559
+ . "',argNames,arguments);"
560
+ . 'return(result);}';
561
+ } else {
562
+ $result .= "){}";
563
+ }
564
+ }
565
+
566
+ return $result . "}";
567
+ }
568
+
569
+ /**
570
+ * Encode the public properties of the ReflectionClass in the class2
571
+ * format.
572
+ *
573
+ * @param $cls ReflectionClass
574
+ * @return string Encode properties list
575
+ *
576
+ */
577
+ private static function _encodeVariables(ReflectionClass $cls)
578
+ {
579
+ $properties = $cls->getProperties();
580
+ $propValues = get_class_vars($cls->getName());
581
+ $result = "variables:{";
582
+ $cnt = 0;
583
+
584
+ $tmpArray = array();
585
+ foreach ($properties as $prop) {
586
+ if (! $prop->isPublic()) {
587
+ continue;
588
+ }
589
+
590
+ $tmpArray[] = $prop->getName()
591
+ . ':'
592
+ . self::encode($propValues[$prop->getName()]);
593
+ }
594
+ $result .= implode(',', $tmpArray);
595
+
596
+ return $result . "}";
597
+ }
598
+
599
+ /**
600
+ * Encodes the given $className into the class2 model of encoding PHP
601
+ * classes into JavaScript class2 classes.
602
+ * NOTE: Currently only public methods and variables are proxied onto
603
+ * the client machine
604
+ *
605
+ * @param $className string The name of the class, the class must be
606
+ * instantiable using a null constructor
607
+ * @param $package string Optional package name appended to JavaScript
608
+ * proxy class name
609
+ * @return string The class2 (JavaScript) encoding of the class
610
+ * @throws Ait_Zend_Json_Exception
611
+ */
612
+ public static function encodeClass($className, $package = '')
613
+ {
614
+ $cls = new ReflectionClass($className);
615
+ if (! $cls->isInstantiable()) {
616
+ throw new Ait_Zend_Json_Exception("$className must be instantiable");
617
+ }
618
+
619
+ return "Class.create('$package$className',{"
620
+ . self::_encodeConstants($cls) .","
621
+ . self::_encodeMethods($cls) .","
622
+ . self::_encodeVariables($cls) .'});';
623
+ }
624
+
625
+ /**
626
+ * Encode several classes at once
627
+ *
628
+ * Returns JSON encoded classes, using {@link encodeClass()}.
629
+ *
630
+ * @param array $classNames
631
+ * @param string $package
632
+ * @return string
633
+ */
634
+ public static function encodeClasses(array $classNames, $package = '')
635
+ {
636
+ $result = '';
637
+ foreach ($classNames as $className) {
638
+ $result .= self::encodeClass($className, $package);
639
+ }
640
+
641
+ return $result;
642
+ }
643
+ }
644
+
645
+ /**
646
+ * Decode JSON encoded string to PHP variable constructs
647
+ *
648
+ * @category Zend
649
+ * @package Zend_Json
650
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
651
+ * @license http://framework.zend.com/license/new-bsd New BSD License
652
+ */
653
+ class Ait_Zend_Json_Decoder
654
+ {
655
+ /**
656
+ * Parse tokens used to decode the JSON object. These are not
657
+ * for public consumption, they are just used internally to the
658
+ * class.
659
+ */
660
+ const EOF = 0;
661
+ const DATUM = 1;
662
+ const LBRACE = 2;
663
+ const LBRACKET = 3;
664
+ const RBRACE = 4;
665
+ const RBRACKET = 5;
666
+ const COMMA = 6;
667
+ const COLON = 7;
668
+
669
+ /**
670
+ * Use to maintain a "pointer" to the source being decoded
671
+ *
672
+ * @var string
673
+ */
674
+ protected $_source;
675
+
676
+ /**
677
+ * Caches the source length
678
+ *
679
+ * @var int
680
+ */
681
+ protected $_sourceLength;
682
+
683
+ /**
684
+ * The offset within the souce being decoded
685
+ *
686
+ * @var int
687
+ *
688
+ */
689
+ protected $_offset;
690
+
691
+ /**
692
+ * The current token being considered in the parser cycle
693
+ *
694
+ * @var int
695
+ */
696
+ protected $_token;
697
+
698
+ /**
699
+ * Flag indicating how objects should be decoded
700
+ *
701
+ * @var int
702
+ * @access protected
703
+ */
704
+ protected $_decodeType;
705
+
706
+ /**
707
+ * Constructor
708
+ *
709
+ * @param string $source String source to decode
710
+ * @param int $decodeType How objects should be decoded -- see
711
+ * {@link Zend_Json::TYPE_ARRAY} and {@link Zend_Json::TYPE_OBJECT} for
712
+ * valid values
713
+ * @return void
714
+ */
715
+ protected function __construct($source, $decodeType)
716
+ {
717
+ // Set defaults
718
+ $this->_source = $source;
719
+ $this->_sourceLength = strlen($source);
720
+ $this->_token = self::EOF;
721
+ $this->_offset = 0;
722
+
723
+ // Normalize and set $decodeType
724
+ if (!in_array($decodeType, array(Ait_Zend_Json::TYPE_ARRAY, Ait_Zend_Json::TYPE_OBJECT)))
725
+ {
726
+ $decodeType = Ait_Zend_Json::TYPE_ARRAY;
727
+ }
728
+ $this->_decodeType = $decodeType;
729
+
730
+ // Set pointer at first token
731
+ $this->_getNextToken();
732
+ }
733
+
734
+ /**
735
+ * Decode a JSON source string
736
+ *
737
+ * Decodes a JSON encoded string. The value returned will be one of the
738
+ * following:
739
+ * - integer
740
+ * - float
741
+ * - boolean
742
+ * - null
743
+ * - StdClass
744
+ * - array
745
+ * - array of one or more of the above types
746
+ *
747
+ * By default, decoded objects will be returned as associative arrays; to
748
+ * return a StdClass object instead, pass {@link Zend_Json::TYPE_OBJECT} to
749
+ * the $objectDecodeType parameter.
750
+ *
751
+ * Throws a Zend_Json_Exception if the source string is null.
752
+ *
753
+ * @static
754
+ * @access public
755
+ * @param string $source String to be decoded
756
+ * @param int $objectDecodeType How objects should be decoded; should be
757
+ * either or {@link Zend_Json::TYPE_ARRAY} or
758
+ * {@link Zend_Json::TYPE_OBJECT}; defaults to TYPE_ARRAY
759
+ * @return mixed
760
+ * @throws Ait_Zend_Json_Exception
761
+ */
762
+ public static function decode($source = null, $objectDecodeType = Ait_Zend_Json::TYPE_ARRAY)
763
+ {
764
+ if (null === $source) {
765
+ throw new Ait_Zend_Json_Exception('Must specify JSON encoded source for decoding');
766
+ } elseif (!is_string($source)) {
767
+ throw new Ait_Zend_Json_Exception('Can only decode JSON encoded strings');
768
+ }
769
+
770
+ $decoder = new self($source, $objectDecodeType);
771
+
772
+ return $decoder->_decodeValue();
773
+ }
774
+
775
+ /**
776
+ * Recursive driving rountine for supported toplevel tops
777
+ *
778
+ * @return mixed
779
+ */
780
+ protected function _decodeValue()
781
+ {
782
+ switch ($this->_token) {
783
+ case self::DATUM:
784
+ $result = $this->_tokenValue;
785
+ $this->_getNextToken();
786
+ return($result);
787
+ break;
788
+ case self::LBRACE:
789
+ return($this->_decodeObject());
790
+ break;
791
+ case self::LBRACKET:
792
+ return($this->_decodeArray());
793
+ break;
794
+ default:
795
+ return null;
796
+ break;
797
+ }
798
+ }
799
+
800
+ /**
801
+ * Decodes an object of the form:
802
+ * { "attribute: value, "attribute2" : value,...}
803
+ *
804
+ * If Zend_Json_Encoder was used to encode the original object then
805
+ * a special attribute called __className which specifies a class
806
+ * name that should wrap the data contained within the encoded source.
807
+ *
808
+ * Decodes to either an array or StdClass object, based on the value of
809
+ * {@link $_decodeType}. If invalid $_decodeType present, returns as an
810
+ * array.
811
+ *
812
+ * @return array|StdClass
813
+ */
814
+ protected function _decodeObject()
815
+ {
816
+ $members = array();
817
+ $tok = $this->_getNextToken();
818
+
819
+ while ($tok && $tok != self::RBRACE) {
820
+ if ($tok != self::DATUM || ! is_string($this->_tokenValue)) {
821
+ throw new Ait_Zend_Json_Exception('Missing key in object encoding: ' . $this->_source);
822
+ }
823
+
824
+ $key = $this->_tokenValue;
825
+ $tok = $this->_getNextToken();
826
+
827
+ if ($tok != self::COLON) {
828
+ throw new Ait_Zend_Json_Exception('Missing ":" in object encoding: ' . $this->_source);
829
+ }
830
+
831
+ $tok = $this->_getNextToken();
832
+ $members[$key] = $this->_decodeValue();
833
+ $tok = $this->_token;
834
+
835
+ if ($tok == self::RBRACE) {
836
+ break;
837
+ }
838
+
839
+ if ($tok != self::COMMA) {
840
+ throw new Ait_Zend_Json_Exception('Missing "," in object encoding: ' . $this->_source);
841
+ }
842
+
843
+ $tok = $this->_getNextToken();
844
+ }
845
+
846
+ switch ($this->_decodeType) {
847
+ case Ait_Zend_Json::TYPE_OBJECT:
848
+ // Create new StdClass and populate with $members
849
+ $result = new StdClass();
850
+ foreach ($members as $key => $value) {
851
+ $result->$key = $value;
852
+ }
853
+ break;
854
+ case Ait_Zend_Json::TYPE_ARRAY:
855
+ default:
856
+ $result = $members;
857
+ break;
858
+ }
859
+
860
+ $this->_getNextToken();
861
+ return $result;
862
+ }
863
+
864
+ /**
865
+ * Decodes a JSON array format:
866
+ * [element, element2,...,elementN]
867
+ *
868
+ * @return array
869
+ */
870
+ protected function _decodeArray()
871
+ {
872
+ $result = array();
873
+ $starttok = $tok = $this->_getNextToken(); // Move past the '['
874
+ $index = 0;
875
+
876
+ while ($tok && $tok != self::RBRACKET) {
877
+ $result[$index++] = $this->_decodeValue();
878
+
879
+ $tok = $this->_token;
880
+
881
+ if ($tok == self::RBRACKET || !$tok) {
882
+ break;
883
+ }
884
+
885
+ if ($tok != self::COMMA) {
886
+ throw new Ait_Zend_Json_Exception('Missing "," in array encoding: ' . $this->_source);
887
+ }
888
+
889
+ $tok = $this->_getNextToken();
890
+ }
891
+
892
+ $this->_getNextToken();
893
+ return($result);
894
+ }
895
+
896
+ /**
897
+ * Removes whitepsace characters from the source input
898
+ */
899
+ protected function _eatWhitespace()
900
+ {
901
+ if (preg_match(
902
+ '/([\t\b\f\n\r ])*/s',
903
+ $this->_source,
904
+ $matches,
905
+ PREG_OFFSET_CAPTURE,
906
+ $this->_offset)
907
+ && $matches[0][1] == $this->_offset)
908
+ {
909
+ $this->_offset += strlen($matches[0][0]);
910
+ }
911
+ }
912
+
913
+ /**
914
+ * Retrieves the next token from the source stream
915
+ *
916
+ * @return int Token constant value specified in class definition
917
+ */
918
+ protected function _getNextToken()
919
+ {
920
+ $this->_token = self::EOF;
921
+ $this->_tokenValue = null;
922
+ $this->_eatWhitespace();
923
+
924
+ if ($this->_offset >= $this->_sourceLength) {
925
+ return(self::EOF);
926
+ }
927
+
928
+ $str = $this->_source;
929
+ $str_length = $this->_sourceLength;
930
+ $i = $this->_offset;
931
+ $start = $i;
932
+
933
+ switch ($str{$i}) {
934
+ case '{':
935
+ $this->_token = self::LBRACE;
936
+ break;
937
+ case '}':
938
+ $this->_token = self::RBRACE;
939
+ break;
940
+ case '[':
941
+ $this->_token = self::LBRACKET;
942
+ break;
943
+ case ']':
944
+ $this->_token = self::RBRACKET;
945
+ break;
946
+ case ',':
947
+ $this->_token = self::COMMA;
948
+ break;
949
+ case ':':
950
+ $this->_token = self::COLON;
951
+ break;
952
+ case '"':
953
+ $result = '';
954
+ do {
955
+ $i++;
956
+ if ($i >= $str_length) {
957
+ break;
958
+ }
959
+
960
+ $chr = $str{$i};
961
+ if ($chr == '\\') {
962
+ $i++;
963
+ if ($i >= $str_length) {
964
+ break;
965
+ }
966
+ $chr = $str{$i};
967
+ switch ($chr) {
968
+ case '"' :
969
+ $result .= '"';
970
+ break;
971
+ case '\\':
972
+ $result .= '\\';
973
+ break;
974
+ case '/' :
975
+ $result .= '/';
976
+ break;
977
+ case 'b' :
978
+ $result .= chr(8);
979
+ break;
980
+ case 'f' :
981
+ $result .= chr(12);
982
+ break;
983
+ case 'n' :
984
+ $result .= chr(10);
985
+ break;
986
+ case 'r' :
987
+ $result .= chr(13);
988
+ break;
989
+ case 't' :
990
+ $result .= chr(9);
991
+ break;
992
+ case '\'' :
993
+ $result .= '\'';
994
+ break;
995
+ default:
996
+ throw new Ait_Zend_Json_Exception("Illegal escape "
997
+ . "sequence '" . $chr . "'");
998
+ }
999
+ } elseif ($chr == '"') {
1000
+ break;
1001
+ } else {
1002
+ $result .= $chr;
1003
+ }
1004
+ } while ($i < $str_length);
1005
+
1006
+ $this->_token = self::DATUM;
1007
+ //$this->_tokenValue = substr($str, $start + 1, $i - $start - 1);
1008
+ $this->_tokenValue = $result;
1009
+ break;
1010
+ case 't':
1011
+ if (($i+ 3) < $str_length && substr($str, $start, 4) == "true") {
1012
+ $this->_token = self::DATUM;
1013
+ }
1014
+ $this->_tokenValue = true;
1015
+ $i += 3;
1016
+ break;
1017
+ case 'f':
1018
+ if (($i+ 4) < $str_length && substr($str, $start, 5) == "false") {
1019
+ $this->_token = self::DATUM;
1020
+ }
1021
+ $this->_tokenValue = false;
1022
+ $i += 4;
1023
+ break;
1024
+ case 'n':
1025
+ if (($i+ 3) < $str_length && substr($str, $start, 4) == "null") {
1026
+ $this->_token = self::DATUM;
1027
+ }
1028
+ $this->_tokenValue = NULL;
1029
+ $i += 3;
1030
+ break;
1031
+ }
1032
+
1033
+ if ($this->_token != self::EOF) {
1034
+ $this->_offset = $i + 1; // Consume the last token character
1035
+ return($this->_token);
1036
+ }
1037
+
1038
+ $chr = $str{$i};
1039
+ if ($chr == '-' || $chr == '.' || ($chr >= '0' && $chr <= '9')) {
1040
+ if (preg_match('/-?([0-9])*(\.[0-9]*)?((e|E)((-|\+)?)[0-9]+)?/s',
1041
+ $str, $matches, PREG_OFFSET_CAPTURE, $start) && $matches[0][1] == $start) {
1042
+
1043
+ $datum = $matches[0][0];
1044
+
1045
+ if (is_numeric($datum)) {
1046
+ if (preg_match('/^0\d+$/', $datum)) {
1047
+ throw new Ait_Zend_Json_Exception("Octal notation not supported by JSON (value: $datum)");
1048
+ } else {
1049
+ $val = intval($datum);
1050
+ $fVal = floatval($datum);
1051
+ $this->_tokenValue = ($val == $fVal ? $val : $fVal);
1052
+ }
1053
+ } else {
1054
+ throw new Ait_Zend_Json_Exception("Illegal number format: $datum");
1055
+ }
1056
+
1057
+ $this->_token = self::DATUM;
1058
+ $this->_offset = $start + strlen($datum);
1059
+ }
1060
+ } else {
1061
+ throw new Ait_Zend_Json_Exception('Illegal Token');
1062
+ }
1063
+
1064
+ return($this->_token);
1065
+ }
1066
+ }
1067
+
1068
+ /**
1069
+ * Zend Framework
1070
+ *
1071
+ * LICENSE
1072
+ *
1073
+ * This source file is subject to the new BSD license that is bundled
1074
+ * with this package in the file LICENSE.txt.
1075
+ * It is also available through the world-wide-web at this URL:
1076
+ * http://framework.zend.com/license/new-bsd
1077
+ * If you did not receive a copy of the license and are unable to
1078
+ * obtain it through the world-wide-web, please send an email
1079
+ * to license@zend.com so we can send you a copy immediately.
1080
+ *
1081
+ * @category Zend
1082
+ * @package Zend_Http
1083
+ * @subpackage Response
1084
+ * @version $Id: Response.php 12519 2008-11-10 18:41:24Z alexander $
1085
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
1086
+ * @license http://framework.zend.com/license/new-bsd New BSD License
1087
+ */
1088
+
1089
+ /**
1090
+ * Zend_Http_Response represents an HTTP 1.0 / 1.1 response message. It
1091
+ * includes easy access to all the response's different elemts, as well as some
1092
+ * convenience methods for parsing and validating HTTP responses.
1093
+ *
1094
+ * @package Zend_Http
1095
+ * @subpackage Response
1096
+ * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
1097
+ * @license http://framework.zend.com/license/new-bsd New BSD License
1098
+ */
1099
+ class Ait_Zend_Http_Response
1100
+ {
1101
+ /**
1102
+ * List of all known HTTP response codes - used by responseCodeAsText() to
1103
+ * translate numeric codes to messages.
1104
+ *
1105
+ * @var array
1106
+ */
1107
+ protected static $messages = array(
1108
+ // Informational 1xx
1109
+ 100 => 'Continue',
1110
+ 101 => 'Switching Protocols',
1111
+
1112
+ // Success 2xx
1113
+ 200 => 'OK',
1114
+ 201 => 'Created',
1115
+ 202 => 'Accepted',
1116
+ 203 => 'Non-Authoritative Information',
1117
+ 204 => 'No Content',
1118
+ 205 => 'Reset Content',
1119
+ 206 => 'Partial Content',
1120
+
1121
+ // Redirection 3xx
1122
+ 300 => 'Multiple Choices',
1123
+ 301 => 'Moved Permanently',
1124
+ 302 => 'Found', // 1.1
1125
+ 303 => 'See Other',
1126
+ 304 => 'Not Modified',
1127
+ 305 => 'Use Proxy',
1128
+ // 306 is deprecated but reserved
1129
+ 307 => 'Temporary Redirect',
1130
+
1131
+ // Client Error 4xx
1132
+ 400 => 'Bad Request',
1133
+ 401 => 'Unauthorized',
1134
+ 402 => 'Payment Required',
1135
+ 403 => 'Forbidden',
1136
+ 404 => 'Not Found',
1137
+ 405 => 'Method Not Allowed',
1138
+ 406 => 'Not Acceptable',
1139
+ 407 => 'Proxy Authentication Required',
1140
+ 408 => 'Request Timeout',
1141
+ 409 => 'Conflict',
1142
+ 410 => 'Gone',
1143
+ 411 => 'Length Required',
1144
+ 412 => 'Precondition Failed',
1145
+ 413 => 'Request Entity Too Large',
1146
+ 414 => 'Request-URI Too Long',
1147
+ 415 => 'Unsupported Media Type',
1148
+ 416 => 'Requested Range Not Satisfiable',
1149
+ 417 => 'Expectation Failed',
1150
+
1151
+ // Server Error 5xx
1152
+ 500 => 'Internal Server Error',
1153
+ 501 => 'Not Implemented',
1154
+ 502 => 'Bad Gateway',
1155
+ 503 => 'Service Unavailable',
1156
+ 504 => 'Gateway Timeout',
1157
+ 505 => 'HTTP Version Not Supported',
1158
+ 509 => 'Bandwidth Limit Exceeded'
1159
+ );
1160
+
1161
+ /**
1162
+ * The HTTP version (1.0, 1.1)
1163
+ *
1164
+ * @var string
1165
+ */
1166
+ protected $version;
1167
+
1168
+ /**
1169
+ * The HTTP response code
1170
+ *
1171
+ * @var int
1172
+ */
1173
+ protected $code;
1174
+
1175
+ /**
1176
+ * The HTTP response code as string
1177
+ * (e.g. 'Not Found' for 404 or 'Internal Server Error' for 500)
1178
+ *
1179
+ * @var string
1180
+ */
1181
+ protected $message;
1182
+
1183
+ /**
1184
+ * The HTTP response headers array
1185
+ *
1186
+ * @var array
1187
+ */
1188
+ protected $headers = array();
1189
+
1190
+ /**
1191
+ * The HTTP response body
1192
+ *
1193
+ * @var string
1194
+ */
1195
+ protected $body;
1196
+
1197
+ /**
1198
+ * HTTP response constructor
1199
+ *
1200
+ * In most cases, you would use Zend_Http_Response::fromString to parse an HTTP
1201
+ * response string and create a new Zend_Http_Response object.
1202
+ *
1203
+ * NOTE: The constructor no longer accepts nulls or empty values for the code and
1204
+ * headers and will throw an exception if the passed values do not form a valid HTTP
1205
+ * responses.
1206
+ *
1207
+ * If no message is passed, the message will be guessed according to the response code.
1208
+ *
1209
+ * @param int $code Response code (200, 404, ...)
1210
+ * @param array $headers Headers array
1211
+ * @param string $body Response body
1212
+ * @param string $version HTTP version
1213
+ * @param string $message Response code as text
1214
+ * @throws Ait_Zend_Http_Exception
1215
+ */
1216
+ public function __construct($code, $headers, $body = null, $version = '1.1', $message = null)
1217
+ {
1218
+ // Make sure the response code is valid and set it
1219
+ if (self::responseCodeAsText($code) === null) {
1220
+ throw new Ait_Zend_Http_Exception("{$code} is not a valid HTTP response code");
1221
+ }
1222
+
1223
+ $this->code = $code;
1224
+
1225
+ // Make sure we got valid headers and set them
1226
+ if (! is_array($headers)) {
1227
+ throw new Ait_Zend_Http_Exception('No valid headers were passed');
1228
+ }
1229
+
1230
+ foreach ($headers as $name => $value) {
1231
+ if (is_int($name))
1232
+ list($name, $value) = explode(": ", $value, 1);
1233
+
1234
+ $this->headers[ucwords(strtolower($name))] = $value;
1235
+ }
1236
+
1237
+ // Set the body
1238
+ $this->body = $body;
1239
+
1240
+ // Set the HTTP version
1241
+ if (! preg_match('|^\d\.\d$|', $version)) {
1242
+ throw new Ait_Zend_Http_Exception("Invalid HTTP response version: $version");
1243
+ }
1244
+
1245
+ $this->version = $version;
1246
+
1247
+ // If we got the response message, set it. Else, set it according to
1248
+ // the response code
1249
+ if (is_string($message)) {
1250
+ $this->message = $message;
1251
+ } else {
1252
+ $this->message = self::responseCodeAsText($code);
1253
+ }
1254
+ }
1255
+
1256
+ /**
1257
+ * Check whether the response is an error
1258
+ *
1259
+ * @return boolean
1260
+ */
1261
+ public function isError()
1262
+ {
1263
+ $restype = floor($this->code / 100);
1264
+ if ($restype == 4 || $restype == 5) {
1265
+ return true;
1266
+ }
1267
+
1268
+ return false;
1269
+ }
1270
+
1271
+ /**
1272
+ * Check whether the response in successful
1273
+ *
1274
+ * @return boolean
1275
+ */
1276
+ public function isSuccessful()
1277
+ {
1278
+ $restype = floor($this->code / 100);
1279
+ if ($restype == 2 || $restype == 1) { // Shouldn't 3xx count as success as well ???
1280
+ return true;
1281
+ }
1282
+
1283
+ return false;
1284
+ }
1285
+
1286
+ /**
1287
+ * Check whether the response is a redirection
1288
+ *
1289
+ * @return boolean
1290
+ */
1291
+ public function isRedirect()
1292
+ {
1293
+ $restype = floor($this->code / 100);
1294
+ if ($restype == 3) {
1295
+ return true;
1296
+ }
1297
+
1298
+ return false;
1299
+ }
1300
+
1301
+ /**
1302
+ * Get the response body as string
1303
+ *
1304
+ * This method returns the body of the HTTP response (the content), as it
1305
+ * should be in it's readable version - that is, after decoding it (if it
1306
+ * was decoded), deflating it (if it was gzip compressed), etc.
1307
+ *
1308
+ * If you want to get the raw body (as transfered on wire) use
1309
+ * $this->getRawBody() instead.
1310
+ *
1311
+ * @return string
1312
+ */
1313
+ public function getBody()
1314
+ {
1315
+ $body = '';
1316
+
1317
+ // Decode the body if it was transfer-encoded
1318
+ switch ($this->getHeader('transfer-encoding')) {
1319
+
1320
+ // Handle chunked body
1321
+ case 'chunked':
1322
+ $body = self::decodeChunkedBody($this->body);
1323
+ break;
1324
+
1325
+ // No transfer encoding, or unknown encoding extension:
1326
+ // return body as is
1327
+ default:
1328
+ $body = $this->body;
1329
+ break;
1330
+ }
1331
+
1332
+ // Decode any content-encoding (gzip or deflate) if needed
1333
+ switch (strtolower($this->getHeader('content-encoding'))) {
1334
+
1335
+ // Handle gzip encoding
1336
+ case 'gzip':
1337
+ $body = self::decodeGzip($body);
1338
+ break;
1339
+
1340
+ // Handle deflate encoding
1341
+ case 'deflate':
1342
+ $body = self::decodeDeflate($body);
1343
+ break;
1344
+
1345
+ default:
1346
+ break;
1347
+ }
1348
+
1349
+ return $body;
1350
+ }
1351
+
1352
+ /**
1353
+ * Get the raw response body (as transfered "on wire") as string
1354
+ *
1355
+ * If the body is encoded (with Transfer-Encoding, not content-encoding -
1356
+ * IE "chunked" body), gzip compressed, etc. it will not be decoded.
1357
+ *
1358
+ * @return string
1359
+ */
1360
+ public function getRawBody()
1361
+ {
1362
+ return $this->body;
1363
+ }
1364
+
1365
+ /**
1366
+ * Get the HTTP version of the response
1367
+ *
1368
+ * @return string
1369
+ */
1370
+ public function getVersion()
1371
+ {
1372
+ return $this->version;
1373
+ }
1374
+
1375
+ /**
1376
+ * Get the HTTP response status code
1377
+ *
1378
+ * @return int
1379
+ */
1380
+ public function getStatus()
1381
+ {
1382
+ return $this->code;
1383
+ }
1384
+
1385
+ /**
1386
+ * Return a message describing the HTTP response code
1387
+ * (Eg. "OK", "Not Found", "Moved Permanently")
1388
+ *
1389
+ * @return string
1390
+ */
1391
+ public function getMessage()
1392
+ {
1393
+ return $this->message;
1394
+ }
1395
+
1396
+ /**
1397
+ * Get the response headers
1398
+ *
1399
+ * @return array
1400
+ */
1401
+ public function getHeaders()
1402
+ {
1403
+ return $this->headers;
1404
+ }
1405
+
1406
+ /**
1407
+ * Get a specific header as string, or null if it is not set
1408
+ *
1409
+ * @param string$header
1410
+ * @return string|array|null
1411
+ */
1412
+ public function getHeader($header)
1413
+ {
1414
+ $header = ucwords(strtolower($header));
1415
+ if (! is_string($header) || ! isset($this->headers[$header])) return null;
1416
+
1417
+ return $this->headers[$header];
1418
+ }
1419
+
1420
+ /**
1421
+ * Get all headers as string
1422
+ *
1423
+ * @param boolean $status_line Whether to return the first status line (IE "HTTP 200 OK")
1424
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
1425
+ * @return string
1426
+ */
1427
+ public function getHeadersAsString($status_line = true, $br = "\n")
1428
+ {
1429
+ $str = '';
1430
+
1431
+ if ($status_line) {
1432
+ $str = "HTTP/{$this->version} {$this->code} {$this->message}{$br}";
1433
+ }
1434
+
1435
+ // Iterate over the headers and stringify them
1436
+ foreach ($this->headers as $name => $value)
1437
+ {
1438
+ if (is_string($value))
1439
+ $str .= "{$name}: {$value}{$br}";
1440
+
1441
+ elseif (is_array($value)) {
1442
+ foreach ($value as $subval) {
1443
+ $str .= "{$name}: {$subval}{$br}";
1444
+ }
1445
+ }
1446
+ }
1447
+
1448
+ return $str;
1449
+ }
1450
+
1451
+ /**
1452
+ * Get the entire response as string
1453
+ *
1454
+ * @param string $br Line breaks (eg. "\n", "\r\n", "<br />")
1455
+ * @return string
1456
+ */
1457
+ public function asString($br = "\n")
1458
+ {
1459
+ return $this->getHeadersAsString(true, $br) . $br . $this->getRawBody();
1460
+ }
1461
+
1462
+ /**
1463
+ * A convenience function that returns a text representation of
1464
+ * HTTP response codes. Returns 'Unknown' for unknown codes.
1465
+ * Returns array of all codes, if $code is not specified.
1466
+ *
1467
+ * Conforms to HTTP/1.1 as defined in RFC 2616 (except for 'Unknown')
1468
+ * See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10 for reference
1469
+ *
1470
+ * @param int $code HTTP response code
1471
+ * @param boolean $http11 Use HTTP version 1.1
1472
+ * @return string
1473
+ */
1474
+ public static function responseCodeAsText($code = null, $http11 = true)
1475
+ {
1476
+ $messages = self::$messages;
1477
+ if (! $http11) $messages[302] = 'Moved Temporarily';
1478
+
1479
+ if ($code === null) {
1480
+ return $messages;
1481
+ } elseif (isset($messages[$code])) {
1482
+ return $messages[$code];
1483
+ } else {
1484
+ return 'Unknown';
1485
+ }
1486
+ }
1487
+
1488
+ /**
1489
+ * Extract the response code from a response string
1490
+ *
1491
+ * @param string $response_str
1492
+ * @return int
1493
+ */
1494
+ public static function extractCode($response_str)
1495
+ {
1496
+ preg_match("|^HTTP/[\d\.x]+ (\d+)|", $response_str, $m);
1497
+
1498
+ if (isset($m[1])) {
1499
+ return (int) $m[1];
1500
+ } else {
1501
+ return false;
1502
+ }
1503
+ }
1504
+
1505
+ /**
1506
+ * Extract the HTTP message from a response
1507
+ *
1508
+ * @param string $response_str
1509
+ * @return string
1510
+ */
1511
+ public static function extractMessage($response_str)
1512
+ {
1513
+ preg_match("|^HTTP/[\d\.x]+ \d+ ([^\r\n]+)|", $response_str, $m);
1514
+
1515
+ if (isset($m[1])) {
1516
+ return $m[1];
1517
+ } else {
1518
+ return false;
1519
+ }
1520
+ }
1521
+
1522
+ /**
1523
+ * Extract the HTTP version from a response
1524
+ *
1525
+ * @param string $response_str
1526
+ * @return string
1527
+ */
1528
+ public static function extractVersion($response_str)
1529
+ {
1530
+ preg_match("|^HTTP/([\d\.x]+) \d+|", $response_str, $m);
1531
+
1532
+ if (isset($m[1])) {
1533
+ return $m[1];
1534
+ } else {
1535
+ return false;
1536
+ }
1537
+ }
1538
+
1539
+ /**
1540
+ * Extract the headers from a response string
1541
+ *
1542
+ * @param string $response_str
1543
+ * @return array
1544
+ */
1545
+ public static function extractHeaders($response_str)
1546
+ {
1547
+ $headers = array();
1548
+
1549
+ // First, split body and headers
1550
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
1551
+ if (! $parts[0]) return $headers;
1552
+
1553
+ // Split headers part to lines
1554
+ $lines = explode("\n", $parts[0]);
1555
+ unset($parts);
1556
+ $last_header = null;
1557
+
1558
+ foreach($lines as $line) {
1559
+ $line = trim($line, "\r\n");
1560
+ if ($line == "") break;
1561
+
1562
+ if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) {
1563
+ unset($last_header);
1564
+ $h_name = strtolower($m[1]);
1565
+ $h_value = $m[2];
1566
+
1567
+ if (isset($headers[$h_name])) {
1568
+ if (! is_array($headers[$h_name])) {
1569
+ $headers[$h_name] = array($headers[$h_name]);
1570
+ }
1571
+
1572
+ $headers[$h_name][] = $h_value;
1573
+ } else {
1574
+ $headers[$h_name] = $h_value;
1575
+ }
1576
+ $last_header = $h_name;
1577
+ } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) {
1578
+ if (is_array($headers[$last_header])) {
1579
+ end($headers[$last_header]);
1580
+ $last_header_key = key($headers[$last_header]);
1581
+ $headers[$last_header][$last_header_key] .= $m[1];
1582
+ } else {
1583
+ $headers[$last_header] .= $m[1];
1584
+ }
1585
+ }
1586
+ }
1587
+
1588
+ return $headers;
1589
+ }
1590
+
1591
+ /**
1592
+ * Extract the body from a response string
1593
+ *
1594
+ * @param string $response_str
1595
+ * @return string
1596
+ */
1597
+ public static function extractBody($response_str)
1598
+ {
1599
+ $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
1600
+ if (isset($parts[1])) {
1601
+ return $parts[1];
1602
+ }
1603
+ return '';
1604
+ }
1605
+
1606
+ /**
1607
+ * Decode a "chunked" transfer-encoded body and return the decoded text
1608
+ *
1609
+ * @param string $body
1610
+ * @return string
1611
+ */
1612
+ public static function decodeChunkedBody($body)
1613
+ {
1614
+ $decBody = '';
1615
+
1616
+ while (preg_match("/^([\da-fA-F]+)[^\r\n]*\r\n/sm", trim($body), $m)) {
1617
+ $length = hexdec(trim($m[1]));
1618
+ $cut = strlen($m[0]);
1619
+
1620
+ $decBody .= substr($body, $cut, $length);
1621
+ $body = substr($body, $cut + $length + 2);
1622
+ }
1623
+
1624
+ return $decBody;
1625
+ }
1626
+
1627
+ /**
1628
+ * Decode a gzip encoded message (when Content-encoding = gzip)
1629
+ *
1630
+ * Currently requires PHP with zlib support
1631
+ *
1632
+ * @param string $body
1633
+ * @return string
1634
+ */
1635
+ public static function decodeGzip($body)
1636
+ {
1637
+ if (! function_exists('gzinflate')) {
1638
+ throw new Ait_Zend_Http_Exception('Unable to decode gzipped response ' .
1639
+ 'body: perhaps the zlib extension is not loaded?');
1640
+ }
1641
+
1642
+ return gzinflate(substr($body, 10));
1643
+ }
1644
+
1645
+ /**
1646
+ * Decode a zlib deflated message (when Content-encoding = deflate)
1647
+ *
1648
+ * Currently requires PHP with zlib support
1649
+ *
1650
+ * @param string $body
1651
+ * @return string
1652
+ */
1653
+ public static function decodeDeflate($body)
1654
+ {
1655
+ if (! function_exists('gzuncompress')) {
1656
+ throw new Ait_Zend_Http_Exception('Unable to decode deflated response ' .
1657
+ 'body: perhaps the zlib extension is not loaded?');
1658
+ }
1659
+
1660
+ return gzuncompress($body);
1661
+ }
1662
+
1663
+ /**
1664
+ * Create a new Zend_Http_Response object from a string
1665
+ *
1666
+ * @param string $response_str
1667
+ * @return Ait_Zend_Http_Response
1668
+ */
1669
+ public static function fromString($response_str)
1670
+ {
1671
+ $code = self::extractCode($response_str);
1672
+ $headers = self::extractHeaders($response_str);
1673
+ $body = self::extractBody($response_str);
1674
+ $version = self::extractVersion($response_str);
1675
+ $message = self::extractMessage($response_str);
1676
+
1677
+ return new Ait_Zend_Http_Response($code, $headers, $body, $version, $message);
1678
+ }
1679
+ }