Handling FTP exceptions like no internet etc











up vote
1
down vote

favorite












I'm currently working in a project where the user needs to log in and after that i will check if the directory /cloud/user/Projects exists and if it doesn't i will create them.



The code works, however i would like to know if there is any better way of handleing exceptions,errors or if the internet is down while doing one of the steps.



I don't think that using try-catch blocks for each FTPCommand is the best way of doing it but i cannot find information about it.(I'm using FluentFTP library).



Also i'm using await and asynchronous methods because i do not want to freeze the UI (WPF).



  var ftp = StoryManager.MainWindow.FtpClient;

ContentGrid.Opacity = 0;
LoadingIndicator.Opacity = 1;

if (UsernameTextBox.Text.Equals("") || PasswordTextBox.Password.ToString().Equals(""))
{

MessageBox.Show("Please, enter your credentials");
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
return;
}


if ((Properties.Settings.Default.LoggedUser = await Rest.LoginAsync(UsernameTextBox.Text.ToLower(), PasswordTextBox.Password.ToString())) != null)
{
Properties.Settings.Default.KeepLogged = (bool)KeepLogged.IsChecked;
Properties.Settings.Default.Save();
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.Reload();
string userDir = "/cloud/" + Properties.Settings.Default.LoggedUser.UserName;

try
{
bool userDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir);
bool projectsDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir + "/Projects");
bool fileExist = StoryManager.MainWindow.FtpClient.FileExists("log.txt");

if (userDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}

if (!projectsDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}
}

else
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

if (!fileExist)
{
var tempPath = Path.GetTempPath();
var textFile = "##### Log File #####";
textFile.AddLine(DateTime.Now.ToString());
File.WriteAllText(tempPath + "log.txt", textFile);
await StoryManager.MainWindow.FtpClient.UploadFileAsync(tempPath + "log.txt", "log.txt");
File.Delete(tempPath + "log.txt");
}

StoryManager.Add(new WelcomeScreen());
}


catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

else
{
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
}
}


Any tips/recommendations for better security, performance and error handleing for this method or for FTP management in general?



Edit 1



The Rest.LoginAsync method implementation is



  public static async Task<User> LoginAsync(string usernameValue, string passwordValue)
{

try
{
var result = await "https://foo.com/bar"
.PostUrlEncodedAsync(new
{
username = usernameValue,
password = passwordValue
}).ReceiveString();

var fields = result.Split(';');

switch (result)
{
case "-1":
MessageBox.Show("User/Password error");
break;
case "-2":
MessageBox.Show("User/Password error");
break;
case "-3":
MessageBox.Show("No License");
break;
case "-4":
MessageBox.Show("Connection error");
break;
default:
break;
}

User loggedUser = new User
{
IdUser = int.Parse(fields[0]),
UserName = fields[1],
MembershipStatus = fields[2],
Name = fields[3]
};

return loggedUser;

}
catch (Exception ex)

{
Console.WriteLine(ex.ToString());
}

return null;

}


The rest of the operations are from C#, WPF or FluentFTP (CreateDirectory, UploadFile...)










share|improve this question
















bumped to the homepage by Community 9 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.











  • 2




    It'd be better if you posted the complete method, not just a snippet.
    – t3chb0t
    Feb 21 at 9:36










  • I updated my post with the other method code, however, i do not know how the FTP library is implemented or how C# or WPF implement there methods...Do you need anything else?
    – ODB8
    Feb 21 at 10:35

















up vote
1
down vote

favorite












I'm currently working in a project where the user needs to log in and after that i will check if the directory /cloud/user/Projects exists and if it doesn't i will create them.



The code works, however i would like to know if there is any better way of handleing exceptions,errors or if the internet is down while doing one of the steps.



I don't think that using try-catch blocks for each FTPCommand is the best way of doing it but i cannot find information about it.(I'm using FluentFTP library).



Also i'm using await and asynchronous methods because i do not want to freeze the UI (WPF).



  var ftp = StoryManager.MainWindow.FtpClient;

ContentGrid.Opacity = 0;
LoadingIndicator.Opacity = 1;

if (UsernameTextBox.Text.Equals("") || PasswordTextBox.Password.ToString().Equals(""))
{

MessageBox.Show("Please, enter your credentials");
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
return;
}


