NODE SECURITY PDF

adminComment(0)

bestthing.info community, and recently he joined the Node Security Project as an Did you know that Packt offers eBook versions of every book published, with PDF. bestthing.info SECURITY. DONE RIGHT. Tips and Tricks. They Won't Teach. You in School. Liran Tal. R&D Team Lead for a Full-Stack Technology. If you want to learn how to secure your bestthing.info apps, there's no way around Karl .org/LDP/solrhe/Securing-Optimizing-Linux-The-Ultimate-Solution-vpdf.


Node Security Pdf

Author:GARNET SHEFTALL
Language:English, Indonesian, Japanese
Country:Estonia
Genre:Academic & Education
Pages:352
Published (Last):20.04.2015
ISBN:275-4-56104-356-8
ePub File Size:22.84 MB
PDF File Size:9.37 MB
Distribution:Free* [*Sign up for free]
Downloads:22581
Uploaded by: HANH

Slightly richer man's usage of. SSL. ○ One shared certificate used for server role. ○ Individual certificates used for client role. ○ Only master candidate. A very simple wrapper for qpdf which is a content-preserving transformations on PDF files. It includes encrypting and decrypting PDF with AES. bestthing.info Secure Code GuidelinesOWASP Essential Security Risks and CountermeasuresExpressJS bestthing.info and npm secure dependencies.

With so many web-apps using images these days, Image Magick is often being used in the background for things like cropping and resizing. To use this tool with Node, you might see code like this:. This may look harmless, but with a carefully crafted imageFilename , you can execute any code you want in the shell.

Even better, check npm for a library that wraps the command line tool. These are usually built with this kind of security in mind, or at least have more eyes on the code to check for problems. For Image Magick, there are a few modules available, like gm.

Many vulnerabilities in web applications apply to all services, regardless of programming language and framework used. Although, how you attack those services may differ based on the technology stack you're using.

To better defend yourself, you really need to learn how these exploits work. Review these and then do a thorough analysis of your website to see if any of these apply to you. Even better, check out NodeGoat , which is a deployable website created by OWASP meant to teach you how to identify these risks in Node applications specifically. There is no better way to learn these concepts than actually doing it yourself. The tutorial provided will walk you through all of the risks, showing specific examples of how to both exploit and defend against the vulnerabilities.

Node security is a big topic, so it wouldn't be reasonable to try and cover it all here. If you're interested in getting more details, I'd suggest reading some more resources, like these:.

All too often the security of an application is an after-thought to development and design. It's difficult enough just to get your code to work correctly, let alone making it safe to use for your users. Luckily you're not the only one going through these problems, so that means there are plenty of tools and resources out there created by others to help you secure your apps quickly and easily. Just take the time to search NPM, ask questions on forums, or even hire an expert.

It's definitely worth the time and money! Get occassional tutorials, guides, and reviews in your inbox. No spam ever. Unsubscribe at any time. Subscribe to our newsletter!

Welcome to freeCodeCamp News.

Toggle navigation Stack Abuse. Securing Your Node. Don't Run Code with Sudo This happens way more than you think, and it's dangerous. Avoid eval at all Costs Okay, I'll admit it, at times it can be tempting to make your code more dynamic by letting it execute arbitrary JavaScript using eval , but believe me, this is a bad idea.

After all, the V8 JavaScript engine is really good at parsing things like simple math operations, so it would be tempting to use that to your advantage: Here is a simple example of the exploit: Use Scanning Utilities like Retire. To use this tool with Node, you might see code like this: Understand the Vulnerabilities Many vulnerabilities in web applications apply to all services, regardless of programming language and framework used.

More Info Node security is a big topic, so it wouldn't be reasonable to try and cover it all here. If you're interested in getting more details, I'd suggest reading some more resources, like these: Node Security Advisories Analysis of Node.

What other ways do you secure your Node applications? Let us know in the comments! About Scott Robinson. Subscribe to our Newsletter Get occassional tutorials, guides, and reviews in your inbox. Previous Post: Learn Node.

Follow Us Twitter. Development dependencies are intended as development-only packages, that are unneeded in production. For example testing packages, webpack or Babel. When you go in production , if you type npm install and the folder contains a package. You need to set the --production flag npm install --production to avoid installing those development dependencies. There is another great feature of npm , which is allowing to run commands without first installing them.

