Compare commits

..

288 Commits

Author SHA1 Message Date
c8ac054093 Merge branch 'release/v8.0.0.M26' 2019-11-12 09:32:50 +01:00
fe2ac1b8d4 New release, updating pom.xml 2019-11-12 09:22:45 +01:00
ba74898441 Add JavaScript to assignment otherwise you will not be able to see the flow of the endpoint 2019-11-12 09:12:37 +01:00
1d477bd0e8 Rename endpoint in JavaScript as backend call uses different endpoint 2019-11-12 09:12:37 +01:00
48b604d6d9 Enable salaries again as rest controller 2019-11-12 09:12:37 +01:00
2ab8a838c3 update JRE and milestone version to latest 2019-11-11 22:03:20 +01:00
e07a2aff48 Fix mistake the SQL exception should be throws otherwise users cannot see the table name (servers) makes it impossible to
solve the assignment. Add explicit test for this to guard against future mistakes
2019-11-11 21:17:51 +01:00
7d48427d4f Integrate ZAP 2.8.0 (no HUB) as the setup is different also update the filtering as usual ZAP exclusion is again broken 2019-11-11 21:17:51 +01:00
d8844216cc Add solution for Firefox no longer proxying localhost at all 2019-11-11 10:38:25 +01:00
ab3cd118c9 Explicitly set Maven repo to https 2019-11-11 10:38:05 +01:00
8da4342430 Improve readability of query (#685)
thanks! and do not forget to clean your .webgoat... local db related files
2019-11-04 13:28:35 +01:00
ddf6ac9bdb Improve handling of missing parameters, now returns HTTP/401 (#698) 2019-11-03 18:27:03 +01:00
f7b794bf68 Race condition in counting number of attempts #567 (#697)
Add version to Hibernate mapping so we get optimistic locking this solves
number of parallel calls trying to update/guess and mess with the lesson
counter
2019-11-03 18:14:15 +01:00
1a83e2825e Code style (#696)
* Remove Guava dependency from WebGoat

* Add Checkstyle to the project with very basic standards so we have a
style across lessons. It does not interfere with basic Intellij formatting
2019-11-03 18:11:09 +01:00
66bd1d8c1a Remove obsolete methods
As there were removed also in e8d086ac9b (diff-98a46e7f04c7a2dd03d59046076aac5bL40)
2019-10-30 08:28:42 +01:00
531db87876 Fix CommandInjection java files
Avoid these compilation errors:

```
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjectionExecute.java:[47,8] class HttpBasicsInterceptRequest is public, should be declared in a file named HttpBasicsInterceptRequest.java
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[38,8] class HttpProxies is public, should be declared in a file named HttpProxies.java
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[5,33] cannot find symbol
  symbol:   class AbstractLesson
  location: package org.owasp.webgoat.lessons
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[38,34] cannot find symbol
  symbol: class AbstractLesson
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[39,5] method does not override or implement a method from a supertype
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[44,5] method does not override or implement a method from a supertype
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[49,5] method does not override or implement a method from a supertype
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[54,5] method does not override or implement a method from a supertype
[ERROR] /tmp/app/webgoat-lessons/command-injection/src/main/java/org/owasp/webgoat/plugin/CommandInjection.java:[59,5] method does not override or implement a method from a supertype
[INFO] 9 errors
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  4.356 s
[INFO] Finished at: 2019-10-19T21:13:03Z
[INFO] ------------------------------------------------------------------------
```
2019-10-30 08:28:42 +01:00
cac5985873 Fix command-injection pom.xml 2019-10-30 08:28:42 +01:00
c03b8e22bf Fix webgoat-lesson-template parent artifact ref
WebGoat 8 latest ([develop](9fdbbf69d6)) has the following compilation error:

```
Building Maven project at /builds/gitlab-org/security-products/tests/webgoat/webgoat-lessons/webgoat-lesson-template.
[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM for org.owasp.webgoat.lesson:webgoat-lesson-template:[unknown-version]: Could not find artifact org.owasp.webgoat.lesson:webgoat-lessons-parent:pom:8.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 6, column 13
 @ 
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project org.owasp.webgoat.lesson:webgoat-lesson-template:[unknown-version] (/builds/gitlab-org/security-products/tests/webgoat/webgoat-lessons/webgoat-lesson-template/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.owasp.webgoat.lesson:webgoat-lesson-template:[unknown-version]: Could not find artifact org.owasp.webgoat.lesson:webgoat-lessons-parent:pom:8.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 6, column 13 -> [Help 2]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
Error: Project couldn't be built: exit status 1
```

This is due to an invalid (obsolete) ref in the parent artifact.

Full logs: https://gitlab.com/gitlab-org/security-products/tests/webgoat/-/jobs/322887707
2019-10-30 08:28:42 +01:00
710adfae20 Upgrade to latest Spring Boot version 2019-10-30 08:28:14 +01:00
9b87fd602c Explicitly set session persistence to false (result in non serializable exception) 2019-10-30 08:28:14 +01:00
28299f3ced Bind HSQLDB to same address as WebGoat 2019-10-30 08:28:14 +01:00
689e3de7a4 Final changes for splitting SQL WebGoat and lessons 2019-10-30 08:28:14 +01:00
25dae3a4a8 Fix merge request 2019-10-30 08:28:14 +01:00
d73875e8e8 Remove empty line 2019-10-30 08:28:14 +01:00
e783c0c1f1 SQL: Cannot use apostrophe/quotes on string literals #662 2019-10-30 08:28:14 +01:00
2a6b3d189e Disable csrf through property no longer works and we already have it in WebSecurityConfig. Thymeleaf templates caching is set on the resolvers themselves 2019-10-30 08:28:14 +01:00
96d11697d4 SQL Injection lesson 6 minor mistakes in examples #663 2019-10-30 08:28:14 +01:00
a0933d83d5 Reworked all the SQL statements to be uppercase 2019-10-30 08:28:14 +01:00
9fdbbf69d6 Proposition for fixing broken/improving links (#686)
* As stated on enzoic.com: "PasswordPing is now Enzoic!"

* Add references to other OWASP resources
2019-10-16 17:29:27 +02:00
1f00d461a8 cleaned logs and changed username length for csrf-uuid 2019-10-15 13:59:18 +02:00
6dc679e7b8 final tests and fixed the issue of getting the name of the loggedinuser 2019-10-15 13:59:18 +02:00
00873cfe3f csrf7 test cases added 2019-10-15 13:59:18 +02:00
e932253f06 initial test cases added 2019-10-15 13:59:18 +02:00
8d7142e6d3 upgrade ascii doc with support for link in new tab 2019-10-15 13:55:34 +02:00
e0ac4a1083 lessons in correct order and scoreboard visible again (#680) 2019-10-10 09:45:43 +02:00
f140875156 fixed views for password reset (#679) 2019-10-10 07:50:47 +02:00
18d43f16d3 working version with fixed link and GET for tracing purposes (#677)
* working version with fixed link and GET for tracing purposes

* added integration test

* filter on request log
2019-10-09 09:58:35 +02:00
aee4b74202 Update Receiving_mail.adoc (#676) 2019-10-03 18:22:54 +02:00
b481ed70e8 Fix typo in SQL Injection(Introduction) (#675)
Fix typo `date` to `data` which seems more appropriate in context.
2019-10-03 10:01:35 +02:00
fd7fb4cfbc seems that we forgot about this one in the spring-boot-2 upgrade (#674) 2019-10-02 14:52:21 +02:00
663224d06a xxe path info (#670)
* xxe path info aid added

* xxe path info aid added

*  changes to template file and hints

* added ssl test support for XXE

* added ssl test support for XXE

* restconfig replaced by httpsrelaxed

* processed review comments on hints and example
2019-10-02 09:59:32 +02:00
7536770769 deserialization made solvable again (#673)
* first objects and unit tests for making a fix for the lesson

* example added

* unit test for windows and linux

* added unit tests hints and feedbacks and updated lesson pages

* small typo correction
2019-10-02 08:26:48 +02:00
6c14f4987c Update IntroductionWebWolf.adoc
use aangepast in gebruiker
2019-10-02 07:55:57 +02:00
3d38ed7680 some text change 2019-10-02 07:55:57 +02:00
1a11702979 NL intro 2019-10-02 07:55:57 +02:00
0319c477b1 XSS lesson completion fixes (#669)
* XSS lesson completion fixes

* removed log all

* lesson progress capable of deprecated assignments in the database

* fixed unit test for lesson progress
2019-09-29 14:46:18 +02:00
45c7949118 Merge pull request #668 from afcidk/fix-typo
thanks for the fix
2019-09-27 15:05:59 +02:00
9b906a2a29 Fix typo in XXE lesson 2019-09-25 00:37:36 +08:00
686d8b0c85 Merge pull request #667 from WebGoat/spring-boot-2
Spring boot 2
2019-09-24 17:09:09 +02:00
d080b3ef06 Review comment 2019-09-24 07:36:49 +02:00
dad9c75ee0 Fix tests after updating from develop, changes applied for migrating to Spring Boot 2 2019-09-23 17:35:04 +02:00
35c1305ce9 Merge conflicts resolved 2019-09-23 07:34:27 +02:00
261f947777 Fix 2019-09-20 17:45:33 +02:00
c8ef848657 Fix 2019-09-20 17:36:15 +02:00
f29b923eef FIx? 2019-09-20 17:10:58 +02:00
6fe5831f11 FIx? 2019-09-20 16:46:26 +02:00
cf00454f8b Testing issue 2019-09-20 08:30:07 +02:00
e8d086ac9b All successful 2019-09-20 07:59:04 +02:00
3ec4592fb2 Merge pull request #657 from WebGoat/xxe-int-test
XXE tests added
2019-09-19 18:09:02 +02:00
d7a2596670 Update lesson template 2019-09-19 07:54:30 +02:00
9c431eb2a3 Remove (was not generated btw) 2019-09-18 18:03:40 +02:00
1be9397c21 Add notifications from Travis 2019-09-18 18:02:14 +02:00
82ad0a7cc7 Finally working 2019-09-18 17:53:43 +02:00
4777dab57a review comments processed 2019-09-18 17:46:32 +02:00
a5cb5b0e8e removed log in checkresults 2019-09-18 16:16:44 +02:00
30d38f9b56 completed test 2019-09-18 16:10:52 +02:00
ec236a4ff5 First steps in XXE integration tests 2019-09-18 14:48:34 +02:00
57e6a84cef fixed and improved first two jwt challenges 2019-09-17 18:33:05 +02:00
2b01cbcb75 Fixed last tests 2019-09-16 07:43:22 +02:00
f774364461 Working unit tests 2019-09-13 20:05:25 +02:00
04f1b9a282 Update to the copyright 2019-09-13 19:27:25 +02:00
71dea87653 WebWolf test working again 2019-09-13 19:25:09 +02:00
dceb375d5e WIP 2019-09-13 18:57:40 +02:00
5e6f825e64 WIP 2019-09-13 16:42:13 +02:00
361249c666 First attempt at moving to Spring Boot 2 2019-09-12 17:22:03 +02:00
fb2e11fe11 fix for complete progress of sql mitigations and integration test 2019-09-10 13:58:58 +02:00
a56f41e0ea Merge branch 'pr/579' into develop 2019-09-10 13:55:43 +02:00
43c25dc3bb Modified PR to reflect coding style 2019-09-10 13:53:30 +02:00
6e9a52a05e Merge pull request #647 from WebGoat/separate_project
Nice work. I will add some tests for the missing parts in the SQL mitigations (in a separate pull request)
2019-09-09 14:05:21 +02:00
f7c8a271aa Fixed small typos 2019-09-09 13:55:24 +02:00
7a4f6e6fd3 Merge branch 'JeffreyWagnerBHN-develop' into develop 2019-09-09 13:54:38 +02:00
aec051a9f1 Fixed minor spelling mistake 2019-09-09 13:41:38 +02:00
bf52e7a992 Fixed checking of server already running 2019-09-09 11:37:26 +02:00
0982bd982c Review comments processed:
- Ports can now be changed
- User is now a default user making it easier to login and look around after a failure
2019-09-08 18:52:12 +02:00
75a174ff7b Fixed description and grammer 2019-09-06 21:12:55 -04:00
2283f945a9 Fix failing configuration 2019-08-25 17:53:36 +02:00
ff530e926e Use separate project for integration tests so we can start WebGoat and WebWolf 2019-08-25 17:43:14 +02:00
139651615e Make lesson csrf-7 stricter (do not allow invalid JSON, e.g. trailing =) 2019-08-22 17:44:52 +02:00
924a53c22a fixed sql adv 5 progress and added prove in integration test 2019-08-22 17:44:34 +02:00
c93563da3f Merge pull request #643 from TortugaAttack/multipleTracker45
Fixed #642 - multiple tracker for one user fixed
2019-08-22 15:07:59 +02:00
73553d91d3 Merge pull request #639 from jskiba99/patch-2
Update CrossSiteScripting_content9.adoc
2019-08-22 11:14:38 +02:00
f0d1555a09 Fixed #45 - multiple tracker for one user fixed 2019-08-21 23:38:27 +02:00
6d36e7db74 Added new endpoint for POST so it will give feedback to the UI. It now
ended up in a HTTP/405 which does not give any feedback to the UI
2019-08-17 13:52:59 +02:00
e01c2a35ce Add test case for security question assignment and the tracking is now
done with a session scoped bean
2019-08-06 19:04:07 +02:00
7d9f24c86b Update CrossSiteScripting_content9.adoc
Fix broken resource link
2019-08-06 05:26:05 -04:00
18eee4df58 Fix for issue with timestamp not being parsed when sending to WebWolf
timestamp was already fixed at LocalDateTime.now() however WebGoat still
send the timestamp along, removed it
2019-07-28 20:50:19 +02:00
e61c943f97 #601 bug: username is case sensitive, but email in general is not
Opted for completing remove support for uppercase letters in username
this way we never come across issued with casing in WebGoat
2019-07-28 20:48:20 +02:00
d2e23f6b8e reduce logging 2019-07-25 20:17:52 +02:00
ffbc808e26 Integration test support 2019-07-25 20:17:52 +02:00
ae674b9297 Merge pull request #620 from zubcevic/july2019-bugfixes
increased sql form fields and fixed chrome progress
2019-07-25 08:39:34 +02:00
33c73a7dca Adding new developer 2019-07-24 20:37:32 +02:00
216b29fca2 Clean up in pom files 2019-07-24 20:37:32 +02:00
ee0988effe Merge pull request #627 from WebGoat/gh-jwhite-patch-1
Delete do-not-merge.md
2019-07-23 14:19:26 -06:00
67440a6cc8 Delete do-not-merge.md
removing earlier test file
2019-07-23 14:18:51 -06:00
6c8921a951 Merge pull request #625 from WebGoat/another-ci-fail-test
Create do-not-merge.md
2019-07-23 11:41:35 -06:00
b395be9bd0 Create do-not-merge.md
testing a status check/branch protection thing
2019-07-23 10:38:25 -06:00
7ad3996f2f fix 6a6b page 2019-07-22 15:36:31 +02:00
b65644edee progress fix for SqlInjectionMitigations 2019-07-22 12:16:18 +02:00
ea38973068 UTF-8 config added for ThymeLeaf 2019-07-22 08:21:34 +02:00
7d0a63ac95 small html changes to improve progress 2019-07-20 09:34:27 +02:00
f9e78739f3 reverted mandatory file encoding which will make it worse on windows 2019-07-20 09:13:21 +02:00
656fa40182 style sheet and advanced sql 2019-07-19 16:49:30 +02:00
99435a1073 increased sql form fields and fixed chrome progress 2019-07-19 12:16:06 +02:00
9471e53818 Fix image names for google chrome dev tools lesson 2019-07-14 12:40:05 +02:00
d814522223 Fix test for HTTP proxy lesson 2019-07-14 12:39:07 +02:00
2eaf263e81 Improve task description for HTTP proxy lesson 2019-07-14 12:39:07 +02:00
41f252970b corrected path in pom 2019-07-14 12:38:11 +02:00
63a1097466 owasp categories 2019-07-14 12:38:11 +02:00
bc0d803123 add login&pwd in JDBC url for PostgreSQL
I really don't know why exactly spring parameters are not used here,
probably for schema creation step. Until changing what the application does on startup
this will make it 'just work' without extra changes.
2019-07-14 12:29:51 +02:00
12de48ebbb additional environment entries to support https on webgoat 2019-07-14 12:18:07 +02:00
62fbd6d340 Merge pull request #610 from johannesegger/patch-1
Fix typo in CIA lesson
2019-07-12 17:21:46 -06:00
e36b4c3910 Merge pull request #618 from matthias-g/csrf-3-post
Do not allow trivial solution to CSRF-3
2019-07-12 17:16:23 -06:00
97f66545e0 In CSRF-3 use POST instead of GET to prevent solving the assignment just by opening the URL in a new tab 2019-07-12 17:25:58 +02:00
27125acd22 Fix issue with maven wrapper using TLS 1.2 as it no longer is supported 2019-07-09 20:19:54 +02:00
1aa98be908 Fix issue with maven wrapper using TLS 1.2 as it no longer is supported 2019-07-09 20:18:54 +02:00
cb667094f2 update jar plugin version 2019-07-09 19:11:52 +02:00
703b6c676e Fix typo 2019-06-14 15:09:55 +02:00
00deb66ad9 Small update for password reset lesson 2019-05-09 09:17:11 +02:00
2a5e8dfdac Add missing step necessary to finish the release 2019-05-03 11:20:53 +02:00
98537426f2 SNAPSHOT version 2019-05-03 11:15:11 +02:00
529e8d73e1 Merge tag 'v8.0.0.M25' into develop
New release
2019-05-03 09:57:22 +02:00
d8d32c60cb Merge branch 'release/v8.0.0.M25' 2019-05-03 09:57:12 +02:00
9b0c4e62c2 New release, updating pom.xml 2019-05-03 09:50:01 +02:00
aa2eac0cd8 fixed test 2019-04-21 14:14:23 +02:00
8fdfbbd3fb changed order of attack forms in order to get the green completed 2019-04-21 14:12:26 +02:00
80b8326766 link corrected to avoid 404 2019-04-21 14:11:45 +02:00
a4da1a76e8 Add link to landing pages 2019-04-21 14:10:37 +02:00
e57c9d05b6 added checkbox and corrected fall back for the other labels 2019-04-21 14:10:01 +02:00
2b2e267594 hide password for testing with your actual password in front of colleagues 2019-04-21 14:10:01 +02:00
4bafc19883 fixed classcast exception on randValue 2019-04-21 13:59:26 +02:00
48d926491f removed possible NullpointerException and System.out 2019-04-21 13:59:26 +02:00
203b5fe717 chrome NetworkNum fix 2019-04-21 13:59:26 +02:00
0ac8b7c716 Merge branch 'develop' into add-user-validator-tests 2019-03-26 20:36:06 +00:00
331d9c8dd4 add authur tag to test class 2019-03-26 20:33:11 +00:00
c6c0cc60f9 Add UserValidator tests + minor code clean up 2019-03-26 20:23:28 +00:00
bb7fb3f197 add UserService unit test, modify UserService 2019-03-26 13:59:22 +01:00
93830ac15b adjusted to findByUser 2019-03-26 13:57:21 +01:00
5df6e987eb Fim simple email assignment typo 2019-03-26 13:56:31 +01:00
a242347ee0 add UserService unit test, modify UserService 2019-03-26 12:05:42 +00:00
89037c3dfb Fim simple email assignment typo 2019-03-26 10:01:07 +00:00
bcacf94c6f Added Test for Developer Tools 2019-03-26 08:43:38 +01:00
5a11a5dae9 Added test for CIA Quiz 2019-03-26 08:43:38 +01:00
b8e68d13b8 implement xss (mitigation) assignment 6 2019-03-26 08:43:38 +01:00
a8106f6671 Removed git merge symbols 2019-03-26 08:43:38 +01:00
2d5919dfc6 Changed snapshot versions of cia, dev-tools and secure passwords lessons. 2019-03-26 08:43:38 +01:00
b190b08258 Added Import of AssignmentsHints to SQL Injection Challenge to fix build error. 2019-03-26 08:43:38 +01:00
256c0d05aa Implemented some feedback 2019-03-26 08:43:38 +01:00
53c16c8b82 fixed minor spelling mistakes, unified wording 2019-03-26 08:43:38 +01:00
875f0487bd assignment 4: specifying data type in instructions 2019-03-26 08:43:38 +01:00
5c2d9cd8e9 assignment 5: display query string to user after success, improved regex to allow missing semicolon after query 2019-03-26 08:43:38 +01:00
e976dbe10f assignment 4: display query string to user after success 2019-03-26 08:43:38 +01:00
f586bded4d assignment 3: display query string to user after success 2019-03-26 08:43:38 +01:00
7c32232faa display query string to user after success, added hints 2019-03-26 08:43:38 +01:00
2be2de8ce1 Added improved quiz for cia-triad and xss 2019-03-26 08:43:38 +01:00
27a61f0f70 Reworked and styled quiz 2019-03-26 08:43:38 +01:00
0915bf3d7f Changed checkboxes to radio buttons, since it is single choice.
Moved css to seperate css file.
Made questions clickable not just the checkbox.
Reworked java code.
Work in Progress...
2019-03-26 08:43:38 +01:00
df49fcdb39 Added a little more info to assignments 11-13 of sql-introduction 2019-03-26 08:43:38 +01:00
e8caeedf53 implemented xss-quiz 2019-03-26 08:43:38 +01:00
d27577c1c4 Implemented better lesson description, hints and feedback 2019-03-26 08:43:38 +01:00
cec60447c4 Fixed error in SQL Inj quiz
fixed a type that didn't allow the quiz to load.
2019-03-26 08:43:38 +01:00
e859c9c37b Fixed errors in tests for sql injection introduction 10 2019-03-26 08:43:38 +01:00
3883563c7d Fixed feedback-check in sql introduction tests. 2019-03-26 08:43:38 +01:00
5c41e6080c Fixed Tests 2019-03-26 08:43:38 +01:00
7daaac9a3f Fixed Typos 2019-03-26 08:43:38 +01:00
84f67b5a7e changed order of xss mitigation lesson 2019-03-26 08:43:38 +01:00
64d3cdfc86 Added info to sql injections introduction to check out the CIA-Traid lesson if unfamiliar with it. 2019-03-26 08:43:38 +01:00
4878ea637e Fixed wrong Hint in SqlInjection Assignment 5a/b 2019-03-26 08:43:38 +01:00
0588daff9d Added Assignment for Security Questions. 2019-03-26 08:43:38 +01:00
37b5abea80 added unsecure password recommendations to secure passwords lesson to see why passwords are rated as weak 2019-03-26 08:43:38 +01:00
aa22bfb528 Fixed wrong hint 2019-03-26 08:43:38 +01:00
bbb0b607b2 Added Assignment for Security Questions. 2019-03-26 08:43:38 +01:00
8b61811278 Added doc to quiz js 2019-03-26 08:43:38 +01:00
3d7974aa45 Added more hints to password reset 5 lesson. Recommended Burp as a proxy 2019-03-26 08:43:38 +01:00
8c7eaf87d6 Fixed package of xss-mititgation assignment. Hints are working again. 2019-03-26 08:43:38 +01:00
587c44b52e Removed unused imports. 2019-03-26 08:43:38 +01:00
1d9abef80f Page after assignment working again. 2019-03-26 08:43:38 +01:00
74961c5632 ace_collect now uses API call 2019-03-26 08:43:38 +01:00
2f39f48747 deleted unnecessary lines 2019-03-26 08:43:38 +01:00
387a0e8e7d assignment now has working feedback 2019-03-26 08:43:38 +01:00
66821df6f0 polished feedback, implemented password warnings and suggestions 2019-03-26 08:43:38 +01:00
49e0f75fb5 secure password assignment first draft 2019-03-26 08:43:38 +01:00
30b2c8b4d6 Added Hints for second Assignment in Chrome DevTools 2019-03-26 08:43:38 +01:00
b7a90345b2 Added second assignment for chrome developer tools. 2019-03-26 08:43:38 +01:00
2a26cc3cc7 polished feedback, implemented password warnings and suggestions 2019-03-26 08:43:38 +01:00
0bd14d9178 (wrong branch) updated assignment (OWASP Java Encoder) and hints (still not shown) 2019-03-26 08:43:38 +01:00
06a8bd8b0e Strength bar 2019-03-26 08:43:38 +01:00
44a9a776bf added pw reset mitigation explanation 2019-03-26 08:43:38 +01:00
43504b9a7b Fixed Double Hints in SqlInjection Advanced Challenge 2019-03-26 08:43:38 +01:00
5fa11a1b4b secure password assignment first draft 2019-03-26 08:43:38 +01:00
8bc91ba4ec finished assignment 2019-03-26 08:43:38 +01:00
94b936036a Added explanations for creating and storing passwords. 2019-03-26 08:43:38 +01:00
72e13889d0 Started NIST explanation 2019-03-26 08:43:38 +01:00
91e6f70919 Added lesson (no content yet) for explaining nist password standards. 2019-03-26 08:43:38 +01:00
b02a01d35e squash 2019-03-26 08:43:38 +01:00
6d974b5fa8 Fixed lesson sorting issue 2019-03-26 08:43:38 +01:00
cfce7763f0 Outcommented lines in XSS Lessons 3 that were causing erros 2019-03-26 08:43:38 +01:00
63502d6328 added jsoup html parser 2019-03-26 08:43:38 +01:00
971062561d renamed hints 2019-03-26 08:43:38 +01:00
e7b69c4953 edited table of relevant special chars (\' not recommended because its not in the HTML spec) 2019-03-26 08:43:38 +01:00
8944bfcc1d implemented xss mitigation assignment 1, draft validation without parser 2019-03-26 08:43:38 +01:00
6327b82204 ace editor text as request parameter 2019-03-26 08:43:38 +01:00
f209c424b4 mitigation preparations 2019-03-26 08:43:38 +01:00
73c2313658 added assignment draft (not working yet) 2019-03-26 08:43:38 +01:00
760c3f2990 Added Hints for second Assignment in Chrome DevTools 2019-03-26 08:43:38 +01:00
98a32c7cdf Fixed bug, where assignment hints did not get displayed. 2019-03-26 08:43:38 +01:00
09baecb3e9 Added second assignment for chrome developer tools. 2019-03-26 08:43:38 +01:00
6cf3740c04 Fixes bug in introduction assignment 3 and adjusted wording in assignment
1
2019-03-26 08:43:38 +01:00
e873752eac Reworked description and added additional hints. Split regex for code checks for better readability. 2019-03-26 08:43:38 +01:00
4cdd649a5a Added html mode for code editor 2019-03-26 08:43:38 +01:00
ea04d6ef35 Removed ajax from assignment. Now using normal post-request.
Made successmessages green and failure messages red for all sql-i messages
2019-03-26 08:43:38 +01:00
72ae0d503b Made small text adjustments for developer-tools lesson. 2019-03-26 08:43:38 +01:00
f66ad51721 Added comment parsing and feedback to text editor lessons 2019-03-26 08:43:38 +01:00
b22deec5b8 Added quick fix description to code editor assignment 2019-03-26 08:43:38 +01:00
af565b5035 Added Tutorial for Chrome Developer Tools. 2019-03-26 08:43:38 +01:00
eb29ed00ff Removed old unused files from XSS 2019-03-26 08:43:38 +01:00
58dc5d2d41 Removed unneccessary comments from html documents. 2019-03-26 08:43:38 +01:00
600c6203ef Changed the lesson plans of all the XSS lessons. 2019-03-26 08:43:38 +01:00
fffbb3c804 Added missing messages. 2019-03-26 08:43:38 +01:00
dd8b067a55 Changed names of hints and messages fro SQL-Injection assignments for better readability in properties file. 2019-03-26 08:43:38 +01:00
596383fd59 bugfixes 2019-03-26 08:43:38 +01:00
90da672be2 added hints to sql injection assignment 4 & 5, minor text changes to be consistent to other assignments 2019-03-26 08:43:38 +01:00
0098f07d00 implemented sql injection assignment 5 2019-03-26 08:43:38 +01:00
6b669df025 implemented assignment 4, some other changes 2019-03-26 08:43:38 +01:00
7733ea0c85 Bug fixes due to changed fuction, Updated text 2019-03-26 08:43:38 +01:00
295b5a4772 implemented assignment 2 & 3 of sql injection lession 2019-03-26 08:43:38 +01:00
2ee3b22207 Reworked some XSS assignments 2019-03-26 08:43:38 +01:00
990bf079d3 Added hints for dom-based xss assignment (part 2) 2019-03-26 08:43:38 +01:00
362671e67e Added hints for dom-based xss assignment (part 1) 2019-03-26 08:43:38 +01:00
46f92dad3b Added hints for Reflected XSS assignment. 2019-03-26 08:43:38 +01:00
3a7601d348 Moved js files to global directory, added id system to question json 2019-03-26 08:43:38 +01:00
2962ddbb3e Restructured XSS category. Updated gitignore to ignore TestClass.class. 2019-03-26 08:43:38 +01:00
1cfd8dd843 Added feedback to cia quiz 2019-03-26 08:43:38 +01:00
61d8051b5f Added feedback for assignment 2019-03-26 08:43:38 +01:00
7db39765c6 Improved Tests 2019-03-26 08:43:38 +01:00
718b113f86 Added my improved assignments 2019-03-26 08:43:38 +01:00
551f87dbd9 Deleted more unessecary files 2019-03-26 08:43:38 +01:00
dbba0fc188 Deleted not needed files for syntax highlighter 2019-03-26 08:43:38 +01:00
8dd0957c39 Added syntax highlighting for mitigation assignment 2019-03-26 08:43:38 +01:00
50c88738c2 Added a quiz for cia-triad lessons 2019-03-26 08:43:38 +01:00
baff6b06f3 Moved questions JSON to seperate file 2019-03-26 08:43:38 +01:00
41998a0143 Deleted old assignments (introduction) and added tests for the new ones 2019-03-26 08:43:38 +01:00
46e71a8bcd Renamed hints 2019-03-26 08:43:38 +01:00
3b0c09add7 Highlighted important parts of text and expanded the CIA explanations. 2019-03-26 08:43:38 +01:00
002ce6e8a6 Polished and fixed assignment 10 (A) of sql injections 2019-03-26 08:43:38 +01:00
1bcddaf710 Reworked and polished assignment 8 and 9 (C and I) 2019-03-26 08:43:38 +01:00
cd3f7ea924 Inserted quiz into sql injection advanced 2019-03-26 08:43:38 +01:00
14f4b42ba5 Fixed some errors. 2019-03-26 08:43:38 +01:00
26e3803de0 Added more hints 2019-03-26 08:43:38 +01:00
6fe7582dfb Added an assignment for compromising availability to the sql injections (introduction).
WIP
2019-03-26 08:43:38 +01:00
4e6c721545 Added an assignment for compromising integrity by query chaining to the sql injections (introduction) 2019-03-26 08:43:38 +01:00
75b1895122 Added a new lessons for sql injections on "Compromising confidentiality with String SQL Injection" 2019-03-26 08:43:38 +01:00
083eb1b567 improved the description of the new sql injection mitigation assignments 2019-03-26 08:43:38 +01:00
d2a2716a9a Added a lesson for the CIA-Triad in the general category explaining the three elements of the triad. 2019-03-26 08:43:38 +01:00
0529289f6d Added (introduction) extra to the sidebar menu on the left.
Slightly modified SQL Injections explanation/example.
2019-03-26 08:43:38 +01:00
adc8891160 Reworked SQl-Injections Introdruction Lesson plan 2019-03-26 08:43:38 +01:00
2fdde982eb Restructured SQL Injection introduction lesson and created new required lesson-pages. 2019-03-26 08:43:38 +01:00
2334b3c02d lessons: sql_injection
added another assignment
2019-03-26 08:43:38 +01:00
8667a85865 Draft_Version for SQL Injection 2019-03-26 08:43:38 +01:00
78ff54b910 Modified and improved explanations for SQL Injections (basics) 2019-03-26 08:43:38 +01:00
bca50e8ca5 lesson: sql-injection-mitigation
added new assignment for jdbc code completion
2019-03-26 08:43:38 +01:00
6e36cc1ea4 removed unnecessary interceptors 2019-03-26 08:37:47 +01:00
4050e899ff changed unit test to dynamic port to prevent port conflict and build failure 2019-03-26 08:37:47 +01:00
1c2648e0a9 disable the fallback to the system locale to fix unit test and establish the desired behaviour 2019-03-26 08:37:47 +01:00
24bbb636f8 Update HttpBasics_ProxyIntro1.adoc
Fixed along to alone
2019-03-26 08:35:55 +01:00
7291651967 Update IntroductionWebWolf.adoc
Fixed typos and language to make it clearer
2019-03-26 08:35:55 +01:00
528c05a859 Update Landing_page.adoc
Updated the language to make it easier to understand
2019-03-26 08:35:55 +01:00
e625d4008b Update Receiving_mail.adoc
Clarify text to make it easier to understand
2019-03-26 08:35:55 +01:00
53050d7198 Make language more understandable
Changed wording, to make it more intuitive
2019-03-26 08:35:55 +01:00
5ebf838cd2 Merge branch 'alexanderfry-feature/ssrf' into develop 2019-02-09 20:51:27 +01:00
a49dd6c348 Updated version in pom.xml 2019-02-09 20:51:14 +01:00
c0dd773b90 Merge branch 'develop' into alexanderfry-feature/ssrf 2019-02-09 18:20:43 +01:00
bd86dc6ee0 SNAPSHOT version 2019-02-09 18:20:08 +01:00
d6dae9ef75 Merge branch 'feature/ssrf' of git://github.com/alexanderfry/WebGoat into alexanderfry-feature/ssrf 2019-02-09 16:42:08 +01:00
941ca5e9a1 SQL injection add hints #470 2019-02-09 16:41:46 +01:00
5bc48193b6 Merge branch 'master' into develop 2019-02-08 14:56:53 +01:00
e9b1a10a52 Update landing page 2019-02-08 14:56:35 +01:00
c58ff9d0cb Merge tag 'v8.0.0.M24' into develop
New version v8.0.0.M24
2019-02-08 14:21:57 +01:00
98f75e34d5 Initial Commit of SSRF Lesson 2019-01-21 18:09:31 -04:00
698 changed files with 99169 additions and 8645 deletions

1
.gitignore vendored
View File

@ -51,3 +51,4 @@ webgoat.lck
webgoat.log webgoat.log
webgoat.properties webgoat.properties
webgoat.script webgoat.script
TestClass.class

117
.mvn/wrapper/MavenWrapperDownloader.java vendored Normal file
View File

@ -0,0 +1,117 @@
/*
* Copyright 2007-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import java.util.Properties;
public class MavenWrapperDownloader {
private static final String WRAPPER_VERSION = "0.5.5";
/**
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
*/
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
/**
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
* use instead of the default one.
*/
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
".mvn/wrapper/maven-wrapper.properties";
/**
* Path where the maven-wrapper.jar will be saved to.
*/
private static final String MAVEN_WRAPPER_JAR_PATH =
".mvn/wrapper/maven-wrapper.jar";
/**
* Name of the property which should be used to override the default download url for the wrapper.
*/
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
public static void main(String args[]) {
System.out.println("- Downloader started");
File baseDirectory = new File(args[0]);
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
// If the maven-wrapper.properties exists, read it and check if it contains a custom
// wrapperUrl parameter.
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
String url = DEFAULT_DOWNLOAD_URL;
if(mavenWrapperPropertyFile.exists()) {
FileInputStream mavenWrapperPropertyFileInputStream = null;
try {
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
Properties mavenWrapperProperties = new Properties();
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
} catch (IOException e) {
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
} finally {
try {
if(mavenWrapperPropertyFileInputStream != null) {
mavenWrapperPropertyFileInputStream.close();
}
} catch (IOException e) {
// Ignore ...
}
}
}
System.out.println("- Downloading from: " + url);
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
if(!outputFile.getParentFile().exists()) {
if(!outputFile.getParentFile().mkdirs()) {
System.out.println(
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
}
}
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
try {
downloadFileFromURL(url, outputFile);
System.out.println("Done");
System.exit(0);
} catch (Throwable e) {
System.out.println("- Error downloading");
e.printStackTrace();
System.exit(1);
}
}
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
String username = System.getenv("MVNW_USERNAME");
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
}
URL website = new URL(urlString);
ReadableByteChannel rbc;
rbc = Channels.newChannel(website.openStream());
FileOutputStream fos = new FileOutputStream(destination);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
rbc.close();
}
}

View File

@ -1 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.2.1/apache-maven-3.2.1-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar

View File

@ -15,6 +15,10 @@ git flow release start <version>
mvn versions:set <<version> mvn versions:set <<version>
git commit -am "New release, updating pom.xml" git commit -am "New release, updating pom.xml"
git flow release publish git flow release publish
<<Make changes if necessary>>
git flow release finish <version>
git push origin develop git push origin develop
git push origin master git push origin master
git push --tags git push --tags

19
LICENSE.txt Normal file
View File

@ -0,0 +1,19 @@
This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
Copyright (c) 2002 - 2019 Bruce Mayhew
This program is free software; you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
Getting Source ==============
Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.

View File

@ -27,7 +27,7 @@ you are caught engaging in unauthorized hacking, most companies will fire you.
Claiming that you were doing security research will not work as that is the Claiming that you were doing security research will not work as that is the
first thing that all hackers claim.* first thing that all hackers claim.*
# Run Instructions: # Installation Instructions:
## 1. Standalone ## 1. Standalone
@ -97,27 +97,10 @@ To change IP address add the following variable to WebGoat/webgoat-container/src
server.address=x.x.x.x server.address=x.x.x.x
``` ```
# Vagrant
We supply a complete environment using Vagrant, to run WebGoat with Vagrant you must first have Vagrant and Virtualbox installed.
```shell
$ cd WebGoat/webgoat-images/vagrant-training
$ vagrant up
```
Once the provisioning is complete login to the Virtualbox with username vagrant and password vagrant.
WebGoat and WebWolf will automatically start when you login to this image.
# Building a new Docker image # Building a new Docker image
NOTE: Travis will create a new Docker image automatically when making a new release. NOTE: Travis will create a new Docker image automatically when making a new release.
WebGoat now has Docker support for x86 and ARM (raspberry pi).
### Docker on x86
On x86 you can build a container with the following commands:
```Shell ```Shell
cd WebGoat/ cd WebGoat/
mvn install mvn install
@ -128,27 +111,6 @@ docker login
docker push webgoat/webgoat-8.0 docker push webgoat/webgoat-8.0
``` ```
### Docker on ARM (Raspberry Pi) # Run Instructions:
On a Raspberry Pi (it has yet been tested with a Raspberry Pi 3 and the hypriot Docker image) you need to build JFFI for
ARM first. This is needed by the docker-maven-plugin ([see here](https://github.com/spotify/docker-maven-plugin/issues/233)):
```Shell Once installed connect to http://localhost:8080/WebGoat and http://localhost:9090/WebWolf
sudo apt-get install build-essential
git clone https://github.com/jnr/jffi.git
cd jffi
ant jar
cd build/jni
sudo cp libjffi-1.2.so /usr/lib
```
When you have done this you can build the Docker container using the following commands:
```Shell
cd WebGoat/
mvn install
cd webgoat-server
mvn docker:build -Drpi=true
docker tag webgoat/webgoat-8.0 webgoat/webgoat-8.0:8.0
docker login
docker push webgoat/webgoat-8.0
```

259
config/checkstyle/checkstyle.xml Executable file
View File

@ -0,0 +1,259 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"http://checkstyle.sourceforge.net/dtds/configuration_1_3.dtd">
<!--
Checkstyle configuration that checks the Google coding conventions from Google Java Style
that can be found at https://google.github.io/styleguide/javaguide.html.
Checkstyle is very configurable. Be sure to read the documentation at
http://checkstyle.sf.net (or in your downloaded distribution).
To completely disable a check, just comment it out or delete it from the file.
Authors: Max Vetrenko, Ruslan Diachenko, Roman Ivanov.
-->
<module name="Checker">
<property name="charset" value="UTF-8"/>
<property name="severity" value="error"/>
<property name="fileExtensions" value="java, properties, xml"/>
<!-- Checks for whitespace -->
<!-- See http://checkstyle.sf.net/config_whitespace.html -->
<module name="SuppressionFilter">
<property name="file" value="${suppressionsLocation}" default="target/checkstyle-suppressions.xml"/>
</module>
<module name="TreeWalker">
<module name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="maximum" value="0"/>
<property name="format" value="org\.junit\.Assert\.assert"/>
<property name="message"
value="Please use AssertJ imports."/>
<property name="ignoreComments" value="true"/>
</module>
<module
name="com.puppycrawl.tools.checkstyle.checks.imports.IllegalImportCheck">
<property name="regexp" value="true"/>
<property name="illegalPkgs"
value="^sun.*, ^org\.apache\.commons\.(?!compress|dbcp2|lang|lang3|logging|io|pool2).*, ^org\.flywaydb\.core\.internal.*, ^org\.testcontainers\.shaded.*"/>
<property name="illegalClasses"
value="^com\.hazelcast\.util\.Base64, ^org\.junit\.rules\.ExpectedException, ^org\.slf4j\.LoggerFactory, ^reactor\.core\.support\.Assert, ^com\.google\.common\.collect\.Maps, ^com\.google\.common\.collect\.Sets, ^com\.google\.common\.collect\.Lists"/>
</module>
<module
name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="maximum" value="0"/>
<property name="format"
value="assertThatExceptionOfType\((NullPointerException|IllegalArgumentException|IOException|IllegalStateException)\.class\)"/>
<property name="message"
value="Please use specialized AssertJ assertThat*Exception method."/>
<property name="ignoreComments" value="true"/>
</module>
<module
name="com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck">
<property name="maximum" value="0"/>
<property name="format"
value="@SneakyThrows"/>
<property name="message"
value="Please use a unchecked exceptions instead of @SneakyThrows gives compiler warnings"/>
<property name="ignoreComments" value="true"/>
</module>
<module name="OuterTypeFilename"/>
<module name="IllegalTokenText">
<property name="tokens" value="STRING_LITERAL, CHAR_LITERAL"/>
<property name="format"
value="\\u00(09|0(a|A)|0(c|C)|0(d|D)|22|27|5(C|c))|\\(0(10|11|12|14|15|42|47)|134)"/>
<property name="message"
value="Consider using special escape sequence instead of octal value or Unicode escaped value."/>
</module>
<module name="AvoidEscapedUnicodeCharacters">
<property name="allowEscapesForControlCharacters" value="true"/>
<property name="allowByTailComment" value="true"/>
<property name="allowNonPrintableEscapes" value="true"/>
</module>
<module name="OneTopLevelClass">
<property name="severity" value="warning"/>
</module>
<module name="NoLineWrap"/>
<module name="EmptyBlock">
<property name="option" value="TEXT"/>
<property name="tokens" value="LITERAL_TRY, LITERAL_FINALLY, LITERAL_IF, LITERAL_ELSE, LITERAL_SWITCH"/>
</module>
<module name="WhitespaceAround">
<property name="allowEmptyConstructors" value="true"/>
<property name="allowEmptyMethods" value="true"/>
<property name="allowEmptyTypes" value="true"/>
<property name="allowEmptyLoops" value="true"/>
<message key="ws.notFollowed"
value="WhitespaceAround: ''{0}'' is not followed by whitespace. Empty blocks may only be represented as '{}' when not part of a multi-block statement (4.1.3)"/>
<message key="ws.notPreceded"
value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/>
</module>
<module name="OneStatementPerLine"/>
<module name="MultipleVariableDeclarations"/>
<module name="ArrayTypeStyle"/>
<module name="MissingSwitchDefault"/>
<module name="FallThrough"/>
<module name="UpperEll"/>
<module name="ModifierOrder"/>
<module name="EmptyLineSeparator">
<property name="allowNoEmptyLineBetweenFields" value="true"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapDot"/>
<property name="tokens" value="DOT"/>
<property name="option" value="nl"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapComma"/>
<property name="tokens" value="COMMA"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ELLIPSIS is EOL until https://github.com/google/styleguide/issues/258 -->
<property name="id" value="SeparatorWrapEllipsis"/>
<property name="tokens" value="ELLIPSIS"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<!-- ARRAY_DECLARATOR is EOL until https://github.com/google/styleguide/issues/259 -->
<property name="id" value="SeparatorWrapArrayDeclarator"/>
<property name="tokens" value="ARRAY_DECLARATOR"/>
<property name="option" value="EOL"/>
</module>
<module name="SeparatorWrap">
<property name="id" value="SeparatorWrapMethodRef"/>
<property name="tokens" value="METHOD_REF"/>
<property name="option" value="nl"/>
</module>
<module name="PackageName">
<property name="format" value="^[a-z]+(\.[a-z_][a-z0-9_]*)*$"/>
<message key="name.invalidPattern"
value="Package name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="TypeName">
<message key="name.invalidPattern"
value="Type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MemberName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9]*$"/>
<message key="name.invalidPattern"
value="Member name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9_]*)?$"/>
<message key="name.invalidPattern"
value="Parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="CatchParameterName">
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Catch parameter name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="LocalVariableName">
<property name="tokens" value="VARIABLE_DEF"/>
<property name="format" value="^[a-z]([a-z0-9][a-zA-Z0-9]*)?$"/>
<message key="name.invalidPattern"
value="Local variable name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="ClassTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Class type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="MethodTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Method type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="InterfaceTypeParameterName">
<property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)"/>
<message key="name.invalidPattern"
value="Interface type name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="NoFinalizer"/>
<module name="GenericWhitespace">
<message key="ws.followed"
value="GenericWhitespace ''{0}'' is followed by whitespace."/>
<message key="ws.preceded"
value="GenericWhitespace ''{0}'' is preceded with whitespace."/>
<message key="ws.illegalFollow"
value="GenericWhitespace ''{0}'' should followed by whitespace."/>
<message key="ws.notPreceded"
value="GenericWhitespace ''{0}'' is not preceded with whitespace."/>
</module>
<module name="AbbreviationAsWordInName">
<property name="ignoreFinal" value="false"/>
<property name="allowedAbbreviationLength" value="4"/>
<property name="severity" value="warning"/>
</module>
<module name="OverloadMethodsDeclarationOrder"/>
<module name="VariableDeclarationUsageDistance"/>
<module name="CustomImportOrder">
<property name="sortImportsInGroupAlphabetically" value="false"/>
<property name="separateLineBetweenGroups" value="true"/>
<property name="customImportOrderRules" value="THIRD_PARTY_PACKAGE###STATIC"/>
</module>
<module name="MethodParamPad"/>
<module name="NoWhitespaceBefore">
<property name="tokens" value="COMMA, SEMI, POST_INC, POST_DEC, DOT, ELLIPSIS, METHOD_REF"/>
<property name="allowLineBreaks" value="true"/>
</module>
<module name="ParenPad"/>
<module name="OperatorWrap">
<property name="option" value="NL"/>
<property name="tokens"
value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, PLUS, QUESTION, SL, SR, STAR, METHOD_REF "/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationMostCases"/>
<property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF"/>
</module>
<module name="AnnotationLocation">
<property name="id" value="AnnotationLocationVariables"/>
<property name="tokens" value="VARIABLE_DEF"/>
<property name="allowSamelineMultipleAnnotations" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation"/>
<module name="SummaryJavadoc">
<property name="forbiddenSummaryFragments"
value="^@return the *|^This method returns |^A [{]@code [a-zA-Z0-9]+[}]( is a )"/>
<property name="severity" value="warning"/>
</module>
<module name="JavadocParagraph">
<property name="severity" value="warning"/>
</module>
<module name="AtclauseOrder">
<property name="tagOrder" value="@param, @return, @throws, @deprecated"/>
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
<property name="severity" value="warning"/>
</module>
<module name="JavadocMethod">
<property name="tokens" value="CLASS_DEF,INTERFACE_DEF,ENUM_DEF,METHOD_DEF,ANNOTATION_FIELD_DEF"/>
<property name="scope" value="public"/>
<property name="allowMissingParamTags" value="true"/>
<property name="allowMissingThrowsTags" value="true"/>
<property name="allowMissingReturnTag" value="true"/>
<property name="minLineCount" value="2"/>
<property name="allowedAnnotations" value="Override, Test"/>
<property name="allowThrowsTagsForSubclasses" value="true"/>
<property name="severity" value="warning"/>
</module>
<module name="MethodName">
<property name="format" value="^[a-z][a-z0-9][a-zA-Z0-9_]*$"/>
<message key="name.invalidPattern"
value="Method name ''{0}'' must match pattern ''{1}''."/>
</module>
<module name="SingleLineJavadoc">
<property name="ignoreInlineTags" value="false"/>
</module>
<module name="EmptyCatchBlock">
<property name="exceptionVariableName" value="expected"/>
</module>
<module name="CommentsIndentation"/>
</module>
</module>

View File

@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
<suppressions>
<suppress files="MD5.java" checks="[a-zA-Z0-9]*" />
<suppress files="VulnerableComponentsLesson.java" checks="[a-zA-Z0-9]*" />
<suppress files="ContentTypeAssignment.java" checks="IllegalImportCheck" />
<suppress files="SimpleXXE.java" checks="IllegalImportCheck" />
<suppress files="HtmlTamperingTask.java" checks="ParameterName" />
</suppressions>

View File

@ -7,7 +7,7 @@ services:
environment: environment:
- WEBWOLF_HOST=webwolf - WEBWOLF_HOST=webwolf
- WEBWOLF_PORT=9090 - WEBWOLF_PORT=9090
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat - spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat
- spring.datasource.username=webgoat - spring.datasource.username=webgoat
- spring.datasource.password=webgoat - spring.datasource.password=webgoat
- spring.datasource.driver-class-name=org.postgresql.Driver - spring.datasource.driver-class-name=org.postgresql.Driver
@ -19,7 +19,7 @@ services:
webwolf: webwolf:
image: webgoat/webwolf image: webgoat/webwolf
environment: environment:
- spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat - spring.datasource.url=jdbc:postgresql://webgoat_db:5432/webgoat?user=webgoat&password=webgoat
- spring.datasource.username=webgoat - spring.datasource.username=webgoat
- spring.datasource.password=webgoat - spring.datasource.password=webgoat
- spring.datasource.driver-class-name=org.postgresql.Driver - spring.datasource.driver-class-name=org.postgresql.Driver

View File

@ -192,7 +192,7 @@
<div class="copyright py-4 text-center text-white"> <div class="copyright py-4 text-center text-white">
<div class="container"> <div class="container">
<small>Copyright &copy; Team WebGoat 2019</small> <small>Team WebGoat 2019</small>
</div> </div>
</div> </div>

30
mvnw vendored
View File

@ -114,7 +114,6 @@ if $mingw ; then
M2_HOME="`(cd "$M2_HOME"; pwd)`" M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] && [ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
# TODO classpath?
fi fi
if [ -z "$JAVA_HOME" ]; then if [ -z "$JAVA_HOME" ]; then
@ -212,7 +211,11 @@ else
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi fi
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
fi
while IFS="=" read key value; do while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;; case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac esac
@ -221,22 +224,38 @@ else
echo "Downloading from: $jarUrl" echo "Downloading from: $jarUrl"
fi fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget" echo "Found wget ... using wget"
fi fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" wget "$jarUrl" -O "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl" echo "Found curl ... using curl"
fi fi
curl -o "$wrapperJarPath" "$jarUrl" if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else else
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download" echo "Falling back to using Java to download"
fi fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then if [ "$MVNW_VERBOSE" = true ]; then
@ -277,6 +296,11 @@ if $cygwin; then
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \ exec "$JAVACMD" \

29
mvnw.cmd vendored
View File

@ -37,7 +37,7 @@
@echo off @echo off
@REM set title of command window @REM set title of command window
title %0 title %0
@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' @REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME @REM set %HOME% to equivalent of $HOME
@ -120,23 +120,44 @@ SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar" set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
) )
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data. @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% ( if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR% echo Found %WRAPPER_JAR%
)
) else ( ) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ... echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL% echo Downloading from: %DOWNLOAD_URL%
powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')" )
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR% echo Finished downloading %WRAPPER_JAR%
) )
)
@REM End of extension @REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error if ERRORLEVEL 1 goto error
goto end goto end

130
pom.xml
View File

@ -6,7 +6,7 @@
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId> <artifactId>webgoat-parent</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>v8.0.0.M24</version> <version>v8.0.0.M26</version>
<name>WebGoat Parent Pom</name> <name>WebGoat Parent Pom</name>
<description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description> <description>Parent Pom for the WebGoat Project. A deliberately insecure Web Application</description>
@ -21,7 +21,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.18.RELEASE</version> <version>2.2.0.RELEASE</version>
</parent> </parent>
<licenses> <licenses>
@ -51,6 +51,11 @@
<name>Jason White</name> <name>Jason White</name>
<email>jason.white@owasp.org</email> <email>jason.white@owasp.org</email>
</developer> </developer>
<developer>
<id>zubcevic</id>
<name>René Zubcevic</name>
<email>rene.zubcevic@owasp.org</email>
</developer>
<developer> <developer>
<id>jwayman</id> <id>jwayman</id>
<name>Jeff Wayman</name> <name>Jeff Wayman</name>
@ -110,53 +115,27 @@
<!-- Use UTF-8 Encoding --> <!-- Use UTF-8 Encoding -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<!-- This build number will be ubdated by Travis-CI --> <!-- This build number will be ubdated by Travis-CI -->
<build.number>build</build.number> <build.number>build</build.number>
<!-- Shared properties with plugins and version numbers across submodules--> <!-- Shared properties with plugins and version numbers across submodules-->
<activation.version>1.1.1</activation.version> <activation.version>1.1.1</activation.version>
<axis-ant.version>1.4</axis-ant.version>
<axis-jaxrpc.version>1.4</axis-jaxrpc.version>
<axis-saaj.version>1.4</axis-saaj.version>
<axis.version>1.4</axis.version>
<build-helper-maven-plugin.version>1.9.1</build-helper-maven-plugin.version>
<cobertura-maven-plugin.version>2.7</cobertura-maven-plugin.version>
<commons-collections.version>3.2.1</commons-collections.version> <commons-collections.version>3.2.1</commons-collections.version>
<commons-digester.version>2.1</commons-digester.version>
<commons-discovery.version>0.5</commons-discovery.version>
<commons-fileupload.version>1.3.1</commons-fileupload.version>
<commons-io.version>2.6</commons-io.version>
<commons-lang3.version>3.4</commons-lang3.version> <commons-lang3.version>3.4</commons-lang3.version>
<coveralls-maven-plugin.version>4.0.0</coveralls-maven-plugin.version> <commons-io.version>2.6</commons-io.version>
<gatling.version>2.2.5</gatling.version>
<gatling-plugin.version>2.2.4</gatling-plugin.version>
<guava.version>18.0</guava.version> <guava.version>18.0</guava.version>
<h2.version>1.4.190</h2.version>
<hsqldb.version>2.3.4</hsqldb.version> <hsqldb.version>2.3.4</hsqldb.version>
<j2h.version>1.3.1</j2h.version>
<jackson-core.version>2.6.3</jackson-core.version>
<jackson-databind.version>2.6.3</jackson-databind.version>
<javaee-api.version>6.0</javaee-api.version>
<javax.transaction-api.version>1.3</javax.transaction-api.version>
<jcl-over-slf4j.version>1.7.12</jcl-over-slf4j.version>
<jtds.version>1.3.1</jtds.version>
<junit.version>4.12</junit.version> <junit.version>4.12</junit.version>
<lombok.version>1.18.4</lombok.version> <lombok.version>1.18.4</lombok.version>
<mail-api.version>1.5.4</mail-api.version>
<maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
<maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version> <maven-failsafe-plugin.version>2.22.0</maven-failsafe-plugin.version>
<maven-gpg-plugin.version>1.6</maven-gpg-plugin.version> <maven-jar-plugin.version>3.1.2</maven-jar-plugin.version>
<maven-jar-plugin.version>2.6</maven-jar-plugin.version> <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version>
<maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version> <maven-source-plugin.version>3.1.0</maven-source-plugin.version>
<maven-release-plugin.version>2.5.2</maven-release-plugin.version> <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
<maven-source-plugin.version>3.0.1</maven-source-plugin.version>
<maven-surefire-plugin.version>2.22.0</maven-surefire-plugin.version>
<nexus-staging-maven-plugin.version>1.6.6</nexus-staging-maven-plugin.version>
<scala.version>2.11.7</scala.version>
<sauce_junit.version>2.1.20</sauce_junit.version>
<selenium-java.version>2.48.2</selenium-java.version>
<spring.security.version>3.2.4.RELEASE</spring.security.version>
</properties> </properties>
<modules> <modules>
@ -164,34 +143,9 @@
<module>webgoat-lessons</module> <module>webgoat-lessons</module>
<module>webgoat-server</module> <module>webgoat-server</module>
<module>webwolf</module> <module>webwolf</module>
<module>webgoat-integration-tests</module>
</modules> </modules>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>http://repository.apache.org/snapshots/</url>
<!-- The releases element here is due to an issue in Maven 2.0 that will be
fixed in future releases. This should be able to be disabled altogether. -->
<releases>
<updatePolicy>daily</updatePolicy>
</releases>
<snapshots>
<updatePolicy>daily</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
@ -226,37 +180,37 @@
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>${maven-release-plugin.version}</version> <version>3.1.0</version>
<configuration> <configuration>
<autoVersionSubmodules>true</autoVersionSubmodules> <encoding>UTF-8</encoding>
<useReleaseProfile>false</useReleaseProfile> <consoleOutput>true</consoleOutput>
<releaseProfiles>release</releaseProfiles> <failsOnError>true</failsOnError>
<tagNameFormat>@{project.version}</tagNameFormat> <configLocation>config/checkstyle/checkstyle.xml</configLocation>
<goals>deploy</goals> <suppressionsLocation>config/checkstyle/suppressions.xml</suppressionsLocation>
</configuration> <suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
</plugin>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>${coveralls-maven-plugin.version}</version>
<configuration>
<repoToken/>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>${cobertura-maven-plugin.version}</version>
<configuration>
<check/>
<format>xml</format>
<maxmem>256m</maxmem>
<!-- aggregated reports for multi-module projects -->
<aggregate>true</aggregate>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project> </project>

View File

@ -10,32 +10,9 @@
<parent> <parent>
<groupId>org.owasp.webgoat</groupId> <groupId>org.owasp.webgoat</groupId>
<artifactId>webgoat-parent</artifactId> <artifactId>webgoat-parent</artifactId>
<version>v8.0.0.M24</version> <version>v8.0.0.M26</version>
</parent> </parent>
<profiles>
<profile>
<id>performance</id>
<build>
<plugins>
<plugin>
<groupId>io.gatling</groupId>
<artifactId>gatling-maven-plugin</artifactId>
<version>${gatling-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>execute</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build> <build>
<resources> <resources>
<resource> <resource>
@ -69,7 +46,11 @@
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version> <version>${maven-surefire-plugin.version}</version>
<configuration> <configuration>
<forkMode>never</forkMode> <forkCount>0</forkCount>
<reuseForks>true</reuseForks>
<argLine>
--illegal-access=permit
</argLine>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
@ -89,44 +70,52 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.datatype</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>jackson-datatype-jsr310</artifactId> <artifactId>spring-boot-starter-undertow</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.asciidoctor</groupId> <groupId>org.asciidoctor</groupId>
<artifactId>asciidoctorj</artifactId> <artifactId>asciidoctorj</artifactId>
<version>1.5.4</version> <version>1.5.8.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<artifactId>HikariCP</artifactId>
<groupId>com.zaxxer</groupId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version> <version>${commons-lang3.version}</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>io.gatling.highcharts</groupId>
<artifactId>gatling-charts-highcharts</artifactId>
<version>${gatling.version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
@ -137,31 +126,13 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.thymeleaf.extras</groupId> <groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId> <artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.hsqldb</groupId> <groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId> <artifactId>hsqldb</artifactId>
<version>${hsqldb.version}</version> <version>${hsqldb.version}</version>
</dependency> </dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>${javax.transaction-api.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>${scala.version}</version>
<scope>test</scope>
</dependency>
<!-- ************* END spring MVC and related dependencies ************** --> <!-- ************* END spring MVC and related dependencies ************** -->
<!-- ************* START: Dependencies for Unit and Integration Testing ************** --> <!-- ************* START: Dependencies for Unit and Integration Testing ************** -->

View File

@ -28,25 +28,27 @@
* @version $Id: $Id * @version $Id: $Id
* @since December 12, 2015 * @since December 12, 2015
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.asciidoctor.Asciidoctor; import org.asciidoctor.Asciidoctor;
import org.asciidoctor.extension.JavaExtensionRegistry; import org.asciidoctor.extension.JavaExtensionRegistry;
import org.owasp.webgoat.asciidoc.WebGoatVersionMacro; import org.owasp.webgoat.asciidoc.*;
import org.owasp.webgoat.asciidoc.WebWolfMacro;
import org.owasp.webgoat.asciidoc.WebWolfRootMacro;
import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Language;
import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.*; import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
import static org.apache.commons.lang3.CharEncoding.UTF_8;
import static org.asciidoctor.Asciidoctor.Factory.create; import static org.asciidoctor.Asciidoctor.Factory.create;
/** /**
@ -57,7 +59,7 @@ import static org.asciidoctor.Asciidoctor.Factory.create;
* </code> * </code>
*/ */
@Slf4j @Slf4j
public class AsciiDoctorTemplateResolver extends TemplateResolver { public class AsciiDoctorTemplateResolver extends FileTemplateResolver {
private static final Asciidoctor asciidoctor = create(); private static final Asciidoctor asciidoctor = create();
private static final String PREFIX = "doc:"; private static final String PREFIX = "doc:";
@ -65,38 +67,31 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
public AsciiDoctorTemplateResolver(Language language) { public AsciiDoctorTemplateResolver(Language language) {
this.language = language; this.language = language;
setResolvablePatterns(Set.of(PREFIX + "*"));
setResourceResolver(new AdocResourceResolver());
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
} }
@Override @Override
protected String computeResourceName(TemplateProcessingParameters params) { protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
String templateName = params.getTemplateName(); var templateName = resourceName.substring(PREFIX.length());
return templateName.substring(PREFIX.length()); try (InputStream is = readInputStreamOrFallbackToEnglish(templateName, language)) {
}
private class AdocResourceResolver implements IResourceResolver {
@Override
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
try (InputStream is = readInputStreamOrFallbackToEnglish(resourceName, language)) {
if (is == null) { if (is == null) {
log.warn("Resource name: {} not found, did you add the adoc file?", resourceName); log.warn("Resource name: {} not found, did you add the adoc file?", templateName);
return new ByteArrayInputStream(new byte[0]); return new StringTemplateResource("");
} else { } else {
StringWriter writer = new StringWriter();
JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry(); JavaExtensionRegistry extensionRegistry = asciidoctor.javaExtensionRegistry();
extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class); extensionRegistry.inlineMacro("webWolfLink", WebWolfMacro.class);
extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class); extensionRegistry.inlineMacro("webWolfRootLink", WebWolfRootMacro.class);
extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class); extensionRegistry.inlineMacro("webGoatVersion", WebGoatVersionMacro.class);
extensionRegistry.inlineMacro("webGoatTempDir", WebGoatTmpDirMacro.class);
extensionRegistry.inlineMacro("operatingSystem", OperatingSystemMacro.class);
StringWriter writer = new StringWriter();
asciidoctor.convert(new InputStreamReader(is), writer, createAttributes()); asciidoctor.convert(new InputStreamReader(is), writer, createAttributes());
return new ByteArrayInputStream(writer.getBuffer().toString().getBytes(UTF_8)); return new StringTemplateResource(writer.getBuffer().toString());
} }
} catch (IOException e) { } catch (IOException e) {
//no html yet //no html yet
return new ByteArrayInputStream(new byte[0]); return new StringTemplateResource("");
} }
} }
@ -117,20 +112,13 @@ public class AsciiDoctorTemplateResolver extends TemplateResolver {
} }
private Map<String, Object> createAttributes() { private Map<String, Object> createAttributes() {
Map<String, Object> attributes = Maps.newHashMap(); Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "coderay"); attributes.put("source-highlighter", "coderay");
attributes.put("backend", "xhtml"); attributes.put("backend", "xhtml");
Map<String, Object> options = Maps.newHashMap(); Map<String, Object> options = new HashMap<>();
options.put("attributes", attributes); options.put("attributes", attributes);
return options; return options;
} }
@Override
public String getName() {
return "adocResourceResolver";
}
}
} }

View File

@ -0,0 +1,50 @@
package org.owasp.webgoat;
import org.flywaydb.core.Flyway;
import org.owasp.webgoat.service.RestartLessonService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.sql.DataSource;
import java.util.Map;
/**
* Define 2 Flyway instances, 1 for WebGoat itself which it uses for internal storage like users and 1 for lesson
* specific tables we use. This way we clean the data in the lesson database quite easily see {@link RestartLessonService#restartLesson()}
* for how we clean the lesson related tables.
*/
@Configuration
public class DatabaseInitialization {
private final DataSource dataSource;
private String driverClassName;
public DatabaseInitialization(DataSource dataSource,
@Value("${spring.datasource.driver-class-name}") String driverClassName) {
this.dataSource = dataSource;
this.driverClassName = driverClassName;
}
@Bean(initMethod = "migrate")
public Flyway flyWayContainer() {
return Flyway
.configure()
.configuration(Map.of("driver", driverClassName))
.dataSource(dataSource)
.schemas("container")
.locations("db/container")
.load();
}
@Bean(initMethod = "migrate")
@DependsOn("flyWayContainer")
public Flyway flywayLessons() {
return Flyway
.configure()
.configuration(Map.of("driver", driverClassName))
.dataSource(dataSource)
.load();
}
}

View File

@ -1,48 +1,47 @@
/** /**
* ************************************************************************************************ * ************************************************************************************************
* * <p>
* * <p>
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/ * please see http://www.owasp.org/
* * <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* * <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the * This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* * <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* * <p>
* You should have received a copy of the GNU General Public License along with this program; if * You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 02111-1307, USA.
* * <p>
* Getting Source ============== * Getting Source ==============
* * <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects. * projects.
* *
* @author WebGoat * @author WebGoat
* @since October 28, 2003
* @version $Id: $Id * @version $Id: $Id
* @since October 28, 2003
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.ByteStreams;
import lombok.SneakyThrows;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.TemplateProcessingParameters; import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.resourceresolver.IResourceResolver; import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.templateresource.ITemplateResource;
import org.thymeleaf.templateresource.StringTemplateResource;
import java.io.ByteArrayInputStream; import java.io.IOException;
import java.io.File; import java.nio.charset.StandardCharsets;
import java.io.InputStream; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* Dynamically resolve a lesson. In the html file this can be invoked as: * Dynamically resolve a lesson. In the html file this can be invoked as:
@ -53,42 +52,29 @@ import java.util.Map;
* *
* Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory * Thymeleaf will invoke this resolver based on the prefix and this implementation will resolve the html in the plugins directory
*/ */
public class LessonTemplateResolver extends TemplateResolver { public class LessonTemplateResolver extends FileTemplateResolver {
private final static String PREFIX = "lesson:"; private static final String PREFIX = "lesson:";
private final File pluginTargetDirectory;
private ResourceLoader resourceLoader; private ResourceLoader resourceLoader;
private Map<String, byte[]> resources = Maps.newHashMap(); private Map<String, byte[]> resources = new HashMap<>();
public LessonTemplateResolver(File pluginTargetDirectory, ResourceLoader resourceLoader) { public LessonTemplateResolver(ResourceLoader resourceLoader) {
this.pluginTargetDirectory = pluginTargetDirectory;
this.resourceLoader = resourceLoader; this.resourceLoader = resourceLoader;
setResourceResolver(new LessonResourceResolver()); setResolvablePatterns(Set.of(PREFIX + "*"));
setResolvablePatterns(Sets.newHashSet(PREFIX + "*"));
} }
@Override @Override
protected String computeResourceName(TemplateProcessingParameters params) { protected ITemplateResource computeTemplateResource(IEngineConfiguration configuration, String ownerTemplate, String template, String resourceName, String characterEncoding, Map<String, Object> templateResolutionAttributes) {
String templateName = params.getTemplateName(); var templateName = resourceName.substring(PREFIX.length());;
return templateName.substring(PREFIX.length()); byte[] resource = resources.get(templateName);
}
private class LessonResourceResolver implements IResourceResolver {
@Override
@SneakyThrows
public InputStream getResourceAsStream(TemplateProcessingParameters params, String resourceName) {
byte[] resource = resources.get(resourceName);
if (resource == null) { if (resource == null) {
resource = ByteStreams.toByteArray(resourceLoader.getResource("classpath:/html/" + resourceName + ".html").getInputStream()); try {
resource = resourceLoader.getResource("classpath:/html/" + templateName + ".html").getInputStream().readAllBytes();
} catch (IOException e) {
e.printStackTrace();
}
resources.put(resourceName, resource); resources.put(resourceName, resource);
} }
return new ByteArrayInputStream(resource); return new StringTemplateResource(new String(resource, StandardCharsets.UTF_8));
}
@Override
public String getName() {
return "lessonResourceResolver";
}
} }
} }

View File

@ -28,41 +28,40 @@
* @version $Id: $Id * @version $Id: $Id
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import com.google.common.collect.Sets;
import org.owasp.webgoat.i18n.Language; import org.owasp.webgoat.i18n.Language;
import org.owasp.webgoat.i18n.Messages; import org.owasp.webgoat.i18n.Messages;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.LabelDebugger; import org.owasp.webgoat.session.LabelDebugger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader; import org.springframework.core.io.ResourceLoader;
import org.springframework.web.servlet.LocaleResolver; import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.SessionLocaleResolver; import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect; import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring4.SpringTemplateEngine; import org.thymeleaf.extras.springsecurity5.dialect.SpringSecurityDialect;
import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver; import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import java.io.File; import java.util.Set;
/** /**
* Configuration for Spring MVC * Configuration for Spring MVC
*/ */
@Configuration @Configuration
public class MvcConfiguration extends WebMvcConfigurerAdapter { public class MvcConfiguration implements WebMvcConfigurer {
@Autowired private static final String UTF8 = "UTF-8";
@Qualifier("pluginTargetDirectory")
private File pluginTargetDirectory;
@Override @Override
public void addViewControllers(ViewControllerRegistry registry) { public void addViewControllers(ViewControllerRegistry registry) {
@ -73,23 +72,33 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
//registry.addViewController("/list_users").setViewName("list_users"); //registry.addViewController("/list_users").setViewName("list_users");
} }
@Bean
public ViewResolver viewResolver(SpringTemplateEngine thymeleafTemplateEngine) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(thymeleafTemplateEngine);
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
@Bean @Bean
public TemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) { public ITemplateResolver springThymeleafTemplateResolver(ApplicationContext applicationContext) {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver(); SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("classpath:/templates/"); resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html"); resolver.setSuffix(".html");
resolver.setOrder(1); resolver.setTemplateMode(TemplateMode.HTML);
resolver.setOrder(2);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8);
resolver.setApplicationContext(applicationContext); resolver.setApplicationContext(applicationContext);
return resolver; return resolver;
} }
@Bean @Bean
public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) { public LessonTemplateResolver lessonTemplateResolver(ResourceLoader resourceLoader) {
LessonTemplateResolver resolver = new LessonTemplateResolver(pluginTargetDirectory, resourceLoader); LessonTemplateResolver resolver = new LessonTemplateResolver(resourceLoader);
resolver.setOrder(2); resolver.setOrder(0);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setCharacterEncoding(UTF8);
return resolver; return resolver;
} }
@ -97,34 +106,29 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) { public AsciiDoctorTemplateResolver asciiDoctorTemplateResolver(Language language) {
AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language); AsciiDoctorTemplateResolver resolver = new AsciiDoctorTemplateResolver(language);
resolver.setCacheable(false); resolver.setCacheable(false);
resolver.setOrder(3); resolver.setOrder(1);
resolver.setCharacterEncoding(UTF8);
return resolver; return resolver;
} }
@Bean @Bean
public SpringTemplateEngine thymeleafTemplateEngine(TemplateResolver springThymeleafTemplateResolver, public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver springThymeleafTemplateResolver,
LessonTemplateResolver lessonTemplateResolver, LessonTemplateResolver lessonTemplateResolver,
AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) { AsciiDoctorTemplateResolver asciiDoctorTemplateResolver) {
SpringTemplateEngine engine = new SpringTemplateEngine(); SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.addDialect(new SpringSecurityDialect()); engine.addDialect(new SpringSecurityDialect());
engine.setTemplateResolvers( engine.setTemplateResolvers(
Sets.newHashSet(springThymeleafTemplateResolver, lessonTemplateResolver, asciiDoctorTemplateResolver)); Set.of(lessonTemplateResolver, asciiDoctorTemplateResolver, springThymeleafTemplateResolver));
return engine; return engine;
} }
/**
* This way we expose the plugins target directory as a resource within the web application.
*
* @param registry
*/
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/plugin_lessons/**").addResourceLocations("file:///" + pluginTargetDirectory.toString() + "/");
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/"); registry.addResourceHandler("/images/**").addResourceLocations("classpath:/images/");
registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/"); registry.addResourceHandler("/lesson_js/**").addResourceLocations("classpath:/js/");
registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/"); registry.addResourceHandler("/lesson_css/**").addResourceLocations("classpath:/css/");
registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/"); registry.addResourceHandler("/video/**").addResourceLocations("classpath:/video/");
super.addResourceHandlers(registry);
} }
@Bean @Bean
@ -132,6 +136,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
PluginMessages pluginMessages = new PluginMessages(messages, language); PluginMessages pluginMessages = new PluginMessages(messages, language);
pluginMessages.setDefaultEncoding("UTF-8"); pluginMessages.setDefaultEncoding("UTF-8");
pluginMessages.setBasenames("i18n/WebGoatLabels"); pluginMessages.setBasenames("i18n/WebGoatLabels");
pluginMessages.setFallbackToSystemLocale(false);
return pluginMessages; return pluginMessages;
} }
@ -145,6 +150,7 @@ public class MvcConfiguration extends WebMvcConfigurerAdapter {
Messages messages = new Messages(language); Messages messages = new Messages(language);
messages.setDefaultEncoding("UTF-8"); messages.setDefaultEncoding("UTF-8");
messages.setBasename("classpath:i18n/messages"); messages.setBasename("classpath:i18n/messages");
messages.setFallbackToSystemLocale(false);
return messages; return messages;
} }

View File

@ -28,45 +28,22 @@
* @version $Id: $Id * @version $Id: $Id
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Context;
import org.owasp.webgoat.plugins.PluginEndpointPublisher;
import org.owasp.webgoat.plugins.PluginsLoader;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.session.WebgoatContext;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.io.File; import java.io.File;
import java.util.Arrays;
@SpringBootApplication @Configuration
@Slf4j public class WebGoat {
public class WebGoat extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebGoat.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(WebGoat.class, args);
}
@Bean(name = "pluginTargetDirectory") @Bean(name = "pluginTargetDirectory")
public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) { public File pluginTargetDirectory(@Value("${webgoat.user.directory}") final String webgoatHome) {
@ -75,8 +52,8 @@ public class WebGoat extends SpringBootServletInitializer {
@Bean @Bean
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS) @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public WebSession webSession(WebgoatContext webgoatContext) { public WebSession webSession() {
return new WebSession(webgoatContext); return new WebSession();
} }
@Bean @Bean
@ -85,34 +62,8 @@ public class WebGoat extends SpringBootServletInitializer {
return new UserSessionData("test", "data"); return new UserSessionData("test", "data");
} }
@Bean
public PluginEndpointPublisher pluginEndpointPublisher(ApplicationContext applicationContext) {
return new PluginEndpointPublisher(applicationContext);
}
@Bean
public Course course(PluginEndpointPublisher pluginEndpointPublisher) {
return new PluginsLoader(pluginEndpointPublisher).loadPlugins();
}
@Bean @Bean
public RestTemplate restTemplate() { public RestTemplate restTemplate() {
return new RestTemplate(); return new RestTemplate();
} }
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
return factory;
}
static class CustomCustomizer implements TomcatContextCustomizer {
@Override
public void customize(Context context) {
context.setUseHttpOnly(false);
}
}
} }

View File

@ -1,4 +1,3 @@
/** /**
* ************************************************************************************************ * ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, * This file is part of WebGoat, an Open Web Application Security Project utility. For details,
@ -28,6 +27,7 @@
* @version $Id: $Id * @version $Id: $Id
* @since December 12, 2015 * @since December 12, 2015
*/ */
package org.owasp.webgoat; package org.owasp.webgoat;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -35,13 +35,14 @@ import org.owasp.webgoat.users.UserService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/** /**
* Security configuration for WebGoat. * Security configuration for WebGoat.
@ -58,8 +59,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
.authorizeRequests() .authorizeRequests()
.antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "/registration", "/register.mvc").permitAll() .antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "/registration", "/register.mvc").permitAll()
.antMatchers("/servlet/AdminServlet/**").hasAnyRole("WEBGOAT_ADMIN", "SERVER_ADMIN") //
.antMatchers("/JavaSource/**").hasRole("SERVER_ADMIN") //
.anyRequest().authenticated(); .anyRequest().authenticated();
security.and() security.and()
.formLogin() .formLogin()
@ -76,12 +75,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login")); http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
} }
//// TODO: 11/18/2016 make this a little bit more configurabe last part at least
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/plugin_lessons/**", "/XXE/**");
}
@Autowired @Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder()); auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());
@ -92,4 +85,16 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
public UserDetailsService userDetailsServiceBean() throws Exception { public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService; return userDetailsService;
} }
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@SuppressWarnings("deprecation")
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
} }

View File

@ -0,0 +1,18 @@
package org.owasp.webgoat.asciidoc;
import java.util.Map;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
public class OperatingSystemMacro extends InlineMacroProcessor {
public OperatingSystemMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return System.getProperty("os.name");
}
}

View File

@ -0,0 +1,17 @@
package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor;
import java.util.Map;
public class WebGoatTmpDirMacro extends InlineMacroProcessor {
public WebGoatTmpDirMacro(String macroName, Map<String, Object> config) {
super(macroName, config);
}
@Override
public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return EnvironmentExposure.getEnv().getProperty("webgoat.server.directory");
}
}

View File

@ -2,12 +2,6 @@ package org.owasp.webgoat.asciidoc;
import org.asciidoctor.ast.AbstractBlock; import org.asciidoctor.ast.AbstractBlock;
import org.asciidoctor.extension.InlineMacroProcessor; import org.asciidoctor.extension.InlineMacroProcessor;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Map; import java.util.Map;
public class WebGoatVersionMacro extends InlineMacroProcessor { public class WebGoatVersionMacro extends InlineMacroProcessor {
@ -17,7 +11,7 @@ public class WebGoatVersionMacro extends InlineMacroProcessor {
} }
@Override @Override
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) { public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
return EnvironmentExposure.getEnv().getProperty("webgoat.build.version"); return EnvironmentExposure.getEnv().getProperty("webgoat.build.version");
} }
} }

View File

@ -23,7 +23,7 @@ public class WebWolfMacro extends InlineMacroProcessor {
} }
@Override @Override
protected String process(AbstractBlock parent, String target, Map<String, Object> attributes) { public String process(AbstractBlock parent, String target, Map<String, Object> attributes) {
Environment env = EnvironmentExposure.getEnv(); Environment env = EnvironmentExposure.getEnv();
String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port")); String hostname = determineHost(env.getProperty("webwolf.host"), env.getProperty("webwolf.port"));

View File

@ -22,26 +22,18 @@
* projects. * projects.
* <p> * <p>
*/ */
package org.owasp.webgoat.assignments; package org.owasp.webgoat.assignments;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.session.UserSessionData; import org.owasp.webgoat.session.UserSessionData;
import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.users.UserTracker; import org.owasp.webgoat.users.UserTracker;
import org.owasp.webgoat.users.UserTrackerRepository; import org.owasp.webgoat.users.UserTrackerRepository;
import org.owasp.webgoat.session.WebSession;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/** public abstract class AssignmentEndpoint {
* Each lesson can define an endpoint which can support the lesson. So for example if you create a lesson which uses JavaScript and
* needs to call out to the server to fetch data you can define an endpoint in that lesson. WebGoat will pick up this endpoint and
* Spring will publish it.
* </p>
* Extend this class and implement the met
* </p>
* Note: each subclass should declare this annotation otherwise the WebGoat framework cannot find your endpoint.
*/
public abstract class AssignmentEndpoint extends Endpoint {
@Autowired @Autowired
private UserTrackerRepository userTrackerRepository; private UserTrackerRepository userTrackerRepository;
@ -53,7 +45,6 @@ public abstract class AssignmentEndpoint extends Endpoint {
@Autowired @Autowired
private PluginMessages messages; private PluginMessages messages;
//// TODO: 11/13/2016 events better fit?
protected AttackResult trackProgress(AttackResult attackResult) { protected AttackResult trackProgress(AttackResult attackResult) {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
if (userTracker == null) { if (userTracker == null) {
@ -76,17 +67,12 @@ public abstract class AssignmentEndpoint extends Endpoint {
return userSessionData; return userSessionData;
} }
@Override
public final String getPath() {
return this.getClass().getAnnotationsByType(AssignmentPath.class)[0].value();
}
/** /**
* Convenience method for create a successful result: * Convenience method for create a successful result:
* * <p>
* - Assignment is set to solved * - Assignment is set to solved
* - Feedback message is set to 'assignment.solved' * - Feedback message is set to 'assignment.solved'
* * <p>
* Of course you can overwrite these values in a specific lesson * Of course you can overwrite these values in a specific lesson
* *
* @return a builder for creating a result from a lesson * @return a builder for creating a result from a lesson
@ -97,10 +83,10 @@ public abstract class AssignmentEndpoint extends Endpoint {
/** /**
* Convenience method for create a failed result: * Convenience method for create a failed result:
* * <p>
* - Assignment is set to not solved * - Assignment is set to not solved
* - Feedback message is set to 'assignment.not.solved' * - Feedback message is set to 'assignment.not.solved'
* * <p>
* Of course you can overwrite these values in a specific lesson * Of course you can overwrite these values in a specific lesson
* *
* @return a builder for creating a result from a lesson * @return a builder for creating a result from a lesson

View File

@ -1,5 +1,7 @@
package org.owasp.webgoat.assignments; package org.owasp.webgoat.assignments;
import org.springframework.web.bind.annotation.RequestMethod;
import java.lang.annotation.ElementType; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -12,5 +14,9 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface AssignmentPath { public @interface AssignmentPath {
String value(); String[] path() default {};
RequestMethod[] method() default {};
String value() default "";
} }

View File

@ -28,9 +28,10 @@
* @version $Id: $Id * @version $Id: $Id
* @since October 28, 2003 * @since October 28, 2003
*/ */
package org.owasp.webgoat.controller; package org.owasp.webgoat.controller;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
@ -79,8 +80,8 @@ public class StartLesson {
//GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next(); //GrantedAuthority authority = context.getAuthentication().getAuthorities().iterator().next();
String path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson String path = request.getRequestURL().toString(); // we now got /a/b/c/AccessControlMatrix.lesson
String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson")); String lessonName = path.substring(path.lastIndexOf('/') + 1, path.indexOf(".lesson"));
List<AbstractLesson> lessons = course.getLessons(); List<? extends Lesson> lessons = course.getLessons();
Optional<AbstractLesson> lesson = lessons.stream() Optional<? extends Lesson> lesson = lessons.stream()
.filter(l -> l.getId().equals(lessonName)) .filter(l -> l.getId().equals(lessonName))
.findFirst(); .findFirst();
ws.setCurrentLesson(lesson.get()); ws.setCurrentLesson(lesson.get());

View File

@ -28,6 +28,7 @@
* @since October 28, 2003 * @since October 28, 2003
* @version $Id: $Id * @version $Id: $Id
*/ */
package org.owasp.webgoat.controller; package org.owasp.webgoat.controller;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;

View File

@ -22,6 +22,7 @@
* projects. * projects.
* <p> * <p>
*/ */
package org.owasp.webgoat.i18n; package org.owasp.webgoat.i18n;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -25,9 +25,10 @@
package org.owasp.webgoat.i18n; package org.owasp.webgoat.i18n;
import lombok.SneakyThrows;
import org.springframework.context.support.ReloadableResourceBundleMessageSource; import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Properties; import java.util.Properties;
@ -50,18 +51,23 @@ public class PluginMessages extends ReloadableResourceBundleMessageSource {
} }
@Override @Override
@SneakyThrows
protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) { protected PropertiesHolder refreshProperties(String filename, PropertiesHolder propHolder) {
Properties properties = new Properties(); Properties properties = new Properties();
long lastModified = System.currentTimeMillis(); long lastModified = System.currentTimeMillis();
Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX); Enumeration<URL> resources = null;
try {
resources = Thread.currentThread().getContextClassLoader().getResources(filename + PROPERTIES_SUFFIX);
while (resources.hasMoreElements()) { while (resources.hasMoreElements()) {
URL resource = resources.nextElement(); URL resource = resources.nextElement();
String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, ""); String sourcePath = resource.toURI().toString().replace(PROPERTIES_SUFFIX, "");
PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder); PropertiesHolder holder = super.refreshProperties(sourcePath, propHolder);
properties.putAll(holder.getProperties()); properties.putAll(holder.getProperties());
} }
} catch (IOException | URISyntaxException e) {
logger.error("Unable to read plugin message", e);
}
return new PropertiesHolder(properties, lastModified); return new PropertiesHolder(properties, lastModified);
} }

View File

@ -1,9 +1,9 @@
package org.owasp.webgoat.lessons; package org.owasp.webgoat.lessons;
import com.google.common.collect.Lists;
import lombok.*; import lombok.*;
import javax.persistence.*; import javax.persistence.*;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -45,6 +45,7 @@ public class Assignment {
private Long id; private Long id;
private String name; private String name;
private String path; private String path;
@Transient @Transient
private List<String> hints; private List<String> hints;
@ -52,13 +53,27 @@ public class Assignment {
//Hibernate //Hibernate
} }
public Assignment(String name, String path) { public Assignment(String name) {
this(name, path, Lists.newArrayList()); this(name, name, new ArrayList<>());
} }
public Assignment(String name, String path, List<String> hints) { public Assignment(String name, String path, List<String> hints) {
if (path.equals("") || path.equals("/") || path.equals("/WebGoat/")) {
throw new IllegalStateException("The path of assignment '" + name + "' overrides WebGoat endpoints, please choose a path within the scope of the lesson");
}
this.name = name; this.name = name;
this.path = path; this.path = path;
this.hints = hints; this.hints = hints;
} }
/**
* Set path is here to overwrite stored paths.
* Since a stored path can no longer be used in a lesson while
* the lesson (name) itself is still part of the lesson.
*
* @param pathName the path
*/
public void setPath(String pathName) {
this.path = pathName;
}
} }