if ((Properties.Settings.Default.LoggedUser = await Rest.LoginAsync(UsernameTextBox.Text.ToLower(), PasswordTextBox.Password.ToString())) != null)
{
Properties.Settings.Default.KeepLogged = (bool)KeepLogged.IsChecked;
Properties.Settings.Default.Save();
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.Reload();
string userDir = "/cloud/" + Properties.Settings.Default.LoggedUser.UserName;

try
{
bool userDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir);
bool projectsDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir + "/Projects");
bool fileExist = StoryManager.MainWindow.FtpClient.FileExists("log.txt");

if (userDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}

if (!projectsDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}
}

else
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

if (!fileExist)
{
var tempPath = Path.GetTempPath();
var textFile = "##### Log File #####";
textFile.AddLine(DateTime.Now.ToString());
File.WriteAllText(tempPath + "log.txt", textFile);
await StoryManager.MainWindow.FtpClient.UploadFileAsync(tempPath + "log.txt", "log.txt");
File.Delete(tempPath + "log.txt");
}

StoryManager.Add(new WelcomeScreen());
}


catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

else
{
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
}
}


Any tips/recommendations for better security, performance and error handleing for this method or for FTP management in general?



Edit 1



The Rest.LoginAsync method implementation is



  public static async Task<User> LoginAsync(string usernameValue, string passwordValue)
{

try
{
var result = await "https://foo.com/bar"
.PostUrlEncodedAsync(new
{
username = usernameValue,
password = passwordValue
}).ReceiveString();

var fields = result.Split(';');

switch (result)
{
case "-1":
MessageBox.Show("User/Password error");
break;
case "-2":
MessageBox.Show("User/Password error");
break;
case "-3":
MessageBox.Show("No License");
break;
case "-4":
MessageBox.Show("Connection error");
break;
default:
break;
}

User loggedUser = new User
{
IdUser = int.Parse(fields[0]),
UserName = fields[1],
MembershipStatus = fields[2],
Name = fields[3]
};

return loggedUser;

}
catch (Exception ex)

{
Console.WriteLine(ex.ToString());
}

return null;

}


The rest of the operations are from C#, WPF or FluentFTP (CreateDirectory, UploadFile...)










share|improve this question
















bumped to the homepage by Community 9 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.











  • 2




    It'd be better if you posted the complete method, not just a snippet.
    – t3chb0t
    Feb 21 at 9:36










  • I updated my post with the other method code, however, i do not know how the FTP library is implemented or how C# or WPF implement there methods...Do you need anything else?
    – ODB8
    Feb 21 at 10:35















up vote
1
down vote

favorite









up vote
1
down vote

favorite











I'm currently working in a project where the user needs to log in and after that i will check if the directory /cloud/user/Projects exists and if it doesn't i will create them.



The code works, however i would like to know if there is any better way of handleing exceptions,errors or if the internet is down while doing one of the steps.



I don't think that using try-catch blocks for each FTPCommand is the best way of doing it but i cannot find information about it.(I'm using FluentFTP library).



Also i'm using await and asynchronous methods because i do not want to freeze the UI (WPF).



  var ftp = StoryManager.MainWindow.FtpClient;

ContentGrid.Opacity = 0;
LoadingIndicator.Opacity = 1;

if (UsernameTextBox.Text.Equals("") || PasswordTextBox.Password.ToString().Equals(""))
{

MessageBox.Show("Please, enter your credentials");
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
return;
}


if ((Properties.Settings.Default.LoggedUser = await Rest.LoginAsync(UsernameTextBox.Text.ToLower(), PasswordTextBox.Password.ToString())) != null)
{
Properties.Settings.Default.KeepLogged = (bool)KeepLogged.IsChecked;
Properties.Settings.Default.Save();
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.Reload();
string userDir = "/cloud/" + Properties.Settings.Default.LoggedUser.UserName;

try
{
bool userDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir);
bool projectsDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir + "/Projects");
bool fileExist = StoryManager.MainWindow.FtpClient.FileExists("log.txt");

if (userDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}

if (!projectsDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}
}

else
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

if (!fileExist)
{
var tempPath = Path.GetTempPath();
var textFile = "##### Log File #####";
textFile.AddLine(DateTime.Now.ToString());
File.WriteAllText(tempPath + "log.txt", textFile);
await StoryManager.MainWindow.FtpClient.UploadFileAsync(tempPath + "log.txt", "log.txt");
File.Delete(tempPath + "log.txt");
}