A typical demonstration of using npx is through the cowsay command. For example:. Use the to specify the version, and combine that with the node npm package:. You can run code that sits in a GitHub gist, for example:. Of course, you need to be careful when running code that you do not control, as with great power comes great responsibility.

The Event Loop is one of the most important aspects to understand about JavaScript. This section explains the inner details of how JavaScript works with a single thread, and how it handles asynchronous functions. You just need to pay attention to how you write your code and avoid anything that could block the thread, like synchronous network calls or infinite loops.

Generally, in most browsers there is an event loop for every browser tab, to make every process isolated and avoid a web page with infinite loops or heavy processing to block your entire browser.

The environment manages multiple concurrent event loops, to handle API calls for example. Web Workers run in their own event loop as well. You mainly need to be concerned that your code will run on a single event loop, and write code with this thing in mind to avoid blocking it. Any JavaScript code that takes too long to return back control to the event loop will block the execution of any JavaScript code in the page — even block the UI thread — and the user cannot click around, scroll the page, and so on.

Network requests, Node. While doing so, it adds any function call it finds to the call stack and executes each one in order. You know the error stack trace you might be familiar with, in the debugger or in the browser console?

The browser looks up the function names in the call stack to inform you which function originates the current call:. When this code runs, first foo is called. Inside foo we first call bar , then we call baz. JavaScript finds things to execute, runs them in order. Inside foo we first call setTimeout , passing bar as an argument, and we instruct it to run immediately as fast as it can, passing 0 as the timer. Then we call baz. When setTimeout is called, the Browser or Node.

Once the timer expires, in this case immediately as we put 0 as the timeout, the callback function is put in the Message Queue.

Fill out the form below

The Message Queue is also where user-initiated events like click and keyboard events or fetch responses are queued before your code has the opportunity to react to them. Or also DOM events like onLoad. The loop gives priority to the call stack.

Promises that resolve before the current function ends will be executed right after the current function. I find nice the analogy of a rollercoaster ride at an amusement park: As you try to understand the Node. It interacts with the event loop in a special way. When we pass a function to process. When this operation ends, the JavaScript engine runs all the functions passed to nextTick calls during that operation.

Use nextTick when you want to make sure that in the next event loop iteration that code is already executed. When you want to execute some piece of code asynchronously, but as soon as possible, one option is to use the setImmediate function provided by Node.

A function passed to process. This means it will always execute before setTimeout and setImmediate.

Subscribe to RSS

A setTimeout callback with a 0ms delay is very similar to setImmediate. The execution order will depend on various factors, but they will be both run in the next iteration of the event loop.

When writing JavaScript code, you might want to delay the execution of a function. Learn how to use setTimeout and setInterval to schedule functions in the future. This is the job of setTimeout. You can specify a callback function to execute later, and a value expressing how much later you want it to run, in milliseconds:. This syntax defines a new function. You can call whatever other function you want in there, or you can pass an existing function name, and a set of parameters:.

This is generally not used, but you can store this id, and clear it if you want to delete this scheduled function execution:. If you specify the timeout delay to 0 , the callback function will be executed as soon as possible, but after the current function execution:.

This is especially useful to avoid blocking the CPU on intensive tasks and let other functions be executed while performing a heavy calculation, by queuing functions in the scheduler. Instead of running the callback function once, it will run it forever, at the specific time interval you specify in milliseconds:. The function above runs every 2 seconds unless you tell it to stop, using clearInterval , passing it the interval id that setInterval returned:. For example this code runs something unless App.

To avoid this, you can schedule a recursive setTimeout to be called when the callback function finishes:. JavaScript is synchronous by default, and is single threaded. This means that code cannot create new threads and run in parallel.

In the current consumer computers, every program runs for a specific time slot, and then it stops its execution to let another program continue its execution.

When a program is waiting for a response from the network, it cannot halt the processor until the request finishes. Normally, programming languages are synchronous, and some provide a way to manage asynchronicity, in the language or through libraries. Some of them handle asynchronicity by using threads, spawning a new process.

JavaScript is synchronous by default and is single threaded. But JavaScript was born inside the browser. Its main job, in the beginning, was to respond to user actions like onClick , onMouseOver , onChange , onSubmit and so on. How could it do this with a synchronous programming model? The answer was in its environment.

