Пример #1
0
 /**
  * {@inheritdoc}
  */
 public function run()
 {
     // Include diff engine
     $this->update_helper->include_file('includes/diff/diff.' . $this->php_ext);
     $this->update_helper->include_file('includes/diff/engine.' . $this->php_ext);
     // Set up basic vars
     $old_path = $this->update_helper->get_path_to_old_update_files();
     $new_path = $this->update_helper->get_path_to_new_update_files();
     $files_to_diff = $this->installer_config->get('update_files', array());
     $files_to_diff = $files_to_diff['update_with_diff'];
     // Set progress bar
     $this->iohandler->set_task_count(count($files_to_diff), true);
     $this->iohandler->set_progress('UPDATE_FILE_DIFF', 0);
     $progress_count = $this->installer_config->get('file_diff_update_count', 0);
     // Recover progress
     $progress_key = $this->installer_config->get('differ_progress_key', -1);
     $progress_recovered = $progress_key === -1;
     $merge_conflicts = $this->installer_config->get('merge_conflict_list', array());
     foreach ($files_to_diff as $key => $filename) {
         if ($progress_recovered === false) {
             if ($progress_key === $key) {
                 $progress_recovered = true;
             }
             continue;
         }
         // Read in files' content
         $file_contents = array();
         // Handle the special case when user created a file with the filename that is now new in the core
         $file_contents[0] = file_exists($old_path . $filename) ? file_get_contents($old_path . $filename) : '';
         $filenames = array($this->phpbb_root_path . $filename, $new_path . $filename);
         foreach ($filenames as $file_to_diff) {
             $file_contents[] = file_get_contents($file_to_diff);
             if ($file_contents[sizeof($file_contents) - 1] === false) {
                 $this->iohandler->add_error_message(array('FILE_DIFFER_ERROR_FILE_CANNOT_BE_READ', $files_to_diff));
                 unset($file_contents);
                 throw new user_interaction_required_exception();
             }
         }
         $diff = new \diff3($file_contents[0], $file_contents[1], $file_contents[2]);
         unset($file_contents);
         // Handle conflicts
         if ($diff->get_num_conflicts() !== 0) {
             $merge_conflicts[] = $filename;
         }
         // Save merged output
         $this->cache->put('_file_' . md5($filename), base64_encode(implode("\n", $diff->merged_output())));
         unset($diff);
         $progress_count++;
         $this->iohandler->set_progress('UPDATE_FILE_DIFF', $progress_count);
         if ($this->installer_config->get_time_remaining() <= 0 || $this->installer_config->get_memory_remaining() <= 0) {
             // Save differ progress
             $this->installer_config->set('differ_progress_key', $key);
             $this->installer_config->set('merge_conflict_list', $merge_conflicts);
             $this->installer_config->set('file_diff_update_count', $progress_count);
             // Request refresh
             throw new resource_limit_reached_exception();
         }
     }
     $this->iohandler->finish_progress('ALL_FILES_DIFFED');
     $this->installer_config->set('merge_conflict_list', $merge_conflicts);
 }
