PageRenderTime 46ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/system/core/core.spellcheck.php

https://github.com/danboy/Croissierd
PHP | 1361 lines | 1001 code | 229 blank | 131 comment | 210 complexity | 46ba0aa4ffcc46ae433cfa977589cc14 MD5 | raw file
  1. <?php
  2. /*
  3. =====================================================
  4. ExpressionEngine - by EllisLab
  5. -----------------------------------------------------
  6. http://expressionengine.com/
  7. -----------------------------------------------------
  8. Copyright (c) 2003 - 2010 EllisLab, Inc.
  9. =====================================================
  10. THIS IS COPYRIGHTED SOFTWARE
  11. PLEASE READ THE LICENSE AGREEMENT
  12. http://expressionengine.com/docs/license.html
  13. =====================================================
  14. File: core.spellcheck.php
  15. -----------------------------------------------------
  16. Purpose: JavaScript Spell Check class
  17. =====================================================
  18. */
  19. if ( ! defined('EXT'))
  20. {
  21. exit('Invalid file request');
  22. }
  23. class Spellcheck {
  24. var $enabled = FALSE;
  25. /** -------------------------------------
  26. /** Constructor
  27. /** -------------------------------------*/
  28. function Spellcheck()
  29. {
  30. global $LANG;
  31. $LANG->fetch_language_file('spellcheck');
  32. if (function_exists('pspell_new') OR function_exists('curl_init') OR extension_loaded('openssl'))
  33. {
  34. $this->enabled = TRUE;
  35. }
  36. }
  37. /* END */
  38. //-------------------------------------
  39. // JavaScript Required By Class
  40. //
  41. // Put this before the eeSpell object
  42. // is called.
  43. //-------------------------------------
  44. function Javascript($check_url, $wrap = FALSE)
  45. {
  46. global $LANG;
  47. if ($this->enabled === FALSE)
  48. {
  49. return '';
  50. }
  51. $spell_save_edit = $LANG->line('spell_save_edit');
  52. $spell_edit_word = $LANG->line('spell_edit_word');
  53. $unsupported_browser = $LANG->line('unsupported_browser');
  54. $no_spelling_errors = $LANG->line('no_spelling_errors');
  55. $spellcheck_in_progress = $LANG->line('spellcheck_in_progress');
  56. $check_url = str_replace('&amp;', '&', $check_url);
  57. $r = ($wrap === TRUE) ? '<script type="text/javascript">'.NL.'//<![CDATA['.NL : '';
  58. $r .= <<<EOT
  59. /** --------------------------------------------------
  60. /** Spelling Check
  61. /** --------------------------------------------------*/
  62. var SP_XMLHttp;
  63. var SP_originalText;
  64. var SP_checkedText;
  65. var SP_frameBase;
  66. var SP_frameObj;
  67. var SP_win = false;
  68. var SP_popupDiv;
  69. var SP_additionalLinks;
  70. var SP_hiddenField;
  71. var SP_spellField;
  72. var SP_contentField;
  73. var SP_clicked = false;
  74. var SP_unSupported = false;
  75. var isIE = false;
  76. var SP_PinTA = false;
  77. var SP_recentlyClicked = false;
  78. var SP_temp = false;
  79. var SP_timeOut = 1000;
  80. var SP_timeOutMax = 5000;
  81. var SP_suggested = new Array();
  82. var SP_repWords = new Array();
  83. var spellClass = 'spellchecked_word';
  84. var spellClassSelected = 'spellchecked_word_selected';
  85. var langNoSuggestions = '{$no_spelling_errors}';
  86. var langUnsupported = '{$unsupported_browser}';
  87. var langInProgress = '&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;{$spellcheck_in_progress}';
  88. var langEditWord = '{$spell_edit_word}';
  89. var langSaveEdit = '{$spell_save_edit}';
  90. function spellingCheck()
  91. {
  92. }
  93. spellingCheck.prototype.searchXML = function(xmlURL, data)
  94. {
  95. var XMLurl = xmlURL;
  96. if (window.XMLHttpRequest)
  97. {
  98. SP_frameBase.body.innerHTML = '';
  99. SP_inProgress();
  100. SP_XMLHttp = new XMLHttpRequest();
  101. SP_XMLHttp.onreadystatechange = this.processReqChange;
  102. SP_XMLHttp.open("POST", XMLurl, true);
  103. SP_XMLHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;');
  104. SP_XMLHttp.send(data);
  105. // branch for IE/Windows ActiveX version
  106. }
  107. else if (window.ActiveXObject)
  108. {
  109. isIE = true;
  110. try
  111. {
  112. SP_XMLHttp = new ActiveXObject("Microsoft.XMLHTTP");
  113. }
  114. catch(g){ return SP_unsupportedBrowser();}
  115. if (SP_XMLHttp)
  116. {
  117. SP_frameBase.body.innerHTML = '';
  118. SP_inProgress();
  119. SP_XMLHttp.onreadystatechange = this.processReqChange;
  120. SP_XMLHttp.open("POST", XMLurl, true);
  121. SP_XMLHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;');
  122. SP_XMLHttp.send(data);
  123. }
  124. }
  125. else
  126. {
  127. SP_unsupportedBrowser();
  128. }
  129. }
  130. spellingCheck.prototype.processReqChange = function()
  131. {
  132. // only if SP_XMLHttp shows "loaded"
  133. if (SP_XMLHttp.readyState == 4)
  134. {
  135. // only if "OK"
  136. if (SP_XMLHttp.status == 200)
  137. {
  138. if (SP_XMLHttp.responseText == '')
  139. {
  140. SP_clicked = false;
  141. alert("There was a problem retrieving the XML data");
  142. }
  143. else
  144. {
  145. SP_parseXML();
  146. if (SP_suggested.length == 0)
  147. {
  148. SP_frameBase.body.innerHTML = '';
  149. SP_frameObj.style.display = 'none';
  150. return SP_noSuggestions();
  151. }
  152. SP_prepareText();
  153. SP_tagSpans();
  154. //SP_tagLinks();
  155. SP_frameObj.style.display = 'block';
  156. SP_hiddenField.innerHTML = SP_additionalLinks;
  157. SP_hiddenField.style.visibility = 'visible';
  158. // In some cases, Safari was not displaying the contents
  159. // until there was some action with the screen or frame contents
  160. // after the mouse click. This seems to fix it. Not sure why.
  161. var temp = SP_frameBase.body.innerHTML;
  162. }
  163. }
  164. else
  165. {
  166. SP_clicked = false;
  167. alert("There was a problem retrieving the XML data:\\n" + SP_XMLHttp.status + ' - ' + SP_XMLHttp.responseText);
  168. }
  169. }
  170. }
  171. spellingCheck.prototype.getResults = function(field)
  172. {
  173. if (SP_clicked)
  174. {
  175. return SP_closeSpellCheck();
  176. }
  177. if (SP_win) SP_win.hidePopup();
  178. if ( ! field)
  179. {
  180. return;
  181. }
  182. SP_spellField = field;
  183. SP_hiddenField = document.getElementById('spellcheck_hidden_' + field);
  184. SP_contentField = document.getElementById(field);
  185. SP_originalText = SP_contentField.value;
  186. SP_checkedText = SP_contentField.value;
  187. SP_suggested = new Array();
  188. if ( ! SP_originalText || SP_originalText == '')
  189. {
  190. return;
  191. }
  192. SP_clicked = true;
  193. var searchString = SP_originalText;
  194. xmlURL = "{$check_url}";
  195. data = "q=" + escape(searchString) + "&XID={XID_SECURE_HASH}";
  196. if (!SP_additionalLinks)
  197. {
  198. SP_additionalLinks = SP_hiddenField.innerHTML;
  199. }
  200. SP_popupDiv = document.getElementById('spellcheck_popup');
  201. SP_frameObj = document.getElementById('spellcheck_frame_'+SP_spellField);
  202. if (SP_frameObj.contentDocument)
  203. {
  204. SP_frameBase = SP_frameObj.contentDocument;
  205. }
  206. else if (SP_frameObj.contentWindow)
  207. {
  208. SP_frameBase = SP_frameObj.contentWindow.document;
  209. }
  210. else if (SP_frameObj.document)
  211. {
  212. SP_frameBase = SP_frameObj.document;
  213. }
  214. else
  215. {
  216. if ( ! SP_PinTA)
  217. {
  218. SP_clicked = false;
  219. SP_frameObj.style.display = 'block';
  220. SP_inProgress();
  221. SP_PinTA = new Date();
  222. setTimeout("eeSpell.getResults(SP_spellField)", SP_timeOut);
  223. return;
  224. }
  225. else
  226. {
  227. var current = new Date();
  228. if (current - SP_PinTA > SP_timeOutMax) // Final Chance
  229. {
  230. if (SP_frameObj.contentDocument)
  231. {
  232. SP_frameBase = SP_frameObj.contentDocument;
  233. }
  234. else
  235. {
  236. SP_PinTA = false;
  237. SP_clicked = false;
  238. return SP_unsupportedBrowser();
  239. }
  240. }
  241. else if (current - SP_PinTA > SP_timeOut) // First Chance
  242. {
  243. if (SP_frameObj.contentDocument)
  244. {
  245. SP_frameBase = SP_frameObj.contentDocument;
  246. }
  247. else
  248. {
  249. SP_clicked = false;
  250. setTimeout("eeSpell.getResults(SP_spellField)", SP_timeOut);
  251. return;
  252. }
  253. }
  254. else
  255. {
  256. SP_clicked = false;
  257. return; // Double-click
  258. }
  259. }
  260. }
  261. if (SP_win) SP_frameBase.onmouseup = SP_PopupWindow_hidePopupWindows;
  262. SP_PinTA = false;
  263. SP_hiddenField.style.visibility = 'hidden';
  264. this.searchXML(xmlURL, data);
  265. }
  266. function SP_parseXML()
  267. {
  268. //alert(SP_XMLHttp.responseText);
  269. var SP_suggestedItems = SP_XMLHttp.responseXML.getElementsByTagName("item");
  270. for (var i = 0; i < SP_suggestedItems.length; i++)
  271. {
  272. if (SP_suggestedItems[i].childNodes.length > 1)
  273. {
  274. elementText = SP_suggestedItems[i].childNodes[1].nodeValue;
  275. }
  276. else
  277. {
  278. elementText = SP_suggestedItems[i].firstChild.nodeValue;
  279. }
  280. elementParts = elementText.split(':');
  281. SP_suggested[i] = elementParts[0];
  282. SP_repWords[i] = elementParts[1];
  283. }
  284. }
  285. function SP_prepareText()
  286. {
  287. SP_checkedText = SP_checkedText.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  288. for (i=0; i < SP_suggested.length; i++)
  289. {
  290. compareString = eval("/(\\W*)" + SP_suggested[i] + "(\\W*)/g");
  291. SP_checkedText = SP_checkedText.replace(compareString,'$1<span class="'+spellClass+'">' + SP_suggested[i] + '</span>$2');
  292. }
  293. SP_checkedText = SP_checkedText.replace(/(\\r\\n|\\n|\\r)/g, '<br>');
  294. }
  295. function SP_tagSpans()
  296. {
  297. SP_frameBase.body.innerHTML = SP_checkedText;
  298. var spans = SP_frameBase.getElementsByTagName("span");
  299. for (var i = 0, l = spans.length; i < l; ++i)
  300. {
  301. if (spans[i].className.indexOf(spellClass) > -1)
  302. {
  303. spans[i].id = "spellcheckedword_" + i;
  304. spans[i].onclick = SP_clickWord;
  305. }
  306. }
  307. }
  308. function SP_tagLinks()
  309. {
  310. var links = SP_frameBase.getElementsByTagName("a");
  311. for (var i = 0, l = links.length; i < l; ++i)
  312. {
  313. links[i].onclick = function() {return false;};
  314. }
  315. }
  316. function SP_resetSpanStyles()
  317. {
  318. var spans = SP_frameBase.getElementsByTagName("span");
  319. for (var i = 0, l = spans.length; i < l; ++i)
  320. {
  321. if (spans[i].className.indexOf(spellClassSelected) > -1)
  322. {
  323. spans[i].className = spellClass;
  324. }
  325. }
  326. }
  327. function SP_clickWord()
  328. {
  329. SP_recentlyClicked = this;
  330. var spans = SP_frameBase.getElementsByTagName("span");
  331. for (var i = 0, l = spans.length; i < l; ++i)
  332. {
  333. spans[i].className = spellClass;
  334. }
  335. this.className = spellClassSelected;
  336. for(i=0, l = SP_suggested.length; i < l; ++i)
  337. {
  338. if (SP_suggested[i] == this.innerHTML)
  339. {
  340. break;
  341. }
  342. }
  343. //alert(this.innerHTML + ' :' + SP_repWords[i] + ' ID:' + this.id);
  344. SP_popupDiv.innerHTML = SP_suggestionMenu(SP_repWords[i], this.id);
  345. frameCoordinates = SP_absolutePosition(SP_frameObj);
  346. scrollCoordinates = SP_scrollPosition(SP_frameBase);
  347. SP_win = new SP_PopupWindow('spellcheck_popup');
  348. SP_win.offsetX = frameCoordinates.x;
  349. SP_win.offsetY = frameCoordinates.y+17 - scrollCoordinates.y;
  350. SP_win.showPopup(this);
  351. SP_win.autoHide();
  352. SP_win.editInProgress = false;
  353. }
  354. function SP_suggestionMenu(suggestions, id)
  355. {
  356. words = suggestions.split(',');
  357. for (i=0, l = words.length, str=''; i < l; ++i)
  358. {
  359. str += '<a href="javascript:void(0);" onclick="SP_replaceWord(this, \'' + id + '\');return false;">';
  360. str += words[i] + '</a><br />';
  361. }
  362. str += '----<br /><a href="javascript:void(0);" onmousedown="SP_editWordPause();" onclick="SP_editWord(this, \'' + id + '\');return false;">' + langEditWord + '</a>';
  363. return str;
  364. }
  365. function SP_replaceWord(el, id)
  366. {
  367. var spans = SP_frameBase.getElementsByTagName("span");
  368. var newText = SP_frameBase.createTextNode(el.innerHTML);
  369. if (spans[id])
  370. {
  371. spans[id].parentNode.insertBefore(newText, spans[id]);
  372. spans[id].parentNode.removeChild(spans[id]);
  373. SP_resetSpanStyles();
  374. // spans[id].innerHTML = el.innerHTML;
  375. }
  376. if (SP_win) SP_win.hidePopup();
  377. }
  378. function SP_editWordPause()
  379. {
  380. // Safari has issues
  381. SP_temp = document.onmouseup;
  382. document.onmouseup = function() {}
  383. }
  384. function SP_editWord(el, id)
  385. {
  386. var spans = SP_frameBase.getElementsByTagName("span");
  387. if (spans[id])
  388. {
  389. var newObj = document.createElement('input');
  390. newObj.setAttribute("type", "text");
  391. //newObj.setAttribute("name", 'input_'+id);
  392. newObj.setAttribute("id", 'input_'+id);
  393. newObj.setAttribute("value", spans[id].innerHTML);
  394. newObj.setAttribute('size', spans[id].innerHTML.length+2);
  395. newObj.setAttribute('class', 'input');
  396. newObj.onkeypress = SP_saveEditReturn;
  397. el.parentNode.insertBefore(newObj, el);
  398. var newObj2 = document.createElement('a');
  399. newObj2.setAttribute("href", "javascript:void(0);");
  400. newObj2.setAttribute("id", 'link_'+id);
  401. newObj2.onclick = SP_saveEdit;
  402. newObj2.innerHTML = langSaveEdit;
  403. el.parentNode.insertBefore(document.createElement('br'), el);
  404. el.parentNode.insertBefore(newObj2, el);
  405. el.parentNode.removeChild(el);
  406. newObj.focus();
  407. newObj.select();
  408. }
  409. if (SP_temp)
  410. {
  411. document.onmouseup = SP_temp;
  412. SP_temp = false;
  413. }
  414. }
  415. function SP_saveEdit()
  416. {
  417. var id = this.id.replace('link_', '');
  418. var spans = SP_frameBase.getElementsByTagName("span");
  419. var inputs = document.getElementsByTagName("input");
  420. if (spans[id] && inputs['input_'+id])
  421. {
  422. var newText = SP_frameBase.createTextNode(inputs['input_'+id].value);
  423. spans[id].parentNode.insertBefore(newText, spans[id]);
  424. spans[id].parentNode.removeChild(spans[id]);
  425. SP_resetSpanStyles();
  426. }
  427. if (SP_win) SP_win.hidePopup();
  428. }
  429. function SP_saveEditReturn(e)
  430. {
  431. if (window.event)
  432. {
  433. e = window.event;
  434. }
  435. var charCode = (!e.which || e.which == 0) ? e.keyCode : e.which;
  436. if (charCode == 13)
  437. {
  438. var id = this.id.replace('input_', '');
  439. var spans = SP_frameBase.getElementsByTagName("span");
  440. if (spans[id])
  441. {
  442. var newText = SP_frameBase.createTextNode(this.value);
  443. spans[id].parentNode.insertBefore(newText, spans[id]);
  444. spans[id].parentNode.removeChild(spans[id]);
  445. SP_resetSpanStyles();
  446. }
  447. SP_win.hidePopup();
  448. return false;
  449. }
  450. }
  451. function SP_absolutePosition(el)
  452. {
  453. var coordinates = { x: el.offsetLeft, y: el.offsetTop };
  454. if (el.offsetParent)
  455. {
  456. var tmp = SP_absolutePosition(el.offsetParent);
  457. coordinates.x += tmp.x;
  458. coordinates.y += tmp.y;
  459. }
  460. return coordinates;
  461. };
  462. function SP_scrollPosition(el)
  463. {
  464. if ( ! el.documentElement.scrollTop)
  465. {
  466. var coordinates = { x: SP_frameBase.body.scrollLeft, y: SP_frameBase.body.scrollTop };
  467. }
  468. else
  469. {
  470. var coordinates = { x: SP_frameBase.documentElement.scrollLeft, y: SP_frameBase.documentElement.scrollTop };
  471. }
  472. return coordinates;
  473. };
  474. function SP_closeSpellCheck()
  475. {
  476. if (SP_win) SP_win.hidePopup();
  477. SP_clicked = false;
  478. if (SP_frameObj && ! SP_unSupported)
  479. {
  480. SP_frameObj.style.display = 'none';
  481. SP_hiddenField.style.visibility = 'hidden';
  482. SP_frameBase.body.innerHTML = '';
  483. }
  484. }
  485. function SP_inProgress()
  486. {
  487. SP_unSupported = false;
  488. SP_hiddenField.innerHTML = langInProgress;
  489. SP_hiddenField.style.visibility = 'visible';
  490. }
  491. function SP_saveSpellCheck()
  492. {
  493. if (SP_win) SP_win.hidePopup();
  494. SP_clicked = false;
  495. var spans = SP_frameBase.getElementsByTagName("span");
  496. for (var i = spans.length; --i >= 0;) // Need to go backwards through nodes
  497. {
  498. if (spans[i].className.indexOf(spellClass) > -1)
  499. {
  500. spans[i].parentNode.insertBefore(spans[i].firstChild, spans[i]);
  501. spans[i].parentNode.removeChild(spans[i]);
  502. }
  503. }
  504. var content = SP_frameBase.body.innerHTML;
  505. content = content.replace(/(\\r\\n|\\r|\\n)/g, ' ').replace(/<br *\/?>/gi, "\\n");
  506. SP_frameBase.body.innerHTML = '';
  507. SP_frameObj.style.display = 'none';
  508. SP_hiddenField.style.visibility = 'hidden';
  509. content = content.replace(/&gt;/g, '>').replace(/&lt;/g, '<').replace(/&amp;/g, '&');
  510. SP_contentField.value = content;
  511. if (document.getElementById('entryform')) hide_open_panes(); // Publish area panes
  512. }
  513. function SP_revertToOriginal()
  514. {
  515. if (SP_win) SP_win.hidePopup();
  516. SP_clicked = false;
  517. SP_frameObj.style.display = 'none';
  518. SP_hiddenField.style.visibility = 'hidden';
  519. SP_contentField.value = SP_originalText;
  520. SP_frameBase.body.innerHTML = '';
  521. if (document.getElementById('entryform')) hide_open_panes(); // Publish area panes
  522. }
  523. function SP_unsupportedBrowser()
  524. {
  525. SP_clicked = false;
  526. SP_unSupported = true;
  527. SP_hiddenField.innerHTML = ' | ' + langUnsupported;
  528. SP_hiddenField.style.visibility = 'visible';
  529. }
  530. function SP_noSuggestions()
  531. {
  532. SP_clicked = false;
  533. SP_hiddenField.innerHTML = ' | ' + langNoSuggestions;
  534. SP_hiddenField.style.visibility = 'visible';
  535. }
  536. var eeSpell = new spellingCheck();
  537. /** ----------------------------------------
  538. /** Spell Check Popup Code
  539. /** ----------------------------------------*/
  540. // ===================================================================
  541. // - CREATOR -
  542. // Author: Matt Kruse <matt@mattkruse.com>
  543. // WWW: http://www.mattkruse.com/
  544. // ===================================================================
  545. // SP_getAnchorPosition(anchorname)
  546. // This function returns an object having .x and .y properties which are the coordinates
  547. // of the named anchor, relative to the page.
  548. function SP_getAnchorPosition(object)
  549. {
  550. // This function will return an Object with x and y properties
  551. var useWindow=false;
  552. var coordinates=new Object();
  553. var x=0,y=0;
  554. // Browser capability sniffing
  555. var use_gebi=false, use_css=false, use_layers=false;
  556. if (document.getElementById) { use_gebi=true; }
  557. else if (document.all) { use_css=true; }
  558. else if (document.layers) { use_layers=true; }
  559. // Logic to find position
  560. if (use_gebi && document.all) {
  561. x=SP_AnchorPosition_getPageOffsetLeft(object);
  562. y=SP_AnchorPosition_getPageOffsetTop(object);
  563. }
  564. else if (use_gebi) {
  565. x=SP_AnchorPosition_getPageOffsetLeft(object);
  566. y=SP_AnchorPosition_getPageOffsetTop(object);
  567. }
  568. else if (use_css) {
  569. x=SP_AnchorPosition_getPageOffsetLeft(object);
  570. y=SP_AnchorPosition_getPageOffsetTop(object);
  571. }
  572. else if (use_layers) {
  573. var found=0;
  574. for (var i=0; i<document.anchors.length; i++) {
  575. if (document.anchors[i].name==object.id) { found=1; break; }
  576. }
  577. if (found==0) {
  578. coordinates.x=0; coordinates.y=0; return coordinates;
  579. }
  580. x=document.anchors[i].x;
  581. y=document.anchors[i].y;
  582. }
  583. else {
  584. coordinates.x=0; coordinates.y=0; return coordinates;
  585. }
  586. coordinates.x=x;
  587. coordinates.y=y;
  588. return coordinates;
  589. }
  590. // Functions for IE to get position of an object
  591. function SP_AnchorPosition_getPageOffsetLeft (el)
  592. {
  593. var ol=el.offsetLeft;
  594. while ((el=el.offsetParent) != null) { ol += el.offsetLeft; }
  595. return ol;
  596. }
  597. function SP_AnchorPosition_getPageOffsetTop (el)
  598. {
  599. var ot=el.offsetTop;
  600. while((el=el.offsetParent) != null) { ot += el.offsetTop; }
  601. return ot;
  602. }
  603. /* SOURCE FILE: PopupWindow.js */
  604. /*
  605. PopupWindow.js
  606. Author: Matt Kruse
  607. Last modified: 02/16/04
  608. */
  609. // Set the position of the popup window based on the anchor
  610. function SP_PopupWindow_getXYPosition(object) {
  611. var coordinates = SP_getAnchorPosition(object);
  612. this.x = coordinates.x;
  613. this.y = coordinates.y;
  614. }
  615. // Set width/height of DIV/popup window
  616. function SP_PopupWindow_setSize(width,height) {
  617. this.width = width;
  618. this.height = height;
  619. }
  620. // Fill the window with contents
  621. function SP_PopupWindow_populate(contents) {
  622. this.contents = contents;
  623. this.populated = false;
  624. }
  625. // Set the URL to go to
  626. function SP_PopupWindow_setUrl(url) {
  627. this.url = url;
  628. }
  629. // Set the window popup properties
  630. function SP_PopupWindow_setWindowProperties(props) {
  631. this.windowProperties = props;
  632. }
  633. // Refresh the displayed contents of the popup
  634. function SP_PopupWindow_refresh() {
  635. if (this.divName != null) {
  636. // refresh the DIV object
  637. if (this.use_gebi) {
  638. document.getElementById(this.divName).innerHTML = this.contents;
  639. }
  640. else if (this.use_css) {
  641. document.all[this.divName].innerHTML = this.contents;
  642. }
  643. else if (this.use_layers) {
  644. var d = document.layers[this.divName];
  645. d.document.open();
  646. d.document.writeln(this.contents);
  647. d.document.close();
  648. }
  649. }
  650. else {
  651. if (this.popupWindow != null && !this.popupWindow.closed) {
  652. if (this.url !="") {
  653. this.popupWindow.location.href=this.url;
  654. }
  655. else {
  656. this.popupWindow.document.open();
  657. this.popupWindow.document.writeln(this.contents);
  658. this.popupWindow.document.close();
  659. }
  660. this.popupWindow.focus();
  661. }
  662. }
  663. }
  664. // Position and show the popup, relative to an anchor object
  665. function SP_PopupWindow_showPopup(object) {
  666. this.getXYPosition(object);
  667. this.x += this.offsetX;
  668. this.y += this.offsetY;
  669. if (!this.populated && (this.contents != "")) {
  670. this.populated = true;
  671. this.refresh();
  672. }
  673. if (this.divName != null) {
  674. // Show the DIV object
  675. if (this.use_gebi) {
  676. document.getElementById(this.divName).style.left = this.x + "px";
  677. document.getElementById(this.divName).style.top = this.y + "px";
  678. document.getElementById(this.divName).style.visibility = "visible";
  679. }
  680. else if (this.use_css) {
  681. document.all[this.divName].style.left = this.x;
  682. document.all[this.divName].style.top = this.y;
  683. document.all[this.divName].style.visibility = "visible";
  684. }
  685. else if (this.use_layers) {
  686. document.layers[this.divName].left = this.x;
  687. document.layers[this.divName].top = this.y;
  688. document.layers[this.divName].visibility = "visible";
  689. }
  690. }
  691. else {
  692. if (this.popupWindow == null || this.popupWindow.closed) {
  693. // If the popup window will go off-screen, move it so it doesn't
  694. if (this.x<0) { this.x=0; }
  695. if (this.y<0) { this.y=0; }
  696. if (screen && screen.availHeight) {
  697. if ((this.y + this.height) > screen.availHeight) {
  698. this.y = screen.availHeight - this.height;
  699. }
  700. }
  701. if (screen && screen.availWidth) {
  702. if ((this.x + this.width) > screen.availWidth) {
  703. this.x = screen.availWidth - this.width;
  704. }
  705. }
  706. var avoidAboutBlank = window.opera || ( document.layers && !navigator.mimeTypes['*'] ) || navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled );
  707. this.popupWindow = window.open(avoidAboutBlank?"":"about:blank","window_"+object.id,this.windowProperties+",width="+this.width+",height="+this.height+",screenX="+this.x+",left="+this.x+",screenY="+this.y+",top="+this.y+"");
  708. }
  709. this.refresh();
  710. }
  711. }
  712. // Hide the popup
  713. function SP_PopupWindow_hidePopup()
  714. {
  715. if (this.divName != null)
  716. {
  717. if (this.use_gebi)
  718. {
  719. document.getElementById(this.divName).style.visibility = "hidden";
  720. }
  721. else if (this.use_css)
  722. {
  723. document.all[this.divName].style.visibility = "hidden";
  724. }
  725. else if (this.use_layers)
  726. {
  727. document.layers[this.divName].visibility = "hidden";
  728. }
  729. }
  730. else
  731. {
  732. if (this.popupWindow && !this.popupWindow.closed)
  733. {
  734. this.popupWindow.close();
  735. this.popupWindow = null;
  736. }
  737. }
  738. }
  739. // Pass an event and return whether or not it was the popup DIV that was clicked
  740. function SP_PopupWindow_isClicked(e) {
  741. if (this.divName != null) {
  742. if (this.use_layers) {
  743. var clickX = e.pageX;
  744. var clickY = e.pageY;
  745. var t = document.layers[this.divName];
  746. if ((clickX > t.left) && (clickX < t.left+t.clip.width) && (clickY > t.top) && (clickY < t.top+t.clip.height)) {
  747. return true;
  748. }
  749. else { return false; }
  750. }
  751. else if (document.all) { // Need to hard-code this to trap IE for error-handling
  752. var t = e;
  753. try {
  754. while (t.parentElement != null) {
  755. if (t.id==this.divName) {
  756. return true;
  757. }
  758. t = t.parentElement;
  759. }
  760. } catch(g) {}
  761. return false;
  762. }
  763. else if (this.use_gebi && e) {
  764. var t = e.originalTarget;
  765. try {while (t.parentNode != null) {
  766. if (t.id==this.divName) {
  767. return true;
  768. }
  769. t = t.parentNode;
  770. } } catch(g) {}
  771. return false;
  772. }
  773. return false;
  774. }
  775. return false;
  776. }
  777. // Check an onmouseDown event to see if we should hide
  778. function SP_PopupWindow_hideIfNotClicked(e) {
  779. if (this.autoHideEnabled && !this.isClicked(e)) {
  780. this.hidePopup();
  781. }
  782. }
  783. // Call this to make the DIV disable automatically when mouse is clicked outside it
  784. function SP_PopupWindow_autoHide() {
  785. this.autoHideEnabled = true;
  786. }
  787. // This global function checks all PopupWindow objects onmouseup to see if they should be hidden
  788. function SP_PopupWindow_hidePopupWindows(e) {
  789. for (var i=0; i<popupWindowObjects.length; i++) {
  790. if (popupWindowObjects[i] != null) {
  791. var p = popupWindowObjects[i];
  792. p.hideIfNotClicked(e);
  793. }
  794. }
  795. SP_recentlyClicked.className = spellClass;
  796. }
  797. // Run this immediately to attach the event listener
  798. function SP_PopupWindow_attachListener()
  799. {
  800. if (document.layers)
  801. {
  802. document.captureEvents(Event.MOUSEUP);
  803. }
  804. window.popupWindowOldEventListener = document.onmouseup;
  805. if (window.popupWindowOldEventListener != null)
  806. {
  807. document.onmouseup = new Function("window.popupWindowOldEventListener(); SP_PopupWindow_hidePopupWindows();");
  808. if (SP_frameBase)
  809. {
  810. SP_frameBase.onmouseup = new Function("window.popupWindowOldEventListener(); SP_PopupWindow_hidePopupWindows();");
  811. }
  812. }
  813. else
  814. {
  815. // Turned this off because Safari is a pain with the Edit Word ability
  816. document.onmouseup = SP_PopupWindow_hidePopupWindows;
  817. if (SP_frameBase)
  818. {
  819. SP_frameBase.onmouseup = SP_PopupWindow_hidePopupWindows;
  820. }
  821. }
  822. }
  823. // CONSTRUCTOR for the PopupWindow object
  824. // Pass it a DIV name to use a DHTML popup, otherwise will default to window popup
  825. function SP_PopupWindow() {
  826. if (!window.popupWindowIndex) { window.popupWindowIndex = 0; }
  827. if (!window.popupWindowObjects) { window.popupWindowObjects = new Array(); }
  828. if (!window.SP_listenerAttached) {
  829. window.SP_listenerAttached = true;
  830. SP_PopupWindow_attachListener();
  831. }
  832. this.index = popupWindowIndex++;
  833. popupWindowObjects[this.index] = this;
  834. this.divName = null;
  835. this.popupWindow = null;
  836. this.width=0;
  837. this.height=0;
  838. this.populated = false;
  839. this.visible = false;
  840. this.autoHideEnabled = false;
  841. this.contents = "";
  842. this.url="";
  843. this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
  844. if (arguments.length>0) {
  845. this.type="DIV";
  846. this.divName = arguments[0];
  847. }
  848. else {
  849. this.type="WINDOW";
  850. }
  851. this.use_gebi = false;
  852. this.use_css = false;
  853. this.use_layers = false;
  854. if (document.getElementById) { this.use_gebi = true; }
  855. else if (document.all) { this.use_css = true; }
  856. else if (document.layers) { this.use_layers = true; }
  857. else { this.type = "WINDOW"; }
  858. this.offsetX = 0;
  859. this.offsetY = 0;
  860. // Method mappings
  861. this.getXYPosition = SP_PopupWindow_getXYPosition;
  862. this.populate = SP_PopupWindow_populate;
  863. this.setUrl = SP_PopupWindow_setUrl;
  864. this.setWindowProperties = SP_PopupWindow_setWindowProperties;
  865. this.refresh = SP_PopupWindow_refresh;
  866. this.showPopup = SP_PopupWindow_showPopup;
  867. this.hidePopup = SP_PopupWindow_hidePopup;
  868. this.setSize = SP_PopupWindow_setSize;
  869. this.isClicked = SP_PopupWindow_isClicked;
  870. this.autoHide = SP_PopupWindow_autoHide;
  871. this.hideIfNotClicked = SP_PopupWindow_hideIfNotClicked;
  872. this.object = false;
  873. }
  874. EOT;
  875. $r .= ($wrap === TRUE) ? NL.'//]]>'.NL.'</script>' : '';
  876. if (REQ != 'CP')
  877. {
  878. $r = str_replace('{XID_SECURE_HASH}', 'ignore', $r);
  879. }
  880. return $r;
  881. }
  882. /* END */
  883. /** -----------------------------------------
  884. /** Base IFRAME for Spell Check
  885. /** -----------------------------------------*/
  886. function iframe()
  887. {
  888. global $PREFS;
  889. if (class_exists('Display'))
  890. {
  891. global $DSP;
  892. }
  893. else
  894. {
  895. require PATH_CP.'cp.display'.EXT;
  896. $DSP = new Display();
  897. }
  898. $css = <<<EOT
  899. /*
  900. SPELL CHECK CSS
  901. --------------------------------------------------------------- */
  902. body
  903. {
  904. margin: 0;
  905. padding: 5px;
  906. font-family: Verdana, Geneva, Tahoma, Trebuchet MS, Arial, Sans-serif;
  907. font-size: 11px;
  908. color: #333;
  909. background-color: #fff;
  910. line-height: 18px;
  911. }
  912. .wordSuggestion
  913. {
  914. background-color: #f4f4f4;
  915. border: 1px solid #ccc;
  916. padding: 4px;
  917. }
  918. .wordSuggestion a, .wordSuggestion a:active
  919. {
  920. cursor: pointer;
  921. }
  922. .spellchecked_word
  923. {
  924. cursor: pointer;
  925. background-color: #fff;
  926. border-bottom: 1px dashed #ff0000;
  927. }
  928. .spellchecked_word_selected
  929. {
  930. cursor: pointer;
  931. background-color: #ADFF98;
  932. }
  933. EOT;
  934. $header =
  935. "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\"\n\n".
  936. "\"http://www.w3.org/TR/html4/loose.dtd\">\n\n".
  937. "<head>\n".
  938. "<title>".APP_NAME." | Spell Check</title>\n\n".
  939. "<meta http-equiv='content-type' content='text/html; charset=".$PREFS->ini('charset')."'>\n".
  940. "<meta name='MSSmartTagsPreventParsing' content='TRUE'>\n".
  941. "<meta http-equiv='expires' content='-1'>\n".
  942. "<meta http-equiv='expires' content='Mon, 01 Jan 1970 23:59:59 GMT'>\n".
  943. "<meta http-equiv='pragma' content='no-cache'>\n";
  944. $header .=
  945. "<style type='text/css'>\n".
  946. $css."\n".
  947. "</style>\n\n".
  948. "</head>\n\n".
  949. "<body></body>\n</html>";
  950. @header('Content-Type: text/html');
  951. exit($header);
  952. }
  953. /* END */
  954. /** -----------------------------------------
  955. /** Spell Check for Textareas
  956. /** -----------------------------------------*/
  957. function check($lang='en')
  958. {
  959. global $IN, $REGX, $PREFS, $OUT;
  960. /* -------------------------------------------
  961. /* Hidden Configuration Variable
  962. /*
  963. /* - spellcheck_language_code => What is the two letter ISO 639 language
  964. /* code for the spellcheck (ex: en, es, de)
  965. /* -------------------------------------------*/
  966. if ($PREFS->ini('spellcheck_language_code') !== FALSE && strlen($PREFS->ini('spellcheck_language_code')) == 2)
  967. {
  968. $lang = $PREFS->ini('spellcheck_language_code');
  969. }
  970. // ----------------------------------
  971. // These 100 words make up 1/2 of all written material
  972. // and by not checking them we should be able to greatly
  973. // speed up the spellchecker
  974. // ----------------------------------
  975. $common = array('the', 'of', 'and', 'a', 'to', 'in', 'is', 'you', 'that',
  976. 'it', 'he', 'was', 'for', 'on', 'are', 'as', 'with', 'his',
  977. 'they', 'I', 'at', 'be', 'this', 'have', 'from', 'or', 'one',
  978. 'had', 'by', 'word', 'but', 'not', 'what', 'all', 'were', 'we',
  979. 'when', 'your', 'can', 'said', 'there', 'use', 'an', 'each',
  980. 'which', 'she', 'do', 'how', 'their', 'if', 'will', 'up',
  981. 'other', 'about', 'out', 'many', 'then', 'them', 'these', 'so',
  982. 'some', 'her', 'would', 'make', 'like', 'him', 'into', 'time',
  983. 'has', 'look', 'two', 'more', 'write', 'go', 'see', 'number',
  984. 'no', 'way', 'could', 'people', 'my', 'than', 'first', 'water',
  985. 'been', 'call', 'who', 'oil', 'its', 'now', 'find', 'long',
  986. 'down', 'day', 'did', 'get', 'come', 'made', 'may', 'part');
  987. // The contents of the field are encoded by javascript before
  988. // they are sent to us so we have to decode them before processing.
  989. // We are also removing any HTML code and HTML code entities so that we
  990. // do not process them as misspelled words.
  991. $content = preg_replace("|<.*?".">|", '', rawurldecode($REGX->xss_clean($IN->GBL('q'))));
  992. $content = str_replace(array('&amp;', '&lt;', '&gt;'), '', $content);
  993. $str = '<?xml version="1.0" encoding="UTF-8"?'.">\n<items>\n";
  994. $items = array();
  995. $prechecked = array();
  996. if ( ! function_exists('pspell_new'))
  997. {
  998. $content = str_replace('&', ' ', stripslashes($content));
  999. // Google has silently changed the service internally, setting ignoredups="1" now causes results to
  1000. // always return as spelled correctly. -- changed 8/20/08 d.j.
  1001. $payload = '<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="0"><text>'
  1002. . $content
  1003. .'</text></spellrequest>';
  1004. $url = 'https://www.google.com/tbproxy/spell?lang='.$lang.'&hl='.$lang;
  1005. if ( function_exists('curl_init'))
  1006. {
  1007. $data = Spellcheck::curl_process($url, $payload);
  1008. }
  1009. else
  1010. {
  1011. $data = Spellcheck::fsockopen_process($url, $payload);
  1012. }
  1013. if ($data == '')
  1014. {
  1015. $OUT->http_status_header(404);
  1016. @header("Date: ".gmdate("D, d M Y H:i:s")." GMT");
  1017. exit('Unable to connect to spellcheck');
  1018. }
  1019. // suckz => <c o="10" l="5" s="0">sucks sicks suck sacks socks</c>
  1020. if ($data != '' && preg_match_all("|<c\s+(.*?)>(.*?)</c>|is", $data, $matches))
  1021. {
  1022. for($i = 0, $s = sizeof($matches['0']); $i < $s; ++$i)
  1023. {
  1024. $x = explode('"', $matches['1'][$i]);
  1025. $word = substr($content, $x['1'], $x['3']);
  1026. if ( ! in_array($word, $prechecked))
  1027. {
  1028. $sug = preg_split("|\s+|s", $matches['2'][$i]);
  1029. natcasesort($sug);
  1030. $items[] = $word.':'.implode(',',$sug).'';
  1031. $prechecked[] = $word;
  1032. }
  1033. }
  1034. }
  1035. }
  1036. else
  1037. {
  1038. // Split it up by non-words
  1039. preg_match_all("|[\w\']{2,20}|", stripslashes($content), $parts);
  1040. $pspell = pspell_new($lang);
  1041. for($i=0, $s = sizeof($parts['0']); $i < $s; $i++)
  1042. {
  1043. if (! is_numeric($parts['0'][$i]) &&
  1044. ! in_array(strtolower($parts['0'][$i]), $common) &&
  1045. ! in_array($parts['0'][$i], $prechecked) &&
  1046. ! pspell_check($pspell, $parts['0'][$i]))
  1047. {
  1048. $sug = array();
  1049. if ($suggestions = pspell_suggest($pspell, $parts['0'][$i]))
  1050. {
  1051. foreach ($suggestions as $suggest)
  1052. {
  1053. $sug[] = $suggest;
  1054. if (sizeof($sug) > 8) break;
  1055. }
  1056. }
  1057. natcasesort($sug);
  1058. $items[] = $parts['0'][$i].':'.implode(',',$sug).'';
  1059. $prechecked[] = $parts['0'][$i];
  1060. }
  1061. }
  1062. }
  1063. $str .= (sizeof($items) == 0) ? '' : "<item>".implode("</item>\n<item>",$items)."</item>";
  1064. $str .= "\n</items>";
  1065. @header("Content-Type: text/xml");
  1066. exit($str);
  1067. }
  1068. /* END */
  1069. /** ----------------------------------------
  1070. /** Sing a Song, Have a Dance
  1071. /** ----------------------------------------*/
  1072. function curl_process($url, $payload)
  1073. {
  1074. $ch=curl_init();
  1075. curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
  1076. curl_setopt($ch,CURLOPT_URL,$url);
  1077. curl_setopt($ch,CURLOPT_POST,1);
  1078. curl_setopt($ch,CURLOPT_POSTFIELDS,$payload);
  1079. // Start ob to prevent curl_exec from displaying stuff.
  1080. ob_start();
  1081. curl_exec($ch);
  1082. //Get contents of output buffer
  1083. $info=ob_get_contents();
  1084. curl_close($ch);
  1085. //End ob and erase contents.
  1086. ob_end_clean();
  1087. return $info;
  1088. }
  1089. /* END */
  1090. /** ----------------------------------------
  1091. /** Drinking with Friends is Fun!
  1092. /** ----------------------------------------*/
  1093. function fsockopen_process($url, $payload)
  1094. {
  1095. $parts = parse_url($url);
  1096. $host = $parts['host'];
  1097. $path = (!isset($parts['path'])) ? '/' : $parts['path'];
  1098. $port = ($parts['scheme'] == "https") ? '443' : '80';
  1099. $ssl = ($parts['scheme'] == "https") ? 'ssl://' : '';
  1100. if (isset($parts['query']) && $parts['query'] != '')
  1101. {
  1102. $path .= '?'.$parts['query'];
  1103. }
  1104. $info = '';
  1105. $fp = @fsockopen($ssl.$host, $port, $error_num, $error_str, 8);
  1106. if (is_resource($fp))
  1107. {
  1108. fputs($fp, "POST {$path} HTTP/1.0\r\n");
  1109. fputs($fp, "Host: {$host}\r\n");
  1110. fputs($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
  1111. fputs($fp, "Content-Length: ".strlen($payload)."\r\n");
  1112. fputs($fp, "Connection: close\r\n\r\n");
  1113. fputs($fp, $payload . "\r\n\r\n");
  1114. /* ------------------------------
  1115. /* This error suppression has to do with a PHP bug involving
  1116. /* SSL connections: http://bugs.php.net/bug.php?id=23220
  1117. /* ------------------------------*/
  1118. $old_level = error_reporting(0);
  1119. while($datum = fread($fp, 4096))
  1120. {
  1121. $info .= $datum;
  1122. }
  1123. error_reporting($old_level);
  1124. @fclose($fp);
  1125. }
  1126. return $info;
  1127. }
  1128. /* END */
  1129. }
  1130. // END CLASS
  1131. ?>