StoryManager.Add(new WelcomeScreen());
}


catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

else
{
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
}
}


Any tips/recommendations for better security, performance and error handleing for this method or for FTP management in general?



Edit 1



The Rest.LoginAsync method implementation is



  public static async Task<User> LoginAsync(string usernameValue, string passwordValue)
{

try
{
var result = await "https://foo.com/bar"
.PostUrlEncodedAsync(new
{
username = usernameValue,
password = passwordValue
}).ReceiveString();

var fields = result.Split(';');

switch (result)
{
case "-1":
MessageBox.Show("User/Password error");
break;
case "-2":
MessageBox.Show("User/Password error");
break;
case "-3":
MessageBox.Show("No License");
break;
case "-4":
MessageBox.Show("Connection error");
break;
default:
break;
}

User loggedUser = new User
{
IdUser = int.Parse(fields[0]),
UserName = fields[1],
MembershipStatus = fields[2],
Name = fields[3]
};

return loggedUser;

}
catch (Exception ex)

{
Console.WriteLine(ex.ToString());
}

return null;

}


The rest of the operations are from C#, WPF or FluentFTP (CreateDirectory, UploadFile...)










share|improve this question















I'm currently working in a project where the user needs to log in and after that i will check if the directory /cloud/user/Projects exists and if it doesn't i will create them.



The code works, however i would like to know if there is any better way of handleing exceptions,errors or if the internet is down while doing one of the steps.



I don't think that using try-catch blocks for each FTPCommand is the best way of doing it but i cannot find information about it.(I'm using FluentFTP library).



Also i'm using await and asynchronous methods because i do not want to freeze the UI (WPF).



  var ftp = StoryManager.MainWindow.FtpClient;

ContentGrid.Opacity = 0;
LoadingIndicator.Opacity = 1;

if (UsernameTextBox.Text.Equals("") || PasswordTextBox.Password.ToString().Equals(""))
{

MessageBox.Show("Please, enter your credentials");
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
return;
}


if ((Properties.Settings.Default.LoggedUser = await Rest.LoginAsync(UsernameTextBox.Text.ToLower(), PasswordTextBox.Password.ToString())) != null)
{
Properties.Settings.Default.KeepLogged = (bool)KeepLogged.IsChecked;
Properties.Settings.Default.Save();
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.Reload();
string userDir = "/cloud/" + Properties.Settings.Default.LoggedUser.UserName;

try
{
bool userDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir);
bool projectsDirExist = StoryManager.MainWindow.FtpClient.DirectoryExists(userDir + "/Projects");
bool fileExist = StoryManager.MainWindow.FtpClient.FileExists("log.txt");

if (userDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}

if (!projectsDirExist)
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}
}

else
{
try
{
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.SetWorkingDirectoryAsync(userDir);
await StoryManager.MainWindow.FtpClient.CreateDirectoryAsync(userDir + "/Projects");
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

if (!fileExist)
{
var tempPath = Path.GetTempPath();
var textFile = "##### Log File #####";
textFile.AddLine(DateTime.Now.ToString());
File.WriteAllText(tempPath + "log.txt", textFile);
await StoryManager.MainWindow.FtpClient.UploadFileAsync(tempPath + "log.txt", "log.txt");
File.Delete(tempPath + "log.txt");
}

StoryManager.Add(new WelcomeScreen());
}


catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show("An error ocurred please try again " + ex.Message);
}
}

else
{
ContentGrid.Opacity = 1;
LoadingIndicator.Opacity = 0;
}
}


Any tips/recommendations for better security, performance and error handleing for this method or for FTP management in general?



Edit 1



The Rest.LoginAsync method implementation is



  public static async Task<User> LoginAsync(string usernameValue, string passwordValue)
{

try
{
var result = await "https://foo.com/bar"
.PostUrlEncodedAsync(new
{
username = usernameValue,
password = passwordValue
}).ReceiveString();

var fields = result.Split(';');

switch (result)
{
case "-1":
MessageBox.Show("User/Password error");
break;
case "-2":
MessageBox.Show("User/Password error");
break;
case "-3":
MessageBox.Show("No License");
break;
case "-4":
MessageBox.Show("Connection error");
break;
default:
break;
}

User loggedUser = new User
{
IdUser = int.Parse(fields[0]),
UserName = fields[1],
MembershipStatus = fields[2],
Name = fields[3]
};

return loggedUser;

}
catch (Exception ex)

{
Console.WriteLine(ex.ToString());
}

return null;

}