Пример #2
0
 function editPage()
 {
     global $WikiTheme;
     $saveFailed = false;
     $tokens =& $this->tokens;
     $tokens['PAGE_LOCKED_MESSAGE'] = '';
     $tokens['CONCURRENT_UPDATE_MESSAGE'] = '';
     $r =& $this->request;
     if (isset($r->args['pref']['editWidth']) and $r->getPref('editWidth') != $r->args['pref']['editWidth']) {
         $r->_prefs->set('editWidth', $r->args['pref']['editWidth']);
     }
     if (isset($r->args['pref']['editHeight']) and $r->getPref('editHeight') != $r->args['pref']['editHeight']) {
         $r->_prefs->set('editHeight', $r->args['pref']['editHeight']);
     }
     if (!$this->canEdit()) {
         if ($this->isInitialEdit()) {
             return $this->viewSource();
         }
         $tokens['PAGE_LOCKED_MESSAGE'] = $this->getLockedMessage();
     } elseif ($r->getArg('save_and_redirect_to') != "") {
         if (ENABLE_CAPTCHA && $this->Captcha->Failed()) {
             $this->tokens['PAGE_LOCKED_MESSAGE'] = HTML::p(HTML::h1($this->Captcha->failed_msg));
         } elseif ($this->savePage()) {
             // noreturn
             $r->redirect(WikiURL($r->getArg('save_and_redirect_to')));
             return true;
             // Page saved.
         }
         $saveFailed = true;
     } elseif ($this->editaction == 'save') {
         if (ENABLE_CAPTCHA && $this->Captcha->Failed()) {
             $this->tokens['PAGE_LOCKED_MESSAGE'] = HTML::p(HTML::h1($this->Captcha->failed_msg));
         } elseif ($this->savePage()) {
             return true;
             // Page saved.
         } else {
             $saveFailed = true;
         }
     }
     if ($saveFailed and $this->isConcurrentUpdate()) {
         // Get the text of the original page, and the two conflicting edits
         // The diff3 class takes arrays as input.  So retrieve content as
         // an array, or convert it as necesary.
         $orig = $this->page->getRevision($this->_currentVersion);
         // FIXME: what if _currentVersion has be deleted?
         $orig_content = $orig->getContent();
         $this_content = explode("\n", $this->_content);
         $other_content = $this->current->getContent();
         include_once "lib/diff3.php";
         $diff = new diff3($orig_content, $this_content, $other_content);
         $output = $diff->merged_output(_("Your version"), _("Other version"));
         // Set the content of the textarea to the merged diff
         // output, and update the version
         $this->_content = implode("\n", $output);
         $this->_currentVersion = $this->current->getVersion();
         $this->version = $this->_currentVersion;
         $unresolved = $diff->ConflictingBlocks;
         $tokens['CONCURRENT_UPDATE_MESSAGE'] = $this->getConflictMessage($unresolved);
     } elseif ($saveFailed && !$this->_isSpam) {
         $tokens['CONCURRENT_UPDATE_MESSAGE'] = HTML(HTML::h2(_("Some internal editing error")), HTML::p(_("Your are probably trying to edit/create an invalid version of this page.")), HTML::p(HTML::em(_("&version=-1 might help."))));
     }
     if ($this->editaction == 'edit_convert') {
         $tokens['PREVIEW_CONTENT'] = $this->getConvertedPreview();
     }
     if ($this->editaction == 'preview') {
         $tokens['PREVIEW_CONTENT'] = $this->getPreview();
     }
     // FIXME: convert to _MESSAGE?
     // FIXME: NOT_CURRENT_MESSAGE?
     $tokens = array_merge($tokens, $this->getFormElements());
     if (ENABLE_EDIT_TOOLBAR) {
         include_once "lib/EditToolbar.php";
         $toolbar = new EditToolbar();
         $tokens = array_merge($tokens, $toolbar->getTokens());
     }
     return $this->output('editpage', _("Edit: %s"));
 }
	/**
	* Compare files for storage in update_list
	*/
	function make_update_diff(&$update_list, $original_file, $file, $custom = false)
	{
		global $phpbb_root_path, $user;

		$update_ary = array('filename' => $file, 'custom' => $custom);

		if ($custom)
		{
			$update_ary['original'] = $original_file;
		}

		// On a successfull update the new location file exists but the old one does not exist.
		// Check for this circumstance, the new file need to be up-to-date with the current file then...
		if (!file_exists($this->old_location . $original_file) && file_exists($this->new_location . $original_file) && file_exists($phpbb_root_path . $file))
		{
			$tmp = array(
				'file1'		=> file_get_contents($this->new_location . $original_file),
				'file2'		=> file_get_contents($phpbb_root_path . $file),
			);

			// We need to diff the contents here to make sure the file is really the one we expect
			$diff = new diff($tmp['file1'], $tmp['file2'], false);
			$empty = $diff->is_empty();

			unset($tmp, $diff);

			// if there are no differences we have an up-to-date file...
			if ($empty)
			{
				$update_list['up_to_date'][] = $update_ary;
				return;
			}

			// If no other status matches we have another file in the way...
			$update_list['new_conflict'][] = $update_ary;
			return;
		}

		// Old file removed?
		if (file_exists($this->old_location . $original_file) && !file_exists($this->new_location . $original_file))
		{
			return;
		}

		// Check for existance, else abort immediately
		if (!file_exists($this->old_location . $original_file) || !file_exists($this->new_location . $original_file))
		{
			trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
		}

		$tmp = array(
			'file1'		=> file_get_contents($this->old_location . $original_file),
			'file2'		=> file_get_contents($phpbb_root_path . $file),
		);

		// We need to diff the contents here to make sure the file is really the one we expect
		$diff = new diff($tmp['file1'], $tmp['file2'], false);
		$empty_1 = $diff->is_empty();

		unset($tmp, $diff);

		$tmp = array(
			'file1'		=> file_get_contents($this->new_location . $original_file),
			'file2'		=> file_get_contents($phpbb_root_path . $file),
		);

		// We need to diff the contents here to make sure the file is really the one we expect
		$diff = new diff($tmp['file1'], $tmp['file2'], false);
		$empty_2 = $diff->is_empty();

		unset($tmp, $diff);

		// If the file is not modified we are finished here...
		if ($empty_1)
		{
			// Further check if it is already up to date - it could happen that non-modified files
			// slip through
			if ($empty_2)
			{
				$update_list['up_to_date'][] = $update_ary;
				return;
			}

			$update_list['not_modified'][] = $update_ary;
			return;
		}

		// If the file had been modified then we need to check if it is already up to date

		// if there are no differences we have an up-to-date file...
		if ($empty_2)
		{
			$update_list['up_to_date'][] = $update_ary;
			return;
		}

		// if the file is modified we try to make sure a merge succeed
		$tmp = array(
			'file1'		=> file_get_contents($this->old_location . $original_file),
			'file2'		=> file_get_contents($phpbb_root_path . $file),
			'file3'		=> file_get_contents($this->new_location . $original_file),
		);

		$diff = new diff3($tmp['file1'], $tmp['file2'], $tmp['file3'], false);

		unset($tmp);

		if ($diff->merged_output(false, false, false, true))
		{
			$update_ary['conflicts'] = $diff->_conflicting_blocks;

			// There is one special case... users having merged with a conflicting file... we need to check this
			$tmp = array(
				'file1'		=> file_get_contents($phpbb_root_path . $file),
				'file2'		=> implode("\n", $diff->merged_orig_output()),
			);

			$diff = new diff($tmp['file1'], $tmp['file2'], false);
			$empty = $diff->is_empty();

			if ($empty)
			{
				unset($update_ary['conflicts']);
				unset($diff);
				$update_list['up_to_date'][] = $update_ary;
				return;
			}

			$update_list['conflict'][] = $update_ary;
			unset($diff);

			return;
		}

		$tmp = array(
			'file1'		=> file_get_contents($phpbb_root_path . $file),
			'file2'		=> implode("\n", $diff->merged_output()),
		);

		// now compare the merged output with the original file to see if the modified file is up to date
		$diff = new diff($tmp['file1'], $tmp['file2'], false);
		$empty = $diff->is_empty();

		if ($empty)
		{
			unset($diff);

			$update_list['up_to_date'][] = $update_ary;
			return;
		}

		// If no other status matches we have a modified file...
		$update_list['modified'][] = $update_ary;
	}
