silverstripe /
silverstripe-spamprotection
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | namespace SilverStripe\SpamProtection; |
||
| 4 | |||
| 5 | use SilverStripe\Core\ClassInfo; |
||
| 6 | use SilverStripe\Core\Convert; |
||
| 7 | use SilverStripe\Core\Manifest\ModuleLoader; |
||
| 8 | use SilverStripe\Forms\DropdownField; |
||
| 9 | use SilverStripe\Forms\FieldGroup; |
||
| 10 | use SilverStripe\Forms\FieldList; |
||
| 11 | use SilverStripe\Forms\FormField; |
||
| 12 | use SilverStripe\ORM\UnsavedRelationList; |
||
| 13 | use SilverStripe\SpamProtection\Extension\FormSpamProtectionExtension; |
||
| 14 | use SilverStripe\UserForms\Model\EditableFormField; |
||
| 15 | use SilverStripe\UserForms\Model\EditableFormField\EditableEmailField; |
||
| 16 | use SilverStripe\UserForms\Model\EditableFormField\EditableNumericField; |
||
| 17 | use SilverStripe\UserForms\Model\EditableFormField\EditableTextField; |
||
| 18 | |||
| 19 | if (!class_exists(EditableFormField::class)) { |
||
| 20 | return; |
||
| 21 | } |
||
| 22 | |||
| 23 | /** |
||
| 24 | * Editable Spam Protecter Field. Used with the User Defined Forms module (if |
||
| 25 | * installed) to allow the user to have captcha fields with their custom forms |
||
| 26 | * |
||
| 27 | * @package spamprotection |
||
| 28 | */ |
||
| 29 | class EditableSpamProtectionField extends EditableFormField |
||
| 30 | { |
||
| 31 | private static $singular_name = 'Spam Protection Field'; |
||
| 32 | |||
| 33 | private static $plural_name = 'Spam Protection Fields'; |
||
| 34 | |||
| 35 | private static $table_name = 'EditableSpamProtectionField'; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * Fields to include spam detection for |
||
| 39 | * |
||
| 40 | * @var array |
||
| 41 | * @config |
||
| 42 | */ |
||
| 43 | private static $check_fields = array( |
||
| 44 | EditableEmailField::class, |
||
| 45 | EditableTextField::class, |
||
| 46 | EditableNumericField::class |
||
| 47 | ); |
||
| 48 | |||
| 49 | private static $db = array( |
||
| 50 | 'SpamFieldSettings' => 'Text' |
||
| 51 | ); |
||
| 52 | |||
| 53 | /** |
||
| 54 | * @var FormField |
||
| 55 | */ |
||
| 56 | protected $formField = null; |
||
| 57 | |||
| 58 | public function getFormField() |
||
| 59 | { |
||
| 60 | if ($this->formField) { |
||
| 61 | return $this->formField; |
||
| 62 | } |
||
| 63 | |||
| 64 | // Get protector |
||
| 65 | $protector = FormSpamProtectionExtension::get_protector(); |
||
| 66 | if (!$protector) { |
||
| 67 | return false; |
||
| 68 | } |
||
| 69 | |||
| 70 | // Extract saved field mappings and update this field. |
||
| 71 | $fieldMapping = array(); |
||
| 72 | foreach ($this->getCandidateFields() as $otherField) { |
||
| 73 | $mapSetting = "Map-{$otherField->Name}"; |
||
| 74 | $spamField = $this->spamMapValue($mapSetting); |
||
| 75 | $fieldMapping[$otherField->Name] = $spamField; |
||
| 76 | } |
||
| 77 | $protector->setFieldMapping($fieldMapping); |
||
| 78 | |||
| 79 | // Generate field |
||
| 80 | return $protector->getFormField($this->Name, $this->Title, null); |
||
| 81 | } |
||
| 82 | |||
| 83 | /** |
||
| 84 | * @param FormField $field |
||
| 85 | * @return self |
||
| 86 | */ |
||
| 87 | public function setFormField(FormField $field) |
||
| 88 | { |
||
| 89 | $this->formField = $field; |
||
| 90 | |||
| 91 | return $this; |
||
| 92 | } |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Gets the list of all candidate spam detectable fields on this field's form |
||
| 96 | * |
||
| 97 | * @return DataList |
||
| 98 | */ |
||
| 99 | protected function getCandidateFields() |
||
| 100 | { |
||
| 101 | |||
| 102 | // Get list of all configured classes available for spam detection |
||
| 103 | $types = $this->config()->get('check_fields'); |
||
| 104 | $typesInherit = array(); |
||
| 105 | foreach ($types as $type) { |
||
| 106 | $subTypes = ClassInfo::subclassesFor($type); |
||
| 107 | $typesInherit = array_merge($typesInherit, $subTypes); |
||
| 108 | } |
||
| 109 | |||
| 110 | // Get all candidates of the above types |
||
| 111 | return $this |
||
| 112 | ->Parent() |
||
| 113 | ->Fields() |
||
| 114 | ->filter('ClassName', $typesInherit) |
||
| 115 | ->exclude('Title', ''); // Ignore this field and those without titles |
||
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * Write the spam field mapping values to a serialised DB field |
||
| 120 | * |
||
| 121 | * {@inheritDoc} |
||
| 122 | */ |
||
| 123 | public function onBeforeWrite() |
||
| 124 | { |
||
| 125 | $fieldMap = json_decode($this->SpamFieldSettings, true); |
||
| 126 | if (empty($fieldMap)) { |
||
| 127 | $fieldMap = array(); |
||
| 128 | } |
||
| 129 | |||
| 130 | foreach ($this->record as $key => $value) { |
||
| 131 | if (substr($key, 0, 8) === 'spammap-') { |
||
| 132 | $fieldMap[substr($key, 8)] = $value; |
||
| 133 | } |
||
| 134 | } |
||
| 135 | $this->setField('SpamFieldSettings', json_encode($fieldMap)); |
||
| 136 | |||
| 137 | return parent::onBeforeWrite(); |
||
| 138 | } |
||
| 139 | |||
| 140 | /** |
||
| 141 | * Used in userforms 3.x and above |
||
| 142 | * |
||
| 143 | * {@inheritDoc} |
||
| 144 | */ |
||
| 145 | public function getCMSFields() |
||
| 146 | { |
||
| 147 | /** @var FieldList $fields */ |
||
| 148 | $fields = parent::getCMSFields(); |
||
| 149 | |||
| 150 | // Get protector |
||
| 151 | $protector = FormSpamProtectionExtension::get_protector(); |
||
| 152 | if (!$protector) { |
||
| 153 | return $fields; |
||
| 154 | } |
||
| 155 | |||
| 156 | if ($this->Parent()->Fields() instanceof UnsavedRelationList) { |
||
| 157 | return $fields; |
||
| 158 | } |
||
| 159 | |||
| 160 | // Each other text field in this group can be assigned a field mapping |
||
| 161 | $mapGroup = FieldGroup::create() |
||
| 162 | ->setTitle(_t(__CLASS__.'.SPAMFIELDMAPPING', 'Spam Field Mapping')) |
||
| 163 | ->setName('SpamFieldMapping') |
||
| 164 | ->setDescription(_t( |
||
| 165 | __CLASS__.'.SPAMFIELDMAPPINGDESCRIPTION', |
||
| 166 | 'Select the form fields that correspond to any relevant spam protection identifiers' |
||
| 167 | )); |
||
| 168 | |||
| 169 | // Generate field specific settings |
||
| 170 | $mappableFields = FormSpamProtectionExtension::config()->get('mappable_fields'); |
||
| 171 | $mappableFieldsMerged = array_combine($mappableFields, $mappableFields); |
||
| 172 | foreach ($this->getCandidateFields() as $otherField) { |
||
| 173 | $mapSetting = "Map-{$otherField->Name}"; |
||
| 174 | $fieldOption = DropdownField::create( |
||
| 175 | 'spammap-' . $mapSetting, |
||
| 176 | $otherField->Title, |
||
| 177 | $mappableFieldsMerged, |
||
| 178 | $this->spamMapValue($mapSetting) |
||
| 179 | )->setEmptyString(''); |
||
| 180 | $mapGroup->push($fieldOption); |
||
| 181 | } |
||
| 182 | $fields->addFieldToTab('Root.Main', $mapGroup); |
||
| 183 | |||
| 184 | return $fields; |
||
| 185 | } |
||
| 186 | |||
| 187 | /** |
||
| 188 | * Try to retrieve a value for the given spam field map name from the serialised data |
||
| 189 | * |
||
| 190 | * @param string $mapSetting |
||
| 191 | * @return string |
||
| 192 | */ |
||
| 193 | public function spamMapValue($mapSetting) |
||
| 194 | { |
||
| 195 | $map = json_decode($this->SpamFieldSettings, true); |
||
| 196 | if (empty($map)) { |
||
| 197 | $map = array(); |
||
| 198 | } |
||
| 199 | |||
| 200 | if (array_key_exists($mapSetting, $map)) { |
||
| 201 | return $map[$mapSetting]; |
||
| 202 | } |
||
| 203 | return ''; |
||
| 204 | } |
||
| 205 | |||
| 206 | /** |
||
| 207 | * Using custom validateField method |
||
| 208 | * as Spam Protection Field implementations may have their own error messages |
||
| 209 | * and may not be based on the field being required, e.g. Honeypot Field |
||
| 210 | * |
||
| 211 | * @param array $data |
||
| 212 | * @param Form $form |
||
| 213 | * @return void |
||
| 214 | */ |
||
| 215 | public function validateField($data, $form) |
||
| 216 | { |
||
| 217 | $formField = $this->getFormField(); |
||
| 218 | $formField->setForm($form); |
||
| 219 | |||
| 220 | if (isset($data[$this->Name])) { |
||
| 221 | $formField->setValue($data[$this->Name]); |
||
| 222 | } |
||
| 223 | |||
| 224 | $validator = $form->getValidator(); |
||
| 225 | if (!$formField->validate($validator)) { |
||
| 226 | $errors = $validator->getErrors(); |
||
| 227 | $foundError = false; |
||
| 228 | |||
| 229 | // field validate implementation may not add error to validator |
||
| 230 | if (count($errors) > 0) { |
||
| 231 | // check if error already added from fields' validate method |
||
| 232 | foreach ($errors as $error) { |
||
| 233 | if ($error['fieldName'] == $this->Name) { |
||
| 234 | $foundError = $error; |
||
| 235 | break; |
||
| 236 | } |
||
| 237 | } |
||
| 238 | } |
||
| 239 | |||
| 240 | if ($foundError !== false) { |
||
| 241 | // use error messaging already set from validate method |
||
| 242 | $form->sessionMessage($foundError['message'], $foundError['messageType']); |
||
| 243 | } else { |
||
| 244 | // fallback to custom message set in CMS or default message if none set |
||
| 245 | $form->sessionError($this->getErrorMessage()->HTML()); |
||
| 246 | } |
||
| 247 | } |
||
| 248 | } |
||
| 249 | |||
| 250 | public function getFieldValidationOptions() |
||
| 251 | { |
||
| 252 | return FieldList::create(); |
||
| 253 | } |
||
| 254 | |||
| 255 | public function getRequired() |
||
| 256 | { |
||
| 257 | return false; |
||
| 258 | } |
||
| 259 | |||
| 260 | public function getIcon() |
||
| 261 | { |
||
| 262 | $resource = ModuleLoader::getModule('silverstripe/spamprotection') |
||
|
0 ignored issues
–
show
|
|||
| 263 | ->getResource('images/editablespamprotectionfield.png'); |
||
| 264 | |||
| 265 | if (!$resource->exists()) { |
||
| 266 | return ''; |
||
| 267 | } |
||
| 268 | |||
| 269 | return $resource->getURL(); |
||
| 270 | } |
||
| 271 | |||
| 272 | public function showInReports() |
||
| 273 | { |
||
| 274 | return false; |
||
| 275 | } |
||
| 276 | } |
||
| 277 |
This check marks calls to methods that do not seem to exist on an object.
This is most likely the result of a method being renamed without all references to it being renamed likewise.