View File

@ -36,31 +36,40 @@ import lombok.Getter;
*/ */
public enum Category { public enum Category {
INTRODUCTION("Introduction", new Integer(5)), INTRODUCTION("Introduction", 5),
GENERAL("General", new Integer(100)), GENERAL("General", 100),
INJECTION("Injection Flaws", new Integer(200)),
AUTHENTICATION("Authentication Flaws", new Integer(300)), INJECTION("(A1) Injection", 300),
XSS("Cross-Site Scripting (XSS)", new Integer(400)), AUTHENTICATION("(A2) Broken Authentication", 302),
REQ_FORGERIES("Request Forgeries", new Integer(450)), INSECURE_COMMUNICATION("(A3) Sensitive Data Exposure", 303),
ACCESS_CONTROL("Access Control Flaws", new Integer(500)), XXE("(A4) XML External Entities (XXE)", 304),
INSECURE_CONFIGURATION("Insecure Configuration", new Integer(600)), ACCESS_CONTROL("(A5) Broken Access Control", 305),
INSECURE_COMMUNICATION("Insecure Communication", new Integer(700)),
INSECURE_STORAGE("Insecure Storage", new Integer(800)), XSS("(A7) Cross-Site Scripting (XSS)", 307),
INSECURE_DESERIALIZATION("Insecure Deserialization", new Integer(850)), INSECURE_DESERIALIZATION("(A8) Insecure Deserialization", 308),
REQUEST_FORGERIES("Request Forgeries", new Integer(900)), VULNERABLE_COMPONENTS("(A9) Vulnerable Components", 309),
VULNERABLE_COMPONENTS("Vulnerable Components - A9", new Integer(950)),
AJAX_SECURITY("AJAX Security", new Integer(1000)), REQUEST_FORGERIES("(A8:2013) Request Forgeries", 318),
BUFFER_OVERFLOW("Buffer Overflows", new Integer(1100)),
CODE_QUALITY("Code Quality", new Integer(1200)),
CONCURRENCY("Concurrency", new Integer(1300)), REQ_FORGERIES("Request Forgeries", 450),
ERROR_HANDLING("Improper Error Handling", new Integer(1400)),
DOS("Denial of Service", new Integer(1500)), INSECURE_CONFIGURATION("Insecure Configuration", 600),
MALICIOUS_EXECUTION("Malicious Execution", new Integer(1600)), INSECURE_STORAGE("Insecure Storage", 800),
CLIENT_SIDE("Client side", new Integer(1700)),
SESSION_MANAGEMENT("Session Management Flaws", new Integer(1800)),
WEB_SERVICES("Web Services", new Integer(1900)), AJAX_SECURITY("AJAX Security", 1000),
ADMIN_FUNCTIONS("Admin Functions", new Integer(2000)), BUFFER_OVERFLOW("Buffer Overflows", 1100),
CHALLENGE("Challenges", new Integer(3000)); CODE_QUALITY("Code Quality", 1200),
CONCURRENCY("Concurrency", 1300),
ERROR_HANDLING("Improper Error Handling", 1400),
DOS("Denial of Service", 1500),
MALICIOUS_EXECUTION("Malicious Execution", 1600),
CLIENT_SIDE("Client side", 1700),
SESSION_MANAGEMENT("Session Management Flaws", 1800),
WEB_SERVICES("Web Services", 1900),
ADMIN_FUNCTIONS("Admin Functions", 2000),
CHALLENGE("Challenges", 3000);
@Getter @Getter
private String name; private String name;

View File

@ -24,10 +24,10 @@
* projects. * projects.
* *
*/ */
package org.owasp.webgoat.lessons; package org.owasp.webgoat.lessons;
import lombok.Getter; import lombok.Value;
import lombok.Setter;
/** /**
* <p>Hint class.</p> * <p>Hint class.</p>
@ -35,12 +35,9 @@ import lombok.Setter;
* @author rlawson * @author rlawson
* @version $Id: $Id * @version $Id: $Id
*/ */
@Getter @Value
@Setter
public class Hint { public class Hint {
private String hint; private String hint;
private String lesson;
private String assignmentPath; private String assignmentPath;
private int number;
} }

View File

@ -1,64 +1,46 @@
package org.owasp.webgoat.lessons; /*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
import com.google.common.collect.Lists; *
import lombok.Setter; * Copyright (c) 2002 - 2019 Bruce Mayhew
import org.owasp.webgoat.session.Screen; *
import java.util.List;
/**
* ************************************************************************************************
* <p>
* <p>
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the * This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the * GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version. * License, or (at your option) any later version.
* <p> *
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details. * General Public License for more details.
* <p> *
* You should have received a copy of the GNU General Public License along with this program; if * You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA. * 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* *
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a> * Getting Source ==============
* @version $Id: $Id *
* @since October 28, 2003 * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
public abstract class AbstractLesson extends Screen implements Comparable<Object> {
package org.owasp.webgoat.lessons;
import lombok.Getter;
import lombok.Setter;
import lombok.Singular;
import java.util.List;
@Getter
@Setter
public abstract class Lesson {
private static int count = 1; private static int count = 1;
private Integer id = null; private Integer id = null;
private Integer ranking;
@Setter
private List<Assignment> assignments; private List<Assignment> assignments;
public List<Assignment> getAssignments() {
if (assignments == null) {
return Lists.newArrayList();
}
return assignments;
}
/** /**
* Constructor for the Lesson object * Constructor for the Lesson object
*/ */
public AbstractLesson() { public Lesson() {
id = new Integer(++count); id = ++count;
} }
@ -72,34 +54,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
return className.substring(className.lastIndexOf('.') + 1); return className.substring(className.lastIndexOf('.') + 1);
} }
/**
* <p>Setter for the field <code>ranking</code>.</p>
*
* @param ranking a {@link java.lang.Integer} object.
*/
public void setRanking(Integer ranking) {
this.ranking = ranking;
}
/**
* {@inheritDoc}
* <p>
* Description of the Method
*/
public int compareTo(Object obj) {
return this.getRanking().compareTo(((AbstractLesson) obj).getRanking());
}
/**
* {@inheritDoc}
* <p>
* Description of the Method
*/
public boolean equals(Object obj) {
return this.getScreenId() == ((AbstractLesson) obj).getScreenId();
}
/** /**
* Gets the category attribute of the Lesson object * Gets the category attribute of the Lesson object
* *
@ -109,13 +63,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
return getDefaultCategory(); return getDefaultCategory();
} }
/**
* <p>getDefaultRanking.</p>
*
* @return a {@link java.lang.Integer} object.
*/
protected abstract Integer getDefaultRanking();
/** /**
* <p>getDefaultCategory.</p> * <p>getDefaultCategory.</p>
* *
@ -123,29 +70,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
*/ */
protected abstract Category getDefaultCategory(); protected abstract Category getDefaultCategory();
/**
* <p>getDefaultHidden.</p>
*
* @return a boolean.
*/
protected abstract boolean getDefaultHidden();
/**
* Gets the hintCount attribute of the Lesson object
*
* @return The hintCount value
*/
public int getHintCount() {
return getHints().size();
}
/**
* <p>getHints.</p>
*
* @return a {@link java.util.List} object.
*/
public abstract List<String> getHints();
/** /**
* Gets the title attribute of the HelloScreen object * Gets the title attribute of the HelloScreen object
* *
@ -153,28 +77,6 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
*/ */
public abstract String getTitle(); public abstract String getTitle();
/**
* Gets the ranking attribute of the Lesson object
*
* @return The ranking value
*/
public Integer getRanking() {
if (ranking != null) {
return ranking;
} else {
return getDefaultRanking();
}
}
/**
* Gets the uniqueID attribute of the AbstractLesson object
*
* @return The uniqueID value
*/
public int getScreenId() {
return id.intValue();
}
/** /**
* <p>Returns the default "path" portion of a lesson's URL.</p> * <p>Returns the default "path" portion of a lesson's URL.</p>
* <p> * <p>
@ -218,5 +120,4 @@ public abstract class AbstractLesson extends Screen implements Comparable<Object
} }
public abstract String getId(); public abstract String getId();
} }

View File

@ -1,86 +0,0 @@
/**
*************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @since October 28, 2003
* @version $Id: $Id
*/
package org.owasp.webgoat.lessons;
//// TODO: 11/8/2016 remove
public abstract class LessonAdapter extends AbstractLesson {
/**
* <p>getDefaultHidden.</p>
*
* @return a boolean.
*/
protected boolean getDefaultHidden() {
return false;
}
/**
* Initiates lesson restart functionality. Lessons should override this for
* lesson specific actions
*/
public void restartLesson() {
// Do Nothing - called when restart lesson is pressed. Each lesson can do something
}
private final static Integer DEFAULT_RANKING = new Integer(1000);
/**
* <p>getDefaultRanking.</p>
*
* @return a {@link java.lang.Integer} object.
*/
protected Integer getDefaultRanking() {
return DEFAULT_RANKING;
}
/**
* provide a default submitMethod of lesson does not implement
*
* @return a {@link java.lang.String} object.
*/
public String getSubmitMethod() {
return "GET";
}
/**
* Fill in a descriptive title for this lesson. The title of the lesson.
* This will appear above the control area at the top of the page. This
* field will be rendered as html.
*
* @return The title value
*/
public String getTitle() {
return "Untitled Lesson " + getScreenId();
}
}