Пример #4
0
	/**
	* Compare files for storage in update_list
	*/
	function make_update_diff(&$update_list, $original_file, $file, $custom = false)
	{
		global $phpbb_root_path, $user;

		$update_ary = array('filename' => $file, 'custom' => $custom);

		if ($custom)
		{
			$update_ary['original'] = $original_file;
		}

		// we only want to know if the files are successfully merged and newlines could result in errors (duplicate addition of lines and such things)
		// Therefore we check for empty diffs with two methods, preserving newlines and not preserving them (which mostly works best, therefore the first option)

		// On a successfull update the new location file exists but the old one does not exist.
		// Check for this circumstance, the new file need to be up-to-date with the current file then...
		if (!file_exists($this->old_location . $original_file) && file_exists($this->new_location . $original_file) && file_exists($phpbb_root_path . $file))
		{
			$tmp = array(
				'file1'		=> file_get_contents($this->new_location . $original_file),
				'file2'		=> file_get_contents($phpbb_root_path . $file),
			);

			// We need to diff the contents here to make sure the file is really the one we expect
			$diff = new diff($tmp['file1'], $tmp['file2'], false);
			$empty = $diff->is_empty();

			unset($tmp, $diff);

			// if there are no differences we have an up-to-date file...
			if ($empty)
			{
				$update_list['up_to_date'][] = $update_ary;
				return;
			}

			// If no other status matches we have another file in the way...
			$update_list['new_conflict'][] = $update_ary;
			return;
		}

		// Old file removed?
		if (file_exists($this->old_location . $original_file) && !file_exists($this->new_location . $original_file))
		{
			return;
		}

		// Check for existance, else abort immediately
		if (!file_exists($this->old_location . $original_file) || !file_exists($this->new_location . $original_file))
		{
			trigger_error($user->lang['INCOMPLETE_UPDATE_FILES'], E_USER_ERROR);
		}

		$preserve_cr_ary = array(false, true);

		foreach ($preserve_cr_ary as $preserve_cr)
		{
			$tmp = array(
				'file1'		=> file_get_contents($this->old_location . $original_file),
				'file2'		=> file_get_contents($phpbb_root_path . $file),
			);

			// We need to diff the contents here to make sure the file is really the one we expect
			$diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
			$empty_1 = $diff->is_empty();

			unset($tmp, $diff);

			$tmp = array(
				'file1'		=> file_get_contents($this->new_location . $original_file),
				'file2'		=> file_get_contents($phpbb_root_path . $file),
			);

			$diff = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
			$empty_2 = $diff->is_empty();

			unset($tmp, $diff);

			// If the file is not modified we are finished here...
			if ($empty_1)
			{
				// Further check if it is already up to date - it could happen that non-modified files
				// slip through
				if ($empty_2)
				{
					$update_list['up_to_date'][] = $update_ary;
					return;
				}

				$update_list['not_modified'][] = $update_ary;
				return;
			}

			// If the file had been modified then we need to check if it is already up to date

			// if there are no differences we have an up-to-date file...
			if ($empty_2)
			{
				$update_list['up_to_date'][] = $update_ary;
				return;
			}
		}

		$conflicts = false;

		foreach ($preserve_cr_ary as $preserve_cr)
		{
			// if the file is modified we try to make sure a merge succeed
			$tmp = array(
				'orig'		=> file_get_contents($this->old_location . $original_file),
				'final1'	=> file_get_contents($phpbb_root_path . $file),
				'final2'	=> file_get_contents($this->new_location . $original_file),
			);

			$diff = new diff3($tmp['orig'], $tmp['final1'], $tmp['final2'], $preserve_cr);
			unset($tmp);

			if (!$diff->get_num_conflicts())
			{
				$tmp = array(
					'file1'		=> file_get_contents($phpbb_root_path . $file),
					'file2'		=> implode("\n", $diff->merged_output()),
				);

				// now compare the merged output with the original file to see if the modified file is up to date
				$diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
				$empty = $diff2->is_empty();

				unset($diff, $diff2);

				if ($empty)
				{
					$update_list['up_to_date'][] = $update_ary;
					return;
				}

				// If we preserve cr tag it as modified because the conflict would not show in this mode anyway
				if ($preserve_cr)
				{
					$update_list['modified'][] = $update_ary;
					return;
				}
			}
			else
			{
				// There is one special case... users having merged with a conflicting file... we need to check this
				$tmp = array(
					'file1'		=> file_get_contents($phpbb_root_path . $file),
					'file2'		=> implode("\n", $diff->merged_new_output()),
				);

				$diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
				$empty = $diff2->is_empty();

				if (!$empty)
				{
					unset($tmp, $diff2);

					// We check if the user merged with his output
					$tmp = array(
						'file1'		=> file_get_contents($phpbb_root_path . $file),
						'file2'		=> implode("\n", $diff->merged_orig_output()),
					);

					$diff2 = new diff($tmp['file1'], $tmp['file2'], $preserve_cr);
					$empty = $diff2->is_empty();
				}

				if (!$empty)
				{
					$conflicts = $diff->get_num_conflicts();
				}

				unset($diff, $diff2);

				if ($empty)
				{
					// A conflict got resolved...
					$update_list['up_to_date'][] = $update_ary;
					return;
				}
			}
		}

		if ($conflicts !== false)
		{
			$update_ary['conflicts'] = $conflicts;
			$update_list['conflict'][] = $update_ary;
			return;
		}

		// If no other status matches we have a modified file...
		$update_list['modified'][] = $update_ary;
	}