The rest of the operations are from C#, WPF or FluentFTP (CreateDirectory, UploadFile...)







c# security error-handling wpf ftp






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 21 at 10:34

























asked Feb 21 at 9:24









ODB8

112




112





bumped to the homepage by Community 9 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.







bumped to the homepage by Community 9 hours ago


This question has answers that may be good or bad; the system has marked it active so that they can be reviewed.










  • 2




    It'd be better if you posted the complete method, not just a snippet.
    – t3chb0t
    Feb 21 at 9:36










  • I updated my post with the other method code, however, i do not know how the FTP library is implemented or how C# or WPF implement there methods...Do you need anything else?
    – ODB8
    Feb 21 at 10:35
















  • 2




    It'd be better if you posted the complete method, not just a snippet.
    – t3chb0t
    Feb 21 at 9:36










  • I updated my post with the other method code, however, i do not know how the FTP library is implemented or how C# or WPF implement there methods...Do you need anything else?
    – ODB8
    Feb 21 at 10:35










2




2




It'd be better if you posted the complete method, not just a snippet.
– t3chb0t
Feb 21 at 9:36




It'd be better if you posted the complete method, not just a snippet.
– t3chb0t
Feb 21 at 9:36












I updated my post with the other method code, however, i do not know how the FTP library is implemented or how C# or WPF implement there methods...Do you need anything else?
– ODB8
Feb 21 at 10:35






I updated my post with the other method code, however, i do not know how the FTP library is implemented or how C# or WPF implement there methods...Do you need anything else?
– ODB8
Feb 21 at 10:35












1 Answer
1






active

oldest

votes

















up vote
0
down vote














  • I would add a variable var ftpClient = StoryManager.MainWindow.FtpClient; to shorten the calls to FtpClient a bit

  • You catch exceptions several times, but handle them equally. And also continue after an error. I would make a single try..catch block around everything. So the exception handling code is not duplicated and the following actions don't get executed. (Why try to add a project dir to user dir project dir does not exist yet?)






share|improve this answer





















    Your Answer





    StackExchange.ifUsing("editor", function () {
    return StackExchange.using("mathjaxEditing", function () {
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    });
    });
    }, "mathjax-editing");

    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "196"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














     

    draft saved


    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188006%2fhandling-ftp-exceptions-like-no-internet-etc%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote














    • I would add a variable var ftpClient = StoryManager.MainWindow.FtpClient; to shorten the calls to FtpClient a bit

    • You catch exceptions several times, but handle them equally. And also continue after an error. I would make a single try..catch block around everything. So the exception handling code is not duplicated and the following actions don't get executed. (Why try to add a project dir to user dir project dir does not exist yet?)






    share|improve this answer

























      up vote
      0
      down vote














      • I would add a variable var ftpClient = StoryManager.MainWindow.FtpClient; to shorten the calls to FtpClient a bit

      • You catch exceptions several times, but handle them equally. And also continue after an error. I would make a single try..catch block around everything. So the exception handling code is not duplicated and the following actions don't get executed. (Why try to add a project dir to user dir project dir does not exist yet?)






      share|improve this answer























        up vote
        0
        down vote










        up vote
        0
        down vote










        • I would add a variable var ftpClient = StoryManager.MainWindow.FtpClient; to shorten the calls to FtpClient a bit

        • You catch exceptions several times, but handle them equally. And also continue after an error. I would make a single try..catch block around everything. So the exception handling code is not duplicated and the following actions don't get executed. (Why try to add a project dir to user dir project dir does not exist yet?)






        share|improve this answer













        • I would add a variable var ftpClient = StoryManager.MainWindow.FtpClient; to shorten the calls to FtpClient a bit

        • You catch exceptions several times, but handle them equally. And also continue after an error. I would make a single try..catch block around everything. So the exception handling code is not duplicated and the following actions don't get executed. (Why try to add a project dir to user dir project dir does not exist yet?)







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Feb 25 at 17:01









        Markus Meyer

        211




        211






























             

            draft saved


            draft discarded



















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f188006%2fhandling-ftp-exceptions-like-no-internet-etc%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Costa Masnaga

            Fotorealismo

            Sidney Franklin