Flackser On Mac Os Web App

Appked is the Apple macOS and Mac OS X Apps & Games download site. Download Free Mac Apps and Mac Games for Apple Mac. Recovery Developer Tools File Management Finance Finder FTP Games Graphics & Design Image Editing Instagram Internet iPhone Keygen Mac App Store Markdown MAS Menubar Monitor Multimedia & Design Music Network. Download Slack for free for mobile devices and desktop. Keep up with the conversation with our apps for iOS, Android, Mac, Windows and Linux. Aug 28, 2018  Web Applications: A web application or dynamic website generates content based on retrieved data (most of the time is a database) that changes based on a user’s interaction with the site. In a web application, the server is responsible for querying, retrieving, and updating data. Remove a folder from the Flickr Uploadr for Mac If you want to stop automatically uploading photos from a folder, you can remove the folder as a source.&nb.

This means that from time-to-time, when browsing the web on your Mac, you will see alerts that there is a 'Missing Plug-In', or requests that you install the Flash Player. Your App for Movies and TV Shows. I ALSO RUN ON MAC 😉 You can easily install FreeFlix HQ on your MacBook or iMac and this is how it will look. The messages show The installation was successfully done. But, there is the ApplicationLoader app that doesn't appear anywhere. How to install and get the Applicationloader app in Application-Utility folder? I'm using Mac OSX version 10.6.8.

by Salvador Villalon

Introduction

In each section, I will show pieces of code for you to follow along. All the code used in the tutorial is available in this GitHub Repository.

What is HTTP and What Does it Have to do with Flask?

HTTP is the protocol for websites. The internet uses it to interact and communicate with computers and servers. Let me give you an example of how you use it everyday.

When you type the name of a website in the address bar of your browser and you hit enter. What happens is that an HTTP request has been sent to a server.

For example, when I go to my address bar and type google.com, then hit enter, an HTTP request is sent to a Google Server. The Google Server receives the request and needs to figure how to interpret that request. The Google Server sends back an HTTP response that contains the information that my web browser receives. Then it displays what you asked for on a page in the browser.

How is Flask involved?

We will write code that will take care of the server side processing. Our code will receive requests. It will figure out what those requests are dealing with and what they are asking. It will also figure out what response to send to the user.

To do all this we will use Flask.

What is Flask?

It makes the process of designing a web application simpler. Flask lets us focuson what the users are requesting and what sort of response to give back.

Learn more about micro frameworks.

How Does a Flask App Work?

The code lets us run a basic web application that we can serve, as if it were a website.

This piece of code is stored in our main.py.

Line 1: Here we are importing the Flask module and creating a Flask web server from the Flask module.

Line 3: __name__ means this current file. In this case, it will be main.py. This current file will represent my web application.

We are creating an instance of the Flask class and calling it app. Here we are creating a new web application.

Line 5: It represents the default page. For example, if I go to a website such as “google.com/” with nothing after the slash. Then this will be the default page of Google.

Line 6–7: When the user goes to my website and they go to the default page (nothing after the slash), then the function below will get activated.

Line 9: When you run your Python script, Python assigns the name “__main__” to the script when executed.

If we import another script, the if statement will prevent other scripts from running. When we run main.py, it will change its name to __main__ and only then will that if statement activate.

Line 10: This will run the application. Having debug=True allows possible Python errors to appear on the web page. This will help us trace the errors.

Let’s Try Running main.py

In your Terminal or Command Prompt go to the folder that contains your main.py.Then do py main.py or python main.py. In your terminal or command prompt you should see this output.

The important part is where it says Running on http://127.0.0.1:5000/.

127.0.0.1 means this local computer. If you do not know the meaning of this (like I didn’t when I started — this article is really helpful), the main idea is that 127.0.0.1 and localhost refer to this local computer.

Go to that address and you should see the following:

More Fun with Flask

Flicker On Mac Os Web App Download

Earlier you saw what happened when we ran main.py with one route which was app.route(“/”).

Let’s add more routes so you can see the difference.

In lines 9–11. we added a new route, this time to /salvador.

Now run the main.py again and go tohttp://localhost:5000/salvador.

So far we have been returning text. Let’s make our website look nicer by adding HTML and CSS.

HTML, CSS, and Virtual Environments

HTML and Templates in Flask

First create a new HTML file. I called mine home.html.

