I have a PHPBB forum and just ran into a serious issue after my host switched me from a shared server to a VPS, and they can't figure out how to fix it for me.
On all of my posts that contained inline attached pictures, the pictures no longer display, instead if I get a hyperlink to the image.
Instead of hyperlinks, the visitor is supposed to see actual pictures.
When I hover over the hyperlink, I see the following http://www.mydomain.com/forum/download/file.php?id=58
If I paste it directly into the browser, I get the following error message generated by file.php
"Unable to deliver file."
I'm attaching file.php to this post.
Now, if I post a new topic, attach and image and place the image inline, the image shows fine inside the post.
I'm not sure what went wrong and how I can resolve this issue.
Thank you

<?php
/**
*
* @package phpBB3
* @version $Id$
* @copyright (c) 2005 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/

/**
* @ignore
*/
define('IN_PHPBB', true);
$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './../';
$phpEx = substr(strrchr(__FILE__, '.'), 1);


// Thank you sun.
if (isset($_SERVER['CONTENT_TYPE']))
{
    if ($_SERVER['CONTENT_TYPE'] === 'application/x-java-archive')
    {
        exit;
    }
}
else if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Java') !== false)
{
    exit;
}

if (isset($_GET['avatar']))
{
    require($phpbb_root_path . 'includes/startup.' . $phpEx);
    require($phpbb_root_path . 'config.' . $phpEx);

    if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
    {
        exit;
    }

    require($phpbb_root_path . 'includes/acm/acm_' . $acm_type . '.' . $phpEx);
    require($phpbb_root_path . 'includes/cache.' . $phpEx);
    require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
    require($phpbb_root_path . 'includes/constants.' . $phpEx);
    require($phpbb_root_path . 'includes/functions.' . $phpEx);

    $db = new $sql_db();
    $cache = new cache();

    // Connect to DB
    if (!@$db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, false))
    {
        exit;
    }
    unset($dbpasswd);

    // worst-case default
    $browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : 'msie 6.0';

    $config = $cache->obtain_config();
    $filename = request_var('avatar', '');
    $avatar_group = false;
    $exit = false;

    if (isset($filename[0]) && $filename[0] === 'g')
    {
        $avatar_group = true;
        $filename = substr($filename, 1);
    }

    // '==' is not a bug - . as the first char is as bad as no dot at all
    if (strpos($filename, '.') == false)
    {
        send_status_line(403, 'Forbidden');
        $exit = true;
    }

    if (!$exit)
    {
        $ext        = substr(strrchr($filename, '.'), 1);
        $stamp      = (int) substr(stristr($filename, '_'), 1);
        $filename   = (int) $filename;
        $exit = set_modified_headers($stamp, $browser);
    }
    if (!$exit && !in_array($ext, array('png', 'gif', 'jpg', 'jpeg')))
    {
        // no way such an avatar could exist. They are not following the rules, stop the show.
        send_status_line(403, 'Forbidden');
        $exit = true;
    }


    if (!$exit)
    {
        if (!$filename)
        {
            // no way such an avatar could exist. They are not following the rules, stop the show.
            send_status_line(403, 'Forbidden');
        }
        else
        {
            send_avatar_to_browser(($avatar_group ? 'g' : '') . $filename . '.' . $ext, $browser);
        }
    }
    file_gc();
}

// implicit else: we are not in avatar mode
include($phpbb_root_path . 'common.' . $phpEx);

$download_id = request_var('id', 0);
$mode = request_var('mode', '');
$thumbnail = request_var('t', false);

// Start session management, do not update session page.
$user->session_begin(false);
$auth->acl($user->data);
$user->setup('viewtopic');

if (!$download_id)
{
    send_status_line(404, 'Not Found');
    trigger_error('NO_ATTACHMENT_SELECTED');
}

if (!$config['allow_attachments'] && !$config['allow_pm_attach'])
{
    send_status_line(404, 'Not Found');
    trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED');
}

