Udi Mosayev

Doing web stuff

Better History Manager 0.2.x

Hey,

A quick update for Better History Manager extension for you. I’ve released version 0.2 which allows you to have 10 sites on the block list, also I’ve redesigned the popup slightly (but that’s far from being a masterpiece) and fixed a bug where your entire history was removed.

I’ll be glad to hear some feedback on it.

Useful PHP Libraries Gist

Stumbled upon this Gist few days ago, has many libraries you might find interesting: https://gist.github.com/ziadoz/1677679

Howto: Reverse SSH Tunnel

Intro

You ever had to access a server/computer behind a firewall / closed network? your office computer or perhaps one of your servers behind a closed network/firewall.

For one of my contract projects I had to have a full control over a server in a remote location inside a closed network. In order to do that I had to setup a reverse ssh tunnel.

(This post is written for Ubuntu and OpenSSH)

You need

A Server behind closed network, lets call it “remote server”.
A proxy server. A server you can access easily which you’ll use in order to SSH into the remote server.

Step 1: Configure OpenSSH

Open /etc/ssh/sshd_config

1
$ vi /etc/ssh/sshd_config

Find GatewayPorts and make sure it says ‘yes’. If it doesn’t exists, add it:

1
GatewayPorts yes

Save & close.

Run:

1
$ service ssh restart

Repeat the same process on OpenSSH of the remote server as well.

Step 2: Open the Tunnel & Connect

In your remote server, run:

1
$ ssh -R <tunnel_port>:localhost:22 proxy_server_user@proxy_server_ip

tunnel_port – can be any available port.
proxy_server_user – root or any other user you’ll have for that purpose.

Now the tunnel is open in our remote destination server, let’s connect to it through the proxy server.
First you need to ssh into the proxy server, then:

1
$ ssh user_on_remote_server@localhost -p <tunnel_port>

This is it.

If the remote server is an office computer or something you can access daily, you’ll probably open this tunnel before you leave the office. Otherwise, you need to figure out a way to do it remotely, when you don’t have physical access to that machine (read the Automating Tunnel Management below).

Authentication

Every time you’ll create the tunnel, it’ll ask you for password/passphrase and etc. In my case, the tunnel is created by me for the first time, but afterwards I need to create it remotely by scripts, and I couldn’t have password/passphrase in the process. So this is what I did:

1. Create a tunnel user on proxy server.

2. Create an SSH Key on remote server (empty passphrase, so it won’t ask for it), add this key to /home/tunnel/.ssh/authorized_keys file.

Automating Tunnel Management

In my case, the server sits in a corner of a room, without any monitor or keyboard. No one can easily access it without a laptop connected to the same network this server is connected to.
Whenever I need to create a tunnel, I want to be able to click on a button on my machine and make the remote server create the tunnel on a port I define. For this reason I’ve created a cron job that runs every minute, it pings my server and asks “Hey, I’m server 163, do you need me to do anything?”
In this point I send back a JSON describing what I need this script to do. It can be anything: update the code, run OS update or open an ssh tunnel on port X and proxy server Y.

Hope it helps. I’m not a sysadmin guru, but I’ll be glad to help if you have any questions.

Better History Manager – Google Chrome Extension

Hey

I have a certain problem with the way Google Chrome let’s us manage our history. I’ll give you an example:
I don’t want Chrome to keep track of file sharing sites browsing, Facebook browsing and Google searches I made for privacy reasons (I think we can all understand that). But Chrome doesn’t have an easy way to remove history for specific site/domain, and if you do search for a specific site or domain it won’t actually find ALL the urls of that site.

Overnight I wrote a little extension called Better History Manager, and basically you can define a list of websites that you don’t want them to be stored in Google Chrome history. This way you don’t need to manually select them, clear history of the last X hours or entire history.

I’m planning on adding a few more features to id, whitelists, allowing larger block list (its only 5 sites at the moment).

Download it on Google Chrome Webstore – I’ll be happy to get any feedback, let me know what you think.

Updated MY_Model class for CodeIgniter 2.0

Hi,

A year~ ago I shared with you MY_Model class I wrote and used on most of my CodeIgniter projects, since these posts are still popular but very very old I’ve decide to share the most recent one, which I host on GitHub as well, It’s still in progress, but gives you a solid start with your own projects.

Link to the Gist.

Creating Applications with AppIgnite

A few months ago, I had the opportunity to test AppIgnite.  Now, I want to share my Applgnite experience with you.

