/** * Updates the setting table based on data passed in then rebuilds the datastore. * Only entries in the array are updated (allows partial updates). * * @param array Array of settings. Format: [setting_name] = new_value */ function save_settings($settings) { global $vbulletin, $vbphrase; $varnames = array(); foreach (array_keys($settings) as $varname) { $varnames[] = $vbulletin->db->escape_string($varname); } $rebuildstyle = false; $oldsettings = $vbulletin->db->query_read("\n\t\tSELECT value, varname, datatype, optioncode\n\t\tFROM " . TABLE_PREFIX . "setting\n\t\tWHERE varname IN ('" . implode("', '", $varnames) . "')\n\t\tORDER BY varname\n\t"); while ($oldsetting = $vbulletin->db->fetch_array($oldsettings)) { switch ($oldsetting['varname']) { // ************************************************** case 'bbcode_html_colors': $settings['bbcode_html_colors'] = serialize($settings['bbcode_html_colors']); break; // ************************************************** // ************************************************** case 'styleid': $vbulletin->db->query_write("\n\t\t\t\t\tUPDATE " . TABLE_PREFIX . "style\n\t\t\t\t\tSET userselect = 1\n\t\t\t\t\tWHERE styleid = " . $settings['styleid'] . "\n\t\t\t\t"); break; case 'as_content': $vbulletin->db->query_write("\n\t\t\t\t\tUPDATE " . TABLE_PREFIX . "activitystreamtype\n\t\t\t\t\tSET enabled = 0;\n\t\t\t\t"); $vbulletin->db->query_write("\n\t\t\t\t\tUPDATE " . TABLE_PREFIX . "activitystreamtype\n\t\t\t\t\tSET enabled = 1\n\t\t\t\t\tWHERE typeid IN (" . implode(",", array_keys($vbulletin->GPC['setting']['as_content'])) . ")\n\t\t\t\t"); build_activitystream_datastore(); $settings['as_content'] = ''; break; // ************************************************** // ************************************************** case 'banemail': build_datastore('banemail', $settings['banemail']); $settings['banemail'] = ''; break; // ************************************************** // ************************************************** case 'editormodes': $vbulletin->input->clean_array_gpc('p', array('fe' => TYPE_UINT, 'qr' => TYPE_UINT, 'qe' => TYPE_UINT)); $settings['editormodes'] = serialize(array('fe' => $vbulletin->GPC['fe'], 'qr' => $vbulletin->GPC['qr'], 'qe' => $vbulletin->GPC['qe'])); break; // ************************************************** // ************************************************** case 'cookiepath': case 'cookiedomain': if ($settings[$oldsetting['varname'] . '_other'] and $settings[$oldsetting['varname'] . '_value']) { $settings[$oldsetting['varname']] = $settings[$oldsetting['varname'] . '_value']; } break; case 'apipostidmanage': $store = array('enable' => $settings['apipostidmanage']['enable'], 'iphone' => $settings['apipostidmanage']['iphone'], 'android' => $settings['apipostidmanage']['android'], 'facebook' => $settings['apipostidmanage']['facebook']); $settings["{$oldsetting['varname']}"] = serialize($store); break; // ************************************************** // ************************************************** default: ($hook = vBulletinHook::fetch_hook('admin_options_processing')) ? eval($hook) : false; if ($oldsetting['optioncode'] == 'multiinput') { $store = array(); foreach ($settings["{$oldsetting['varname']}"] as $value) { if ($value != '') { $store[] = $value; } } $settings["{$oldsetting['varname']}"] = serialize($store); } else { if (preg_match('#^(usergroup|forum)s?:([0-9]+|all|none)$#', $oldsetting['optioncode'])) { // serialize the array of usergroup inputs if (!is_array($settings["{$oldsetting['varname']}"])) { $settings["{$oldsetting['varname']}"] = array(); } $settings["{$oldsetting['varname']}"] = array_map('intval', $settings["{$oldsetting['varname']}"]); $settings["{$oldsetting['varname']}"] = serialize($settings["{$oldsetting['varname']}"]); } } } $newvalue = validate_setting_value($settings["{$oldsetting['varname']}"], $oldsetting['datatype']); // this is a strict type check because we want '' to be different from 0 // some special cases below only use != checks to see if the logical value has changed if (strval($oldsetting['value']) !== strval($newvalue)) { switch ($oldsetting['varname']) { case 'activememberdays': case 'activememberoptions': if ($oldsetting['value'] != $newvalue) { $vbulletin->options["{$oldsetting['varname']}"] = $newvalue; require_once DIR . '/includes/functions_databuild.php'; build_birthdays(); } break; case 'showevents': case 'showholidays': if ($oldsetting['value'] != $newvalue) { $vbulletin->options["{$oldsetting['varname']}"] = $newvalue; require_once DIR . '/includes/functions_calendar.php'; build_events(); } break; case 'languageid': if ($oldsetting['value'] != $newvalue) { $vbulletin->options['languageid'] = $newvalue; require_once DIR . '/includes/adminfunctions_language.php'; build_language($vbulletin->options['languageid']); } break; case 'cpstylefolder': $admindm =& datamanager_init('Admin', $vbulletin, ERRTYPE_CP); $admindm->set_existing($vbulletin->userinfo); $admindm->set('cssprefs', $newvalue); $admindm->save(); unset($admindm); break; case 'smcolumns': case 'attachthumbssize': if ($oldsetting['value'] != $newvalue) { $rebuildstyle = true; } case 'storecssasfile': if (!is_demo_mode() and $oldsetting['value'] != $newvalue) { $vbulletin->options['storecssasfile'] = $newvalue; $rebuildstyle = true; } break; case 'loadlimit': update_loadavg(); break; case 'tagcloud_usergroup': build_datastore('tagcloud', serialize(''), 1); break; case 'censorwords': case 'codemaxlines': case 'url_nofollow': case 'url_nofollow_whitelist': if ($oldsetting['value'] != $newvalue) { $vbulletin->db->query_write("TRUNCATE TABLE " . TABLE_PREFIX . "postparsed"); if (is_newer_version($vbulletin->options['templateversion'], '3.6', true)) { $vbulletin->db->query_write("TRUNCATE TABLE " . TABLE_PREFIX . "sigparsed"); } } ($hook = vBulletinHook::fetch_hook('admin_options_processing_censorcode')) ? eval($hook) : false; break; case 'album_recentalbumdays': if ($oldsetting['value'] > $newvalue) { require_once DIR . '/includes/functions_album.php'; exec_rebuild_album_updates(); } default: ($hook = vBulletinHook::fetch_hook('admin_options_processing_build')) ? eval($hook) : false; } if (is_demo_mode() and in_array($oldsetting['varname'], array('storecssasfile', 'attachfile', 'usefileavatar', 'errorlogdatabase', 'errorlogsecurity', 'safeupload', 'tmppath'))) { continue; } $vbulletin->db->query_write("\n\t\t\t\tUPDATE " . TABLE_PREFIX . "setting\n\t\t\t\tSET value = '" . $vbulletin->db->escape_string($newvalue) . "'\n\t\t\t\tWHERE varname = '" . $vbulletin->db->escape_string($oldsetting['varname']) . "'\n\t\t\t"); } } build_options(); if ($rebuildstyle) { require_once DIR . '/includes/adminfunctions_template.php'; print_rebuild_style(-1, '', 1, 0, 0, 0); print_rebuild_style(-2, '', 1, 0, 0, 0); } }
$upgrade->run_query($upgrade_phrases['upgrade_300b3.php']['updating_usergroup_permissions'], "UPDATE " . TABLE_PREFIX . "usergroup SET\n\t\t\t\tgenericpermissions = genericpermissions | " . $vbulletin->bf_ugp_genericoptions['requirehvcheck'] . "\n\t\t\t WHERE usergroupid = 1"); } else { $hvcheck = array_sum($vbulletin->bf_misc_hvcheck); } $upgrade->run_query($upgrade_phrases['upgrade_380a2.php']['update_hv_options'], "REPLACE INTO " . TABLE_PREFIX . "setting\n\t\t\t(varname, grouptitle, value, volatile, product)\n\t\tVALUES ('hvcheck', 'humanverification', {$hvcheck}, 1, 'vbulletin')"); // Give permissions $upgrade->run_query(sprintf($upgrade_phrases['upgrade_380a2.php']['granting_permissions'], 'usergroup', 1, 1), "UPDATE " . TABLE_PREFIX . "usergroup SET\n\t\t\tusercsspermissions = usercsspermissions |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_genericpermissions['canmodifyprofile'] . ", " . $vbulletin->bf_ugp_usercsspermissions['caneditprivacy'] . ", 0),\n\t\t\tforumpermissions = forumpermissions |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_forumpermissions['cangetattachment'] . ", " . $vbulletin->bf_ugp_forumpermissions['canseethumbnails'] . ", 0),\n\t\t\tgenericoptions = genericoptions |\n\t\t\t\tIF(usergroupid = 1," . $vbulletin->bf_ugp_genericoptions['requirehvcheck'] . ", 0),\n\t\t\tsocialgrouppermissions = socialgrouppermissions |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_forumpermissions['canreplyown'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['canpostmessage'] . ", 0) |\n\t\t\t\tIF(adminpermissions & " . $vbulletin->bf_ugp_adminpermissions['ismoderator'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['canalwayspostmessage'] . ", 0) |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_forumpermissions['canpostnew'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['cancreatediscussion'] . ", 0) |\n\t\t\t\tIF(adminpermissions & " . $vbulletin->bf_ugp_adminpermissions['ismoderator'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['canalwayscreatediscussion'] . ", 0) |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_forumpermissions['canopenclose'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['canlimitdiscussion'] . ", 0) |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_forumpermissions['candeletethread'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['canmanagediscussions'] . ", 0) |\n\t\t\t\tIF(genericpermissions & " . $vbulletin->bf_ugp_genericpermissions['canprofilepic'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['canuploadgroupicon'] . ", 0) |\n\t\t\t\tIF(genericpermissions & " . $vbulletin->bf_ugp_genericpermissions['cananimateprofilepic'] . ", " . $vbulletin->bf_ugp_socialgrouppermissions['cananimategroupicon'] . ", 0),\n\t\t\tgroupiconmaxsize = profilepicmaxsize,\n\t\t\tpmthrottlequantity = 0,\n\t\t\tmaximumsocialgroups = 5\n\t\t"); $upgrade->run_query(sprintf($upgrade_phrases['upgrade_380a2.php']['granting_permissions'], 'forumpermission', 1, 1), "UPDATE " . TABLE_PREFIX . "forumpermission SET\n\t\t\tforumpermissions = forumpermissions |\n\t\t\t\tIF(forumpermissions & " . $vbulletin->bf_ugp_forumpermissions['cangetattachment'] . ", " . $vbulletin->bf_ugp_forumpermissions['canseethumbnails'] . ", 0)\n\t\t"); // Give moderator permissions $upgrade->run_query(sprintf($upgrade_phrases['upgrade_300b3.php']['altering_x_table'], 'moderator', 1, 1), "UPDATE " . TABLE_PREFIX . "moderator SET\n\t\t\tpermissions2 = permissions2 |\n\t\t\t\tIF(permissions & " . $vbulletin->bf_misc_moderatorpermissions2['caneditgroupmessages'] . ", " . $vbulletin->bf_misc_moderatorpermissions2['caneditsocialgroups'] . ", 0) |\n\t\t\t\tIF(permissions & " . $vbulletin->bf_misc_moderatorpermissions2['candeletegroupmessages'] . ", " . $vbulletin->bf_misc_moderatorpermissions2['candeletediscussions'] . ", 0) |\n\t\t\t\tIF(permissions & " . $vbulletin->bf_misc_moderatorpermissions2['candeletesocialgroups'] . ", " . $vbulletin->bf_misc_moderatorpermissions2['cantransfersocialgroups'] . ", 0) |\n\t\t\t\tIF(permissions & " . $vbulletin->bf_misc_moderatorpermissions2['canremovegroupmessages'] . ", " . $vbulletin->bf_misc_moderatorpermissions2['canremovediscussions'] . ", 0) |\n\t\t\t\tIF(permissions & " . $vbulletin->bf_misc_moderatorpermissions2['canmoderategroupmessages'] . ", " . $vbulletin->bf_misc_moderatorpermissions2['canmoderatediscussions'] . ", 0)\n\t\t"); // Update latest albums $upgrade->show_message($upgrade_phrases['upgrade_380a2.php']['update_album_update_counters']); $upgrade->execute(); require_once DIR . '/includes/functions_album.php'; $vbulletin->options['album_recentalbumdays'] = 7; exec_rebuild_album_updates(); } // ############################################################################# // FINAL step (notice the SCRIPTCOMPLETE define) if ($vbulletin->GPC['step'] == 5) { $db->query_write("\n\t\tDELETE FROM " . TABLE_PREFIX . "phrase\n\t\tWHERE varname LIKE 'notice\\_%\\_title'\n\t\t\tAND fieldname = 'global'\n\t"); require_once DIR . '/includes/adminfunctions_prefix.php'; build_prefix_datastore(); build_forum_permissions(); // tell log_upgrade_step() that the script is done define('SCRIPTCOMPLETE', true); } // ############################################################################# print_next_step(); print_upgrade_footer(); /*======================================================================*\
/** * Updates the setting table based on data passed in then rebuilds the datastore. * Only entries in the array are updated (allows partial updates). * * @param array Array of settings. Format: [setting_name] = new_value * */ function save_settings($settings) { global $vbulletin, $vbphrase; //a few variables to track changes for processing after all variables are updated. $rebuildstyle = false; $templatecachepathchanged = false; $oldtemplatepath = null; $newtemplatepath = null; $userContext = vB::getUserContext(); $cleaner = vB::getCleaner(); $canAdminAll = $userContext->hasAdminPermission('canadminsettingsall'); $oldsettings = vB::getDbAssertor()->assertQuery('vBAdmincp:getCurrentSettings', array('varname' => array_keys($settings))); foreach ($oldsettings as $oldsetting) { //check the setting and group permissions if (!empty($oldsetting['adminperm']) and !$userContext->hasAdminPermission($oldsetting['adminperm']) or !empty($oldsetting['groupperm']) and !$userContext->hasAdminPermission($oldsetting['groupperm'])) { throw new vB_Exception_Api('no_permission'); } switch ($oldsetting['varname']) { // ************************************************** case 'bbcode_html_colors': $settings['bbcode_html_colors'] = serialize($settings['bbcode_html_colors']); break; // ************************************************** // ************************************************** case 'styleid': vB::getDbAssertor()->assertQuery('vBForum:style', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'userselect' => 1, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'styleid', 'value' => $settings['styleid'], 'operator' => vB_dB_Query::OPERATOR_EQ)))); break; // ************************************************** // ************************************************** case 'banemail': vB::getDatastore()->build('banemail', $settings['banemail']); $settings['banemail'] = ''; break; // ************************************************** // ************************************************** case 'editormodes': $vbulletin->input->clean_array_gpc('p', array('fe' => vB_Cleaner::TYPE_UINT, 'qr' => vB_Cleaner::TYPE_UINT, 'qe' => vB_Cleaner::TYPE_UINT)); $settings['editormodes'] = serialize(array('fe' => $vbulletin->GPC['fe'], 'qr' => $vbulletin->GPC['qr'], 'qe' => $vbulletin->GPC['qe'])); break; // ************************************************** // ************************************************** case 'attachresizes': $vbulletin->input->clean_array_gpc('p', array('attachresizes' => vB_Cleaner::TYPE_ARRAY_UINT)); $value = @unserialize($oldsetting['value']); $invalidate = array(); if ($value[vB_Api_Filedata::SIZE_ICON] != $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_ICON]) { $invalidate[] = vB_Api_Filedata::SIZE_ICON; } if ($value[vB_Api_Filedata::SIZE_THUMB] != $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_THUMB]) { $invalidate[] = vB_Api_Filedata::SIZE_THUMB; } if ($value[vB_Api_Filedata::SIZE_SMALL] != $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_SMALL]) { $invalidate[] = vB_Api_Filedata::SIZE_SMALL; } if ($value[vB_Api_Filedata::SIZE_MEDIUM] != $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_MEDIUM]) { $invalidate[] = vB_Api_Filedata::SIZE_MEDIUM; } if ($value[vB_Api_Filedata::SIZE_LARGE] != $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_LARGE]) { $invalidate[] = vB_Api_Filedata::SIZE_LARGE; } if (!empty($invalidate)) { vB::getDbAssertor()->update('vBForum:filedataresize', array('reload' => 1), array('resize_type' => $invalidate)); } $settings['attachresizes'] = serialize(array(vB_Api_Filedata::SIZE_ICON => $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_ICON], vB_Api_Filedata::SIZE_THUMB => $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_THUMB], vB_Api_Filedata::SIZE_SMALL => $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_SMALL], vB_Api_Filedata::SIZE_MEDIUM => $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_MEDIUM], vB_Api_Filedata::SIZE_LARGE => $vbulletin->GPC['attachresizes'][vB_Api_Filedata::SIZE_LARGE])); break; case 'thumbquality': if ($oldsetting['value'] != $settings['thumbquality']) { vB::getDbAssertor()->update('vBForum:filedataresize', array('reload' => 1), vB_dB_Query::CONDITION_ALL); } break; // ************************************************** // ************************************************** case 'cookiepath': case 'cookiedomain': if ($settings[$oldsetting['varname'] . '_other'] and $settings[$oldsetting['varname'] . '_value']) { $settings[$oldsetting['varname']] = $settings[$oldsetting['varname'] . '_value']; } break; // ************************************************** // ************************************************** default: // Legacy Hook 'admin_options_processing' Removed // if ($oldsetting['optioncode'] == 'multiinput') { $store = array(); foreach ($settings["{$oldsetting['varname']}"] as $value) { if ($value != '') { $store[] = $value; } } $settings["{$oldsetting['varname']}"] = serialize($store); } else { if (preg_match('#^(usergroup|forum)s?:([0-9]+|all|none)$#', $oldsetting['optioncode'])) { // serialize the array of usergroup inputs if (!is_array($settings["{$oldsetting['varname']}"])) { $settings["{$oldsetting['varname']}"] = array(); } $settings["{$oldsetting['varname']}"] = array_map('intval', $settings["{$oldsetting['varname']}"]); $settings["{$oldsetting['varname']}"] = serialize($settings["{$oldsetting['varname']}"]); } } } $newvalue = validate_setting_value($settings["{$oldsetting['varname']}"], $oldsetting['datatype']); if ($canAdminAll and isset($_POST['adminperm_' . $oldsetting[varname]])) { $newAdminPerm = substr($cleaner->clean($_POST['adminperm_' . $oldsetting[varname]], vB_Cleaner::TYPE_STR), 0, 32); } else { $newAdminPerm = $oldsetting['adminperm']; } // this is a strict type check because we want '' to be different from 0 // some special cases below only use != checks to see if the logical value has changed if ($oldsetting['value'] === NULL or strval($oldsetting['value']) !== strval($newvalue) or strval($oldsetting['adminperm']) !== strval($newAdminPerm)) { switch ($oldsetting['varname']) { case 'cache_templates_as_files': if (!is_demo_mode()) { $templatecachepathchanged = true; } break; case 'template_cache_path': if (!is_demo_mode()) { $oldtemplatepath = strval($oldsetting['value']); $newtemplatepath = $newvalue; } break; case 'languageid': if ($oldsetting['value'] != $newvalue) { vB::getDatastore()->setOption('languageid', $newvalue, false); require_once DIR . '/includes/adminfunctions_language.php'; build_language($newvalue); } break; case 'cpstylefolder': $admindm =& datamanager_init('Admin', $vbulletin, vB_DataManager_Constants::ERRTYPE_CP); $admindm->set_existing(vB::getCurrentSession()->fetch_userinfo()); $admindm->set('cssprefs', $newvalue); $admindm->save(); unset($admindm); break; case 'attachthumbssize': if ($oldsetting['value'] != $newvalue) { $rebuildstyle = true; } case 'storecssasfile': if (!is_demo_mode() and $oldsetting['value'] != $newvalue) { vB::getDatastore()->setOption('storecssasfile', $newvalue, false); $rebuildstyle = true; } break; case 'loadlimit': update_loadavg(); break; case 'tagcloud_usergroup': build_datastore('tagcloud', serialize(''), 1); break; case 'censorwords': case 'codemaxlines': case 'url_nofollow': case 'url_nofollow_whitelist': if ($oldsetting['value'] != $newvalue) { if (vB::getDatastore()->getOption('templateversion') >= '3.6') { vB::getDbAssertor()->assertQuery('truncateTable', array('table' => 'sigparsed')); } } // Legacy Hook 'admin_options_processing_censorcode' Removed // break; case 'album_recentalbumdays': if ($oldsetting['value'] > $newvalue) { require_once DIR . '/includes/functions_album.php'; exec_rebuild_album_updates(); } default: // Legacy Hook 'admin_options_processing_build' Removed // } if (is_demo_mode() and in_array($oldsetting['varname'], array('cache_templates_as_files', 'template_cache_path', 'storecssasfile', 'attachfile', 'usefileavatar', 'errorlogdatabase', 'errorlogsecurity', 'safeupload', 'tmppath'))) { continue; } $updateSetting = vB::getDbAssertor()->assertQuery('setting', array(vB_dB_Query::TYPE_KEY => vB_dB_Query::QUERY_UPDATE, 'value' => $newvalue, 'adminperm' => $newAdminPerm, vB_dB_Query::CONDITIONS_KEY => array(array('field' => 'varname', 'value' => $oldsetting['varname'], 'operator' => vB_dB_Query::OPERATOR_EQ)))); } } if (!isset($oldsetting)) { return false; } vB::getDatastore()->build_options(); if (defined('DEV_AUTOEXPORT') and DEV_AUTOEXPORT) { require_once DIR . '/includes/functions_filesystemxml.php'; $xml = get_settings_export_xml('vbulletin'); autoexport_write_file_with_backup(DIR . '/install/vbulletin-settings.xml', $xml); } //handle changes for cache_templates_as_files and template_cache_path //we do it here because there are interactions between them and we don't //want to redo the chache changes twice if both are changed. $api = vB_Api::instanceInternal('template'); if ($templatecachepathchanged or !is_null($oldtemplatepath) and !is_null($newtemplatepath)) { if (vB::getDatastore()->getOption('cache_templates_as_files')) { if (!is_null($oldtemplatepath)) { //temporarily set the datastore path to the old value to clear it. vB::getDatastore()->setOption('template_cache_path', $oldtemplatepath, false); $api->deleteAllTemplateFiles(); vB::getDatastore()->setOption('template_cache_path', $newtemplatepath, false); } $api->saveAllTemplatesToFile(); } else { //we we changed directories and the cache is off, delete from the old directory if (!is_null($oldtemplatepath)) { vB::getDatastore()->setOption('template_cache_path', $oldtemplatepath, false); $api->deleteAllTemplateFiles(); vB::getDatastore()->setOption('template_cache_path', $newtemplatepath, false); } else { $api->deleteAllTemplateFiles(); } } } if ($rebuildstyle) { require_once DIR . '/includes/adminfunctions_template.php'; print_rebuild_style(-1, '', 1, 0, 0, 0); } return true; }