├── .htaccess ├── Dockerfile ├── LICENSE.txt ├── README.md ├── conf.php ├── countries.sql ├── css ├── bootstrap-theme.min.css ├── bootstrap.min.css ├── bs_cm.php ├── codemirror.css ├── common_bs.css ├── highlight.css └── task │ └── view.css ├── ctl ├── .htaccess ├── Login.php ├── Logout.php ├── Main.php ├── Wiki.php ├── _hookBefore.php ├── api │ └── Weekbest.php ├── forum │ ├── Delete.php │ ├── Edit.php │ ├── Main.php │ ├── Newtopic.php │ ├── Post.php │ ├── Rename.php │ ├── Topic.php │ ├── Update.php │ └── View.php ├── mess │ └── Hall.php ├── task │ ├── Attempt2.php │ ├── Edit.php │ ├── List.php │ ├── Preparedata.php │ ├── Save.php │ ├── Solution.php │ ├── Solvers.php │ ├── Star.php │ ├── Success.php │ ├── Testchecker.php │ ├── Text.php │ ├── View.php │ └── tag │ │ ├── Assign.php │ │ ├── Edit.php │ │ ├── List.php │ │ └── Update.php ├── tools │ └── Calcpoints.php ├── user │ ├── Profile.php │ ├── Ranking.php │ ├── Settings.php │ ├── Unsolved.php │ └── settings │ │ ├── Avatar.php │ │ ├── Chname.php │ │ ├── Country.php │ │ ├── Email.php │ │ ├── Info.php │ │ └── Password.php └── wiki │ ├── Edit.php │ └── Save.php ├── data └── db-ip.txt ├── dbinit.sql ├── docker-build.sh ├── docker-run.sh ├── fragments ├── .htaccess ├── countryselect.html ├── cssandjs.html ├── flash.html ├── footer.html ├── forumform.html ├── langselect.html ├── main │ ├── bottomnote.html │ ├── image.html │ ├── lastforum.html │ ├── lasttasks.html │ ├── login.html │ ├── middlenote.html │ └── rank.html ├── menu-bs.html ├── metas.html ├── rankline.html ├── tasklist │ └── notice.html └── taskview │ ├── badattempt.html │ ├── errorsmodal.html │ ├── runtools.html │ └── solcaption.html ├── img ├── facade.gif ├── flags │ └── zz.gif ├── logingg.png ├── logingh.png ├── logout.png ├── profile.png ├── random.png ├── search2.png └── settings.png ├── index.php ├── js ├── _ace │ ├── ace.js │ ├── mode-c_cpp.js │ ├── mode-csharp.js │ ├── mode-golang.js │ ├── mode-haskell.js │ ├── mode-java.js │ ├── mode-javascript.js │ ├── mode-julia.js │ ├── mode-lua.js │ ├── mode-perl.js │ ├── mode-php.js │ ├── mode-plain_text.js │ ├── mode-python.js │ ├── mode-ruby.js │ ├── mode-rust.js │ ├── mode-scala.js │ ├── mode-sql.js │ ├── mode-swift.js │ └── test-it.html ├── _cm │ ├── clike.js │ ├── codemirror.js │ ├── markdown.js │ ├── matchbrackets.js │ ├── php.js │ └── xml.js ├── bootstrap.min.js ├── common.js ├── highlight.js ├── jq.js ├── jq_bs_cm.php ├── task │ ├── _view.js │ └── edit.js └── wiki │ └── edit.js ├── layouts ├── .htaccess └── default_bs.html ├── module ├── .htaccess ├── Context.php ├── auth │ └── Auth.php ├── dao │ ├── ChallengesDao.php │ ├── ForumTopicsDao.php │ ├── MysqlDao.php │ ├── TasksDao.php │ ├── UserDataDao.php │ └── UserTasksDao.php ├── lib │ └── Markdown_Parser.php ├── service │ ├── CertService.php │ ├── ChallengeService.php │ ├── CheatService.php │ ├── ForumService.php │ ├── FriendService.php │ ├── LangService.php │ ├── LocaleService.php │ ├── LoginService.php │ ├── MiscService.php │ ├── MsgService.php │ ├── StrUtils.php │ ├── TaskService.php │ └── UserService.php └── sys │ ├── Elems.php │ ├── ProtoContext.php │ └── Util.php ├── pages ├── .htaccess ├── error.php ├── error403.php ├── error404.php ├── forum │ ├── edit.php │ ├── list.php │ ├── main.php │ ├── newtopic.php │ ├── noaccess.php │ ├── topic.php │ └── view.php ├── login.php ├── main.php ├── mess │ └── hall.php ├── message.php ├── task │ ├── edit.php │ ├── list.php │ ├── solution.php │ ├── solvers.php │ ├── success.php │ ├── tag │ │ ├── edit.php │ │ └── list.php │ └── view.php ├── user │ ├── profile.php │ ├── ranking.php │ ├── settings.php │ └── unsolved.php ├── wiki.php └── wiki │ ├── edit.php │ └── index.php ├── sqlexec.php └── taskinit.sql /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | 3 | #RewriteRule ^(.*)$ "http\:\/\/localhost\:8080\/$1" [R=301,L] 4 | 5 | RewriteRule ^index$ index.php 6 | RewriteRule ^index\/([\w]+)\/?$ index.php?page=$1 [QSA] 7 | RewriteRule ^index\/([\w]+)\/([A-Za-z\d\-\.]+)\/?$ index.php?page=$1¶m=$2 [QSA] 8 | RewriteRule ^index\/([\w]+)\/([A-Za-z]+)\_([A-Za-z\d\-]+)\/?$ index.php?page=$1&$2=$3 [QSA] 9 | 10 | ErrorDocument 403 /index/error404 11 | ErrorDocument 404 /index/error404 12 | Options -Indexes 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.3-apache 2 | 3 | RUN docker-php-ext-install mysqli && a2enmod rewrite \ 4 | && apt-get update && apt-get install -y mariadb-server \ 5 | && mkdir /run/mysqld \ 6 | && chmod a+s /usr/bin/mariadb 7 | 8 | CMD ["/bin/bash", "-c", "coproc mariadbd --user=root && sleep 5 && apache2-foreground"] 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | CodeAbbey License 2 | 3 | Copyright (c) 2013 Rodion Gorkovenko 4 | 5 | Permission is granted to run, study, share, modify this software, 6 | free of charge, to anyone, provided the following condition is met: 7 | 8 | 1. The reference to original repository https://github.com/codeabbey/src 9 | should be retained in unobscured way in user-facing interface (e.g. 10 | link with words "based upon CodeAbbey sources" in the footer of every web-page) 11 | 12 | 2. Redistributed copies and derived works should contain the above copyright 13 | notice and the link to original repository https://github.com/codeabbey/src 14 | 15 | The motivation is that any end-user may in turn obtain the copy of the original 16 | software. No conditions on publishing any changes, improvements, additions in 17 | derived works are imposed. 18 | 19 | The software is provided "AS IS", with no warranty of any kind. Reusing it you 20 | agree that the author is not responsible for any effects due to its use or misuse. 21 | -------------------------------------------------------------------------------- /conf.php: -------------------------------------------------------------------------------- 1 | elems->conf->modrewrite = true; 6 | 7 | $ctx->elems->conf->mysql = array( 8 | 'host' => '127.0.0.1', 9 | 'port' => '3306', 10 | 'username' => 'causer', 11 | 'password' => 'somepwd', 12 | 'db' => 'ca', 13 | 'prefix' => 'pfx_', 14 | 'charset' => 'utf8' 15 | ); 16 | 17 | $ctx->elems->conf->projectName = 'CodeAbbey'; 18 | $ctx->elems->conf->title = "{$ctx->elems->conf->projectName} - programming problems"; 19 | $ctx->elems->conf->descr = 'Collection of free programming puzzles'; 20 | $ctx->elems->conf->descrSuffix = 'Programming problems for beginners'; 21 | $ctx->elems->conf->author = 'Rodion Gorkovenko'; 22 | $ctx->elems->conf->mainImage = aurl('img/facade.gif'); 23 | $ctx->elems->conf->motto = 'We believe in three things, which lead to success:
Practice, Practice and Practice!'; 24 | $ctx->elems->conf->copyright = '© 2013 - ' . date('Y') . ', Rodion Gorkovenko'; 25 | $ctx->elems->conf->defTaskSort = 'id1'; 26 | $ctx->elems->conf->singleForum = false; 27 | $ctx->elems->conf->nameChangeLevel = 125; 28 | $ctx->elems->conf->personalInfoLevel = 25; 29 | 30 | $ctx->elems->conf->taskVolumes = array('simple' => 'Simple', 'advanced' => 'Advanced', 'special' => 'Special'); 31 | 32 | $ctx->elems->conf->custFrag = array( 33 | 'adblock' => '', 34 | 'user_extraconfig' => '', 35 | ); 36 | 37 | $ctx->elems->conf->custSvc = array( 38 | ); 39 | 40 | $ctx->elems->conf->logging = array('activity' => false); 41 | 42 | $ctx->elems->conf->languages = array("c/c++" => "C/C++", "python" => "Python", "go" => "Go", 43 | "java" => "Java", "c#" => "C#", "javascript" => "JavaScript", "other" => "Other"); 44 | 45 | $ctx->elems->conf->passwordSalt = 'salt#cadabraabra'; 46 | $ctx->elems->conf->emailSalt = 'salt#racadabraab'; 47 | 48 | $ctx->elems->conf->calcPointsSecret = null; 49 | $ctx->elems->conf->viewSolutionSecret = 'baracada'; 50 | ?> 51 | -------------------------------------------------------------------------------- /countries.sql: -------------------------------------------------------------------------------- 1 | use ca; 2 | 3 | insert into pfx_countries (code, title) values ('AD','Andorra'),('AE','United Arab Emirates'),('AF','Afghanistan'),('AG','Antigua & Barbuda'),('AI','Anguilla'),('AL','Albania'); 4 | insert into pfx_countries (code, title) values ('AM','Armenia'),('AN','Netherlands Antilles'),('AO','Angola'),('AQ','Antarctica'),('AR','Argentina'),('AS','American Samoa'),('AT','Austria'); 5 | insert into pfx_countries (code, title) values ('AU','Australia'),('AW','Aruba'),('AZ','Azerbaijan'),('BA','Bosnia and Herzegovina'),('BB','Barbados'),('BD','Bangladesh'),('BE','Belgium'); 6 | insert into pfx_countries (code, title) values ('BF','Burkina Faso'),('BG','Bulgaria'),('BH','Bahrain'),('BI','Burundi'),('BJ','Benin'),('BM','Bermuda'),('BN','Brunei Darussalam'); 7 | insert into pfx_countries (code, title) values ('BO','Bolivia'),('BR','Brazil'),('BS','Bahama'),('BT','Bhutan'),('BV','Bouvet Island'),('BW','Botswana'),('BY','Belarus'),('BZ','Belize'); 8 | insert into pfx_countries (code, title) values ('CA','Canada'),('CC','Cocos (Keeling) Islands'),('CF','Central African Republic'),('CG','Congo'),('CH','Switzerland'),('CI','Cote D''ivoire (Ivory Coast)'); 9 | insert into pfx_countries (code, title) values ('CK','Cook Iislands'),('CL','Chile'),('CM','Cameroon'),('CN','China'),('CO','Colombia'),('CR','Costa Rica'),('CU','Cuba'),('CV','Cape Verde'); 10 | insert into pfx_countries (code, title) values ('CX','Christmas Island'),('CY','Cyprus'),('CZ','Czech Republic'),('DE','Germany'),('DJ','Djibouti'),('DK','Denmark'),('DM','Dominica'); 11 | insert into pfx_countries (code, title) values ('DO','Dominican Republic'),('DZ','Algeria'),('EC','Ecuador'),('EE','Estonia'),('EG','Egypt'),('EH','Western Sahara'),('ER','Eritrea'); 12 | insert into pfx_countries (code, title) values ('ES','Spain'),('ET','Ethiopia'),('FI','Finland'),('FJ','Fiji'),('FK','Falkland Islands (Malvinas)'),('FM','Micronesia'),('FO','Faroe Islands'); 13 | insert into pfx_countries (code, title) values ('FR','France'),('FX','France, Metropolitan'),('GA','Gabon'),('GB','United Kingdom (Great Britain)'),('GD','Grenada'),('GE','Georgia'); 14 | insert into pfx_countries (code, title) values ('GF','French Guiana'),('GH','Ghana'),('GI','Gibraltar'),('GL','Greenland'),('GM','Gambia'),('GN','Guinea'),('GP','Guadeloupe'),('GQ','Equatorial Guinea'); 15 | insert into pfx_countries (code, title) values ('GR','Greece'),('GS','South Georgia and the South Sandwich Islands'),('GT','Guatemala'),('GU','Guam'),('GW','Guinea-Bissau'),('GY','Guyana'); 16 | insert into pfx_countries (code, title) values ('HK','Hong Kong'),('HM','Heard & McDonald Islands'),('HN','Honduras'),('HR','Croatia'),('HT','Haiti'),('HU','Hungary'),('ID','Indonesia'); 17 | insert into pfx_countries (code, title) values ('IE','Ireland'),('IL','Israel'),('IN','India'),('IO','British Indian Ocean Territory'),('IQ','Iraq'),('IR','Islamic Republic of Iran'); 18 | insert into pfx_countries (code, title) values ('IS','Iceland'),('IT','Italy'),('JM','Jamaica'),('JO','Jordan'),('JP','Japan'),('KE','Kenya'),('KG','Kyrgyzstan'),('KH','Cambodia'),('KI','Kiribati'); 19 | insert into pfx_countries (code, title) values ('KM','Comoros'),('KN','St. Kitts and Nevis'),('KP','Democratic People''s Republic of Korea'),('KR','Republic of Korea'),('KW','Kuwait'); 20 | insert into pfx_countries (code, title) values ('KY','Cayman Islands'),('KZ','Kazakhstan'),('LA','Lao People''s Democratic Republic'),('LB','Lebanon'),('LC','Saint Lucia'),('LI','Liechtenstein'); 21 | insert into pfx_countries (code, title) values ('LK','Sri Lanka'),('LR','Liberia'),('LS','Lesotho'),('LT','Lithuania'),('LU','Luxembourg'),('LV','Latvia'),('LY','Libyan Arab Jamahiriya'); 22 | insert into pfx_countries (code, title) values ('MA','Morocco'),('MC','Monaco'),('MD','Republic of Moldova'),('MG','Madagascar'),('MH','Marshall Islands'),('ML','Mali'),('MM','Myanmar'); 23 | insert into pfx_countries (code, title) values ('MN','Mongolia'),('MO','Macau'),('MP','Northern Mariana Islands'),('MQ','Martinique'),('MR','Mauritania'),('MS','Monserrat'),('MT','Malta'); 24 | insert into pfx_countries (code, title) values ('MU','Mauritius'),('MV','Maldives'),('MW','Malawi'),('MX','Mexico'),('MY','Malaysia'),('MZ','Mozambique'),('NA','Nambia'),('NC','New Caledonia'); 25 | insert into pfx_countries (code, title) values ('NE','Niger'),('NF','Norfolk Island'),('NG','Nigeria'),('NI','Nicaragua'),('NL','Netherlands'),('NO','Norway'),('NP','Nepal'),('NR','Nauru'); 26 | insert into pfx_countries (code, title) values ('NU','Niue'),('NZ','New Zealand'),('OM','Oman'),('PA','Panama'),('PE','Peru'),('PF','French Polynesia'),('PG','Papua New Guinea'),('PH','Philippines'); 27 | insert into pfx_countries (code, title) values ('PK','Pakistan'),('PL','Poland'),('PM','St. Pierre & Miquelon'),('PN','Pitcairn'),('PR','Puerto Rico'),('PT','Portugal'),('PW','Palau'),('PY','Paraguay'); 28 | insert into pfx_countries (code, title) values ('QA','Qatar'),('RE','Reunion'),('RO','Romania'),('RU','Russian Federation'),('RW','Rwanda'),('SA','Saudi Arabia'),('SB','Solomon Islands'),('SC','Seychelles'); 29 | insert into pfx_countries (code, title) values ('SD','Sudan'),('SE','Sweden'),('SG','Singapore'),('SH','St. Helena'),('SI','Slovenia'),('SJ','Svalbard & Jan Mayen Islands'),('SK','Slovakia'),('RS','Serbia'); 30 | insert into pfx_countries (code, title) values ('SL','Sierra Leone'),('SM','San Marino'),('SN','Senegal'),('SO','Somalia'),('SR','Suriname'),('ST','Sao Tome & Principe'),('SV','El Salvador'); 31 | insert into pfx_countries (code, title) values ('SY','Syrian Arab Republic'),('SZ','Swaziland'),('TC','Turks & Caicos Islands'),('TD','Chad'),('TF','French Southern Territories'),('TG','Togo'); 32 | insert into pfx_countries (code, title) values ('TH','Thailand'),('TJ','Tajikistan'),('TK','Tokelau'),('TM','Turkmenistan'),('TN','Tunisia'),('TO','Tonga'),('TP','East Timor'),('TR','Turkey'); 33 | insert into pfx_countries (code, title) values ('TT','Trinidad & Tobago'),('TV','Tuvalu'),('TW','Taiwan'),('TZ','United Republic of Tanzania'),('UA','Ukraine'),('UG','Uganda'); 34 | insert into pfx_countries (code, title) values ('UM','United States Minor Outlying Islands'),('US','United States of America'),('UY','Uruguay'),('UZ','Uzbekistan'),('VA','Vatican City State (Holy See)'); 35 | insert into pfx_countries (code, title) values ('VC','St. Vincent & the Grenadines'),('VE','Venezuela'),('VG','British Virgin Islands'),('VI','United States Virgin Islands'),('VN','Viet Nam'); 36 | insert into pfx_countries (code, title) values ('VU','Vanuatu'),('WF','Wallis & Futuna Islands'),('WS','Samoa'),('YE','Yemen'),('YT','Mayotte'),('YU','Yugoslavia'),('ZA','South Africa'); 37 | insert into pfx_countries (code, title) values ('ZM','Zambia'),('ZR','Zaire'),('ZW','Zimbabwe'),('ZZ','Unknown'); 38 | -------------------------------------------------------------------------------- /css/bs_cm.php: -------------------------------------------------------------------------------- 1 | 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | -webkit-text-size-adjust: none; 14 | } 15 | 16 | .hljs-comment, 17 | .hljs-template_comment, 18 | .diff .hljs-header, 19 | .hljs-javadoc { 20 | color: #998; 21 | font-style: italic; 22 | } 23 | 24 | .hljs-keyword, 25 | .css .rule .hljs-keyword, 26 | .hljs-winutils, 27 | .javascript .hljs-title, 28 | .nginx .hljs-title, 29 | .hljs-subst, 30 | .hljs-request, 31 | .hljs-status { 32 | color: #333; 33 | font-weight: bold; 34 | } 35 | 36 | .hljs-number, 37 | .hljs-hexcolor, 38 | .ruby .hljs-constant { 39 | color: #008080; 40 | } 41 | 42 | .hljs-string, 43 | .hljs-tag .hljs-value, 44 | .hljs-phpdoc, 45 | .hljs-dartdoc, 46 | .tex .hljs-formula { 47 | color: #d14; 48 | } 49 | 50 | .hljs-title, 51 | .hljs-id, 52 | .scss .hljs-preprocessor { 53 | color: #900; 54 | font-weight: bold; 55 | } 56 | 57 | .javascript .hljs-title, 58 | .hljs-list .hljs-keyword, 59 | .hljs-subst { 60 | font-weight: normal; 61 | } 62 | 63 | .hljs-class .hljs-title, 64 | .hljs-type, 65 | .vhdl .hljs-literal, 66 | .tex .hljs-command { 67 | color: #458; 68 | font-weight: bold; 69 | } 70 | 71 | .hljs-tag, 72 | .hljs-tag .hljs-title, 73 | .hljs-rules .hljs-property, 74 | .django .hljs-tag .hljs-keyword { 75 | color: #000080; 76 | font-weight: normal; 77 | } 78 | 79 | .hljs-attribute, 80 | .hljs-variable, 81 | .lisp .hljs-body { 82 | color: #008080; 83 | } 84 | 85 | .hljs-regexp { 86 | color: #009926; 87 | } 88 | 89 | .hljs-symbol, 90 | .ruby .hljs-symbol .hljs-string, 91 | .lisp .hljs-keyword, 92 | .clojure .hljs-keyword, 93 | .scheme .hljs-keyword, 94 | .tex .hljs-special, 95 | .hljs-prompt { 96 | color: #990073; 97 | } 98 | 99 | .hljs-built_in { 100 | color: #0086b3; 101 | } 102 | 103 | .hljs-preprocessor, 104 | .hljs-pragma, 105 | .hljs-pi, 106 | .hljs-doctype, 107 | .hljs-shebang, 108 | .hljs-cdata { 109 | color: #999; 110 | font-weight: bold; 111 | } 112 | 113 | .hljs-deletion { 114 | background: #fdd; 115 | } 116 | 117 | .hljs-addition { 118 | background: #dfd; 119 | } 120 | 121 | .diff .hljs-change { 122 | background: #0086b3; 123 | } 124 | 125 | .hljs-chunk { 126 | color: #aaa; 127 | } 128 | -------------------------------------------------------------------------------- /css/task/view.css: -------------------------------------------------------------------------------- 1 | #task-attempt input[type=submit] { 2 | width:150px; 3 | height:50px; 4 | font-size:200%; 5 | } 6 | 7 | #code-tools input { 8 | width: 105px; 9 | } 10 | -------------------------------------------------------------------------------- /ctl/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all 3 | -------------------------------------------------------------------------------- /ctl/Login.php: -------------------------------------------------------------------------------- 1 | util->paramPost('username'); 4 | $password = $ctx->util->paramPost('password'); 5 | $password2 = $ctx->util->paramPost('password2'); 6 | $email = $ctx->util->paramPost('email'); 7 | 8 | if (!empty($username) && !empty($password) && strlen($password) > 5) { 9 | if (!empty($email) && !empty($password2)) { 10 | $res = $ctx->userService->checkRegisterData($username, $password, $password2, $email); 11 | if ($res !== null) { 12 | $ctx->util->flash("Error: $res"); 13 | } else { 14 | $emailHash = $ctx->loginService->hashEmail($email); 15 | $user = $ctx->userService->register($username, "!!$emailHash", $password); 16 | if (!is_object($user)) { 17 | $ctx->util->redirect('error'); 18 | return; 19 | } 20 | $ctx->loginService->login($user->username, $password); 21 | $ctx->util->flash("Thanks for registering!"); 22 | $ctx->util->redirect('task_list'); 23 | } 24 | } else { 25 | if ($ctx->loginService->login($username, $password)) { 26 | $ctx->util->flash("Hello, glad to see you!"); 27 | $ctx->util->redirect('task_list'); 28 | } else { 29 | $ctx->util->flash("Username or password is wrong?"); 30 | } 31 | } 32 | } 33 | 34 | $model->logged = $ctx->auth->loggedUser() !== null; 35 | $ctx->elems->robots = 'noindex,nofollow'; 36 | 37 | -------------------------------------------------------------------------------- /ctl/Logout.php: -------------------------------------------------------------------------------- 1 | auth->logout(); 4 | 5 | session_unset(); 6 | 7 | $ctx->util->flash('Logout successful. See you later!'); 8 | $ctx->util->redirect('main'); 9 | -------------------------------------------------------------------------------- /ctl/Main.php: -------------------------------------------------------------------------------- 1 | util->redirect(preg_replace('/index.*$/', '', $requestUri)); 7 | } 8 | 9 | $model->rank = $ctx->userService->topOfWeek(); 10 | 11 | $taskIds = $ctx->tasksDao->findIds('shown <> 0'); 12 | $taskIds = array_slice($taskIds, sizeof($taskIds) - 7); 13 | $taskIds = implode(',', $taskIds); 14 | $model->lastTasks = $taskIds ? array_reverse($ctx->tasksDao->find("id in ($taskIds)")) : []; 15 | 16 | $model->lastForum = 17 | array_slice($ctx->forumService->recentList(), 0, 5); 18 | 19 | $ctx->elems->analytics = true; 20 | 21 | $model->logged = ($ctx->auth->loggedUser() !== null); 22 | -------------------------------------------------------------------------------- /ctl/Wiki.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | if (!$url) { 6 | $ctx->util->changePage('wiki/index'); 7 | $model->pages = $ctx->wikiDao->find(); 8 | $ctx->elems->title = 'Wiki: index'; 9 | $model->lastmod = '2014-01-01 00:00:00'; 10 | } else { 11 | $url = $ctx->strUtils->nameToUrl($url); 12 | $wikipage = $ctx->wikiDao->findFirst("url = '$url'"); 13 | 14 | if (!is_object($wikipage)) { 15 | $ctx->util->changePage('error404'); 16 | return; 17 | } 18 | 19 | $model->title = $wikipage->title; 20 | $model->url = $wikipage->url; 21 | $model->text = $ctx->markDown->parse(base64_decode($wikipage->data)); 22 | $model->lastmod = $wikipage->lastmod; 23 | 24 | $ctx->elems->title = 'Wiki: ' . $wikipage->title; 25 | if (strpos($model->text, '') !== false) { 26 | $ctx->elems->robots = 'noindex,nofollow'; 27 | } 28 | } 29 | 30 | $ctx->miscService->headerLastModified($model->lastmod); 31 | 32 | $ctx->elems->styles[] = 'jsmonoterm'; 33 | $ctx->elems->scripts[] = 'jsmonoterm'; 34 | $ctx->elems->analytics = true; 35 | 36 | 37 | -------------------------------------------------------------------------------- /ctl/_hookBefore.php: -------------------------------------------------------------------------------- 1 | httpReferrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; 5 | -------------------------------------------------------------------------------- /ctl/api/Weekbest.php: -------------------------------------------------------------------------------- 1 | userService->topOfWeek(); 4 | 5 | $res = ''; 6 | foreach ($best as $entry) { 7 | $url = url('user_profile', 'param', $entry->url); 8 | $res .= "{$entry->username}" 9 | . "{$entry->rank}{$entry->cnt}\n"; 10 | } 11 | 12 | header('Cache-Control: max-age=1200'); 13 | $ctx->util->plainOutput($res); 14 | -------------------------------------------------------------------------------- /ctl/forum/Delete.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $url = $ctx->util->paramGet('param'); 9 | 10 | $topic = $ctx->forumService->loadTopicByUrl($url); 11 | if (!is_object($topic)) { 12 | $ctx->util->changePage('error404'); 13 | return; 14 | } 15 | 16 | $posts = $ctx->forumPostsDao->find("topicid = {$topic->id}"); 17 | 18 | $ctx->forumTopicsDao->delete($topic->id); 19 | 20 | foreach ($posts as $p) { 21 | $ctx->forumPostsDao->delete($p->id); 22 | } 23 | 24 | $ctx->util->flash('Topic deleted'); 25 | $ctx->util->redirect('forum_view'); 26 | -------------------------------------------------------------------------------- /ctl/forum/Edit.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | if (!empty($url) && preg_match('/[0-9A-F]{32}/i', $url)) { 6 | $id = $ctx->miscService->decryptInt($url); 7 | if ($id !== null) { 8 | $post = $ctx->forumPostsDao->read($id); 9 | } 10 | } 11 | 12 | if (empty($post)) { 13 | $ctx->util->changePage('error404'); 14 | return; 15 | } 16 | 17 | $model->postText = base64_decode($post->post); 18 | $model->url = $url; 19 | 20 | $ctx->forumService->resourcesForCodeMirror(); 21 | 22 | $ctx->elems->robots = 'noindex,nofollow'; 23 | $ctx->elems->title = 'Editing forum post'; 24 | $ctx->elems->analytics = false; 25 | 26 | -------------------------------------------------------------------------------- /ctl/forum/Main.php: -------------------------------------------------------------------------------- 1 | forums = $ctx->forumsDao->makeLookup(); 4 | 5 | foreach ($model->forums as $forum) { 6 | $forum->info = $ctx->markdown->parse(base64_decode($forum->info)); 7 | } 8 | 9 | $model->topics = $ctx->forumService->recentList($model->forums); 10 | 11 | $ctx->elems->title = "Forums"; 12 | $ctx->elems->description = 'Dicussion forum about solving programming problems and learning to code'; 13 | $ctx->elems->analytics = true; 14 | 15 | -------------------------------------------------------------------------------- /ctl/forum/Newtopic.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | if (empty($url) || !$ctx->miscService->validUrlParam($url)) { 6 | $url = 'general'; 7 | } 8 | 9 | $forum = $ctx->forumsDao->findFirst("url = '$url'"); 10 | 11 | if (!is_object($forum)) { 12 | $ctx->util->changePage('error404'); 13 | return; 14 | } 15 | 16 | $model->forum = $forum; 17 | $model->newTopic = true; 18 | 19 | $ctx->forumService->resourcesForCodeMirror(); 20 | 21 | $ctx->elems->robots = 'noindex,nofollow'; 22 | $ctx->elems->title = 'Create forum topic'; 23 | $ctx->elems->analytics = false; 24 | 25 | -------------------------------------------------------------------------------- /ctl/forum/Post.php: -------------------------------------------------------------------------------- 1 | util->paramPost('url'); 4 | $topicTitle = $ctx->util->paramPost('topictitle'); 5 | $text = $ctx->util->paramPost('text'); 6 | $taskId = $ctx->util->paramPost('task'); 7 | $userId = $ctx->auth->loggedUser(); 8 | 9 | if ((empty($url) && empty($topicTitle)) || empty($text) || strlen($text) < 20 || strlen($text) > 5000) { 10 | $ctx->util->changePage('message'); 11 | $model->msg = 'Message post should have from 20 to 5000 characters length!'; 12 | return; 13 | } 14 | 15 | if (!$ctx->miscService->validUrlParam($url) || !$userId || !$ctx->userService->forumAllowed()) { 16 | $ctx->util->redirect('error'); 17 | return; 18 | } 19 | 20 | if (!empty($topicTitle)) { 21 | $topicTitle = $ctx->forumService->stripTopicTitle($topicTitle); 22 | if (strlen($topicTitle) < 10 || strlen($topicTitle) > 100) { 23 | $ctx->util->changePage('message'); 24 | $model->msg = 'Topic title should have from 10 to 100 characters length!'; 25 | return; 26 | } 27 | if (!empty($taskId)) { 28 | if (!preg_match('/\d+/', $taskId)) { 29 | $ctx->util->changePage('message'); 30 | $model->msg = 'Task number for private forum seems to be incorrect!'; 31 | return; 32 | } 33 | $taskId = intval($taskId); 34 | if (!$ctx->auth->admin() && !$ctx->userService->haveSolved($userId, $taskId)) { 35 | $ctx->util->changePage('message'); 36 | $model->msg = 'You can not create private forum for task which you have not solved yet!'; 37 | return; 38 | } 39 | } else { 40 | $taskId = 0; 41 | } 42 | 43 | $forum = $ctx->forumsDao->findFirst("url = '$url'"); 44 | if (is_object($forum)) { 45 | $topic = new \stdClass(); 46 | $topic->forumid = $forum->id; 47 | $topic->userid = $userId; 48 | $topic->taskId = $taskId; 49 | $topic->title = $topicTitle; 50 | $topic->url = md5($topicTitle . $forum->title . rand()); 51 | $topic->created = $ctx->miscService->curTimeStr(); 52 | $url = $topic->url; 53 | $ctx->forumTopicsDao->save($topic); 54 | } else { 55 | $url = ''; 56 | } 57 | } 58 | 59 | $topic = $ctx->forumTopicsDao->findFirst("url = '$url'"); 60 | 61 | if (!is_object($topic)) { 62 | $ctx->util->changePage('error404'); 63 | return; 64 | } 65 | 66 | $post = new \stdClass(); 67 | $post->userid = $userId; 68 | $post->topicid = $topic->id; 69 | $post->post = base64_encode($text); 70 | $post->created = $ctx->miscService->curTimeStr(); 71 | $postId = $ctx->forumPostsDao->save($post); 72 | 73 | $topic->posts += 1; 74 | $topic->lastpost = $ctx->miscService->curTimeStr(); 75 | $topic->lastpostid = $postId; 76 | $ctx->forumTopicsDao->save($topic); 77 | 78 | $ctx->util->redirect(url('forum_topic', 'param', $url)); 79 | 80 | -------------------------------------------------------------------------------- /ctl/forum/Rename.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $newName = $ctx->util->paramPost('newname'); 9 | $url = $ctx->util->paramPost('url'); 10 | 11 | $newName = trim($newName); 12 | $topic = $ctx->forumService->loadTopicByUrl($url); 13 | 14 | if (!is_object($topic) || strlen($newName) < 3) { 15 | $ctx->util->changePage('error404'); 16 | return; 17 | } 18 | 19 | if ($newName[0] != '/') { 20 | $newName = $ctx->forumService->stripTopicTitle($newName); 21 | if (!is_object($topic) || strlen($newName) < 5) { 22 | $ctx->util->flash('Bad title?'); 23 | $ctx->util->redirect('error'); 24 | return; 25 | } 26 | $topic->title = $newName; 27 | } else { 28 | $forumUrl = substr($newName, 1); 29 | $forum = $ctx->forumService->loadForumByUrl($forumUrl); 30 | if (!is_object($forum)) { 31 | $ctx->util->flash('No such forum?'); 32 | $ctx->util->redirect('error'); 33 | return; 34 | } 35 | $topic->forumid = $forum->id; 36 | } 37 | 38 | $ctx->forumTopicsDao->save($topic); 39 | $ctx->util->redirect(url('forum_topic', 'param', $url)); 40 | 41 | -------------------------------------------------------------------------------- /ctl/forum/Topic.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | if (empty($url) || !$ctx->miscService->validUrlParam($url)) { 6 | $ctx->util->changePage('error404'); 7 | return; 8 | } 9 | 10 | $topic = $ctx->forumTopicsDao->findFirst("url = '$url'"); 11 | 12 | if (!is_object($topic)) { 13 | $ctx->util->changePage('error404'); 14 | return; 15 | } 16 | 17 | if ($topic->taskid) { 18 | $model->forTask = $ctx->tasksDao->read($topic->taskid); 19 | $restrict = $ctx->forumService->privateTopicRestriction($topic->taskid); 20 | if ($restrict) { 21 | $ctx->util->changePage('forum_noaccess'); 22 | $ctx->elems->robots = 'noindex,nofollow'; 23 | $ctx->elems->title = 'Private Forum'; 24 | $ctx->elems->analytics = false; 25 | return; 26 | } 27 | } 28 | 29 | $model->topic = $topic; 30 | $model->forum = $ctx->forumsDao->read($topic->forumid); 31 | $model->posts = $ctx->forumService->loadPosts($topic); 32 | $model->posts[count($model->posts) - 1]->lastPost = true; 33 | 34 | $model->showForm = $ctx->userService->forumAllowed(); 35 | if ($model->showForm) { 36 | $ctx->forumService->resourcesForCodeMirror(); 37 | } 38 | 39 | $ctx->elems->title = "{$model->forum->title}: {$topic->title}"; 40 | $ctx->elems->analytics = true; 41 | 42 | -------------------------------------------------------------------------------- /ctl/forum/Update.php: -------------------------------------------------------------------------------- 1 | util->paramPost('url'); 4 | $text = $ctx->util->paramPost('text'); 5 | 6 | if (!empty($id) && !empty($text) && preg_match('/[0-9A-F]{32}/i', $id)) { 7 | $id = $ctx->miscService->decryptInt($id); 8 | if ($id !== null) { 9 | $post = $ctx->forumPostsDao->read($id); 10 | } 11 | } 12 | 13 | if (empty($post)) { 14 | $ctx->util->changePage('error404'); 15 | return; 16 | } 17 | 18 | $post->post = base64_encode($text); 19 | $ctx->forumPostsDao->save($post); 20 | 21 | $topic = $ctx->forumTopicsDao->read($post->topicid); 22 | 23 | $ctx->util->redirect(url('forum_topic', 'param', $topic->url)); 24 | 25 | -------------------------------------------------------------------------------- /ctl/forum/View.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | if (empty($url) || !$ctx->miscService->validUrlParam($url)) { 6 | $forum = new \stdClass(); 7 | $forum->id = null; 8 | $forum->info = ''; 9 | } else { 10 | $forum = $ctx->forumsDao->findFirst("url = '$url'"); 11 | } 12 | 13 | if (!is_object($forum)) { 14 | $ctx->util->changePage('error404'); 15 | return; 16 | } 17 | 18 | $model->topics = $ctx->forumService->loadTopics($forum->id); 19 | 20 | foreach ($model->topics as $topic) { 21 | if ($topic->taskid) { 22 | $topic->title = "[Task#{$topic->taskid}] {$topic->title}"; 23 | } 24 | } 25 | 26 | if (!empty($forum->info)) { 27 | $forum->info = $ctx->markdown->parse(base64_decode($forum->info)); 28 | } 29 | 30 | $model->forum = $forum; 31 | 32 | $model->otherForums = !empty($url) ? $ctx->forumsDao->find("url != '$url'") : array(); 33 | 34 | $model->showCreateLink = $ctx->userService->forumAllowed(); 35 | 36 | $ctx->elems->title = 'Forum'; 37 | if (!empty($forum->title)) { 38 | $ctx->elems->title .= ": {$forum->title}"; 39 | } 40 | $ctx->elems->analytics = true; 41 | 42 | -------------------------------------------------------------------------------- /ctl/mess/Hall.php: -------------------------------------------------------------------------------- 1 | records = $ctx->chatViewDao->find(); 4 | 5 | $oldestTime = time() - 86400; 6 | for ($i = 0; $i < count($model->records); $i++) { 7 | $rec = $model->records[$i]; 8 | $time = strtotime($rec->created); 9 | if ($time < $oldestTime) { 10 | array_splice($model->records, $i); 11 | break; 12 | } 13 | $rec->message = $ctx->markdown->parse(base64_decode($rec->message)); 14 | $rec->created = date('H:i:s', $time); 15 | $rec->rank = $ctx->userService->rank($rec->solved, $rec->username); 16 | } 17 | 18 | $model->stats = $ctx->userTasksDao->solvingStats(date('Y-m-d', time() - 86400 * 15)); 19 | if ($ctx->auth->admin()) { 20 | $statsAvg = 0; 21 | for ($i = 1; $i < count($model->stats); $i++) { 22 | $statsAvg += $model->stats[$i]->cnt; 23 | } 24 | $model->statsAvg = number_format($statsAvg / (count($model->stats) - 1), 1); 25 | } 26 | 27 | $model->rights = $ctx->userService->messAllowed(); 28 | 29 | $ctx->elems->robots = 'noindex,nofollow'; 30 | $ctx->elems->title = 'Mess Hall'; 31 | $ctx->elems->analytics = true; 32 | 33 | -------------------------------------------------------------------------------- /ctl/task/Attempt2.php: -------------------------------------------------------------------------------- 1 | auth->user()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $ctx->util->plainOutput(''); 9 | 10 | $inputPlain = file_get_contents('php://input'); 11 | $input = json_decode($inputPlain); 12 | 13 | $taskid = $input->taskid; 14 | $answer = $input->answer; 15 | $solution = $input->solution; 16 | $lang = $input->lang; 17 | if ($input->b64enc ?? 0) { 18 | if ($solution[0] == '-') { 19 | $solution = strrev(substr($solution, 1)); 20 | } 21 | $solution = str_replace(array('.','_','-'), array('+','/','='), $solution); 22 | $solution = base64_decode($solution); 23 | } 24 | 25 | if (!is_numeric($taskid) || !$solution || !$answer) { 26 | echo json_encode(['msg'=>'Insufficient data A', 'data'=>$inputPlain]); 27 | return; 28 | } 29 | 30 | $lastSolved = $ctx->util->sessionGet('lastSolved'); 31 | if ($lastSolved) { 32 | $ctx->util->sessionDel('lastSolved'); 33 | $last = array_map('intval', explode(' ', $lastSolved)); 34 | $secRem = ($last[0] == $taskid ? $last[2] : max($last[2], $last[1])) - time(); 35 | if ($secRem > 0) { 36 | echo json_encode(['msg'=>"You could not submit new tasks for $secRem seconds more"]); 37 | return; 38 | } 39 | } 40 | 41 | $languages = $ctx->langService->languagesArray(); 42 | $lang = isset($languages[$lang]) ? $languages[$lang] : ""; 43 | 44 | $task = $ctx->tasksDao->findFirst("id = $taskid"); 45 | 46 | if (!is_object($task)) { 47 | echo json_encode(['msg'=>'Unknown task']); 48 | return; 49 | } 50 | 51 | $userid = $ctx->auth->loggedUser(); 52 | $userData = $ctx->userDataDao->findFirst("userid = $userid"); 53 | 54 | if ($ctx->cheatService->isSuspended($userid)) { 55 | echo json_encode(['msg'=>'Submission not accepted from this account']); 56 | return; 57 | } 58 | 59 | $ctx->util->sessionPut('last_subm', time()); 60 | 61 | $res = $ctx->taskService->processSolution($task, $userid, $answer, $solution, $lang); 62 | $json = new \stdClass(); 63 | $json->solved = $res[0]; 64 | $json->gainedPoints = number_format($res[1], 2); 65 | $json->userPoints = number_format($res[2], 2); 66 | $json->task = $task; 67 | 68 | if ($res[1] > 0 && !$ctx->elems->conf->calcPointsSecret) { 69 | $ctx->miscService->calcPoints(); 70 | } 71 | 72 | $rndPrimes = array(13, 17, 19, 23, 29, 31, 37); 73 | $json->userRnd = $rndPrimes[$userid % count($rndPrimes)]; 74 | $json->numSolved = $userData->solved; 75 | 76 | $expectedAnswer = $ctx->taskService->deleteAnswer($taskid); 77 | if (strlen($expectedAnswer) > 2) { 78 | $eaPrefix = substr($expectedAnswer, 0, 2); 79 | if ($eaPrefix === "' " || $eaPrefix == '. ') { 80 | $expectedAnswer = substr($expectedAnswer, 2); 81 | } 82 | } 83 | 84 | if ($json->solved) { 85 | if ($ctx->challengeService->challengeExists($taskid)) { 86 | $json->challengeResult = explode(' ', $expectedAnswer, 3); 87 | } 88 | } else { 89 | $json->answer = $expectedAnswer; 90 | $json->submittedAnswer = base64_encode($answer); 91 | $json->inputData = $ctx->taskService->deleteInputData($taskid); 92 | } 93 | 94 | $url = url('task_view', 'param', $task->url); 95 | $msg = $json->solved 96 | ? "I'm proud to tell I've just solved [{$task->title}]($url)!" 97 | : "I'm sorry to say I've failed [{$task->title}]($url)... :("; 98 | $ctx->miscService->postToMessHall($userid, $msg); 99 | $ctx->miscService->logAction($userid, ($json->solved ? 'solved' : 'failed') . " {$task->id}"); 100 | 101 | if ($json->solved && $json->gainedPoints > 0) { 102 | $nowSolved = $userData->solved + 1; //we haven't reloaded UD after update 103 | $json->numSolved = $nowSolved; 104 | $rank = $ctx->userService->rankAsNumber($nowSolved); 105 | $rankOld = $ctx->userService->rankAsNumber($userData->solved); 106 | if ($rank != $rankOld) { 107 | $rank = $ctx->userService->rank($nowSolved); 108 | $ctx->miscService->postToMessHall($userid, 109 | "I'm excited to announce I've achieved " 110 | . "$rank rank!!!"); 111 | } 112 | } 113 | 114 | echo json_encode($json); 115 | -------------------------------------------------------------------------------- /ctl/task/Edit.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $id = $ctx->util->paramGet('id'); 9 | $vol = $ctx->util->paramGet('vol'); 10 | 11 | if (is_numeric($id)) { 12 | $model->task = $ctx->tasksDao->read($id); 13 | $taskdata = $ctx->taskDataDao->makeLookup('type', "taskid = $id"); 14 | $model->task->title = htmlentities($model->task->title); 15 | $model->task->text = base64_decode($taskdata['text']->data); 16 | $model->task->checker = base64_decode($taskdata['checker']->data); 17 | } else { 18 | $model->task = new stdClass(); 19 | $model->task->id = null; 20 | $model->task->title = ''; 21 | $model->task->url = ''; 22 | $model->task->author = ''; 23 | $model->task->volumeid = ''; 24 | $model->task->shown = 0; 25 | $model->task->text = "(problem statement in markdown format, please)"; 26 | $model->task->checker = ""; 27 | } 28 | 29 | 30 | array_push($ctx->elems->styles, 'codemirror'); 31 | array_push($ctx->elems->scripts, '_cm/codemirror'); 32 | array_push($ctx->elems->scripts, '_cm/clike'); 33 | array_push($ctx->elems->scripts, '_cm/php'); 34 | array_push($ctx->elems->scripts, '_cm/markdown'); 35 | array_push($ctx->elems->scripts, '_cm/xml'); 36 | array_push($ctx->elems->scripts, '_cm/matchbrackets'); 37 | -------------------------------------------------------------------------------- /ctl/task/List.php: -------------------------------------------------------------------------------- 1 | title = 'Problems'; 4 | 5 | $model->addingAllowed = $ctx->auth->admin(); 6 | $model->isUser = $ctx->auth->user(); 7 | 8 | $param = $ctx->util->paramGet('param'); 9 | if (!$ctx->miscService->validUrlParam($param)) { 10 | $param = ''; 11 | } 12 | $sort = $ctx->util->paramGet('sort'); 13 | if (!in_array($sort, array('tre1', 'num1', 'id1', 'num0', 'id0'))) { 14 | if ($ctx->auth->loggedUser()) { 15 | $sort = $ctx->util->sessionGet('task-list-sort'); 16 | } 17 | $sort = empty($sort) ? $ctx->elems->conf->defTaskSort : $sort; 18 | } else { 19 | if ($ctx->auth->loggedUser()) { 20 | $ctx->util->sessionPut('task-list-sort', $sort); 21 | } 22 | } 23 | $model->sort = $sort; 24 | $sortlen = strlen($sort) - 1; 25 | $sort = array(substr($sort, 0, $sortlen), substr($sort, $sortlen)); 26 | 27 | $tasks = null; 28 | if (!empty($param)) { 29 | $tag = $ctx->tagsDao->findFirst("title = '$param'"); 30 | if (is_object($tag)) { 31 | $tasks = $ctx->taskService->loadTasks($tag->id); 32 | $model->filterTag = $tag->title; 33 | $model->volume = $ctx->elems->conf->taskVolumes[$tag->title] ?? null; 34 | } else { 35 | $ctx->util->flash("No such tag"); 36 | $ctx->util->redirect('task_list'); 37 | return; 38 | } 39 | } 40 | if (empty($tasks)) { 41 | $tasks = $ctx->taskService->loadTasks(null); 42 | } 43 | $model->c1ids = $ctx->taskTagsDao->makeLookup('taskid', 44 | "tagid = (select id from {$ctx->tagsDao->getTable()} where title = 'c-1')"); 45 | if ($sort[0] == 'id') { 46 | usort($tasks, function($a, $b) { 47 | return $a->id - $b->id; 48 | }); 49 | } elseif ($sort[0] == 'tre') { 50 | $sortCnt = $ctx->tasksDao->getCount() + 1; 51 | usort($tasks, function($a, $b) use($sortCnt) { 52 | $av = ($sortCnt - $a->id) / ($a->solved + 1); 53 | $bv = ($sortCnt - $b->id) / ($b->solved + 1); 54 | return ($av > $bv) - ($av < $bv); 55 | }); 56 | } 57 | 58 | if ($model->isUser) { 59 | $userid = $ctx->auth->loggedUser(); 60 | $failedTasks = $ctx->userTasksDao->makeLookup('taskid', "userid = $userid and solved < 0 and variant = 1"); 61 | $userTasks = $ctx->userTasksDao->makeLookup('taskid', "userid = $userid and variant = 0"); 62 | foreach ($failedTasks as $taskId => $taskRecord) { 63 | if (!isset($userTasks[$taskId])) { 64 | $userTasks[$taskId] = $taskRecord; 65 | } 66 | } 67 | $starred = $ctx->miscService->getTaggedValue("star.$userid"); 68 | if ($starred) { 69 | $starred = array_fill_keys(explode(',', $starred), 1); 70 | foreach ($tasks as &$task) 71 | if (isset($starred['' . $task->id])) 72 | $task->starred = 1; 73 | if ($sort[0] == 'tre') { 74 | $tasks1 = []; 75 | $tasks2 = []; 76 | foreach ($tasks as &$task) { 77 | if ($task->starred) 78 | $tasks1[] = $task; 79 | else 80 | $tasks2[] = $task; 81 | } 82 | $tasks = array_merge($tasks1, $tasks2); 83 | } 84 | } 85 | } 86 | 87 | $translations = $ctx->miscService->getTaggedValues('tran-'); 88 | 89 | $states = array(-1 => 'tried', 0 => 'waiting', 1 => 'solved'); 90 | 91 | $headPart = array(); 92 | $tailPart = array(); 93 | 94 | foreach ($tasks as $task) { 95 | $task->solved = $ctx->strUtils->zeroDash($task->solved); 96 | if (!$task->shown) { 97 | if (!$model->addingAllowed) { 98 | continue; 99 | } 100 | $task->solved = 'hid'; 101 | } 102 | $task->cost = number_format($task->cost, 2); 103 | $task->shortUrl = $task->url; 104 | $task->url = url('task_view', 'param', $task->url); 105 | if ($model->addingAllowed) { 106 | $task->editurl = url('task_edit', 'id', $task->id); 107 | } 108 | if ($model->isUser && isset($userTasks[$task->id])) { 109 | $task->state = $states[$userTasks[$task->id]->solved]; 110 | } else { 111 | $task->state = ''; 112 | } 113 | if ($task->state == 'solved' && $sort[1]) { 114 | $tailPart[] = $task; 115 | } else { 116 | $headPart[] = $task; 117 | } 118 | if (isset($translations['tran-' . $task->id])) { 119 | $tongues = explode(' ', $translations['tran-' . $task->id]); 120 | foreach ($tongues as $i => $tongue) { 121 | $urlLocalised = "{$task->url}--$tongue"; 122 | $localeTitle = $ctx->localeService->LOCALES_ARRAY[$tongue]; 123 | $tongueUpper = strtoupper($tongue); 124 | $tongues[$i] = "$tongueUpper"; 125 | } 126 | $task->translations = implode(' ', $tongues); 127 | } else { 128 | $task->translations = ''; 129 | } 130 | } 131 | 132 | $model->tasks = array_merge($headPart, $tailPart); 133 | 134 | $ctx->elems->title = $model->title; 135 | $ctx->elems->description = 'List of programming problems and exercises from beginner to advanced level'; 136 | $ctx->elems->analytics = true; 137 | -------------------------------------------------------------------------------- /ctl/task/Preparedata.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | $userid = $ctx->auth->loggedUser(); 6 | 7 | if (!$userid || !is_numeric($taskid)) { 8 | $ctx->util->changePage('error404'); 9 | return; 10 | } 11 | 12 | $data = $ctx->taskService->prepareData($taskid); 13 | 14 | $ctx->util->plainOutput($data); 15 | -------------------------------------------------------------------------------- /ctl/task/Save.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->redirect('task_list'); 5 | return; 6 | } 7 | 8 | $taskid = $ctx->util->paramPost('id'); 9 | 10 | $task = null; 11 | if (is_numeric($taskid)) { 12 | $task = $ctx->tasksDao->read($taskid); 13 | } 14 | 15 | $justCreated = false; 16 | if (!is_object($task)) { 17 | $taskid = null; 18 | $task = new stdClass(); 19 | $justCreated = true; 20 | } 21 | 22 | $task->id = $taskid; 23 | $task->title = $ctx->util->paramPost('title'); 24 | $task->url = $ctx->util->paramPost('url'); 25 | $task->author = $ctx->util->paramPost('author'); 26 | $task->lastmod = date('Y-m-d'); 27 | $task->shown = $ctx->util->paramPost('shown') ? 1 : 0; 28 | $statement = $ctx->util->paramPost('statement'); 29 | $statement = $ctx->util->sillyDecode($statement); 30 | $checker = $ctx->util->paramPost('checker'); 31 | $checker = $ctx->util->sillyDecode($checker); 32 | 33 | if (empty($task->id)) { 34 | unset($task->id); 35 | } 36 | if (empty($task->author)) { 37 | unset($task->author); 38 | } 39 | if (empty($task->volumeid)) { 40 | unset($task->volumeid); 41 | } 42 | 43 | if (!$task->title || !$statement || !$checker) { 44 | $ctx->util->changePage('message'); 45 | $model->msg = 'Insufficient data'; 46 | return; 47 | } 48 | 49 | $taskid = $ctx->tasksDao->save($task); 50 | 51 | $data = $ctx->taskDataDao->findFirst("taskid = $taskid and type = 'text'"); 52 | if (!is_object($data)) { 53 | $data = new stdClass(); 54 | $data->taskid = $taskid; 55 | $data->type = 'text'; 56 | } 57 | $data->data = base64_encode($statement); 58 | $ctx->taskDataDao->save($data); 59 | 60 | $data = $ctx->taskDataDao->findFirst("taskid = $taskid and type = 'checker'"); 61 | if (!is_object($data)) { 62 | $data = new stdClass(); 63 | $data->taskid = $taskid; 64 | $data->type = 'checker'; 65 | } 66 | $data->data = base64_encode($checker); 67 | $ctx->taskDataDao->save($data); 68 | 69 | if ($justCreated) { 70 | $tagObject = $ctx->tagsDao->findFirst("title = 'unlabeled'"); 71 | $assignment = new \stdClass(); 72 | $assignment->tagid = $tagObject->id; 73 | $assignment->taskid = $taskid; 74 | $ctx->taskTagsDao->save($assignment); 75 | } 76 | 77 | $ctx->util->redirect(url('task_view', 'param', $task->url)); 78 | -------------------------------------------------------------------------------- /ctl/task/Solution.php: -------------------------------------------------------------------------------- 1 | util->paramGet('task'); 4 | $userurl = $ctx->util->paramGet('user'); 5 | $language = $ctx->util->paramGet('lang'); 6 | $key = $ctx->util->paramGet('key'); 7 | 8 | $langArray = $ctx->langService->languagesArray(); 9 | 10 | if (!$ctx->miscService->validUrlParams($taskurl, $userurl) || !in_array($language, $langArray)) { 11 | $ctx->util->changePage('error404'); 12 | return; 13 | } 14 | 15 | $currentUserId = $ctx->auth->loggedUser(); 16 | 17 | if (!$currentUserId && !$key) { 18 | $ctx->util->changePage('message'); 19 | $model->msg = "Excuse us, but you need to be logged in and to solve the task to view other's solution!"; 20 | return; 21 | } 22 | 23 | $ts = $key ? substr($key, 24) : base_convert(time(), 10, 16); 24 | $toHash = "{$ctx->elems->conf->viewSolutionSecret}+$ts+$taskurl+$userurl+$language"; 25 | $h = substr(hash('sha256', $toHash), 0, 24); 26 | if ($key) { 27 | $tsd = base_convert($ts, 16, 10); 28 | if ($h . $ts != $key || $tsd < time() - 86400*7) { 29 | $ctx->util->changePage('message'); 30 | $model->msg = "Link is either broken or expired..."; 31 | return; 32 | } 33 | } 34 | 35 | $task = $ctx->tasksDao->findFirst("url = '$taskurl'"); 36 | $user = $ctx->usersDao->findFirst("url = '$userurl'"); 37 | 38 | if (!is_object($task) || !is_object($user)) { 39 | $ctx->util->changePage('error404'); 40 | return; 41 | } 42 | 43 | $model->key = ($currentUserId == $user->id) ? $h . $ts : ''; 44 | 45 | if ($ctx->util->paramGet('plain') && $currentUserId == $user->id) { 46 | try { 47 | list($usertask, $solution) = $ctx->taskService->loadSolution($task->id, $user->id, $language); 48 | $solution = $solution->solution; 49 | } catch (\Exception $e) { 50 | $solution = 'Code loading failed :('; 51 | } 52 | $ctx->util->plainOutput($solution); 53 | return; 54 | } 55 | 56 | if ($ctx->challengeService->challengeExists($task->id) 57 | && ($currentUserId != $user->id && !$ctx->auth->admin())) { 58 | $ctx->util->redirect(url('task_chlng_stats', 'param', $task->url)); 59 | $ctx->util->flash("You can't see solutions for Challenges!"); 60 | return; 61 | } 62 | 63 | $model->solution = $ctx->taskService->viewSolution($task, $user, $language, $key !== null); 64 | 65 | $model->changeLangAllowed = ($currentUserId === $user->id || $ctx->auth->admin()); 66 | 67 | $model->highlight = (!empty($model->solution->language) && $model->solution->language != 'other') 68 | ? strtolower($model->solution->language) : ''; 69 | 70 | if ($model->changeLangAllowed && !$model->solution->error) { 71 | $model->language = strtolower($model->solution->language); 72 | $model->languages = $ctx->langService->languagesArray(); 73 | } 74 | 75 | $ctx->elems->styles[] = 'jqui'; 76 | $ctx->elems->styles[] = 'highlight'; 77 | $ctx->elems->scripts[] = 'jqui'; 78 | $ctx->elems->scripts[] = 'highlight'; 79 | 80 | $ctx->elems->robots = 'noindex,follow'; 81 | $ctx->elems->title = 'View solution'; 82 | $ctx->elems->analytics = true; 83 | 84 | -------------------------------------------------------------------------------- /ctl/task/Solvers.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | $language = $ctx->util->paramGet('lang'); 5 | 6 | if (!$ctx->miscService->validUrlParam($taskurl) 7 | || (!empty($language) && !array_key_exists($language, $ctx->elems->conf->languages))) { 8 | $ctx->util->changePage('error404'); 9 | return; 10 | } 11 | 12 | $task = $ctx->tasksDao->findFirst("url = '$taskurl'"); 13 | 14 | if (!is_object($task)) { 15 | $ctx->util->flash($taskurl); 16 | $ctx->util->changePage('error404'); 17 | return; 18 | } 19 | 20 | if ($ctx->challengeService->challengeExists($task->id)) { 21 | $ctx->util->redirect(url('task_chlng_stats', 'param', $task->url)); 22 | return; 23 | } 24 | 25 | $criteria = "solved = 1 and taskid = {$task->id}"; 26 | if (!empty($language)) { 27 | $criteria .= " and language = '$language'"; 28 | } 29 | $ids = $ctx->userTasksDao->solvers($criteria, !$ctx->util->paramGet('withblanks')); 30 | shuffle($ids); 31 | if (count($ids) > 15) { 32 | $limit = $ctx->util->paramGet('limit'); 33 | $ids = array_slice($ids, 0, !!$limit ? min(100, intval($limit)) : 15); 34 | } 35 | 36 | $res = array(); 37 | foreach ($ids as $utid) { 38 | $ut = $ctx->userTasksDao->read($utid); 39 | $user = $ctx->usersDao->read($ut->userid); 40 | $entry = new stdClass(); 41 | $entry->url = $user->url; 42 | $entry->username = $user->username; 43 | $entry->language = $ut->language; 44 | $res[] = $entry; 45 | } 46 | 47 | $model->task = $task; 48 | $model->users = $res; 49 | 50 | $loadNotes = true; 51 | if (!$ctx->taskService->isAdminOrAuthor($task)) { 52 | if (!$ctx->auth->loggedUser()) { 53 | $loadNotes = false; 54 | } else { 55 | $usertask = $ctx->userTasksDao->findFirst("solved = 1 and taskid = {$task->id} and userid = " . $ctx->auth->loggedUser()); 56 | $loadNotes = is_object($usertask); 57 | } 58 | } 59 | 60 | if ($loadNotes) { 61 | $model->notes = $model->notes = $ctx->taskService->loadNotes($task->id); 62 | } else { 63 | $model->notes = 'You should solve the problem to see these hints!'; 64 | } 65 | 66 | $model->language = $language; 67 | $model->languages = $ctx->langService->languagesArray(); 68 | 69 | $ctx->elems->robots = 'noindex,nofollow'; 70 | $ctx->elems->title = 'Solution list'; 71 | $ctx->elems->analytics = true; 72 | 73 | -------------------------------------------------------------------------------- /ctl/task/Star.php: -------------------------------------------------------------------------------- 1 | auth->user()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $ctx->util->plainOutput(''); 9 | 10 | $userid = $ctx->auth->loggedUser(); 11 | $taskid = $ctx->util->paramPost('task'); 12 | $star = $ctx->util->paramPost('star'); 13 | 14 | if (!is_numeric($taskid) || !in_array($star, ['0','1'], true)) { 15 | echo "badparams"; 16 | return; 17 | } 18 | 19 | $tag = "star.$userid"; 20 | $starred = $ctx->miscService->getTaggedValue($tag); 21 | echo "already starred: $starred\n"; 22 | $starred = $starred ? explode(',', $starred) : []; 23 | $exists = array_search($taskid, $starred); 24 | if ($star) { 25 | if ($exists !== false) return; 26 | $starred[] = $taskid; 27 | echo "added star\n"; 28 | } else { 29 | if ($exists === false) return; 30 | array_splice($starred, $exists, 1); 31 | echo "removed star\n"; 32 | } 33 | echo "remaining starred: " . json_encode($starred) . "\n"; 34 | $ctx->miscService->setTaggedValue($tag, 35 | $starred ? implode(',', $starred) : null); 36 | -------------------------------------------------------------------------------- /ctl/task/Success.php: -------------------------------------------------------------------------------- 1 | auth->user()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $inputObj = base64_decode($ctx->util->paramPost('obj')); 9 | $input = json_decode($inputObj); 10 | 11 | $model->solved = $input->solved; 12 | $model->gainedPoints = $input->gainedPoints; 13 | $model->userPoints = $input->userPoints; 14 | $model->task = $input->task; 15 | $taskid = $model->task->id; 16 | 17 | $userid = $ctx->auth->loggedUser(); 18 | $userData = $ctx->userDataDao->findFirst("userid = $userid"); 19 | 20 | $rndPrimes = array(13, 17, 19, 23, 29, 31, 37); 21 | $model->userRnd = $rndPrimes[$userid % count($rndPrimes)]; 22 | $model->numSolved = $userData->solved; 23 | 24 | 25 | $model->challengeResult = $input->challengeResult ?? null; 26 | 27 | $model->notes = $ctx->taskService->loadNotes($taskid); 28 | 29 | $model->nextTasks = $ctx->tasksDao->find( 30 | "solved < {$model->task->solved} order by solved desc", 5); 31 | if (count($model->nextTasks) > 3) { 32 | $model->nextTasks = array_slice($model->nextTasks, rand(0, 2), 3); 33 | } 34 | $recom = $ctx->miscService->getTaggedValue("recom-$taskid"); 35 | if ($recom) { 36 | $recom = str_replace(' ', ',', $recom); 37 | $recomTasks = $ctx->tasksDao->find("id in ($recom)"); 38 | array_splice($model->nextTasks, 0, 0, $recomTasks); 39 | } 40 | 41 | $ctx->elems->scripts[] = 'task/attempt'; 42 | -------------------------------------------------------------------------------- /ctl/task/Testchecker.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $code = file_get_contents("php://input"); 9 | 10 | echo $ctx->taskService->testChecker($code); 11 | 12 | $ctx->util->changePage(null); 13 | -------------------------------------------------------------------------------- /ctl/task/Text.php: -------------------------------------------------------------------------------- 1 | auth->loggedUser()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $url = $ctx->util->paramGet('param'); 9 | if (!$ctx->miscService->validUrlParam($url)) { 10 | $ctx->util->changePage('error404'); 11 | return; 12 | } 13 | 14 | $task = $ctx->tasksDao->findFirst("url = '$url'"); 15 | if (!is_object($task)) { 16 | $ctx->util->changePage('error404'); 17 | return; 18 | } 19 | 20 | $taskdata = $ctx->taskDataDao->findFirst("taskid = {$task->id} and type = 'text'"); 21 | 22 | $ctx->util->plainOutput(base64_decode($taskdata->data)); 23 | -------------------------------------------------------------------------------- /ctl/task/View.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | 5 | if ($url == null || !$ctx->miscService->validUrlParam($url)) { 6 | $ctx->util->changePage('error404'); 7 | return; 8 | } 9 | 10 | list($url, $locale) = $ctx->localeService->parseLocale($url); 11 | 12 | $model->task = $ctx->tasksDao->findFirst("url = '$url'"); 13 | 14 | if (!is_object($model->task)) { 15 | $ctx->util->changePage('error404'); 16 | return; 17 | } 18 | 19 | $model->tags = $ctx->taskService->tagNamesForTask($model->task->id); 20 | 21 | $userid = $ctx->auth->loggedUser(); 22 | 23 | $model->task->statement = $ctx->taskService->loadStatement($model->task->id, $locale); 24 | 25 | if (empty($model->task->statement)) { 26 | $ctx->util->changePage('error404'); 27 | return; 28 | } 29 | 30 | $model->textDirection = $ctx->localeService->direction($locale); 31 | 32 | $alternativeLocales = $ctx->localeService->availableTaskLocales($model->task->id); 33 | $model->task->locales = empty($locale) ? $alternativeLocales : array('en' => 'English'); 34 | 35 | if (!empty($alternativeLocales)) { 36 | $ctx->elems->locales = array('en' => $ctx->util->fullUrl( 37 | url('task_view', 'param', $model->task->url))); 38 | foreach ($alternativeLocales as $localeCode => $localeName) { 39 | $ctx->elems->locales[$localeCode] = $ctx->util->fullUrl( 40 | url('task_view', 'param', $model->task->url . "--$localeCode")); 41 | } 42 | } 43 | 44 | if ($ctx->auth->user()) { 45 | $user = $ctx->usersDao->findFirst("id = $userid"); 46 | $userdata = $ctx->userdataDao->findFirst("userid = $userid"); 47 | $usertasks = $ctx->userTasksDao->find("taskid = {$model->task->id} and userid = $userid"); 48 | $model->suspended = $ctx->cheatService->isSuspended($userid); 49 | $model->codes = array(); 50 | foreach ($usertasks as $ut) { 51 | $model->codes[$ut->language] = url('task_solution', 'user', $user->url, 'task', $model->task->url, 'lang', urlencode($ut->language)); 52 | } 53 | 54 | $model->languages = $ctx->langService->languagesArray(); 55 | 56 | if ($model->task->author == $user->url) { 57 | $model->checkerCode = str_replace('taskService->loadChecker($model->task->id)); 58 | } 59 | 60 | $starred = $ctx->miscService->getTaggedValue("star.{$user->id}"); 61 | $model->starred = $starred 62 | ? in_array($model->task->id, explode(',', $starred)) : false; 63 | 64 | $ctx->elems->scripts[] = 'task/_view'; 65 | $ctx->elems->scripts[] = '_ace/ace'; 66 | $ctx->elems->scripts[] = '_sql/sql-wasm'; 67 | } 68 | 69 | if (!$userid) { 70 | $ctx->miscService->headerLastModified($model->task->lastmod); 71 | } 72 | 73 | $ctx->elems->title = $model->task->title; 74 | 75 | $model->challenge = $ctx->challengeService->challengeExists($model->task->id); 76 | if ($model->challenge) { 77 | $model->arena = $ctx->challengeService->arenaExists($model->task->id); 78 | } 79 | 80 | if (!empty($locale) && $locale != 'en') { 81 | $titlematch = array(); 82 | if (preg_match('/\/', 83 | $model->task->statement, $titlematch)) { 84 | $model->task->title = $titlematch[1]; 85 | } 86 | $ctx->elems->title .= " ({$alternativeLocales[$locale]})"; 87 | } 88 | $ctx->elems->keywords = $model->tags; 89 | $ctx->elems->styles[] = 'jsmonoterm'; 90 | $ctx->elems->scripts[] = 'jsmonoterm'; 91 | $ctx->elems->analytics = true; 92 | -------------------------------------------------------------------------------- /ctl/task/tag/Assign.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $tag = $ctx->util->paramPost('tag'); 9 | $taskid = $ctx->util->paramPost('task'); 10 | 11 | if (!is_numeric($taskid)) { 12 | $ctx->util->redirect('task_tag_edit'); 13 | $ctx->util->flash("No task chosen!"); 14 | return; 15 | } 16 | 17 | $returnLink = url('task_tag_edit', 'param', $taskid); 18 | 19 | $tag = strtolower(trim($tag)); 20 | 21 | $tagObject = $ctx->tagsDao->findFirst("title = '$tag'"); 22 | 23 | if (!is_object($tagObject)) { 24 | $ctx->util->redirect($returnLink); 25 | $ctx->util->flash("No such tag!"); 26 | return; 27 | } 28 | 29 | $assignment = $ctx->taskTagsDao->findFirst("tagid = {$tagObject->id} and taskid = $taskid"); 30 | 31 | if (is_object($assignment)) { 32 | $ctx->taskTagsDao->delete($assignment->id); 33 | $ctx->util->flash("Unassigned: $tag"); 34 | } else { 35 | $assignment = new \stdClass(); 36 | $assignment->tagid = $tagObject->id; 37 | $assignment->taskid = $taskid; 38 | $ctx->taskTagsDao->save($assignment); 39 | $ctx->util->flash("Assigned: $tag"); 40 | } 41 | 42 | $ctx->util->redirect($returnLink); 43 | 44 | -------------------------------------------------------------------------------- /ctl/task/tag/Edit.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $taskid = $ctx->util->paramGet('param'); 9 | 10 | $model->tags = $ctx->tagsDao->makeLookup('id'); 11 | 12 | if (!empty($taskid)) { 13 | $model->task = $ctx->tasksDao->read($taskid); 14 | $model->taskTags = $ctx->taskService->tagNamesForTask($taskid); 15 | } else { 16 | $model->task = null; 17 | $model->taskTags = array(); 18 | } 19 | 20 | -------------------------------------------------------------------------------- /ctl/task/tag/List.php: -------------------------------------------------------------------------------- 1 | tags = $ctx->tagsDao->find(); 4 | 5 | if ($ctx->auth->user()) { 6 | shuffle($model->tags); 7 | } 8 | 9 | $ctx->elems->scripts[] = 'cloud'; 10 | $ctx->elems->title = 'Tags for Problems'; 11 | $ctx->elems->analytics = true; 12 | -------------------------------------------------------------------------------- /ctl/task/tag/Update.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $tag = $ctx->util->paramPost('tag'); 9 | $taskid = $ctx->util->paramPost('task'); 10 | 11 | $returnLink = url('task_tag_edit', 'param', $taskid); 12 | 13 | $tag = strtolower(trim($tag)); 14 | 15 | if (!preg_match('/^[a-z]+(?:\-[a-z0-9]+)*$/', $tag)) { 16 | $ctx->util->redirect($returnLink); 17 | $ctx->util->flash("Bad tag title"); 18 | return; 19 | } 20 | 21 | $existing = $ctx->tagsDao->findFirst("title = '$tag'"); 22 | if (is_object($existing)) { 23 | $cnt = $ctx->taskTagsDao->getCount("tagid = {$existing->id}"); 24 | if ($cnt > 0) { 25 | $ctx->util->flash("Some tasks have this tag"); 26 | } else { 27 | $ctx->tagsDao->delete($existing->id); 28 | $ctx->util->flash("Removed: {$existing->title}"); 29 | } 30 | } else { 31 | $entity = new \stdClass(); 32 | $entity->title = $tag; 33 | $ctx->tagsDao->save($entity); 34 | $ctx->util->flash("Added: {$entity->title}"); 35 | } 36 | 37 | $ctx->util->redirect($returnLink); 38 | 39 | -------------------------------------------------------------------------------- /ctl/tools/Calcpoints.php: -------------------------------------------------------------------------------- 1 | elems->conf->calcPointsSecret 4 | || $ctx->util->paramGet('param') != $ctx->elems->conf->calcPointsSecret) { 5 | $ctx->util->changePage('error404'); 6 | return; 7 | } 8 | 9 | $timeStart = microtime(true); 10 | 11 | $ctx->util->plainOutput("Calculations: \n"); 12 | 13 | $taskPoints = $ctx->miscService->calcPoints(); 14 | 15 | $timeEnd = microtime(true); 16 | $deltaTime = number_format(($timeEnd - $timeStart), 3); 17 | 18 | echo implode('', $taskPoints); 19 | echo "\nPoints Calculation completed in $deltaTime seconds\n"; 20 | -------------------------------------------------------------------------------- /ctl/user/Profile.php: -------------------------------------------------------------------------------- 1 | auth->user() ? $ctx->auth->loggedUser() : null; 5 | 6 | $url = $ctx->util->paramGet('param'); 7 | if ($url) { 8 | if (is_numeric($url) && $url != '1') { 9 | $user = $ctx->usersDao->read($url); 10 | $ctx->util->redirect(url('user_profile', 'param', $user->url)); 11 | return; 12 | } 13 | $user = $ctx->userService->byUrl($url); 14 | if (is_object($user)) { 15 | $userid = $user->id; 16 | } 17 | } elseif ($loggedUser) { 18 | $user = $ctx->usersDao->read($loggedUser); 19 | $ctx->util->redirect(url('user_profile', 'param', $user->url)); 20 | return; 21 | } 22 | 23 | if (!is_numeric($userid)) { 24 | $userid = $loggedUser; 25 | } 26 | 27 | if (!is_numeric($userid)) { 28 | $ctx->util->changePage('error404'); 29 | return; 30 | } 31 | 32 | $model->friendType = ($loggedUser !== null && $loggedUser !== $userid) ? $ctx->friendService->getFriendship($loggedUser, $userid) : null; 33 | $model->followedByCount = $ctx->friendService->followedByCount($userid); 34 | $model->followingCount = $ctx->friendService->followingCount($userid); 35 | 36 | if (empty($user) || !is_object($user)) { 37 | $user = $ctx->usersDao->read($userid); 38 | } 39 | $userdata = $ctx->userDataDao->findFirst("userid = $userid"); 40 | 41 | if (!is_object($user) || !is_object($userdata)) { 42 | $ctx->util->changePage('error404'); 43 | return; 44 | } 45 | 46 | $regType = substr($user->loginid, 0, 2); 47 | 48 | switch ($regType) { 49 | case 'gh': 50 | $user->socialnet = 'GitHub'; 51 | $user->socialurl = 'https://github.com/' . preg_replace('/^.+\.(.+)$/', '\1', $user->loginid); 52 | break; 53 | default: 54 | $user->socialurl = null; 55 | } 56 | 57 | $userdata->created = $ctx->miscService->formatDate($userdata->created); 58 | $userdata->lastlogin = $ctx->miscService->formatDate($userdata->lastlogin, true); 59 | $model->data = $userdata; 60 | $model->user = $user; 61 | $model->cheat = $ctx->cheatService->status($user->id); 62 | $model->data->rank = $ctx->userService->rank($userdata->solved); 63 | $model->tasks = $ctx->userService->solvedTasks($user->id); 64 | $model->authored = $ctx->tasksDao->find("author = '{$user->url}'"); 65 | $model->c1tagged = $ctx->userService->solvedTaggedTasks($user->id); 66 | $model->awards = $ctx->certService->forUser($user->id); 67 | $model->total = $ctx->userRankDao->getCount('solved > 0'); 68 | 69 | $model->countries = null; 70 | $model->isCurrentUser = ($userid === $ctx->auth->loggedUser()); 71 | $model->bannerUrl = $ctx->util->fullUrl(url('user_banner', 'param', $user->url . '.png'), 'https://'); 72 | 73 | $personalInfo = $ctx->taskDataDao->findFirst("taskid = $userid and type = 'uinfo'"); 74 | if (is_object($personalInfo)) { 75 | $ctx->markdown->no_markup = true; 76 | $model->personalInfo = trim($ctx->markdown->parse(base64_decode($personalInfo->data))); 77 | $ctx->markdown->no_markup = false; 78 | } else { 79 | $model->personalInfo = null; 80 | } 81 | 82 | $model->country = $ctx->miscService->countryNameByCode($userdata->country); 83 | 84 | $model->fbLike = array( 85 | 'url' => $ctx->util->fullUrl(url('user_profile', 'param', $model->user->url)), 86 | 'image' => $userdata->avatar, 87 | 'title' => "{$model->user->username} - watch my success at CodeAbbey!"); 88 | 89 | $ctx->elems->robots = $userdata->solved >= 5 ? 'index,follow' : 'noindex,nofollow'; 90 | $ctx->elems->title = $user->username . ' - user info'; 91 | $ctx->elems->analytics = true; 92 | 93 | -------------------------------------------------------------------------------- /ctl/user/Ranking.php: -------------------------------------------------------------------------------- 1 | util->paramGet('friends'); 4 | 5 | $pageFromForm = $ctx->util->paramPost('pf'); 6 | if (is_numeric($pageFromForm)) { 7 | $ctx->util->redirect(url('user_ranking', 'p', $pageFromForm - 1)); 8 | return; 9 | } 10 | 11 | if ($ctx->util->paramGet('clr')) { 12 | $ctx->util->sessionDel('ranking-country'); 13 | $ctx->util->sessionDel('ranking-language'); 14 | $ctx->util->redirect(url('user_ranking')); 15 | return; 16 | } 17 | 18 | $model->country = $ctx->util->paramPost('country'); 19 | if (empty($model->country)) { 20 | $model->country = $ctx->util->sessionGet('ranking-country'); 21 | } 22 | $model->language = $ctx->util->paramPost('lang'); 23 | if (empty($model->language)) { 24 | $model->language = $ctx->util->sessionGet('ranking-language'); 25 | } 26 | 27 | $model->userid = $ctx->auth->loggedUser(); 28 | if (!is_numeric($model->userid)) { 29 | $model->friends = null; 30 | } else { 31 | $model->friends = $friends ? $model->userid : null; 32 | } 33 | 34 | $countries = $ctx->countriesDao->makeLookup('code'); 35 | if (!isset($countries[$model->country])) { 36 | $model->country = ''; 37 | } 38 | $model->languages = $ctx->langService->languagesArray(); 39 | if (!isset($model->languages[$model->language])) { 40 | $model->language = ''; 41 | } 42 | 43 | if ($model->friends === null) { 44 | $page = $ctx->util->paramGet('p'); 45 | $count = $ctx->userService->rankingPageSize; 46 | if (!is_numeric($page) || $page < 0 || $page > 100000000) { 47 | $page = 0; 48 | } else { 49 | $page = floor($page); 50 | } 51 | 52 | $query = 'solved > 0'; 53 | if (!empty($model->country)) { 54 | $query .= " and country = '{$model->country}'"; 55 | $ctx->util->sessionPut('ranking-country', $model->country); 56 | } 57 | if (!empty($model->language)) { 58 | $query .= " and language = '{$model->language}'"; 59 | $ctx->util->sessionPut('ranking-language', $model->language); 60 | } 61 | } else { 62 | $friendIds = $ctx->friendService->followingAllIds($model->userid); 63 | if (!in_array($model->userid, $friendIds)) { 64 | $friendIds[] = $model->userid; 65 | } 66 | $page = 0; 67 | $count = count($friendIds); 68 | $friendIdsStr = implode(',', $friendIds); 69 | $query = "id in ($friendIdsStr)"; 70 | } 71 | $model->total = $ctx->userRankDao->getCount($query); 72 | $model->rank = $ctx->userRankDao->find($query, $count, $page * $count); 73 | $model->page = $page; 74 | $model->count = $count; 75 | 76 | 77 | $userPresent = false; 78 | $loggedUser = $ctx->auth->user() ? $ctx->auth->loggedUser() : false; 79 | 80 | foreach ($model->rank as $entry) { 81 | if ($loggedUser !== false && $entry->id == $loggedUser) { 82 | $userPresent = true; 83 | $entry->current = true; 84 | } else { 85 | $entry->current = false; 86 | } 87 | $ctx->userService->additionalRankingData($entry, $countries); 88 | } 89 | 90 | if ($loggedUser !== false && !$userPresent) { 91 | $model->myRank = $ctx->userRankDao->findFirst("id = $loggedUser"); 92 | $ctx->userService->additionalRankingData($model->myRank, $countries); 93 | $model->myRank->current = true; 94 | $model->myRank->before = $model->myRank->rankpos < $model->rank[0]->rankpos; 95 | } else { 96 | $model->myRank = null; 97 | } 98 | 99 | $model->countries = $countries; 100 | 101 | $ctx->elems->robots = $page < 5 ? 'index,follow' : 'noindex,nofollow'; 102 | $ctx->elems->title = 'User ranking'; 103 | $ctx->elems->analytics = true; 104 | 105 | -------------------------------------------------------------------------------- /ctl/user/Settings.php: -------------------------------------------------------------------------------- 1 | auth->user()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $user = $ctx->usersDao->read($ctx->auth->loggedUser()); 9 | 10 | $model->username = $user->username; 11 | 12 | $userdata = $ctx->userDataDao->findFirst("userid = {$user->id}"); 13 | 14 | $model->country = $userdata->country; 15 | 16 | $model->countries = $ctx->countriesDao->find(); 17 | foreach ($model->countries as $land) { 18 | $land->title = $land->code . ' - ' . $land->title; 19 | } 20 | 21 | $loginType = substr($user->loginid, 0, 2); 22 | $model->usesPwd = (strlen($user->password) >= 8); 23 | $model->nameForChange = (!$model->usesPwd || $userdata->solved >= $ctx->elems->conf->nameChangeLevel) 24 | ? $user->username : null; 25 | $model->email = ($loginType == '!!' 26 | ? preg_replace('/(.)[^\@]+(\@.+)/', '\1***\2', substr($user->loginid, 2)) 27 | : null); 28 | $model->ghname = ($loginType == 'gh') 29 | ? preg_replace('/.*\./', '', $user->loginid) : ''; 30 | 31 | $model->avatar = $userdata->avatar; 32 | 33 | $personalInfo = $ctx->taskDataDao->findFirst("taskid = {$user->id} and type = 'uinfo'"); 34 | $model->personalInfo = is_object($personalInfo) 35 | ? base64_decode($personalInfo->data) : ""; 36 | 37 | -------------------------------------------------------------------------------- /ctl/user/Unsolved.php: -------------------------------------------------------------------------------- 1 | util->paramGet('param'); 4 | $user = $ctx->userService->byUrl($url); 5 | if (!is_object($user)) { 6 | $ctx->util->changePage('error404'); 7 | return; 8 | } 9 | 10 | $model->userName = $user->username; 11 | $model->userUrl = $user->url; 12 | 13 | $userTasks = $ctx->userTasksDao->find("userid = {$user->id} and solved <= 0"); 14 | if (!empty($userTasks)) { 15 | $taskIds = $ctx->miscService->listIds($userTasks, 'taskid'); 16 | $tasks = $ctx->tasksDao->makeLookup('id', "id in ($taskIds)"); 17 | } 18 | 19 | $neverSolved = $ctx->userTasksDao->neverSolvedIds($user->id); 20 | 21 | $model->entries = array(); 22 | 23 | foreach ($userTasks as $entry) { 24 | $task = $tasks[$entry->taskid]; 25 | $entry->title = $task->title; 26 | $entry->taskUrl = url('task_view', 'param', $task->url); 27 | $entry->url = url('task_solution', 'user', $user->url, 'task', $task->url, 'lang', urlencode($entry->language)); 28 | $entry->ts = $ctx->miscService->formatDate($entry->ts); 29 | $entry->neverSolved = in_array($entry->taskid, $neverSolved); 30 | } 31 | 32 | usort($userTasks, function($a, $b) { 33 | return $a->taskid - $b->taskid; 34 | }); 35 | 36 | $model->records = $userTasks; 37 | 38 | $ctx->elems->robots = 'noindex,nofollow'; 39 | $ctx->elems->title = $user->username . ' - unsuccessful solutions'; 40 | $ctx->elems->analytics = true; 41 | -------------------------------------------------------------------------------- /ctl/user/settings/Avatar.php: -------------------------------------------------------------------------------- 1 | util->paramPost('url'); 4 | $userid = $ctx->auth->loggedUser(); 5 | 6 | if (empty($userid)) { 7 | $ctx->util->changePage('error404'); 8 | return; 9 | } 10 | 11 | $check = function($url) { 12 | if (preg_match('/^http[s]?\:\/\/[a-zA-Z0-9\-\_\.\/]+$/', $url) != 1) { 13 | return "Invalid URL!"; 14 | } 15 | $image = @getimagesize($url); 16 | if ($image === false) { 17 | return "Image loading failed"; 18 | } 19 | if ($image[0] < 100 || $image[1] < 100) { 20 | return "Image is too small - min 100px"; 21 | } 22 | if ($image[0] > 300 || $image[1] > 300) { 23 | return "Image is too large - max 300px"; 24 | } 25 | if ($image[2] != IMAGETYPE_JPEG && $image[2] != IMAGETYPE_JPEG2000 && $image[2] != IMAGETYPE_PNG) { 26 | return "Image should be JPEG or PNG " . $image[2]; 27 | } 28 | return ""; 29 | }; 30 | 31 | if (!empty($url)) { 32 | $message = $check($url); 33 | } else { 34 | $message = ""; 35 | $url = ""; 36 | } 37 | 38 | if ($message == "") { 39 | $userdata = $ctx->userDataDao->findFirst("userid = $userid"); 40 | $userdata->avatar = $url; 41 | $ctx->userDataDao->save($userdata); 42 | $ctx->util->flash("OK!"); 43 | } else { 44 | $ctx->util->flash($message); 45 | } 46 | 47 | $ctx->util->redirect("user_settings"); 48 | 49 | -------------------------------------------------------------------------------- /ctl/user/settings/Chname.php: -------------------------------------------------------------------------------- 1 | util->paramPost('newname'); 4 | 5 | if (!$ctx->auth->user() || empty($newname)) { 6 | $ctx->util->changePage('error404'); 7 | return; 8 | } 9 | 10 | $user = $ctx->usersDao->findFirst("id = " . $ctx->auth->loggedUser()); 11 | $userData = $ctx->userDataDao->findFirst("userid = {$user->id}"); 12 | 13 | $loginType = substr($user->loginid, 0, 2); 14 | if ($loginType == '!!') { 15 | if ($userData->solved < $ctx->elems->conf->nameChangeLevel) { 16 | $ctx->util->changePage('error404'); 17 | return; 18 | } 19 | } 20 | 21 | $checkName = $ctx->userService->checkNewUsername($newname, true); 22 | if ($checkName !== null) { 23 | $ctx->util->flash("Error: $checkName"); 24 | $ctx->util->redirect('user_profile'); 25 | return; 26 | } 27 | 28 | if (!$ctx->cheatService->isSuspended($user->id)) { 29 | $user->username = $newname; 30 | $ctx->usersDao->save($user); 31 | } 32 | 33 | $ctx->util->flash('Name was changed!'); 34 | $ctx->util->redirect('user_settings'); 35 | 36 | -------------------------------------------------------------------------------- /ctl/user/settings/Country.php: -------------------------------------------------------------------------------- 1 | util->paramPost('code'); 4 | $userid = $ctx->auth->loggedUser(); 5 | 6 | if (empty($userid) || empty($code) || !preg_match('/[a-z]{2,3}/i', $code)) { 7 | $ctx->util->changePage('error404'); 8 | return; 9 | } 10 | 11 | $country = $ctx->countriesDao->findFirst("code = '$code'"); 12 | 13 | if (!is_object($country)) { 14 | $ctx->util->changePage('error404'); 15 | return; 16 | } 17 | 18 | $userdata = $ctx->userDataDao->findFirst("userid = $userid"); 19 | $userdata->country = $code; 20 | $ctx->userDataDao->save($userdata); 21 | 22 | $ctx->util->flash('Country info updated!'); 23 | $ctx->util->redirect('user_settings'); 24 | -------------------------------------------------------------------------------- /ctl/user/settings/Email.php: -------------------------------------------------------------------------------- 1 | util->paramPost('newemail'); 4 | $pwd = $ctx->util->paramPost('chkpwd'); 5 | $userid = $ctx->auth->loggedUser(); 6 | 7 | if (empty($userid) || is_null($email) || is_null($pwd)) { 8 | $ctx->util->changePage('error404'); 9 | return; 10 | } 11 | 12 | $user = $ctx->usersDao->findFirst("id = $userid"); 13 | 14 | if (substr($user->loginid, 0, 2) != '!!') { 15 | $ctx->util->changePage('error404'); 16 | return; 17 | } 18 | 19 | if ($ctx->loginService->hashPassword($pwd) != $user->password) { 20 | $message = 'Error: Password is wrong!'; 21 | } else { 22 | $chk = $ctx->userService->checkEmail($email); 23 | if (is_null($chk)) { 24 | $user->loginid = '!!' . $ctx->loginService->hashEmail($email); 25 | $ctx->usersDao->save($user); 26 | $message = 'E-mail updated! '; 27 | } else { 28 | $message = "Error: $chk"; 29 | } 30 | } 31 | 32 | $ctx->util->flash($message); 33 | $ctx->util->redirect('user_settings'); 34 | -------------------------------------------------------------------------------- /ctl/user/settings/Info.php: -------------------------------------------------------------------------------- 1 | util->paramPost('info'); 4 | 5 | if (!$ctx->userService->personalInfoAllowed()) { 6 | $ctx->util->changePage('error404'); 7 | return; 8 | } 9 | 10 | $userid = $ctx->auth->loggedUser(); 11 | 12 | $userInfo = $ctx->taskDataDao->findFirst("taskid = $userid and type = 'uinfo'"); 13 | if (!is_object($userInfo)) { 14 | $userInfo = new \stdClass(); 15 | $userInfo->taskid = $userid; 16 | $userInfo->type = 'uinfo'; 17 | } 18 | $userInfo->data = base64_encode($info); 19 | $ctx->taskDataDao->save($userInfo); 20 | 21 | $ctx->util->redirect('user_profile'); 22 | -------------------------------------------------------------------------------- /ctl/user/settings/Password.php: -------------------------------------------------------------------------------- 1 | util->paramPost('newpwd'); 4 | $reppwd = $ctx->util->paramPost('reppwd'); 5 | $oldpwd = $ctx->util->paramPost('oldpwd'); 6 | $userid = $ctx->auth->loggedUser(); 7 | 8 | if (empty($userid) || is_null($newpwd) || is_null($reppwd) || is_null($oldpwd)) { 9 | $ctx->util->changePage('error404'); 10 | return; 11 | } 12 | 13 | $user = $ctx->usersDao->findFirst("id = $userid"); 14 | 15 | $wrong = true; 16 | $providedHash = $ctx->loginService->hashPassword($oldpwd); 17 | if ($providedHash == $user->password) { 18 | $wrong = false; 19 | } else { 20 | $tempPwd = $ctx->miscService->getTaggedValue("pwd-{$user->id}"); 21 | if ($tempPwd) { 22 | list($ts, $tempHash) = explode(' ', $tempPwd); 23 | if ($tempHash == $providedHash) { 24 | $wrong = false; 25 | } 26 | } 27 | } 28 | 29 | if ($wrong) { 30 | $message = 'Error: Password is wrong!'; 31 | } else { 32 | $chk = $ctx->userService->checkPassword($newpwd, $reppwd); 33 | if (is_null($chk)) { 34 | $user->password = $ctx->loginService->hashPassword($newpwd); 35 | $ctx->usersDao->save($user); 36 | $message = 'Password updated! '; 37 | $ctx->miscService->logAction($userid, 'pwd changed'); 38 | } else { 39 | $message = "Error: $chk"; 40 | } 41 | } 42 | 43 | $ctx->util->flash($message); 44 | $ctx->util->redirect('user_settings'); 45 | -------------------------------------------------------------------------------- /ctl/wiki/Edit.php: -------------------------------------------------------------------------------- 1 | auth->admin()) { 4 | $ctx->util->changePage('error404'); 5 | return; 6 | } 7 | 8 | $title = $ctx->util->paramGet('url'); 9 | 10 | if (!empty($title)) { 11 | $model->wikipage = $ctx->wikiDao->findFirst("url = '$title'"); 12 | if (!is_object($model->wikipage)) { 13 | $ctx->util->changePage('error404'); 14 | return; 15 | } 16 | $model->wikipage->data = base64_decode($model->wikipage->data); 17 | } else { 18 | $model->wikipage = new stdClass(); 19 | $model->wikipage->title = ''; 20 | $model->wikipage->url = ''; 21 | $model->wikipage->data = ''; 22 | } 23 | 24 | array_push($ctx->elems->styles, 'codemirror'); 25 | array_push($ctx->elems->scripts, '_cm/codemirror'); 26 | array_push($ctx->elems->scripts, '_cm/markdown'); 27 | array_push($ctx->elems->scripts, '_cm/xml'); 28 | -------------------------------------------------------------------------------- /ctl/wiki/Save.php: -------------------------------------------------------------------------------- 1 | util->paramPost('title'); 4 | $url = $ctx->util->paramPost('url'); 5 | $data = $ctx->util->paramPost('data'); 6 | 7 | if (!$ctx->auth->admin() || empty($title) || empty($url)) { 8 | $ctx->util->changePage('error404'); 9 | return; 10 | } 11 | 12 | $url = $ctx->strUtils->nameToUrl($url); 13 | $wikipage = $ctx->wikiDao->findFirst("url = '$url'"); 14 | if (!is_object($wikipage)) { 15 | $wikipage = new stdClass(); 16 | } 17 | 18 | if (trim($data) != 'DELETE') { 19 | $wikipage->title = $title; 20 | $wikipage->url = $url; 21 | $wikipage->data = base64_encode($data); 22 | $wikipage->lastmod = date('Y-m-d'); 23 | 24 | $ctx->wikiDao->save($wikipage); 25 | 26 | $ctx->util->redirect(url('wiki', 'param', $wikipage->url)); 27 | } else { 28 | if ($wikipage->id) { 29 | $ctx->wikiDao->delete($wikipage->id); 30 | $ctx->util->flash("Wiki on $url was deleted!"); 31 | } else { 32 | $ctx->util->flash("Page to delete was not found!"); 33 | } 34 | $ctx->util->redirect('wiki'); 35 | } -------------------------------------------------------------------------------- /docker-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | docker build --tag ca-base . -------------------------------------------------------------------------------- /docker-run.sh: -------------------------------------------------------------------------------- 1 | docker run --rm --name ca-run -p 8080:80 -v $(pwd):/var/www/html -e CA_TEST=1 ca-base 2 | -------------------------------------------------------------------------------- /fragments/.htaccess: -------------------------------------------------------------------------------- 1 | Order deny,allow 2 | Deny from all 3 | -------------------------------------------------------------------------------- /fragments/countryselect.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /fragments/cssandjs.html: -------------------------------------------------------------------------------- 1 | util->sessionGet('css-random-key'); 4 | if ($cssRandomKey === null) { 5 | $cssRandomKey = rand(); 6 | $ctx->util->sessionPut('css-random-key', $cssRandomKey); 7 | } 8 | 9 | foreach ($ctx->elems->styles as $name) { 10 | if (strpos($name, '.') === false) $name .= ".css"; 11 | $file = "css/$name"; 12 | $tag = '"; 13 | if (!file_exists($file)) { 14 | $tag = ""; 15 | } 16 | echo "$tag\n"; 17 | } 18 | 19 | echo ''; 20 | 21 | foreach ($ctx->elems->scripts as $name) { 22 | if (strpos($name, '://') !== false) { 23 | echo ""; 24 | continue; 25 | } 26 | if (strpos($name, '.') === false) $name .= ".js"; 27 | $file = "js/$name"; 28 | $tag = '"; 29 | if (!file_exists($file)) { 30 | $tag = ""; 31 | } 32 | echo "$tag\n"; 33 | } 34 | 35 | ?> 36 | -------------------------------------------------------------------------------- /fragments/flash.html: -------------------------------------------------------------------------------- 1 | util->flash(); 3 | if ($_flash !== null) : 4 | ?> 5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /fragments/footer.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | elems->conf->copyright ?> 4 |
5 | based upon CodeAbbey opensource 6 |
7 |
8 | Contacts and Support 9 |
10 | Issues and Ideas 11 |
12 |
13 | Privacy Policy 14 |
15 |
16 |