Category Archives: Guide

Setting a Windows Desktop Background in Rust

While working on wallers, I came across the need to set the desktop background for Windows machines. For Linux machines, the answer was simple: delegate to feh. For Windows, I needed to delegate to a Windows API call.

The Windows API call of interest is SystemParametersInfo, specifically with the action as SPI_SETDESKWALLPAPER (20 in decimal). For SPI_SETDESKWALLPAPER specifically, the second and fourth parameters are not used, so they can be set to 0. Thus, in order to change the desktop wallpaper, one would call

SystemParametersInfo(20, 0, "path/to/wallpaper.png", 0)

In particular, this function is found in user32.dll. Luckily, retep998 has created a Rust binding for it and it is available as a crate. With this knowledge, changing the desktop wallpaper becomes quite trivial. The only complication is that there are two forms of SystemParametersInfo : SystemParametersInfoA and SystemParametersInfoW. From what I’ve gathered, the former should be called on 32 bit systems while the latter is called on 64 bit systems. This works on my desktop machine; however, on my 64bit Surface Book, SystemParametersInfoW sets the wallpaper to black while SystemParametersInfoA works as intended.

The final bit of difficulty comes in that these functions accept a *mut c_void as a parameter rather than a string (making the function unsafe.. sad). Thus, conversion must also take place.

extern crate user32;

use std::ffi::CString;
use std::os::raw::c_void;

fn set_wallpaper(path: String, force_32bit: bool) -> Result<(), ()> {
 let wallpaper_func = if force_32bit || cfg!(target_pointer_width = "32") {
        user32::SystemParametersInfoA
    }
    else {
        user32::SystemParametersInfoW
    };

    // do work to get the pointer of our owned string
    let path_ptr = CString::new(path).unwrap();
    let path_ptr_c = path_ptr.into_raw();
    let result = unsafe {
        match path_ptr_c.is_null() {
            false => wallpaper_func(20, 0, path_ptr_c as *mut c_void, 0),
            true => 0
        }
    };

    // rust documentation says we must return the pointer this way
    unsafe {
        CString::from_raw(path_ptr_c)
    };

    match result {
        0 => Err( () )
        _ => Ok( () )
    }
}

As you notice, we also insert a way for the user to call SystemParamtersInfoA on a 64bit system, just in-case…. Of course, since this uses OS-specific libraries, it’s best to use macros to prevent this code from running on non-Windows machines.

#[cfg(windows)] extern crate user32;

#[cfg(windows)] use std::ffi::CString;
#[cfg(windows)] use std::os::raw::c_void;
#[cfg(not(windows))] use std::process::Command;

#[cfg(windows)]
fn set_wallpaper(path: String, force_32bit: bool) -> Result<(), ()> {
 let wallpaper_func = if force_32bit || cfg!(target_pointer_width = "32") {
        user32::SystemParametersInfoA
    }
    else {
        user32::SystemParametersInfoW
    };

    // do work to get the pointer of our owned string
    let path_ptr = CString::new(path).unwrap();
    let path_ptr_c = path_ptr.into_raw();
    let result = unsafe {
        match path_ptr_c.is_null() {
            false => wallpaper_func(20, 0, path_ptr_c as *mut c_void, 0),
            true => 0
        }
    };

    // rust documentation says we must return the pointer this way
    unsafe {
        CString::from_raw(path_ptr_c)
    };

    match result {
        0 => Err( () )
        _ => Ok( () )
    }
}

#[cfg(not(windows))]
fn set_wallpaper(path: String, _: bool) -> Result<(), ()> {
let result = Command::new("feh")
        .arg("--bg-fill")
        .arg(path)
        .status()?.success();

    match result {
        true => Ok( () ),
        false => Err( () )
    }
}

 

Simple RPC With Thrift

A key aspect of building a server-based (cloud-based in today’s lingo) service is communication. The (often times remote) client needs to communicate with the server. Further, sometimes other processes on the server also need to communicate with each other. There are several ways to accomplish this, one of which is with RPC.

