<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Password &#8211; Henry Poon&#039;s Blog</title>
	<atom:link href="https://blog.henrypoon.com/blog/tag/password/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.henrypoon.com</link>
	<description></description>
	<lastBuildDate>Mon, 03 Oct 2022 05:35:40 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	
<site xmlns="com-wordpress:feed-additions:1">83044199</site>	<item>
		<title>Installing Seafile with Docker and Apache 2</title>
		<link>https://blog.henrypoon.com/blog/2019/06/12/installing-seafile-with-docker-and-apache-2/</link>
					<comments>https://blog.henrypoon.com/blog/2019/06/12/installing-seafile-with-docker-and-apache-2/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Wed, 12 Jun 2019 07:12:42 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[engineering]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apache 2]]></category>
		<category><![CDATA[Apache HTTP Server]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[cloud storage]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Dia]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[DROPBOX]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[File sharing]]></category>
		<category><![CDATA[Free software]]></category>
		<category><![CDATA[Gmail]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Gran]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IOS]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Lie]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Matt]]></category>
		<category><![CDATA[Nap]]></category>
		<category><![CDATA[Net]]></category>
		<category><![CDATA[Opera]]></category>
		<category><![CDATA[OS-level virtualisation]]></category>
		<category><![CDATA[Page]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[PATH]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[seafile]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[System software]]></category>
		<category><![CDATA[Systemd]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[URL]]></category>
		<category><![CDATA[USR]]></category>
		<category><![CDATA[ypres]]></category>
		<category><![CDATA[Z]]></category>
		<guid isPermaLink="false">https://blog.henrypoon.com/?p=3509</guid>

					<description><![CDATA[Seafile is an open source file sharing software that allows its users to setup their own cloud storage at home. Think Dropbox, but self-hosted. This post is about deploying an instance of Seafile using Docker on a non-standard port (i.e. not 80 and 443). The reason to deploy the app on a non-standard port is [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph"><a rel="noreferrer noopener" aria-label="Seafile (opens in a new tab)" href="https://www.seafile.com" target="_blank">Seafile</a> is an open source file sharing software that allows its users to setup their own cloud storage at home.  Think Dropbox, but self-hosted.</p>



<p class="wp-block-paragraph">This post is about deploying an instance of Seafile using Docker on a non-standard port (i.e. not 80 and 443).  The reason to deploy the app on a non-standard port is usually because there is already another webserver running on that port (in my case Apache 2).  In such scenarios, it is necessary to set up a reverse proxy so the Seafile port can be exposed by Apache on ports 80/443.  Under typical circumstances, deploying Seafile on a standard port would mean that the app would host itself without the need for Apache 2 at all.  This post also assumes Ubuntu 16.04 as the operating system, but in theory should apply to other Linux OS&#8217;s.</p>



<p class="has-text-align-left wp-block-paragraph">The process can be split into multiple parts:</p>



<ol class="wp-block-list"><li>Setup Docker</li><li>Deploy Seafile</li><li>Configure Apache 2</li><li>Setup systemd</li><li>Setup e-mail (optional)</li><li>Backing up the image</li><li>Troubleshooting</li></ol>



<h2 class="wp-block-heading">Setup Docker</h2>



<p class="wp-block-paragraph">This guide won&#8217;t go into depth on how to setup Docker, but rather the setup guide and more information about what Docker is can be found here: <a rel="noreferrer noopener" aria-label="https://docs.docker.com/get-started/ (opens in a new tab)" href="https://docs.docker.com/get-started/" target="_blank">https://docs.docker.com/get-started/</a></p>



<h2 class="wp-block-heading">Deploy Seafile</h2>



<p class="wp-block-paragraph">The key page in the Seafile documentation for deploying Seafile within Docker can be found here: <a href="https://github.com/haiwen/seafile-docker" target="_blank" rel="noreferrer noopener">https://github.com/haiwen/seafile-docker</a>.  The command I used is as follows:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">docker run -d --name seafile \
  -e SEAFILE_SERVER_HOSTNAME=seafile.example.com \
  -e SEAFILE_ADMIN_EMAIL=me@example.com \
  -e SEAFILE_ADMIN_PASSWORD=a_very_secret_password \
  -v /opt/seafile-data:/shared \
  -p 8000:80 \
  seafileltd/seafile:latest</code></pre>



<p class="wp-block-paragraph">I recommend setting up Seafile with an actual secret password because it&#8217;s not easy to change once it&#8217;s set up.</p>



<p class="wp-block-paragraph">Note that the port argument shows 8000:80.  It means that Docker will use the host port 8000 and the container will use port 80 &#8211; meaning that using Docker will interpret requests from my host OS on port 8000 as requests on port 80 in the container.  8000 was used on my setup because port 80 was already used. </p>



<p class="wp-block-paragraph">Once the command is executed, the necessary files will be downloaded and the container will start and will be accessible on port 8000.</p>



<p class="wp-block-paragraph">There is also an option to setup Seafile with an SSL cert from <a rel="noreferrer noopener" aria-label="Let's Encrypt (opens in a new tab)" href="https://letsencrypt.org/" target="_blank">Let&#8217;s Encrypt</a>, but I didn&#8217;t do this because I already had a cert that I wanted to reuse.</p>



<p class="wp-block-paragraph">Once the server is up, navigate to <a href="#">https://seafile.example.com/sys/settings/</a> and change SERVICE_URL and FILE_SERVER_URL to match your domain name.</p>



<h2 class="wp-block-heading">Configure Apache 2</h2>



<p class="wp-block-paragraph">Adding a reverse proxy on Apache 2 will allow Apache 2 to route requests to port 8000, which will go to port 80 in the container.  The main reference for this section is this: <a href="https://manual.seafile.com/deploy/deploy_with_apache/" target="_blank" rel="noreferrer noopener">https://manual.seafile.com/deploy/deploy_with_apache/</a>.  This is done by adding a new site to Apache 2.  The following configuration assumes that a LetsEncrypt SSL certificate is used.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">cd /etc/apache2/sites-available
sudo nano seafile.conf</code></pre>



<pre class="wp-block-code"><code lang="apacheconf" class="language-apacheconf">&lt;IfModule mod_ssl.c&gt;
&lt;VirtualHost *:443&gt;
    ServerName seafile.example.com
    ServerAdmin me@example.com

    RewriteEngine On

    # ModSecurity does not process requests.  There is a hard limit of 1 GB
    # with ModSecurity.
    SecRuleEngine Off

    # Whitelist internal IPs for mod_evasive
    DOSWhitelist 192.168.1.*

    &lt;Location /media&gt;
        Require all granted
    &lt;/Location&gt;

    # Stuff for seafile server
    ProxyPass /seafhttp http://127.0.0.1:8082
    ProxyPassReverse /seafhttp http://127.0.0.1:8082
    RewriteRule ^/seafhttp - [QSA,L]

    # Stuff for seahub
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8000/
    ProxyPassReverse / http://127.0.0.1:8000/

    ErrorLog ${APACHE_LOG_DIR}/seafile_error.log
    CustomLog ${APACHE_LOG_DIR}/seafile_access.log combined

    Include /etc/letsencrypt/options-ssl-apache.conf

    SSLCertificateFile /path/to/cert/file.pem
    SSLCertificateKeyFile /path/to/cert/key/file.pem
&lt;/VirtualHost&gt;
&lt;/IfModule&gt;
</code></pre>



<p class="wp-block-paragraph">I&#8217;ve added my local domain to the whitelist so that mod_evasive doesn&#8217;t think my local host is a threat.</p>



<p class="wp-block-paragraph">There are two sets of ProxyPass and ProxyPassReverse lines.  The reason for this is that Seafile is split up into Seahub and Seafile, where one uses port 8082 (by default), while the other uses 8000.  These two lines are essentially what allows Apache to read requests from port 443 and pass them on to the container.</p>



<p class="wp-block-paragraph">Once the file is saved, execute the following</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo a2ensite seafile.conf
sudo service apache2 reload</code></pre>



<p class="wp-block-paragraph">Navigating to the site at the Apache 2 defined port should now load Seafile without having to go to port 8000.</p>



<h2 class="wp-block-heading">Setup systemd</h2>



<p class="wp-block-paragraph">systemd allows the Docker container to be started up on boot, and be controlled like this:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo service seafile start/stop/restart</code></pre>



<p class="wp-block-paragraph">The configuration is as follows:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo nano /etc/systemd/system/seafile.service</code></pre>



<pre class="wp-block-code"><code lang="properties" class="language-properties">[Unit]
Description=Seafile Server
After=network.target mysql.service

[Service]
Type=oneshot
ExecStart=/usr/bin/docker container start seafile
ExecStop=/usr/bin/docker container stop seafile
ExecReload=/usr/bin/docker container restart seafile
RemainAfterExit=yes
User=root
Group=root

[Install]
WantedBy=multi-user.target</code></pre>



<p class="wp-block-paragraph">Once the configuration is saved, shut off the existing running instance of Seafile and then let systemd start it up for you.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo systemctl daemon-reload
sudo service seafile start</code></pre>



<p class="wp-block-paragraph">At this point, Seafile should start automatically on boot, with Apache 2 doing a reverse proxy to the true Seafile port.</p>



<h2 class="wp-block-heading">Setup e-mail (optional)</h2>



<p class="wp-block-paragraph">Optionally, Seafile can be configured to send e-mails.  The reference is here: <a href="https://manual.seafile.com/config/sending_email/" target="_blank" rel="noreferrer noopener">https://manual.seafile.com/config/sending_email/</a>.  The config file should be under:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">/opt/seafile-data/seafile/conf/seahub_settings.py</code></pre>



<p class="wp-block-paragraph">I happen to be using Gmail SMTP, so at the end of the file I&#8217;ve added</p>



<pre class="wp-block-code"><code lang="properties" class="language-properties">EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'me@example.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER</code></pre>



<h2 class="wp-block-heading">Backing up the image</h2>



<p class="wp-block-paragraph">After setting everything up, you&#8217;ll probably want to backup the Docker image.  First, print out the list of running containers</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo docker ps</code></pre>



<p class="wp-block-paragraph">Then take a snapshot of the current running state:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">docker commit -p &lt;container ID&gt; &lt;whatever you want to call this snapshot&gt;</code></pre>



<p class="wp-block-paragraph">Running this command lists all the images and should show this newly saved image:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo docker images</code></pre>



<p class="wp-block-paragraph">I don&#8217;t have a private docker repository, so I saved the image to the disk and backed up the file by doing the below.  Just make sure to actually move the image to an actual backup location.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo docker save -o &lt;whatever path you want&gt;/&lt;filename&gt;.tar &lt;the name used earlier&gt;</code></pre>



<p class="wp-block-paragraph">The image should be backed up now.  To restore the image, it&#8217;s a matter of running this:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo docker load -i &lt;path to the backup file&gt;</code></pre>



<p class="wp-block-paragraph">Listing the images as above should show that the image was successfully loaded.  Running this starts it back up again.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo docker run &lt;container name&gt;</code></pre>



<h2 class="wp-block-heading">Troubleshooting</h2>



<p class="wp-block-paragraph">Seafile logs can be helpful if it doesn&#8217;t start up correctly.  These can be found at:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">/opt/seafile-data/logs/seafile</code></pre>



<p class="wp-block-paragraph">There may be a need to ssh into the Docker container.  The command for that is:</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">sudo docker exec -it seafile /bin/bash</code></pre>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2019/06/12/installing-seafile-with-docker-and-apache-2/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3509</post-id>	</item>
		<item>
		<title>Jenkins pipeline for Spring with beta and prod stages and deployment rollback</title>
		<link>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/</link>
					<comments>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Thu, 09 Mar 2017 08:04:51 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[Apache Ant]]></category>
		<category><![CDATA[Apache Maven]]></category>
		<category><![CDATA[Build automation]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Compiling tools]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[Const]]></category>
		<category><![CDATA[Continuous integration]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[future]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[groovy]]></category>
		<category><![CDATA[Hole]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Java enterprise platform]]></category>
		<category><![CDATA[Jenkins]]></category>
		<category><![CDATA[Levant]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[PATH]]></category>
		<category><![CDATA[Plug]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Rolling]]></category>
		<category><![CDATA[Run]]></category>
		<category><![CDATA[Scripting languages]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[URL]]></category>
		<category><![CDATA[Variable]]></category>
		<category><![CDATA[Z]]></category>
		<category><![CDATA[Zip]]></category>
		<guid isPermaLink="false">https://blog.henrypoon.com/?p=2614</guid>

					<description><![CDATA[In the past couple of days, I&#8217;ve been experimenting a bit with the Jenkins pipeline plugin to create a code deployment pipeline with independent beta and prod stages for a Spring Boot app. I even managed to add rolling back a deployment in case a prod deployment fails! It took me a bit of time [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">In the past couple of days, I&#8217;ve been experimenting a bit with the <a href="https://wiki.jenkins-ci.org/display/JENKINS/Pipeline+Plugin" target="_blank" rel="noopener">Jenkins pipeline plugin</a> to create a code deployment pipeline with independent beta and prod stages for a Spring Boot app. I even managed to add rolling back a deployment in case a prod deployment fails! It took me a bit of time to Google my way through how to do everything, so I figure I just lay it all out here in case it helps other people do the same thing.</p>



<p class="wp-block-paragraph">The nice thing about all of this is that I can push a code change to git, and Jenkins can build it, run through all the tests and then deploy to production automatically.</p>



<h1 class="wp-block-heading">Layout of a pipeline script</h1>



<p class="wp-block-paragraph">Pipeline scripts are written in <a rel="noopener" href="http://www.groovy-lang.org/" target="_blank">Groovy</a>, which is a variant of Java. In general, a pipeline script is laid out like this:</p>



<pre class="wp-block-code"><code lang="python" class="language-python">node {
    def SOME_CONSTANT = "whatever"
    ...

    stage('some stage name like Build') {
        // Stuff to do as a part of this stage
    }

    stage('another stage') {
        // More stuff
    }

    ...
}</code></pre>



<p class="wp-block-paragraph">Each stage represents a stage in the pipeline (e.g. building, beta deployment, prod deployment etc.)</p>



<h1 class="wp-block-heading">Defining some constants</h1>



<p class="wp-block-paragraph">First, a list of constants can be defined that can be used throughout the pipeline so that if the pipeline script gets reused somewhere, only these constants have to be changed. I&#8217;m not aware of anything that lets me reuse a pipeline in Jenkins without copying and pasting the code somewhere else so for now I&#8217;ll have to live with copying and pasting.</p>



<p class="wp-block-paragraph">My project uses Maven so I got Jenkins to download its own copy of Maven that it can use to execute builds and have defined it as a constant. The name I&#8217;ve given it in the Jenkins Global Tool Configuration is &#8220;Maven 3.3.9&#8221; exactly. My project also uses Tomcat so there are some Tomcat specific things in there that may or may not be relevant to your use case.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">def MAVEN_HOME = tool 'Maven 3.3.9'
    def WORKSPACE = pwd()

    def PROJECT_NAME = "name-of-project"
    def WAR_PATH_RELATIVE = "App/target/${PROJECT_NAME}.war"
    def WAR_PATH_FULL = "${WORKSPACE}/${WAR_PATH_RELATIVE}"
    def TOMCAT_CTX_PATH_BETA = "Tomcat-context-path-for-the-beta-stage"
    def TOMCAT_CTX_PATH_PROD = "Tomcat-context-path-for-the-prod-stage"
    def GIT_REPO_URL = "URL-to-git-repo-ending-in-.git"</code></pre>



<h1 class="wp-block-heading">Preparation Stage</h1>



<p class="wp-block-paragraph">First, the code has to be retrieved from the repository before it gets built. Jenkins allows storing username/password pairs so that they can be referenced without having to write out the password in plaintext. Jenkins uses a &#8220;credential ID&#8221; for this.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Preparation') {
        git branch: "master",
        credentialsId: "credentials-ID-stored-in-Jenkins-that-can-access-the-git-repo",
        url: "${GIT_REPO_URL}"
    }</code></pre>



<h1 class="wp-block-heading">Build Stage</h1>



<p class="wp-block-paragraph">Next, the code must be built and unit tested. &#8220;mvn clean install&#8221; will do just that (depending on what you want, you can always put in a different maven goal). The junit command is just there to take the resulting XML that gets generated during the build process and posts a graph of how many tests were run for each build.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Build') {
        sh "'${MAVEN_HOME}/bin/mvn' clean install"
        junit '**/target/surefire-reports/TEST-*.xml'
    }
