├── README.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt └── src ├── captcha_test.jsx ├── hooks ├── README.md ├── package-lock.json ├── package.json └── react-simple-captcha.js ├── index.css ├── index.js ├── logo.svg └── serviceWorker.js /README.md: -------------------------------------------------------------------------------- 1 | # React Simple Captcha 2 | 3 | React Simple Captcha is a very powerful, highly customizable and easy to use captcha for React JS. 4 | 5 | **Install** 6 | ```sh 7 | $ npm install react-simple-captcha 8 | ``` 9 | 10 | **Demo** 11 | Demo can be seen [here](https://scriptse.com/blog/add-captcha-in-reactjs-application/react-simple-captcha-demo/ "React Simple Captcha Demo"). 12 | 13 | **Usage Guide** 14 | 15 |

Just follow these 4 easy steps to use the react simple captcha:

16 | 17 | 18 | - **Step 1:** 19 | 20 | Import all functions from react-simple-captcha 21 | 22 | ```sh 23 | import { loadCaptchaEnginge, LoadCanvasTemplate, LoadCanvasTemplateNoReload, validateCaptcha } from 'react-simple-captcha'; 24 | ``` 25 | 26 | - **Step 2:** 27 | 28 | Place **< LoadCanvasTemplate />** or **< LoadCanvasTemplateNoReload />** *(if you do not want 'Reload Captcha' functionality)* in your render code 29 | 30 | ```sh 31 | render() { 32 | return (
33 | 34 |
); 35 | }; 36 | ``` 37 | 38 | **OR** 39 | 40 | ```sh 41 | render() { 42 | return (
43 | 44 |
); 45 | }; 46 | ``` 47 | 48 | - **Step 3:** 49 | 50 | Paste **loadCaptchaEnginge(6)** *(You can change 6 to number of captcha charcters you want)* in **componentDidMount** 51 | 52 | ```sh 53 | componentDidMount () { 54 | loadCaptchaEnginge(6); 55 | }; 56 | ``` 57 | - **Step 4:** 58 | 59 | Validate captcha by using **validateCaptcha(user_captcha_value)** 60 | 61 | 62 | ```sh 63 | doSubmit = () => { 64 | 65 | let user_captcha_value = document.getElementById('user_captcha_input').value; 66 | 67 | if (validateCaptcha(user_captcha_value)==true) { 68 | alert('Captcha Matched'); 69 | } 70 | 71 | else { 72 | alert('Captcha Does Not Match'); 73 | } 74 | }; 75 | ``` 76 | 77 | **OR** 78 | If you don't want captcha to be reloaded if user enter the wrong value then set second parameter to *false* **validateCaptcha(user_captcha_value, false)** 79 | 80 | 81 | ```sh 82 | doSubmit = () => { 83 | 84 | let user_captcha_value = document.getElementById('user_captcha_input').value; 85 | 86 | if (validateCaptcha(user_captcha_value, false)==true) { 87 | alert('Captcha Matched'); 88 | } 89 | 90 | else { 91 | alert('Captcha Does Not Match'); 92 | } 93 | }; 94 | ``` 95 | 96 | 97 | ### Options 98 | 99 | Listed are all the options available for react-simple-captcha 100 | 101 | | Name | Description | 102 | | ------ | ------ | 103 | | **< LoadCanvasTemplate />** | It will load the captcha **with 'Reload Captcha'** functionality. Place between your render code, usage example **< LoadCanvasTemplate />** | 104 | | **< LoadCanvasTemplateNoReload />** | It will load the captcha **without 'Reload Captcha'** functionality. Place between your render code, usage example **< LoadCanvasTemplateNoReload />** | 105 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*);** | Simply paste it in **componentDidMount()**. Pass number of captcha characters you want to display. | 106 | | **validateCaptcha(*User_Submitted_Value*)** | Will return *true* if user submitted value matches with captcha otherwise *false*. Also will reload captcha if user submitted value is *false* | 107 | | **validateCaptcha(*User_Submitted_Value*, *false*)** | Will return *true* if user submitted value matches with captcha otherwise *false*. Will not reload captcha if user submitted value is *false* | 108 | 109 | ### Optional Changes 110 | 111 | 112 | | **Options** | **All of these changes are optionals** | 113 | | ------ | ------ | 114 | | **< LoadCanvasTemplate reloadText="Reload My Captcha" />** | If you want to change the **"Reload Captcha"** with your own text | 115 | | **< LoadCanvasTemplate reloadColor="red" />** | If you want to change the blue color of **"Reload Captcha"** | 116 | | **< LoadCanvasTemplate reloadText="Reload My Captcha" reloadColor="red" />** | If you want to change the **"Reload Captcha"** text and it's blue color | 117 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*);** | If you want to change the background color from black to your custom color. Example Syntax to change the background color to red use: **loadCaptchaEnginge(6,'red');** | 118 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*);** | If you want to change the font color from white to your custom color. Example Syntax to change the font color to blue use: **loadCaptchaEnginge(6,'','blue');** | 119 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*);** | If you want to change the both background and font color. Example Syntax to change the background color to white and font color to black use: **loadCaptchaEnginge(6,'white','black');** | 120 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Upper_Characters_Only*);** | If you want only upper characters and numbers use **loadCaptchaEnginge(6,'','','upper');** | 121 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Lower_Characters_Only*);** | If you want only lower characters and numbers use **loadCaptchaEnginge(6,'','','lower');** | 122 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Numbers*);** | If you want only numbers use **loadCaptchaEnginge(6,'','','numbers');** | 123 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Special_Characters*);** | If you want only special characters use **loadCaptchaEnginge(6,'','','special_char');** | 124 | 125 | ### Example 126 | Let's create a class name **CaptchaTest** with react simple captcha functionality: 127 | 128 | ```sh 129 | import React, { Component } from 'react'; 130 | import { loadCaptchaEnginge, LoadCanvasTemplate, LoadCanvasTemplateNoReload, validateCaptcha } from 'react-simple-captcha'; 131 | 132 | 133 | 134 | class CaptchaTest extends Component { 135 | 136 | componentDidMount () { 137 | loadCaptchaEnginge(6); 138 | }; 139 | 140 | doSubmit = () => { 141 | let user_captcha = document.getElementById('user_captcha_input').value; 142 | 143 | if (validateCaptcha(user_captcha)===true) { 144 | alert('Captcha Matched'); 145 | loadCaptchaEnginge(6); 146 | document.getElementById('user_captcha_input').value = ""; 147 | } 148 | 149 | else { 150 | alert('Captcha Does Not Match'); 151 | document.getElementById('user_captcha_input').value = ""; 152 | } 153 | }; 154 | 155 | render() { 156 | 157 | 158 | return (
159 |
160 |
161 | 162 |
163 | 164 |
165 | 166 |
167 |
168 |
169 | 170 |
171 |
172 |
173 | 174 |
175 | 176 |
177 |
); 178 | }; 179 | } 180 | 181 | export default CaptchaTest; 182 | ``` 183 | Import **CaptchaTest** in index.js 184 | ```sh 185 | import CaptchaTest from './captcha_test'; 186 | ``` 187 | Now replace **ReactDOM.render** with 188 | ```sh 189 | ReactDOM.render(, document.getElementById('root')); 190 | ``` 191 | ### Common Issues 192 | 193 | **Not Woking on ReactJS Version 18^** 194 | Solution Here: https://github.com/masroorejaz/react-simple-captcha/issues/23 195 | 196 | **Not Woking on Next.js** 197 | Solution Here: https://github.com/masroorejaz/react-simple-captcha/issues/32 198 | 199 | **Not Woking with TypeScript** 200 | Solution Here: https://github.com/masroorejaz/react-simple-captcha/issues/33 201 | 202 | ### Support Me 203 | https://www.buymeacoffee.com/masroorejaz 204 | 205 | ### Browser support 206 | Works in every modern browser which has support for [canvas element](https://caniuse.com/canvas-text "canvas element"). 207 | 208 | ### License 209 | react-simple-captcha is licensed under the [MIT license](https://opensource.org/licenses/MIT "MIT license"). 210 | 211 | ### Developer Profile 212 | 213 | **Name:** Masroor Ejaz 214 | **Linkedin:** https://www.linkedin.com/in/masroorejaz/ 215 | **Twitter:** https://twitter.com/masroorejaz 216 | **Note:** Feel free to contact me if you have any questions! 217 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-simple-captcha-demo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "bootstrap": "^4.5.3", 10 | "react": "^17.0.1", 11 | "react-dom": "^17.0.1", 12 | "react-html-parser": "^2.0.2", 13 | "react-router-dom": "^5.2.0", 14 | "react-scripts": "4.0.0", 15 | "react-simple-captcha": "^9.0.0", 16 | "web-vitals": "^0.2.4" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masroorejaz/react-simple-captcha/d847a5fb05a5184413ec24a34e8e4c8baefc23ef/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React Simple Captcha 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masroorejaz/react-simple-captcha/d847a5fb05a5184413ec24a34e8e4c8baefc23ef/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/masroorejaz/react-simple-captcha/d847a5fb05a5184413ec24a34e8e4c8baefc23ef/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /src/captcha_test.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { loadCaptchaEnginge, LoadCanvasTemplate, validateCaptcha } from 'react-simple-captcha'; 3 | 4 | 5 | 6 | 7 | class CaptchaTest extends Component { 8 | 9 | componentDidMount () { 10 | loadCaptchaEnginge(8); 11 | }; 12 | 13 | doSubmit = () => { 14 | let user_captcha = document.getElementById('user_captcha_input').value; 15 | 16 | if (validateCaptcha(user_captcha)===true) { 17 | alert('Captcha Matched'); 18 | loadCaptchaEnginge(6); 19 | document.getElementById('user_captcha_input').value = ""; 20 | } 21 | 22 | else { 23 | alert('Captcha Does Not Match'); 24 | document.getElementById('user_captcha_input').value = ""; 25 | } 26 | }; 27 | 28 | render() { 29 | 30 | 31 | return (
32 |
33 |
34 | 35 | 36 |
37 | < LoadCanvasTemplate reloadColor="red" /> 38 |
39 | 40 | 41 |
42 |
43 |
44 | 45 |
46 |
47 |
48 | 49 |
50 | 51 |
52 |
); 53 | }; 54 | } 55 | 56 | export default CaptchaTest; 57 | -------------------------------------------------------------------------------- /src/hooks/README.md: -------------------------------------------------------------------------------- 1 | # React Simple Captcha 2 | 3 | React Simple Captcha is a very powerful, highly customizable and easy to use captcha for React JS. 4 | 5 | **Install** 6 | ```sh 7 | $ npm install react-simple-captcha 8 | ``` 9 | 10 | **Demo** 11 | Demo can be seen [here](https://scriptse.com/blog/add-captcha-in-reactjs-application/react-simple-captcha-demo/ "React Simple Captcha Demo"). 12 | 13 | **Usage Guide** 14 | 15 |

Just follow these 4 easy steps to use the react simple captcha:

16 | 17 | 18 | - **Step 1:** 19 | 20 | Import all functions from react-simple-captcha 21 | 22 | ```sh 23 | import { loadCaptchaEnginge, LoadCanvasTemplate, LoadCanvasTemplateNoReload, validateCaptcha } from 'react-simple-captcha'; 24 | ``` 25 | 26 | - **Step 2:** 27 | 28 | Place **< LoadCanvasTemplate />** or **< LoadCanvasTemplateNoReload />** *(if you do not want 'Reload Captcha' functionality)* in your render code 29 | 30 | ```sh 31 | render() { 32 | return (
33 | 34 |
); 35 | }; 36 | ``` 37 | 38 | **OR** 39 | 40 | ```sh 41 | render() { 42 | return (
43 | 44 |
); 45 | }; 46 | ``` 47 | 48 | - **Step 3:** 49 | 50 | Paste **loadCaptchaEnginge(6)** *(You can change 6 to number of captcha charcters you want)* in **componentDidMount** 51 | 52 | ```sh 53 | componentDidMount () { 54 | loadCaptchaEnginge(6); 55 | }; 56 | ``` 57 | - **Step 4:** 58 | 59 | Validate captcha by using **validateCaptcha(user_captcha_value)** 60 | 61 | 62 | ```sh 63 | doSubmit = () => { 64 | 65 | let user_captcha_value = document.getElementById('user_captcha_input').value; 66 | 67 | if (validateCaptcha(user_captcha_value)==true) { 68 | alert('Captcha Matched'); 69 | } 70 | 71 | else { 72 | alert('Captcha Does Not Match'); 73 | } 74 | }; 75 | ``` 76 | 77 | **OR** 78 | If you don't want captcha to be reloaded if user enter the wrong value then set second parameter to *false* **validateCaptcha(user_captcha_value, false)** 79 | 80 | 81 | ```sh 82 | doSubmit = () => { 83 | 84 | let user_captcha_value = document.getElementById('user_captcha_input').value; 85 | 86 | if (validateCaptcha(user_captcha_value, false)==true) { 87 | alert('Captcha Matched'); 88 | } 89 | 90 | else { 91 | alert('Captcha Does Not Match'); 92 | } 93 | }; 94 | ``` 95 | 96 | 97 | ### Options 98 | 99 | Listed are all the options available for react-simple-captcha 100 | 101 | | Name | Description | 102 | | ------ | ------ | 103 | | **< LoadCanvasTemplate />** | It will load the captcha **with 'Reload Captcha'** functionality. Place between your render code, usage example **< LoadCanvasTemplate />** | 104 | | **< LoadCanvasTemplateNoReload />** | It will load the captcha **without 'Reload Captcha'** functionality. Place between your render code, usage example **< LoadCanvasTemplateNoReload />** | 105 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*);** | Simply paste it in **componentDidMount()**. Pass number of captcha characters you want to display. | 106 | | **validateCaptcha(*User_Submitted_Value*)** | Will return *true* if user submitted value matches with captcha otherwise *false*. Also will reload captcha if user submitted value is *false* | 107 | | **validateCaptcha(*User_Submitted_Value*, *false*)** | Will return *true* if user submitted value matches with captcha otherwise *false*. Will not reload captcha if user submitted value is *false* | 108 | 109 | ### Optional Changes 110 | 111 | 112 | | **Options** | **All of these changes are optionals** | 113 | | ------ | ------ | 114 | | **< LoadCanvasTemplate reloadText="Reload My Captcha" />** | If you want to change the **"Reload Captcha"** with your own text | 115 | | **< LoadCanvasTemplate reloadColor="red" />** | If you want to change the blue color of **"Reload Captcha"** | 116 | | **< LoadCanvasTemplate reloadText="Reload My Captcha" reloadColor="red" />** | If you want to change the **"Reload Captcha"** text and it's blue color | 117 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*);** | If you want to change the background color from black to your custom color. Example Syntax to change the background color to red use: **loadCaptchaEnginge(6,'red');** | 118 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*);** | If you want to change the font color from white to your custom color. Example Syntax to change the font color to blue use: **loadCaptchaEnginge(6,'','blue');** | 119 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*);** | If you want to change the both background and font color. Example Syntax to change the background color to white and font color to black use: **loadCaptchaEnginge(6,'white','black');** | 120 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Upper_Characters_Only*);** | If you want only upper characters and numbers use **loadCaptchaEnginge(6,'','','upper');** | 121 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Lower_Characters_Only*);** | If you want only lower characters and numbers use **loadCaptchaEnginge(6,'','','lower');** | 122 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Numbers*);** | If you want only numbers use **loadCaptchaEnginge(6,'','','numbers');** | 123 | | **loadCaptchaEnginge(*Number_Of_Captcha_Charcters*, *Background_Color*, *Font_Color*, *Special_Characters*);** | If you want only special characters use **loadCaptchaEnginge(6,'','','special_char');** | 124 | 125 | ### Example 126 | Let's create a class name **CaptchaTest** with react simple captcha functionality: 127 | 128 | ```sh 129 | import React, { Component } from 'react'; 130 | import { loadCaptchaEnginge, LoadCanvasTemplate, LoadCanvasTemplateNoReload, validateCaptcha } from 'react-simple-captcha'; 131 | 132 | 133 | 134 | class CaptchaTest extends Component { 135 | 136 | componentDidMount () { 137 | loadCaptchaEnginge(6); 138 | }; 139 | 140 | doSubmit = () => { 141 | let user_captcha = document.getElementById('user_captcha_input').value; 142 | 143 | if (validateCaptcha(user_captcha)===true) { 144 | alert('Captcha Matched'); 145 | loadCaptchaEnginge(6); 146 | document.getElementById('user_captcha_input').value = ""; 147 | } 148 | 149 | else { 150 | alert('Captcha Does Not Match'); 151 | document.getElementById('user_captcha_input').value = ""; 152 | } 153 | }; 154 | 155 | render() { 156 | 157 | 158 | return (
159 |
160 |
161 | 162 |
163 | 164 |
165 | 166 |
167 |
168 |
169 | 170 |
171 |
172 |
173 | 174 |
175 | 176 |
177 |
); 178 | }; 179 | } 180 | 181 | export default CaptchaTest; 182 | ``` 183 | Import **CaptchaTest** in index.js 184 | ```sh 185 | import CaptchaTest from './captcha_test'; 186 | ``` 187 | Now replace **ReactDOM.render** with 188 | ```sh 189 | ReactDOM.render(, document.getElementById('root')); 190 | ``` 191 | ### Common Issues 192 | 193 | **Not Woking on ReactJS Version 18^** 194 | Solution Here: https://github.com/masroorejaz/react-simple-captcha/issues/23 195 | 196 | **Not Woking on Next.js** 197 | Solution Here: https://github.com/masroorejaz/react-simple-captcha/issues/32 198 | 199 | **Not Woking with TypeScript** 200 | Solution Here: https://github.com/masroorejaz/react-simple-captcha/issues/33 201 | 202 | ### Support Me 203 | https://www.buymeacoffee.com/masroorejaz 204 | 205 | ### Browser support 206 | Works in every modern browser which has support for [canvas element](https://caniuse.com/canvas-text "canvas element"). 207 | 208 | ### License 209 | react-simple-captcha is licensed under the [MIT license](https://opensource.org/licenses/MIT "MIT license"). 210 | 211 | ### Developer Profile 212 | 213 | **Name:** Masroor Ejaz 214 | **Linkedin:** https://www.linkedin.com/in/masroorejaz/ 215 | **Twitter:** https://twitter.com/masroorejaz 216 | **Note:** Feel free to contact me if you have any questions! 217 | -------------------------------------------------------------------------------- /src/hooks/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-simple-captcha", 3 | "version": "6.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "dom-serializer": { 8 | "version": "0.2.2", 9 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", 10 | "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", 11 | "requires": { 12 | "domelementtype": "^2.0.1", 13 | "entities": "^2.0.0" 14 | }, 15 | "dependencies": { 16 | "domelementtype": { 17 | "version": "2.0.2", 18 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", 19 | "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==" 20 | }, 21 | "entities": { 22 | "version": "2.1.0", 23 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", 24 | "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==" 25 | } 26 | } 27 | }, 28 | "domelementtype": { 29 | "version": "1.3.1", 30 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", 31 | "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" 32 | }, 33 | "domhandler": { 34 | "version": "2.4.2", 35 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", 36 | "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", 37 | "requires": { 38 | "domelementtype": "1" 39 | } 40 | }, 41 | "domutils": { 42 | "version": "1.7.0", 43 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", 44 | "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", 45 | "requires": { 46 | "dom-serializer": "0", 47 | "domelementtype": "1" 48 | } 49 | }, 50 | "entities": { 51 | "version": "1.1.2", 52 | "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", 53 | "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" 54 | }, 55 | "htmlparser2": { 56 | "version": "3.10.1", 57 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", 58 | "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", 59 | "requires": { 60 | "domelementtype": "^1.3.1", 61 | "domhandler": "^2.3.0", 62 | "domutils": "^1.5.1", 63 | "entities": "^1.1.1", 64 | "inherits": "^2.0.1", 65 | "readable-stream": "^3.1.1" 66 | } 67 | }, 68 | "inherits": { 69 | "version": "2.0.4", 70 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 71 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 72 | }, 73 | "js-tokens": { 74 | "version": "4.0.0", 75 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 76 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" 77 | }, 78 | "loose-envify": { 79 | "version": "1.4.0", 80 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 81 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 82 | "requires": { 83 | "js-tokens": "^3.0.0 || ^4.0.0" 84 | } 85 | }, 86 | "object-assign": { 87 | "version": "4.1.1", 88 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 89 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 90 | }, 91 | "react": { 92 | "version": "17.0.1", 93 | "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz", 94 | "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==", 95 | "requires": { 96 | "loose-envify": "^1.1.0", 97 | "object-assign": "^4.1.1" 98 | } 99 | }, 100 | "react-dom": { 101 | "version": "17.0.1", 102 | "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.1.tgz", 103 | "integrity": "sha512-6eV150oJZ9U2t9svnsspTMrWNyHc6chX0KzDeAOXftRa8bNeOKTTfCJ7KorIwenkHd2xqVTBTCZd79yk/lx/Ug==", 104 | "requires": { 105 | "loose-envify": "^1.1.0", 106 | "object-assign": "^4.1.1", 107 | "scheduler": "^0.20.1" 108 | } 109 | }, 110 | "react-html-parser": { 111 | "version": "2.0.2", 112 | "resolved": "https://registry.npmjs.org/react-html-parser/-/react-html-parser-2.0.2.tgz", 113 | "integrity": "sha512-XeerLwCVjTs3njZcgCOeDUqLgNIt/t+6Jgi5/qPsO/krUWl76kWKXMeVs2LhY2gwM6X378DkhLjur0zUQdpz0g==", 114 | "requires": { 115 | "htmlparser2": "^3.9.0" 116 | } 117 | }, 118 | "readable-stream": { 119 | "version": "3.6.0", 120 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 121 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 122 | "requires": { 123 | "inherits": "^2.0.3", 124 | "string_decoder": "^1.1.1", 125 | "util-deprecate": "^1.0.1" 126 | } 127 | }, 128 | "safe-buffer": { 129 | "version": "5.2.1", 130 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 131 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 132 | }, 133 | "scheduler": { 134 | "version": "0.20.1", 135 | "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.1.tgz", 136 | "integrity": "sha512-LKTe+2xNJBNxu/QhHvDR14wUXHRQbVY5ZOYpOGWRzhydZUqrLb2JBvLPY7cAqFmqrWuDED0Mjk7013SZiOz6Bw==", 137 | "requires": { 138 | "loose-envify": "^1.1.0", 139 | "object-assign": "^4.1.1" 140 | } 141 | }, 142 | "string_decoder": { 143 | "version": "1.3.0", 144 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 145 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 146 | "requires": { 147 | "safe-buffer": "~5.2.0" 148 | } 149 | }, 150 | "util-deprecate": { 151 | "version": "1.0.2", 152 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 153 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /src/hooks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-simple-captcha", 3 | "version": "9.0.0", 4 | "description": "A very simple,powerful and highly customizable captcha for ReactJS", 5 | "main": "react-simple-captcha.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/masroorejaz/react-simple-captcha.git" 12 | }, 13 | "keywords": [ 14 | "react", 15 | "reactjs-captcha", 16 | "captcha", 17 | "react-captcha", 18 | "react-simple-captcha" 19 | ], 20 | "author": "Masroor Ejaz", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/masroorejaz/react-simple-captcha/issues" 24 | }, 25 | "homepage": "https://github.com/masroorejaz/react-simple-captcha#readme", 26 | "dependencies": { 27 | "react-html-parser": "^2.0.2" 28 | }, 29 | "devDependencies": { 30 | "react": "^17.1.0", 31 | "react-dom": "^17.1.0" 32 | }, 33 | "peerDependencies": { 34 | "react": "*" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/hooks/react-simple-captcha.js: -------------------------------------------------------------------------------- 1 | import { Component } from 'react'; 2 | import ReactHtmlParser from 'react-html-parser'; 3 | 4 | let captcha_value = ''; 5 | let captcha_number = ''; 6 | let backgroundColor_value = ''; 7 | let fontColor_value = ''; 8 | let charMap_value = ''; 9 | let LoadCanvasTemplate_HTML = "
Reload Captcha
"; 10 | let LoadCanvasTemplateNoReload_HTML = "
";; 11 | 12 | 13 | export const loadCaptchaEnginge = (numberOfCharacters, backgroundColor = 'white', fontColor = 'black', charMap = '') => { 14 | 15 | backgroundColor_value = backgroundColor; 16 | fontColor_value = fontColor; 17 | charMap_value = charMap; 18 | captcha_number = numberOfCharacters; 19 | let retVal = ""; 20 | let charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 21 | if (charMap === "upper") { 22 | charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 23 | } else if (charMap === "lower") { 24 | charset = "abcdefghijklmnopqrstuvwxyz0123456789"; 25 | } 26 | else if (charMap === "numbers") { 27 | charset = "0123456789"; 28 | } 29 | else if (charMap === "special_char") { 30 | charset = "~`!@#$%^&*()_+-=[]{}\|:'<>,.?/"; 31 | } 32 | 33 | let length = parseInt(numberOfCharacters); 34 | 35 | 36 | 37 | for (let i = 0, n = charset.length; i < length; ++i) { 38 | retVal += charset.charAt(Math.floor(Math.random() * n)); 39 | } 40 | 41 | let captcha = retVal; 42 | 43 | captcha_value = captcha; 44 | 45 | 46 | 47 | let length_height_canvas = Math.round(parseInt(length) / 3); 48 | 49 | let canvas = document.getElementById('canv'), 50 | ctx = canvas.getContext('2d'), 51 | img = document.getElementById('image'); 52 | let text = captcha; 53 | let x = 12.5; 54 | let y = 15; 55 | let lineheight = 30; 56 | 57 | let canvas_height = (parseInt(length) - parseInt(length_height_canvas)) * 20; 58 | let lines = text.split('\n'); 59 | let lineLengthOrder = lines.slice(0).sort(function (a, b) { 60 | return b.length - a.length; 61 | }); 62 | ctx.canvas.width = parseInt(length) * 25; 63 | ctx.canvas.height = (lines.length * lineheight); 64 | 65 | ctx.fillStyle = backgroundColor; 66 | ctx.fillRect(0, 0, canvas.width, canvas.height); 67 | 68 | 69 | ctx.textBaseline = "middle"; 70 | ctx.font = "italic 20px Arial"; 71 | ctx.fillStyle = fontColor; 72 | 73 | 74 | 75 | 76 | let num = 0; 77 | for (let i = 0; i < parseInt(length); i++) { 78 | num = parseInt(num) + 1; 79 | let heigt_num = 20 * num; 80 | ctx.fillText(retVal[i], heigt_num, Math.round(Math.random() * (15 - 12) + 12)); 81 | } 82 | 83 | document.getElementById("reload_href").onclick = function () { 84 | loadCaptchaEnginge(captcha_number, backgroundColor, fontColor, charMap); 85 | } 86 | 87 | }; 88 | 89 | export const validateCaptcha = (userValue, reload = true) => { 90 | if (userValue != captcha_value) { 91 | if (reload == true) { 92 | loadCaptchaEnginge(captcha_number, backgroundColor_value, fontColor_value, charMap_value); 93 | } 94 | 95 | return false; 96 | } 97 | 98 | else { 99 | return true; 100 | } 101 | }; 102 | 103 | export class LoadCanvasTemplate extends Component { 104 | 105 | render() { 106 | let reload_text = ""; 107 | let reload_color = ""; 108 | LoadCanvasTemplate_HTML = "
Reload Captcha
"; 109 | 110 | if (this.props.reloadText) { 111 | reload_text = this.props.reloadText; 112 | 113 | 114 | } 115 | 116 | if (this.props.reloadColor) { 117 | reload_color = this.props.reloadColor; 118 | } 119 | 120 | if (reload_text == "") { 121 | reload_text = "Reload Captcha"; 122 | } 123 | 124 | if (reload_color == "") { 125 | reload_color = "blue"; 126 | } 127 | 128 | LoadCanvasTemplate_HTML = "
" + reload_text + "
"; 129 | 130 | return (ReactHtmlParser(LoadCanvasTemplate_HTML)); 131 | } 132 | 133 | }; 134 | 135 | export class LoadCanvasTemplateNoReload extends Component { 136 | 137 | render() { 138 | return (ReactHtmlParser(LoadCanvasTemplateNoReload_HTML)); 139 | } 140 | 141 | }; 142 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { BrowserRouter } from 'react-router-dom'; 4 | import './index.css'; 5 | import 'bootstrap/dist/css/bootstrap.css'; 6 | import CaptchaTest from './captcha_test'; 7 | 8 | 9 | ReactDOM.render( 10 | 11 | 12 | , document.getElementById('root')); 13 | 14 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' } 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready.then(registration => { 134 | registration.unregister(); 135 | }); 136 | } 137 | } 138 | --------------------------------------------------------------------------------