$sql = 'SELECT attach_id, in_message, post_msg_id, extension, is_orphan, poster_id, filetime
    FROM ' . ATTACHMENTS_TABLE . "
    WHERE attach_id = $download_id";
$result = $db->sql_query_limit($sql, 1);
$attachment = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

if (!$attachment)
{
    send_status_line(404, 'Not Found');
    trigger_error('ERROR_NO_ATTACHMENT');
}

if ((!$attachment['in_message'] && !$config['allow_attachments']) || ($attachment['in_message'] && !$config['allow_pm_attach']))
{
    send_status_line(404, 'Not Found');
    trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED');
}

$row = array();

if ($attachment['is_orphan'])
{
    // We allow admins having attachment permissions to see orphan attachments...
    $own_attachment = ($auth->acl_get('a_attach') || $attachment['poster_id'] == $user->data['user_id']) ? true : false;

    if (!$own_attachment || ($attachment['in_message'] && !$auth->acl_get('u_pm_download')) || (!$attachment['in_message'] && !$auth->acl_get('u_download')))
    {
        send_status_line(404, 'Not Found');
        trigger_error('ERROR_NO_ATTACHMENT');
    }

    // Obtain all extensions...
    $extensions = $cache->obtain_attach_extensions(true);
}
else
{
    if (!$attachment['in_message'])
    {
        //
        $sql = 'SELECT p.forum_id, f.forum_password, f.parent_id
            FROM ' . POSTS_TABLE . ' p, ' . FORUMS_TABLE . ' f
            WHERE p.post_id = ' . $attachment['post_msg_id'] . '
                AND p.forum_id = f.forum_id';
        $result = $db->sql_query_limit($sql, 1);
        $row = $db->sql_fetchrow($result);
        $db->sql_freeresult($result);

        // Global announcement?
        $f_download = (!$row) ? $auth->acl_getf_global('f_download') : $auth->acl_get('f_download', $row['forum_id']);

        if ($auth->acl_get('u_download') && $f_download)
        {
            if ($row && $row['forum_password'])
            {
                // Do something else ... ?
                login_forum_box($row);
            }
        }
        else
        {
            send_status_line(403, 'Forbidden');
            trigger_error('SORRY_AUTH_VIEW_ATTACH');
        }
    }
    else
    {
        $row['forum_id'] = false;
        if (!$auth->acl_get('u_pm_download'))
        {
            send_status_line(403, 'Forbidden');
            trigger_error('SORRY_AUTH_VIEW_ATTACH');
        }

        // Check if the attachment is within the users scope...
        $sql = 'SELECT user_id, author_id
            FROM ' . PRIVMSGS_TO_TABLE . '
            WHERE msg_id = ' . $attachment['post_msg_id'];
        $result = $db->sql_query($sql);

        $allowed = false;
        while ($user_row = $db->sql_fetchrow($result))
        {
            if ($user->data['user_id'] == $user_row['user_id'] || $user->data['user_id'] == $user_row['author_id'])
            {
                $allowed = true;
                break;
            }
        }
        $db->sql_freeresult($result);

        if (!$allowed)
        {
            send_status_line(403, 'Forbidden');
            trigger_error('ERROR_NO_ATTACHMENT');
        }
    }

    // disallowed?
    $extensions = array();
    if (!extension_allowed($row['forum_id'], $attachment['extension'], $extensions))
    {
        send_status_line(404, 'Forbidden');
        trigger_error(sprintf($user->lang['EXTENSION_DISABLED_AFTER_POSTING'], $attachment['extension']));
    }
}

if (!download_allowed())
{
    send_status_line(403, 'Forbidden');
    trigger_error($user->lang['LINKAGE_FORBIDDEN']);
}

$download_mode = (int) $extensions[$attachment['extension']]['download_mode'];

// Fetching filename here to prevent sniffing of filename
$sql = 'SELECT attach_id, is_orphan, in_message, post_msg_id, extension, physical_filename, real_filename, mimetype, filetime
    FROM ' . ATTACHMENTS_TABLE . "
    WHERE attach_id = $download_id";