Many blooming programmers and hackathoners today will jump straight to “Why not just create a simple REST API using JSON serialization?”. On the surface, there are many good things about this. I’m sure you’ve heard them all:

  1. REST is simple and stateless. The semantics of a REST API are widely used and therefore easy to use once you’ve learned them. With a REST API on your server, it’s super easy to manipulate data and debug operations using tools like Postman.
  2. REST encourages readability. I’m all about readability everywhere in computing. Code should be readable, text should be readable, interfaces should be readable. It only makes sense, then, that an API should be readable as well. REST encourages this. It’s very easy to tell what GET api/users will do.
  3. REST encourages readable serializations. Since the API endpoints are readable, it’s only natural to make the response readable as well. Today, most APIs accomplish this by serialiazing data in the easy-to-read JSON format. This way, data is easy to read and easy to manipulate.

This is all well and good. Hackathoners and newcomers should not feel discouraged from using REST/JSON to create an interface to their cloud application. There’s one problem that I’m sure you’ve noticed, however.

JSON is heavy. When you’ve implemented a distributed, load-balanced, fully cached, and 100% optimized service, the largest bottleneck is transmission time from the server to the client, especially if the response object is large. In fact, on all of the teams I’ve worked on at various companies (except one), complaints about transmission time for huge serialized objects were extremely common.

Also, REST is cumbersome. I need more than two hands to count how many times I’ve coded up, from scratch, an interface layer that handles REST-style requests and serves the response in JSON. At one point I thought it a good idea to create a C# tool which actually generates a PHP REST interface when given the dataschema. Why did I have to do this? Surely, someone else has already done it!

Enter Facebook’s Thrift, which is open source and Apache licensed. For me, Thrift’s biggest features are how it solves the problems I’ve mentioned above. In order to use Thrift, you design a schema to represent both your objects and your service. The Thrift compiler then uses your schema to generate a client and server for you, meaning that you no longer have to handle the communication or serialization problems.

As a contrived example, say that I wanted to make a simple service to get my server uptime. I first design a Thrift schema:

service UptimeService {
    i32 getUptimeInDays();
}

Then, I compile the schema using Thrift

thrift --gen py uptime.thrift

I am going to use Python for my client and server, so I use the --gen py flag. Thrift has many supported languages, however.

I can then use the generated Python libraries to write my server implementation:

import UptimeService
import subprocess

from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from thrift.server import TServer

class UptimeHandler:
    def getUptimeInDays():
        return int(subprocess.check_output('uptime').split(' ')[3])

if __name__ == '__main__':
    handler = UptimeHandler()
    processor = UptimeService.Processor(handler)
    transport = TSocket.TServerSocket(port=9090)
    tfactory = TTransport.TBufferedTransportFactory()
    pfactory = TBinaryProtocol.TBinaryProtocolFactory()

    server = TServer.TThreadedServer(processor, transport, tfactory, pfactory)
    server.serve()

And I also use the generated Python libraries to write my client implementation:

import UptimeService

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

def main():
    transport = TSocket.TSocket('localhost', 9090)
    transport = TTransport.TBufferedTransport(transport)
    protocol = TBinaryProtocol.TBinaryProtocol(transport)
    client = UptimeService.Client(protocol)

    transport.open()
    print("Server uptime: {} days".format(client.getUptimeInDays()))
    
    transport.close()

if __name__ == '__main__':
    main()

Of course, this client implementation only works when run from the server itself. If I wanted to get the uptime remotely, I would just change ‘localhost’ to my domain name.

And that’s it! All of the networking details and serialization is handled by Thrift. Of course, a big portion of this post went on about how JSON is too big and too heavy. If one compares performance of various Thrift-like libraries, they will notice that Thrift is definitely not the fastest. Instead, libraries like Avro, Protobuf, and CapnProto are much faster and also more compact.

However, a major pain point for me across the years has been implementing the actual interface layer. Writing client code to summon an HTTP Request and read the response from the server gets old after a while. This is something that Thrift handles for you. As you can see from the example above, Thrift handles all serialization, deserialization, and message-passing for you. All you have to worry about is defining a schema — Thrift gives the rest for free!

Fixing ncurses5 to ncurses6 Dependency Issues on Arch Linux

This post is alternatively titled: “How to resolve error while loading shared libraries: libncursesw.so.5: cannot open shared object file: No such file or directory”.

While attempting to do a recent system update, I ran into two problems:

  1. pacman was not downloading any packages due to an out-of-date gnupg package.
  2. Trying to install the gnupg package manually resulted in the alternative title of this post.