</code></pre>



<h1 class="wp-block-heading">Beta Stage</h1>



<p class="wp-block-paragraph">Once the build succeeds, you&#8217;ll want to deploy it to a beta environment, so integration tests can happen. The following happens at this stage:</p>



<ol class="wp-block-list"><li>Get the right credentials to get permissions to Tomcat</li><li>Call the deploy method to deploy the war file in Tomcat (more on that later)</li><li>If the deployment fails for whatever reason, print out the deployment log for debugging and fail the build</li><li>If the deployment succeeds, run the integration tests (the command to do this may differ based on use case)</li></ol>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Beta') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'credential-id-for-tomcat',
            usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
                // Password is available as an env variable, but will be masked 
                // if you try to print it out any which way
                def output = deploy(WAR_PATH_FULL, TOMCAT_CTX_PATH_BETA,
                        env.USERNAME, env.PASSWORD)
                if (output.contains("FAIL - Deployed application at context path " + 
                        "/${TOMCAT_CTX_PATH_BETA} but context failed to start")) {
                    echo "----- Beta deployment log -----"
                    echo output
                    echo "-------------------------------"
                    currentBuild.result = 'FAILURE'
                    error "Beta stage deployment failure"
                }
            }

        echo "Running integration tests"
        sh "'${MAVEN_HOME}/bin/mvn' -Dtest=*IT test"
        junit '**/target/surefire-reports/TEST-*.xml'
    }</code></pre>