Here is some code to get you started.

Important Point To Remember

The Flask Framework looks for HTML files in a folder called templates. You need to create a templates folder and put all your HTML files in there.

Now we need to change our main.py so that we can view the HTML file we created.

Line 1: We imported render_template() method from the flask framework. render_template() looks for a template (HTML file) in the templates folder. Then it will render the template for which you ask. Learn more about render_templates() function.

Line 7: We change the return so that now it returns render_template(“home.html”). This will let us view our HTML file.

Now visit your localhost and see the changes: http://localhost:5000/.

Let’s add more pages

Let’s create an about.html inside the templates folder.

Let’s make a change similar to what we did before to our main.py.

We made three new changes:

Line 9: Change the route to'/about'.

Line 10: Change the function so it is nowdef about():

Line 11: Change the return so that now it returns render_template('about.html').

Now see the changes: http://localhost:5000/about.

Let’s Connect Both Pages with a Navigation

To connect both pages we can have a navigation menu on the top. We can use Flask to make the process of creating a navigation menu easier.

First, let’s create a template.html. This template.html will serve as a parent template. Our two child templates will inherit code from it.

Line 13–14: We use the function calledurl_for(). It accepts the name of the function as an argument. Right now we gave it the name of the function. More information on url_for() function.

The two lines with the curly brackets will be replaced by the content of home.html and about.html. This willdepend on the URL in which the user is browsing.

These changes allow the child pages (home.html and about.html) to connect to the parent (template.html). This allows us to not have to copy the code for the navigation menu in the about.html and home.html.

Content of about.html:

Content of home.html:

Let’s try adding some CSS.

Adding CSS to Our Website

An important note to remember

In the same way as we created a folder called templates to store all our HTML templates, we need a folder called static.

In static, we will store our CSS, JavaScript, images, and other necessary files. That is why it is important that you should create a CSSfolder to store your stylesheets. After you do this, your project folder should look like this:

Linking our CSS with our HTML file

Our template.html is the one that links all pages. We can insert the code here and it will be applicable to all child pages.

Line 7: Here we are giving the path to where the template.css is located.

Flackser On Mac Os Web App

Now see the changes: http://localhost:5000/about.

Moving Forward with Flask and virtualenv

Now that you are familiar with using Flask, you may start using it in your future projects. One thing to always do is use virtualenv.

Why use virtualenv?

You may use Python for others projects besides web-development.

Your projects might have different versions of Python installed, different dependencies and packages.

We use virtualenv to create an isolated environment for your Python project. This means that each project can have its own dependencies regardless of what dependencies every other project has.

Getting started with virtualenv

First, run this command on your command prompt or terminal:

Second, do the following:

Here you can give a name to the environment. I usually give it a name of virtual. It will look like this: virtualenv virtual.

After setting up virtual environment, check your project folder. It should look like this. The virtual environment needs to be created in the same directory where your app files are located.

Activating the virtual environment

Now go to your terminal or command prompt. Go to the directory that contains the file called activate. The file called activate is found inside a folder called Scripts for Windows and bin for OS X and Linux.

For OS X and Linux Environment:

For Windows Environment:

Since I am using a Windows machine, when I activate the environment it will look like this:

The next step is to install flask on your virtual environment so that we can run the application inside our environment. Run the command:

Run your application and go to http://localhost:5000/

We finally made our web application. Now we want to show the whole world our project.

(More information on virtualenv can be found in the following guides on virtualenv and Flask Official Documentation)

Let’s send it to the Cloud

To show others the project we made, we will need to learn how to use Cloud Services.

Deploy Your Web Application to the Cloud

To deploy our web application to the cloud, we will use Google App Engine (Standard Environment). This is an example of a Platform as a Service (PaaS).

PaaS refers to the delivery of operating systems and associated services over the internet without downloads or installation. The approach lets customers create and deploy applications without having to invest in the underlying infrastructure (More info on PaaS check out TechTarget).

Google App Engine is a platform as a service offering that allows developers and businesses to build and run applications using Google’s advanced infrastructure — TechOpedia.

Before you Start:

You will need a Google Account. Once you create an account, go to the Google Cloud Platform Console and create a new project. Also, you need to install the Google Cloud SDK.

At the end of this tutorial your project structure will look like this.