The browser provides a way to do it by providing a set of APIs that can handle this kind of functionality. More recently, Node. We can do this because JavaScript has first-class functions, which can be assigned to variables and passed around to other functions called higher-order functions. XHR requests also accept a callback, in this example by assigning a function to a property that will be called when a particular event occurs in this case, the state of the request changes:.

How do you handle errors with callbacks?

Download now

One very common strategy is to use what Node. If there is no error, the object is null. If there is an error, it contains some description of the error and other information.

However, every callback adds a level of nesting. When you have lots of callbacks, the code starts to be complicated very quickly:. Starting with ES6, JavaScript introduced several features that help us with asynchronous code that do not involve using callbacks:. Promises are one way to deal with asynchronous code in JavaScript, without writing too many callbacks in your code. A promise is commonly defined as a proxy for a value that will eventually become available.

Although being around for years, they have been standardized and introduced in ES, and now they have been superseded in ES by async functions. Once a promise has been called, it will start in pending state. This means that the caller function continues the execution, while it waits for the promise to do its own processing, and give the caller function some feedback. At this point, the caller function waits for it to either return the promise in a resolved state , or in a rejected state , but as you know JavaScript is asynchronous — so the function continues its execution while the promise does it work.

In addition to your own code and libraries code, promises are used by standard modern Web APIs such as:. Using resolve and reject we can communicate back a value, in the above case we just return a string, but it could be an object as well. Running checkIfItsDone will execute the isItDoneYet promise and will wait for it to resolve, using the then callback, and if there is an error, it will handle it in the catch callback.

The Fetch API is a promise-based mechanism, and calling fetch is equivalent to defining our own promise using new Promise. In this example, we call fetch to get a list of TODO items from the todos.

Running fetch returns a response , which has many properties, and within those we reference:. So given those premises, this is what happens: This operation will cause the promise chain to skip all the chained promises listed and will skip directly to the catch statement at the bottom, logging the Request failed text along with the error message.

If that succeeds instead, it calls the json function we defined. Since the previous promise, when successful, returned the response object, we get it as an input to the second promise. In the example, in the previous section, we had a catch that was appended to the chain of promises.

When anything in the chain of promises fails and raises an error or rejects the promise, the control goes to the nearest catch statement down the chain. If inside the catch you raise an error, you can append a second catch to handle it, and so on. If you need to synchronize different promises, Promise.

The ES destructuring assignment syntax allows you to also do:. You are not limited to using fetch of course, any promise is good to go. If you get the Uncaught TypeError: Async functions are a combination of promises and generators, and basically, they are a higher level abstraction over promises. Let me repeat: When Promises were introduced in ES, they were meant to solve a problem with asynchronous code, and they did, but over the 2 years that separated ES and ES, it was clear that promises could not be the final solution.

Promises were introduced to solve the famous callback hell problem, but they introduced complexity on their own, and syntax complexity. They were good primitives around which a better syntax could be exposed to the developers, so when the time was right we got async functions.

When you want to call this function you prepend await , and the calling code will stop until the promise is resolved or rejected. One caveat: Prepending the async keyword to any function means that the function will return a promise. As you can see in the example above, our code looks very simple. Compare it to code using plain promises, with chaining and callback functions.

And this is a very simple example, the major benefits will arise when the code is much more complex. If you worked with JavaScript in the browser, you know how much of the interaction of the user is handled through events: On the back-end side, Node.

You can pass arguments to the event handler by passing them as additional arguments to emit:. If you ever did an interview, you might have been asked: People just want to see if you can explain some rather basic concepts and if you have any clue how the internet actually works.

This is tech that is very rarely changed, and powers one the most complex and wide ecosystems ever built by humans. If you just entered a domain, like flaviocopes. The domain name is a handy shortcut for us humans, but the internet is organized in such a way that computers can look up the exact location of a server through its IP address, which is a set of numbers like If this does not give any information about the domain, the system makes a request to the DNS server.

They sit at the same conceptual level, but TCP is connection-oriented, while UDP is a connectionless protocol, more lightweight, used to send messages with little overhead. It not, it will ask the root DNS server. The DNS server does not know the address of each and every domain name on the planet. A top-level domain is the domain extension: Say you are looking for flaviocopes. When you download a domain, the domain registrar sends the appropriate TDL the name servers.