$result = $db->sql_query_limit($sql, 1);
$attachment = $db->sql_fetchrow($result);
$db->sql_freeresult($result);

if (!$attachment)
{
    send_status_line(404, 'Not Found');
    trigger_error('ERROR_NO_ATTACHMENT');
}

$attachment['physical_filename'] = utf8_basename($attachment['physical_filename']);
$display_cat = $extensions[$attachment['extension']]['display_cat'];

if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !$user->optionget('viewimg'))
{
    $display_cat = ATTACHMENT_CATEGORY_NONE;
}

if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !$user->optionget('viewflash'))
{
    $display_cat = ATTACHMENT_CATEGORY_NONE;
}

if ($thumbnail)
{
    $attachment['physical_filename'] = 'thumb_' . $attachment['physical_filename'];
}
else if (($display_cat == ATTACHMENT_CATEGORY_NONE/* || $display_cat == ATTACHMENT_CATEGORY_IMAGE*/) && !$attachment['is_orphan'])
{
    // Update download count
    $sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
        SET download_count = download_count + 1
        WHERE attach_id = ' . $attachment['attach_id'];
    $db->sql_query($sql);
}

if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && ((strpos(strtolower($user->browser), 'msie') !== false) && (strpos(strtolower($user->browser), 'msie 8.0') === false)))
{
    wrap_img_in_html(append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'id=' . $attachment['attach_id']), $attachment['real_filename']);
    file_gc();
}
else
{
    // Determine the 'presenting'-method
    if ($download_mode == PHYSICAL_LINK)
    {
        // This presenting method should no longer be used
        if (!@is_dir($phpbb_root_path . $config['upload_path']))
        {
            send_status_line(500, 'Internal Server Error');
            trigger_error($user->lang['PHYSICAL_DOWNLOAD_NOT_POSSIBLE']);
        }

        redirect($phpbb_root_path . $config['upload_path'] . '/' . $attachment['physical_filename']);
        file_gc();
    }
    else
    {
        send_file_to_browser($attachment, $config['upload_path'], $display_cat);
        file_gc();
    }
}


/**
* A simplified function to deliver avatars
* The argument needs to be checked before calling this function.
*/
function send_avatar_to_browser($file, $browser)
{
    global $config, $phpbb_root_path;

    $prefix = $config['avatar_salt'] . '_';
    $image_dir = $config['avatar_path'];

    // Adjust image_dir path (no trailing slash)
    if (substr($image_dir, -1, 1) == '/' || substr($image_dir, -1, 1) == '')
    {
        $image_dir = substr($image_dir, 0, -1) . '/';
    }
    $image_dir = str_replace(array('../', '..', './', '.'), '', $image_dir);

    if ($image_dir && ($image_dir[0] == '/' || $image_dir[0] == ''))
    {
        $image_dir = '';
    }
    $file_path = $phpbb_root_path . $image_dir . '/' . $prefix . $file;

    if ((@file_exists($file_path) && @is_readable($file_path)) && !headers_sent())
    {
        header('Pragma: public');

        $image_data = @getimagesize($file_path);
        header('Content-Type: ' . image_type_to_mime_type($image_data[2]));

        if (strpos(strtolower($browser), 'msie') !== false && strpos(strtolower($browser), 'msie 8.0') === false)
        {
            header('Content-Disposition: attachment; ' . header_filename($file));

            if (strpos(strtolower($browser), 'msie 6.0') !== false)
            {
                header('Expires: -1');
            }
            else
            {
                header('Expires: ' . gmdate('D, d M Y H:i:s GMT', time() + 31536000));
            }
        }
        else
        {
            header('Content-Disposition: inline; ' . header_filename($file));
            header('Expires: ' . gmdate('D, d M Y H:i:s GMT', time() + 31536000));
        }

        $size = @filesize($file_path);
        if ($size)
        {
            header("Content-Length: $size");
        }

        if (@readfile($file_path) == false)
        {
            $fp = @fopen($file_path, 'rb');

            if ($fp !== false)
            {
                while (!feof($fp))
                {
                    echo fread($fp, 8192);
                }
                fclose($fp);
            }
        }

        flush();
    }
    else
    {
        send_status_line(404, 'Not Found');
    }
}