We will need to create three new files: app.yaml, appengine_config.py, and requirements.txt.

Content of app.yaml:

If you were to check Google’s Tutorial in the part where they talk about content of the app.yaml, it does not include the section where I wrote about libraries.

When I first attempted to deploy my simple web app, my deployment never worked. After many attempts, I learned that we needed to include the SSL library.

The SSL Library allows us to create secure connections between the client and server. Every time the user goes to our website they will need to connect to a server run by Google App Engine. We need to create a secure connection for this. (I recently learned this, so if you have a suggestions for this let me know!)

Content of appengine_config.py:

Content of requirements.txt:

Now inside our virtual environment (make sure your virtualenv is activated),we are going to install the new dependencies we have in requirements.txt. Run this command:

-t lib: This flag copies the libraries into a lib folder, which uploads to App Engine during deployment.

-r requirements.txt: Tells pip to install everything from requirements.txt.

Deploying the Application

To deploy the application to Google App Engine, use this command.

I usually include — project [ID of Project]

This specifies what project you are deploying. The command will look like this:

The Application

Now check the URL of your application. The application will be store in the following way:

My application is here: http://sal-flask-tutorial.appspot.com

Conclusion

From this tutorial, you all learned how to:

  • Use the framework called Flask to use Python as a Server Side Language.
  • Learned how to use HTML, CSS, and Flask to make a website.
  • Learned how to create Virtual Environments using virtualenv.
  • Use Google App Engine Standard Environment to deploy an application to the cloud.

What I learned

I learned three important things from this small project.

First, I learned about the difference between a static website and a web application

Static Websites:

  • Means that the server is serving HTML, CSS, and JavaScript files to the client. The content of the site does not change when the user interacts with it.

Web Applications:

  • A web application or dynamic website generates content based on retrieved data (most of the time is a database) that changes based on a user’s interaction with the site. In a web application, the server is responsible for querying, retrieving, and updating data. This causes web applications to be slower and more difficult to deploy than static websites for simple applications (Reddit).

Server Side and Client Side:

  • I learned that a web application has two sides. The client side and the server side. The client side is what the user interacts with and the server side is where the all the information that the user inputted is processed.

Second, I learned about Cloud Services

Most of my previous projects were static websites, and to deploy them I used GitHub Pages. GitHub Pages is a free static site hosting service designed to host projects from a GitHub Repository.

When working with web applications, I could not use GitHub Pages to host them. GitHub Pages is only meant for static websites not for something dynamic like a web application that requires a server and a database. I had to use Cloud Services such as Amazon Web Services or Heroku

Third, I learned how to use Python as a Server Side Language

To create the server side of the web application we had to use a server side language. I learned that I could use the framework called Flask to use Python as the Server Side Language.

Next Steps:

You can build all sorts of things with Flask. I realized that Flask helps make the code behind the website easier to read. I have made the following applications during this summer of 2018 and I hope to make more.

Personal Projects

During my internship

Here is the list of resources that helped me create this tutorial:

  • “App Engine — Build Scalable Web & Mobile Backends in Any Language | App Engine | Google Cloud.” Google, Google, cloud.google.com/appengine/.
  • “Building a Website with Python Flask.” PythonHow, pythonhow.com/building-a-website-with-python-flask/.
  • “Flask — Lecture 2 — CS50’s Web Programming with Python and JavaScript.” YouTube, 6 Feb. 2018, youtu.be/j5wysXqaIV8.
  • “Getting Started with Flask on App Engine Standard Environment | App Engine Standard Environment for Python | Google Cloud.” Google, Google, cloud.google.com/appengine/docs/standard/python/getting-started/python-standard-env.
  • “Installation.” Welcome | Flask (A Python Microframework), flask.pocoo.org/docs/0.12/installation/.
  • “Python — Deploying Static Flask Sites for Free on Github Pages.” Reddit, www.reddit.com/r/Python/comments/1iewqt/deploying_static_flask_sites_for_free_on_github/.
  • Real Python. “Python Virtual Environments: A Primer — Real Python.” Real Python, Real Python, 7 Aug. 2018, realpython.com/python-virtual-environments-a-primer/.
  • “What Is Cloud Services? — Definition from WhatIs.com.” SearchITChannel, searchitchannel.techtarget.com/definition/cloud-services.
  • “What Is Google App Engine (GAE)? — Definition from Techopedia.” Techopedia.com, www.techopedia.com/definition/31267/google-app-engine-gae.