All of this was because I decided to run sudo pacman -S libncurses in order to get my conky working properly. Turns out a lot more programs rely on libncurses than I previously realized.

The problem gave me more of a headache than thought it would, but I eventually solved the issue. Here’s how:

  1. Since I recently upgraded libncurses through pacman from version 5 to version 6, the old version was still saved in the cache in /var/cache/pacman/pkg
  2. I extracted the cached version of libncurses by using sudo mkdir tempNcurses && sudo tar -xvf ncurses-5.9-7-x86_64.pkg.tar.xz -C tempNcurses
  3. I then copied the resulting binary into the libraries folder with sudo cp tempNcurses/libncursesw.so.5.9 /usr/lib
  4. I then made a symbolic link with the file specified in the error messages with sudo ln -s /usr/lib/libncursesw.so.5.9 /usr/lib/libncursesw.so.5

After this, everything worked as expected! I was able to manually update GnuPG and then update everything else that had a dependence on ncurses

Migrating my VPS to Linode and Sentora

Background

If you’ve been following my recent ventures at all, you know that not too long ago I decided to move my virtual private server to DigitalOcean. I also decided to run CentOS7 and use Centos Web Panel (CWP) to allow anyone using my VPS to have a nice graphical interface to manage their services. I have not taken time to formally review either of these services, but I did experience some issues with Centos Web Panel. Some of the key issues I had with the product are:

  • Obfuscated Code. I know that some people like to obfuscate their code in order to make the program uneditable by other parties; however, if I am unable to look at the code of my web-panel to see exactly what it’s doing, I am worried that the web-panel is doing something that it doesn’t want me to see. On top of this, obfuscated code makes it very, very difficult to quickly edit files if I want to make changes.
  • Support is not good. The CWP forums, which should be a central source of information for all who choose to adopt CWP into their own servers, is riddled with posts describing common issues. Almost all of the threads contain an administrator response prompting the original poster to file a ticket. This creates a forum that is essentially useless since no actual problem solving takes place there. On top of this, when an administrator does take the time to answer a question, the answer is usually not completely answering the question. To be fair, for a free product, support is something that doesn’t need to be offered; however, a community-driven forum is important, and CWP is not running theirs properly.
  • Things break. More often than not, users will make changes that unintentionally break things, and these breakages are reported as “random occurrances” by the very users who caused them. Maybe I am just a really poor user; however, during my time with CWP, things would definitely seem to randomly break. People on the forums seemed to agree, too, as all issues that I had were also reported by other users. For instance, after a CWP update, all hosts could no longer navigate to their associated “/roundcube” domains to access webmail. The problem was reported on the forums; however, it was left unanswered.
  • Untemplatable. I don’t only use my VPS to run my web services and applications, I also allow other people to host their websites, services, and applications on my VPS. When they login to their web panel, however, I want them to be reminded that they are using my VPS. Thus, branding the web panel is essential. CWP supported this in no friendly manner. Most web panels have a sort-of template feature, where one is able to define their own template for the web panel to use. However, CWP has no such thing, and even when looking for source images to replace and source files to edit, nothing can be easily found. If something is found, it is obfuscated. Most people would consider this to be a minor issue, however, the default CWP template is slow and unresponsive. The unresponsiveness was probably the straw that broke the camel’s back, so to speak.

With all of these small issues combined, and with a growing favoritism toward Linode’s VPS services, I decided that it was once again, time to make the transition to a new stack of services. This time, I decided to use Linode’s VPS plan, run CentOS7 with the LAMP stack, and finish it off with the free and open source Sentora web panel.

The Process

Preparing the VPS

Setting up the actual VPS with Linode is quite simple. I went with the Linode 4096 plan (Which is the same price as a Digital Ocean plan with less features) and deployed a CentOS7 image onto it. From there, after the machine is booted, the “Remote Access” tab provides all the necessary information to SSH into the machine and install the necessary software.

Installing Sentora

The Sentora installation process is fairly straightforward and fairly well documented. Setup with a fresh new Linode VPS, all of the requirements regarding a minimally installed machine were already met. However, installing Sentora requires a valid subdomain to be pointing towards the server machine. This subdomain will later be used to access the Sentora web panel.