View File

@ -1,32 +1,32 @@
/** /**
* ************************************************************************************************* * *************************************************************************************************
* * <p>
* * <p>
* This file is part of WebGoat, an Open Web Application Security Project * This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/ * utility. For details, please see http://www.owasp.org/
* * <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* * <p>
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* * <p>
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* * <p>
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA. * Place - Suite 330, Boston, MA 02111-1307, USA.
* * <p>
* Getting Source ============== * Getting Source ==============
* * <p>
* Source for this application is maintained at * Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects. * https://github.com/WebGoat/WebGoat, a repository for free software projects.
*
*/ */
package org.owasp.webgoat.lessons; package org.owasp.webgoat.lessons;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,8 +45,7 @@ public class LessonMenuItem {
private List<LessonMenuItem> children = new ArrayList<LessonMenuItem>(); private List<LessonMenuItem> children = new ArrayList<LessonMenuItem>();
private boolean complete; private boolean complete;
private String link; private String link;
// private boolean showSource = true; private int ranking;
// private boolean showHints = true;
/** /**
* <p>Getter for the field <code>name</code>.</p> * <p>Getter for the field <code>name</code>.</p>
@ -111,7 +110,6 @@ public class LessonMenuItem {
children.add(child); children.add(child);
} }
/** {@inheritDoc} */
@Override @Override
public String toString() { public String toString() {
StringBuilder bldr = new StringBuilder(); StringBuilder bldr = new StringBuilder();
@ -156,6 +154,13 @@ public class LessonMenuItem {
this.link = link; this.link = link;
} }
public void setRanking(int ranking) {
this.ranking = ranking;
}
public int getRanking() {
return this.ranking;
}
} }