If you have any suggestions or questions, feel free to leave a comment.

2017-06-03T18:41:15Z

Posted by Miguel Grinberg under Python, Flask, Security.

While you work on your Flask application, you normally run the development web server, which provides a basic, yet functional WSGI complaint HTTP server. But eventually you will want to deploy your application for production use, and at that time, one of the many things you will need to decide is if you should require clients to use encrypted connections for added security.

People ask me all the time about this, in particular how to expose a Flask server on HTTPS. In this article I'm going to present several options for adding encryption to a Flask application, going from an extremely simple one that you can implement in just five seconds, to a robust solution that should give you an A+ rating like my site gets from this exhaustive SSL analysis service.

Flicker On Mac Os Web Apps

How Does HTTPS Work?

The encryption and security functionality for HTTP is implemented through the Transport Layer Security (TLS) protocol. Basically put, TLS defines a standard way to make any network communication channel secure. Since I'm not a security expert, I don't think I can do a great job if I try to give you a detailed description of the TLS protocol, so I will just give you some of the details that are of interest for our purpose of setting up a secure and encrypted Flask server.

The general idea is that when the client establishes a connection with the server and requests an encrypted connection, the server responds with its SSL Certificate. The certificate acts as identification for the server, as it includes the server name and domain. To ensure that the information provided by the server is correct, the certificate is cryptographically signed by a certificate authority, or CA. If the client knows and trusts the CA, it can confirm that the certificate signature indeed comes from this entity, and with this the client can be certain that the server it connected to is legitimate.

After the client verifies the certificate, it creates an encryption key to use for the communication with the server. To make sure that this key is sent securely to the server, it encrypts it using a public key that is included with the server certificate. The server is in possession of the private key that goes with that public key in the certificate, so it is the only party that is able to decrypt the package. From the point when the server receives the encryption key all traffic is encrypted with this key that only the client and server know.

From this summary you can probably guess that to implement TLS encryption we need two items: a server certificate, which includes a public key and is signed by a CA, and a private key that goes with the public key included in the certificate.

The Simplest Way To Do It

Flask, and more specifically Werkzeug, support the use of on-the-fly certificates, which are useful to quickly serve an application over HTTPS without having to mess with certificates. All you need to do, is add ssl_context='adhoc' to your app.run() call. As an example, below you can see the 'Hello, World' Flask application from the official documentation, with TLS encryption added:

This option is also available through the Flask CLI if you are using a Flask 1.x release:

To use ad hoc certificates with Flask, you need to install an additional dependency in your virtual environment:

When you run the script (or start with flask run if you prefer), you will notice that Flask indicates that it is running an https:// server:

Simple, right? The problem is that browsers do not like this type of certificate, so they show a big and scary warning that you need to dismiss before you can access the application. Once you allow the browser to connect, you will have an encrypted connection, just like what you get from a server with a valid certificate, which make these ad hoc certificates convenient for quick & dirty tests, but not for any real use.

Self-Signed Certificates

A so called self-signed certificate is one where the signature is generated using the private key that is associated with that same certificate. I mentioned above that the client needs to 'know and trust' the CA that signed a certificate, because that trust relationship is what allows the client to validate a server certificate. Web browsers and other HTTP clients come pre-configured with a list of known and trusted CAs, but obviously if you use a self-signed certificate the CA is not going to be known and validation will fail. That is exactly what happened with the ad hoc certificate we used in the previous section. If the web browser is unable to validate a server certificate, it will let you proceed and visit the site in question, but it will make sure you understand that you are doing it at your own risk.

But what is the risk, really? With the Flask server from the previous section you obviously trust yourself, so there is no risk to you. The problem is when users are presented with this warning when connecting to a site they do not directly know or control. In those cases, it is impossible for the user to know if the server is authentic or not, because anyone can generate certificates for any domain, as you will see below.

While self-signed certificates can be useful sometimes, the ad hoc certificates from Flask are not that great, because each time the server runs, a different certificate is generated on the fly through pyOpenSSL. When you are working with a self-signed certificate, it is better to have the same certificate used every time you launch your server, because that allows you to configure your browser to trust it, and that eliminates the security warnings.

You can generate self-signed certificates easily from the command line. All you need is to have openssl installed:

This command writes a new certificate in cert.pem with its corresponding private key in key.pem, with a validity period of 365 days. When you run this command, you will be asked a few questions. Below you can see in red how I answered them to generate a certificate for localhost:

We can now use this new self-signed certificate in our Flask application by setting the ssl_context argument in app.run() to a tuple with the filenames of the certificate and private key files:

Alternatively, you can add the --cert and --key options to the flask run command if you are using Flask 1.x or newer:

The browser will continue to complain about this certificate, but if you inspect it, you will see the information that you entered when you created it:

Using Production Web Servers

Of course we all know that the Flask development server is only good for development and testing. So how do we install an SSL certificate on a production server?

If you are using gunicorn, you can do this with command line arguments:

If you use nginx as a reverse proxy, then you can configure the certificate with nginx, and then nginx can 'terminate' the encrypted connection, meaning that it will accept encrypted connections from the outside, but then use regular unencrypted connections to talk to your Flask backend. This is a very useful set up, as it frees your application from having to deal with certificates and encryption. The configuration items for nginx are as follows:

Another important item you need to consider is how are clients that connect through regular HTTP going to be handled. The best solution, in my opinion, is to respond to unencrypted requests with a redirect to the same URL but on HTTPS. For a Flask application, you can achieve that using the Flask-SSLify extension. With nginx, you can include another server block in your configuration:

If you are using a different web server, check their documentation and you will likely find similar ways to create the configurations shown above.

Using 'Real' Certificates

We have now explored all the options we have for self-signed certificates, but in all those cases, the limitation remains that web browsers are not going to trust those certificates unless you tell them to, so the best option for server certificates for a production site is to obtain them from one of these CAs that are well known and automatically trusted by all the web browsers.

When you request a certificate from a CA, this entity is going to verify that you are in control of your server and domain, but how this verification is done depends on the CA. If the server passes this verification then the CA will issue a certificate for it with its own signature and give it to you to install. The certificate is going to be good for a period of time that is usually not longer than a year. Most CAs charge money for these certificates, but there are a couple that offer them for free. The most popular free CA is called Let's Encrypt.

Getting a certificate from Let's Encrypt is fairly easy, since the whole process is automated. Assuming you are using an Ubuntu based server, you have to begin by installing their open source certbot tool on your server:

And now you are ready to request the certificate using this utility. There are a few ways that certbot uses to verify your site. The 'webroot' method is, in general, the easiest to implement. With this method, certbot adds some files in a directory that your web server exposes as static files, and then tries to access these files over HTTP, using the domain you are trying to generate a certificate for. If this test is successful, certbot knows that the server in which it is running it is associated with the correct domain, and with that it is satisfied and issues the certificate. The command to request a certificate with this method is as follows:

In this example, we are trying to generate a certificate for a example.com domain, which uses the directory in /var/www/example as a static file root. Unfortunately a Flask based website does not have a static file root directory, all static files from the application are accessed with the /static prefix, at least when you use the default configuration, so more planning is necessary.

What certbot does to the static root directory is add a .well-known subdirectory, and then store some files in it. Then it uses a HTTP client to retrieve those files as http://example.com/.well-known/.... If it can retrieve the files, then that is confirmation that your server is in full control of the domain name. For Flask and other applications that don't have a static file root directory, it is necessary to define one.

If you are using nginx as reverse proxy, you can take advantage of the powerful mappings that you can create in the configuration to give certbot a private directory where it can write its verification files. In the following example, I extended the HTTP server block shown in the previous section to send all Let's Encrypt related requests (which always begin with /.well-known/...) to a specific directory of your choice:

Then you can give this director to certbot:

If certbot is able to verify the domain, it will write the certificate file as /etc/letsencrypt/live/example.com/fullchain.pem and the private key as /etc/letsencrypt/live/example.com/privkey.pem, and these are going to be valid for a period of 90 days.

To use this newly acquired certificate, you can enter the two filenames mentioned above in place of the self-signed files we used before, and this should work with any of the configurations described above. And of course you will also need to make your application available through the domain name that you registered, as that is the only way the browser will accept the certificate as valid.

Certbot is also used when you need to renew the certificates. To do that, you simply issue the following command:

If there are any certificates in your system that are close to expire, the above command renews them, leaving new certificates in the same locations. You will likely need to restart your web server if you want the renewed certificates to be picked up.