When you update the name servers for example, when you change the hosting provider , this information will be automatically updated by your domain registrar. Those are the DNS servers of the hosting provider. They are usually more than 1, to serve as backup. The DNS resolver starts with the first, and tries to ask the IP of the domain with the subdomain, too you are looking for. A TCP connection requires a bit of handshaking before it can be fully initialized and you can start sending data.

The request is a plain text document structured in a precise way determined by the communication protocol. There are 2 mandatory fields, one of which is Host , and the other is Connection , while all the other fields are optional:. Host indicates the domain name which we want to target, while Connection is always set to close unless the connection must be kept open.

The response starts with the status code and the status message. If the request is successful and returns a , it will start with:. The browser now has received the HTML and starts to parse it, and will repeat the exact same process we did not for all the resources required by the page:.

We include the http module. The server is set to listen on the specified port, When the server is ready, the listen callback function is called. Through it, we access the request headers and request data. This Node. Once established, the channel is kept open, offering a very fast connection with low latency and overhead. Listen for it by assigning a callback function to the onopen property of the connection object:. Listen with a callback function on onmessage , which is called when the message event is received:.

It can also be used to implement a client, and use WebSockets to communicate between two backend services. This code creates a new server on port the default port for WebSockets , and adds a callback function when a connection is established, sending ho! Here is a live example of a WebSockets server. Here is a WebSockets client that interacts with the server. You can also open the file by using the fs.

Once you get the file descriptor, in whatever way you choose, you can perform all the operations that require it, like calling fs. You call it passing a file path, and once Node. The file information is included in the stats variable. What kind of information can we extract using the stats? You need to pay attention when using paths in your applications, as this difference must be taken into account. You can get the file name without the extension by specifying a second argument to basename:.

In this case Node. If you specify a second parameter folder, resolve will use the first as a base for the second:. But resolve and normalize will not check if the path exists. They just calculate a path based on the information they got. The simplest way to read a file in Node. The default encoding is u tf8 , but you can specify a custom encoding using a a second parameter.

Both fs. This means that big files are going to have a major impact on your memory consumption and speed of execution of the program. By default, this API will replace the contents of the file if it does already exist. You can find more about flags. A handy method to append content to the end of a file is fs. All those methods write the full content to the file before returning the control back to your program in the async version, this means executing the callback. Use fs. This piece of code reads the content of a folder, both files and subfolders, and returns their relative path:.

The fs module provides a lot of very useful functionality to access and interact with the file system.

There is no need to install it. Being part of the Node. One peculiar thing about the fs module is that all the methods are asynchronous by default, but they can also work synchronously by appending Sync. Node 10 includes experimental support for a promise based API. The asynchronous API is used with a callback:. The key difference here is that the execution of your script will block in the second example, until the file operation succeeded. The path module provides a lot of very useful functionality to access and interact with the file system.

This module provides path. Tries to calculate the actual path when it contains relative specifiers like. Accepts 2 paths as arguments. Returns the the relative path from the first path to the second, based on the current working directory. By specifying a second parameter, resolve will use the first as a base for the second:. This module provides many functions that you can use to retrieve information from the underlying operating system and the computer the program runs on, and interact with it.

EOL gives the line delimiter sequence. For simplicity I exclude other less popular operating systems Node can run on. You can read them all here. Return the string that identifies the underlying architecture, like arm , x64 , arm The events module provides us the EventEmitter class, which is key to working with events in Node. I published a full article on that, so here I will just describe the API without further examples on how to use it.

Get the maximum amount of listeners one can add to an EventListener object, which defaults to 10 but can be increased or lowered by using setMaxListeners:. This callback is only going to be called once, never again. When you add a listener using on or addListener , it's added last in the queue of listeners, and called last. Using prependListener it's added, and called, before other listeners. When you add a listener using once , it's added last in the queue of listeners, and called last.

Using prependOnceListener it's added, and called, before other listeners. Remove a specific listener. You can do this by saving the callback function to a variable, when added, so you can reference it later:.

Sets the maximum amount of listeners one can add to an EventListener object, which defaults to 10 but can be increased or lowered:. The http module of Node. It is a key module to Node. Points to the global instance of the Agent object, which is an instance of the http.

Agent class. Makes an HTTP request to a server, creating an instance of the http. ClientRequest class.