View File

@ -27,6 +27,7 @@
* for free software projects. * for free software projects.
* *
*/ */
package org.owasp.webgoat.lessons; package org.owasp.webgoat.lessons;
/** /**
@ -69,7 +70,6 @@ public class RequestParameter implements Comparable<RequestParameter> {
return value; return value;
} }
/** {@inheritDoc} */
@Override @Override
public int compareTo(RequestParameter o) { public int compareTo(RequestParameter o) {
return this.name.compareTo(o.getName()); return this.name.compareTo(o.getName());

View File

@ -0,0 +1,115 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.plugins;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.session.Course;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.lang.reflect.Method;
import java.util.*;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
@Slf4j
@Configuration
public class CourseConfiguration {
private final List<Lesson> lessons;
private final List<AssignmentEndpoint> assignments;
private final Map<String, List<AssignmentEndpoint>> assignmentsByPackage;
public CourseConfiguration(List<Lesson> lessons, List<AssignmentEndpoint> assignments) {
this.lessons = lessons;
this.assignments = assignments;
assignmentsByPackage = this.assignments.stream().collect(groupingBy(a -> a.getClass().getPackageName()));
}
@Bean
public Course course() {
lessons.stream().forEach(l -> l.setAssignments(createAssignment(l)));
return new Course(lessons);
}
private List<Assignment> createAssignment(Lesson lesson) {
var endpoints = assignmentsByPackage.get(lesson.getClass().getPackageName());
if (CollectionUtils.isEmpty(endpoints)) {
log.warn("Lesson: {} has no endpoints, is this intentionally?", lesson.getTitle());
return new ArrayList();
}
return endpoints.stream().map(e -> new Assignment(e.getClass().getSimpleName(), getPath(e.getClass()), getHints(e.getClass()))).collect(toList());
}
private String getPath(Class<? extends AssignmentEndpoint> e) {
for (Method m : e.getMethods()) {
if (m.getReturnType() == AttackResult.class) {
var mapping = getMapping(m);
if (mapping == null) {
log.error("AttackResult method found without mapping in: {}", e.getSimpleName());
} else {
return mapping;
}
}
}
return "none";
}
private String getMapping(Method m) {
String[] paths = null;
//Find the path, either it is @GetMapping("/attack") of GetMapping(path = "/attack") both are valid, we need to consider both
if (m.getAnnotation(RequestMapping.class) != null) {
paths = ArrayUtils.addAll(m.getAnnotation(RequestMapping.class).value(), m.getAnnotation(RequestMapping.class).path());
} else if (m.getAnnotation(PostMapping.class) != null) {
paths = ArrayUtils.addAll(m.getAnnotation(PostMapping.class).value(), m.getAnnotation(PostMapping.class).path());
} else if (m.getAnnotation(GetMapping.class) != null) {
paths = ArrayUtils.addAll(m.getAnnotation(GetMapping.class).value(), m.getAnnotation(GetMapping.class).path());
} else if (m.getAnnotation(PutMapping.class) != null) {
paths = ArrayUtils.addAll(m.getAnnotation(PutMapping.class).value(), m.getAnnotation(PutMapping.class).path());
}
if (paths == null) {
return "";
} else {
return Arrays.stream(paths).filter(path -> !"".equals(path)).findFirst().orElseGet(() -> "");
}
}
private List<String> getHints(Class<? extends AssignmentEndpoint> e) {
if (e.isAnnotationPresent(AssignmentHints.class)) {
return List.of(e.getAnnotationsByType(AssignmentHints.class)[0].value());
}
return Collections.emptyList();
}
}

View File

@ -1,66 +0,0 @@
package org.owasp.webgoat.plugins;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.Endpoint;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import java.util.List;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since October 16, 2016
*/
@Slf4j
public class PluginEndpointPublisher {
private AbstractApplicationContext applicationContext;
public PluginEndpointPublisher(ApplicationContext applicationContext) {
this.applicationContext = (AbstractApplicationContext) applicationContext;
}
public void publish(List<Class<Endpoint>> endpoints) {
endpoints.forEach(e -> publishEndpoint(e));
}
private void publishEndpoint(Class<? extends MvcEndpoint> e) {
try {
BeanDefinition beanDefinition = new RootBeanDefinition(e, Autowire.BY_TYPE.value(), true);
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getBeanFactory();
beanFactory.registerBeanDefinition(beanDefinition.getBeanClassName(), beanDefinition);
} catch (Exception ex) {
log.error("Failed to register " + e.getSimpleName() + " as endpoint with Spring, skipping...");
}
}
}

View File

@ -1,46 +0,0 @@
package org.owasp.webgoat.plugins;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.Endpoint;
import org.owasp.webgoat.lessons.NewLesson;
import java.net.URL;
import java.util.List;
import java.util.stream.Collectors;
/**
* Plugin resource
*
* @author nbaars
* @since 3/4/17.
*/
@AllArgsConstructor
@Getter
public class PluginResource {
private final URL location;
private final List<Class> classes;
public List<Class> getLessons() {
return classes.stream().filter(c -> c.getSuperclass() == NewLesson.class).collect(Collectors.toList());
}
public List<Class<Endpoint>> getEndpoints() {
return classes.stream().
filter(c -> c.getSuperclass() == AssignmentEndpoint.class || c.getSuperclass() == Endpoint.class).
map(c -> (Class<Endpoint>) c).
collect(Collectors.toList());
}
public List<Class<AssignmentEndpoint>> getAssignments(Class lesson) {
return classes.stream().
filter(c -> c.getSuperclass() == AssignmentEndpoint.class).
filter(c -> c.getPackage().equals(lesson.getPackage())).
map(c -> (Class<AssignmentEndpoint>) c).
collect(Collectors.toList());
}
}

View File

@ -1,134 +0,0 @@
package org.owasp.webgoat.plugins;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AssignmentPath;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.NewLesson;
import org.owasp.webgoat.session.Course;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.toList;
/**
* ************************************************************************************************
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
* <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew
* <p>
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
* <p>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
* <p>
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
* <p>
* Getting Source ==============
* <p>
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
* <p>
*
* @author nbaars
* @version $Id: $Id
* @since November 25, 2016
*/
@AllArgsConstructor
@Slf4j
public class PluginsLoader {
private final PluginEndpointPublisher pluginEndpointPublisher;
/**
* <p>createLessonsFromPlugins.</p>
*/
public Course loadPlugins() {
List<AbstractLesson> lessons = Lists.newArrayList();
for (PluginResource plugin : findPluginResources()) {
try {
plugin.getLessons().forEach(c -> {
NewLesson lesson = null;
try {
lesson = (NewLesson) c.newInstance();
log.trace("Lesson loaded: {}", lesson.getId());
} catch (Exception e) {
log.error("Error while loading:" + c, e);
}
List<Class<AssignmentEndpoint>> assignments = plugin.getAssignments(c);
lesson.setAssignments(createAssignment(assignments));
lessons.add(lesson);
pluginEndpointPublisher.publish(plugin.getEndpoints());
});
} catch (Exception e) {
log.error("Error in loadLessons: ", e);
}
}
if (lessons.isEmpty()) {
log.error("No lessons found if you downloaded an official release of WebGoat please take the time to");
log.error("create a new issue at https://github.com/WebGoat/WebGoat/issues/new");
log.error("For developers run 'mvn package' first from the root directory.");
}
return new Course(lessons);
}
private List<Assignment> createAssignment(List<Class<AssignmentEndpoint>> endpoints) {
return endpoints.stream().map(e -> new Assignment(e.getSimpleName(), getPath(e), getHints(e))).collect(toList());
}
private String getPath(Class<AssignmentEndpoint> e) {
return e.getAnnotationsByType(AssignmentPath.class)[0].value();
}
private List<String> getHints(Class<AssignmentEndpoint> e) {
if (e.isAnnotationPresent(AssignmentHints.class)) {
return Lists.newArrayList(e.getAnnotationsByType(AssignmentHints.class)[0].value());
}
return Lists.newArrayList();
}
@SneakyThrows
public List<PluginResource> findPluginResources() {
final ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new RegexPatternTypeFilter(Pattern.compile(".*")));
final Set<BeanDefinition> classes = provider.findCandidateComponents("org.owasp.webgoat.plugin");
Map<URL, List<Class>> pluginClasses = Maps.newHashMap();
for (BeanDefinition bean : classes) {
Class<?> clazz = Class.forName(bean.getBeanClassName());
URL location = clazz.getProtectionDomain().getCodeSource().getLocation();
List<Class> classFiles = pluginClasses.get(location);
if (classFiles == null) {
classFiles = Lists.newArrayList(clazz);
} else {
classFiles.add(clazz);
}
pluginClasses.put(location, classFiles);
}
return pluginClasses.entrySet().parallelStream()
.map(e -> new PluginResource(e.getKey(), e.getValue()))
.collect(Collectors.toList());
}
}

View File

@ -1,63 +0,0 @@
/**
* *************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
*/
package org.owasp.webgoat.service;
import com.google.common.collect.Lists;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.util.List;
/**
* <p>CookieService class.</p>
*
* @author rlawson
* @version $Id: $Id
*/
@Controller
public class CookieService {
/**
* Returns cookies for last attack
*
* @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.util.List} object.
*/
@RequestMapping(path = "/service/cookie.mvc", produces = "application/json")
public @ResponseBody
List<Cookie> showCookies() {
//// TODO: 11/6/2016 to be decided
List<Cookie> cookies = Lists.newArrayList();
return cookies;
}
}

View File

@ -3,12 +3,12 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.Hint; import org.owasp.webgoat.lessons.Hint;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -41,42 +41,22 @@ public class HintService {
*/ */
@GetMapping(path = URL_HINTS_MVC, produces = "application/json") @GetMapping(path = URL_HINTS_MVC, produces = "application/json")
@ResponseBody @ResponseBody
public List<Hint> showHint() { public List<Hint> getHints() {
AbstractLesson l = webSession.getCurrentLesson(); Lesson l = webSession.getCurrentLesson();
List<Hint> hints = createLessonHints(l); return createAssignmentHints(l);
hints.addAll(createAssignmentHints(l));
return hints;
} }
private List<Hint> createLessonHints(AbstractLesson l) { private List<Hint> createAssignmentHints(Lesson l) {
if (l != null) { if (l != null) {
return l.getHints().stream().map(h -> createHint(h, l.getName(), null)).collect(toList()); return l.getAssignments().stream()
.map(a -> createHint(a))
.flatMap(hints -> hints.stream())
.collect(toList());
} }
return Lists.newArrayList(); return List.of();
} }
private List<Hint> createAssignmentHints(AbstractLesson l) { private List<Hint> createHint(Assignment a) {
List<Hint> hints = Lists.newArrayList(); return a.getHints().stream().map(h -> new Hint(h, a.getPath())).collect(toList());
if ( l != null) {
List<Assignment> assignments = l.getAssignments();
assignments.stream().forEach(a -> { a.getHints(); createHints(a, hints);});
}
return hints;
}
private void createHints(Assignment a, List<Hint> hints) {
hints.addAll(a.getHints().stream().map(h -> createHint(h, null, a.getPath())).collect(toList()));
}
private Hint createHint(String hintText, String lesson, String assignmentName) {
Hint hint = new Hint();
hint.setHint(hintText);
if (lesson != null) {
hint.setLesson(lesson);
} else {
hint.setAssignmentPath(assignmentName);
}
return hint;
} }
} }

View File

@ -1,32 +1,32 @@
/** /**
* ************************************************************************************************* * *************************************************************************************************
* * <p>
* * <p>
* This file is part of WebGoat, an Open Web Application Security Project * This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/ * utility. For details, please see http://www.owasp.org/
* * <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* * <p>
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* * <p>
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* * <p>
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA. * Place - Suite 330, Boston, MA 02111-1307, USA.
* * <p>
* Getting Source ============== * Getting Source ==============
* * <p>
* Source for this application is maintained at * Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects. * https://github.com/WebGoat/WebGoat, a repository for free software projects.
*
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -26,6 +26,7 @@
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects. * for free software projects.
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
@ -67,18 +68,17 @@ public class LabelService {
* We use Springs session locale resolver which also gives us the option to change the local later on. For * We use Springs session locale resolver which also gives us the option to change the local later on. For
* now it uses the accept-language from the HttpRequest. If this language is not found it will default back * now it uses the accept-language from the HttpRequest. If this language is not found it will default back
* to messages.properties. * to messages.properties.
* * <p>
* Note although it is possible to use Spring language interceptor we for now opt for this solution, the UI * Note although it is possible to use Spring language interceptor we for now opt for this solution, the UI
* will always need to fetch the labels with the new language set by the user. So we don't need to intercept each * will always need to fetch the labels with the new language set by the user. So we don't need to intercept each
* and every request to see if the language param has been set in the request. * and every request to see if the language param has been set in the request.
* *
* @param lang the language to fetch labels for (optional) * @param lang the language to fetch labels for (optional)
* @return a map of labels * @return a map of labels
* @throws Exception
*/ */
@GetMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE) @GetMapping(path = URL_LABELS_MVC, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody @ResponseBody
public ResponseEntity<Properties> fetchLabels(@RequestParam(value = "lang", required = false) String lang, HttpServletRequest request) { public ResponseEntity<Properties> fetchLabels(@RequestParam(value = "lang", required = false) String lang) {
if (!StringUtils.isEmpty(lang)) { if (!StringUtils.isEmpty(lang)) {
Locale locale = Locale.forLanguageTag(lang); Locale locale = Locale.forLanguageTag(lang);
((SessionLocaleResolver) localeResolver).setDefaultLocale(locale); ((SessionLocaleResolver) localeResolver).setDefaultLocale(locale);

View File

@ -1,7 +1,7 @@
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.LessonInfoModel; import org.owasp.webgoat.lessons.LessonInfoModel;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -29,7 +29,7 @@ public class LessonInfoService {
@RequestMapping(path = "/service/lessoninfo.mvc", produces = "application/json") @RequestMapping(path = "/service/lessoninfo.mvc", produces = "application/json")
public @ResponseBody public @ResponseBody
LessonInfoModel getLessonInfo() { LessonInfoModel getLessonInfo() {
AbstractLesson lesson = webSession.getCurrentLesson(); Lesson lesson = webSession.getCurrentLesson();
return new LessonInfoModel(lesson.getTitle(), false, false, false); return new LessonInfoModel(lesson.getTitle(), false, false, false);
} }

View File

@ -26,10 +26,12 @@
* Source for this application is maintained at * Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects. * https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.Category; import org.owasp.webgoat.lessons.Category;
import org.owasp.webgoat.lessons.LessonMenuItem; import org.owasp.webgoat.lessons.LessonMenuItem;
import org.owasp.webgoat.lessons.LessonMenuItemType; import org.owasp.webgoat.lessons.LessonMenuItemType;
@ -45,6 +47,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@ -80,20 +83,37 @@ public class LessonMenuService {
categoryItem.setName(category.getName()); categoryItem.setName(category.getName());
categoryItem.setType(LessonMenuItemType.CATEGORY); categoryItem.setType(LessonMenuItemType.CATEGORY);
// check for any lessons for this category // check for any lessons for this category
List<AbstractLesson> lessons = course.getLessons(category); List<Lesson> lessons = course.getLessons(category);
lessons = lessons.stream().sorted(Comparator.comparing(l -> l.getTitle())).collect(Collectors.toList()); lessons = lessons.stream().sorted(Comparator.comparing(l -> l.getTitle())).collect(Collectors.toList());
for (AbstractLesson lesson : lessons) { for (Lesson lesson : lessons) {
LessonMenuItem lessonItem = new LessonMenuItem(); LessonMenuItem lessonItem = new LessonMenuItem();
lessonItem.setName(lesson.getTitle()); lessonItem.setName(lesson.getTitle());
lessonItem.setLink(lesson.getLink()); lessonItem.setLink(lesson.getLink());
lessonItem.setType(LessonMenuItemType.LESSON); lessonItem.setType(LessonMenuItemType.LESSON);
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson); LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
lessonItem.setComplete(lessonTracker.isLessonSolved()); boolean lessonSolved = lessonCompleted(lessonTracker.getLessonOverview(), lesson);
lessonItem.setComplete(lessonSolved);
categoryItem.addChild(lessonItem); categoryItem.addChild(lessonItem);
} }
categoryItem.getChildren().sort((o1, o2) -> o1.getRanking() - o2.getRanking());
menu.add(categoryItem); menu.add(categoryItem);
} }
return menu; return menu;
} }
private boolean lessonCompleted(Map<Assignment, Boolean> map, Lesson currentLesson) {
boolean result = true;
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
Assignment storedAssignment = entry.getKey();
for (Assignment lessonAssignment: currentLesson.getAssignments()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result = result && entry.getValue();
break;
}
}
}
return result;
}
} }

View File

@ -27,6 +27,7 @@
* for free software projects. * for free software projects.
* *
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;

View File

@ -1,10 +1,8 @@
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import org.owasp.webgoat.lessons.LessonInfoModel; import org.owasp.webgoat.lessons.LessonInfoModel;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
@ -16,6 +14,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -40,14 +39,14 @@ public class LessonProgressService {
@RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json") @RequestMapping(value = "/service/lessonprogress.mvc", produces = "application/json")
@ResponseBody @ResponseBody
public Map getLessonInfo() { public Map getLessonInfo() {
Map json = Maps.newHashMap(); Map json = new HashMap();
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
if (webSession.getCurrentLesson() != null) { if (webSession.getCurrentLesson() != null) {
LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson()); LessonTracker lessonTracker = userTracker.getLessonTracker(webSession.getCurrentLesson());
String successMessage = ""; String successMessage = "";
boolean lessonCompleted = false; boolean lessonCompleted = false;
if (lessonTracker != null) { if (lessonTracker != null) {
lessonCompleted = lessonTracker.isLessonSolved(); lessonCompleted = isLessonComplete(lessonTracker.getLessonOverview(), webSession.getCurrentLesson());
successMessage = "LessonCompleted"; //@todo we still use this?? successMessage = "LessonCompleted"; //@todo we still use this??
} }
json.put("lessonCompleted", lessonCompleted); json.put("lessonCompleted", lessonCompleted);
@ -66,23 +65,53 @@ public class LessonProgressService {
@ResponseBody @ResponseBody
public List<LessonOverview> lessonOverview() { public List<LessonOverview> lessonOverview() {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
AbstractLesson currentLesson = webSession.getCurrentLesson(); Lesson currentLesson = webSession.getCurrentLesson();
List<LessonOverview> result = Lists.newArrayList(); List<LessonOverview> result = new ArrayList<>();
if (currentLesson != null) { if (currentLesson != null) {
LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson); LessonTracker lessonTracker = userTracker.getLessonTracker(currentLesson);
result = toJson(lessonTracker.getLessonOverview()); result = toJson(lessonTracker.getLessonOverview(), currentLesson);
} }
return result; return result;
} }
private List<LessonOverview> toJson(Map<Assignment, Boolean> map) { private List<LessonOverview> toJson(Map<Assignment, Boolean> map, Lesson currentLesson) {
ArrayList<LessonOverview> result = Lists.newArrayList(); List<LessonOverview> result = new ArrayList();
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) { for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
result.add(new LessonOverview(entry.getKey(), entry.getValue())); Assignment storedAssignment = entry.getKey();
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())
&& !lessonAssignment.getPath().equals(storedAssignment.getPath())) {
//here a stored path in the assignments table will be corrected for the JSON output
//with the value of the actual expected path
storedAssignment.setPath(lessonAssignment.getPath());
result.add(new LessonOverview(storedAssignment, entry.getValue()));
break;
} else if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result.add(new LessonOverview(storedAssignment, entry.getValue()));
break;
}
}
//assignments not in the list will not be put in the lesson progress JSON output
} }
return result; return result;
} }
private boolean isLessonComplete(Map<Assignment, Boolean> map, Lesson currentLesson) {
boolean result = true;
for (Map.Entry<Assignment, Boolean> entry : map.entrySet()) {
Assignment storedAssignment = entry.getKey();
for (Assignment lessonAssignment : currentLesson.getAssignments()) {
if (lessonAssignment.getName().equals(storedAssignment.getName())) {
result = result && entry.getValue();
break;
}
}
}
return result;
}
@AllArgsConstructor @AllArgsConstructor
@Getter @Getter

View File