Flicker On Mac Os Web Application

Achieving an SSL A+ Grade

If you use a certificate from Let's Encrypt or another known CA for your production site and you are running a recent and maintained operating system on this server, you are likely very close to have a top-rated server in terms of SSL security. You can head over to the Qualys SSL Labs site and get a report to see where you stand.

Chances are you will still have some minor things to do. The report will indicate what areas you need to improve, but in general, I expect you'll be told that the options the server exposes for the encrypted communication are too wide, or too weak, leaving you open to known vulnerabilities.

One of the areas in which it is easy to make an improvement is in how the coefficients that are used during the encryption key exchange are generated, which usually have defaults that are fairly weak. In particular, the Diffie-Hellman coefficients take a considerable amount of time to be generated, so servers by default use smaller numbers to save time. But we can pre-generate strong coefficients and store them in a file, which then nginx can use. Using the openssl tool, you can run the following command:

You can change the 2048 above for a 4096 if you want even stronger coefficients. This command is going to take some time to run, specially if your server does not have a lot of CPU power, but when it's done, you will have a dhparam.pem file with strong coefficients that you can plug into the ssl server block in nginx:

Next, you will probably need to configure which ciphers the server allows for the encrypted communication. This is the list that I have on my server:

In this list, disabled ciphers are prefixed with a !. The SSL report will tell you if there are any ciphers that are not recommended. You will have to check from time to time to find out if new vulnerabilities have been discovered that require modifications to this list.

Below you can find my current nginx SSL configuration, which includes the above settings, plus a few more that I added to address warnings from the SSL report:

You can see the results that I obtained for my site at the top of this article. If you are after 100% marks in all categories, you will have to add additional restrictions to your configuration, but this is going to limit the number of clients that can connect to your site. In general, older browsers and HTTP clients use ciphers that are not considered to be the strongest, but if you disable those, then these clients will not be able to connect. So you will basically need to compromise, and also routinely review the security reports and make updates as things change over time.

Unfortunately for the level of sophistication on these last SSL improvements you will need to use a professional grade web server, so if you don't want to go with nginx, you will need to find one that supports these settings, and the list is pretty small. I know Apache does, but besides that, I don't know any other.

Conclusion

So there you go, this is how you can implement top-of-the-line SSL security for your Flask application. Is there anything that I left out? Do you do things differently? Let me know below in the comments!

Hello, and thank you for visiting my blog! If you enjoyed this article, please consider supporting my work on this blog on Patreon!

74 comments

  • #1Ezequiel said 2017-06-05T14:53:45Z

  • #2netchose said 2017-06-05T18:37:06Z

  • #3Joe Labi said 2017-06-09T13:57:27Z

  • #4Benjamin said 2017-06-09T21:22:52Z

  • #5Miguel Grinberg said 2017-06-10T16:19:25Z

  • #6Florian said 2017-06-29T14:15:52Z

  • #7Miguel Grinberg said 2017-06-29T16:30:59Z

  • #8mz said 2017-08-11T04:56:26Z

  • #9Rob Mathers said 2017-10-05T17:20:14Z

  • #10cmb said 2017-10-06T05:56:18Z

  • #11zhihong Pei said 2017-11-25T13:56:31Z

  • #12Miguel Grinberg said 2017-11-25T18:08:41Z

  • #13Doron said 2018-03-04T11:53:53Z

  • #14Vipin Reyaroth said 2018-04-13T01:58:36Z

  • #15igor said 2018-05-10T13:17:24Z

  • #16Miguel Grinberg said 2018-05-13T03:16:43Z

  • #17faceless stranger said 2018-07-01T23:08:47Z

  • #18Olav Vahtras said 2018-08-16T06:04:20Z

  • #19Miguel Grinberg said 2018-08-16T07:56:15Z

  • #20Doaa Altarawy said 2018-09-13T18:30:33Z

  • #21Miguel Grinberg said 2018-09-13T22:37:29Z

  • #22Vladyslav said 2018-10-30T14:53:14Z

  • #23Aleksandr Mikheev said 2018-11-03T18:08:56Z

  • #24Alexis ROLLAND said 2018-12-01T10:38:55Z

  • #25Miguel Grinberg said 2018-12-02T09:01:37Z

Leave a Comment