After updating to 2.10 from 2.8 on a postgresql database with php 5.3.1 all settings for specific views vanished and reset to the defaults.
I noticed this happening on the website that I have that uses customfields, but does not seem specific to customfields.

I decided to recreate the contents of the view and discovered:

Whenever the following string is placed in any text box field, all view settings will be deleted and reset to the defaults on save:
"/^http:\/\//i"

Perhaps the slashes are breaking out somehow??

This string is a regular expression intended to be passed to preg_match() of a Customfield: PHP code Field.

Comments

jcsiegrist’s picture

I just tried updating a Site from 2.8 to 2.10 and also lost all views settings. This is on mysql 5.1 & php 5.2 after running update.php. Before running update.php but views 2.10 code already in place, the views are still there. The content of the views_display table are all still there, just the field type for 'display_options' changed from 'blob' to 'longtext', like the update.php reported it.

pwolanin’s picture

This appears to be the same issue uncovered in Drupal 7 core:
#690746: Text column type doesn't reliably hold serialized variables

pwolanin’s picture

I'm also surprised to see that the views object cache was changed from blob to text:

      'data' => array(
        'type' => 'blob', // Updated to 'text' (with size => 'big') in views_schema_6004()
        'description' => 'Serialized data being stored.',
        'serialize' => TRUE,
      ),
josh waihi’s picture

I talked to merlinofchaos about the blob to text thing. He said it was fine because views doesn't store serialized objects, just arrays. Nevertheless, blob does seem a better option IMO.

I'm running View 2.10 (through Acquia) on PHP 5.2. Views don't seem to have been lost, however, the upgrade did fail because I couldn't create a unique index on the views_display table.

thekevinday’s picture

Looking at the save_row function in includes/views.inc:

<?php
    $schema = drupal_get_schema($this->db_table);
    $fields = $defs = $values = $serials = array();

    // Go through our schema and build correlations.
    foreach ($schema['fields'] as $field => $info) {
      // special case -- skip serial types if we are updating.
      if ($info['type'] == 'serial') {
        $serials[] = $field;
        continue;
      }
      $fields[] = $field;
      switch ($info['type']) {
        case 'blob':
          $defs[] = '%b';
          break;
        case 'int':
          $defs[] = '%d';
          break;
        case 'float':
        case 'numeric':
          $defs[] = '%f';
          break;
        default:
          $defs[] = "'%s'";
      }
      if (empty($info['serialize'])) {
        $values[] = $this->$field;
      }
      else {
        $values[] = serialize($this->$field);
      }
 // ..
?>

I can get views to work again if I change:

<?php
 switch ($info['type']) {
        case 'blob':
          $defs[] = '%b';
          break;
?>

to:

<?php
 switch ($info['type']) {
        case 'text':
        case 'blob':
          $defs[] = '%b';
          break;
?>

So, for some reason sending the text as a %b prevents the string from breaking.
Looking at the database differences for when I insert "/^http:\/\//i" into some arbitrary field for both when text is treated as %s and when treated as %b:
%b: s:15:"/^http:\\/\\//i"
%s: s:15:"/^http:\/\//i"

With my curiosity increasing, I tried the string: "/^http:\\/\\//i"
%b: s:17:"/^http:\\\\/\\\\//i"
%s: s:17:"/^http:\\/\\//i"

Interestingly, the second %s case did not return valid data as did the first %b case.

I then changed the last bit of the shown code to look like:

<?php
      if (empty($info['serialize'])) {
        $values[] = $this->$field;
      }
      else {
        if ($info['type'] == 'text'){
          $values[] = str_replace('\\', '\\\\', serialize($this->$field));
        } else {
          $values[] = serialize($this->$field);
        }
      }
?>

If the serialize is done before the string replace, then this works, but if the serialize is done after the string replace, then the same problem occurs.

So it seems that the backslash '\' needs to be delimited for string types.
During the update, when the data type was changed from blob to text, all of the resulting text did not get the '\' delimited and as a result produce unexpected behavior on load.
Should the string replace be applied to the non-serialized data as well?
Is arbitrarily delimiting the '\' after a serialize command the proper solution here (or safe)?
This also begs the question of is there a security issue here?

JoelKleier’s picture

Possibly related? #814006: Disappearing Views

thekevinday’s picture

Status: Active » Needs review
StatusFileSize
new723 bytes

Here is the change from #5 in patch form.

Please Review.

merlinofchaos’s picture

StatusFileSize
new1.14 KB

Let's try the %b instead, I think it more or less does the same thing.

I need some testing of this patch to make sure it does not break anything. I did finally make a pgsql install and this patch does seem to work for me on postgres (yay). I need to make sure it does not break anybody's views, though.

thekevinday’s picture

Thats what concerns me with %b. Doesn't it convert other things than just quotes?
(Granted those other things probably should not appear in a normal "string" type anyway.)

merlinofchaos’s picture

I think putting a basic array of data in the header and making sure it saves and unsaves properly will tell us.

merlinofchaos’s picture

Adding a tag. Really need testing. Hey bug squad! =)

merlinofchaos’s picture

Assigned: Unassigned » bojanz
bojanz’s picture

Started looking into this tonight. No more time, will continue.
In general, I have a bad feeling about this. We'll see if it's justified.

Note that for D7 there's nothing to fix, since Views uses the ctools object cache there.
However, per #690746: Text column type doesn't reliably hold serialized variables all fields storing serialized data should be blob (in Drupal 7), which means that ctools needs to be patched accordingly (it uses text).
I've already noted this in the ctools queue: #865142: Make ctools_object_cache.data DB column blob for storing arbitrary bytes.

tim.plunkett’s picture

Issue tags: +Needs tests

Fixing tag.

Status: Needs review » Needs work
Issue tags: -Needs tests

The last submitted patch, 770514-pgsql-breaks-on-single-quotes.patch, failed testing.

mustanggb’s picture

Issue summary: View changes
Status: Needs work » Closed (won't fix)