<p class="wp-block-paragraph">The deploy method is what takes care of the actual deployment to Tomcat, which is how the Jenkins build tells Tomcat about the newly built war file. The deploy method is below (be sure to change the server IP and port). Alternatively, I could have built my project as an embedded jar file, but that has a different challenge in figuring out how to get Jenkins to tell the OS to execute the newly built jar file as a particular user.</p>



<ol class="wp-block-list"><li>Based on the Tomcat context path, decide whether a beta or production deployment is happening</li><li>Make a copy of the build war file and add .prod or .beta to the end of it so as to keep the original</li><li>Set the Spring profile to use on the newly copied war file (more on that later)</li><li>Call the curl command to do the actual deployment to Tomcat (more on that later)</li></ol>



<pre class="wp-block-code"><code lang="python" class="language-python">def deploy(warPathFull, tomcatCtxPath, username, password) {
    def envSuffix = ""
    def isBeta = tomcatCtxPath.contains("beta")
    if (isBeta) {
        envSuffix = "beta"
    } else {
        envSuffix = "prod"
    }
    sh script: "cp ${warPathFull} ${warPathFull}.${envSuffix}" 
    setSpringProfile(warPathFull, isBeta)
    def output = sh script: "curl --upload-file '${warPathFull}.${envSuffix}' " +
            "'http://${username}:${password}@localhost:8081/manager/text/deploy" + 
            "?path=/${tomcatCtxPath}&amp;update=true'", returnStdout: true
    return output
}</code></pre>