At the time of installing Sentora, I did not have an extra domain lying around to point to the new machine, and knowing very little about DNS and DNS Records, I eventually discovered that what I needed to do was create a new “A” Record that pointed a subdomain of an already existing domain to the new machine. I edited my DNS Zone file to contain a record that looked as such:

www.panel.    1800    IN    A    123.456.789.246

Which mapped the “panel” subdomain to the IP Address (123.456.789.246) of the new machine. After waiting about 15 minutes for this new DNS information to propagate, I was able to ping panel.domain.com and receive responses from the new machine’s IP Address.

Note that at the time, this process was two-fold: Since I was transferring from DigitalOcean, I changed my DNS Zone File on my DigitalOcean host to contain a NS entry that told the DigitalOcean host to “Look for the server that is serving the panel subdomain here”. That entry looked as such:

panel    1800    IN    NS    123.456.789.246

Then, now that the DigitalOcean host knew where to look, the “A” record was added to the Linode host, which basically said “The IP Address for the panel subdomain is this”.

And with that, the pre-installation steps of Sentora are complete. The real installation can begin. As per the documentation, this includes downloading and running a Sentora installation script. The installation script is extremely straightforward and asks only about timezone, hostname (the subdomain that was just declared), and IP Address.

Configuring Sentora

I decided that the best user-architecture for my server would be one that treats every domain as an individual user, even the domains that belonged to myself. Although I could have chosen to attach my domains to the admin account, I wanted to create a separation layer that would allow each website to have its own configuration. On top of this, configuring my websites as “clients” of my website hosting would allow me to better support those who are actually clients of my hosting.

Thus, I added two new reseller packages that would take care of this. The BasicUser package was limited to 10 domains, subdomains, MySQL databases, email accounts, etc, but was given unlimited storage and bandwidth. I figured that 10 was more than enough for the clients of my web hosting. I also created the ElevatedUser pacakge, which had unlimited everything. This, of course, would be for my own domains.

Before moving on to actually creating the users, however, I wanted to customize the Sentora panel so that my brand would be reflected across the panel for my clients. I am a fan of the base Sentora theme, so I decided to basically use that theme, but replace all Sentora images with my own logos. This was done in the following steps:

  1. Copy the “Sentora_Default” folder (The base template) to another folder (Your new template) in /etc/sentora/panel/etc/styles
  2. Replace all images in the img/ folder with your logo
  3. Replace information in /etc/sentora/panel/etc/static/errorpages with your information
  4. Continue searching for things to replace in /etc/sentora/panel/etc

Then, once everything is replaced, the new theme is visible in the Sentora theme manager. Select it and voila!

User Creation and Migration

I created each user’s account using the Sentora admin panel. I would setup a generic username and password for them to use, and before alerting them of their new account information, I would do the following:

  1. Login to the account and create a new domain, which was their domain.
  2. Edit the DNS Records for that domain (The default DNS Records are perfect)
  3. Add a new FTP account (with a generic username and password), set to the root directory for their account.

These three things would allow the user’s information to be transferred from the old server to the new server relatively easily. Transferring users is also a relatively easy process. First, I logged in as the root SFTP account on my old DigitalOcean/CWP configuration and downloaded everyones’ files onto my local machine. This, of course, took some time and allowed me to discover that some of my users were hosting a lot more than I previously thought they were (one user was hosting a 10GB MongoDB Instance). I also was able to go through and delete some of the files that I didn’t think would be used anymore, such as log files, backups from my previous server migration (From HostGator to DigitalOcean), and old files that were not in use anymore.

Once all of the files were downloaded to my local machine, I went ahead and uploaded all of them using the newly created user FTP accounts, being sure to put all of the public_html files into the new public_html directory.

I also logged into phpMyAdmin using the root login credentials. This allowed me to find all MySQL accounts attached to each user. For each user, I logged into the Sentora web panel and created MySQL databases with names matching the old database names. Although this could have been accomplished by simply exporting the tables, exporting the tables would not allow users to see their MySQL databases in their Sentora panel. Thus, creating the database in Sentora would allow the users to see their MySQL databases in the panel. I also created MySQL users for each existing user on the old MySQL servers. Unfortunately, Sentora doesn’t allow users to me named in the same format as my old setup, so I had to change the naming format a bit.

