Issues (10)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

code/SEO_Icons_SiteConfig_DataExtension.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * @todo Description
5
 *
6
 * I called them Pinicons & Tabicons in keeping with the absolutely pointless name: Favicons.
7
 *
8
 * @package silverstripe-seo
9
 * @subpackage icons
10
 * @author Andrew Gerber <[email protected]>
11
 * @version 1.0.0
12
 *
13
 */
14
class SEO_Icons_SiteConfig_DataExtension extends DataExtension
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
15
{
16
17
18
    /* Static Variables
19
    ------------------------------------------------------------------------------*/
20
21
    //
22
    private static $SEOIconsUpload = 'SEO/SiteConfig/Icons/';
23
24
    //
25
    const APPLE_ICON_DEFAULT_BACKGROUND = '000000';
26
27
28
    /* Overload Model
29
    ------------------------------------------------------------------------------*/
30
31
    private static $db = array(
0 ignored issues
show
The property $db is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
32
        // Pinned Icon Title
33
        'PiniconTitle' => 'Varchar(128)',
34
        // Android Pinned Icon
35
        'AndroidPiniconThemeColor' => 'Varchar(6)',
36
        // MS Tile
37
        'WindowsPiniconBackgroundColor' => 'Varchar(6)',
38
        // Safari Pinned Tab
39
//		'SafariTabiconThemeColor' => 'Varchar(6)', // @todo maybe implement
40
    );
41
    private static $has_one = array(
0 ignored issues
show
The property $has_one is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
42
        // Favicon
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
43
//		'HTML4Favicon' => 'Image', // @todo maybe implement
44
        'HTML5Favicon' => 'Image',
45
        // Apple Pinned Icon
46
        'IOSPinicon' => 'Image',
47
        // Android Pinned Icon
48
        'AndroidPinicon' => 'Image',
49
        // Windows Pinned Icon
50
        'WindowsPinicon' => 'Image',
51
        // Safari Pinned Tab
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
52
//		'SafariTabiconDefault' => 'Image', // @todo maybe implement
53
//		'SafariTabiconWide' => 'Image', // @todo maybe implement
54
//		'SafariTabiconLarge' => 'Image', // @todo maybe implement
55
    );
56
57
58
    /* Overload Methods
59
    ------------------------------------------------------------------------------*/
60
61
    /**
62
     * Adds tabs & fields to the CMS.
63
     *
64
     * @param FieldList $fields
65
     */
66
    public function updateCMSFields(FieldList $fields)
67
    {
68
69
        //// Favicons Tab
70
71
        $tab = 'Root.Metadata.Favicons';
72
73
        //// Favicon
74
75
        $fields->addFieldsToTab($tab, array(
76
            LabelField::create('FaviconDescription', 'Favicons are `favourite icons` used by browsers in a number of ways whenever an icon is necessary e.g. tabs, history, bookmarks, dashboards.<br />@ <a href="https://en.wikipedia.org/wiki/Favicon" target="_blank">Favicon - Wikipedia, the free encyclopedia</a>')
77
                ->addExtraClass('information')
78
        ));
79
80
        //// HTML4 Favicon
81
82
        // check favicon.ico & set status
83
        $icoStatus = ReadonlyField::create('HTML4FaviconStatus', 'Favicon ICO<pre>type: ico</pre><pre>size: (multiple)<br />16x16 & 32x32 & 64x64 px</pre>', 'favicon.ico error');
84
        if (Director::fileExists('favicon.ico')) {
85
            $icoStatus
86
                ->setValue('favicon.ico found')
87
                ->addExtraClass('success favicon');
88
        } else {
89
            $icoStatus
90
                ->setValue('favicon.ico not found')
91
                ->addExtraClass('error');
92
        }
93
94
        // header & fields
95
        $fields->addFieldsToTab($tab, array(
96
            HeaderField::create('HTML4FaviconHeader', 'HTML4 <span class="aka">( favicon.ico )</span>'),
97
            LabelField::create('HTML4FaviconDescription', 'It is recommended you simply have a `favicon.ico` file in the webroot.')
98
                ->addExtraClass('information'),
99
            $icoStatus
100
        ));
101
102
        //// HTML5 Favicon
103
104
        // header & fields
105
        $fields->addFieldsToTab($tab, array(
106
            HeaderField::create('HTML5FaviconHeader', 'HTML5 <span class="aka">( favicon.png )</span>'),
107
            LabelField::create('HTML5FaviconDescription', '@todo Description')
108
                ->addExtraClass('information'),
109
            UploadField::create('HTML5Favicon', 'Favicon PNG<pre>type: png</pre><pre>size: 192x192 px</pre>')
110
                ->setAllowedExtensions(array('png'))
111
                ->setFolderName(self::$SEOIconsUpload)
112
        ));
113
114
        //// Pinned Icons Tab
115
116
        $tab = 'Root.Metadata.PinnedIcons';
117
118
        //// Pinned Icons Information
119
120
        $fields->addFieldsToTab($tab, array(
121
            LabelField::create('PiniconDescription', 'Pinned icons are OS-specific desktop shortcuts to pages on your website, they allow you to configure additional theming options to make pages appear more `native` / `web-app-y` within the OS.<br />Given they are OS-specific, they (obviously!) have a different format for each one :(')
122
                ->addExtraClass('information')
123
        ));
124
125
        //// Pinned Icon Title
126
127
        // CMS fields
128
        $fields->addFieldsToTab($tab, array(
129
            // header
130
            HeaderField::create('PiniconTitleHeader', 'Pinned Icon Title <span class="aka">( a.k.a. App Name )</span>'),
131
            // description
132
            LabelField::create('PiniconTitleDescription', 'When adding a link to the home screen, the user can choose a caption. By default, this is the bookmarked page title, which is usually fine. However, iOS and Windows 8 let you override this default value.')
133
                ->addExtraClass('information'),
134
            TextField::create('PiniconTitle', 'Application Title')
135
                ->setAttribute('placeholder', 'default: page title')
136
        ));
137
138
        //// iOS Pinned Icon
139
140
        // CMS fields
141
        $fields->addFieldsToTab($tab, array(
142
            // header
143
            HeaderField::create('IOSPiniconHeader', 'iOS Pinned Icon <span class="aka">( a.k.a. Touch Icons, Web Clips )</span>'),
144
            // information
145
            LabelField::create('IOSPiniconDescription', 'iPhone and iPad users can pin your web site on their home screen. The link looks like a native app.<br />@ <a href="https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html" target="_blank">Configuring Web Applications - iOS Developer Library</a>')
146
                ->addExtraClass('information'),
147
            // icon
148
            UploadField::create('IOSPinicon', 'iOS Icon<pre>type: png</pre><pre>size: 192x192 px</pre>')
149
                ->setAllowedExtensions(array('png'))
150
                ->setFolderName(self::$SEOIconsUpload)
151
                ->setDescription('iOS will fill the transparent regions with black by default, so put your own background in!')
152
        ));
153
154
        //// Android Pinned Icon
155
156
        // CMS fields
157
        $fields->addFieldsToTab($tab, array(
158
            // header
159
            HeaderField::create('AndroidPiniconHeader', 'Android Pinned Icon <span class="aka">( a.k.a. Android Chrome Icons, Launcher Icons )</span>'),
160
            // information
161
            LabelField::create('AndroidPiniconDescription', 'Add to Homescreen is a also a feature of Android Chrome. Your visitors can mix their natives apps and web bookmarks.<br />@ <a href="https://developer.chrome.com/multidevice/android/installtohomescreen" target="_blank">Add to Homescreen - Google Chrome</a>')
162
                ->addExtraClass('information'),
163
            // icon
164
            UploadField::create('AndroidPinicon', 'Android Icon<pre>type: png</pre><pre>size: 192x192 px</pre>')
165
                ->setAllowedExtensions(array('png'))
166
                ->setFolderName(self::$SEOIconsUpload),
167
            // background
168
            TextField::create('AndroidPiniconThemeColor', 'Theme Color<pre>type: hex triplet</pre>')
169
                ->setAttribute('placeholder', 'none')
170
                ->setAttribute('size', 6)
171
                ->setMaxLength(6)
172
                ->setDescription('Starting with Android Lollipop, you can customize the color of the task bar in the switcher.')
173
        ));
174
175
        //// Windows Pinned Icon
176
177
        // CMS fields
178
        $fields->addFieldsToTab($tab, array(
179
            // header
180
            HeaderField::create('WindowsShortcutHeader', 'Windows Pinned Icon <span class="aka">( a.k.a. Windows 8 / Metro Tiles )</span>'),
181
            // information
182
            LabelField::create('WindowsShortcutDescription', 'Windows 8 users can pin your web site on their desktop. Your site appears as a tile, just like a native Windows 8 app.<br />@ <a href="https://msdn.microsoft.com/en-us/library/dn455106" target="_blank">Creating custom tiles for IE11 websites (Windows)</a>')
183
                ->addExtraClass('information'),
184
            // icon
185
            UploadField::create('WindowsPinicon', 'Windows Icon<pre>type: png</pre><pre>size: 192x192 px</pre>')
186
                ->setAllowedExtensions(array('png'))
187
                ->setFolderName(self::$SEOIconsUpload),
188
            // background
189
            TextField::create('WindowsPiniconBackgroundColor', 'Background ( Tile ) Color<pre>type: hex triplet</pre>')
190
                ->setAttribute('placeholder', 'none')
191
                ->setAttribute('size', 6)
192
                ->setMaxLength(6)
193
        ));
194
195
        // @todo Safari Pinned Tab ~ maybe ??
196
197
    }
198
199
    /**
200
     * Generates the Android manifest.json file.
201
     *
202
     * @todo Information about permissions
203
     *
204
     * @return void
205
     */
206
    public function onAfterWrite()
207
    {
208
209
        // parent
210
        parent::onAfterWrite();
211
212
        // @todo Add success & error states + messages
213
        $this->generateAndroidManifest();
214
215
    }
216
217
218
    /* Custom Methods
219
    ------------------------------------------------------------------------------*/
220
221
    //// Fetch functions
222
223
    /**
224
     * Fetches the pinicon title.
225
     *
226
     * @return bool|string
227
     */
228
    public function fetchPiniconTitle()
229
    {
230
231
        if ($this->owner->PiniconTitle) {
232
            // return pinicon title
233
            return $this->owner->PiniconTitle;
234
        } else {
235
            // default
236
            return false;
237
        }
238
239
    }
240
241
    /**
242
     * Fetches the Android pinicon theme color.
243
     *
244
     * @return string|false
245
     */
246
    public function fetchAndroidPiniconThemeColor()
247
    {
248
249
        if ($this->owner->AndroidPiniconThemeColor) {
250
            return '#' . $this->owner->AndroidPiniconThemeColor;
251
        } else {
252
            return false;
253
        }
254
255
    }
256
257
    /**
258
     * Fetches the Windows pinicon background color.
259
     *
260
     * @return string|false
261
     */
262
    public function fetchWindowsPiniconBackgroundColor()
263
    {
264
265
        if ($this->owner->WindowsPiniconBackgroundColor) {
266
            return '#' . $this->owner->WindowsPiniconBackgroundColor;
267
        } else {
268
            return false;
269
        }
270
271
    }
272
273
    //// Generate functions
274
275
    /**
276
     * Generates the android manifest
277
     *
278
     * @todo check this is working 100%
279
     *
280
     * @return bool
281
     */
282
    public function generateAndroidManifest()
283
    {
284
285
        //// Android Pinicon Manifest
286
287
        $pinicon = $this->owner->AndroidPinicon();
288
289
        if ($pinicon->exists()) {
290
291
            //
292
            $manifest = new stdClass();
293
294
            //
295
            $manifest->name = $this->owner->PiniconTitle;
296
//			$manifest->start_url = null; @todo Maybe implement
297
//			$manifest->display = null; @todo Maybe implement
298
//			$manifest->orientation = null; @todo Maybe implement
299
            $manifest->icons = array();
300
301
            // 0.75x density icon
302
            array_push($manifest->icons, array(
303
                'src' => $pinicon->Fill(36, 36)->getAbsoluteURL(),
304
                'sizes' => '36x36',
305
                'type' => 'image/png',
306
                'density' => 0.75
307
            ));
308
309
            // 1x density icon
310
            array_push($manifest->icons, array(
311
                'src' => $pinicon->Fill(48, 48)->getAbsoluteURL(),
312
                'sizes' => '48x48',
313
                'type' => 'image/png',
314
                'density' => 1
315
            ));
316
317
            // 1.5x density icon
318
            array_push($manifest->icons, array(
319
                'src' => $pinicon->Fill(72, 72)->getAbsoluteURL(),
320
                'sizes' => '72x72',
321
                'type' => 'image/png',
322
                'density' => 1.5
323
            ));
324
325
            // 2x density icon
326
            array_push($manifest->icons, array(
327
                'src' => $pinicon->Fill(96, 96)->getAbsoluteURL(),
328
                'sizes' => '96x96',
329
                'type' => 'image/png',
330
                'density' => 2
331
            ));
332
333
            // 3x density icon
334
            array_push($manifest->icons, array(
335
                'src' => $pinicon->Fill(144, 144)->getAbsoluteURL(),
336
                'sizes' => '144x144',
337
                'type' => 'image/png',
338
                'density' => 3
339
            ));
340
341
            // 4x density icon
342
            array_push($manifest->icons, array(
343
                'src' => $pinicon->Fill(192, 192)->getAbsoluteURL(),
344
                'sizes' => '192x192',
345
                'type' => 'image/png',
346
                'density' => 4
347
            ));
348
349
            // create file
350
            $bytes = file_put_contents(Director::baseFolder() . '/manifest.json', json_encode($manifest));
351
352
            //
353
            if ($bytes !== false) {
354
                // success
355
                return true;
356
            }
357
358
        }
359
360
        // default return
361
        return false;
362
363
    }
364
365
}
366