<p class="wp-block-paragraph">In the case of my project, I&#8217;m building a single war file that does not have a Spring profile (beta/prod) defined. This means that I have to manually define this before I deploy the app to Tomcat since there are some things that differ between beta and prod like database URL&#8217;s. To do this, I wrote a method that opens the war file like a zip (jar/war files are zip files) and adds a line to my application.properties to define a Spring profile.</p>



<p class="wp-block-paragraph">Admittedly, doing this zip file manipulation seems kind of hacky. Alternatively, I could have defined my build such that I had a separate beta build and a prod build to avoid modifying the zip file, but the drawback is that I&#8217;d then have to build my code twice.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">def setSpringProfile(warPathFull, isBeta) {
    def zipFileFullPath = warPathFull + "." + (isBeta ? "beta" : "prod")
    def zipIn = new File(zipFileFullPath)
    def zip = new ZipFile(zipIn)
    def zipTemp = File.createTempFile("temp_${System.nanoTime()}", 'zip')
    zipTemp.deleteOnExit()
    def zos = new ZipOutputStream(new FileOutputStream(zipTemp))
    def toModify = "WEB-INF/classes/application.properties"

    for(e in zip.entries()) {
        if(!e.name.equalsIgnoreCase(toModify)) {
            zos.putNextEntry(e)
            zos &lt;&lt; zip.getInputStream(e).bytes
        } else {
            zos.putNextEntry(new ZipEntry(toModify))
            zos &lt;&lt; zip.getInputStream(e).bytes
            zos &lt;&lt; ("\nspring.profiles.active=" + (isBeta ? "beta" : "prod")).bytes
        }
        zos.closeEntry()
    }

    zos.close()
    zipIn.delete()
    zipTemp.renameTo(zipIn)
}</code></pre>



<p class="wp-block-paragraph">A curl command to Tomcat is what actually does the deployment. To deploy a file to Tomcat, do the following below. This will deploy the war file to Tomcat and instantly run it, thus it will be accessible at the given context path.</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash">curl --upload-file 'path-to-war-file' http://username:password@server-address:port/manager/text/deploy?path=/tomcat-context-path&amp;update=true</code></pre>



<h1 class="wp-block-heading">Prod Stage</h1>



<p class="wp-block-paragraph">The same kind of stuff happens in the prod stage as in the beta stage with a few exceptions. The following happens at this stage:</p>



<ol class="wp-block-list"><li>Get the right credentials to get permissions to Tomcat</li><li>Call the deploy method to deploy the war file in Tomcat (except this time it is prod)</li><li>If the deployment fails for whatever reason, print out the deployment log for debugging and roll back the deployment</li><li>If the deployment succeeds, save the build files, and then the pipeline is finished. Alternatively, smoke tests can be run at this point, but I did not implement this in my project</li></ol>



<p class="wp-block-paragraph">Rollback is important because if the deployment fails, you don&#8217;t want to be stuck with a broken environment. Since build artifacts are saved on successful deployments, these same artifacts can be brought back if future deployments fail. This means they can be redeployed so that the code can be fixed before another deployment happens.</p>