Now that all the databases were created, I could go into the old phpMyAdmin and export all tables using phpMyAdmin’s EXPORT functionality, taking care to make sure that the “CREATE TABLE” statements were included. I saved the .sql files, and then used phpMyAdmin on the new Linode host to import these tables.

WIth all database information transferred succesfully, the final change I made was establishing users’ subdomains. I was able to look through the DNS Zone file on the old DigitalOcean/CWP host and find the subdomains for each user. I then logged into each user’s Sentora panel and created the subdomain using Sentora’s Subdomain functionality. Unfortunately, Sentora’s subdomain functionality only creates a directory for that subdomain, so I also had to edit the DNS Information, adding a CNAME entry for each subdomain that was to be added. The CNAME entry looked like:

subdomain     IN    CNAME    123.456.789.246

 

More Database Migration

The most glaring roadbloack with transferring MySQL databases is that there is no way to actually view the password of a user. Although this is a great security feature, it causes problems when migrating servers becasue one is unable to view the passwords of old users to put them into new users.

The solution to this problem that I chose to use utilized mysqldump. When run from the old VPS host, this tool would dump all the important data pertaining to the old MySQL databases, including users and passwords. The full command looked as such:

mysqldump -u root -p mysql > mysql.sql

After typing in the MySQL root user’s password, this creates a mysql.sql file that can be downloaded and then uploaded to the new host, where it can be restored using

mysql -u root -p mysql < mysql.sql
UPDATE user SET password=PASSWORD('<rootPassword>') WHERE user='root';
FLUSH PRIVILEGES;

This command restores all of the users, their passwords, and their permissions to the server. The only problem with using this command is that, for me at least, it changed some information of important users such as the MySQL Root user, Postfix user, ProFTPd user, and Roundcube user. This was due to the fact that those database users just happened to have the same names as they did on my previous server. So, of course, they were overwritten. Thus, with that being said, the above command also contains a line to keep the root MySQL user password in check.

Luckily, Sentora stores a text file that keeps all of the default MySQL user passwords in /root/passwords.txt. Thus, using this file as reference, I went ahead and updated all of the users passwords accordingly. For example:

mysql -u root -p
UPDATE user SET password=PASSWORD('<MySQL Postfix Password>') WHERE user='postfix';
UPDATE user SET password=PASSWORD('<MySQL ProFTPd Password>') WHERE user='proftpd';
UPDATE user SET password=PASSWORD('<MySQL Roundcube Password>') WHERE user='roundcube';
FLUSH PRIVILEGES;

After these updates, everything on the system was working properly. However, I will admit that it took me a long time to figure out that importing my mysqldump file actually changed these passwords.

And with that, all MySQL user accounts were restored and working!

Small Adjustments

Now that all the major elements were transferred from the old server to the new server, I sat back and casually navigated to as many parts of the websites as I could. Mostly everything worked. I also followed certain steps to transfer MyBB instances. Those steps can be found here.

Another issue I was having involved a PHP script I had written to get the name of the song that I was currently listening to (via Last.FM) for my blog. For whatever reason, the script was not executing and was simply acting as plain text. After several hours of troubleshooting, I realized that the default Sentora installation disallows PHP’s short tags (So <?php is required instead of <?). This issue was fixed by editing the php.ini file in /etc/php.ini and seting short_open_tag field to “On”.

Finally, since I thought that some of my users would dislike navigating to panel.mydomain.com when they wanted to edit information about theirdomain.com, I created a simple HTML file with a Javascript redirect, called it index.html, and put it in the public_html/panel directory for each of the primary domains being hosted on my server. In this way, theirdomain.com/panel would take them to the right place and not force them to type my domain into the web browser.

The Final Step for users’ websites was for them to direct their domains to the new host. I directed users to use their domain registrar to register nameservers for their domains, ns1.domain.com and ns2.domain.com and have them point to the new host IP Address. Then, they directed their domains to the newly registered nameservers of the same domains. With this, the domains now pointed to the new host and all DNS configuration changes made on the new host would be picked up and reflected in the domain.

The Final Moment

With that, the migration was complete. In order to ensure that everything worked properly, I shut off my DigitalOcean host and went to bed. Thankfully, when I woke up in the morning, all websites still worked and pinging them returned a fancy IPv6 IP Address.

I ended up encountering some issues with SSL, Antivirus, and Malware later on, but I will cover those in a later post.