What Is AppIgnite?

AppIgnite is a web application that allows anybody with minimal technical knowledge to create web applications. If you know how to work with MS Excel, you can easily produce useful applications with AppIgnite in no time.
AppIgnite was developed by Jason Roberts, a freelance coder and the co-host of TechZing, a great tech podcast which I’ve mentioned in the past.
My first application in AppIgnite was an application for managing personal finance, which I have used to track my expenses/income from different categories.
*Please note: Some Javascript coding and views modifications was needed to actually show “total expenses” on the page. More on that later.

The way it works:

When creating a new application, you can create models. In my application, I have a default “User Model” (which is responsible for user and permissions management in your app and is part of the basic skeleton for each AppIgnite application), “Entry Model” (which represents each expense/income) and “Categories Model.”

You can easily define properties for each model and even define relationships between the different models (for example, the “Entry Model” has 1 category).  You can also set permissions for each model (from the built-in user/permissions management) and you can set the permissions for different CRUD functions within the same model.

Each model has “Views.” Views are the HTML templates for different screens in the application: New Entry form, Entries List table, etc.
AppIgnite has a built-in editor for the views. If you have technical knowledge, you can modify the HTML the way you’d like.

The bad news is that if you really want to change the layout of your app, it is a lot of work. You need to modify each new form individually and on top of that, when creating new models, their views will have the default layout. However, AppIgnite is still in development and I’m sure this feature will be a lot better once it’s final version is released. I hope that it will have the native CSS editor – I’m currently loading external CSS file for my app.  I also hope that it will  load jQuey (the more technical users can add some javascript awesomeness to their apps).

It has Version Control!

Well, not exactly. But it’s good enough. I believe Jason tried to keep AppIgnite as simple as possible for non-technical people to use it.  That way, if you’ve made a mistake or accidently changed something, and you’d like to revert it, you can go back to the previous “build.”

Each change you make creates a new build (i.e. another version of your application).  That way, when it breaks loose or you decide that you don’t like some of the latest changes, you can easily restore it to any of the past versions.

Exporting your application

This is one of the best features both business-wise and technically speaking.  AppIgnite allows you to export the application you’ve created and keep on developing it.

When exporting the application, you’re getting all of the code (PHP) and database (MySQL) from your app.  Even more, you get an install script. Then, all you have to do is upload it to your server and run the installation script.

Whom is it for?

This application is built so well, that it is suitable for all different levels of technical expertise and therefore has a ton of potential.

Let’s start with businesses that are both big and small.  Not everyone has a huge ERP system that manages every little detail in the company. Many employees work with shared Excel documents which aren’t necessarily enough.  It’s very costly for both your time and money to have custom software developed for that usage.  Therefore, a solution like AppIgnite comes in handy.  The coolest part is that AppIgnite is simple enough for employees to quickly create an application to manage the data they want.

Start-ups can speed up the development time of MVP or POC by creating an application with AppIgnite – exporting it and making all of the changes they want, right there, in the code. It’s even possible for them to use it for developing the final product!

Freelancers can use AppIgnite to generate a skeleton of their project, export the application, and keep developing the project.  It’s a big time saver.

If you want to hear more about AppIgnite, you can follow Jason Roberts and listen to his podcast TechZing.

Book Review: PHP 5 Social Networking

PHP 5 Social Network

PHP 5 Social Network

 

Honestly, I think they should rename this book.  Yes, it allows you to learn how to create a “social network” (ie. users, profilers, events, status stream). But it also gives you a lot more programming information than what you might expect. I hope that the people who are trying to learn PHP aren’t too mislead by the title to end up missing out on this book.
For example, in the first chapter, you are getting familiar with MVC and 3 other design patterns.

The biggest surprise in the book is in Chapter 13 – Marketing, SEO, User Retention, and Monetization Strategies.  A lot of people may already be familiar with the marketing and seo sections, but the user retention part in this chapter really caught my attention. It discusses how to keep users coming back. What is especially great about this chapter is that the strategies offered fit most websites/web applications.

 The closing chapter is Chapter 14 – Planning for Growth. I agree that one shouldn’t worry about scaling while building the product (you can also find this tip in other books). It’s more important to keep in mind the potential to be faced with decisions that can affect you in the long-run and are expensive to change.
In this chapter, the author also writes about code and server performance, scaling, caching, NoSQL and more.
There is no in-depth information about those subjects, but there is still more than enough information to get you thinking and allow you to know what to look for when the subject arises. The chapter gives you information about tools you should be familiar with, even if you don’t deal with any issues at the moment.