<pre class="wp-block-code"><code lang="python" class="language-python">    stage('Prod') {
        withCredentials([[$class: 'UsernamePasswordMultiBinding',
            credentialsId: 'credential-id-for-tomcat',
            usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) {
                // Password is available as an env variable, but will be masked 
                // if you try to print it out any which way
                def output = deploy(WAR_PATH_FULL, TOMCAT_CTX_PATH_PROD, env.USERNAME, env.PASSWORD)
                if (output.contains("FAIL - Deployed application at context path " + 
                        "/${TOMCAT_CTX_PATH_PROD} but context failed to start")) {
                    echo "Prod stage deployment failure, rolling back deployment"
                    echo "----- Prod deployment log -----"
                    echo output
                    echo "-------------------------------"
                    step([$class: 'CopyArtifact',
                            filter: "${WAR_PATH_RELATIVE}",
                            fingerprintArtifacts: true,
                            projectName: "${PROJECT_NAME}",
                            target: "${WAR_PATH_RELATIVE}.rollback"])
                    deploy(WAR_PATH_FULL + ".rollback/" + WAR_PATH_RELATIVE,
                            TOMCAT_CTX_PATH_PROD, env.USERNAME, env.PASSWORD)
                    currentBuild.result = 'FAILURE'
                    error "Prod deployment rolled back"
                } else {
                    archiveArtifacts artifacts: "${WAR_PATH_RELATIVE}*", fingerprint: true
                }
            }
    }
</code></pre>



<p class="wp-block-paragraph">At the end you get to have something like this:</p>


<div class="wp-block-image">
<figure class="aligncenter"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="600" height="882" src="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2017/03/JenkinsPipeline.png?resize=600%2C882&#038;ssl=1" alt="" class="wp-image-2638"/></figure>
</div>


<p class="wp-block-paragraph">That pretty much sums up the whole Jenkins pipeline that I&#8217;ve been using lately for Spring projects!</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2017/03/09/jenkins-pipeline-for-spring-with-beta-and-prod-stages-and-deployment-rollback/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2614</post-id>	</item>
		<item>
		<title>Setting up Karaoke (KTV) like an actual Karaoke place at home using JetKTV</title>
		<link>https://blog.henrypoon.com/blog/2012/01/02/setting-up-karaoke-ktv-like-an-actual-karaoke-place-at-home-using-jetktv/</link>
					<comments>https://blog.henrypoon.com/blog/2012/01/02/setting-up-karaoke-ktv-like-an-actual-karaoke-place-at-home-using-jetktv/#comments</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Tue, 03 Jan 2012 03:00:05 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[.exe]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[agra]]></category>
		<category><![CDATA[AppLocale]]></category>
		<category><![CDATA[Artists]]></category>
		<category><![CDATA[Asian culture]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Bopomofo]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[Chinese language]]></category>
		<category><![CDATA[Click]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Contents]]></category>
		<category><![CDATA[Culture]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Dia]]></category>
		<category><![CDATA[Directory]]></category>
		<category><![CDATA[Download]]></category>
		<category><![CDATA[DVD]]></category>
		<category><![CDATA[EAR]]></category>
		<category><![CDATA[English language]]></category>
		<category><![CDATA[Find]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Japan]]></category>
		<category><![CDATA[Karaoke]]></category>
		<category><![CDATA[Language]]></category>
		<category><![CDATA[Light]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Literature]]></category>
		<category><![CDATA[Lyrics]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Net]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[PATH]]></category>
		<category><![CDATA[Pho]]></category>
		<category><![CDATA[Plan]]></category>
		<category><![CDATA[Plug]]></category>
		<category><![CDATA[Prompt]]></category>
		<category><![CDATA[Reference]]></category>
		<category><![CDATA[Simplified Chinese characters]]></category>
		<category><![CDATA[Singing]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Songs]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Struct]]></category>
		<category><![CDATA[taiwan]]></category>
		<category><![CDATA[Taiwanese culture]]></category>
		<category><![CDATA[Thou]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Trac]]></category>
		<category><![CDATA[UNC]]></category>
		<category><![CDATA[Vol]]></category>
		<category><![CDATA[Volume]]></category>
		<category><![CDATA[Websites]]></category>
		<category><![CDATA[YouTube]]></category>
		<category><![CDATA[Z]]></category>
		<category><![CDATA[Zip]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/setting-up-karaoke-ktv-like-an-actual-karaoke-place-at-home-using-jetktv</guid>

					<description><![CDATA[As many people are aware, Karaoke is popular among Asian people.&#160; Generally, people go to a Karaoke establishment to enjoy it, but it can also be done at home.&#160; Current methods involve juggling a bunch of VCD’s, DVD’s, or even LD’s to get the wanted song.&#160; Karaoke establishments have all set up systems for people [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">As many people are aware, Karaoke is popular among Asian people.&nbsp; Generally, people go to a Karaoke establishment to enjoy it, but it can also be done at home.&nbsp; Current methods involve juggling a bunch of VCD’s, DVD’s, or even LD’s to get the wanted song.&nbsp; Karaoke establishments have all set up systems for people to use a computer to choose a song from a database (by artist, name, gender, etc.) that will be played on the TV.&nbsp; This set up can be replicated at home.</p>



<p class="wp-block-paragraph">This guide presents how to mimic the system used in professional karaoke establishments at home.&nbsp; The software this system uses revolves around a Taiwanese program called JetKTV.&nbsp; Much of the content from this guide was drawn from Chinese language websites discussing the usage of this program (scroll all the way down for References).&nbsp;&nbsp;&nbsp; There is little literature on this subject in English and so this guide presents basically an English version of the reference sites plus a few added notes.</p>



<p class="wp-block-paragraph">The program used is in Chinese, so people who are not fluent in Chinese may have a hard time navigating through the software.&nbsp; Those who are brave enough to continue or have a basic knowledge of Chinese with better English fluency may find it helpful to see English instructions. &nbsp;The Chinese sites on this subject are also written for older versions, and the setup procedure for those older versions are slightly different.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2012/01/jetktv.png?ssl=1" target="_blank" rel="noreferrer noopener"><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2012/01/jetktv_thumb.png?w=1280&#038;ssl=1" alt="jetktv" title="jetktv"/></a></figure>
</div>


<h1 class="wp-block-heading">Contents</h1>



<ul class="wp-block-list"><li><a href="#tvsetup">Proposed Setup</a></li><li><a href="#jetktvsetup">Setting Up JetKTV2010</a></li><li><a href="#insertsong">Inserting A New Song</a></li><li><a href="#insertartist">Inserting A New Artist</a></li><li><a href="#testing">Testing</a></li><li><a href="#ref">References</a></li></ul>



<h1 class="wp-block-heading"><a name="tvsetup"></a>Proposed Setup</h1>



<p class="wp-block-paragraph">The proposed setup of all the hardware (TV’s, amps, computer, etc.) is in the diagram below.</p>


<div class="wp-block-image">
<figure class="aligncenter"><a href="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2012/01/ksetup.png?ssl=1" target="_blank" rel="noreferrer noopener"><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/blog.henrypoon.com/wp-content/uploads/2012/01/ksetup_thumb.png?w=1280&#038;ssl=1" alt="ksetup" title="ksetup"/></a></figure>
</div>


<p class="wp-block-paragraph">The computer will play the chosen Karaoke videos and transmit the video signal to the TV (via extended display like in a dual monitor set up).&nbsp; The computer’s audio will go to an amplifier or a mixer, which is then transmitted to a set of speakers.&nbsp; Microphones are plugged into the amplifier/mixer is well so that the speakers can also play the sound picked up by the microphones.&nbsp; Depending on the hardware, the cables could be different (some TV’s may not have HD output etc.)The&nbsp; computer is the source of all the signals transmitted to the other devices and must be set up with the Karaoke software.</p>



<h1 class="wp-block-heading"><a name="jetktvsetup"></a>Setting up JetKTV2010</h1>



<p class="wp-block-paragraph">The PC will use the following software:</p>



<ul class="wp-block-list"><li>JetKTV2010 (<a rel="noopener" href="https://skydrive.live.com/?cid=46746bb36e167913&amp;sc=documents&amp;id=46746BB36E167913!171" target="_blank">link</a>)</li><li>SongMgr (optional – not helpful on English language PC’s – more on that topic later)</li></ul>



<p class="wp-block-paragraph">It is helpful to set up the software using a dual monitor setup.&nbsp; That way, it is easier to test without having to go and plug the computer to the TV each time.</p>



<p class="wp-block-paragraph">Unzip the contents of the JetKTV2010 program in a folder and open JetKTV2010.exe.&nbsp; The GUI buttons are for searching through the database (by looking for the artist, song name, etc.) to find the wanted song. Once a song is selected, it will be added to the list of songs to play just like the software at actual Karaoke establishments. The video will play in full screen on one monitor and the song picker GUI will say on another monitor.&nbsp; To close the program, click on the top left corner of the GUI (hidden button).</p>



<p class="wp-block-paragraph">Some of the software features in addition to searching and adding songs:</p>



<ul class="wp-block-list"><li>Skipping songs</li><li>Fast forwarding, pausing, etc.</li><li>Switching from one audio channel to both audio channels (alternating between vocal on/off)</li></ul>



<p class="wp-block-paragraph">This program reads from a database that contains the song names, artists, language, etc.&nbsp;&nbsp; Therefore, <strong><em>it does not come with songs</em></strong>.&nbsp; Songs must be downloaded separately and added on.&nbsp; These can come from existing DVD’s or YouTube.&nbsp; The next section will explain how to populate the database.</p>



<h1 class="wp-block-heading">Populating the Database</h1>



<p class="wp-block-paragraph">The SongMgr program mentioned above can add/remove contents from the database, but there are problems with it when using it on English language PC’s due to problems in encoding some of the Chinese characters.&nbsp; Even Microsoft AppLocale fails to rectify the problems.&nbsp; The solution is to use Microsoft Access to open up the database file directly and make changes.</p>



<p class="wp-block-paragraph">Adding one song can seem like a lengthy process at the first try, but it will get easier as one becomes more familiar with the system.</p>



<h3 class="wp-block-heading"><a name="insertsong"></a>Inserting A New Song</h3>



<p class="wp-block-paragraph">To insert a new song, one must navigate to the table where the songs are stored and then add an entry to it.</p>



<ol class="wp-block-list"><li>Open <em>Song.mdb</em>in the JetKTV program directory</li><li>When prompted for a password, input “tmwcmgumbonqd” without quotes</li><li>Navigate to the table <em>Tbl_Song.&nbsp; </em>This is the table that records all the song entries.</li></ol>



<p class="wp-block-paragraph">Below is an explanation of each column:</p>



<ul class="wp-block-list"><li>Song_ID: numerical identifier for each song (the program lists them as 5 digit numbers starting at 10000)</li><li>Song_Title: song title</li><li>Song_Singer: each singer has a unique number associated with them (see next section)</li><li>Song_Singer (2nd one): the name of the artist in text</li><li>Song_Word: number of characters in the song name</li><li>Song_Type: a number representing a language (Mandarin,Taiwanese,Cantonese,Hakka Chinese,English,Japanese,Movies,Cartoons,Other&nbsp; in that order starting from 1)</li><li>Song_Volume: song volume, but not sure what units they are in.&nbsp; Default value is 70.</li><li>Song_Channel: the audio channel that does <em>not</em> have the vocal track. (1-Left, 2-Right, 3-Both)</li><li>Song_FileName: filename of the video without the directory</li><li>Song_Path: the directory to the file (could use absolute pathing only, but unsure of whether relative paths work)</li><li>Song_Create: the time that the song was added in</li><li>Song_Count: the play count of a song</li><li>Song_Juyin: the Zhuyin characters representing the song title</li><li>Song_Stroke: number of strokes in the first character of the song name</li></ul>



<p class="wp-block-paragraph">Some of the columns can be left out, but that means that it will not be possible to find a particular song using the omitted information.&nbsp; For example, Song_Juyin can be left out for those who dont use the Zhuyin system, and that feature won’t be used for song searching anyway.</p>



<p class="wp-block-paragraph">To add a song, fill out the following information at the minimum on one row:</p>



<ul class="wp-block-list"><li>Song_ID (must be a unique number and should have five digits)</li><li>Song_Title</li><li>Song_Singer</li><li>Song_Volume (70 is the default)</li><li>Song_Channel</li><li>Song_FileName</li><li>Song_Path</li></ul>



<p class="wp-block-paragraph">For the Song_Singer information, refer to the next section.</p>



<h3 class="wp-block-heading"><a name="insertartist"></a>Inserting A New Artist</h3>



<p class="wp-block-paragraph">Artist information is stored on a different table called <em>Tbl_Singer</em></p>



<ol class="wp-block-list"><li>Open the table called <em>Tbl_Singer</em></li><li>Fill out an entire row to add a new singer (see below for the reference for each information column)</li></ol>



<p class="wp-block-paragraph">Below is an explanation of each column:</p>



<ul class="wp-block-list"><li>Singer_ID: unique identifier for each singer (this is the unique ID that is to put inserted in the Song_Singer column in <em>Tbl_Song</em>)</li><li>Singer_Sex: singer gender (0-Female, 1-Male, 2-Group/Band)</li><li>Singer_Name: artist name in text</li><li>Singer_Juyin: the Zhuyin characters representing the artist name</li><li>Singer_Stroke: number of strokes in the first character of the artist’s name</li></ul>



<h1 class="wp-block-heading"><a name="testing"></a>Testing</h1>



<p class="wp-block-paragraph">One a song or two has been entered into the database, one can test it by opening up the JetKTV program and trying to pick a song.&nbsp; It is working when one screen shows the video playing and another screen showing the JetKTV GUI.</p>



<p class="wp-block-paragraph">One can also try clicking the button labeled &#8220;導唱&#8221; to test if the audio channels are set up properly (toggling it turns on and off the vocals).</p>



<p class="wp-block-paragraph">The next step would be to plug in the computer with all the television components and then trying it again.&nbsp; Once everything works, the system is ready.</p>



<h1 class="wp-block-heading"><a name="ref"></a>References</h1>



<p class="wp-block-paragraph">All reference sites are in Chinese</p>



<p class="wp-block-paragraph">[1] 動手打造窮人 KTV <strong>&lt;</strong>http://www.jetktv.ktvdiy.com/&gt; [Update 2022 October: JetKTV seems to be defunct]</p>



<p class="wp-block-paragraph">[2] [影音相關] JetKTV 輕鬆打造免費 KTV 點唱機 (進階設定篇) &lt;<a href="http://www.soft4fun.net/video-related/%E5%BD%B1%E9%9F%B3%E7%9B%B8%E9%97%9C-jetktv-%E8%BC%95%E9%AC%86%E6%89%93%E9%80%A0%E5%85%8D%E8%B2%BB-ktv-%E9%BB%9E%E5%94%B1%E6%A9%9F-%E9%80%B2%E9%9A%8E%E8%A8%AD%E5%AE%9A%E7%AF%87.htm#doublescr" target="_blank" rel="noreferrer noopener">http://www.soft4fun.net/video-related/%E5%BD%B1%E9%9F%B3%E7%9B%B8%E9%97%9C-jetktv-%E8%BC%95%E9%AC%86%E6%89%93%E9%80%A0%E5%85%8D%E8%B2%BB-ktv-%E9%BB%9E%E5%94%B1%E6%A9%9F-%E9%80%B2%E9%9A%8E%E8%A8%AD%E5%AE%9A%E7%AF%87.htm#doublescr</a>></p>



<p class="wp-block-paragraph">[3] 峰網誌 JetKTV-DIY電腦點歌機..軟體篇 &lt;<a href="http://www.wretch.cc/blog/Linpy/4853370" target="_blank" rel="noreferrer noopener">http://www.wretch.cc/blog/Linpy/4853370</a>></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2012/01/02/setting-up-karaoke-ktv-like-an-actual-karaoke-place-at-home-using-jetktv/feed/</wfw:commentRss>
			<slash:comments>46</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1301</post-id>	</item>
		<item>
		<title>Receiving MMS on Vodafone</title>
		<link>https://blog.henrypoon.com/blog/2011/03/01/receiving-mms-on-vodafone/</link>
					<comments>https://blog.henrypoon.com/blog/2011/03/01/receiving-mms-on-vodafone/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Tue, 01 Mar 2011 19:03:12 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[Chan]]></category>
		<category><![CDATA[Click]]></category>
		<category><![CDATA[Companies]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Deutsche Bahn]]></category>
		<category><![CDATA[Euro]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Final]]></category>
		<category><![CDATA[German]]></category>
		<category><![CDATA[Germany]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[IDE]]></category>
		<category><![CDATA[In Germany]]></category>
		<category><![CDATA[Instant messaging clients]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Messages]]></category>
		<category><![CDATA[Multimedia Messaging Service]]></category>
		<category><![CDATA[My Phone]]></category>
		<category><![CDATA[Net]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[Pho]]></category>
		<category><![CDATA[Plan]]></category>
		<category><![CDATA[Port]]></category>
		<category><![CDATA[Printer]]></category>
		<category><![CDATA[Printing]]></category>
		<category><![CDATA[Racal]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Telecommunications]]></category>
		<category><![CDATA[Tickets]]></category>
		<category><![CDATA[tuna]]></category>
		<category><![CDATA[Vodafone]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/receiving-mms-on-vodafone</guid>

					<description><![CDATA[Receiving MMS on Vodafone Up until now, I&#8217;ve never opened an MMS successfully. My Internet settings on the phone were never set probably plus I never bothered to do it. I also didn&#8217;t know the billing rates for opening them either. But now, an opportunity arose for me to require MMS. The Deutsche Bahn has [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><title>Receiving MMS on Vodafone</title></p>
<p>Up until now, I&#8217;ve never opened an MMS successfully.  My Internet settings on the phone were never set<br />
probably plus I never bothered to do it.  I also didn&#8217;t know the billing rates for opening them either.<br />
But now, an opportunity arose for me to require MMS.  The Deutsche Bahn has three options for distributing tickets purchased online.  The first one is by printing them out, but I don&#8217;t have a printer.  The second method is having them mailed to me, but that costs 3.50 euro.  The third and best option, is to have them sent as MMS.  Knowing that my phone, the P1i, has this ability, I looked for how to do it.  After going through lots of Googling and reading through translated German sites, I finally figured it out.</p>
<p>Now, I use Vodafone in Germany, but this method may work on other providers even.  I am also using GPRS, and not 3G (I don&#8217;t have a dataplan unfortunately).  The way to do it is to register an account on Vodafone.de using your phone number.  Obviously, if you use a different provider, you&#8217;d go to their website to make the account.  I clicked through their services and found an option called the &#8220;HandyKonfigurator&#8221;.  What it does is it sends me the proper settings required for my phone.  I clicked through the dropdown boxes, found my phone and pressed continue.  Vodafone then sent me a file that would inject the settings into my phone.  They also sent me a PIN that I had to enter before my phone settings were changed.  I did as I was asked, and now I can receive MMS messages!</p>
<p>Vodafone Internet Account Settings</p>
<ul>
<li>Address: event.vodafone.de</li>
<li>No user name and password required</li>
<li>IP Config and DNS Addresses are set to automatic</li>
<li>Proxy Server: 139.7.29.17 at port 80</li>
</ul>
<p>Vodafone MMS Account Settings</p>
<ul>
<li>Service Center Address: http://139.7.24.1/servlets/mms</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2011/03/01/receiving-mms-on-vodafone/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">901</post-id>	</item>
		<item>
		<title>Automatically Logon to Windows 7</title>
		<link>https://blog.henrypoon.com/blog/2010/07/16/automatically-logon-to-windows-7/</link>
					<comments>https://blog.henrypoon.com/blog/2010/07/16/automatically-logon-to-windows-7/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Fri, 16 Jul 2010 23:05:30 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[9]]></category>
		<category><![CDATA[COM]]></category>
		<category><![CDATA[Computer]]></category>
		<category><![CDATA[Computer access control]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Digital technology]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Graphical identification and authentication]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Login]]></category>
		<category><![CDATA[Microsoft Windows]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[SAP Logon Ticket]]></category>
		<category><![CDATA[STR]]></category>
		<category><![CDATA[Struct]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Vol]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Windows 7]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/automatically-logon-to-windows-7</guid>

					<description><![CDATA[If you ever get annoyed by having to logon to your computer every time you turn it on, just follow the instructions in that link below.&#160; The process does not involve removing the password, but rather tells Windows to log on using that specific information every time the computer is turned on. http://www.windows7news.com/2009/02/01/automatic-logon-into-windows-7/]]></description>
										<content:encoded><![CDATA[<p>If you ever get annoyed by having to logon to your computer every time you turn it on, just follow the instructions in that link below.&nbsp; The process does not involve removing the password, but rather tells Windows to log on using that specific information every time the computer is turned on.</p>
<p><a href="http://www.windows7news.com/2009/02/01/automatic-logon-into-windows-7/" target="_blank" rel="noopener noreferrer">http://www.windows7news.com/2009/02/01/automatic-logon-into-windows-7/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2010/07/16/automatically-logon-to-windows-7/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">403</post-id>	</item>
		<item>
		<title>Weird Router Login Issue</title>
		<link>https://blog.henrypoon.com/blog/2010/05/10/weird-router-login-issue/</link>
					<comments>https://blog.henrypoon.com/blog/2010/05/10/weird-router-login-issue/#respond</comments>
		
		<dc:creator><![CDATA[hp]]></dc:creator>
		<pubDate>Tue, 11 May 2010 06:07:06 +0000</pubDate>
				<category><![CDATA[computer stuff]]></category>
		<category><![CDATA[Computer networking]]></category>
		<category><![CDATA[Computing]]></category>
		<category><![CDATA[D]]></category>
		<category><![CDATA[Firmware]]></category>
		<category><![CDATA[IME]]></category>
		<category><![CDATA[Internet architecture]]></category>
		<category><![CDATA[It]]></category>
		<category><![CDATA[Link]]></category>
		<category><![CDATA[Login]]></category>
		<category><![CDATA[Networking hardware]]></category>
		<category><![CDATA[Page]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[Router]]></category>
		<category><![CDATA[Server appliance]]></category>
		<category><![CDATA[Telecommunications]]></category>
		<category><![CDATA[Time]]></category>
		<category><![CDATA[Tools]]></category>
		<guid isPermaLink="false">http://henrypoon.mooo.com/blog/weird-router-login-issue</guid>

					<description><![CDATA[So I just upgraded my router (DGL-4500) to the latest firmware today (1.22), and I started experiencing this weird bug where I couldn&#8217;t log into the router page. &#160;Every time I typed in my password, the router would deny me access. &#160;According to the D-Link forum, pressing the Login button rather than pressing the Enter [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>So I just upgraded my router (DGL-4500) to the latest firmware today (1.22), and I started experiencing this weird bug where I couldn&#8217;t log into the router page. &nbsp;Every time I typed in my password, the router would deny me access. &nbsp;According to the D-Link forum, pressing the Login button rather than pressing the Enter key works. &nbsp;For some weird reason, that fixed it.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.henrypoon.com/blog/2010/05/10/weird-router-login-issue/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">314</post-id>	</item>
	</channel>
</rss>