Writing Papers is Easy

In middle school, high school, and even college, the word “paper” carries a
heavy negative connotation. It is not a rare event for a student to sigh, frown,
and mutter “I have to write a paper”. For whatever reason, papers are agreed to
be feared by the majority of people; however, they have no reason to be feared.
Writing papers is a simple and formulaic process that can easily be taught to
anyone, as I will attempt to do here.

The main reason for writing this post is because of my brother, who came to me
seeking help on a paper that was due in a few days. Although he was assigned
the paper weeks ago, he put it off because he was scared to write it. With my
help, he was able to complete an A paper in just a few days and impress his
peers. On top of this, he is now confident writing any sort of paper.

Please keep in mind that this article is geared toward writing research-style
papers, where an argument is being made. Although some of these tips may apply
to other styles of writing, this article is not meant to be strictly adhered
to when writing things such as creative papers.

So What’s the Secret?

In general, there are several pieces of advice you should follow when writing a
paper. You’ve probably heard a few of these words of wisdom in your life, but
they should be taken seriously.
* Start Early. Although it is tempting to continuously put off a paper,
starting early allows you to do only a small amount of work each day and allows
for time at the end to revise and make sure that everything is perfect.
* Write Often. This goes with the previous piece of advice, where starting
early is fairly useless unless you also write fairly often. It is very useful
to stick to a strict schedule and not waver from it. If a strict schedule is
followed, daily writing time can be minimized to something like an hour a day,
which is not bad at all.
* Stay Calm. One of the worst mistakes that people make while writing papers
is getting overwhelmed. They will think of the fifteen pages that have to write
and constantly just try to meet the page limit without thinking about the
quality of their work. Stay calm, stay collected, and consistently complete
small amounts of high quality work.
* Self-Discipline is Important. All of the above rules are great; however,
they do not have any effects on their own. Without self-discipline, it is easy
to waver from any rules you may set and “do it some other time”. Discipline
yourself seriously by taking away things you love. Be your own parent.

The General Formula

With the above tips in mind, it is fairly easy to begin writing and complete
your paper in a reasonable amount of time. Careful attention to planning,
detail, and quality also help create an excellent paper. However, no paper
can be written without an explicit statement of the requirements of that paper.
For most research papers, the general requirements follow a pattern of making
a claim, backing up that claim with a source, and proving that source is
reputable. It’s that simple. Of course, this process needs to be repeated many
times in a succesful paper; however, the process itself is still very easy.

Making a Claim

A claim is simply something that you believe to be true. For instance, “Green
makes humans feel relaxed.” is a claim. Other examples of claims are “Violent
video games cause violent behavior”, “Using a mouse boosts productivity” and
“Wearing hats boosts self-confidence”. Basically, a claim is a statement that
is debatable and must be proven. Thus, the main argument of your paper is also
a claim. Making a claim is quite simple, really. All you have to do is state
what you think to be correct. The hard part comes next.

Proving your Claim

A claim is great on its own because it may cause the reader to question the
thing you’re making a claim about. This questioning may cause them to make a
new conclusion about the topic and thus lead to an advancement in knowledge.
However, this doesn’t really advance your paper. Thus, you need to prove your
claim. Generally, in order to prove your claim, you need to provide evidence
that suggests that your claim may be true. Using the examples of claims from
the above section, here is what some evidence may look like:

  • Violent video games cause violent behavior. A study of 20 children showed that
    those who played violent video games were more aggressive as adults.
  • Using a mouse boosts productivity. People who use a mouse report 5 times more
    productivity than their keyboard-weilding counterparts.
  • Wearing hats boosts self-confidence. Several brain imaging scans show that
    the frontal lobe is more active while wearing a hat.

With the evidence provided, you can see that our claims are now strengthened.
The claim strengthened with the evidence makes up our argument. How do we know
that this evidence is actually correct, though? That leads to the final step in
our paper-recipe-for-success.

Bolstering the Evidence