Similar to http. Node creates a global instance of the http. This object makes sure that every request made to a server is queued and a single socket is reused. An http. ClientRequest object is created when http. When a response is received, the response event is called with the response, with an http. IncomingMessage instance as argument.

This class is commonly instantiated and returned when creating a new server using http. Created by an http. Server and passed as the second parameter to the request event it fires. It must be called on each response. After processing the headers you can send them to the client by calling response.

To send data to the client in the response body, you use write. It will send buffered data to the HTTP response stream. If the headers were not sent yet using response. The data is accessed using streams, since http.

IncomingMessage implements the Readable Stream interface. Streams are not a concept unique to Node. They were introduced in the Unix operating system decades ago, and programs can interact with each other passing streams through the pipe operator. For example, in the traditional way, when you tell the program to read a file, the file is read into memory, from start to finish, and then you process it.

Using streams you read it piece by piece, processing its content without keeping it all in memory. Using the Node. If the file is big, the operation will take quite a bit of time. Here is the same thing written using streams:. Instead of waiting until the file is fully read, we start streaming it to the HTTP client as soon as we have a chunk of data ready to be sent. The above example uses the line stream.

You call it on the source stream, so in this case, the file stream is piped to the HTTP response. The return value of the pipe method is the destination stream, which is a very convenient thing that lets us chain multiple pipe calls, like this:.

Due to their advantages, many Node. We get the Readable stream from the stream module, and we initialize it:. Now you are ready to perform an SQL query on the database. The query once executed will invoke a callback function which contains an eventual error, the results and the fields:. When you need to terminate the connection to the database you can call the end method:.

You can signal Node. You can also apply the environment variable by prepending it to your application initialization command:. Express views are compiled in every request in development mode, while in production they are cached.

There are many more examples. I hope this introduction to Node. Learn Forum News. Welcome to freeCodeCamp News. This is a free, open source, no-ads place to cross-post your blog articles. Read about it here. Flavio Copes Read more posts by this author. Image credits: Unsplash Note: Table of Contents Introduction to Node.

How to use or execute a package installed using npm The package. Overview Node. It has a huge number of libraries With its simple structure, the node package manager npm helped the ecosystem of Node. A sample Node. These 2 objects are essential to handle the HTTP call. The second is used to return data to the caller. In this case with: We set the Content-Type header: Here is a non-comprehensive list to the ones I consider very relevant and worth learning: Express One of the most simple yet powerful ways to create a web server.

Its minimalist approach and unopinionated focus on the core features of a server is key to its success. Meteor An incredibly powerful full-stack framework, empowering you with an isomorphic approach to building apps with JavaScript and sharing code on the client and the server. Once an off-the-shelf tool that provided everything, it now integrates with front-end libraries such as React , Vue and Angular. Meteor can be used to create mobile apps as well. Koa Built by the same team behind Express, Koa aims to be even simpler and smaller, building on top of years of knowledge.

The new project was born out of the need to create incompatible changes without disrupting the existing community. A brief history of Node. A little bit of history JavaScript is a programming language that was created at Netscape as a scripting tool to manipulate web pages inside their browser, Netscape Navigator. Ghost Koa is born Big drama: Node 6 npm focuses more on security: It is also very useful to test your code with old Node.

How much JavaScript do you need to know to use Node. If you are just starting out with JavaScript, how deeply do you need to know the language? Differences between Node. Both the browser and Node use JavaScript as their programming language.

What changes is the ecosystem. Compilation JavaScript is generally considered an interpreted language, but modern JavaScript engines no longer just interpret JavaScript, they compile it. How to exit from a Node. If this is fine for you, you can pass an integer that signals the operating system the exit code: You can also set the process.

A program will gracefully exit when all the processing is done. Many times with Node. You can send this signal from inside the program, in another function: How to read environment variables from Node.

In the same way you can access any custom environment variable you set. Where to host a Node. I will list the options from simplest and constrained to more complex and powerful. Simplest option ever: Zero configuration deployments Glitch Glitch is a playground and a way to build your apps faster than ever, and see them live on their own glitch. I use it a lot for demo purposes.