In conclusion, the chapters are really clear and well-structured.  It provides a step-by-step guide on how to create a social network.
After each chapter, you will get closer and closer to a decent social networking site.

Packt Pub book page

MY_Model v2.0 For CodeIgniter

Update: This post is very old. I’ve created new model class for my CodeIgniter projects, you can find it here: Updated MY_Model for CodeIgniter 2.0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<?php

class MY_Model extends CI_Model
{

    // The main table name
    private $_table;

    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Setter/Getters for the table prop
     * @param String $table
     */

    public function setTable($table)
    {
        $this->_table = $table;
    }

    public function getTable()
    {
        return $this->_table;
    }


    // Log as Error each time nonexisting method called.
    public function __call($name, $arguments)
    {
        $args = implode(',', $arguments);
        log_message('error', $name . '(' . $args . ') Not exists.');
        return FALSE;
    }

    /**
     * Checks if certain field in any row has a certain value.
     * Its used to have a unique data like username, email etc.
     * @param String $field Name of the field in the table to check the data in
     * @param String $value The value to check if exists in that field
     * @return Bool TRUE if this data exists, FALSE if unique
     */

    public function is_duplicate($fieldName, $value)
    {
        if (empty($fieldName) OR empty($value))
        {
            log_message('error', 'Got some empty param. field: ' . $fieldName . ' | value: ' . $value);
            exit(0);
        }
        else
        {
            $this->db->select($fieldName);
            $query = $this->db->get_where($this->getTable() , array(
                $fieldName => $value
            ));
            if ($query->num_rows > 0)
            {
                return TRUE;
            }
            else
            {
                return FALSE;
            }
        }

        return FALSE;
    }

    /**
     * This method inserts some array of data into the db
     * @param Array $data
     * @return Int Insert ID
     */

    public function add($data)
    {
        if (is_array($data))
        {

            // $data['Reorder'] = $this->getLastOrder()+1;

            $this->db->insert($this->getTable() , $data);
            return $this->db->insert_id();
        }
        else
        {
            log_message('error', 'Got non-array param.');
            return FALSE;
        }
    }

    /**
     * This method updates fields in my table.
     * @param String $fieldName
     * @param String $value
     * @param Integer $id
     */

    public function update_field($fieldName, $fieldValue, $id)
    {
        if (empty($fieldName))
        {
            log_message('error', 'Got empty fieldName: ' . $fieldName);
            return FALSE;
        }
        else
        if (!is_numeric($id))
        {
            log_message('error', 'Got non-numeric id: ' . $id);
            return FALSE;
        }
        else
        {
            $this->db->where('id', $id);
            $query = $this->db->update($this->getTable() , array(
                $fieldName => $fieldValue
            ));
        }
    }

    /**
     * Updates whole row [unlike update_field()]
     * @param Array $data
     * @param Integer $id
     */

    public function update($data, $id)
    {
        if (!is_array($data))
        {
            log_message('error', 'Supposed to get an array!');
            return FALSE;
        }
        else
        if (!is_numeric($id))
        {
            log_message('error', 'Got non-numeric id: ' . $id);
            return FALSE;
        }
        else
        {
            /* write the old&amp;new data to history
            foreach($data as $fieldName=>$fieldValue) {
            $this->history->write($this->getTable(), $id, $fieldName, $fieldValue);
            }

            */

            $this->db->where('id', $id);
            $this->db->update($this->getTable() , $data);
        }
    }

    /**
     * This method returns all the rows of this model
     * @param Array $where Array of field=>value
     * @param Array $orderby field to order by and side - desc/asc.
     * @return CI_Query_Resource the $query object
     */

    public function get_where($where = array('is_deleted' => 0) , $orderBy = null)
    {
        if ($orderBy != null) $this->db->order_by($orderBy[1], $orderBy[2]);
        $query = $this->db->get_where($this->getTable() , $where);
        return $query;
    }

    /**
     * This method gets 1 row from a table and returns it.
     * @param Integer $id
     * @return DB_Res $query CodeIgniter's db resource
     */

    public function get($id)
    {
        if (!is_numeric($id))
        {
            log_message('error', 'Got not numeric id: ' . $id);
            return FALSE;
        }
        else
        {
            $query = $this->db->get_where($this->getTable() , array(
                'id' => $id
            ));
            return $query;
        }
    }