The details of evidence can either make or break the evidence. For instance,
saying that “because my grandma said it and my grandma is always right” is much
less powerful than saying “journal X reported it and journal X peer-reviews
all submitted articles”. In order to help the reader believe that the evidence
you provided is legitimate and correct, you need to explicitly tell them. In a
nutshell, the reader needs to know why the evidence you chose is the best and
most relevant evidence and why it isn’t incorrect. Using our previous examples
to prove our point:

  • A study of 20 children showed that those who played violent video games were
    more aggressive as adults. The control group, who were not exposed to
    violent video games, were less aggressive. The lives of the subjects were
    heavily monitored.

  • People who use a mouse report 5 times more productivity than their
    keyboard-weilding counterparts, who reported only a small productivity boost
    when asked the same question about a keyboard. This question was performed by
    an unbiased team over thousands of subjects.

  • Several brain imaging scans show that the frontal lobe is more active while
    wearing a hat. These results were reported in Journal of Sciences, which is
    peer-reviewed and notorious for rejecting submissions with even a hint of
    malpractice.

As you can see, a lot of “evidence bolstering” involves showing that the
evidence was not simply construed, but rather it was compared with a control
group, meaning that the observed evidence was indeed significant. With the third
example, we don’t show details about the experiment (because we may not know),
but we show that the experiment was well-done and results were accurate because
the journal wouldn’t accept anything less. All of these are valid ways to show
that an example is more than just words, but a meaningful set of results.

And with that, the three simple steps of an argument come together and form
something meaningful and convincing. A research paper simply consists of these
steps repeated several times. However, they are repeated in a cascading matter.
That is, your big “main claim” is supported by several “subclaims”, which are
each supported by evidence that has some sort of backing behind it. This
cascading layout can create a pretty complex paper. As an outline, your paper
should look something like this:

A) Background information and significance
B) Main Claim (Also known as the Thesis statement)
C) Subclaim #1
–i) Evidence
—-a) Backing of Evidence
–ii) More Evidence
—-a) Backing of Evidence
D) Subclaim #2
–i) Evidence
—-a) Backing of Evidence
–ii) More Evidence
—-a) Backing of Evidence
E) Subclaim #3
–i) Evidence
—-a) Backing of Evidence
–ii) More Evidence
—-a) Backing of Evidence
F) Conclusion

Sometimes, of course, a subclaim may be so complicated that it warrants its own
subclaim, which may warrant another subclaim, and so on. However, in order to
create a convincing paper, the amount of subclaims should be kept to a minimal
amount. An example of this repeating subclaim hierarchy can be seen with our
last example, where a bit of the evidence also requires a subclaim. In totality,
our current claim is as follows:

” People who wear hats are more self-confident. This was proven to indeed be
the case in S&R’s experiment reported in Journal of Science, which showed
increased frontal lobe activity while wearing hats. ”

This claim is a little problematic. Why? You, like I, may be wondering what
“frontal lobe activity” has to do with self-confidence. It is here where another
subclaim may serve to be useful. In order to complete the argument, we can
make another subclaim showing that frontal lobe activity is indeed correlated
with self-confidence, which of course, will require another piece of evidence.
Thus, our argument could be:

” People who wear hats are more self-confident. This was proven to indeed be
the case in S&R’s experiment reported in Journal of Science, which showed
increased frontal lobe activity while wearing hats. This frontal lobe activity
is commonly correlated with increases in self-confidence, as shown in Kirk’s
study of students, which showed that those who categorized themselves as having
a large amount of “self-confidence” had larger frontal lobe regions. This
study was posted in a peer-reviewed journal and is the basis of most modern
self-confidence studies. Therefore, if you’re ever feeling a little lacking in
the confidence area, donning a hat may help. ”

When all elements are combined, a fantastic and convincing argument will create
itself.

The Steps to Completing The Paper

Now that you’re aware of how to write a convincing argument, you may be
wondering how in the world you will have time to come up with claims, address
necessary subclaims, and find reputable evidence for each claim. The process
is surprisingly not very time-consuming as long as you follow the general
time-management guidelines suggested above.

Make an Outline

The first step to any long-term project involves getting your thoughts and
ideas out in an organized fashion. For a paper, the perfect way of doing this
is through an outline. In your first outline, you may want to include the
following items:
1) Your full introduction less your thesis statement
2) Your thesis statement (Or a rough version of it)
3) Subclaim #1
–3i) Evidence supporting subclaim #1 and proof that it is reputable
–3ii) Evidence supporting subclaim #1 and proof that it is reputable
4) Subclaim #2
–4i) Evidence supporting subclaim #2 and proof that it is reputable
–4ii) Evidence supporting subclaim #2 and proof that it is reputable
5) Subclaim #3
–5i) Evidence supporting subclaim #3 and proof that it is reputable
–5ii) Evidence supporting subclaim #3 and proof that it is reputable
6) Conclusion Paragraph