@ -1,6 +1,6 @@
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -31,7 +31,7 @@ public class LessonTitleService {
public public
@ResponseBody @ResponseBody
String showPlan() { String showPlan() {
AbstractLesson lesson = webSession.getCurrentLesson(); Lesson lesson = webSession.getCurrentLesson();
return lesson != null ? lesson.getTitle() : ""; return lesson != null ? lesson.getTitle() : "";
} }

View File

@ -1,65 +0,0 @@
/**
* *************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository
* for free software projects.
*
*/
package org.owasp.webgoat.service;
import com.google.common.collect.Lists;
import org.owasp.webgoat.lessons.RequestParameter;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpSession;
import java.util.Collections;
import java.util.List;
/**
* <p>ParameterService class.</p>
*
* @author rlawson
* @version $Id: $Id
*/
@Controller
public class ParameterService {
/**
* Returns request parameters for last attack
*
* @param session a {@link javax.servlet.http.HttpSession} object.
* @return a {@link java.util.List} object.
*/
@RequestMapping(path = "/service/parameter.mvc", produces = "application/json")
public @ResponseBody
List<RequestParameter> showParameters(HttpSession session) {
//// TODO: 11/6/2016 to decide not sure about the role in WebGoat 8
List<RequestParameter> listParms = Lists.newArrayList();
Collections.sort(listParms);
return listParms;
}
}

View File

@ -1,32 +1,32 @@
/** /**
* ************************************************************************************************* * *************************************************************************************************
* * <p>
* * <p>
* This file is part of WebGoat, an Open Web Application Security Project * This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/ * utility. For details, please see http://www.owasp.org/
* * <p>
* Copyright (c) 2002 - 20014 Bruce Mayhew * Copyright (c) 2002 - 20014 Bruce Mayhew
* * <p>
* This program is free software; you can redistribute it and/or modify it under * This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software * the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later * Foundation; either version 2 of the License, or (at your option) any later
* version. * version.
* * <p>
* This program is distributed in the hope that it will be useful, but WITHOUT * This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details. * details.
* * <p>
* You should have received a copy of the GNU General Public License along with * You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA. * Place - Suite 330, Boston, MA 02111-1307, USA.
* * <p>
* Getting Source ============== * Getting Source ==============
* * <p>
* Source for this application is maintained at * Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects. * https://github.com/WebGoat/WebGoat, a repository for free software projects.
*
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
@ -46,6 +46,7 @@ import java.util.Map;
* @author nbaars * @author nbaars
* @version $Id: $Id * @version $Id: $Id
*/ */
//TODO REMOVE?
@Controller @Controller
public class PluginReloadService { public class PluginReloadService {
@ -58,15 +59,6 @@ public class PluginReloadService {
@RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(path = "/service/reloadplugins.mvc", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody public @ResponseBody
ResponseEntity<Map<String, Object>> reloadPlugins(HttpSession session) { ResponseEntity<Map<String, Object>> reloadPlugins(HttpSession session) {
// WebSession webSession = (WebSession) session.getAttribute(WebSession.SESSION);
//
// logger.debug("Loading plugins into cache");
// String pluginPath = session.getServletContext().getRealPath("plugin_lessons");
// String targetPath = session.getServletContext().getRealPath("plugin_extracted");
// //TODO fix me
// //new PluginsLoader(Paths.get(pluginPath), Paths.get(targetPath)).copyJars();
// //webSession.getCourse().createLessonsFromPlugins();
Map<String, Object> result = new HashMap<String, Object>(); Map<String, Object> result = new HashMap<String, Object>();
result.put("success", true); result.put("success", true);
result.put("message", "Plugins reloaded"); result.put("message", "Plugins reloaded");

View File

@ -26,14 +26,14 @@
* Source for this application is maintained at * Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects. * https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.Course; import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.users.LessonTracker; import org.owasp.webgoat.users.LessonTracker;
@ -43,6 +43,7 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -66,14 +67,14 @@ public class ReportCardService {
@GetMapping(path = "/service/reportcard.mvc", produces = "application/json") @GetMapping(path = "/service/reportcard.mvc", produces = "application/json")
@ResponseBody @ResponseBody
public ReportCard reportCard() { public ReportCard reportCard() {
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
List<AbstractLesson> lessons = course.getLessons();
ReportCard reportCard = new ReportCard(); ReportCard reportCard = new ReportCard();
reportCard.setTotalNumberOfLessons(course.getTotalOfLessons()); reportCard.setTotalNumberOfLessons(course.getTotalOfLessons());
reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments()); reportCard.setTotalNumberOfAssignments(course.getTotalOfAssignments());
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved()); reportCard.setNumberOfAssignmentsSolved(userTracker.numberOfAssignmentsSolved());
reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved()); reportCard.setNumberOfLessonsSolved(userTracker.numberOfLessonsSolved());
for (AbstractLesson lesson : lessons) { for (Lesson lesson : course.getLessons()) {
LessonTracker lessonTracker = userTracker.getLessonTracker(lesson); LessonTracker lessonTracker = userTracker.getLessonTracker(lesson);
LessonStatistics lessonStatistics = new LessonStatistics(); LessonStatistics lessonStatistics = new LessonStatistics();
lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle())); lessonStatistics.setName(pluginMessages.getMessage(lesson.getTitle()));
@ -93,7 +94,7 @@ public class ReportCardService {
private int solvedLessons; private int solvedLessons;
private int numberOfAssignmentsSolved; private int numberOfAssignmentsSolved;
private int numberOfLessonsSolved; private int numberOfLessonsSolved;
private List<LessonStatistics> lessonStatistics = Lists.newArrayList(); private List<LessonStatistics> lessonStatistics = new ArrayList<>();
} }
@Setter @Setter

View File

@ -21,11 +21,13 @@
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software * Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects. * projects.
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson; import org.flywaydb.core.Flyway;
import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.session.WebSession; import org.owasp.webgoat.session.WebSession;
import org.owasp.webgoat.users.UserTracker; import org.owasp.webgoat.users.UserTracker;
import org.owasp.webgoat.users.UserTrackerRepository; import org.owasp.webgoat.users.UserTrackerRepository;
@ -34,33 +36,26 @@ import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;
/**
* <p>RestartLessonService class.</p>
*
* @author rlawson
* @version $Id: $Id
*/
@Controller @Controller
@AllArgsConstructor @AllArgsConstructor
@Slf4j @Slf4j
public class RestartLessonService { public class RestartLessonService {
private final WebSession webSession; private final WebSession webSession;
private UserTrackerRepository userTrackerRepository; private final UserTrackerRepository userTrackerRepository;
private final Flyway flywayLessons;
/**
* Returns current lesson
*
* @return a {@link java.lang.String} object.
*/
@RequestMapping(path = "/service/restartlesson.mvc", produces = "text/text") @RequestMapping(path = "/service/restartlesson.mvc", produces = "text/text")
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public void restartLesson() { public void restartLesson() {
AbstractLesson al = webSession.getCurrentLesson(); Lesson al = webSession.getCurrentLesson();
log.debug("Restarting lesson: " + al); log.debug("Restarting lesson: " + al);
UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName()); UserTracker userTracker = userTrackerRepository.findByUser(webSession.getUserName());
userTracker.reset(al); userTracker.reset(al);
userTrackerRepository.save(userTracker); userTrackerRepository.save(userTracker);
flywayLessons.clean();
flywayLessons.migrate();
} }
} }

View File

@ -3,6 +3,7 @@
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package org.owasp.webgoat.service; package org.owasp.webgoat.service;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;

View File

@ -1,11 +1,9 @@
package org.owasp.webgoat.session; package org.owasp.webgoat.session;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Category; import org.owasp.webgoat.lessons.Category;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toList;
@ -41,10 +39,13 @@ import static java.util.stream.Collectors.toList;
* @since October 28, 2003 * @since October 28, 2003
*/ */
@Slf4j @Slf4j
@AllArgsConstructor
public class Course { public class Course {
private List<AbstractLesson> lessons = new LinkedList<>(); private List<? extends Lesson> lessons;
public Course(List<? extends Lesson> lessons) {
this.lessons = lessons;
}
/** /**
* Gets the categories attribute of the Course object * Gets the categories attribute of the Course object
@ -60,7 +61,7 @@ public class Course {
* *
* @return The firstLesson value * @return The firstLesson value
*/ */
public AbstractLesson getFirstLesson() { public Lesson getFirstLesson() {
// Category 0 is the admin function. We want the first real category // Category 0 is the admin function. We want the first real category
// to be returned. This is normally the General category and the Http Basics lesson // to be returned. This is normally the General category and the Http Basics lesson
return getLessons(getCategories().get(0)).get(0); return getLessons(getCategories().get(0)).get(0);
@ -71,7 +72,7 @@ public class Course {
* *
* @return a {@link java.util.List} object. * @return a {@link java.util.List} object.
*/ */
public List<AbstractLesson> getLessons() { public List<? extends Lesson> getLessons() {
return this.lessons; return this.lessons;
} }
@ -81,11 +82,11 @@ public class Course {
* @param category a {@link org.owasp.webgoat.lessons.Category} object. * @param category a {@link org.owasp.webgoat.lessons.Category} object.
* @return a {@link java.util.List} object. * @return a {@link java.util.List} object.
*/ */
public List<AbstractLesson> getLessons(Category category) { public List<Lesson> getLessons(Category category) {
return this.lessons.stream().filter(l -> l.getCategory() == category).sorted().collect(toList()); return this.lessons.stream().filter(l -> l.getCategory() == category).collect(toList());
} }
public void setLessons(List<AbstractLesson> lessons) { public void setLessons(List<Lesson> lessons) {
this.lessons = lessons; this.lessons = lessons;
} }
@ -94,9 +95,6 @@ public class Course {
} }
public int getTotalOfAssignments() { public int getTotalOfAssignments() {
final int[] total = {0}; return this.lessons.stream().reduce(0, (total, lesson) -> lesson.getAssignments().size() + total, Integer::sum);
this.lessons.stream().forEach(l -> total[0] = total[0] + l.getAssignments().size());
return total[0];
} }
} }

View File

@ -1,129 +0,0 @@
package org.owasp.webgoat.session;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/**
*************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
* projects.
*
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
* @version $Id: $Id
*/
//TODO: class we need to refactor to new structure, we can put the connection in the current session of the user
// start using jdbc template
public class DatabaseUtilities
{
private static Map<String, Connection> connections = new HashMap<String, Connection>();
private static Map<String, Boolean> dbBuilt = new HashMap<String, Boolean>();
/**
* <p>getConnection.</p>
*
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @return a {@link java.sql.Connection} object.
* @throws java.sql.SQLException if any.
*/
public static Connection getConnection(WebSession s) throws SQLException
{
return getConnection(s.getUserName(), s.getWebgoatContext());
}
/**
* <p>getConnection.</p>
*
* @param user a {@link java.lang.String} object.
* @param context a {@link org.owasp.webgoat.session.WebgoatContext} object.
* @return a {@link java.sql.Connection} object.
* @throws java.sql.SQLException if any.
*/
public static synchronized Connection getConnection(String user, WebgoatContext context) throws SQLException
{
Connection conn = connections.get(user);
if (conn != null && !conn.isClosed()) return conn;
conn = makeConnection(user, context);
connections.put(user, conn);
if (dbBuilt.get(user) == null)
{
new CreateDB().makeDB(conn);
dbBuilt.put(user, Boolean.TRUE);
}
return conn;
}
/**
* <p>returnConnection.</p>
*
* @param user a {@link java.lang.String} object.
*/
public static synchronized void returnConnection(String user)
{
try
{
Connection connection = connections.get(user);
if (connection == null || connection.isClosed()) return;
if (connection.getMetaData().getDatabaseProductName().toLowerCase().contains("oracle")) connection.close();
} catch (SQLException sqle)
{
sqle.printStackTrace();
}
}
private static Connection makeConnection(String user, WebgoatContext context) throws SQLException
{
try
{
Class.forName(context.getDatabaseDriver());
if (context.getDatabaseConnectionString().contains("hsqldb")) return getHsqldbConnection(user, context);
String userPrefix = context.getDatabaseUser();
String password = context.getDatabasePassword();
String url = context.getDatabaseConnectionString();
return DriverManager.getConnection(url, userPrefix + "_" + user, password);
} catch (ClassNotFoundException cnfe)
{
cnfe.printStackTrace();
throw new SQLException("Couldn't load the database driver: " + cnfe.getLocalizedMessage());
}
}
private static Connection getHsqldbConnection(String user, WebgoatContext context) throws ClassNotFoundException,
SQLException
{
String url = context.getDatabaseConnectionString().replace("{USER}", user);
return DriverManager.getConnection(url, "sa", "");
}
}

View File

@ -1,53 +0,0 @@
package org.owasp.webgoat.session;
/**
* *************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 20014 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at
* https://github.com/WebGoat/WebGoat, a repository for free software projects.
*
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect
* Security</a>
* @since October 28, 2003
* @version $Id: $Id
*/
public abstract class Screen {
/**
* Constructor for the Screen object
*/
public Screen() {
}
/**
* Fill in a descriptive title for this lesson
*
* @return The title value
*/
public abstract String getTitle();
}

View File

@ -1,10 +1,10 @@
package org.owasp.webgoat.session; package org.owasp.webgoat.session;
import lombok.extern.slf4j.Slf4j; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.users.WebGoatUser; import org.owasp.webgoat.users.WebGoatUser;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import java.io.Serializable;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
@ -37,58 +37,31 @@ import java.sql.SQLException;
* @version $Id: $Id * @version $Id: $Id
* @since October 28, 2003 * @since October 28, 2003
*/ */
@Slf4j public class WebSession implements Serializable {
public class WebSession {
private static final long serialVersionUID = -4270066103101711560L;
private final WebGoatUser currentUser; private final WebGoatUser currentUser;
private final WebgoatContext webgoatContext; private Lesson currentLesson;
private AbstractLesson currentLesson;
/** public WebSession() {
* Constructor for the WebSession object
*
* @param webgoatContext a {@link org.owasp.webgoat.session.WebgoatContext} object.
*/
public WebSession(WebgoatContext webgoatContext) {
this.webgoatContext = webgoatContext;
this.currentUser = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); this.currentUser = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
} }
/**
* <p> getConnection. </p>
*
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
* @return a {@link java.sql.Connection} object.
* @throws java.sql.SQLException if any.
*/
public static synchronized Connection getConnection(WebSession s) throws SQLException {
return DatabaseUtilities.getConnection(s);
}
/**
* <p> returnConnection. </p>
*
* @param s a {@link org.owasp.webgoat.session.WebSession} object.
*/
public static void returnConnection(WebSession s) {
DatabaseUtilities.returnConnection(s.getUserName());
}
/** /**
* <p> Setter for the field <code>currentScreen</code>. </p> * <p> Setter for the field <code>currentScreen</code>. </p>
* *
* @param lesson current lesson * @param lesson current lesson
*/ */
public void setCurrentLesson(AbstractLesson lesson) { public void setCurrentLesson(Lesson lesson) {
this.currentLesson = lesson; this.currentLesson = lesson;
} }
/** /**
* <p> getCurrentLesson. </p> * <p> getCurrentLesson. </p>
* *
* @return a {@link org.owasp.webgoat.lessons.AbstractLesson} object. * @return a {@link Lesson} object.
*/ */
public AbstractLesson getCurrentLesson() { public Lesson getCurrentLesson() {
return this.currentLesson; return this.currentLesson;
} }
@ -100,13 +73,4 @@ public class WebSession {
public String getUserName() { public String getUserName() {
return currentUser.getUsername(); return currentUser.getUsername();
} }
/**
* <p> Getter for the field <code>webgoatContext</code>. </p>
*
* @return a {@link org.owasp.webgoat.session.WebgoatContext} object.
*/
public WebgoatContext getWebgoatContext() {
return webgoatContext;
}
} }

View File

@ -1,187 +0,0 @@
package org.owasp.webgoat.session;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* <p>WebgoatContext class.</p>
*
* @version $Id: $Id
* @author dm
*/
@Configuration
public class WebgoatContext {
@Value("${webgoat.database.connection.string}")
private String databaseConnectionString;
private String realConnectionString = null;
@Value("${webgoat.database.driver}")
private String databaseDriver;
private String databaseUser;
private String databasePassword;
private boolean showCookies = false;
private boolean showParams = false;
private boolean showRequest = false;
private boolean showSource = false;
private boolean showSolution = false;
private boolean enterprise = false;
private boolean codingExercises = false;
@Value("${webgoat.feedback.address}")
private String feedbackAddress;
@Value("${webgoat.feedback.address.html}")
private String feedbackAddressHTML = "";
private boolean isDebug = false;
@Value("${webgoat.default.language}")
private String defaultLanguage;
/**
* returns the connection string with the real path to the database
* directory inserted at the word PATH
*
* @return The databaseConnectionString value
*/
public String getDatabaseConnectionString() {
return this.databaseConnectionString;
}
/**
* Gets the databaseDriver attribute of the WebSession object
*
* @return The databaseDriver value
*/
public String getDatabaseDriver() {
return (databaseDriver);
}
/**
* Gets the databaseUser attribute of the WebSession object
*
* @return The databaseUser value
*/
public String getDatabaseUser() {
return (databaseUser);
}
/**
* Gets the databasePassword attribute of the WebSession object
*
* @return The databasePassword value
*/
public String getDatabasePassword() {
return (databasePassword);
}
/**
* <p>isEnterprise.</p>
*
* @return a boolean.
*/
public boolean isEnterprise() {
return enterprise;
}
/**
* <p>isCodingExercises.</p>
*
* @return a boolean.
*/
public boolean isCodingExercises() {
return codingExercises;
}
/**
* <p>Getter for the field <code>feedbackAddress</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getFeedbackAddress() {
return feedbackAddress;
}
/**
* <p>Getter for the field <code>feedbackAddressHTML</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getFeedbackAddressHTML() {
return feedbackAddressHTML;
}
/**
* <p>isDebug.</p>
*
* @return a boolean.
*/
public boolean isDebug() {
return isDebug;
}
/**
* <p>isShowCookies.</p>
*
* @return a boolean.
*/
public boolean isShowCookies() {
return showCookies;
}
/**
* <p>isShowParams.</p>
*
* @return a boolean.
*/
public boolean isShowParams() {
return showParams;
}
/**
* <p>isShowRequest.</p>
*
* @return a boolean.
*/
public boolean isShowRequest() {
return showRequest;
}
/**
* <p>isShowSource.</p>
*
* @return a boolean.
*/
public boolean isShowSource() {
return showSource;
}
/**
* <p>isShowSolution.</p>
*
* @return a boolean.
*/
public boolean isShowSolution() {
return showSolution;
}
/**
* <p>Getter for the field <code>defaultLanguage</code>.</p>
*
* @return a {@link java.lang.String} object.
*/
public String getDefaultLanguage() {
return defaultLanguage;
}
}

View File

@ -1,17 +1,12 @@
package org.owasp.webgoat.users; package org.owasp.webgoat.users;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import javax.persistence.*; import javax.persistence.*;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -54,19 +49,21 @@ public class LessonTracker {
@Getter @Getter
private String lessonName; private String lessonName;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private final Set<Assignment> solvedAssignments = Sets.newHashSet(); private final Set<Assignment> solvedAssignments = new HashSet<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private final Set<Assignment> allAssignments = Sets.newHashSet(); private final Set<Assignment> allAssignments = new HashSet<>();
@Getter @Getter
private int numberOfAttempts = 0; private int numberOfAttempts = 0;
@Version
private Integer version;
private LessonTracker() { private LessonTracker() {
//JPA //JPA
} }
public LessonTracker(AbstractLesson lesson) { public LessonTracker(Lesson lesson) {
lessonName = lesson.getId(); lessonName = lesson.getId();
allAssignments.addAll(lesson.getAssignments()); allAssignments.addAll(lesson.getAssignments() == null ? List.of() : lesson.getAssignments());
} }
public Optional<Assignment> getAssignment(String name) { public Optional<Assignment> getAssignment(String name) {

View File

@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid; import javax.validation.Valid;
@ -32,8 +33,7 @@ public class RegistrationController {
} }
@PostMapping("/register.mvc") @PostMapping("/register.mvc")
@SneakyThrows public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) throws ServletException {
public String registration(@ModelAttribute("userForm") @Valid UserForm userForm, BindingResult bindingResult, HttpServletRequest request) {
userValidator.validate(userForm, bindingResult); userValidator.validate(userForm, bindingResult);
if (bindingResult.hasErrors()) { if (bindingResult.hasErrors()) {

View File

@ -1,6 +1,5 @@
package org.owasp.webgoat.users; package org.owasp.webgoat.users;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import org.owasp.webgoat.i18n.PluginMessages; import org.owasp.webgoat.i18n.PluginMessages;
@ -8,6 +7,7 @@ import org.owasp.webgoat.session.Course;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -36,7 +36,7 @@ public class Scoreboard {
@GetMapping("/scoreboard-data") @GetMapping("/scoreboard-data")
public List<Ranking> getRankings() { public List<Ranking> getRankings() {
List<WebGoatUser> allUsers = userRepository.findAll(); List<WebGoatUser> allUsers = userRepository.findAll();
List<Ranking> rankings = Lists.newArrayList(); List<Ranking> rankings = new ArrayList<>();
for (WebGoatUser user : allUsers) { for (WebGoatUser user : allUsers) {
UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername()); UserTracker userTracker = userTrackerRepository.findByUser(user.getUsername());
rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker))); rankings.add(new Ranking(user.getUsername(), challengesSolved(userTracker)));
@ -45,7 +45,7 @@ public class Scoreboard {
} }
private List<String> challengesSolved(UserTracker userTracker) { private List<String> challengesSolved(UserTracker userTracker) {
List<String> challenges = Lists.newArrayList("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5", "Challenge6", "Challenge7", "Challenge8", "Challenge9"); List<String> challenges = List.of("Challenge1", "Challenge2", "Challenge3", "Challenge4", "Challenge5", "Challenge6", "Challenge7", "Challenge8", "Challenge9");
return challenges.stream() return challenges.stream()
.map(c -> userTracker.getLessonTracker(c)) .map(c -> userTracker.getLessonTracker(c))
.filter(l -> l.isPresent()).map(l -> l.get()) .filter(l -> l.isPresent()).map(l -> l.get())

View File

@ -16,8 +16,8 @@ import javax.validation.constraints.Size;
public class UserForm { public class UserForm {
@NotNull @NotNull
@Size(min=6, max=20) @Size(min = 6, max = 45)
@Pattern(regexp = "[a-zA-Z0-9-]*", message = "can only contain letters, digits, and -") @Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
private String username; private String username;
@NotNull @NotNull
@Size(min = 6, max = 10) @Size(min = 6, max = 10)

View File

@ -30,14 +30,26 @@ public class UserService implements UserDetailsService {
} }
public void addUser(String username, String password) { public void addUser(String username, String password) {
//get user if there exists one by the name
WebGoatUser webGoatUser = userRepository.findByUsername(username);
//if user exists it will be updated, otherwise created
userRepository.save(new WebGoatUser(username, password)); userRepository.save(new WebGoatUser(username, password));
//if user previously existed it will not get another tracker
if (webGoatUser == null) {
userTrackerRepository.save(new UserTracker(username)); userTrackerRepository.save(new UserTracker(username));
} }
}
public void addUser(String username, String password, String role) { public void addUser(String username, String password, String role) {
//get user if there exists one by the name
WebGoatUser webGoatUser = userRepository.findByUsername(username);
//if user exists it will be updated, otherwise created
userRepository.save(new WebGoatUser(username, password, role)); userRepository.save(new WebGoatUser(username, password, role));
//if user previously existed it will not get another tracker
if (webGoatUser == null) {
userTrackerRepository.save(new UserTracker(username)); userTrackerRepository.save(new UserTracker(username));
} }
}
public List<WebGoatUser> getAllUsers() { public List<WebGoatUser> getAllUsers() {
return userRepository.findAll(); return userRepository.findAll();

View File

@ -1,14 +1,12 @@
package org.owasp.webgoat.users; package org.owasp.webgoat.users;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.owasp.webgoat.lessons.AbstractLesson; import org.owasp.webgoat.lessons.Lesson;
import org.owasp.webgoat.lessons.Assignment; import org.owasp.webgoat.lessons.Assignment;
import javax.persistence.*; import javax.persistence.*;
import java.util.List; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -55,7 +53,7 @@ public class UserTracker {
@Column(name = "username") @Column(name = "username")
private String user; private String user;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private Set<LessonTracker> lessonTrackers = Sets.newHashSet(); private Set<LessonTracker> lessonTrackers = new HashSet<>();
private UserTracker() {} private UserTracker() {}
@ -69,7 +67,7 @@ public class UserTracker {
* @param lesson the lesson * @param lesson the lesson
* @return a lesson tracker created if not already present * @return a lesson tracker created if not already present
*/ */
public LessonTracker getLessonTracker(AbstractLesson lesson) { public LessonTracker getLessonTracker(Lesson lesson) {
Optional<LessonTracker> lessonTracker = lessonTrackers Optional<LessonTracker> lessonTracker = lessonTrackers
.stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst(); .stream().filter(l -> l.getLessonName().equals(lesson.getId())).findFirst();
if (!lessonTracker.isPresent()) { if (!lessonTracker.isPresent()) {
@ -91,18 +89,18 @@ public class UserTracker {
return lessonTrackers.stream().filter(l -> l.getLessonName().equals(id)).findFirst(); return lessonTrackers.stream().filter(l -> l.getLessonName().equals(id)).findFirst();
} }
public void assignmentSolved(AbstractLesson lesson, String assignmentName) { public void assignmentSolved(Lesson lesson, String assignmentName) {
LessonTracker lessonTracker = getLessonTracker(lesson); LessonTracker lessonTracker = getLessonTracker(lesson);
lessonTracker.incrementAttempts(); lessonTracker.incrementAttempts();
lessonTracker.assignmentSolved(assignmentName); lessonTracker.assignmentSolved(assignmentName);
} }
public void assignmentFailed(AbstractLesson lesson) { public void assignmentFailed(Lesson lesson) {
LessonTracker lessonTracker = getLessonTracker(lesson); LessonTracker lessonTracker = getLessonTracker(lesson);
lessonTracker.incrementAttempts(); lessonTracker.incrementAttempts();
} }
public void reset(AbstractLesson al) { public void reset(Lesson al) {
LessonTracker lessonTracker = getLessonTracker(al); LessonTracker lessonTracker = getLessonTracker(al);
lessonTracker.reset(); lessonTracker.reset();
} }

View File

@ -16,8 +16,8 @@ public class UserValidator implements Validator {
private final UserRepository userRepository; private final UserRepository userRepository;
@Override @Override
public boolean supports(Class<?> aClass) { public boolean supports(Class<?> clazz) {
return UserForm.class.equals(aClass); return UserForm.class.equals(clazz);
} }
@Override @Override

View File

@ -1,26 +1,32 @@
server.error.include-stacktrace=always server.error.include-stacktrace=always
server.error.path=/error.html server.error.path=/error.html
server.session.timeout=600 server.servlet.context-path=/WebGoat
server.contextPath=/WebGoat server.servlet.session.persistent=false
server.port=8080 server.port=${WEBGOAT_PORT:8080}
server.address=127.0.0.1 server.address=${WEBGOAT_HOST:127.0.0.1}
spring.datasource.url=jdbc:hsqldb:hsql://localhost:9001/webgoat
spring.jpa.hibernate.ddl-auto=update server.ssl.key-store-type=${WEBGOAT_KEYSTORE_TYPE:PKCS12}
server.ssl.key-store=${WEBGOAT_KEYSTORE:classpath:goatkeystore.pkcs12}
server.ssl.key-store-password=${WEBGOAT_KEYSTORE_PASSWORD:password}
server.ssl.key-alias=${WEBGOAT_KEY_ALIAS:goat}
server.ssl.enabled=${WEBGOAT_SSLENABLED:false}
hsqldb.port=${WEBGOAT_HSQLPORT:9001}
spring.datasource.url=jdbc:hsqldb:hsql://${server.address}:${hsqldb.port}/webgoat
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.jpa.properties.hibernate.default_schema=CONTAINER
logging.level.org.thymeleaf=INFO
logging.level.org.thymeleaf.TemplateEngine.CONFIG=INFO
logging.level.org.thymeleaf.TemplateEngine.TIMER=INFO
logging.level.org.thymeleaf.TemplateEngine.cache.TEMPLATE_CACHE=INFO
logging.level.org.springframework.web=INFO
logging.level.org.springframework=INFO logging.level.org.springframework=INFO
logging.level.org.springframework.boot.devtools=INFO logging.level.org.springframework.boot.devtools=INFO
logging.level.org.owasp=DEBUG logging.level.org.owasp=DEBUG
logging.level.org.owasp.webgoat=TRACE logging.level.org.owasp.webgoat=DEBUG
# Needed for creating a vulnerable web application
security.enable-csrf=false
spring.resources.cache-period=0
spring.thymeleaf.cache=false
webgoat.start.hsqldb=true webgoat.start.hsqldb=true
webgoat.clean=false webgoat.clean=false
@ -32,11 +38,10 @@ webgoat.email=webgoat@owasp.org
webgoat.emaillist=owasp-webgoat@lists.owasp.org webgoat.emaillist=owasp-webgoat@lists.owasp.org
webgoat.feedback.address=webgoat@owasp.org webgoat.feedback.address=webgoat@owasp.org
webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A> webgoat.feedback.address.html=<A HREF=mailto:webgoat@owasp.org>webgoat@owasp.org</A>
webgoat.database.driver=org.hsqldb.jdbcDriver
webgoat.database.connection.string=jdbc:hsqldb:mem:{USER} webgoat.database.connection.string=jdbc:hsqldb:mem:{USER}
webgoat.default.language=en webgoat.default.language=en
webwolf.host=${WEBWOLF_HOST:localhost} webwolf.host=${WEBWOLF_HOST:127.0.0.1}
webwolf.port=${WEBWOLF_PORT:9090} webwolf.port=${WEBWOLF_PORT:9090}
webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf webwolf.url=http://${webwolf.host}:${webwolf.port}/WebWolf
webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing webwolf.url.landingpage=http://${webwolf.host}:${webwolf.port}/landing

View File

@ -0,0 +1,64 @@
CREATE SCHEMA CONTAINER;
CREATE SEQUENCE CONTAINER.HIBERNATE_SEQUENCE AS INTEGER START WITH 1;
CREATE TABLE CONTAINER.ASSIGNMENT (
ID BIGINT NOT NULL PRIMARY KEY,
NAME VARCHAR(255),
PATH VARCHAR(255)
);
CREATE TABLE CONTAINER.LESSON_TRACKER(
ID BIGINT NOT NULL PRIMARY KEY,
LESSON_NAME VARCHAR(255),
NUMBER_OF_ATTEMPTS INTEGER NOT NULL
);
CREATE TABLE CONTAINER.LESSON_TRACKER_ALL_ASSIGNMENTS(
LESSON_TRACKER_ID BIGINT NOT NULL,
ALL_ASSIGNMENTS_ID BIGINT NOT NULL,
PRIMARY KEY(LESSON_TRACKER_ID,ALL_ASSIGNMENTS_ID),
CONSTRAINT FKNHIDKE27BCJHI8C7WJ9QW6Y3Q FOREIGN KEY(ALL_ASSIGNMENTS_ID) REFERENCES CONTAINER.ASSIGNMENT(ID),
CONSTRAINT FKBM51QSDJ7N17O2DNATGAMW7D FOREIGN KEY(LESSON_TRACKER_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
CONSTRAINT UK_SYGJY2S8O8DDGA2K5YHBMUVEA UNIQUE(ALL_ASSIGNMENTS_ID)
);
CREATE TABLE CONTAINER.LESSON_TRACKER_SOLVED_ASSIGNMENTS(
LESSON_TRACKER_ID BIGINT NOT NULL,
SOLVED_ASSIGNMENTS_ID BIGINT NOT NULL,
PRIMARY KEY(LESSON_TRACKER_ID,SOLVED_ASSIGNMENTS_ID),
CONSTRAINT FKPP850U1MG09YKKL2EQGM0TRJK FOREIGN KEY(SOLVED_ASSIGNMENTS_ID) REFERENCES CONTAINER.ASSIGNMENT(ID),
CONSTRAINT FKNKRWGA1UHLOQ6732SQXHXXSCR FOREIGN KEY(LESSON_TRACKER_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
CONSTRAINT UK_9WFYDUY3TVE1XD05LWOUEG0C1 UNIQUE(SOLVED_ASSIGNMENTS_ID)
);
CREATE TABLE CONTAINER.USER_TRACKER(
ID BIGINT NOT NULL PRIMARY KEY,
USERNAME VARCHAR(255)
);
CREATE TABLE CONTAINER.USER_TRACKER_LESSON_TRACKERS(
USER_TRACKER_ID BIGINT NOT NULL,
LESSON_TRACKERS_ID BIGINT NOT NULL,
PRIMARY KEY(USER_TRACKER_ID,LESSON_TRACKERS_ID),
CONSTRAINT FKQJSTCA3YND3OHP35D50PNUH3H FOREIGN KEY(LESSON_TRACKERS_ID) REFERENCES CONTAINER.LESSON_TRACKER(ID),
CONSTRAINT FKC9GX8INK7LRC79XC77O2MN9KE FOREIGN KEY(USER_TRACKER_ID) REFERENCES CONTAINER.USER_TRACKER(ID),
CONSTRAINT UK_5D8N5I3IC26CVF7DF7N95DOJB UNIQUE(LESSON_TRACKERS_ID)
);
CREATE TABLE CONTAINER.WEB_GOAT_USER(
USERNAME VARCHAR(255) NOT NULL PRIMARY KEY,
PASSWORD VARCHAR(255),
ROLE VARCHAR(255)
);
CREATE TABLE CONTAINER.EMAIL(
ID BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,
CONTENTS VARCHAR(1024),
RECIPIENT VARCHAR(255),
SENDER VARCHAR(255),
TIME TIMESTAMP,
TITLE VARCHAR(255)
);
ALTER TABLE CONTAINER.EMAIL ALTER COLUMN ID RESTART WITH 2;

View File

@ -0,0 +1 @@
ALTER TABLE CONTAINER.LESSON_TRACKER ADD VERSION INTEGER;

View File

@ -1001,9 +1001,15 @@ cookie-container {
margin: 3px; margin: 3px;
} }
@keyframes blink {
50% { border-color: white; }
}
.cur-page { .cur-page {
border-bottom: 2px solid #000; animation: blink 1.5s 2 forwards;
border: 3px solid blue;
color:#aaa; color:#aaa;
background-color: lightsalmon;
} }
span.show-next-page, span.show-prev-page { span.show-next-page, span.show-prev-page {

View File

@ -0,0 +1,67 @@
.attack-container.quiz {
background: none;
border: none;
}
#q_container p {
font-weight: bold;
}
#q_container .quiz_question {
border: solid 2px white;
padding: 4px;
margin: 5px 2px 20px 2px;
box-shadow: 0px 1px 3px 1px #e4e4e4;
}
#q_container .quiz_question label {
font-weight: normal;
position: relative;
top: -2px;
}
#q_container .quiz_question input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
border: 2px solid #dadada;
background: white;
width: 15px;
height: 15px;
margin-right: 6px;
}
#q_container .quiz_question input:checked {
background: #51b7ff;
}
#q_container .quiz_question input:hover,
#q_container .quiz_question label:hover {
cursor: pointer;
}
#q_container .quiz_question.correct {
border: solid 2px #ddf7dd;
background: #ddf7dd;
transition: all 300ms ease-in-out;
}
#q_container .quiz_question.incorrect {
border: solid 2px #f5d3d3;
background: #f5d3d3;
transition: all 300ms ease-in-out;
}
input[name='Quiz_solutions'] {
background: white;
border: 1px solid gray;
padding: 7px 10px;
transition: 300ms all ease-in-out;
}
input[name='Quiz_solutions']:hover {
background: #51b7ff;
color: white;
border-color: white;
transition: 300ms all ease-in-out;
}

View File

@ -0,0 +1,6 @@
*Issue #, if available:*
*Description of changes:*
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

View File

@ -0,0 +1,4 @@
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.

View File

@ -0,0 +1,61 @@
# Contributing Guidelines
Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
documentation, we greatly value feedback and contributions from our community.
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
information to effectively respond to your bug report or contribution.
## Reporting Bugs/Feature Requests
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
When filing an issue, please check [existing open](https://github.com/ajaxorg/ace-builds/issues), or [recently closed](https://github.com/ajaxorg/ace-builds/issues?utf8=%E2%9C%93&q=is%3Aissue%20is%3Aclosed%20), issues to make sure somebody else hasn't already
reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
* A reproducible test case or series of steps
* The version of our code being used
* Any modifications you've made relevant to the bug
* Anything unusual about your environment or deployment
## Contributing via Pull Requests
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
1. You are working against the latest source on the *master* branch.
2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
To send us a pull request, please:
1. Fork the repository.
2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
3. Ensure local tests pass.
4. Commit to your fork using clear commit messages.
5. Send us a pull request, answering any default questions in the pull request interface.
6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
## Finding contributions to work on
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels ((enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any ['help wanted'](https://github.com/ajaxorg/ace-builds/labels/help%20wanted) issues is a great place to start.
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.
## Security issue notifications
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
## Licensing
See the [LICENSE](https://github.com/ajaxorg/ace-builds/blob/master/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.
We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes.

View File

@ -0,0 +1,426 @@
2018.08.07 Version 1.4.1
* fix regression in autocomplete
2018.08.06 Version 1.4.0
* remove usage of innerHTML
* improved handling of textinput for IME and mobile
* add support for relative line numbers
* improve autocompletion popup
2018.03.26 Version 1.3.3
* fix regession in static-highlight extension
* use css animation for cursor blinking
2018.03.21 Version 1.3.2
* add experimental support for using ace-builds with webpack
2018.02.11 Version 1.3.1
* fixed regression with selectionChange event not firing some times
* improved handling of non-ascii characters in vim normal mode
2018.01.31 Version 1.3.0
* added copy copyWithEmptySelection option
* improved undoManager
* improved settings_menu plugin
* improved handling of files with very long lines
* fixed bug with scrolling editor out of view in transformed elements
2017.10.17 Version 1.2.9
* added support for bidirectional text, with monospace font (Alex Shensis)
* added support for emoji 😊
* new language modes
- Red (Toomas Vooglaid)
- CSound (Nathan Whetsell)
- JSSM (John Haugeland)
* New Themes
- Dracula (Austin Schwartz)
2017.07.02 Version 1.2.8
* Fixed small bugs in searchbox and autocompleter
2017.06.18 Version 1.2.7
* Added Support for arrow keys on external IPad keyboard (Emanuele Tamponi)
* added match counter to searchbox extension
- implemented higlighting of multiline strings in yaml mode (Maxim Trushin)
- improved haml syntax highlighter (Andrés Álvarez)
2016.12.03 Version 1.2.6
* Fixed IME handling on new Chrome
* Support for php 7 in the syntax checker
2016.08.16 Version 1.2.5
* Fixed regression in noconflict mode
2016.07.27 Version 1.2.4
* Maintenance release with several new modes and small bugfixes
2016.01.17 Version 1.2.3
* Bugfixes
- fix memory leak in setSession (Tyler Stalder)
- double click not working on linux/mac
* new language modes
- reStructuredText (Robin Jarry)
- NSIS (Jan T. Sott)
2015.10.28 Version 1.2.1
* new language modes
- Swift
- JSX
2015.07.11 Version 1.2.0
* New Features
- Indented soft wrap (danyaPostfactum)
- Rounded borders on selections
* API Changes
- unified delta types `{start, end, action, lines}` (Alden Daniels https://github.com/ajaxorg/ace/pull/1745)
- "change" event listeners on session and editor get delta objects directly
* new language modes
- SQLServer (Morgan Yarbrough)
2015.04.03 Version 1.1.9
- Small Enhancements and Bugfixes
2014.11.08 Version 1.1.8
* API Changes
- `editor.commands.commandKeyBinding` now contains direct map from keys to commands instead of grouping them by hashid
* New Features
- Improved autoindent for html and php modes (Adam Jimenez)
- Find All from searchbox (Colton Voege)
* new language modes
- Elixir, Elm
2014.09.21 Version 1.1.7
* Bugfixes
- fix several bugs in autocompletion
- workaround for inaccurate getBoundingClientRect on chrome 37
2014.08.17 Version 1.1.6
* Bugfixes
- fix regression in double tap to highlight
- Improved Latex Mode (Daniel Felder)
* API Changes
- editor.destroy destroys editor.session too (call editor.setSession(null) to prevent that)
* new language modes
- Praat (José Joaquín Atria)
- Eiffel (Victorien Elvinger)
- G-code (Adam Joseph Cook)
2014.07.09 Version 1.1.5
* Bugfixes
- fix regression in autocomplete popup
* new language modes
- gitignore (Devon Carew)
2014.07.01 Version 1.1.4
* New Features
- Highlight matching tags (Adam Jimenez)
- Improved jump to matching command (Adam Jimenez)
* new language modes
- AppleScript (Yaogang Lian)
- Vala
2014.03.08 Version 1.1.3
* New Features
- Allow syntax checkers to be loaded from CDN (Derk-Jan Hartman)
- Add ColdFusion behavior (Abram Adams)
- add showLineNumbers option
- Add html syntax checker (danyaPostfactum)
* new language modes
- Gherkin (Patrick Nevels)
- Smarty
2013.12.02 Version 1.1.2
* New Features
- Accessibility Theme for Ace (Peter Xiao)
- use snipetManager for expanding emmet snippets
- update jshint to 2.1.4
- improve php syntax checker (jdalegonzalez)
- add option for autoresizing
- add option for autohiding vertical scrollbar
- improvements to highlighting of xml like languages (danyaPostfactum)
- add support for autocompletion and snippets (gjtorikyan danyaPostfactum and others)
- add option to merge similar changes in undo history
- add scrollPastEnd option
- use html5 dragndrop for text dragging (danyaPostfactum)
* API Changes
- fixed typo in HashHandler commmandManager
* new language modes
- Nix (Zef Hemel)
- Protobuf (Zef Hemel)
- Soy
- Handlebars
2013.06.04 Version 1.1.1
- Improved emacs keybindings (Robert Krahn)
- Added markClean, isClean methods to UndoManager (Joonsoo Jeon)
- Do not allow `Toggle comments` command to remove spaces from indentation
- Softer colors for indent guides in dark themes
* new language modes
- Ada
- Assembly_x86
- Cobol
- D
- ejs
- MATLAB
- MySQL
- Twig
- Verilog
2013.05.01, Version 1.1.0
* API Changes
- Default position of the editor container is changed to relative. Add `.ace_editor {position: absolute}` css rule to restore old behavior
- Changed default line-height to `normal` to not conflict with bootstrap. Use `line-height: inherit` for old behavior.
- Changed marker types accepted by session.addMarker. It now accepts "text"|"line"|"fullLine"|"screenLine"
- Internal classnames used by editor were made more consistent
- Introduced `editor.setOption/getOption/setOptions/getOptions` methods
- Introduced positionToIndex, indexToPosition methods
* New Features
- Improved emacs mode (chetstone)
with Incremental search and Occur modes (Robert Krahn)
- Improved ime handling
- Searchbox (Vlad Zinculescu)
- Added elastic tabstops lite extension (Garen Torikian)
- Added extension for whitespace manipulation
- Added extension for enabling spellchecking from contextmenu
- Added extension for displaying available keyboard shortcuts (Matthew Christopher Kastor-Inare III)
- Added extension for displaying options panel (Matthew Christopher Kastor-Inare III)
- Added modelist extension (Matthew Christopher Kastor-Inare III)
- Improved toggleCommentLines and added ToggleCommentBlock command
- `:;` pairing in CSS mode (danyaPostfactum)
- Added suppoert for Delete and SelectAll from context menu (danyaPostfactum)
- Make wrapping behavior optional
- Selective bracket insertion/skipping
- Added commands for increase/decrease numbers, sort lines (Vlad Zinculescu)
- Folding for Markdown, Lua, LaTeX
- Selective bracket insertion/skipping for C-like languages
* Many new languages
- Scheme (Mu Lei)
- Dot (edwardsp)
- FreeMarker (nguillaumin)
- Tiny Mushcode (h3rb)
- Velocity (Ryan Griffith)
- TOML (Garen Torikian)
- LSL (Nemurimasu Neiro, Builders Brewery)
- Curly (Libo Cannici)
- vbScript (Jan Jongboom)
- R (RStudio)
- ABAP
- Lucene (Graham Scott)
- Haml (Garen Torikian)
- Objective-C (Garen Torikian)
- Makefile (Garen Torikian)
- TypeScript (Garen Torikian)
- Lisp (Garen Torikian)
- Stylus (Garen Torikian)
- Dart (Garen Torikian)
* Live syntax checks
- PHP (danyaPostfactum)
- Lua
* New Themes
- Chaos
- Terminal
2012.09.17, Version 1.0.0
* New Features
- Multiple cursors and selections (https://c9.io/site/blog/2012/08/be-an-armenian-warrior-with-block-selection-on-steroids/)
- Fold buttons displayed in the gutter
- Indent Guides
- Completely reworked vim mode (Sergi Mansilla)
- Improved emacs keybindings
- Autoclosing of html tags (danyaPostfactum)
* 20 New language modes
- Coldfusion (Russ)
- Diff
- GLSL (Ed Mackey)
- Go (Davide Saurino)
- Haxe (Jason O'Neil)
- Jade (Garen Torikian)
- jsx (Syu Kato)
- LaTeX (James Allen)
- Less (John Roepke)
- Liquid (Bernie Telles)
- Lua (Lee Gao)
- LuaPage (Choonster)
- Markdown (Chris Spencer)
- PostgreSQL (John DeSoi)
- Powershell (John Kane)
- Sh (Richo Healey)
- SQL (Jonathan Camile)
- Tcl (Cristoph Hochreiner)
- XQuery (William Candillion)
- Yaml (Meg Sharkey)
* Live syntax checks
- for XQuery and JSON
* New Themes
- Ambiance (Irakli Gozalishvili)
- Dreamweaver (Adam Jimenez)
- Github (bootstraponline)
- Tommorrow themes (https://github.com/chriskempson/tomorrow-theme)
- XCode
* Many Small Enhancements and Bugfixes
2011.08.02, Version 0.2.0
* Split view (Julian Viereck)
- split editor area horizontally or vertivally to show two files at the same
time
* Code Folding (Julian Viereck)
- Unstructured code folding
- Will be the basis for language aware folding
* Mode behaviours (Chris Spencer)
- Adds mode specific hooks which allow transformations of entered text
- Autoclosing of braces, paranthesis and quotation marks in C style modes
- Autoclosing of angular brackets in XML style modes
* New language modes
- Clojure (Carin Meier)
- C# (Rob Conery)
- Groovy (Ben Tilford)
- Scala (Ben Tilford)
- JSON
- OCaml (Sergi Mansilla)
- Perl (Panagiotis Astithas)
- SCSS/SASS (Andreas Madsen)
- SVG
- Textile (Kelley van Evert)
- SCAD (Jacob Hansson)
* Live syntax checks
- Lint for CSS using CSS Lint <http://csslint.net/>
- CoffeeScript
* New Themes
- Crimson Editor (iebuggy)
- Merbivore (Michael Schwartz)
- Merbivore soft (Michael Schwartz)
- Solarized dark/light <http://ethanschoonover.com/solarized> (David Alan Hjelle)
- Vibrant Ink (Michael Schwartz)
* Small Features/Enhancements
- Lots of render performance optimizations (Harutyun Amirjanyan)
- Improved Ruby highlighting (Chris Wanstrath, Trent Ogren)
- Improved PHP highlighting (Thomas Hruska)
- Improved CSS highlighting (Sean Kellogg)
- Clicks which cause the editor to be focused don't reset the selection
- Make padding text layer specific so that print margin and active line
highlight are not affected (Irakli Gozalishvili)
- Added setFontSize method
- Improved vi keybindings (Trent Ogren)
- When unfocused make cursor transparent instead of removing it (Harutyun Amirjanyan)
- Support for matching groups in tokenizer with arrays of tokens (Chris Spencer)
* Bug fixes
- Add support for the new OSX scroll bars
- Properly highlight JavaScript regexp literals
- Proper handling of unicode characters in JavaScript identifiers
- Fix remove lines command on last line (Harutyun Amirjanyan)
- Fix scroll wheel sluggishness in Safari
- Make keyboard infrastructure route keys like []^$ the right way (Julian Viereck)
2011.02.14, Version 0.1.6
* Floating Anchors
- An Anchor is a floating pointer in the document.
- Whenever text is inserted or deleted before the cursor, the position of
the cursor is updated
- Usesd for the cursor and selection
- Basis for bookmarks, multiple cursors and snippets in the future
* Extensive support for Cocoa style keybindings on the Mac <https://github.com/ajaxorg/ace/issues/closed#issue/116/comment/767803>
* New commands:
- center selection in viewport
- remove to end/start of line
- split line
- transpose letters
* Refator markers
- Custom code can be used to render markers
- Markers can be in front or behind the text
- Markers are now stored in the session (was in the renderer)
* Lots of IE8 fixes including copy, cut and selections
* Unit tests can also be run in the browser
<https://github.com/ajaxorg/ace/blob/master/lib/ace/test/tests.html>
* Soft wrap can adapt to the width of the editor (Mike Ratcliffe, Joe Cheng)
* Add minimal node server server.js to run the Ace demo in Chrome
* The top level editor.html demo has been renamed to index.html
* Bug fixes
- Fixed gotoLine to consider wrapped lines when calculating where to scroll to (James Allen)
- Fixed isues when the editor was scrolled in the web page (Eric Allam)
- Highlighting of Python string literals
- Syntax rule for PHP comments
2011.02.08, Version 0.1.5
* Add Coffeescript Mode (Satoshi Murakami)
* Fix word wrap bug (Julian Viereck)
* Fix packaged version of the Eclipse mode
* Loading of workers is more robust
* Fix "click selection"
* Allow tokizing empty lines (Daniel Krech)
* Make PageUp/Down behavior more consistent with native OS (Joe Cheng)
2011.02.04, Version 0.1.4
* Add C/C++ mode contributed by Gastón Kleiman
* Fix exception in key input
2011.02.04, Version 0.1.3
* Let the packaged version play nice with requireJS
* Add Ruby mode contributed by Shlomo Zalman Heigh
* Add Java mode contributed by Tom Tasche
* Fix annotation bug
* Changing a document added a new empty line at the end

View File

@ -0,0 +1,24 @@
Copyright (c) 2010, Ajax.org B.V.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Ajax.org B.V. nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,23 @@
Ace (Ajax.org Cloud9 Editor)
============================
[![CDNJS](https://img.shields.io/cdnjs/v/ace.svg)](https://cdnjs.com/libraries/ace)
[![npm](https://img.shields.io/npm/v/ace-builds.svg)](https://www.npmjs.com/package/ace-builds)
Ace is a code editor written in JavaScript.
This repository has only generated files.
If you want to work on ace please go to https://github.com/ajaxorg/ace instead.
here you can find pre-built files for convenience of embedding.
it contains 4 versions
* [src](https://github.com/ajaxorg/ace-builds/tree/master/src) concatenated but not minified
* [src-min](https://github.com/ajaxorg/ace-builds/tree/master/src-min) concatenated and minified with uglify.js
* [src-noconflict](https://github.com/ajaxorg/ace-builds/tree/master/src-noconflict) uses ace.require instead of require
* [src-min-noconflict](https://github.com/ajaxorg/ace-builds/tree/master/src-min-noconflict) concatenated, minified with uglify.js, and uses ace.require instead of require
For a simple way of embedding ace into webpage see [editor.html](https://github.com/ajaxorg/ace-builds/blob/master/editor.html) or list of other [simple examples](https://github.com/ajaxorg/ace-builds/tree/master/demo)
To see ace in action go to [kitchen-sink-demo](http://ajaxorg.github.com/ace-builds/kitchen-sink.html), [scrollable-page-demo](http://ajaxorg.github.com/ace-builds/demo/scrollable-page.html) or [minimal demo](http://ajaxorg.github.com/ace-builds/editor.html),

View File

@ -0,0 +1,215 @@
declare module 'ace-builds/src-noconflict/ext-beautify';
declare module 'ace-builds/src-noconflict/ext-elastic_tabstops_lite';
declare module 'ace-builds/src-noconflict/ext-emmet';
declare module 'ace-builds/src-noconflict/ext-error_marker';
declare module 'ace-builds/src-noconflict/ext-keybinding_menu';
declare module 'ace-builds/src-noconflict/ext-language_tools';
declare module 'ace-builds/src-noconflict/ext-linking';
declare module 'ace-builds/src-noconflict/ext-modelist';
declare module 'ace-builds/src-noconflict/ext-options';
declare module 'ace-builds/src-noconflict/ext-rtl';
declare module 'ace-builds/src-noconflict/ext-searchbox';
declare module 'ace-builds/src-noconflict/ext-settings_menu';
declare module 'ace-builds/src-noconflict/ext-spellcheck';
declare module 'ace-builds/src-noconflict/ext-split';
declare module 'ace-builds/src-noconflict/ext-static_highlight';
declare module 'ace-builds/src-noconflict/ext-statusbar';
declare module 'ace-builds/src-noconflict/ext-textarea';
declare module 'ace-builds/src-noconflict/ext-themelist';
declare module 'ace-builds/src-noconflict/ext-whitespace';
declare module 'ace-builds/src-noconflict/keybinding-emacs';
declare module 'ace-builds/src-noconflict/keybinding-vim';
declare module 'ace-builds/src-noconflict/mode-abap';
declare module 'ace-builds/src-noconflict/mode-abc';
declare module 'ace-builds/src-noconflict/mode-actionscript';
declare module 'ace-builds/src-noconflict/mode-ada';
declare module 'ace-builds/src-noconflict/mode-apache_conf';
declare module 'ace-builds/src-noconflict/mode-applescript';
declare module 'ace-builds/src-noconflict/mode-asciidoc';
declare module 'ace-builds/src-noconflict/mode-asl';
declare module 'ace-builds/src-noconflict/mode-assembly_x86';
declare module 'ace-builds/src-noconflict/mode-autohotkey';
declare module 'ace-builds/src-noconflict/mode-batchfile';
declare module 'ace-builds/src-noconflict/mode-bro';
declare module 'ace-builds/src-noconflict/mode-c9search';
declare module 'ace-builds/src-noconflict/mode-cirru';
declare module 'ace-builds/src-noconflict/mode-clojure';
declare module 'ace-builds/src-noconflict/mode-cobol';
declare module 'ace-builds/src-noconflict/mode-coffee';
declare module 'ace-builds/src-noconflict/mode-coldfusion';
declare module 'ace-builds/src-noconflict/mode-csharp';
declare module 'ace-builds/src-noconflict/mode-csound_document';
declare module 'ace-builds/src-noconflict/mode-csound_orchestra';
declare module 'ace-builds/src-noconflict/mode-csound_score';
declare module 'ace-builds/src-noconflict/mode-csp';
declare module 'ace-builds/src-noconflict/mode-css';
declare module 'ace-builds/src-noconflict/mode-curly';
declare module 'ace-builds/src-noconflict/mode-c_cpp';
declare module 'ace-builds/src-noconflict/mode-d';
declare module 'ace-builds/src-noconflict/mode-dart';
declare module 'ace-builds/src-noconflict/mode-diff';
declare module 'ace-builds/src-noconflict/mode-django';
declare module 'ace-builds/src-noconflict/mode-dockerfile';
declare module 'ace-builds/src-noconflict/mode-dot';
declare module 'ace-builds/src-noconflict/mode-drools';
declare module 'ace-builds/src-noconflict/mode-edifact';
declare module 'ace-builds/src-noconflict/mode-eiffel';
declare module 'ace-builds/src-noconflict/mode-ejs';
declare module 'ace-builds/src-noconflict/mode-elixir';
declare module 'ace-builds/src-noconflict/mode-elm';
declare module 'ace-builds/src-noconflict/mode-erlang';
declare module 'ace-builds/src-noconflict/mode-forth';
declare module 'ace-builds/src-noconflict/mode-fortran';
declare module 'ace-builds/src-noconflict/mode-fsharp';
declare module 'ace-builds/src-noconflict/mode-ftl';
declare module 'ace-builds/src-noconflict/mode-gcode';
declare module 'ace-builds/src-noconflict/mode-gherkin';
declare module 'ace-builds/src-noconflict/mode-gitignore';
declare module 'ace-builds/src-noconflict/mode-glsl';
declare module 'ace-builds/src-noconflict/mode-gobstones';
declare module 'ace-builds/src-noconflict/mode-golang';
declare module 'ace-builds/src-noconflict/mode-graphqlschema';
declare module 'ace-builds/src-noconflict/mode-groovy';
declare module 'ace-builds/src-noconflict/mode-haml';
declare module 'ace-builds/src-noconflict/mode-handlebars';
declare module 'ace-builds/src-noconflict/mode-haskell';
declare module 'ace-builds/src-noconflict/mode-haskell_cabal';
declare module 'ace-builds/src-noconflict/mode-haxe';
declare module 'ace-builds/src-noconflict/mode-hjson';
declare module 'ace-builds/src-noconflict/mode-html';
declare module 'ace-builds/src-noconflict/mode-html_elixir';
declare module 'ace-builds/src-noconflict/mode-html_ruby';
declare module 'ace-builds/src-noconflict/mode-ini';
declare module 'ace-builds/src-noconflict/mode-io';
declare module 'ace-builds/src-noconflict/mode-jack';
declare module 'ace-builds/src-noconflict/mode-jade';
declare module 'ace-builds/src-noconflict/mode-java';
declare module 'ace-builds/src-noconflict/mode-javascript';
declare module 'ace-builds/src-noconflict/mode-json';
declare module 'ace-builds/src-noconflict/mode-jsoniq';
declare module 'ace-builds/src-noconflict/mode-jsp';
declare module 'ace-builds/src-noconflict/mode-jssm';
declare module 'ace-builds/src-noconflict/mode-jsx';
declare module 'ace-builds/src-noconflict/mode-julia';
declare module 'ace-builds/src-noconflict/mode-kotlin';
declare module 'ace-builds/src-noconflict/mode-latex';
declare module 'ace-builds/src-noconflict/mode-less';
declare module 'ace-builds/src-noconflict/mode-liquid';
declare module 'ace-builds/src-noconflict/mode-lisp';
declare module 'ace-builds/src-noconflict/mode-livescript';
declare module 'ace-builds/src-noconflict/mode-logiql';
declare module 'ace-builds/src-noconflict/mode-lsl';
declare module 'ace-builds/src-noconflict/mode-lua';
declare module 'ace-builds/src-noconflict/mode-luapage';
declare module 'ace-builds/src-noconflict/mode-lucene';
declare module 'ace-builds/src-noconflict/mode-makefile';
declare module 'ace-builds/src-noconflict/mode-markdown';
declare module 'ace-builds/src-noconflict/mode-mask';
declare module 'ace-builds/src-noconflict/mode-matlab';
declare module 'ace-builds/src-noconflict/mode-maze';
declare module 'ace-builds/src-noconflict/mode-mel';
declare module 'ace-builds/src-noconflict/mode-mixal';
declare module 'ace-builds/src-noconflict/mode-mushcode';
declare module 'ace-builds/src-noconflict/mode-mysql';
declare module 'ace-builds/src-noconflict/mode-nix';
declare module 'ace-builds/src-noconflict/mode-nsis';
declare module 'ace-builds/src-noconflict/mode-objectivec';
declare module 'ace-builds/src-noconflict/mode-ocaml';
declare module 'ace-builds/src-noconflict/mode-pascal';
declare module 'ace-builds/src-noconflict/mode-perl';
declare module 'ace-builds/src-noconflict/mode-pgsql';
declare module 'ace-builds/src-noconflict/mode-php';
declare module 'ace-builds/src-noconflict/mode-php_laravel_blade';
declare module 'ace-builds/src-noconflict/mode-pig';
declare module 'ace-builds/src-noconflict/mode-plain_text';
declare module 'ace-builds/src-noconflict/mode-powershell';
declare module 'ace-builds/src-noconflict/mode-praat';
declare module 'ace-builds/src-noconflict/mode-prolog';
declare module 'ace-builds/src-noconflict/mode-properties';
declare module 'ace-builds/src-noconflict/mode-protobuf';
declare module 'ace-builds/src-noconflict/mode-puppet';
declare module 'ace-builds/src-noconflict/mode-python';
declare module 'ace-builds/src-noconflict/mode-r';
declare module 'ace-builds/src-noconflict/mode-razor';
declare module 'ace-builds/src-noconflict/mode-rdoc';
declare module 'ace-builds/src-noconflict/mode-red';
declare module 'ace-builds/src-noconflict/mode-redshift';
declare module 'ace-builds/src-noconflict/mode-rhtml';
declare module 'ace-builds/src-noconflict/mode-rst';
declare module 'ace-builds/src-noconflict/mode-ruby';
declare module 'ace-builds/src-noconflict/mode-rust';
declare module 'ace-builds/src-noconflict/mode-sass';
declare module 'ace-builds/src-noconflict/mode-scad';
declare module 'ace-builds/src-noconflict/mode-scala';
declare module 'ace-builds/src-noconflict/mode-scheme';
declare module 'ace-builds/src-noconflict/mode-scss';
declare module 'ace-builds/src-noconflict/mode-sh';
declare module 'ace-builds/src-noconflict/mode-sjs';
declare module 'ace-builds/src-noconflict/mode-slim';
declare module 'ace-builds/src-noconflict/mode-smarty';
declare module 'ace-builds/src-noconflict/mode-snippets';
declare module 'ace-builds/src-noconflict/mode-soy_template';
declare module 'ace-builds/src-noconflict/mode-space';
declare module 'ace-builds/src-noconflict/mode-sparql';
declare module 'ace-builds/src-noconflict/mode-sql';
declare module 'ace-builds/src-noconflict/mode-sqlserver';
declare module 'ace-builds/src-noconflict/mode-stylus';
declare module 'ace-builds/src-noconflict/mode-svg';
declare module 'ace-builds/src-noconflict/mode-swift';
declare module 'ace-builds/src-noconflict/mode-tcl';
declare module 'ace-builds/src-noconflict/mode-terraform';
declare module 'ace-builds/src-noconflict/mode-tex';
declare module 'ace-builds/src-noconflict/mode-text';
declare module 'ace-builds/src-noconflict/mode-textile';
declare module 'ace-builds/src-noconflict/mode-toml';
declare module 'ace-builds/src-noconflict/mode-tsx';
declare module 'ace-builds/src-noconflict/mode-turtle';
declare module 'ace-builds/src-noconflict/mode-twig';
declare module 'ace-builds/src-noconflict/mode-typescript';
declare module 'ace-builds/src-noconflict/mode-vala';
declare module 'ace-builds/src-noconflict/mode-vbscript';
declare module 'ace-builds/src-noconflict/mode-velocity';
declare module 'ace-builds/src-noconflict/mode-verilog';
declare module 'ace-builds/src-noconflict/mode-vhdl';
declare module 'ace-builds/src-noconflict/mode-wollok';
declare module 'ace-builds/src-noconflict/mode-xml';
declare module 'ace-builds/src-noconflict/mode-xquery';
declare module 'ace-builds/src-noconflict/mode-yaml';
declare module 'ace-builds/src-noconflict/theme-ambiance';
declare module 'ace-builds/src-noconflict/theme-chaos';
declare module 'ace-builds/src-noconflict/theme-chrome';
declare module 'ace-builds/src-noconflict/theme-clouds';
declare module 'ace-builds/src-noconflict/theme-clouds_midnight';
declare module 'ace-builds/src-noconflict/theme-cobalt';
declare module 'ace-builds/src-noconflict/theme-crimson_editor';
declare module 'ace-builds/src-noconflict/theme-dawn';
declare module 'ace-builds/src-noconflict/theme-dracula';
declare module 'ace-builds/src-noconflict/theme-dreamweaver';
declare module 'ace-builds/src-noconflict/theme-eclipse';
declare module 'ace-builds/src-noconflict/theme-github';
declare module 'ace-builds/src-noconflict/theme-gob';
declare module 'ace-builds/src-noconflict/theme-gruvbox';
declare module 'ace-builds/src-noconflict/theme-idle_fingers';
declare module 'ace-builds/src-noconflict/theme-iplastic';
declare module 'ace-builds/src-noconflict/theme-katzenmilch';
declare module 'ace-builds/src-noconflict/theme-kr_theme';
declare module 'ace-builds/src-noconflict/theme-kuroir';
declare module 'ace-builds/src-noconflict/theme-merbivore';
declare module 'ace-builds/src-noconflict/theme-merbivore_soft';
declare module 'ace-builds/src-noconflict/theme-monokai';
declare module 'ace-builds/src-noconflict/theme-mono_industrial';
declare module 'ace-builds/src-noconflict/theme-pastel_on_dark';
declare module 'ace-builds/src-noconflict/theme-solarized_dark';
declare module 'ace-builds/src-noconflict/theme-solarized_light';
declare module 'ace-builds/src-noconflict/theme-sqlserver';
declare module 'ace-builds/src-noconflict/theme-terminal';
declare module 'ace-builds/src-noconflict/theme-textmate';
declare module 'ace-builds/src-noconflict/theme-tomorrow';
declare module 'ace-builds/src-noconflict/theme-tomorrow_night';
declare module 'ace-builds/src-noconflict/theme-tomorrow_night_blue';
declare module 'ace-builds/src-noconflict/theme-tomorrow_night_bright';
declare module 'ace-builds/src-noconflict/theme-tomorrow_night_eighties';
declare module 'ace-builds/src-noconflict/theme-twilight';
declare module 'ace-builds/src-noconflict/theme-vibrant_ink';
declare module 'ace-builds/src-noconflict/theme-xcode';
declare module 'ace-builds/webpack-resolver';

View File

@ -0,0 +1,798 @@
/// <reference path="./ace-modules.d.ts" />
export namespace Ace {
export type NewLineMode = 'auto' | 'unix' | 'windows';
export interface Anchor extends EventEmitter {
getPosition(): Position;
getDocument(): Document;
setPosition(row: number, column: number, noClip?: boolean): void;
detach(): void;
attach(doc: Document): void;
}
export interface Document extends EventEmitter {
setValue(text: string): void;
getValue(): string;
createAnchor(row: number, column: number): Anchor;
getNewLineCharacter(): string;
setNewLineMode(newLineMode: NewLineMode): void;
getNewLineMode(): NewLineMode;
isNewLine(text: string): boolean;
getLine(row: number): string;
getLines(firstRow: number, lastRow: number): string[];
getAllLines(): string[];
getTextRange(range: Range): string;
getLinesForRange(range: Range): string[];
insert(position: Position, text: string): Position;
insertInLine(position: Position, text: string): Position;
clippedPos(row: number, column: number): Point;
clonePos(pos: Point): Point;
pos(row: number, column: number): Point;
insertFullLines(row: number, lines: string[]): void;
insertMergedLines(position: Position, lines: string[]): Point;
remove(range: Range): Position;
removeInLine(row: number, startColumn: number, endColumn: number): Position;
removeFullLines(firstRow: number, lastRow: number): string[];
removeNewLine(row: number): void;
replace(range: Range, text: string): Position;
applyDeltas(deltas: Delta[]): void;
revertDeltas(deltas: Delta[]): void;
applyDelta(delta: Delta, doNotValidate?: boolean): void;
revertDelta(delta: Delta): void;
indexToPosition(index: number, startRow: number): Position;
positionToIndex(pos: Position, startRow?: number): number;
}
export interface FoldLine {
folds: Fold[];
range: Range;
start: Point;
end: Point;
shiftRow(shift: number): void;
addFold(fold: Fold): void;
containsRow(row: number): boolean;
walk(callback: Function, endRow?: number, endColumn?: number): void;
getNextFoldTo(row: number, column: number): null | { fold: Fold, kind: string };
addRemoveChars(row: number, column: number, len: number): void;
split(row: number, column: number): FoldLine;
merge(foldLineNext: FoldLine): void;
idxToPosition(idx: number): Point;
}
export interface Fold {
range: Range;
start: Point;
end: Point;
foldLine?: FoldLine;
sameRow: boolean;
subFolds: Fold[];
setFoldLine(foldLine: FoldLine): void;
clone(): Fold;
addSubFold(fold: Fold): Fold;
restoreRange(range: Range): void;
}
export interface Range {
start: Point;
end: Point;
isEqual(range: Range): boolean;
toString(): string;
contains(row: number, column: number): boolean;
compareRange(range: Range): number;
comparePoint(p: Point): number;
containsRange(range: Range): boolean;
intersects(range: Range): boolean;
isEnd(row: number, column: number): boolean;
isStart(row: number, column: number): boolean;
setStart(row: number, column: number): void;
setEnd(row: number, column: number): void;
inside(row: number, column: number): boolean;
insideStart(row: number, column: number): boolean;
insideEnd(row: number, column: number): boolean;
compare(row: number, column: number): number;
compareStart(row: number, column: number): number;
compareEnd(row: number, column: number): number;
compareInside(row: number, column: number): number;
clipRows(firstRow: number, lastRow: number): Range;
extend(row: number, column: number): Range;
isEmpty(): boolean;
isMultiLine(): boolean;
clone(): Range;
collapseRows(): Range;
toScreenRange(session: EditSession): Range;
moveBy(row: number, column: number): void;
}
export interface EditSessionOptions {
wrap: string | number;
wrapMethod: 'code' | 'text' | 'auto';
indentedSoftWrap: boolean;
firstLineNumber: number;
useWorker: boolean;
useSoftTabs: boolean;
tabSize: number;
navigateWithinSoftTabs: boolean;
foldStyle: 'markbegin' | 'markbeginend' | 'manual';
overwrite: boolean;
newLineMode: NewLineMode;
mode: string;
}
export interface VirtualRendererOptions {
animatedScroll: boolean;
showInvisibles: boolean;
showPrintMargin: boolean;
printMarginColumn: number;
printMargin: boolean | number;
showGutter: boolean;
fadeFoldWidgets: boolean;
showFoldWidgets: boolean;
showLineNumbers: boolean;
displayIndentGuides: boolean;
highlightGutterLine: boolean;
hScrollBarAlwaysVisible: boolean;
vScrollBarAlwaysVisible: boolean;
fontSize: number;
fontFamily: string;
maxLines: number;
minLines: number;
scrollPastEnd: boolean;
fixedWidthGutter: boolean;
theme: string;
hasCssTransforms: boolean;
maxPixelHeight: number;
}
export interface MouseHandlerOptions {
scrollSpeed: number;
dragDelay: number;
dragEnabled: boolean;
focusTimeout: number;
tooltipFollowsMouse: boolean;
}
export interface EditorOptions extends EditSessionOptions,
MouseHandlerOptions,
VirtualRendererOptions {
selectionStyle: string;
highlightActiveLine: boolean;
highlightSelectedWord: boolean;
readOnly: boolean;
copyWithEmptySelection: boolean;
cursorStyle: 'ace' | 'slim' | 'smooth' | 'wide';
mergeUndoDeltas: true | false | 'always';
behavioursEnabled: boolean;
wrapBehavioursEnabled: boolean;
autoScrollEditorIntoView: boolean;
keyboardHandler: string;
value: string;
session: EditSession;
}
export interface SearchOptions {
needle: string | RegExp;
preventScroll: boolean;
backwards: boolean;
start: Range;
skipCurrent: boolean;
range: Range;
preserveCase: boolean;
regExp: RegExp;
wholeWord: string;
caseSensitive: boolean;
wrap: boolean;
}
export interface EventEmitter {
once(name: string, callback: Function): void;
setDefaultHandler(name: string, callback: Function): void;
removeDefaultHandler(name: string, callback: Function): void;
on(name: string, callback: Function, capturing?: boolean): void;
addEventListener(name: string, callback: Function, capturing?: boolean): void;
off(name: string, callback: Function): void;
removeListener(name: string, callback: Function): void;
removeEventListener(name: string, callback: Function): void;
}
export interface Point {
row: number;
column: number;
}
export interface Delta {
action: 'insert' | 'remove';
start: Point;
end: Point;
lines: string[];
}
export interface Annotation {
row?: number;
column?: number;
text: string;
type: string;
}
export interface Command {
name?: string;
bindKey?: string | { mac?: string, win?: string };
readOnly?: boolean;
exec: (editor: Editor, args?: any) => void;
}
export type CommandLike = Command | ((editor: Editor) => void);
export interface KeyboardHandler {
handleKeyboard: Function;
}
export interface MarkerLike {
range: Range;
type: string;
renderer?: MarkerRenderer;
clazz: string;
inFront: boolean;
id: number;
update?: (html: string[],
// TODO maybe define Marker class
marker: any,
session: EditSession,
config: any) => void;
}
export type MarkerRenderer = (html: string[],
range: Range,
left: number,
top: number,
config: any) => void;
export interface Token {
type: string;
value: string;
index?: number;
start?: number;
}
export interface Completion {
value: string;
score: number;
meta?: string;
name?: string;
caption?: string;
}
export interface Tokenizer {
removeCapturingGroups(src: string): string;
createSplitterRegexp(src: string, flag?: string): RegExp;
getLineTokens(line: string, startState: string | string[]): Token[];
}
export interface SyntaxMode {
getTokenizer(): Tokenizer;
toggleCommentLines(state: any,
session: EditSession,
startRow: number,
endRow: number): void;
toggleBlockComment(state: any,
session: EditSession,
range: Range,
cursor: Position): void;
getNextLineIndent(state: any, line: string, tab: string): string;
checkOutdent(state: any, line: string, input: string): boolean;
autoOutdent(state: any, doc: Document, row: number): void;
// TODO implement WorkerClient types
createWorker(session: EditSession): any;
createModeDelegates(mapping: {[key: string]: string}): void;
transformAction(state: string,
action: string,
editor: Editor,
session: EditSession,
text: string): any;
getKeywords(append?: boolean): Array<string | RegExp>;
getCompletions(state: string,
session: EditSession,
pos: Position,
prefix: string): Completion[];
}
export interface Config {
get(key: string): any;
set(key: string, value: any): void;
all(): {[key: string]: any};
moduleUrl(name: string, component?: string): string;
setModuleUrl(name: string, subst: string): string;
loadModule(moduleName: string | [string, string],
onLoad: (module: any) => void): void;
init(packaged: any): any;
defineOptions(obj: any, path: string, options: {[key: string]: any}): Config;
resetOptions(obj: any): void;
setDefaultValue(path: string, name: string, value: any): void;
setDefaultValues(path: string, optionHash: {[key: string]: any}): void;
}
export interface OptionsProvider {
setOptions(optList: {[key: string]: any}): void;
getOptions(optionNames?: string[] | {[key: string]: any}): {[key: string]: any};
setOption(name: string, value: any): void;
getOption(name: string): any;
}
export interface UndoManager {
addSession(session: EditSession): void;
add(delta: Delta, allowMerge: boolean, session: EditSession): void;
addSelection(selection: string, rev?: number): void;
startNewGroup(): void;
markIgnored(from: number, to?: number): void;
getSelection(rev: number, after?: boolean): { value: string, rev: number };
getRevision(): number;
getDeltas(from: number, to?: number): Delta[];
undo(session: EditSession, dontSelect?: boolean): void;
redo(session: EditSession, dontSelect?: boolean): void;
reset(): void;
canUndo(): boolean;
canRedo(): boolean;
bookmark(rev?: number): void;
isAtBookmark(): boolean;
}
export interface EditSession extends EventEmitter, OptionsProvider {
selection: Selection;
on(name: 'changeFold',
callback: (obj: { data: Fold, action: string }) => void): void;
on(name: 'changeScrollLeft', callback: (scrollLeft: number) => void): void;
on(name: 'changeScrollTop', callback: (scrollTop: number) => void): void;
on(name: 'tokenizerUpdate',
callback: (obj: { data: { first: number, last: number } }) => void): void;
setOption<T extends keyof EditSessionOptions>(name: T, value: EditSessionOptions[T]): void;
getOption<T extends keyof EditSessionOptions>(name: T): EditSessionOptions[T];
setDocument(doc: Document): void;
getDocument(): Document;
resetCaches(): void;
setValue(text: string): void;
getValue(): string;
getSelection(): Selection;
getState(row: number): string;
getTokens(row: number): Token[];
getTokenAt(row: number, column: number): Token | null;
setUndoManager(undoManager: UndoManager): void;
markUndoGroup(): void;
getUndoManager(): UndoManager;
getTabString(): string;
setUseSoftTabs(val: boolean): void;
getUseSoftTabs(): boolean;
setTabSize(tabSize: number): void;
getTabSize(): number;
isTabStop(position: Position): boolean;
setNavigateWithinSoftTabs(navigateWithinSoftTabs: boolean): void;
getNavigateWithinSoftTabs(): boolean;
setOverwrite(overwrite: boolean): void;
getOverwrite(): boolean;
toggleOverwrite(): void;
addGutterDecoration(row: number, className: string): void;
removeGutterDecoration(row: number, className: string): void;
getBreakpoints(): string[];
setBreakpoints(rows: number[]): void;
clearBreakpoints(): void;
setBreakpoint(row: number, className: string): void;
clearBreakpoint(row: number): void;
addMarker(range: Range,
clazz: string,
type: MarkerRenderer,
inFront: boolean): number;
addDynamicMarker(marker: MarkerLike, inFront: boolean): MarkerLike;
removeMarker(markerId: number): void;
getMarkers(inFront?: boolean): MarkerLike[];
highlight(re: RegExp): void;
highlightLines(startRow: number,
endRow: number,
clazz: string,
inFront?: boolean): Range;
setAnnotations(annotations: Annotation[]): void;
getAnnotations(): Annotation[];
clearAnnotations(): void;
getWordRange(row: number, column: number): Range;
getAWordRange(row: number, column: number): Range;
setNewLineMode(newLineMode: NewLineMode): void;
getNewLineMode(): NewLineMode;
setUseWorker(useWorker: boolean): void;
getUseWorker(): boolean;
setMode(mode: string | SyntaxMode, callback?: () => void): void;
getMode(): SyntaxMode;
setScrollTop(scrollTop: number): void;
getScrollTop(): number;
setScrollLeft(scrollLeft: number): void;
getScrollLeft(): number;
getScreenWidth(): number;
getLineWidgetMaxWidth(): number;
getLine(row: number): string;
getLines(firstRow: number, lastRow: number): string[];
getLength(): number;
getTextRange(range: Range): string;
insert(position: Position, text: string): void;
remove(range: Range): void;
removeFullLines(firstRow: number, lastRow: number): void;
undoChanges(deltas: Delta[], dontSelect?: boolean): void;
redoChanges(deltas: Delta[], dontSelect?: boolean): void;
setUndoSelect(enable: boolean): void;
replace(range: Range, text: string): void;
moveText(fromRange: Range, toPosition: Position, copy?: boolean): void;
indentRows(startRow: number, endRow: number, indentString: string): void;
outdentRows(range: Range): void;
moveLinesUp(firstRow: number, lastRow: number): void;
moveLinesDown(firstRow: number, lastRow: number): void;
duplicateLines(firstRow: number, lastRow: number): void;
setUseWrapMode(useWrapMode: boolean): void;
getUseWrapMode(): boolean;
setWrapLimitRange(min: number, max: number): void;
adjustWrapLimit(desiredLimit: number): boolean;
getWrapLimit(): number;
setWrapLimit(limit: number): void;
getWrapLimitRange(): { min: number, max: number };
getRowLineCount(row: number): number;
getRowWrapIndent(screenRow: number): number;
getScreenLastRowColumn(screenRow: number): number;
getDocumentLastRowColumn(docRow: number, docColumn: number): number;
getdocumentLastRowColumnPosition(docRow: number, docColumn: number): Position;
getRowSplitData(row: number): string | undefined;
getScreenTabSize(screenColumn: number): number;
screenToDocumentRow(screenRow: number, screenColumn: number): number;
screenToDocumentColumn(screenRow: number, screenColumn: number): number;
screenToDocumentPosition(screenRow: number,
screenColumn: number,
offsetX?: number): Position;
documentToScreenPosition(docRow: number, docColumn: number): Position;
documentToScreenPosition(position: Position): Position;
documentToScreenColumn(row: number, docColumn: number): number;
documentToScreenRow(docRow: number, docColumn: number): number;
getScreenLength(): number;
destroy(): void;
}
export interface KeyBinding {
setDefaultHandler(handler: KeyboardHandler): void;
setKeyboardHandler(handler: KeyboardHandler): void;
addKeyboardHandler(handler: KeyboardHandler, pos: number): void;
removeKeyboardHandler(handler: KeyboardHandler): boolean;
getKeyboardHandler(): KeyboardHandler;
getStatusText(): string;
}
export interface CommandManager extends EventEmitter {
on(name: 'exec', callback: (obj: {
editor: Editor,
command: Command,
args: any[]
}) => void): void;
once(name: string, callback: Function): void;
setDefaultHandler(name: string, callback: Function): void;
removeDefaultHandler(name: string, callback: Function): void;
on(name: string, callback: Function, capturing?: boolean): void;
addEventListener(name: string, callback: Function, capturing?: boolean): void;
off(name: string, callback: Function): void;
removeListener(name: string, callback: Function): void;
removeEventListener(name: string, callback: Function): void;
exec(command: string, editor: Editor, args: any): boolean;
toggleRecording(editor: Editor): void;
replay(editor: Editor): void;
addCommand(command: Command): void;
removeCommand(command: Command, keepCommand?: boolean): void;
bindKey(key: string | { mac?: string, win?: string},
command: CommandLike,
position?: number): void;
}
export interface VirtualRenderer extends OptionsProvider, EventEmitter {
container: HTMLElement;
setOption<T extends keyof VirtualRendererOptions>(name: T, value: VirtualRendererOptions[T]): void;
getOption<T extends keyof VirtualRendererOptions>(name: T): VirtualRendererOptions[T];
setSession(session: EditSession): void;
updateLines(firstRow: number, lastRow: number, force?: boolean): void;
updateText(): void;
updateFull(force?: boolean): void;
updateFontSize(): void;
adjustWrapLimit(): boolean;
setAnimatedScroll(shouldAnimate: boolean): void;
getAnimatedScroll(): boolean;
setShowInvisibles(showInvisibles: boolean): void;
getShowInvisibles(): boolean;
setDisplayIndentGuides(display: boolean): void;
getDisplayIndentGuides(): boolean;
setShowPrintMargin(showPrintMargin: boolean): void;
getShowPrintMargin(): boolean;
setPrintMarginColumn(showPrintMargin: boolean): void;
getPrintMarginColumn(): boolean;
setShowGutter(show: boolean): void;
getShowGutter(): boolean;
setFadeFoldWidgets(show: boolean): void;
getFadeFoldWidgets(): boolean;
setHighlightGutterLine(shouldHighlight: boolean): void;
getHighlightGutterLine(): boolean;
getContainerElement(): HTMLElement;
getMouseEventTarget(): HTMLElement;
getTextAreaContainer(): HTMLElement;
getFirstVisibleRow(): number;
getFirstFullyVisibleRow(): number;
getLastFullyVisibleRow(): number;
getLastVisibleRow(): number;
setPadding(padding: number): void;
setScrollMargin(top: number,
bottom: number,
left: number,
right: number): void;
setHScrollBarAlwaysVisible(alwaysVisible: boolean): void;
getHScrollBarAlwaysVisible(): boolean;
setVScrollBarAlwaysVisible(alwaysVisible: boolean): void;
getVScrollBarAlwaysVisible(): boolean;
freeze(): void;
unfreeze(): void;
updateFrontMarkers(): void;
updateBackMarkers(): void;
updateBreakpoints(): void;
setAnnotations(annotations: Annotation[]): void;
updateCursor(): void;
hideCursor(): void;
showCursor(): void;
scrollSelectionIntoView(anchor: Position,
lead: Position,
offset?: number): void;
scrollCursorIntoView(cursor: Position, offset?: number): void;
getScrollTop(): number;
getScrollLeft(): number;
getScrollTopRow(): number;
getScrollBottomRow(): number;
scrollToRow(row: number): void;
alignCursor(cursor: Position | number, alignment: number): number;
scrollToLine(line: number,
center: boolean,
animate: boolean,
callback: () => void): void;
animateScrolling(fromValue: number, callback: () => void): void;
scrollToY(scrollTop: number): void;
scrollToX(scrollLeft: number): void;
scrollTo(x: number, y: number): void;
scrollBy(deltaX: number, deltaY: number): void;
isScrollableBy(deltaX: number, deltaY: number): boolean;
textToScreenCoordinates(row: number, column: number): { pageX: number, pageY: number};
visualizeFocus(): void;
visualizeBlur(): void;
showComposition(position: number): void;
setCompositionText(text: string): void;
hideComposition(): void;
setTheme(theme: string, callback?: () => void): void;
getTheme(): string;
setStyle(style: string, include?: boolean): void;
unsetStyle(style: string): void;
setCursorStyle(style: string): void;
setMouseCursor(cursorStyle: string): void;
attachToShadowRoot(): void;
destroy(): void;
}
export interface Selection extends EventEmitter {
moveCursorWordLeft(): void;
moveCursorWordRight(): void;
fromOrientedRange(range: Range): void;
setSelectionRange(match: any): void;
getAllRanges(): Range[];
addRange(range: Range): void;
isEmpty(): boolean;
isMultiLine(): boolean;
setCursor(row: number, column: number): void;
setAnchor(row: number, column: number): void;
getAnchor(): Position;
getCursor(): Position;
isBackwards(): boolean;
getRange(): Range;
clearSelection(): void;
selectAll(): void;
setRange(range: Range, reverse?: boolean): void;
selectTo(row: number, column: number): void;
selectToPosition(pos: any): void;
selectUp(): void;
selectDown(): void;
selectRight(): void;
selectLeft(): void;
selectLineStart(): void;
selectLineEnd(): void;
selectFileEnd(): void;
selectFileStart(): void;
selectWordRight(): void;
selectWordLeft(): void;
getWordRange(): void;
selectWord(): void;
selectAWord(): void;
selectLine(): void;
moveCursorUp(): void;
moveCursorDown(): void;
moveCursorLeft(): void;
moveCursorRight(): void;
moveCursorLineStart(): void;
moveCursorLineEnd(): void;
moveCursorFileEnd(): void;
moveCursorFileStart(): void;
moveCursorLongWordRight(): void;
moveCursorLongWordLeft(): void;
moveCursorBy(rows: number, chars: number): void;
moveCursorToPosition(position: any): void;
moveCursorTo(row: number, column: number, keepDesiredColumn?: boolean): void;
moveCursorToScreen(row: number, column: number, keepDesiredColumn: boolean): void;
}
var Selection: {
new(session: EditSession): Selection;
}
export interface Editor extends OptionsProvider, EventEmitter {
container: HTMLElement;
renderer: VirtualRenderer;
id: string;
commands: CommandManager;
keyBinding: KeyBinding;
session: EditSession;
selection: Selection;
on(name: 'blur', callback: (e: Event) => void): void;
on(name: 'change', callback: (delta: Delta) => void): void;
on(name: 'changeSelectionStyle', callback: (obj: { data: string }) => void): void;
on(name: 'changeSession',
callback: (obj: { session: EditSession, oldSession: EditSession }) => void): void;
on(name: 'copy', callback: (obj: { text: string }) => void): void;
on(name: 'focus', callback: (e: Event) => void): void;
on(name: 'paste', callback: (obj: { text: string }) => void): void;
setOption<T extends keyof EditorOptions>(name: T, value: EditorOptions[T]): void;
getOption<T extends keyof EditorOptions>(name: T): EditorOptions[T];
setKeyboardHandler(keyboardHandler: string, callback?: () => void): void;
getKeyboardHandler(): string;
setSession(session: EditSession): void;
getSession(): EditSession;
setValue(val: string, cursorPos?: number): string;
getValue(): string;
getSelection(): Selection;
resize(force?: boolean): void;
setTheme(theme: string, callback?: () => void): void;
getTheme(): string;
setStyle(style: string): void;
unsetStyle(style: string): void;
getFontSize(): string;
setFontSize(size: string): void;
focus(): void;
isFocused(): boolean;
flur(): void;
getSelectedText(): string;
getCopyText(): string;
execCommand(command: string | string[], args: any): boolean;
insert(text: string, pasted?: boolean): void;
setOverwrite(overwrite: boolean): void;
getOverwrite(): boolean;
toggleOverwrite(): void;
setScrollSpeed(speed: number): void;
getScrollSpeed(): number;
setDragDelay(dragDelay: number): void;
getDragDelay(): number;
setSelectionStyle(val: string): void;
getSelectionStyle(): string;
setHighlightActiveLine(shouldHighlight: boolean): void;
getHighlightActiveLine(): boolean;
setHighlightGutterLine(shouldHighlight: boolean): void;
getHighlightGutterLine(): boolean;
setHighlightSelectedWord(shouldHighlight: boolean): void;
getHighlightSelectedWord(): boolean;
setAnimatedScroll(shouldAnimate: boolean): void;
getAnimatedScroll(): boolean;
setShowInvisibles(showInvisibles: boolean): void;
getShowInvisibles(): boolean;
setDisplayIndentGuides(display: boolean): void;
getDisplayIndentGuides(): boolean;
setShowPrintMargin(showPrintMargin: boolean): void;
getShowPrintMargin(): boolean;
setPrintMarginColumn(showPrintMargin: number): void;
getPrintMarginColumn(): number;
setReadOnly(readOnly: boolean): void;
getReadOnly(): boolean;
setBehavioursEnabled(enabled: boolean): void;
getBehavioursEnabled(): boolean;
setWrapBehavioursEnabled(enabled: boolean): void;
getWrapBehavioursEnabled(): boolean;
setShowFoldWidgets(show: boolean): void;
getShowFoldWidgets(): boolean;
setFadeFoldWidgets(fade: boolean): void;
getFadeFoldWidgets(): boolean;
remove(dir?: 'left' | 'right'): void;
removeWordRight(): void;
removeWordLeft(): void;
removeLineToEnd(): void;
splitLine(): void;
transposeLetters(): void;
toLowerCase(): void;
toUpperCase(): void;
indent(): void;
blockIndent(): void;
blockOutdent(): void;
sortLines(): void;
toggleCommentLines(): void;
toggleBlockComment(): void;
modifyNumber(amount: number): void;
removeLines(): void;
duplicateSelection(): void;
moveLinesDown(): void;
moveLinesUp(): void;
moveText(range: Range, toPosition: Point, copy?: boolean): Range;
copyLinesUp(): void;
copyLinesDown(): void;
getFirstVisibleRow(): number;
getLastVisibleRow(): number;
isRowVisible(row: number): boolean;
isRowFullyVisible(row: number): boolean;
selectPageDown(): void;
selectPageUp(): void;
gotoPageDown(): void;
gotoPageUp(): void;
scrollPageDown(): void;
scrollPageUp(): void;
scrollToRow(row: number): void;
scrollToLine(line: number, center: boolean, animate: boolean, callback: () => void): void;
centerSelection(): void;
getCursorPosition(): Point;
getCursorPositionScreen(): Point;
getSelectionRange(): Range;
selectAll(): void;
clearSelection(): void;
moveCursorTo(row: number, column: number): void;
moveCursorToPosition(pos: Point): void;
jumpToMatching(select: boolean, expand: boolean): void;
gotoLine(lineNumber: number, column: number, animate: boolean): void;
navigateTo(row: number, column: number): void;
navigateUp(): void;
navigateDown(): void;
navigateLeft(): void;
navigateRight(): void;
navigateLineStart(): void;
navigateLineEnd(): void;
navigateFileEnd(): void;
navigateFileStart(): void;
navigateWordRight(): void;
navigateWordLeft(): void;
replace(replacement: string, options?: Partial<SearchOptions>): number;
replaceAll(replacement: string, options?: Partial<SearchOptions>): number;
getLastSearchOptions(): Partial<SearchOptions>;
find(needle: string, options?: Partial<SearchOptions>, animate?: boolean): void;
findNext(options?: Partial<SearchOptions>, animate?: boolean): void;
findPrevious(options?: Partial<SearchOptions>, animate?: boolean): void;
undo(): void;
redo(): void;
destroy(): void;
setAutoScrollEditorIntoView(enable: boolean): void;
}
}
export const version: string;
export const config: Ace.Config;
export function require(name: string): any;
export function edit(el: Element | string, options?: Partial<Ace.EditorOptions>): Ace.Editor;
export function createEditSession(text: Ace.Document | string, mode: Ace.SyntaxMode): Ace.EditSession;
export const VirtualRenderer: {
new(container: HTMLElement, theme?: string): Ace.VirtualRenderer;
};
export const EditSession: {
new(text: string | Document, mode?: Ace.SyntaxMode): Ace.EditSession;
};
export const UndoManager: {
new(): Ace.UndoManager;
};
export const Range: {
new(startRow: number, startColumn: number, endRow: number, endColumn: number): Ace.Range;
fromPoints(start: Ace.Point, end: Ace.Point): Ace.Range;
comparePoints(p1: Ace.Point, p2: Ace.Point): number;
};

View File

@ -0,0 +1,20 @@
{
"name": "ace-builds",
"description": "Ace (Ajax.org Cloud9 Editor)",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"ignore": [
"demo"
],
"repository": {
"type": "git",
"url": "https://github.com/ajaxorg/ace-builds.git"
},
"author": "",
"license": "BSD",
"bugs": {
"url": "https://github.com/ajaxorg/ace-builds/issues"
},
"homepage": "https://github.com/ajaxorg/ace-builds"
}

View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Editor</title>
<style type="text/css" media="screen">
body {
overflow: hidden;
}
#editor {
margin: 0;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
</style>
</head>
<body>
<pre id="editor">function foo(items) {
var i;
for (i = 0; i &lt; items.length; i++) {
alert("Ace Rocks " + items[i]);
}
}</pre>
<script src="src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>
<script>
var editor = ace.edit("editor");
editor.setTheme("ace/theme/twilight");
editor.session.setMode("ace/mode/javascript");
</script>
</body>
</html>

View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Ace Kitchen Sink</title>
<meta name="author" content="Fabian Jakobs">
<!--
Ace
version 1.4.1
commit
-->
<link rel="stylesheet" href="demo/kitchen-sink/styles.css" type="text/css" media="screen" charset="utf-8">
<script async="true" src="https://use.edgefonts.net/source-code-pro.js"></script>
<link href="./doc/site/images/favicon.ico" rel="icon" type="image/x-icon">
</head>
<body>
<div style="position:absolute;height:100%;width:260px">
<a href="https://c9.io" title="Cloud9 IDE | Your code anywhere, anytime">
<img id="c9-logo" src="demo/kitchen-sink/logo.png" style="width: 172px;margin: -9px 30px -12px 51px;">
</a>
<div style="position: absolute; overflow: hidden; top:100px; bottom:0">
<div id="optionsPanel" style="width: 120%; height:100%; overflow-y: scroll">
<a href="https://ace.c9.io">
<img id="ace-logo" src="demo/kitchen-sink/ace-logo.png" style="width: 134px;margin: 46px 0px 4px 66px;">
</a>
</div>
</div>
</div>
<div id="editor-container"></div>
<script src="src/ace.js" data-ace-base="src" type="text/javascript" charset="utf-8"></script>
<script src="src/keybinding-vim.js"></script>
<script src="src/keybinding-emacs.js"></script>
<script src="demo/kitchen-sink/demo.js"></script>
<script type="text/javascript" charset="utf-8">
require("kitchen-sink/demo");
</script>
</body>
</html>

View File

@ -0,0 +1,20 @@
{
"name": "ace-builds",
"main": "./src-noconflict/ace.js",
"typings": "ace.d.ts",
"version": "1.4.1",
"description": "Ace (Ajax.org Cloud9 Editor)",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/ajaxorg/ace-builds.git"
},
"author": "",
"license": "BSD",
"bugs": {
"url": "https://github.com/ajaxorg/ace-builds/issues"
},
"homepage": "https://github.com/ajaxorg/ace-builds"
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/beautify",["require","exports","module","ace/token_iterator"],function(e,t,n){"use strict";function i(e,t){return e.type.lastIndexOf(t+".xml")>-1}var r=e("../token_iterator").TokenIterator;t.singletonTags=["area","base","br","col","command","embed","hr","html","img","input","keygen","link","meta","param","source","track","wbr"],t.blockTags=["article","aside","blockquote","body","div","dl","fieldset","footer","form","head","header","html","nav","ol","p","script","section","style","table","tbody","tfoot","thead","ul"],t.beautify=function(e){var n=new r(e,0,0),s=n.getCurrentToken(),o=e.getTabString(),u=t.singletonTags,a=t.blockTags,f,l=!1,c=!1,h=!1,p="",d="",v="",m=0,g=0,y=0,b=0,w=0,E=0,S=!1,x,T=0,N=0,C=[],k=!1,L,A=!1,O=!1,M=!1,_=!1,D={0:0},P={},H=function(){f&&f.value&&f.type!=="string.regexp"&&(f.value=f.value.trim())},B=function(){p=p.replace(/ +$/,"")},j=function(){p=p.trimRight(),l=!1};while(s!==null){T=n.getCurrentTokenRow(),C=n.$rowTokens,f=n.stepForward();if(typeof s!="undefined"){d=s.value,w=0,M=v==="style"||e.$modeId==="ace/mode/css",i(s,"tag-open")?(O=!0,f&&(_=a.indexOf(f.value)!==-1),d==="</"&&(_&&!l&&N<1&&N++,M&&(N=1),w=1,_=!1)):i(s,"tag-close")?O=!1:i(s,"comment.start")?_=!0:i(s,"comment.end")&&(_=!1),!O&&!N&&s.type==="paren.rparen"&&s.value.substr(0,1)==="}"&&N++,T!==x&&(N=T,x&&(N-=x));if(N){j();for(;N>0;N--)p+="\n";l=!0,!i(s,"comment")&&!s.type.match(/^(comment|string)$/)&&(d=d.trimLeft())}if(d){s.type==="keyword"&&d.match(/^(if|else|elseif|for|foreach|while|switch)$/)?(P[m]=d,H(),h=!0,d.match(/^(else|elseif)$/)&&p.match(/\}[\s]*$/)&&(j(),c=!0)):s.type==="paren.lparen"?(H(),d.substr(-1)==="{"&&(h=!0,A=!1,O||(N=1)),d.substr(0,1)==="{"&&(c=!0,p.substr(-1)!=="["&&p.trimRight().substr(-1)==="["?(j(),c=!1):p.trimRight().substr(-1)===")"?j():B())):s.type==="paren.rparen"?(w=1,d.substr(0,1)==="}"&&(P[m-1]==="case"&&w++,p.trimRight().substr(-1)==="{"?j():(c=!0,M&&(N+=2))),d.substr(0,1)==="]"&&p.substr(-1)!=="}"&&p.trimRight().substr(-1)==="}"&&(c=!1,b++,j()),d.substr(0,1)===")"&&p.substr(-1)!=="("&&p.trimRight().substr(-1)==="("&&(c=!1,b++,j()),B()):s.type!=="keyword.operator"&&s.type!=="keyword"||!d.match(/^(=|==|===|!=|!==|&&|\|\||and|or|xor|\+=|.=|>|>=|<|<=|=>)$/)?s.type==="punctuation.operator"&&d===";"?(j(),H(),h=!0,M&&N++):s.type==="punctuation.operator"&&d.match(/^(:|,)$/)?(j(),H(),h=!0,l=!1):s.type==="support.php_tag"&&d==="?>"&&!l?(j(),c=!0):i(s,"attribute-name")&&p.substr(-1).match(/^\s$/)?c=!0:i(s,"attribute-equals")?(B(),H()):i(s,"tag-close")&&(B(),d==="/>"&&(c=!0)):(j(),H(),c=!0,h=!0);if(l&&(!s.type.match(/^(comment)$/)||!!d.substr(0,1).match(/^[/#]$/))&&(!s.type.match(/^(string)$/)||!!d.substr(0,1).match(/^['"]$/))){b=y;if(m>g){b++;for(L=m;L>g;L--)D[L]=b}else m<g&&(b=D[m]);g=m,y=b,w&&(b-=w),A&&!E&&(b++,A=!1);for(L=0;L<b;L++)p+=o}s.type==="keyword"&&d.match(/^(case|default)$/)&&(P[m]=d,m++),s.type==="keyword"&&d.match(/^(break)$/)&&P[m-1]&&P[m-1].match(/^(case|default)$/)&&m--,s.type==="paren.lparen"&&(E+=(d.match(/\(/g)||[]).length,m+=d.length),s.type==="keyword"&&d.match(/^(if|else|elseif|for|while)$/)?(A=!0,E=0):!E&&d.trim()&&s.type!=="comment"&&(A=!1);if(s.type==="paren.rparen"){E-=(d.match(/\)/g)||[]).length;for(L=0;L<d.length;L++)m--,d.substr(L,1)==="}"&&P[m]==="case"&&m--}c&&!l&&(B(),p.substr(-1)!=="\n"&&(p+=" ")),p+=d,h&&(p+=" "),l=!1,c=!1,h=!1;if(i(s,"tag-close")&&(_||a.indexOf(v)!==-1)||i(s,"doctype")&&d===">")_&&f&&f.value==="</"?N=-1:N=1;i(s,"tag-open")&&d==="</"?m--:i(s,"tag-open")&&d==="<"&&u.indexOf(f.value)===-1?m++:i(s,"tag-name")?v=d:i(s,"tag-close")&&d==="/>"&&u.indexOf(v)===-1&&m--,x=T}}s=f}p=p.trim(),e.doc.setValue(p)},t.commands=[{name:"beautify",exec:function(e){t.beautify(e.session)},bindKey:"Ctrl-Shift-B"}]});
(function() {
ace.require(["ace/ext/beautify"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/elastic_tabstops_lite",["require","exports","module","ace/editor","ace/config"],function(e,t,n){"use strict";var r=function(e){this.$editor=e;var t=this,n=[],r=!1;this.onAfterExec=function(){r=!1,t.processRows(n),n=[]},this.onExec=function(){r=!0},this.onChange=function(e){r&&(n.indexOf(e.start.row)==-1&&n.push(e.start.row),e.end.row!=e.start.row&&n.push(e.end.row))}};(function(){this.processRows=function(e){this.$inChange=!0;var t=[];for(var n=0,r=e.length;n<r;n++){var i=e[n];if(t.indexOf(i)>-1)continue;var s=this.$findCellWidthsForBlock(i),o=this.$setBlockCellWidthsToMax(s.cellWidths),u=s.firstRow;for(var a=0,f=o.length;a<f;a++){var l=o[a];t.push(u),this.$adjustRow(u,l),u++}}this.$inChange=!1},this.$findCellWidthsForBlock=function(e){var t=[],n,r=e;while(r>=0){n=this.$cellWidthsForRow(r);if(n.length==0)break;t.unshift(n),r--}var i=r+1;r=e;var s=this.$editor.session.getLength();while(r<s-1){r++,n=this.$cellWidthsForRow(r);if(n.length==0)break;t.push(n)}return{cellWidths:t,firstRow:i}},this.$cellWidthsForRow=function(e){var t=this.$selectionColumnsForRow(e),n=[-1].concat(this.$tabsForRow(e)),r=n.map(function(e){return 0}).slice(1),i=this.$editor.session.getLine(e);for(var s=0,o=n.length-1;s<o;s++){var u=n[s]+1,a=n[s+1],f=this.$rightmostSelectionInCell(t,a),l=i.substring(u,a);r[s]=Math.max(l.replace(/\s+$/g,"").length,f-u)}return r},this.$selectionColumnsForRow=function(e){var t=[],n=this.$editor.getCursorPosition();return this.$editor.session.getSelection().isEmpty()&&e==n.row&&t.push(n.column),t},this.$setBlockCellWidthsToMax=function(e){var t=!0,n,r,i,s=this.$izip_longest(e);for(var o=0,u=s.length;o<u;o++){var a=s[o];if(!a.push){console.error(a);continue}a.push(NaN);for(var f=0,l=a.length;f<l;f++){var c=a[f];t&&(n=f,i=0,t=!1);if(isNaN(c)){r=f;for(var h=n;h<r;h++)e[h][o]=i;t=!0}i=Math.max(i,c)}}return e},this.$rightmostSelectionInCell=function(e,t){var n=0;if(e.length){var r=[];for(var i=0,s=e.length;i<s;i++)e[i]<=t?r.push(i):r.push(0);n=Math.max.apply(Math,r)}return n},this.$tabsForRow=function(e){var t=[],n=this.$editor.session.getLine(e),r=/\t/g,i;while((i=r.exec(n))!=null)t.push(i.index);return t},this.$adjustRow=function(e,t){var n=this.$tabsForRow(e);if(n.length==0)return;var r=0,i=-1,s=this.$izip(t,n);for(var o=0,u=s.length;o<u;o++){var a=s[o][0],f=s[o][1];i+=1+a,f+=r;var l=i-f;if(l==0)continue;var c=this.$editor.session.getLine(e).substr(0,f),h=c.replace(/\s*$/g,""),p=c.length-h.length;l>0&&(this.$editor.session.getDocument().insertInLine({row:e,column:f+1},Array(l+1).join(" ")+" "),this.$editor.session.getDocument().removeInLine(e,f,f+1),r+=l),l<0&&p>=-l&&(this.$editor.session.getDocument().removeInLine(e,f+l,f),r+=l)}},this.$izip_longest=function(e){if(!e[0])return[];var t=e[0].length,n=e.length;for(var r=1;r<n;r++){var i=e[r].length;i>t&&(t=i)}var s=[];for(var o=0;o<t;o++){var u=[];for(var r=0;r<n;r++)e[r][o]===""?u.push(NaN):u.push(e[r][o]);s.push(u)}return s},this.$izip=function(e,t){var n=e.length>=t.length?t.length:e.length,r=[];for(var i=0;i<n;i++){var s=[e[i],t[i]];r.push(s)}return r}}).call(r.prototype),t.ElasticTabstopsLite=r;var i=e("../editor").Editor;e("../config").defineOptions(i.prototype,"editor",{useElasticTabstops:{set:function(e){e?(this.elasticTabstops||(this.elasticTabstops=new r(this)),this.commands.on("afterExec",this.elasticTabstops.onAfterExec),this.commands.on("exec",this.elasticTabstops.onExec),this.on("change",this.elasticTabstops.onChange)):this.elasticTabstops&&(this.commands.removeListener("afterExec",this.elasticTabstops.onAfterExec),this.commands.removeListener("exec",this.elasticTabstops.onExec),this.removeListener("change",this.elasticTabstops.onChange))}}})});
(function() {
ace.require(["ace/ext/elastic_tabstops_lite"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
;
(function() {
ace.require(["ace/ext/error_marker"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/menu_tools/overlay_page",["require","exports","module","ace/lib/dom"],function(e,t,n){"use strict";var r=e("../../lib/dom"),i="#ace_settingsmenu, #kbshortcutmenu {background-color: #F7F7F7;color: black;box-shadow: -5px 4px 5px rgba(126, 126, 126, 0.55);padding: 1em 0.5em 2em 1em;overflow: auto;position: absolute;margin: 0;bottom: 0;right: 0;top: 0;z-index: 9991;cursor: default;}.ace_dark #ace_settingsmenu, .ace_dark #kbshortcutmenu {box-shadow: -20px 10px 25px rgba(126, 126, 126, 0.25);background-color: rgba(255, 255, 255, 0.6);color: black;}.ace_optionsMenuEntry:hover {background-color: rgba(100, 100, 100, 0.1);transition: all 0.3s}.ace_closeButton {background: rgba(245, 146, 146, 0.5);border: 1px solid #F48A8A;border-radius: 50%;padding: 7px;position: absolute;right: -8px;top: -8px;z-index: 100000;}.ace_closeButton{background: rgba(245, 146, 146, 0.9);}.ace_optionsMenuKey {color: darkslateblue;font-weight: bold;}.ace_optionsMenuCommand {color: darkcyan;font-weight: normal;}.ace_optionsMenuEntry input, .ace_optionsMenuEntry button {vertical-align: middle;}.ace_optionsMenuEntry button[ace_selected_button=true] {background: #e7e7e7;box-shadow: 1px 0px 2px 0px #adadad inset;border-color: #adadad;}.ace_optionsMenuEntry button {background: white;border: 1px solid lightgray;margin: 0px;}.ace_optionsMenuEntry button:hover{background: #f0f0f0;}";r.importCssString(i),n.exports.overlayPage=function(t,n,i,s,o,u){function l(e){e.keyCode===27&&a.click()}i=i?"top: "+i+";":"",o=o?"bottom: "+o+";":"",s=s?"right: "+s+";":"",u=u?"left: "+u+";":"";var a=document.createElement("div"),f=document.createElement("div");a.style.cssText="margin: 0; padding: 0; position: fixed; top:0; bottom:0; left:0; right:0;z-index: 9990; background-color: rgba(0, 0, 0, 0.3);",a.addEventListener("click",function(){document.removeEventListener("keydown",l),a.parentNode.removeChild(a),t.focus(),a=null}),document.addEventListener("keydown",l),f.style.cssText=i+s+o+u,f.addEventListener("click",function(e){e.stopPropagation()});var c=r.createElement("div");c.style.position="relative";var h=r.createElement("div");h.className="ace_closeButton",h.addEventListener("click",function(){a.click()}),c.appendChild(h),f.appendChild(c),f.appendChild(n),a.appendChild(f),document.body.appendChild(a),t.blur()}}),ace.define("ace/ext/menu_tools/get_editor_keyboard_shortcuts",["require","exports","module","ace/lib/keys"],function(e,t,n){"use strict";var r=e("../../lib/keys");n.exports.getEditorKeybordShortcuts=function(e){var t=r.KEY_MODS,n=[],i={};return e.keyBinding.$handlers.forEach(function(e){var t=e.commandKeyBinding;for(var r in t){var s=r.replace(/(^|-)\w/g,function(e){return e.toUpperCase()}),o=t[r];Array.isArray(o)||(o=[o]),o.forEach(function(e){typeof e!="string"&&(e=e.name),i[e]?i[e].key+="|"+s:(i[e]={key:s,command:e},n.push(i[e]))})}}),n}}),ace.define("ace/ext/keybinding_menu",["require","exports","module","ace/editor","ace/ext/menu_tools/overlay_page","ace/ext/menu_tools/get_editor_keyboard_shortcuts"],function(e,t,n){"use strict";function i(t){if(!document.getElementById("kbshortcutmenu")){var n=e("./menu_tools/overlay_page").overlayPage,r=e("./menu_tools/get_editor_keyboard_shortcuts").getEditorKeybordShortcuts,i=r(t),s=document.createElement("div"),o=i.reduce(function(e,t){return e+'<div class="ace_optionsMenuEntry"><span class="ace_optionsMenuCommand">'+t.command+"</span> : "+'<span class="ace_optionsMenuKey">'+t.key+"</span></div>"},"");s.id="kbshortcutmenu",s.innerHTML="<h1>Keyboard Shortcuts</h1>"+o+"</div>",n(t,s,"0","0","0",null)}}var r=e("ace/editor").Editor;n.exports.init=function(e){r.prototype.showKeyboardShortcuts=function(){i(this)},e.commands.addCommands([{name:"showKeyboardShortcuts",bindKey:{win:"Ctrl-Alt-h",mac:"Command-Alt-h"},exec:function(e,t){e.showKeyboardShortcuts()}}])}});
(function() {
ace.require(["ace/ext/keybinding_menu"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/linking",["require","exports","module","ace/editor","ace/config"],function(e,t,n){function i(e){var n=e.editor,r=e.getAccelKey();if(r){var n=e.editor,i=e.getDocumentPosition(),s=n.session,o=s.getTokenAt(i.row,i.column);t.previousLinkingHover&&t.previousLinkingHover!=o&&n._emit("linkHoverOut"),n._emit("linkHover",{position:i,token:o}),t.previousLinkingHover=o}else t.previousLinkingHover&&(n._emit("linkHoverOut"),t.previousLinkingHover=!1)}function s(e){var t=e.getAccelKey(),n=e.getButton();if(n==0&&t){var r=e.editor,i=e.getDocumentPosition(),s=r.session,o=s.getTokenAt(i.row,i.column);r._emit("linkClick",{position:i,token:o})}}var r=e("ace/editor").Editor;e("../config").defineOptions(r.prototype,"editor",{enableLinking:{set:function(e){e?(this.on("click",s),this.on("mousemove",i)):(this.off("click",s),this.off("mousemove",i))},value:!1}}),t.previousLinkingHover=!1});
(function() {
ace.require(["ace/ext/linking"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/modelist",["require","exports","module"],function(e,t,n){"use strict";function i(e){var t=a.text,n=e.split(/[\/\\]/).pop();for(var i=0;i<r.length;i++)if(r[i].supportsFile(n)){t=r[i];break}return t}var r=[],s=function(e,t,n){this.name=e,this.caption=t,this.mode="ace/mode/"+e,this.extensions=n;var r;/\^/.test(n)?r=n.replace(/\|(\^)?/g,function(e,t){return"$|"+(t?"^":"^.*\\.")})+"$":r="^.*\\.("+n+")$",this.extRe=new RegExp(r,"gi")};s.prototype.supportsFile=function(e){return e.match(this.extRe)};var o={ABAP:["abap"],ABC:["abc"],ActionScript:["as"],ADA:["ada|adb"],Apache_Conf:["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],AsciiDoc:["asciidoc|adoc"],ASL:["dsl|asl"],Assembly_x86:["asm|a"],AutoHotKey:["ahk"],BatchFile:["bat|cmd"],Bro:["bro"],C_Cpp:["cpp|c|cc|cxx|h|hh|hpp|ino"],C9Search:["c9search_results"],Cirru:["cirru|cr"],Clojure:["clj|cljs"],Cobol:["CBL|COB"],coffee:["coffee|cf|cson|^Cakefile"],ColdFusion:["cfm"],CSharp:["cs"],Csound_Document:["csd"],Csound_Orchestra:["orc"],Csound_Score:["sco"],CSS:["css"],Curly:["curly"],D:["d|di"],Dart:["dart"],Diff:["diff|patch"],Dockerfile:["^Dockerfile"],Dot:["dot"],Drools:["drl"],Edifact:["edi"],Eiffel:["e|ge"],EJS:["ejs"],Elixir:["ex|exs"],Elm:["elm"],Erlang:["erl|hrl"],Forth:["frt|fs|ldr|fth|4th"],Fortran:["f|f90"],FSharp:["fsi|fs|ml|mli|fsx|fsscript"],FTL:["ftl"],Gcode:["gcode"],Gherkin:["feature"],Gitignore:["^.gitignore"],Glsl:["glsl|frag|vert"],Gobstones:["gbs"],golang:["go"],GraphQLSchema:["gql"],Groovy:["groovy"],HAML:["haml"],Handlebars:["hbs|handlebars|tpl|mustache"],Haskell:["hs"],Haskell_Cabal:["cabal"],haXe:["hx"],Hjson:["hjson"],HTML:["html|htm|xhtml|vue|we|wpy"],HTML_Elixir:["eex|html.eex"],HTML_Ruby:["erb|rhtml|html.erb"],INI:["ini|conf|cfg|prefs"],Io:["io"],Jack:["jack"],Jade:["jade|pug"],Java:["java"],JavaScript:["js|jsm|jsx"],JSON:["json"],JSONiq:["jq"],JSP:["jsp"],JSSM:["jssm|jssm_state"],JSX:["jsx"],Julia:["jl"],Kotlin:["kt|kts"],LaTeX:["tex|latex|ltx|bib"],LESS:["less"],Liquid:["liquid"],Lisp:["lisp"],LiveScript:["ls"],LogiQL:["logic|lql"],LSL:["lsl"],Lua:["lua"],LuaPage:["lp"],Lucene:["lucene"],Makefile:["^Makefile|^GNUmakefile|^makefile|^OCamlMakefile|make"],Markdown:["md|markdown"],Mask:["mask"],MATLAB:["matlab"],Maze:["mz"],MEL:["mel"],MIXAL:["mixal"],MUSHCode:["mc|mush"],MySQL:["mysql"],Nix:["nix"],NSIS:["nsi|nsh"],ObjectiveC:["m|mm"],OCaml:["ml|mli"],Pascal:["pas|p"],Perl:["pl|pm"],pgSQL:["pgsql"],PHP_Laravel_blade:["blade.php"],PHP:["php|phtml|shtml|php3|php4|php5|phps|phpt|aw|ctp|module"],Puppet:["epp|pp"],Pig:["pig"],Powershell:["ps1"],Praat:["praat|praatscript|psc|proc"],Prolog:["plg|prolog"],Properties:["properties"],Protobuf:["proto"],Python:["py"],R:["r"],Razor:["cshtml|asp"],RDoc:["Rd"],Red:["red|reds"],RHTML:["Rhtml"],RST:["rst"],Ruby:["rb|ru|gemspec|rake|^Guardfile|^Rakefile|^Gemfile"],Rust:["rs"],SASS:["sass"],SCAD:["scad"],Scala:["scala"],Scheme:["scm|sm|rkt|oak|scheme"],SCSS:["scss"],SH:["sh|bash|^.bashrc"],SJS:["sjs"],Slim:["slim|skim"],Smarty:["smarty|tpl"],snippets:["snippets"],Soy_Template:["soy"],Space:["space"],SQL:["sql"],SQLServer:["sqlserver"],Stylus:["styl|stylus"],SVG:["svg"],Swift:["swift"],Tcl:["tcl"],Terraform:["tf","tfvars","terragrunt"],Tex:["tex"],Text:["txt"],Textile:["textile"],Toml:["toml"],TSX:["tsx"],Twig:["twig|swig"],Typescript:["ts|typescript|str"],Vala:["vala"],VBScript:["vbs|vb"],Velocity:["vm"],Verilog:["v|vh|sv|svh"],VHDL:["vhd|vhdl"],Wollok:["wlk|wpgm|wtest"],XML:["xml|rdf|rss|wsdl|xslt|atom|mathml|mml|xul|xbl|xaml"],XQuery:["xq"],YAML:["yaml|yml"],Django:["html"]},u={ObjectiveC:"Objective-C",CSharp:"C#",golang:"Go",C_Cpp:"C and C++",Csound_Document:"Csound Document",Csound_Orchestra:"Csound",Csound_Score:"Csound Score",coffee:"CoffeeScript",HTML_Ruby:"HTML (Ruby)",HTML_Elixir:"HTML (Elixir)",FTL:"FreeMarker",PHP_Laravel_blade:"PHP (Blade Template)"},a={};for(var f in o){var l=o[f],c=(u[f]||f).replace(/_/g," "),h=f.toLowerCase(),p=new s(h,c,l[0]);a[h]=p,r.push(p)}n.exports={getModeForPath:i,modes:r,modesByName:a}});
(function() {
ace.require(["ace/ext/modelist"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/rtl",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/editor","ace/config"],function(e,t,n){"use strict";function u(e,t){var n=t.getSelection().lead;t.session.$bidiHandler.isRtlLine(n.row)&&n.column===0&&(t.session.$bidiHandler.isMoveLeftOperation&&n.row>0?t.getSelection().moveCursorTo(n.row-1,t.session.getLine(n.row-1).length):t.getSelection().isEmpty()?n.column+=1:n.setPosition(n.row,n.column+1))}function a(e){e.editor.session.$bidiHandler.isMoveLeftOperation=/gotoleft|selectleft|backspace|removewordleft/.test(e.command.name)}function f(e,t){t.$bidiHandler.currentRow=null;if(t.$bidiHandler.isRtlLine(e.start.row)&&e.action==="insert"&&e.lines.length>1)for(var n=e.start.row;n<e.end.row;n++)t.getLine(n+1).charAt(0)!==t.$bidiHandler.RLE&&(t.getDocument().$lines[n+1]=t.$bidiHandler.RLE+t.getLine(n+1))}function l(e,t){var n=t.session,r=n.$bidiHandler,i=t.$textLayer.$lines.cells,s=t.layerConfig.width-t.layerConfig.padding+"px";i.forEach(function(e){var t=e.element.style;r&&r.isRtlLine(e.row)?(t.direction="rtl",t.textAlign="right",t.width=s):(t.direction="",t.textAlign="",t.width="")})}function c(e){function n(e){var t=e.element.style;t.direction=t.textAlign=t.width=""}var t=e.$textLayer.$lines;t.cells.forEach(n),t.cellCache.forEach(n)}var r=e("ace/lib/dom"),i=e("ace/lib/lang"),s=[{name:"leftToRight",bindKey:{win:"Ctrl-Alt-Shift-L",mac:"Command-Alt-Shift-L"},exec:function(e){e.session.$bidiHandler.setRtlDirection(e,!1)},readOnly:!0},{name:"rightToLeft",bindKey:{win:"Ctrl-Alt-Shift-R",mac:"Command-Alt-Shift-R"},exec:function(e){e.session.$bidiHandler.setRtlDirection(e,!0)},readOnly:!0}],o=e("../editor").Editor;e("../config").defineOptions(o.prototype,"editor",{rtlText:{set:function(e){e?(this.on("session",f),this.on("changeSelection",u),this.renderer.on("afterRender",l),this.commands.on("exec",a),this.commands.addCommands(s)):(this.off("session",f),this.off("changeSelection",u),this.renderer.off("afterRender",l),this.commands.off("exec",a),this.commands.removeCommands(s),c(this.renderer)),this.renderer.updateFull()}}})});
(function() {
ace.require(["ace/ext/rtl"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
ace.define("ace/ext/spellcheck",["require","exports","module","ace/lib/event","ace/editor","ace/config"],function(e,t,n){"use strict";var r=e("../lib/event");t.contextMenuHandler=function(e){var t=e.target,n=t.textInput.getElement();if(!t.selection.isEmpty())return;var i=t.getCursorPosition(),s=t.session.getWordRange(i.row,i.column),o=t.session.getTextRange(s);t.session.tokenRe.lastIndex=0;if(!t.session.tokenRe.test(o))return;var u="\x01\x01",a=o+" "+u;n.value=a,n.setSelectionRange(o.length,o.length+1),n.setSelectionRange(0,0),n.setSelectionRange(0,o.length);var f=!1;r.addListener(n,"keydown",function l(){r.removeListener(n,"keydown",l),f=!0}),t.textInput.setInputHandler(function(e){console.log(e,a,n.selectionStart,n.selectionEnd);if(e==a)return"";if(e.lastIndexOf(a,0)===0)return e.slice(a.length);if(e.substr(n.selectionEnd)==a)return e.slice(0,-a.length);if(e.slice(-2)==u){var r=e.slice(0,-2);if(r.slice(-1)==" ")return f?r.substring(0,n.selectionEnd):(r=r.slice(0,-1),t.session.replace(s,r),"")}return e})};var i=e("../editor").Editor;e("../config").defineOptions(i.prototype,"editor",{spellcheck:{set:function(e){var n=this.textInput.getElement();n.spellcheck=!!e,e?this.on("nativecontextmenu",t.contextMenuHandler):this.removeListener("nativecontextmenu",t.contextMenuHandler)},value:!0}})});
(function() {
ace.require(["ace/ext/spellcheck"], function(m) {
if (typeof module == "object" && typeof exports == "object" && module) {
module.exports = m;
}
});
})();

Some files were not shown because too many files have changed in this diff Show More