    /**
     * This method logically deletes a row.
     * @param Integer $id
     * @return Boolean
     */

    public function delete($id)
    {
        if (is_numeric($id))
        {
            $this->update_field('is_deleted', 1, $id);
            return TRUE;
        }
        else
        {
            return FALSE;
        }
    }
}

Start A Design Firm? A How to Guide By Forrst Users

I want to share with you a question by @garrettbolin on ForrstStart A Design Firm? A How to Guide By Forrst Users [Click to read the question].


You probably know I’m  a little bit experienced in this field, and I read the question during my morning tea so I was really focused and responded informatively.
Lots of people [ok ok.. only 22] found my comment useful, and I want to share it with you:

At the beginning

  • If you figure out you need a little bit of money to start, for legal docs and maybe some hardware [printer and etc.] then put this money in, but save it as much as possible. Buy used hardware, nothing fancy. Don’t buy “work” laptop, just use w/e you all have now.
  • Set a goal – set a goal, “We need to make $1k each month for the first 6 months. How can we achieve that?” think about your rate for all sorts of different work you can do, and establish a number of projects you need to do each month.
    This is your goal now, to have a number of project you must have and working your ass off to get them.
    The thing that helped me when I freelanced is to know “I need to sell my CMS app to 3 clients at least,
    if I’ll get a new app dev project, then I can afford myself to find only 1 buyer”. Setting a goal in business is very important rule.
  • Responsibilities – Who’s doing what. Sit down with your co’s, and define who’s doing what. You don’t want any issues to be forgotten because no one was responsible.

Clients, where are you??
These are some of the things I’ve done to find new clients:

  • Contacts – finding business owners through friends and family. Talk to everybody, “Hi man, your dad still has this bakery?”. EVEN IF this business owner don’t need your service [already has a website], try to figure out how the website helps his business, see why he wanted/needed a website from the begin with.
  • Hunt – Now, when you know why business X needs a website, write these things down in a nice document. Actually describe why a bakery needs a website and why, include good info like 30% more profit, 70% of the clients order online or using the cupons we have online when calling to order…etc.
    Meet other bakery owners in your town, give them a 5min pitch, explain why you think they need a website OR why the current one isn’t enough. Leave them the document for further reading, and wait for the call :)

Some quick tips:

  • Do more then promised – always do more then you’ve promised, but be careful with that. Read this post: Pride vs Payment http://forrst.com/posts/Pride_vs_Payment-BtL , its a very delicate issue, so if you need further explanation just ask.
  • Don’t lie/cheat/deceive – if a someone interested in a service, he probably talked to other firms/freelancers, or will be. Especially if its the first time you’re talking. So don’t lie or cheat. It might work for you once, but plz don’t do it. Be honest! if you don’t have an answer on a certain topic, just say so. Don’t treat them as one night stand, because if you’re good to them, they’ll be good to you and even refer people to you.
    You may earned few bucks from this client, but if he treated well, you’ll get through him or by him in the future lots of work. Trust me.
  • Work hard, life ain’t easy, and probably you’ll have hard time to achieve your goals and find new clients. But if you’ll work really hard, you see its worth it.
  • This is it.
    If this topic interests you, you can read How to become a freelance web developer – Part 1 I wrote.

    First Impression about Android Development

    In the last two days I read and wrote some code for my Android device, and I gotta say, its really good. Not my code, buy the Android framework.

    My first app was ToDo list, which has simple text field that you write your task and saving it with current date.
    Afterwards I started to work on my first real app, something my Mom asked me to, working hours tracker. Its really simple, you write how many hours you worked in certain day, and you can see weekly/monthly stats and calculate the salary.

    I’m almost done with the Add New Work Day activity [every screen in Android is an Activity], I need to keep reading about saving state and how to use SQLite DB.

    This are some lessons I learned while working with Eclipse and ADT:

    1. DDMS Perspective -> Log isn’t running.

    It happened to me after few hours working on the app, my guess is the connectivity with my Android Device lost. I restarted Eclipse and reconnected my device, it worked again.

    2. Get Android Device!

    At the beginning I used the emulator, but then I realized I already got the real thing, so I should use it. Now, maybe its just for me because my laptop isn’t that powerful, but the emulator is really heavy, and it takes too much time to run the app again. But with my Android Device its really snappy, and you don’t get frustrated during the debugging. So I really recommend you, if you’re taking Android Development seriously, for your own sanity, get Android Device.

    3. developer.android.com

    Click Here. You are welcome.