Codepen Codepen is an amazing platform and community. Serverless A way to publish your apps, and have no server at all to manage, is Serverless. To very popular solutions are: Zeit Now Zeit is an interesting option. Nanobox Nanobox Heroku Heroku is an amazing platform. Microsoft Azure Azure is the Microsoft Cloud offering. Google Cloud Platform Google Cloud is an amazing structure for your apps. Virtual Private Server In this section you find the usual suspects, ordered from more user friendly to less user friendly: Bare metal Another solution is to get a bare metal server , install a Linux distribution, connect it to the internet or rent one monthly, like you can do using the Vultr Bare Metal service How to use the Node.

The node command is the one we use to run our Node. Start simple and enter: We can now enter a new line of JavaScript. The REPL will print all the properties and methods you can access on that class: Explore global objects You can inspect the globals you have access to by typing global.

They are. Once you are in this mode, enter ctrl-D to run the code you wrote. Same as pressing ctrl-C. For example if you start typing an iteration like this: For example: The way you retrieve it is using the process object built into Node.

The first argument is the full path of the node command. The second element is the full path of the file being executed. All the additional arguments are present from the third position going forward. You can iterate over all the arguments including the node path and the file path using a loop: The best way to do so is by using the minimist library , which helps dealing with arguments: It is basically the same as the console object you find in the browser.

If you pass an object, it will render it as a string. You can pass multiple variables to console. We can also format pretty phrases by passing variables and a format specifier. Take this code: You can just count apples and oranges: Trace at function2 repl: It will not appear in the console, but it will appear in the error log.

Color the output You can color the output of your text in the console by using escape sequences. You install it with npm install chalk , then you can use it: Check the project link I posted above for more usage examples. Create a progress bar Progress is an awesome package to create a progress bar in the console.

When the bar completes we clear the interval: In this callback function, we close the readline interface. You can install it using npm install inquirer , and then you can replicate the above code like this: Expose functionality from a Node.

When you want to import something you use: In this file, functionality must be exposed before it can be imported by other files. You can do so in 2 ways. This way allows you to export multiple objects, functions or data: Introduction to npm npm means node package manager. There are many things that npm does. Downloads npm manages downloads of dependencies of your project. Installing all dependencies If a project has a packages.

Updating packages Updating is also made easy, by running npm update npm will check all packages for a newer version that satisfies your versioning constraints. You can specify a single package to update as well: Or a bug in the latest release of a lib, still unfixed, is causing an issue. Running Tasks The package.

When you install a package using npm or yarn , you can perform 2 types of installation: A global installation is performed using the -g flag: Where, exactly? The npm root -g command will tell you where that exact location is on your machine. To use it in your code, you just need to import it into your program using require: There is a hidden. How do you execute those? You just run: This is another package. Properties breakdown This section describes the properties you can use in detail.

There are other popular services baked in: When you install a package using npm or yarn: Command-specific properties The package. Package versions You have seen in the description above version numbers like these: That symbol specifies which updates you package accepts, from that dependency.

Given that using semver semantic versioning all versions have 3 digits, the first being the major release, the second the minor release and the third is the patch release, you have these rules: In version 5, npm introduced the package-lock. An example This is an example structure of a package-lock.

Find the installed version of an npm package To see the latest version of all the npm package installed, including their dependencies: You can install an old version of an npm package using the syntax: Install version 1.

To discover new releases of the packages, you run npm outdated. To update to a new major version all the packages, install the npm-check-updates package globally: You are now ready to run the update: The Semantic Versioning concept is simple: Why is that so important? The rules use those symbols: There are other rules, too: And why?

The main difference between local and global packages is this: In general, all packages should be installed locally. Great examples of popular global packages which you might know are: You can see them by running:After all, the V8 JavaScript engine is really good at parsing things like simple math operations, so it would be tempting to use that to your advantage:. The more information they have about your technology stack, the more ways they'll be able to attack it.

The first is to use Browserify , which is a Node module packager for the browser with the familiar require syntax. Receiving Security Updates Security notifications will be distributed via the following methods.

The following diagram shows an example message flow and gives an overview of the sequence of events that occur when an input message is received by an input node that is not security enabled or that has no associated security profile and is later processed by a SecurityPEP node in the message flow: The following steps explain the sequence of events that occur when a message arrives at an input node that is not security enabled or that has no associated security profile.

With so many web-apps using images these days, Image Magick is often being used in the background for things like cropping and resizing. There are just too many ways this can come back to bite you.

DESPINA from Vancouver
I enjoy exploring ePub and PDF books jubilantly. See my other posts. I have a variety of hobbies, like bank pool.
>