Projet

Général

Profil

Paste
Télécharger (27 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / ckeditor / ckeditor.module @ 6fd71452

1
<?php
2

    
3
/**
4
 * CKEditor - The text editor for the Internet - http://ckeditor.com
5
 * Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved.
6
 *
7
 * == BEGIN LICENSE ==
8
 *
9
 * Licensed under the terms of any of the following licenses of your
10
 * choice:
11
 *
12
 *  - GNU General Public License Version 2 or later (the "GPL")
13
 *    http://www.gnu.org/licenses/gpl.html
14
 *
15
 *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
16
 *    http://www.gnu.org/licenses/lgpl.html
17
 *
18
 *  - Mozilla Public License Version 1.1 or later (the "MPL")
19
 *    http://www.mozilla.org/MPL/MPL-1.1.html
20
 *
21
 * == END LICENSE ==
22
 *
23
 * @file
24
 * CKEditor Module for Drupal 7.x
25
 *
26
 * This module allows Drupal to replace textarea fields with CKEditor.
27
 *
28
 * CKEditor is an online rich text editor that can be embedded inside web pages.
29
 * It is a WYSIWYG (What You See Is What You Get) editor which means that the
30
 * text edited in it looks as similar as possible to the results end users will
31
 * see after the document gets published. It brings to the Web popular editing
32
 * features found in desktop word processors such as Microsoft Word and
33
 * OpenOffice.org Writer. CKEditor is truly lightweight and does not require any
34
 * kind of installation on the client computer.
35
 */
36
/**
37
 * The name of the simplified toolbar that should be forced.
38
 * Make sure that this toolbar is defined in ckeditor.config.js or fckconfig.js.
39
 */
40
define('CKEDITOR_FORCE_SIMPLE_TOOLBAR_NAME', 'DrupalBasic');
41
define('CKEDITOR_ENTERMODE_P', 1);
42
define('CKEDITOR_ENTERMODE_BR', 2);
43
define('CKEDITOR_ENTERMODE_DIV', 3);
44

    
45
global $_ckeditor_configuration;
46
global $_ckeditor_ids;
47

    
48
require_once('includes/ckeditor.user.inc');
49

    
50
$_ckeditor_configuration = array();
51
$_ckeditor_ids = array();
52

    
53
/**
54
 * Implementation of hook_menu().
55
 */
56
function ckeditor_menu() {
57
  $items = array();
58

    
59
  $items['ckeditor/xss'] = array(
60
    'title' => 'XSS Filter',
61
    'description' => 'XSS Filter.',
62
    'page callback' => 'ckeditor_filter_xss',
63
    'file' => 'includes/ckeditor.page.inc',
64
    'access callback' => TRUE,
65
    'type' => MENU_CALLBACK,
66
  );
67

    
68
  $items['ckeditor/disable/wysiwyg/%'] = array(
69
    'title' => 'Disable the WYSIWYG module',
70
    'description' => 'Disable WYSIWYG module.',
71
    'page callback' => 'ckeditor_disable_wysiwyg',
72
    'page arguments' => array(3),
73
    'file' => 'includes/ckeditor.admin.inc',
74
    'access arguments' => array('administer ckeditor'),
75
    'access callback' => TRUE,
76
    'type' => MENU_CALLBACK,
77
  );
78

    
79
  $items['admin/config/content/ckeditor'] = array(
80
    'title' => 'CKEditor',
81
    'description' => 'Configure the rich text editor.',
82
    'page callback' => 'ckeditor_admin_main',
83
    'file' => 'includes/ckeditor.admin.inc',
84
    'access arguments' => array('administer ckeditor'),
85
    'type' => MENU_NORMAL_ITEM,
86
  );
87

    
88
  $items['admin/config/content/ckeditor/skinframe'] = array(
89
    'title' => 'Change skin of CKEditor',
90
    'description' => 'Configure skin for CKEditor.',
91
    'page callback' => 'ckeditor_skinframe',
92
    'file' => 'includes/ckeditor.admin.inc',
93
    'access arguments' => array('administer ckeditor'),
94
    'type' => MENU_CALLBACK,
95
  );
96

    
97
  $items['admin/config/content/ckeditor/add'] = array(
98
    'title' => 'Add a new CKEditor profile',
99
    'description' => 'Configure the rich text editor.',
100
    'page callback' => 'drupal_get_form',
101
    'page arguments' => array('ckeditor_admin_profile_form', 'add'),
102
    'file' => 'includes/ckeditor.admin.inc',
103
    'access arguments' => array('administer ckeditor'),
104
    'type' => MENU_CALLBACK,
105
  );
106

    
107
  $items['admin/config/content/ckeditor/clone/%ckeditor_profile'] = array(
108
    'title' => 'Clone the CKEditor profile',
109
    'description' => 'Configure the rich text editor.',
110
    'page callback' => 'drupal_get_form',
111
    'page arguments' => array('ckeditor_admin_profile_clone_form', 'clone', 5),
112
    'file' => 'includes/ckeditor.admin.inc',
113
    'access arguments' => array('administer ckeditor'),
114
    'type' => MENU_CALLBACK,
115
  );
116

    
117
  $items['admin/config/content/ckeditor/edit/%ckeditor_profile'] = array(
118
    'title' => 'Edit the CKEditor profile',
119
    'description' => 'Configure the rich text editor.',
120
    'page callback' => 'drupal_get_form',
121
    'page arguments' => array('ckeditor_admin_profile_form', 'edit', 5),
122
    'file' => 'includes/ckeditor.admin.inc',
123
    'access arguments' => array('administer ckeditor'),
124
    'type' => MENU_CALLBACK,
125
  );
126

    
127
  $items['admin/config/content/ckeditor/delete/%ckeditor_profile'] = array(
128
    'title' => 'Delete the CKEditor profile',
129
    'description' => 'Configure the rich text editor.',
130
    'page callback' => 'drupal_get_form',
131
    'page arguments' => array('ckeditor_admin_profile_delete_form', 5),
132
    'file' => 'includes/ckeditor.admin.inc',
133
    'access arguments' => array('administer ckeditor'),
134
    'type' => MENU_CALLBACK,
135
  );
136

    
137
  $items['admin/config/content/ckeditor/addg'] = array(
138
    'title' => 'Add the CKEditor Global profile',
139
    'description' => 'Configure the rich text editor.',
140
    'page callback' => 'drupal_get_form',
141
    'page arguments' => array('ckeditor_admin_global_profile_form', 'add'),
142
    'file' => 'includes/ckeditor.admin.inc',
143
    'access arguments' => array('administer ckeditor'),
144
    'type' => MENU_CALLBACK,
145
  );
146

    
147
  $items['admin/config/content/ckeditor/editg'] = array(
148
    'title' => 'Edit the CKEditor Global profile',
149
    'description' => 'Configure the rich text editor.',
150
    'page callback' => 'drupal_get_form',
151
    'page arguments' => array('ckeditor_admin_global_profile_form', 'edit'),
152
    'file' => 'includes/ckeditor.admin.inc',
153
    'access arguments' => array('administer ckeditor'),
154
    'type' => MENU_CALLBACK,
155
  );
156

    
157
  return $items;
158
}
159

    
160
/**
161
 * Implementation of hook_permission().
162
 *
163
 * People -> Permissions
164
 */
165
function ckeditor_permission() {
166
  $arr = array();
167
  $arr['administer ckeditor'] = array(
168
    'title' => t('Administer CKEditor access'),
169
    'description' => t('Allow users to change CKEditor settings.')
170
  );
171

    
172
  $arr['customize ckeditor'] = array(
173
    'title' => t('Customize CKEditor appearance'),
174
    'description' => t('Allow users to customize CKEditor appearance.')
175
  );
176

    
177
  if (file_exists(ckfinder_path('local'))) {
178
    $arr['allow CKFinder file uploads'] = array(
179
      'title' => t('CKFinder access'),
180
      'description' => t('Allow users to use CKFinder.')
181
    );
182
  }
183
  return $arr;
184
}
185

    
186
/**
187
 * Implementation of hook_help().
188
 *
189
 * This function delegates the execution to ckeditor_help_delegate() in includes/ckeditor.page.inc to
190
 * lower the amount of code in ckeditor.module.
191
 */
192
function ckeditor_help($path, $arg) {
193
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.page');
194
  return module_invoke('ckeditor', 'help_delegate', $path, $arg);
195
}
196

    
197
/**
198
 * Check CKEditor version
199
 */
200
function ckeditor_get_version($main_version = FALSE) {
201
  static $ckeditor_version = FALSE;
202

    
203
  if ($ckeditor_version !== FALSE) {
204
    if (!$main_version) {
205
      return $ckeditor_version;
206
    }
207
    $version = explode('.', $ckeditor_version);
208
    return trim($version[0]);
209
  }
210

    
211
  $editor_path = ckeditor_path('local', TRUE);
212
  if ($editor_path == '<URL>') {
213
    $url = ckeditor_path('url', TRUE);
214
    $matches = array();
215
    if (preg_match("|cdn.ckeditor.com/(\d(\.\d+)+.*)/|i", $url, $matches)) {
216
      $ckeditor_version = $matches[1];
217
      return $matches[1];
218
    }
219
    return $ckeditor_version = NULL;
220
  }
221

    
222
  $jspath = $editor_path . '/ckeditor.js';
223

    
224
  $configcontents = @file_get_contents($jspath);
225
  if (!$configcontents) {
226
    return $ckeditor_version = NULL;
227
  }
228
  $matches = array();
229
  if (preg_match('#,version:[\'\"]{1}(.*?)[\'\"]{1},#', $configcontents, $matches)) {
230
    $ckeditor_version = $matches[1];
231
    if ($ckeditor_version == '%VERSION%') {
232
      $ckeditor_version = '4.0.0';
233
    }
234
    if (!$main_version) {
235
      return $ckeditor_version;
236
    }
237
    $version = explode('.', $ckeditor_version);
238
    return trim($version[0]);
239
  }
240
  return $ckeditor_version = NULL;
241
}
242

    
243
/**
244
 * Implements hook_page_build().
245
 */
246
function ckeditor_page_build(&$page) {
247
  // Add our CSS file that adds common needed classes, such as align-left,
248
  // align-right, underline, indent, etc.
249
  $page['page_bottom']['ckeditor']['#attached']['css'] = array(
250
    drupal_get_path('module', 'ckeditor') . '/css/ckeditor.css' => array(
251
      'every_page' => TRUE,
252
    ),
253
  );
254
}
255

    
256
/**
257
 * Implements hook_form_FORM_ID_alter() for user_profile_form().
258
 */
259
function ckeditor_form_user_profile_form_alter(&$form, &$form_state) {
260
  if ($form['#user_category'] == 'account') {
261
    module_load_include('inc', 'ckeditor', 'includes/ckeditor.user');
262
    ckeditor_user_customize($form, $form_state, 'user_profile_form');
263
  }
264
}
265

    
266
/**
267
 * Implementation of hook_element_info_alter().
268
 *
269
 * Replace the textarea with CKEditor using a callback function (ckeditor_pre_render_text_format).
270
 */
271
function ckeditor_element_info_alter(&$types) {
272
  $types['text_format']['#pre_render'][] = 'ckeditor_pre_render_text_format';
273
}
274

    
275
/**
276
 * This function creates the HTML objects required for CKEditor.
277
 *
278
 * @param $element
279
 *   A fully populated form element to add the editor to.
280
 * @return
281
 *   The same $element with extra CKEditor markup and initialization.
282
 */
283
function ckeditor_pre_render_text_format($element) {
284
  static $init = FALSE;
285
  if (!isset($element['#format'])) {
286
    return $element;
287
  }
288

    
289
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
290
  if ($init === FALSE) {
291
    $input_formats = ckeditor_profiles_compile();
292
    drupal_add_js(array('ckeditor' => array('input_formats' => $input_formats, 'plugins' => array())), 'setting');
293
    $init = TRUE;
294
  }
295

    
296
  if (isset($element['value'])) {
297
    if (!isset($element['format'])) {
298
      return $element;
299
    }
300
    if (isset($element['summary'])) {
301
      $element['value'] = ckeditor_load_by_field($element['value'], $element['format']['format'], TRUE, $element['summary']['#id']);
302
      $element['summary'] = ckeditor_load_by_field($element['summary'], $element['format']['format'], FALSE);
303
    }
304
    else {
305
      $element['value'] = ckeditor_load_by_field($element['value'], $element['format']['format']);
306
    }
307
  }
308
  else {
309
    $element = ckeditor_load_by_field($element, $element['#format']);
310
  }
311

    
312
  return $element;
313
}
314

    
315
/**
316
 * Load all profiles. Just load one profile if $name is passed in.
317
 */
318
function ckeditor_profile_load($name = '', $clear = FALSE, $check_access = TRUE) {
319
  static $profiles = array();
320
  global $user;
321

    
322
  if (empty($profiles) || $clear === TRUE) {
323
    $result = db_select('ckeditor_settings', 's')->fields('s')->execute();
324
    foreach ($result as $data) {
325
      $data->settings = unserialize($data->settings);
326
      $data->input_formats = array();
327

    
328
      $profiles[$data->name] = $data;
329
    }
330
    if ($check_access === FALSE) {
331
      // don't check if user has access to filter formats, needed for exporting as feature with drush
332
      $input_formats = filter_formats();
333
    } else {
334
      $input_formats = filter_formats($user);
335
    }
336
    $result = db_select('ckeditor_input_format', 'f')->fields('f')->execute();
337
    foreach ($result as $data) {
338
      if (isset($input_formats[$data->format])) {
339
        $profiles[$data->name]->input_formats[$data->format] = $input_formats[$data->format]->name;
340
      }
341
    }
342
  }
343

    
344
  return ($name ? (isset($profiles[urldecode($name)]) ? $profiles[urldecode($name)] : FALSE) : $profiles);
345
}
346

    
347
/**
348
 * Generate base path of the Drupal installation.
349
 *
350
 * @return
351
 *   Path of the Drupal installation.
352
 */
353
function ckeditor_base_path($mode = 'relative') {
354
  if ($mode == 'local') {
355
    return $cke_base_local_path = '.';
356
  }
357
  return rtrim(base_path(), '/');
358
}
359

    
360
/**
361
 * Generate module path of the CKEditor module.
362
 *
363
 * @return
364
 *   Path of CKEditor module.
365
 */
366
function ckeditor_module_path($mode = 'relative') {
367
  switch ($mode) {
368
    default:
369
    case 'relative':
370
      return ckeditor_base_path('relative') . '/' . drupal_get_path('module', 'ckeditor');
371
    case 'local':
372
      return ckeditor_base_path('local') . '/' . drupal_get_path('module', 'ckeditor');
373
    case 'url':
374
      return drupal_get_path('module', 'ckeditor');
375
  }
376
}
377

    
378
/**
379
 * Generate library path of the Drupal installation.
380
 *
381
 * @return
382
 *   Path of library in the Drupal installation.
383
 */
384
function ckeditor_library_path($mode = 'relative') {
385
  $lib_path = 'sites/all/libraries';
386

    
387
  if (function_exists('libraries_get_path')) {
388
    $path = libraries_get_path('ckeditor');
389
    if ($path !== FALSE) {
390
      $lib_path = drupal_substr($path, 0, strlen($path) - 9);
391
    }
392
  }
393
  switch ($mode) {
394
    default:
395
    case 'relative':
396
      return ckeditor_base_path('relative') . '/' . $lib_path;
397
    case 'local':
398
      return ckeditor_base_path('local') . '/' . $lib_path;
399
    case 'url':
400
      return $lib_path;
401
  }
402
}
403

    
404
/**
405
 * Read the CKEditor path from the Global profile.
406
 *
407
 * @return
408
 *   Path to CKEditor folder.
409
 */
410
function ckeditor_path($mode = 'relative', $refresh = FALSE) {
411
  static $cke_static;
412

    
413
  if (!isset($cke_static)) {
414
    $cke_static = array();
415
  }
416

    
417
  if ($refresh || !isset($cke_static[$mode])) {
418
    $global_profile = ckeditor_profile_load('CKEditor Global Profile', $refresh);
419
    switch ($mode) {
420
      default:
421
      case 'relative':
422
        if ($global_profile && isset($global_profile->settings['ckeditor_path'])) {
423
          // http:// OR https:// OR //
424
          if (preg_match("|^(http(s)?:)?//|i", $global_profile->settings['ckeditor_path'])) {
425
            return '<URL>';
426
          }
427
          $cke_path = $global_profile->settings['ckeditor_path'];
428
          $cke_path = strtr($cke_path, array("%b" => ckeditor_base_path('relative'), "%m" => ckeditor_module_path('relative'), "%l" => ckeditor_library_path('relative')));
429
          $cke_path = str_replace('\\', '/', $cke_path);
430
          $cke_path = str_replace('//', '/', $cke_path);
431
          return $cke_static[$mode] = $cke_path;
432
        }
433
        return $cke_static[$mode] = ckeditor_module_path('relative') . '/ckeditor';
434
      case 'local':
435
        if ($global_profile) {
436
          if (!empty($global_profile->settings['ckeditor_local_path'])) {
437
            return $cke_static[$mode] = $global_profile->settings['ckeditor_local_path'];
438
          }
439
          if (isset($global_profile->settings['ckeditor_path'])) {
440
            // http:// OR https:// OR //
441
            if (preg_match("|^(http(s)?:)?//|i", $global_profile->settings['ckeditor_path'])) {
442
              return '<URL>';
443
            }
444
            $cke_local_path = $global_profile->settings['ckeditor_path'];
445
            $cke_local_path = strtr($cke_local_path, array("%b" => ckeditor_base_path('local'), "%m" => ckeditor_module_path('local'), "%l" => ckeditor_library_path('local')));
446
            return $cke_static[$mode] = $cke_local_path;
447
          }
448
        }
449
        return $cke_static[$mode] = ckeditor_module_path('local') . '/ckeditor';
450
      case 'url':
451
        if ($global_profile && isset($global_profile->settings['ckeditor_path'])) {
452
          // http:// OR https:// OR //
453
          if (preg_match("|^(http(s)?:)?//|i", $global_profile->settings['ckeditor_path'])) {
454
            $cke_path = $global_profile->settings['ckeditor_path'];
455
          }
456
          else {
457
            $cke_path = $global_profile->settings['ckeditor_path'];
458
            $cke_path = strtr($cke_path, array("%m" => ckeditor_module_path('url'), "%l" => ckeditor_library_path('url')));
459
            $cke_path = str_replace('\\', '/', $cke_path);
460
            $cke_path = str_replace('//', '/', $cke_path);
461
            //In D7 base path in URL mode is not needed, so we need to remove it with trailing slash (if exists)
462
            $cke_path = str_replace(array("%b/", "%b"), '', $cke_path);
463
          }
464
          return $cke_static[$mode] = $cke_path;
465
        }
466
        return $cke_static[$mode] = ckeditor_module_path('url') . '/ckeditor';
467
    }
468
  }
469
  return $cke_static[$mode];
470
}
471

    
472
/**
473
 * Read the CKEditor plugins path from the Global profile.
474
 *
475
 * @return
476
 *   Path to CKEditor plugins folder.
477
 */
478
function ckeditor_plugins_path($mode = 'relative', $refresh = FALSE) {
479
  static $cke_static;
480

    
481
  if (!isset($cke_static)) {
482
    $cke_static = array();
483
  }
484

    
485
  if ($refresh || !isset($cke_static[$mode])) {
486
    $global_profile = ckeditor_profile_load('CKEditor Global Profile', $refresh);
487
    switch ($mode) {
488
      default:
489
      case 'relative':
490
        if ($global_profile && isset($global_profile->settings['ckeditor_plugins_path'])) {
491
          $cke_plugins_path = $global_profile->settings['ckeditor_plugins_path'];
492
          $cke_plugins_path = strtr($cke_plugins_path, array("%b" => ckeditor_base_path('relative'), "%m" => ckeditor_module_path('relative'), "%l" => ckeditor_library_path('relative')));
493
          $cke_plugins_path = str_replace('\\', '/', $cke_plugins_path);
494
          $cke_plugins_path = str_replace('//', '/', $cke_plugins_path);
495
          $cke_plugins_path = rtrim($cke_plugins_path, ' \/');
496
          return $cke_static[$mode] = $cke_plugins_path;
497
        }
498
        return $cke_static[$mode] = ckeditor_module_path('relative') . '/plugins';
499
      case 'local':
500
        if ($global_profile) {
501
          if (!empty($global_profile->settings['ckeditor_plugins_local_path'])) {
502
            return $cke_static[$mode] = $global_profile->settings['ckeditor_plugins_local_path'];
503
          }
504
          if (isset($global_profile->settings['ckeditor_plugins_path'])) {
505
            $cke_plugins_local_path = $global_profile->settings['ckeditor_plugins_path'];
506
            $cke_plugins_local_path = strtr($cke_plugins_local_path, array("%b" => ckeditor_base_path('local'), "%m" => ckeditor_module_path('local'), "%l" => ckeditor_library_path('local')));
507
            return $cke_static[$mode] = $cke_plugins_local_path;
508
          }
509
        }
510
        return $cke_static[$mode] = ckeditor_module_path('local') . '/plugins';
511
      case 'url':
512
        if ($global_profile && isset($global_profile->settings['ckeditor_plugins_path'])) {
513
          $cke_plugins_path = $global_profile->settings['ckeditor_plugins_path'];
514
          $cke_plugins_path = strtr($cke_plugins_path, array("%m" => ckeditor_module_path('url'), "%l" => ckeditor_library_path('url')));
515
          $cke_plugins_path = str_replace('\\', '/', $cke_plugins_path);
516
          $cke_plugins_path = str_replace('//', '/', $cke_plugins_path);
517
          $cke_plugins_path = rtrim($cke_plugins_path, ' \/');
518
          //In D7 base path in URL mode is not needed, so we need to remove it with trailing slash (if exists)
519
          $cke_plugins_path = str_replace(array("%b/", "%b"), '', $cke_plugins_path);
520
          return $cke_static[$mode] = $cke_plugins_path;
521
        }
522
        return $cke_static[$mode] = ckeditor_module_path('url') . '/plugins';
523
    }
524
  }
525
  return $cke_static[$mode];
526
}
527

    
528
/**
529
 * Read the CKFinder path from the Global profile.
530
 *
531
 * @return
532
 *   Path to CKFinder folder.
533
 */
534
function ckfinder_path($mode = 'relative', $refresh = FALSE) {
535
 static $cke_static;
536

    
537
  if (!isset($cke_static)) {
538
    $cke_static = array();
539
  }
540

    
541
  if ($refresh || !isset($cke_static[$mode])) {
542
    $global_profile = ckeditor_profile_load('CKEditor Global Profile', $refresh);
543
    switch ($mode) {
544
      default:
545
      case 'relative':
546
        if ($global_profile && isset($global_profile->settings['ckfinder_path'])) {
547
          $ckfinder_path = $global_profile->settings['ckfinder_path'];
548
          $ckfinder_path = strtr($ckfinder_path, array("%b" => ckeditor_base_path('relative'), "%m" => ckeditor_module_path('relative'), "%l" => ckeditor_library_path('relative')));
549
          $ckfinder_path = str_replace('\\', '/', $ckfinder_path);
550
          $ckfinder_path = str_replace('//', '/', $ckfinder_path);
551
          return $cke_static[$mode] = $ckfinder_path;
552
        }
553
        return $cke_static[$mode] = ckeditor_module_path('relative') . '/ckfinder';
554
      case 'local':
555
        if ($global_profile) {
556
          if (!empty($global_profile->settings['ckfinder_local_path'])) {
557
            return $cke_static[$mode] = $global_profile->settings['ckfinder_local_path'];
558
          }
559
          if (isset($global_profile->settings['ckfinder_path'])) {
560
            $ckfinder_path = $global_profile->settings['ckfinder_path'];
561
            $ckfinder_path = strtr($ckfinder_path, array("%b" => ckeditor_base_path('local'), "%m" => ckeditor_module_path('local'), "%l" => ckeditor_library_path('local')));
562
            return $cke_static[$mode] = $ckfinder_path;
563
          }
564
        }
565
        return $cke_static[$mode] = ckeditor_module_path('local') . '/ckfinder';
566
      case 'url':
567
        if ($global_profile && isset($global_profile->settings['ckfinder_path'])) {
568
          $ckfinder_path = $global_profile->settings['ckfinder_path'];
569
          $ckfinder_path = strtr($ckfinder_path, array("%m" => ckeditor_module_path('url'), "%l" => ckeditor_library_path('url')));
570
          $ckfinder_path = str_replace('\\', '/', $cke_plugins_path);
571
          $ckfinder_path = str_replace('//', '/', $cke_plugins_path);
572
          //In D7 base path in URL mode is not needed, so we need to remove it with trailing slash (if exists)
573
          $ckfinder_path = str_replace(array("%b/", "%b"), '', $ckfinder_path);
574
          return $cke_static[$mode] = $ckfinder_path;
575
        }
576
        return $cke_static[$mode] = ckeditor_module_path('url') . '/ckfinder';
577
    }
578
  }
579
  return $cke_static[$mode];
580
}
581

    
582
/**
583
 * Implementation of hook_features_api().
584
 *
585
 * Allow exporting of CKEditor profiles by the Features module.
586
 */
587
function ckeditor_features_api() {
588
  return array(
589
    'ckeditor_profile' => array(
590
      'name' => t('CKEditor profiles'),
591
      'feature_source' => TRUE,
592
      'default_hook' => 'ckeditor_profile_defaults',
593
      'default_file' => FEATURES_DEFAULTS_INCLUDED,
594
      'file' => drupal_get_path('module', 'ckeditor') . '/includes/ckeditor.features.inc',
595
    )
596
  );
597
}
598

    
599
/**
600
 * Implementation of hook_file_download().
601
 * Support for private downloads.
602
 * CKEditor does not implement any kind of potection on private files.
603
 */
604
function ckeditor_file_download($uri) {
605
  if ($path = file_create_url($uri)) {
606
    $result = db_query("SELECT f.* FROM {file_managed} f WHERE uri = :uri", array(':uri' => $uri));
607
    foreach ($result as $record) {
608
      return NULL;
609
    }
610
    //No info in DB? Probably a file uploaded with FCKeditor / CKFinder
611
    $global_profile = ckeditor_profile_load("CKEditor Global Profile");
612
    //Assume that files inside of ckeditor directory belong to the CKEditor. If private directory is set, let the decision about protection to the user.
613
    $private_dir_db = $private_dir = isset($global_profile->settings['private_dir']) ? trim($global_profile->settings['private_dir'], '\/') : '';
614
    $private_dir_db = str_replace(array('\\%u', '\\%n'), array('', ''), $private_dir_db);
615
    $private_dir = preg_quote($private_dir, '#');
616
    $private_dir = strtr($private_dir, array('%u' => '(\d+)', '%n' => '([\x80-\xF7 \w@.-]+)')); // regex for %n taken from user_validate_name() in user.module
617
    $private_dir = trim($private_dir, '\/');
618

    
619
    $regex = '#^' . preg_quote('private://', '#') . $private_dir . '#';
620

    
621
    if (!strstr($uri, 'private://') && !strstr($uri, 'public://')) {
622
      $path = 'private://' . $uri;
623
    }
624
    else {
625
      $path = $uri;
626
    }
627
    //check if CKEditor's "Enable access to files located in the private folder" option is disabled or enabled
628
    $allow_download_private_files = FALSE;
629
    if (isset($global_profile->settings['ckeditor_allow_download_private_files']) && $global_profile->settings['ckeditor_allow_download_private_files'] === 't') {
630
      $allow_download_private_files = TRUE;
631
    }
632
    //denied access to file if private upload is set and CKEditor's "Enable access to files located in the private folder" option is disabled
633
    if ($allow_download_private_files == FALSE)
634
      return NULL;
635
    //check if file can be served by comparing regex and path to file
636
    if (preg_match($regex, $path)) {
637
      $info = image_get_info($uri);
638
      return array('Content-Type' => $info['mime_type']);
639
    }
640
  }
641
}
642

    
643
/**
644
 * Implementation of hook_modules_enabled().
645
 *
646
 * Enable disabled plugins by hook_modules_disabled().
647
 */
648
function ckeditor_modules_enabled($modules) {
649
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
650
  if (in_array('libraries', $modules)) {
651
    // Check and update path to CKEditor in the global profile
652
    _ckeditor_requirements_isinstalled();
653
  }
654
  $profiles_list = ckeditor_profile_input_formats();
655
  $plugins_list = ckeditor_load_plugins();
656
  foreach ($profiles_list AS $_profile => $_inputs) {
657
    $changed = FALSE;
658
    $profile = ckeditor_profile_load($_profile);
659
    if (!isset($profile->settings['loadPlugins'])) continue;
660
    foreach (array_keys((array) $profile->settings['loadPlugins']) as $plugin_name) {
661
      if (isset($profile->settings['loadPlugins'][$plugin_name]['active']) && $profile->settings['loadPlugins'][$plugin_name]['active'] == 0 && array_key_exists($plugin_name, $plugins_list)) {
662
        $profile->settings['loadPlugins'][$plugin_name]['active'] = 1;
663
        $changed = TRUE;
664
      }
665
    }
666
    if ($changed === TRUE) {
667
      db_update('ckeditor_settings')
668
          ->fields(array(
669
            'settings' => serialize($profile->settings)
670
          ))
671
          ->condition('name', $profile->name, '=')
672
          ->execute();
673
    }
674
  }
675
}
676

    
677
/**
678
 * Implementation of hook_modules_disabled().
679
 *
680
 * Disable enabled plugins in CKEditor profiles added by disabled modules.
681
 */
682
function ckeditor_modules_disabled($modules) {
683
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
684
  $profiles_list = ckeditor_profile_input_formats();
685
  $plugins_list = ckeditor_load_plugins();
686
  foreach ($profiles_list AS $_profile => $_inputs) {
687
    $changed = FALSE;
688
    $profile = ckeditor_profile_load($_profile);
689
    if (!isset($profile->settings['loadPlugins'])) continue;
690
    foreach (array_keys((array) $profile->settings['loadPlugins']) as $plugin_name) {
691
      if (!array_key_exists($plugin_name, $plugins_list)) {
692
        $profile->settings['loadPlugins'][$plugin_name]['active'] = 0;
693
        $changed = TRUE;
694
      }
695
    }
696
    if ($changed === TRUE) {
697
      db_update('ckeditor_settings')
698
          ->fields(array(
699
            'settings' => serialize($profile->settings)
700
          ))
701
          ->condition('name', $profile->name, '=')
702
          ->execute();
703
    }
704
  }
705
}
706

    
707
/**
708
 * Implementation of hook_modules_uninstalled().
709
 *
710
 * Remove enabled plugins in CKEditor profiles added by uninstalled modules.
711
 */
712
function ckeditor_modules_uninstalled($modules) {
713
  module_load_include('inc', 'ckeditor', 'includes/ckeditor.lib');
714
  $profiles_list = ckeditor_profile_input_formats();
715
  $plugins_list = ckeditor_load_plugins();
716
  foreach ($profiles_list AS $_profile => $_inputs) {
717
    $changed = FALSE;
718
    $profile = ckeditor_profile_load($_profile);
719
    if (!isset($profile->settings['loadPlugins'])) continue;
720
    foreach (array_keys((array) $profile->settings['loadPlugins']) as $plugin_name) {
721
      if (!array_key_exists($plugin_name, $plugins_list)) {
722
        unset($profile->settings['loadPlugins'][$plugin_name]);
723
        $changed = TRUE;
724
      }
725
    }
726
    if ($changed === TRUE) {
727
      db_update('ckeditor_settings')
728
          ->fields(array(
729
            'settings' => serialize($profile->settings)
730
          ))
731
          ->condition('name', $profile->name, '=')
732
          ->execute();
733
    }
734
  }
735
}
736

    
737

    
738
/**
739
 * Implements hook_field_extra_fields().
740
 */
741
function ckeditor_field_extra_fields() {
742
  $fields['user']['user']['form']['ckeditor'] = array(
743
    'label' => t('Rich text editor settings'),
744
    'description' => t('Rich text editor settings'),
745
    'weight' => 10,
746
  );
747
  return $fields;
748
}