/**
* Wraps an url into a simple html page. Used to display attachments in IE.
* this is a workaround for now; might be moved to template system later
* direct any complaints to 1 Microsoft Way, Redmond
*/
function wrap_img_in_html($src, $title)
{
    echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-Strict.dtd">';
    echo '<html>';
    echo '<head>';
    echo '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />';
    echo '<title>' . $title . '</title>';
    echo '</head>';
    echo '<body>';
    echo '<div>';
    echo '<img src="' . $src . '" alt="' . $title . '" />';
    echo '</div>';
    echo '</body>';
    echo '</html>';
}

/**
* Send file to browser
*/
function send_file_to_browser($attachment, $upload_dir, $category)
{
    global $user, $db, $config, $phpbb_root_path;

    $filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename'];

    if (!@file_exists($filename))
    {
        send_status_line(404, 'Not Found');
        trigger_error('ERROR_NO_ATTACHMENT');
    }

    // Correct the mime type - we force application/octetstream for all files, except images
    // Please do not change this, it is a security precaution
    if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0)
    {
        $attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream';
    }

    if (@ob_get_length())
    {
        @ob_end_clean();
    }

    // Now send the File Contents to the Browser
    $size = @filesize($filename);

    // To correctly display further errors we need to make sure we are using the correct headers for both (unsetting content-length may not work)

    // Check if headers already sent or not able to get the file contents.
    if (headers_sent() || !@file_exists($filename) || !@is_readable($filename))
    {
        // PHP track_errors setting On?
        if (!empty($php_errormsg))
        {
            send_status_line(500, 'Internal Server Error');
            trigger_error($user->lang['UNABLE_TO_DELIVER_FILE'] . '<br />' . sprintf($user->lang['TRACKED_PHP_ERROR'], $php_errormsg));
        }

        send_status_line(500, 'Internal Server Error');
        trigger_error('UNABLE_TO_DELIVER_FILE');
    }

    // Now the tricky part... let's dance
    header('Pragma: public');

    /**
    * Commented out X-Sendfile support. To not expose the physical filename within the header if xsendfile is absent we need to look into methods of checking it's status.
    *
    * Try X-Sendfile since it is much more server friendly - only works if the path is *not* outside of the root path...
    * lighttpd has core support for it. An apache2 module is available at http://celebnamer.celebworld.ws/stuff/mod_xsendfile/
    *
    * Not really ideal, but should work fine...
    * <code>
    *   if (strpos($upload_dir, '/') !== 0 && strpos($upload_dir, '../') === false)
    *   {
    *       header('X-Sendfile: ' . $filename);
    *   }
    * </code>
    */

    // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
    $is_ie8 = (strpos(strtolower($user->browser), 'msie 8.0') !== false);
    header('Content-Type: ' . $attachment['mimetype']);

    if ($is_ie8)
    {
        header('X-Content-Type-Options: nosniff');
    }

    if ($category == ATTACHMENT_CATEGORY_FLASH && request_var('view', 0) === 1)
    {
        // We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline
        header('Content-Disposition: inline');
    }
    else
    {
        if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false)))
        {
            header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
            if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
            {
                header('expires: -1');
            }
        }
        else
        {
            header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
            if ($is_ie8 && (strpos($attachment['mimetype'], 'image') !== 0))
            {
                header('X-Download-Options: noopen');
            }
        }
    }

    if ($size)
    {
        header("Content-Length: $size");
    }

    // Close the db connection before sending the file
    $db->sql_close();

    if (!set_modified_headers($attachment['filetime'], $user->browser))
    {
        // Try to deliver in chunks
        @set_time_limit(0);

        $fp = @fopen($filename, 'rb');

        if ($fp !== false)
        {
            while (!feof($fp))
            {
                echo fread($fp, 8192);
            }
            fclose($fp);
        }
        else
        {
            @readfile($filename);
        }

        flush();
    }
    file_gc();
}