Then, over the next few days, instead of working on the details of the paper
itself, iterate over the outline, find better evidence and sources to back up
your claims, refine your thesis statement and your subclaims. Then, when writing
the actual paper, the only hard work will be choosing words that sound nice.
Each number in the outline represents a new paragraph. Thus, the outline
very closely resembles what your final paper looks like. I’m not going to tell
you the exact process of turning the outline into a paper, but it definitely
isn’t hard.

The Source List

Now, your paper should be pretty close to being complete. The final step is to
simply include your “bibliography” or “reference list”. This is the easiest
step of the entire paper, but most people have a hard time with it. Most papers
will have a format requirement, whether it be MLA or APA or Chicago-Style. Thus,
since you have already compiled your list of evidence when creating your
outline, making a source list is easy. Simply look up the guidelines for your
required formatting style and put in the list of evidence that you used
in your outline. That’s it.

Formatting is Easy

Speaking of formatting requirements, many people who are writing papers for
school lose easy points because they mess up while formatting their papers.
Admittedly, it is easy to be intimidated while getting caught up in the minute
details of MLA or APA or Chicago; however, most of these formatting styles have
online checklists that are easy to follow. Generally, each format has their
own unique style for the following items:

  • Margins
  • Headers including title pages
  • Fonts
  • In-Text citations
  • Source Lists

Once you edit each of these components of your essay to reflect the style
guidelines set by your formatting requirement, it will look great, giving off
a better first impression and hopefully a higher grade.

Additional Techniques

There are also some additional techniques that will give your paper extra
oomph and extra convincing power. Most of these techniques involve a sort-of
interaction with the reader. If you can predict what the reader is thinking,
you become liked by the reader and they are more prone to listen to what you
have to say in your paper.

Addressing Counter-Arguments

Have you ever watched a commercial or talked to someone who said “But wait..
I know what you’re thinking!” and then they proceed to disprove your opinion?
It’s a very powerful tool. The listener becomes impressed at the fact that
the speaker knew what they were thinking, and the listener is even more
prone to further convincing.

Basically, any time that your argument may seem to have a flaw in it, explicitly
address this seeming flaw and disprove it. Take, for instance, our hat argument,
which is seemingly riddled with flaws. Addressing the possible counter-arguments
makes our argument even stronger.

” It has been proven that people who wear hats have higher levels of
self-confidence. In order to avoid a scenario where only people with naturally
high self-confidence levels were measured, self-confidence levels were measured
before and after the donning of the cap, which always resulted in increased
self-confidence levels. ”

This particular snippet addresses the possible counter-argument of “But what if
the people measured are simply self-confident by themselves?”. For any reader
that was thinking that, addressing their thoughts makes your argument powerful
to them. This addressing of counter-argument can be done with almost any claim
you make, and when used at the right moments will only help convince your
audience that you are right.

Show your Personality

Everyone has that one friend that tells them something along the lines of “Just
use big words from the thesaurus and it will make you sound smart”. In general,
the belief is that if you use big words, you will sound smarter and receive
a higher grade on your paper. Although this course of action may actually result
in higher grades, it does not result in a higher quality paper. In order to
create the highest quality paper, you should let your personality shine through
with every word you choose. If your paper has your sense of humor, your
cheerful choice of words, and your own personal vocabulary, your paper is more
likely to come off as natural to the reader. If your paper is more natural
and more human, it will also be more believable. Of course, never use so much
of your personality that your paper comes off as unprofessional.

In Short

In short, it’s really not too challenging to write a good paper. The main
barriers that stop people from writing good papers are in the minds of the
writers. Most people simply don’t want to follow a strict paper-writing
schedule, while others get too overwhelmed by the idea of following a
strict-schedule and instead ruin their chances of writing a good paper by
committing to a schedule that does not promote solid research and solid
revisioning. As long as you stick to a strict schedule with self-discipline,
make a good outline, make good claims with good evidence, and give yourself
plenty of time for revisions, writing a paper should be a breeze.