diff --git a/composer.json b/composer.json index 0f9a2d0b2..f816cf772 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,7 @@ "require": { "php": ">=7.2", "ckeditor/ckeditor": "^4.25.1", + "gregwar/captcha": "1.3.0", "neutron/sphinxsearch-api": "^2.0.8", "phpmailer/phpmailer": "^7.0.2", "setasign/fpdf": "^1.8.6" diff --git a/composer.lock b/composer.lock index 8f2bfb7f7..cbbfb69f3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "74b71e62d63a46a6e0ae814882295c57", + "content-hash": "9bc151f3858a0d8379c0a8b48db468b7", "packages": [ { "name": "ckeditor/ckeditor", @@ -54,6 +54,64 @@ }, "time": "2025-02-05T12:32:07+00:00" }, + { + "name": "gregwar/captcha", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/Gregwar/Captcha.git", + "reference": "4edbcd09fde4353b94ce550f43460eba73baf2cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Gregwar/Captcha/zipball/4edbcd09fde4353b94ce550f43460eba73baf2cc", + "reference": "4edbcd09fde4353b94ce550f43460eba73baf2cc", + "shasum": "" + }, + "require": { + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-mbstring": "*", + "php": ">=5.3.0", + "symfony/finder": "*" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6.4 || ^7.0 || ^8.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Gregwar\\": "src/Gregwar" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Passault", + "email": "g.passault@gmail.com", + "homepage": "http://www.gregwar.com/" + }, + { + "name": "Jeremy Livingston", + "email": "jeremy.j.livingston@gmail.com" + } + ], + "description": "Captcha generator", + "homepage": "https://github.com/Gregwar/Captcha", + "keywords": [ + "bot", + "captcha", + "spam" + ], + "support": { + "issues": "https://github.com/Gregwar/Captcha/issues", + "source": "https://github.com/Gregwar/Captcha/tree/v1.3.0" + }, + "time": "2025-06-23T12:25:54+00:00" + }, { "name": "neutron/sphinxsearch-api", "version": "2.0.8.1", @@ -227,6 +285,152 @@ "source": "https://github.com/Setasign/FPDF/tree/1.8.6" }, "time": "2023-06-26T14:44:25+00:00" + }, + { + "name": "symfony/finder", + "version": "v4.4.44", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "66bd787edb5e42ff59d3523f623895af05043e4f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/66bd787edb5e42ff59d3523f623895af05043e4f", + "reference": "66bd787edb5e42ff59d3523f623895af05043e4f", + "shasum": "" + }, + "require": { + "php": ">=7.1.3", + "symfony/polyfill-php80": "^1.16" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v4.4.44" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-29T07:35:46+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.37.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.37.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-04-10T16:19:22+00:00" } ], "packages-dev": [ @@ -3177,90 +3381,6 @@ ], "time": "2024-09-09T11:45:10+00:00" }, - { - "name": "symfony/polyfill-php80", - "version": "v1.36.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dfb55726c3a76ea3b6459fcfda1ec2d80a682411", - "reference": "dfb55726c3a76ea3b6459fcfda1ec2d80a682411", - "shasum": "" - }, - "require": { - "php": ">=7.2" - }, - "type": "library", - "extra": { - "thanks": { - "url": "https://github.com/symfony/polyfill", - "name": "symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php80\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ion Bazan", - "email": "ion.bazan@gmail.com" - }, - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.36.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-04-10T16:19:22+00:00" - }, { "name": "symfony/polyfill-php81", "version": "v1.36.0", diff --git a/db/cats_schema.sql b/db/cats_schema.sql index 6fbd1dbcc..4967cbcd8 100755 --- a/db/cats_schema.sql +++ b/db/cats_schema.sql @@ -431,7 +431,7 @@ insert into `career_portal_template`(`career_portal_template_id`,`career_portal insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (17,'CATS 2.0','Content - Questionnaire','
\r\n\r\n

\r\n
\r\n\r\n
\r\n
'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (18,'CATS 2.0','Content - Job Details','
\r\n \r\n

Position Details: </h1>\r\n <table id=\"detailsTable\">\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Location:</strong></td>\r\n <td><city>, <state></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Openings:</strong></td>\r\n <td><openings></td>\r\n </tr>\r\n <tr>\r\n <td class=\"detailsHeader\"><strong>Salary Range:</strong></td>\r\n <td><salary></td>\r\n </tr>\r\n </table>\r\n <div id=\"descriptive\">\r\n <p><strong>Description:</strong></p>\r\n <description>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <a-applyToJob onmouseover=\"buttonMouseOver(\'applyToPosition\',true);\" onmouseout=\"buttonMouseOver(\'applyToPosition\',false);\"><img src=\"images/careers_apply.gif\" id=\"applyToPosition\" alt=\"IMAGE: Apply to Position\" /></a>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (19,'CATS 2.0','Content - Thanks for your Submission','<div id=\"careerContent\">\r\n <h1>Application Submitted For: <title></h1>\r\n <div id=\"descriptive\">\r\n <p>Please check your email inbox — You should receive an email confirmation of your application.</p>\r\n <p>Thank you for submitting your application to us. We will review it shortly and make contact with you soon.</p>\r\n </div>\r\n <div id=\"detailsTools\">\r\n <h2>Perform an action:</h2>\r\n <ul>\r\n <li><a href=\"\">Visit our website</a></li>\r\n </ul>\r\n </div>\r\n </div>'); -insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (20,'CATS 2.0','Content - Apply for Position','<div id=\"careerContent\">\r\n <h1>Applying to: <title></h1>\r\n <div class=\"applyBoxLeft\">\r\n <div><h3>1. Import Resume (or CV) and Populate Fields</h3></div>\r\n <table>\r\n <tr>\r\n <td>\r\n \r\n <input-resumeUploadPreview>\r\n </td>\r\n </tr>\r\n </table>\r\n <br />\r\n\r\n <div><h3>2. Tell us about yourself</h3></div>\r\n <p class=\"instructions\">All fields marked with asterisk (*) are required.</p>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td>\r\n <td><input-firstName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td>\r\n <td><input-lastName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailConfirmLabel\" for=\"emailconfirm\">*Confirm Email:</label></td>\r\n <td><input-emailconfirm></td>\r\n </tr>\r\n </table>\r\n </div>\r\n \r\n <div class=\"applyBoxRight\">\r\n <div><h3>3. How may we contact you?</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td>\r\n <td><input-phone-home></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td>\r\n <td><input-phone-cell></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td>\r\n <td><input-phone></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td>\r\n <td><input-best-time-to-call></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td>\r\n <td><input-address></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td>\r\n <td><input-city></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td>\r\n <td><input-state></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td>\r\n <td><input-zip></td>\r\n </tr>\r\n </table>\r\n <br />\r\n <div><h3>4. Additional Information</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td>\r\n <td><input-keySkills></td>\r\n </tr>\r\n <tr>\r\n <td> </td>\r\n <td><img src=\"images/careers_submit.gif\" onmouseover=\"buttonMouseOver(\'submitApplicationNow\',true)\" onmouseout=\"buttonMouseOver(\'submitApplicationNow\',false)\" style=\"cursor: pointer;\" id=\"submitApplicationNow\" alt=\"Submit Application Now\" onclick=\"if (applyValidate()) { document.applyToJobForm.submit(); }\" /></td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>'); +insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (20,'CATS 2.0','Content - Apply for Position','<div id=\"careerContent\">\r\n <h1>Applying to: <title></h1>\r\n <div class=\"applyBoxLeft\">\r\n <div><h3>1. Import Resume (or CV) and Populate Fields</h3></div>\r\n <table>\r\n <tr>\r\n <td>\r\n \r\n <input-resumeUploadPreview>\r\n </td>\r\n </tr>\r\n </table>\r\n <br />\r\n\r\n <div><h3>2. Tell us about yourself</h3></div>\r\n <p class=\"instructions\">All fields marked with asterisk (*) are required.</p>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td>\r\n <td><input-firstName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td>\r\n <td><input-lastName></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"emailConfirmLabel\" for=\"emailconfirm\">*Confirm Email:</label></td>\r\n <td><input-emailconfirm></td>\r\n </tr>\r\n </table>\r\n </div>\r\n \r\n <div class=\"applyBoxRight\">\r\n <div><h3>3. How may we contact you?</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td>\r\n <td><input-phone-home></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td>\r\n <td><input-phone-cell></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td>\r\n <td><input-phone></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td>\r\n <td><input-best-time-to-call></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td>\r\n <td><input-address></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td>\r\n <td><input-city></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td>\r\n <td><input-state></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td>\r\n <td><input-zip></td>\r\n </tr>\r\n </table>\r\n <br />\r\n <div><h3>4. Additional Information</h3></div>\r\n <table>\r\n <tr>\r\n <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td>\r\n <td><input-keySkills></td>\r\n </tr>\r\n <tr>\r\n <td class=\"label\"><label id=\"captchaLabel\" for=\"captcha\">*Captcha:</label></td>\r\n <td><input-captcha req></td>\r\n </tr>\r\n <tr>\r\n <td> </td>\r\n <td><img src=\"images/careers_submit.gif\" onmouseover=\"buttonMouseOver(\'submitApplicationNow\',true)\" onmouseout=\"buttonMouseOver(\'submitApplicationNow\',false)\" style=\"cursor: pointer;\" id=\"submitApplicationNow\" alt=\"Submit Application Now\" onclick=\"if (applyValidate()) { document.applyToJobForm.submit(); }\" /></td>\r\n </tr>\r\n </table>\r\n </div>\r\n </div>'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (21,'CATS 2.0','Content - Candidate Registration','<div id=\"careerContent\">\r\n <h1><applyContent>Applying to <title></applyContent></h1>\r\n <center>\r\n <table cellpadding=\"0\" cellspacing=\"0\">\r\n <tr>\r\n <td><label id=\"emailLabel\" for=\"email\"><h2>Enter your e-mail address:</h2></label></td>\r\n <td><input-email></td>\r\n </tr>\r\n <tr>\r\n <td align=\"right\" valign=\"top\"><input-new></td>\r\n <td style=\"line-height: 18px;\">\r\n <applyContent>\r\n <strong>I have not registered on this website.</strong><br />\r\n (I haven\'t applied to any jobs online)\r\n </applyContent>\r\n </td>\r\n </tr>\r\n <tr>\r\n <td align=\"right\" valign=\"top\"><input-registered></td>\r\n <td style=\"line-height: 20px;\">\r\n <strong>I have registered before</strong><br />\r\n and my last name is:<br />\r\n <input-lastName><br />\r\n and my zip code is:<br />\r\n <input-zip><br /><br />\r\n <input-rememberMe> Remember my information for future visits<br /><br />\r\n <input-submit><br /><br />\r\n </td>\r\n </tr>\r\n </table>\r\n </center>\r\n</div>\r\n'); insert into `career_portal_template`(`career_portal_template_id`,`career_portal_name`,`setting`,`value`) values (22,'CATS 2.0','Content - Candidate Profile','<div id=\"careerContent\"> <h1 style=\"padding: 0; margin: 0; border: 0;\">My Profile</h1><h3 style=\"font-weight: normal;\">Any changes you make to your profile will be updated on our website for all past and future jobs you apply for.</h3> <br /> <div class=\"applyBoxLeft\"> <div><h3>1. Tell us about yourself</h3></div> <p class=\"instructions\">All fields marked with asterisk (*) are required.</p> <table> <tr> <td class=\"label\"><label id=\"firstNameLabel\" for=\"firstName\">*First Name:</label></td> <td><input-firstName></td> </tr> <tr> <td class=\"label\"><label id=\"lastNameLabel\" for=\"lastName\">*Last Name:</label></td> <td><input-lastName></td> </tr> <tr> <td class=\"label\"><label id=\"emailLabel\" for=\"email\">*Email Adddress:</label></td> <td><input-email1></td> </tr> <tr> <td colspan=\"2\"> <input-resume> </td> </tr> </table> </div> <div class=\"applyBoxRight\"> <div><h3>2. How may we contact you?</h3></div> <table> <tr> <td class=\"label\"><label id=\"homePhoneLabel\" for=\"homePhone\">Home Phone:</label></td> <td><input-phoneHome></td> </tr> <tr> <td class=\"label\"><label id=\"mobilePhoneLabel\" for=\"mobilePhone\">Mobile Phone:</label></td> <td><input-phoneCell></td> </tr> <tr> <td class=\"label\"><label id=\"workPhoneLabel\" for=\"workPhone\">Work Phone:</label></td> <td><input-phoneWork></td> </tr> <tr> <td class=\"label\"><label id=\"bestTimeLabel\" for=\"bestTime\">*Best time to call:</label></td> <td><input-bestTimeToCall></td> </tr> <tr> <td class=\"label\"><label id=\"mailingAddressLabel\" for=\"mailingAddress\">Mailing Address:</label></td> <td><input-address></td> </tr> <tr> <td class=\"label\"><label id=\"cityProvinceLabel\" for=\"cityProvince\">*City/Province:</label></td> <td><input-city></td> </tr> <tr> <td class=\"label\"><label id=\"stateCountryLabel\" for=\"stateCountry\">*State/Country:</label></td> <td><input-state></td> </tr> <tr> <td class=\"label\"><label id=\"zipPostalLabel\" for=\"zipPostal\">*Zip/Postal Code:</label></td> <td><input-zip></td> </tr> </table> <br /> <div><h3>3. Additional Information</h3></div> <table> <tr> <td class=\"label\"><label id=\"keySkillsLabel\" for=\"keySkills\">*Key Skills:</label></td> <td><input-keySkills></td> </tr> <tr> <td> </td> <td style=\"padding-top: 40px;\"><input-submit></td> </tr> </table> </div></div>'); diff --git a/modules/careers/CareersUI.php b/modules/careers/CareersUI.php index 9cdddf814..0d85f8c30 100755 --- a/modules/careers/CareersUI.php +++ b/modules/careers/CareersUI.php @@ -154,7 +154,11 @@ private function careersPage() break; } - if ($p == 'showAll') + if ($p == 'captcha') + { + $this->outputCareerPortalCaptcha(); + } + else if ($p == 'showAll') { $template['Content'] = $template['Content - Search Results']; @@ -664,6 +668,7 @@ private function careersPage() $template['Content'] = str_replace('<input-keySkills>', '<input name="keySkills" id="keySkills" class="inputBoxNormal" value="' . $keySkillsEscaped . '" />', $template['Content']); $template['Content'] = str_replace('<input-source>', '<input name="source" id="source" class="inputBoxNormal" value="' . $sourceEscaped . '" />', $template['Content']); $template['Content'] = str_replace('<input-employer>', '<input name="employer" id="employer" class="inputBoxNormal" value="' . $employerEscaped . '" />', $template['Content']); + $template['Content'] = str_replace(array('<input-captcha>', '<input-captcha req>'), '<img src="' . CATSUtility::getIndexName() . '?m=careers&p=captcha&t=' . time() . '" alt="Captcha" /><br />' . '<input type="text" name="captcha" id="captcha" class="inputBoxNormal" />', $template['Content']); $template['Content'] = str_replace('<input-resumeUpload>', '<input type="file" id="resume" name="file" class="inputBoxFile" />', $template['Content']); $template['Content'] = str_replace('<input-resumeUploadPreview>', '<input type="hidden" id="applyToJobSubAction" name="applyToJobSubAction" value="" /> ' @@ -790,6 +795,16 @@ private function careersPage() die(); } + if ($this->careerPortalTemplateRequiresCaptcha($template['Content - Apply for Position'])) + { + $captchaValue = isset($_POST['captcha']) ? $_POST['captcha'] : ''; + if (!$this->validateCareerPortalCaptcha($captchaValue)) + { + CommonErrors::fatal(COMMONERROR_MISSINGFIELDS, $this, 'Invalid CAPTCHA response. Please try again.'); + return; + } + } + // Check if this is a returning candidate $candidateID = isset($_POST['candidateID']) ? intval($_POST['candidateID']) : -1; if ($candidateID == -1) $candidateID = false; @@ -1127,6 +1142,44 @@ private function careersPage() } } + private function outputCareerPortalCaptcha() + { + $builder = new \Gregwar\Captcha\CaptchaBuilder(); + $builder->build(); + + $_SESSION['careerPortalCaptcha'] = $builder->getPhrase(); + + header('Content-type: image/jpeg'); + $builder->output(); + + die(); + } + + private function careerPortalTemplateRequiresCaptcha($templateContent) + { + return (strpos($templateContent, '<input-captcha req>') !== false); + } + + private function validateCareerPortalCaptcha($captchaValue) + { + $expectedPhrase = isset($_SESSION['careerPortalCaptcha']) ? trim((string) $_SESSION['careerPortalCaptcha']) : ''; + $submittedPhrase = trim((string) $captchaValue); + + $this->clearCareerPortalCaptchaPhrase(); + + if ($expectedPhrase === '' || $submittedPhrase === '') + { + return false; + } + + return (strcasecmp($submittedPhrase, $expectedPhrase) === 0); + } + + private function clearCareerPortalCaptchaPhrase() + { + unset($_SESSION['careerPortalCaptcha']); + } + private function _makeApplyValidator($template) { diff --git a/modules/install/Schema.php b/modules/install/Schema.php index 6be26b691..f043cd8a5 100755 --- a/modules/install/Schema.php +++ b/modules/install/Schema.php @@ -1498,6 +1498,61 @@ public static function get() ALTER TABLE `joborder` CHANGE `state` `state` VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT NULL; ', + '379' => 'PHP: + $rows = $db->getAllAssoc( + "SELECT + career_portal_template_id, + value + FROM + career_portal_template + WHERE + career_portal_name = \'CATS 2.0\' + AND setting = \'Content - Apply for Position\'" + ); + + $oldFragment = "<tr>\\r\\n <td> </td>\\r\\n <td><img src=\"images/careers_submit.gif\" onmouseover=\"buttonMouseOver(\'submitApplicationNow\',true)\" onmouseout=\"buttonMouseOver(\'submitApplicationNow\',false)\" style=\"cursor: pointer;\" id=\"submitApplicationNow\" alt=\"Submit Application Now\" onclick=\"if (applyValidate()) { document.applyToJobForm.submit(); }\" /></td>\\r\\n </tr>"; + $captchaFragment = "<tr>\\r\\n <td class=\"label\"><label id=\"captchaLabel\" for=\"captcha\">*Captcha:</label></td>\\r\\n <td><input-captcha req></td>\\r\\n </tr>\\r\\n "; + + foreach ($rows as $row) + { + $templateValue = $row[\'value\']; + + if (strpos($templateValue, \'<input-captcha req>\') !== false) + { + continue; + } + + if (strpos($templateValue, \'<input-captcha>\') !== false) + { + continue; + } + + if (strpos($templateValue, $oldFragment) === false) + { + continue; + } + + $updatedValue = str_replace($oldFragment, $captchaFragment . $oldFragment, $templateValue); + + if ($updatedValue === $templateValue) + { + continue; + } + + $db->query( + sprintf( + "UPDATE + career_portal_template + SET + value = %s + WHERE + career_portal_template_id = %d", + $db->makeQueryString($updatedValue), + (int) $row[\'career_portal_template_id\'] + ) + ); + } + ', ); }