/**
* Get a browser friendly UTF-8 encoded filename
*/
function header_filename($file)
{
    $user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : '';

    // There be dragons here.
    // Not many follows the RFC...
    if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Safari') !== false || strpos($user_agent, 'Konqueror') !== false)
    {
        return "filename=" . rawurlencode($file);
    }

    // follow the RFC for extended filename for the rest
    return "filename*=UTF-8''" . rawurlencode($file);
}

/**
* Check if downloading item is allowed
*/
function download_allowed()
{
    global $config, $user, $db;

    if (!$config['secure_downloads'])
    {
        return true;
    }

    $url = (!empty($_SERVER['HTTP_REFERER'])) ? trim($_SERVER['HTTP_REFERER']) : trim(getenv('HTTP_REFERER'));

    if (!$url)
    {
        return ($config['secure_allow_empty_referer']) ? true : false;
    }

    // Split URL into domain and script part
    $url = @parse_url($url);

    if ($url === false)
    {
        return ($config['secure_allow_empty_referer']) ? true : false;
    }

    $hostname = $url['host'];
    unset($url);

    $allowed = ($config['secure_allow_deny']) ? false : true;
    $iplist = array();

    if (($ip_ary = @gethostbynamel($hostname)) !== false)
    {
        foreach ($ip_ary as $ip)
        {
            if ($ip)
            {
                $iplist[] = $ip;
            }
        }
    }

    // Check for own server...
    $server_name = $user->host;

    // Forcing server vars is the only way to specify/override the protocol
    if ($config['force_server_vars'] || !$server_name)
    {
        $server_name = $config['server_name'];
    }

    if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
    {
        $allowed = true;
    }

    // Get IP's and Hostnames
    if (!$allowed)
    {
        $sql = 'SELECT site_ip, site_hostname, ip_exclude
            FROM ' . SITELIST_TABLE;
        $result = $db->sql_query($sql);

        while ($row = $db->sql_fetchrow($result))
        {
            $site_ip = trim($row['site_ip']);
            $site_hostname = trim($row['site_hostname']);

            if ($site_ip)
            {
                foreach ($iplist as $ip)
                {
                    if (preg_match('#^' . str_replace('*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
                    {
                        if ($row['ip_exclude'])
                        {
                            $allowed = ($config['secure_allow_deny']) ? false : true;
                            break 2;
                        }
                        else
                        {
                            $allowed = ($config['secure_allow_deny']) ? true : false;
                        }
                    }
                }
            }

            if ($site_hostname)
            {
                if (preg_match('#^' . str_replace('*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
                {
                    if ($row['ip_exclude'])
                    {
                        $allowed = ($config['secure_allow_deny']) ? false : true;
                        break;
                    }
                    else
                    {
                        $allowed = ($config['secure_allow_deny']) ? true : false;
                    }
                }
            }
        }
        $db->sql_freeresult($result);
    }

    return $allowed;
}

/**
* Check if the browser has the file already and set the appropriate headers-
* @returns false if a resend is in order.
*/
function set_modified_headers($stamp, $browser)
{
    // let's see if we have to send the file at all
    $last_load  =  isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime(trim($_SERVER['HTTP_IF_MODIFIED_SINCE'])) : false;
    if ((strpos(strtolower($browser), 'msie 6.0') === false) && (strpos(strtolower($browser), 'msie 8.0') === false))
    {
        if ($last_load !== false && $last_load >= $stamp)
        {
            send_status_line(304, 'Not Modified');
            // seems that we need those too ... browsers
            header('Pragma: public');
            header('Expires: ' . gmdate('D, d M Y H:i:s GMT', time() + 31536000));
            return true;
        }
        else
        {
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
        }
    }
    return false;
}

function file_gc()
{
    global $cache, $db;
    if (!empty($cache))
    {
        $cache->unload();
    }
    $db->sql_close();
    exit;
}

?>Inline Code Example Here

Recommended Answers

All 10 Replies

I'm guessing that the reason you're seeing hyperlinks to broken images instead of the actual images is because their path isn't correct.

There's nothing wrong with your PHP file. The problem is most likely an Apache issue related to an .htaccess file or the way Apache (or whichever web server you're using) is configured.

Things to check:

  • Ensure the path to the httpdocs (or similar) directory is the same as it used to be on the old server
  • Ensure that all of the existing images are stored in the same relative directory as they used to be
  • Check the owner and permissions of all the old files (it's possible the owner changed during the migration)
  • Check that .htaccess files are the same

Things like that :)

Good luck!

If you are in production mode, I'd suggest to get you back on line as quick as possible on the shared system since you know that was working...

it seems logical (at least to me) that you should be able to have them help you restore the old system prior to the move, then while your old system is functional, help you get the new VPS system (in parallel). When it the VPS system is stable, schedule the cutover of data, then shut off the shared system.

If they are unwilling to do that...at least for me, I'd bring up a VPS system with another provider and bring the system online with the other provider, when fully tested, migrate the data, update my DNS record and let them know that their inflexibility was the reason why they lost your business and cofidence in them. Another provider may even be eager to win your business over by giving you a hand, especially since your traffic is expected to increase and their is a chance of you further expanding your infrastructure.

Not sure who your provider is, but go with one that is willing to partner with you and can provide you with a service level agreement to ensure they are putting their money on the line.

Sometimes, you'll find some of the smaller providers out there have better customer service and support for their infrastructure and customer sites...

JorgeM, while I agree with you, basically what he is saying is that he has a PHP file (which he listed above, although not pertinent) that pulls files from a file system and outputs them to the browser. When the PHP file tries to load a file from before the migration, it is unable to do so, but loading files after the migration works fine. That means that the Linux Apache user is unable to read the older files but can read the newer files just fine: Either an issue with the older and newer files being in different locations or have their permissions set differently.

If I had to guess, the root user migrated over all of the old files without chown'ing them to the Apache user, and the Apache user owns all of the new files.

That being said, this is sysadmin 101 and for your hosting company to say they migrated everything for you and are now stumped why it doesn't work means that they are incompetent.

That being said, this is sysadmin 101 and for your hosting company to say they migrated everything for you and are now stumped why it doesn't work means that they are incompetent.

Yes, I'm sure you are on target with the problem at hand. I absolutely believe that based on their response as described by techman41973, incompetence is the real issue here. If they cant fix this, what can you expect for more complex problems.

As you know, every minute that site is down, there is a potential loss for revenue and confidence in techman41973's product.

It would be great if you could let us know if that worked ...

Sorry for the delay, I've been overhelmed with other priorities and I finally found some time to thoroughly investigate. Although I'm going back to the shared server, I still like to resolve my issues, in case I stick with my current host and need to migrate back to a VPS from shared. My host provider refuses to help me any more with this issue.

Dani was right. Images are stored in files in the relative directory named /forum/files
On the shared server, the owner/group is listed as (mydomain, mydomain)on the VPS, the owner is listed as (www-data,www-data) .
I'm certain this is the issue.

So... How do I resolve this.
It seems logistical that I should just change the ownership of all the older files owned by (mydomain, mydomain) to (www-data,www-data)
Is there a linux command that would make it easy to change the ownership of all files in a directory? I can't find a way to change the ownership for the bulk of the files in filezilla (my ftp client).

Thank you to all who have provided support. Again I'm sorry for the delay in getting back to you all

found the linux command. chown -R owner:group /var/www/forum/files
can't try it though until my host gives me ssh priveledges on my VPS.

I would never rent a VPS without ssh.

confirmed. Problem solved.
Simply executed Chown command
chown -R www-data:www-data /var/www/forum/files

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.