Nov 19, 2011

Android :: wrong image / data in ListView rows

Android's ListView reuses list items when they aren't need anymore. For this reason, you need to make sure all views that should change, will actually get changed. Your problem is that if you don't find a drawable for the current list item, you don't empty nor hide the ImageView. You should do thumb.setImageDrawable(null) in that case, or thumb.setVisibility(View.GONE).
- From stackoverflow

Example code:


 @Override
     public View getView(int pos, View v, ViewGroup parent) {
      TimetableViewHolder timetableHolder;
         if (v == null) {
             LayoutInflater vi = ((Activity)context).getLayoutInflater();
             v = vi.inflate(R.layout.timetable_item, parent, false);
             timetableHolder = new TimetableViewHolder();
             timetableHolder.rel = (TextView) v.findViewById(R.id.rel);
             timetableHolder.time = (TextView) v.findViewById(R.id.time);
             timetableHolder.icon = (ImageView) v.findViewById(R.id.icon);
             v.setTag(timetableHolder);
         } else {
          timetableHolder = (TimetableViewHolder) v.getTag(); 
         }

         TimetableItem item = items.get(pos);

         if(item != null) {
          timetableHolder.rel.setText(item.rel);
          timetableHolder.time.setText(item.time);
          if(item.url.equals("ERROR")) {
           timetableHolder.icon.setImageResource(android.R.drawable.ic_menu_close_clear_cancel);
          } else if(item.url.equals("PRESTOP")) {
           timetableHolder.icon.setImageResource(android.R.drawable.ic_menu_directions);
          } else { // THIS IS IMPORTANT
           timetableHolder.icon.setImageResource(android.R.drawable.ic_dialog_info);
          }
         }

         return v;
     }

Android search dialog doesn't appear

Have a problem?
The search dialog doesn't show up?

I just thought you should know, I found this interesting comment on stackoverflow:

oh my god. this is f*ing stupid. i had to use android:label="@string/xyz" instead of android:label="lol" and no single word about this in the documentation. unbelievable

 This is my manifest:

<activity android:name=".SearchableActivity" >
 <intent-filter >
  <action android:name="android.intent.action.SEARCH" />
 </intent-filter>

 <meta-data
  android:name="android.app.searchable"
  android:resource="@xml/searchable" />
</activity>
<activity
 android:label="Preferred stations"
 android:name="PreferredStation"
 android:theme="@android:style/Theme.NoTitleBar" >
 <meta-data
  android:name="android.app.default_searchable"
  android:value=".SearchableActivity" />
</activity>
And searchable
<?xml version="1.0" encoding="utf-8"?>
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
    android:label="@string/search_label"
    android:hint="@string/search_hint" >
</searchable>


Android :: google maps (MapView) hacks, tricks, workarounds

MapView isn't very developer friendly now is it?

Here are some hacks I've had to work with:

1) When tapping on the overlay, the app crashes if you're trying to display the dialog.
Unable to add window -- token null is not for an application
Yes, this is due to context. Especially if you're trying to do this in a seperate thread or AsyncTask.
Turns out the context you need to pass to your dialog is mapView.getContext();
AlertDialog.Builder dialog = new AlertDialog.Builder(mapView.getContext());




2) Displaying only the overlays which are within map bounds
Oh yeah, several problems here. You've probably come across at least one of these:

  • Wrong map bounds in onCreate (0, 360000000),
    Yeah, in onCreate those haven't been calculated yet. onStart doesn't help either. Try this:
Runnable waitForMapTimeTask = new Runnable() {
  public void run() {
    if(mapView.getLatitudeSpan()==0||mapView.getLongitudeSpan()== 360000000) {
      mapView.postDelayed(this, 100);
    } else {
      redrawMarkers(); // draw here
    }
  }
};
mapView.postDelayed(waitForMapTimeTask, 100);

You create a new thread and wait until you get the right bounds. Recursively call it again.
  • Map bounds ???
    Don't worry, it's simple.
public Rect getMapBounds() {
return new Rect(
mapView.getMapCenter().getLongitudeE6() - mapView.getLongitudeSpan()/2,
mapView.getMapCenter().getLatitudeE6() - mapView.getLatitudeSpan()/2,
mapView.getMapCenter().getLongitudeE6() + mapView.getLongitudeSpan()/2,
mapView.getMapCenter().getLatitudeE6() + mapView.getLatitudeSpan()/2
);
}

...
if(!s.drawn && rect.contains(point.getLongitudeE6(), point.getLatitudeE6())) {


  • Yeah, okay, but what about panning / zooming?
    Well, there are no methods, like onPan or onZoom, but some people found their way around this problem. There is no perfect solution, you'll see.
    Check these links out:
  1. http://stackoverflow.com/questions/2328650/how-can-i-detect-if-an-android-mapview-has-been-panned-or-zoomed
  2. http://bricolsoftconsulting.com/2011/10/31/extending-mapview-to-add-a-change-event/
  3. http://stackoverflow.com/questions/3567420/how-to-catch-that-map-panning-and-zoom-are-really-finished
  • Zoom in on double tap?
    Click here: http://dev.kafol.net/2011/11/how-hard-is-it-to-make-simple-zoom-in.html.
  • Overlays don't get drawn immediately!
    Try this:
    mapView.postInvalidate();
    or this:
    mapView.invalidate();

    But keep in mind, that invalidate() needs to be called from an UI! If you're trying to get it working from a thread, use postInvalidate()!
  • MapView java.util.ConcurrentModificationException when adding new overlays
    Not sure if I solved this one, but it seems to work now. I read somewhere that this could happen if you add overlays in a non UI thread. I moved the 
    Nope, sorry, this one was my bad. I was doing some crazy async sorting and all hell broke loose.
itemizedOverlay.populateNow();
mapOverlays.add(itemizedOverlay);
mapView.postInvalidate();

From doInBackground to  onPostExecute in  AsyncTask.


You could also run something in a UI thread like this:

runOnUiThread(new Runnable() {
      @Override
       public void run() {
           //do stuff here
       }
});



Nov 18, 2011

Android :: google maps on double tap zoom in

How hard is it to make a simple zoom in call on double tap in MapView in Android?

Not very.

How hard is it to get the information on how to do it?

Very.

Here's what you probably didn't know:
You need to extend the MapView and use this extended class in the Android XML layout file.
In the extended class you instantiate the gesture detector and set on double tap listener.
In the Map Activity you implement OnGestureListener and OnDoubleTapListener.

Example:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center_horizontal" >
    
 <net.kafol.vlaki.ExtMapView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/mapview"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:clickable="true"
     android:enabled="true"
     android:apiKey=""
 />

</RelativeLayout>
package net.kafol.vlaki;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.MotionEvent;
import android.view.GestureDetector.OnGestureListener;
import com.google.android.maps.MapView;

public class ExtMapView extends MapView {
 private Context context;
 private GestureDetector gestureDetector;

 public ExtMapView(Context c, AttributeSet attrs) {
  super(c, attrs);
  context = c;

  gestureDetector = new GestureDetector((OnGestureListener) context);
  gestureDetector.setOnDoubleTapListener((OnDoubleTapListener) context);
 }

 public boolean onTouchEvent(MotionEvent ev) {
  if (this.gestureDetector.onTouchEvent(ev))
   return true;
  else
   return super.onTouchEvent(ev);
 }
}
public class Map extends MapActivity implements OnGestureListener, OnDoubleTapListener {
...
 @Override
 public boolean onDoubleTap(MotionEvent e) {
     int x = (int)e.getX(), y = (int)e.getY();;
     Projection p = mapView.getProjection();
     mapView.getController().animateTo(p.fromPixels(x, y)); // zoom in to a point you tapped 
     mapView.getController().zoomIn();
  return true;
 }

Android : Checkbox ListView - (un) check all

This recycling of views in android is preety insane. Pain to work with.

So the problem is how to check all check boxes in a list view, if a list view only contains the visible items.

Iterating through the adapter or array of holders was pretty unreliable, some checkboxes weren't affected.

What I did was actually add an attribute to the data object and iterate through this object array (the same way it get's added in the adapter)-

Here are some functions:
 public void toggleCheck(Boolean val) {
  
  for(Station s : stations.list) {
   s.checked = val;
   editor.putBoolean("PF_"+s.getID(), val);
  }
  
  for(int i=0 ; i < lv.getChildCount() ; i++) {
   CheckBox cb = (CheckBox) lv.getChildAt(i).findViewById(R.id.cb);
   cb.setChecked(val);
  }

  editor.apply();
 }
 
    private class StationCBViewHolder {
        public CheckBox cb;
        public Station s;
    }
 
 private class StationListAdapter extends ArrayAdapter {
     private ArrayList items;
     private Context context;
     
     public StationListAdapter(Context context, int tvResId, ArrayList items) {
         super(context, tvResId, items);
         this.items = items;
         this.context = context;
     }

     @Override
     public View getView(int pos, View v, ViewGroup parent) {
      final StationCBViewHolder holder;
      final Station item = items.get(pos);
      
         if (v == null) {
             LayoutInflater vi = ((Activity)context).getLayoutInflater();
             v = vi.inflate(R.layout.stationcheckboxitem, parent, false);
             
             holder = new StationCBViewHolder();
             holder.cb = (CheckBox) v.findViewById(R.id.cb);
             holder.s = item;
             
             item.checked = prefs.getBoolean("PF_"+item.getID(),true);
             
             //holder.cb.setTag(holder);
             holder.cb.setTag(item);
             holder.cb.setChecked(item.checked);
             holder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
     @Override
     public void onCheckedChanged(CompoundButton v, boolean isChecked) {
      Station s = (Station) v.getTag();
      editor.putBoolean("PF_"+s.getID(), isChecked);
      editor.apply();
     }
    });
                        
             v.setTag(holder);
         } else {
          holder = (StationCBViewHolder) v.getTag(); 
         }

         holder.cb.setText(item.toString());
         holder.cb.setChecked(item.checked);

         return v;
     }

 }


Full code here: http://pastebin.com/8NMbHqRV


The code still has some bugs related to SharedPreferences and SharedPreferences.Editor, but at least it checks and unchecks all checkboxes.

Sep 14, 2011

URL shortening - make your own URL shortener

If you ever thought about URL shortening, you've probably already figured out, how it works.

Those random letters and numbers which serve as a key (in hashtable data structures) are basically encoded integers, which are AUTO_INCREMENT values in the database.

Here are the encoding and decoding functions:
const ALLOWED_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

function id2short($integer, $base = self::ALLOWED_CHARS) {
	$out = '';
	$length = strlen($base);
	while($integer > $length-1) {
		$out = $base[fmod($integer, $length)].$out;
		$integer = floor( $integer / $length);
	}
	return $base[$integer].$out;
}

function short2id($string, $base = self::ALLOWED_CHARS) {
	$length = strlen($base);
	$size = strlen($string)-1;
	$string = str_split($string);
	$out = strpos($base, array_pop($string));
	foreach($string as $i=>$char) {
		$out += strpos($base, $char) * pow($length, $size - $i);
	}
	return $out;
}

Full code here.

Sep 3, 2011

MySQL error 1236: Client requested master to start replication from impossible position

Symptoms:
[1236] Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position'

110902 16:47:08 [ERROR] Error reading packet from server: Client requested master to start replication from impossible position ( server_errno=1236)
110902 16:47:08 [ERROR] Slave I/O: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position', Error_code: 1236
110902 16:47:08 [Note] Slave I/O thread exiting, read up to log 'mysql-bin.000033', position 4621679


on the master
root@dimko:/var/lib/mysql# ls -la mysql-bin.000033
-rw-rw---- 1 mysql mysql 4620018 2011-09-01 13:45 mysql-bin.000033

4620018 is less than 4621679, therefore it's an invalid position.


Causes:
Master server has crashed and the binlog cache has not been flushed to disk. Slave has recieved a new position, did not recieve data, and data gets lost in a crash (however it might have been written to table, but not in binlog).


Solution:
Use this CHANGE MASTER statement on the slave.
CHANGE MASTER TO MASTER_LOG_FILE=[NEXT FILE], MASTER_LOG_POS=4;
SLAVE START;

in my case that would be

CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000034', MASTER_LOG_POS=4;
SLAVE START;

I don't know why the master log position needs to be 4 for the new file.

What happens:
When the master server restarts it logs binary changes to a new binlog file, so that we minimize data loss by skipping to the next file (everything from the previous file was written already).

Prevention:
Add this line to my.cnf:

sync_binlog = 1

 With this setting the master server flushes cache in the binlog after every write, so that in case of a crash you can lose one statement at most.

Jul 28, 2011

Facebook php-sdk 3.0 changes getLoginURL()

Somehow these frequent changes are still poorly documented. Documentation is scattered across forums, changelogs, code comments and docs pages. Never on the single place. This is horrible. I'm sorry Facebook people, but this makes you look incompetent.

The most obvious change is the abandonment of the getSession method. I have also found out that getLoginURL has been changed.
'req_perms' has been changed to 'scope'
'next' has been changed to 'redirect_uri'
'cancel_url' option has been removed. You'll have to find another way. If the user denies access it will be redirected to 'redirect_uri'. The user will also be redirected to 'redirect_uri' if he clicks allow.
You can know if the user denied access by looking at these GET parameters:
[error_reason] => user_denied 
[error] => access_denied 
[error_description] => The user denied your request.
Also worth knowing is that redirect_uri will not work every time on a single page load (without refreshing the page).
Explanation:
The first time the users sees the oauth dialog there will be two options: Allow and Deny. Both buttons will redirect to 'redirect_uri'.
The second time the user sees the oauth dialog, Deny option will be renamed to 'Leave app'. 'redirect_uri' will still work.
The third time and so on, the button 'Leave app' will redirect to facebook.com/home.php

While this may not be entirely precise, it is true that eventually the Deny/Leave app button will not follow the redirect_uri parameter.

Jul 24, 2011

SiOL TV, dve mrežni kartici, VLC player, Windows 7 x64-bit

V primeru da vam IPTv ne deluje, če imate dve mrežni kartici (eno za internet in drugo za TV), poskusite pri mrežnem adapterju za TV nastaviti metriko na 2.



Ne pozabite na ostale nastavitve za vzpostavitev TV na VLC playerju:
-odprite VLC in pritisnite CTRL+P (Preferences)
-spodaj levo obkljukate Show settings "All"-s tem se omogočijo napredne nastavitve
-v meniju gremo na Input/Codecs - na desni pri UDP portu vnesemo pravi port, ki je za t2 "5000", pri MTU pa imam "1492", potem pa še obkljukamo "Force IPv4"
-gremo v meni "Video" in nato kliknemo "output modules" - pri "Video output modules" izberemo možnost iz seznama "OpenGL video output"
-nato v levem meniju izberemo meni "Stream output" in nato "Access output"
-V Access output sem v okence kjer piše "Multicast output interface" vpisal IP mrežne kartice, ki jo uporabljam za internet, v okence "IPv4 multicast output interface adress" pa sem vpisal IP mrežne kartice, ki jo uporabljam zgolj za IPTV
-zadevo shranite in ponovno zaženite program.



M3U file editor

M3U are playlist files. I have developed this simple editor for a friend, that needed to edit IPTv playlist files.

The editor includes mass (bulk) edits as well as item editor. You can upload and export the same filetype.

You can check out the editor here:
http://kafol.net/code/m3u-edit/

M3U files are easy to parse:
<?
class m3u {
 public $data = array();
 public $name = '';
 
 public function __construct($data = null) {
  if(!is_null($data)) {
   $this->load($data);
  }
 }
 
 public function load($data) {
  if(!is_array($data)) explode("\n",$data);
  
  foreach($data as $i=>$line) {
   if(preg_match('/^#EXTNAME:(.+)/is',$line,$m)) {
    $this->name = clean($m[1]);
   }
   if(preg_match('/^#EXTINF:(\d+),(.+)/is',$line,$m)) {
    $item = new m3uitem();
    $item->length = intval($m[1]);
    $item->setName($m[2]);
    if(preg_match('/^#EXTTV:(.+)/is',$data[$i+1],$m)) {
     $item->setCategories($m[1]);
    }
    $item->file = trim($data[$i+2]);
    $this->data[] = $item;
   }
  }
 }
 
 public function sort() {
  usort($this->data, array(__CLASS__,'cmp'));
 }
 
 public static function cmp($a,$b) {
  if($a->sort == $b->sort) {
   return 0;
  }
  return ($a->sort > $b->sort) ? +1 : -1;
 }
 
 public function export() {
  $r = "#EXTM3U\n#EXTNAME:{$this->name}\n\n";
  foreach($this->data as $d) {
   $r .= "#EXTINF:{$d->length},{$d->getName()}\n";
   if($d->getCategories() != '') {
    $r .= "#EXTTV:{$d->getCategories()}\n";
   }
   $r .= "{$d->file}\n\n";
  }
  return $r;
 }
 
}

class m3uitem {
 public $sort = 0;
 public $length = 0;
 public $file = '';
 private $name = '';
 private $categories = array();
 
 public function __construct() {}
 
 public function getName() { 
  return $this->name; 
 }
 
 public function setName($name) {
  $this->name = clean($name);
 }
 
 public function getCategories() {
  return implode(';',$this->categories);
 }
 
 public function setCategories($data) {
  $this->categories = is_array($data) ? $data : explode(';',clean($data));
  
  foreach($this->categories as $i=>$cat) {
   if(empty($cat)) {
    unset($this->categories[$i]);
   } else {
    $this->categories[$i] = clean($this->categories[$i]);
   }
  }
 }
}
?>


Jul 19, 2011

Automatically download subtitles in VLC player

You can write VideoLAN VLC player's extensions in LUA programming language. Extensions are in Videolan\VLC directory lua\extensions.

This is a modified extension to automatically download subtitles.

Download extension

Will add more languages upon request.
Currently this extension is intended for personal use.

Screenshots:



PHP goo.gl url shortener

Here's an implementation of Google's url shortener: goo.gl.
<?
class googl {
 const api = 'https://www.googleapis.com/urlshortener/v1/url';
 private $key = null;
 
 public function __construct($key = null) {
  if(defined('GOOGLE_API_KEY')) {
   $this->setKey(GOOGLE_API_KEY);
  }
  
  if(!is_null($key)) {
   $this->setKey($key);
  }
 }
 
 public function setKey($key) {
  $this->key = $key;
 }
 
 public function s($url) {
  $data = $this->shorten($url);
  return isset($data->id) ? $data->id : $url;
 }
 
 public function shorten($url) {
  $key = '';
  $data = array();
  $data['longUrl'] = $url;
  
  if(!is_null($this->key)) {
   $key = '?key='.$this->key;
  }
  
  return $this->fetch(self::api.$key,$data);
 }
 
 public function expand($url) {
  $key = is_null($this->key) ? '' : "&key={$this->key}";
  return $this->fetch(self::api.'?shortUrl='.urlencode($url)."$key&projection=FULL");
 }
 
 private function fetch($url, $data = array()) {
  $ch = curl_init();
  
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json'));
  
  if(!empty($data)) {
   curl_setopt($ch, CURLOPT_POST, 1);
   curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  }
  
  $r = curl_exec($ch);
  curl_close($ch);
  
  return json_decode($r);
 }
}
?>

May 25, 2011

Disable Ubuntu Unity Launcher

I guess I'm the only one that hates launchers in desktop environment systems. They're too dumbed down and I can't tell which apps are running and which are just shortcuts.

The easiest way to disable the Unity Netbook Launcher in Ubuntu is to log out from the session, click on the user name and before you enter the password, click on the bottom on the screen and switch to Ubuntu classic


Apr 27, 2011

Custom page numbering in MS Word

I'm sure most of you came across this problem before - how to add custom page numbering.

I don't really like making seperate documents for the pages I don't want numbered and options in MS Word are preety limited. You can set up the numbering to start with a different number. You can't, however, set it up to start with a negative number.

Example: You have the first three pages you don't want numbered (front page, page index, thanks). Everything after those pages is numbered and starts with 1.

- Go to the header/footer - wherever you want to set up page numbering.
- Add page numbering, set it up to start with zero and check the option to have a different header/footer on the first page. This way the front page will have the page number zero, but you can delete numbering for that page.
- Now you need to "extend" the first page, so that the second (or third) page will also be unnumbered. You can do this with page breaks, go to Insert -> page break. There are a couple of different page breaks, choose the one that fits your needs.

There's an other way to do a completely custom page numbering, but it involves a tiny amount of "programming" and it won't work the same if you add page index, but here goes:

- Go to the header/footer
- Retype this code for the example above:
{ IF { PAGE } < 4 "" "{ = { PAGE } - 3 }" }


The important thing here is that you need to press CTRL+F9 to get the curly braces. If you retype them, it won't work.
- After you've written the conditions for page numbering, right-click on it and choose "Update field".

{ IF { PAGE } < 4 "" "{ = { PAGE } - 3 }" }
This is a simple conditional statement, if the current page number is less than four, the first argument (The empty "" string) will be used, otherwise it will calculate the current page number minus three.

Here are some other examples:
{ IF { PAGE } < 3 "" "{ = { PAGE } - 2 }" }
Skip the first two pages

{ IF { PAGE } < 3 "{ PAGE }" "{ = { PAGE } + 5 }" }
Number the first two pages normally, then add 5 to the current page number.

{ IF { PAGE } < 3 "{ PAGE }" "" }
Add a page number only to the first two pages.

Source

Apr 25, 2011

PHP: in_range()

function in_range($num,$low,$high,$step=1) {
    return in_array($num,range($low,$high,$step));
}


Apr 16, 2011

jQuery cycle flash - swf file reloads

Flash object gets reloaded if you use jQuery functions .hide() and .show() or to be exact, setting the css property display from 'block' to 'none' resets the swf (flash) objects.

This topic has some info on how to hide a flash object without resetting it.

jQuery Cycle plugin hides slides with .hide(), so I changed all .hide(), .show() functions and .display properties to use the 'visibility' property. The topic mentioned above says that this is not a cross-browser solution, so it needs some testing.

Here's the fixed code
http://pastebin.com/r5bySug4

Apr 14, 2011

Exporting wireless network passwords in windows

Open command prompt as an administrator

netsh wlan export profile folder=C:\

To import, type:

netsh wlan add profile filename="c:\Wireless Network Connection-whatever.xml" user=all

Mar 18, 2011

Configuring repcached service on Debian/Ubuntu

Repcached is a slightly modified version of memcached, that supports replication of data between two repcached nodes.

Let's say you've read all about these two and you know the benefits of replication and why this article could be useful to you.

One example of why replicated memcache could be useful are replicated PHP sessions between servers.

If you want to configure that PHP sessions are stored in memcache's memory, you need to edit these settings in /etc/php5/apache2/php.ini:
session.save_handler = memcache
session.save_path = "tcp://IP_OF_REPCACHE_1:11311, tcp://IP_OF_REPCACHE_2:11311"
and these optional settings in /etc/php5/apache2/conf.d /memcache.ini:
memcache.maxratio=0
memcache.allow_failover=1
memcache.allow_failover setting is used if one of the servers becomes unreachable, so there is an automatic failover.
Read more about configuring PHP sessions in memcached here.

Now, let's set up repcached to start on boot and System V init scripts, so you can easly start and stop the daemon with the service command.

Steps described here imitate memcached's default configuration in great detail, so you shoud set up memcached before repcached.
sudo apt-get install memcached

Obtain, configure, compile and install repcached. There is a dependancy with libevent-dev for repcached.
sudo apt-get install libevent-dev
tar xvf memcached-1.2.8-repcached-2.2.tar 
cd memcached-1.2.8-repcached-2.2/
./configure --enable-replication
make
make install
At this point you have two installations of memcached. Default memcached that came from apt packages, which is installed in /usr/bin/memcached and repcached, that installed itself in /usr/local/bin/memcached, leaving the original memcached intact.

Now that we have both versions installed, we can copy memcached's default settings and init script and modify them to use repcached. This way you can quickly switch between versions. I would even recommend using default ports (just remember to firewall them!) Arguments are saved in /etc/memcached.conf, so we will create /etc/repcached.conf

See example here.

Note that the only differences with memcached.conf is the name (repcached) and two extra arguments: -x for the server IP and -X for replication port.

Memcached has an enable/disable config in /etc/default so you can quickly switch between daemons or disable them. We will copy this as well.
cp /etc/default/memcached /etc/default/repcached
vi /etc/default/repcached
Change the line to: ENABLE_REPCACHED=yes, and then edit /etc/default/memcached
vi /etc/default/memcached
and disable it, by changing the line to ENABLE_MEMCACHED=no.

Now let's move on to init scripts.
cd /etc/init.d
cp memcached repcached
Edit the file /etc/init.d/repcached.

Here is my example.

Again, we didn't change much, mostly changed from memcached to repcached, but note that the actual start-up of the service happens in this file: /usr/share/memcached/scripts/start-repcached which doesn't exist yet, so we will copy and edit it.
cp /usr/share/memcached/scripts/start-memcached /usr/share/memcached/scripts/start-repcached
File contents or /usr/share/memcached/scripts/start-repcached

Setting up repcached to start at boot

We need to be sure that /etc/init.d/repcached is executable. If you copied it from memcached, everything should be OK, but if init's not recognising the repcached service, you need to chmod +x /etc/init.d/repcached

After you've run update-rc.d command in the terminal it will create shortcuts in rc?.d files which are read at boot.
update-rc.d repcached defaults
For more information on update-rc.d, click here.

You have successfully configured repcached as a service and to start on boot.

To start/stop repcached use
service repcached start
service repcached stop
Try to run repcached by hand at first with the configuration you provided in /etc/repcached.conf.
In my example it's this:
/usr/local/bin/memcached -m 64 -p 11211 -u memcache -X 11212 -x 22.163.130.33

After installing repcached on another machine I've found out that the default user for memcached is nobody, not memcache, so please always check the differences from the default memcache config with the repcached config you've modified or copied from here.

Feb 5, 2011

PHP:: socket_select(), socket_write() and socket_recv()

As it was already said, some clients need \0 character to end transmission, for example Flash's XMLSocket.

You should also be prepared to read less data than you have requested.

Here is an example of a socket buffer - it's an array which has socket resources for keys and an array of a timestamp and recieved data as values.

I find that the best practice for sending data is trailing it with a new line and zero character (\n\0), because you will probably have different types of clients which behave differently for reading data from sockets. Some need a \n to fire an event, some need \0.

For recieving data, sometimes you will get splitted data - this can hapen because the buffer is full (in my example 8192 bytes) or it just gets broken during transmission in lower levels.

Sometimes you can read two messages at once, but they have a zero character in between, so you can just use preg_split() to split the messages. The second message may not be complete, so you add it to your buffer.

 const message_delimiter = "\n\0";

 /*
  * Clear socket buffers older than 1 hour
  */
 function clear_buffer() {
  foreach($this->buffer as $key=>$val) {
   if(time() - $val['ts'] > 3600) {
    unset($this->buffer[$key]);
   }
  }
 }

 /*
  * Add data to a buffer
  */
 function buffer_add($sock,$data) {
  if(!isset($this->buffer[$sock])) {
   $this->buffer[$sock]['data'] = '';
  }

  $this->buffer[$sock]['data'] .= $data;
  $this->buffer[$sock]['ts'] = time();
 }

 function buffer_get($sock) {
  // split buffer by the end of string
  $lines = preg_split('/\0/',$this->buffer[$sock]['data']);

  // reset buffer to the last line of input
  // if the buffer was sent completely, the last line of input should be
  // an empty string
  $this->buffer[$sock]['data'] = trim($lines[count($lines)-1]);

  if(!empty($this->buffer[$sock]['data'])) {
   debug("buffer is not empty for $sock, len: ".strlen($this->buffer[$sock]['data']));
  }

  // remove the last line of input (incomplete data)
  // parse any complete data
  unset($lines[count($lines)-1]);

  // return only the fully sent data
  return $lines;
 }

 function read(&$sock,$len=8192,$flag=MSG_DONTWAIT) {
  $lines = array();

  $this->clear_buffer();

  $bytes_read = @socket_recv($sock,$read_data,$len,$flag);

  if ($bytes_read === false || $bytes_read == 0) {
   return false;
  } else {
   debug("recv: $read_data");
   $this->buffer_add($sock,$read_data);
   return $this->buffer_get($sock);
  }
 }

 /*
  * Write to a socket
  * add a newline and null character at the end
  * some clients don't read until new line is recieved
  *
  * try to send the rest of the data if it gets truncated
  */
 function write(&$sock,$msg) {
  $msg = $msg.self::message_delimiter;
  $length = strlen($msg);
  while(true) {
   $sent = @socket_write($sock,$msg,$length);
   if($sent <= 0) {
    return false;
   }
   if($sent < $length) {
    $msg = substr($msg, $sent);
    $length -= $sent;
    debug("Message truncated: Resending: $msg");
   } else {
    return true;
   }
  }
  return false;
 }

Dec 29, 2010

PHP:: Facebook getLoginUrl iframe next parameter redirect issue

DUE TO FREQUENT FACEBOOK API CHANGES THIS ARTICLE IS OUTDATED.

The php-sdk from Facebook has some bugs in it.

http://stackoverflow.com/questions/3380876/how-to-authorize-facebook-app-using-redirect-in-canvas http://forum.developers.facebook.net/viewtopic.php?id=70575

These solutions didn't work for me, so I had to change the function getLoginUrl in class Facebook

  public function getLoginUrl($params=array()) {
 $currentUrl = $this->getCurrentUrl();
 $args = array(
        'api_key'         => $this->getAppId(),
        'cancel_url'      => 'http://www.facebook.com/',
        'display'         => 'page',
        'fbconnect'       => 0,
        'next'            => $currentUrl,
        'return_session'  => 1,
        'session_version' => 3,
  'canvas'          => 1,
        'v'               => '1.0',
      );
 foreach($params as $key=>$val) {
  $args[$key] = $val;
 }
 return $this->getUrl(
  'www',
  'login.php',
  $args
 );
  }
Example:
if($me) {
 $logoutUrl = $facebook->getLogoutUrl();
} else {
 $loginUrl = $facebook->getLoginUrl(array('next'=>'http://apps.facebook.com/xxxxxxx/'));
 ?>
 <script type="text/javascript">
 top.location.href = '<?=$loginUrl?>';
 </script>
 <?php 
 exit;
}

Dec 6, 2010

PHP:: relative paths in include() or require()

While this might seem fairly obvious, I'd still like to point out that PHP's functions include(), include_once(), require() and require_once() have problems including files in different directories where paths of the filenames are relative. The absolute path of the included files is generated from the filename of the first included file, so any relative path in the second nested include will not have relative paths starting from it's directory, but the directory of the first file. To avoid confusion I find it's best to use absolute paths with the magic constant __FILE__, which is always the current script's filename.

Example:
require_once(dirname(__FILE__).'/../../include_all.php');

Nov 21, 2010

Flash wmode (transparent/opaque/window) z-index

In flash player 9 and below there was a problem with the object's z-index if the wmode was set to window.

When this option is set to transparent, it fixes the z-index issue, but messes up the keyboard layout and mouse wheel events in flash object. Flash player 10.1 fixes the keyboard layout issue.

Workaround
Setting wmode to opaque keeps the mouse wheel functionality and z-index of absolute elements on the page, but only if you set the background color for the element!

Having a transparent background (or setting the opacity attribute in CSS) (still) does not solve the issue.

Nov 13, 2010

flashlog.txt NS_ERROR_FAILURE

If flash player (debugger) locks the flashlog.txt file (can't be deleted or truncated), try deleting the mm.cfg file and restarting the browser and/or flash player. After that, try using a different plugin/software for reading flash traces.

Aug 22, 2010

Installing BackTrack Linux on a USB key with VMWare, the easy way

  1. Create a new virtual machine in VMWare. You do not need to add a hard disk. Just delete it, just in case. For the CD Rom add the iso image of BackTrack Linux.
  2. Start the virtual machine. You might need to edit boot in the BIOS, so press F2 to enter BIOS setup and set CD rom as the primary boot.
  3. Enable Removable Device in vmware so that it will show up as a USB disk on Backtrack
  4. When BackTrack loads open install.sh on the desktop.
  5. The installer should now automatically use your USB key as the primary disk for the install.
  6. Use default partitioning and install. Just Click OK.
  7. After a successfull installation, your USB key is ready to boot.
  8. Boot into Backtrack and login with root/toor - the default username and password

Jul 31, 2010

Enabling Lightbox on Google's Blogger


It's fairly simple. Just add a simple JavaScript to the template next to the Lightbox import.
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
jQuery.noConflict();
jQuery(document).ready(function() {
jQuery('#Blog1 a img[class!=icon-action]').parent().attr('rel','lightbox[imgs]');
jQuery('#Blog1 a img[class!=icon-action]').parent().attr('title','© Žan Kafol');
});
</script>
<script type="text/javascript" src="js/prototype.js"></script>
<script type="text/javascript" src="js/scriptaculous.js?load=effects,builder"></script>
<script type="text/javascript" src="js/lightbox.js"></script>
<link rel="stylesheet" href="css/lightbox.css" type="text/css" media="screen">

Jul 16, 2010

JavaScript: escape()

When you're sending a string through a GET request with javascript, you should obviously URL encode the string to ensure all characters get transmitted. The escape() function in javascript works fairly well, even when you're sending UTF-8 characters. But the + character is interpreted as a space in the GET request, so you need to handle it manually. Here's how I do it:
 msg = msg.replace(/\+/g,'%2B'); 
 geturl('ajax.get.php?msg='+escape(msg));
First, you do a global regex match for the plus character, replace it with it's url encoded equivalent, and then you url encode the string with escape().

Jul 12, 2010

Example usage of Facebook.streamPublish()

DUE TO FREQUENT FACEBOOK API CHANGES THIS ARTICLE IS OUTDATED.

You can force streamPublish dialog from within the href bar in the browser. Also note the application ID prefix in the functions. More detailed code description is superfluous. javascript:c=9999999;h='Click Challenge';l='http://apps.facebook.com/click-challenge-en/?ref_6w=f_clicks';a126752370697733_Facebook.streamPublish('',{'name':h,'href':l,'caption':'{*actor*} made '+(c/1)+' clicks in 10 seconds.','properties':{'Speed':{'text':(c/10)+' clicks/sec','href':l}},'media':[{'type':'image','src':'http://w6.6waves.com/my-app/data/126752370697733/logo.gif','href':l}]},[{'text':h,'href':l}]);

Mar 26, 2010

Solution for problem code FCTRL on SPOJ

#include <stdio.h>

int main() {
int s;
scanf("%d",&s);
while(s--) {
int r,c,x=0,p=1;
scanf("%d",&c);
do x += (r = c/(p*=5)); while(r);
printf("%d\n",x);
}
return 0;
}

Jan 18, 2010

PHP: calculate distance between two points

Each point is an one-dimensional array, each value in the array is a coordinate, so dimension of coordinates in this function is arbitriary.
 /*
 * Calculates Euclidian distance between two points in p-norm
 * Points $p1 and $p2 are Nx1 matrices
 */
 function euclidian_distance($p1,$p2) {
  if(count($p1) != count($p2)) return false;
  $distances = 0;
  
  $p1 = array_values($p1);
  $p2 = array_values($p2);
  
  $norm = count($p2);
  
  for($i=0;$i<$norm;$i++) $distances += pow(abs($p1[$i]-$p2[$i]),2);
  
  return pow($distances,1/2);
 }

Jan 8, 2010

Windows 7/Vista & ArcGIS & ESRI License Manager

It seems that ESRI License Manager has difficulties running in Windows 7 or Vista – the License server fails to start at boot or on demand in License Manager Tools.

Consequently, ArcGIS didn’t start because there was no license server running. Obviously this problem doesn’t occur if the license server is running on another machine in the network.

At first I tried the quick and dirty solution – to manually start the server daemon and see where it fails.

I ran Command Prompt as an administrator:

Untitled

Now, the server is called lmgrd.exe, so if you navigate to C:\Program Files\ESRI\License\arcgis9x and start lmgrd, it says that there is no license specified.

So I typed the location of the license (it was in the same folder), ran the program in the foreground:

lmgrd –c license.lic -z

I kept the command prompt open, and ArcGIS started succesfully.

But this isn’t really a long term solution, since this method would require manual server start in the command prompt everytime I would want to start ArcGIS.

So I thought, maybe the problem is that the server can’t find the license file. After some googling, I found out that the environment variable LM_LICENSE_FILE wasn’t set. It says on the support page that you’d need to enter port@machine-name for the variable value, but since we’re running the server on the local machine, you just need to enter your C:\Path\to\your\license.lic.

sd

When all goes well with License Manager Tools, you might still need to enter "localhost" in the ArcGIS desktop manager in the license server.

If anyone has a better solution or information, please post in the comments.

UPDATE:

After further experimentation I found out that you also need the Sentinel driver to successfuly run License Manager on Windows 7. Don't know why, but it works. You should install Sentinel driver first, then the license manager, so that everything for the license works before you install ArcGIS. That way you won't have to manually configure ArcGIS for license after it has been installed. You have less work that way.

Dec 25, 2009

Quick Tip: light switch effect

Here's a quick tip for novice programmers. Every time you want to create a "light-switch" effect for toggling a parameter on and off, or should I say true or false, 0 or 1, ... You can simply do it by typing:
p ^= 1;
This is a binary-safe Exclusive-OR assignment operator. First, it computes the value of p XOR 1 (p = p ^ 1) and then stores that value in p. If we look at the truth table of exclusive-or (XOR)

a

b

a XOR b

0

0

0

0

1

1

1

0

1

1

1

0

We see that if our b variable is 1 (true) the result of a ^ 1 (a XOR 1) is exactly the opposite of a. All in all, this operation is simply a shortcut for these assignments:
p = p ^ 1;

p = !p;

p = p ? false : true;

if(p) p = false; else p = true;

So if you want to toggle something ON and OFF, let's say when a user clicks a button, this method is extremely short and useful.

Dec 20, 2009

Facebook Connect: FB.Connect.streamPublish() does not show up

DUE TO FREQUENT FACEBOOK API CHANGES THIS ARTICLE IS OUTDATED.

Here are the reasons why FBJS functions sometimes fail:
  • xd_reciever.html is not installed correctly
  • application key is not set in FB.init()
  • Facebook Connect callback URL is not set in the application settings
  • Facebook JavaScript API is not set correctly in your HTML. This should be set immediately after the body tag <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js" type="text/javascript"></script> This should be set before the closing body tag <script src="http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php/en_US" type="text/javascript"></script>
  • Facebook functions are called before JavaScript objects are initialized. FB.init(api_key, channel_path); FB.ensureInit(function() { // put your functions here });
  • All Facebook JavaScript functions are called BEFORE the FeatureLoader.js.php You should put your functions after this call and into FB.ensureInit() function
  • There are JavaScript errors in your code
If any of the errors mentioned above are met, the function will fail. If FBML tags are not rendered, you might also want to check, if you set the HTML header correctly. http://wiki.developers.facebook.com/index.php/XFBML Also, XFBML tags are required to render tags correctly.

Sep 17, 2009

PHP: mail() Sender domain must exist - UPDATE

Regarding my last post, it seems that you can't set the Return-Path in the header parameter of the mail() function. The workaround is in the fifth argument of mail() - the additional parameters. If you set the "-fsender@domain.com" it should set the Return-Path. Here's my mail() wrapper function:
function construct_mail($to,$subject,$content,$sender='') {
$from = ADMIN_EMAIL;
if(!empty($sender)) $from = $sender;
$header  = "From: $from\r\n";
$header .= "Content-Type: text/html; charset=utf-8\r\n";
$header .= "Date: ".date("r")."\r\n";
$header .= "Reply-To: $from\r\n";
$header .= "Return-Path: $from\r\n";
$header .= "X-Mailer: PHP\r\n";
$content = ''.$content.'';
$subject = ' =?UTF-8?B?'. base64_encode($subject) ."?=";
return mail($to,$subject,$content,$header,"-f$from");
}
Also, the -f switch might trigger a E_WARNING if you don't set the trusted users (the user that executes the script - webserver) in the /etc/mail/trusted-users

PHP: mail() Sender domain must exist

Lately I've found out that a lot of emails sent from PHP's mail() get bounced (they weren't before). Servers bounce the message with the "Sender domain must exist" error, or more precisely, the domain in question was the servers (the server that the script runs on, not the email server) hostname. Well of course that domain doesn't exist (localhost.localdomain), so after some googling, I figured that some additional headers might help, like Return-Path and Reply-To.
$from = "your@email.com";
$header  = "From: $from\r\n";
$header .= "Content-Type: text/html; charset=utf-8\r\n";
$header .= "Date: ".date("r")."\r\n";
$header .= "Reply-To: $from\r\n";
$header .= "Return-Path: $from\r\n";
$header .= "X-Mailer: PHP\r\n";
I'll test it now, when this post reaches my newsletter subscribers. UPDATE: http://dev.kafol.net/2009/09/php-mail-sender-domain-must-exist.html

Aug 3, 2009

PHP: calculating age with no bugs

As it turns out, calculating a person's age is not a very simple thing to do.

I've been very lazy lately so I googled for a PHP or MySQL function to calculate age in years. The more I searched, the more I found out that people were doing it wrong.

For example: floor(time_difference_in_days) / 356, let's say 7000/356 = 19,66.

What the hell? That won't work. We have leap years and such.

And even worse: some calculated the difference in days with strtotime() or mktime() that uses unix timestamps, which is very unfortunate for people born before 1970-01-01. (if you don't know why, read the wiki)

I decided to do this the way that we humans do it. It's commented and streched out for a reason. Stop doing it wrong.
function age($dob) {
//year, month, day of birth
 list($y, $m, $d) = explode('-', $dob);
//this year,month, day
 list($yn, $mn, $dn) = explode('-', date('Y-m-d'));

//AGE is (THIS_YEAR - YEAR_OF_BIRTH) if the person already had or is having his birthday THIS_YEAR
 $age = $yn - $y;

//If the person didn't have his birthday yet, then AGE is (THIS_YEAR - YEAR_OF_BIRTH - 1)
 if ($mn < $m) {
//THIS_MONTH is less than MONTH_OF_BIRTH so no birtday yet this year!    
  $age--;
 } else {
//if it's the same MONTH_OF_YEAR then the birthday did not occur only if THIS_DAY_OF_MONTH is less than DAY_OF_BIRTH    
  if ($mn == $m) {
   if ($dn < $d) {
    $age--;
   }
  }
 }
 return $age;
}

Jul 31, 2009

ActionScript: fade in/out

function fadeAnimation(target,show,speed) {
 target.showing = show;
 target.speed = speed;
 if(show) target._visible = true;
 
 target.onEnterFrame = function() {
  this._alpha += (this.showing) ? +this.speed : -this.speed;  
  if(this._alpha<=0 && !this.showing) {
   this._visible = false;
   delete this.onEnterFrame;
  }
  if(this._alpha>=100 && this.showing) {
   delete this.onEnterFrame;
  }
 }
}

Jul 11, 2009

Windows Tips: How Be Safe From Viruses / Kako ostati varen pred virusi

English version | Slovene version

Here's a non-developing blog entry... So, how to be safe from viruses?

I get asked this question a lot lately (wish I knew why, is there a new dark age coming or something?), especially which Anti-Virus software should one use, to be 100% safe from viruses.

Well, I'm not a big fan of Anti-Virus programs (I do use one, for "just in case"), nor do I want to advertise such software and above all, I don't think that any program can ensure full security.

Here's why (sorry for the lecture):
Viruses exist for any Operating System (Windows, Linux, ...). They're not called the same on different operating systems, but they act the same. They have simmilar methods of reproduction, and so on. Making a virus is very easy, even if you are a beginner at programming, making a good virus is a bit harder, but not much. A virus is a program, like any other, but it does stuff it's not supposed to, and that's why it's flagged as being a virus (malicious). And because it's a program, detecting it may be difficult sometimes, because it's functions don't look as fishy as they actually are - the program does things any normal program would do, let's say connects to a server and communicates with it. A lot of programs do that. Your browser does that. Your browser could be a "virus" if it would let someone else have access to things they're not supposed to.

Okay, enough of that, let's get to the good part.

Here's a short list of 4 simple tips you should follow, and if you'll follow all of them, you'll quickly find out that you don't have any use of your Anti-Virus program anymore.
They mostly apply on Windows Operating systems, but the idea is general.
  1. Disable Auto-Run
    Disable it. Disable it for everything. For CDs, USB keys, everything. It's useless and it's a major security problem. It's also a VERY popular way of virus reproduction.
    If you don't know what Auto-Run is, read about it on the wiki, but in a nutshell, AutoRun is a Windows service that enables a computer to run a program automatically when you plug in your USB key or a CD/DVD. Running a program whitout knowing what it is is like jumping from a bridge. It's dangerous and it's very likely that you'll get hurt.

    I'll be short on How-Tos, but here are some links:
    Basically, you navigate to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Cdrom in your Registry, and set the AutoRun DWORD value to 0. You might also disable autoplay in your gpedit.msc - Local computer Policy\Computer configuration\Administrative Templates\System, select the item "Turn off Autoplay" and click the "Enabled" radio button.

    Also, if you don't know how to disable AutoRun, there is an alternative:
    If you hold the
    Shift key when you plug in a USB key/CD, you temporarily disable AutoRun.

  2. Use a firewall
    Firewalls come in many forms - there are physical firewalls, such as routers (but firewalling is not the router's primary function), and there are software firewalls.
    Firewalls block certain types of internet communication. They filter open ports which is also a very common way for virus reproduction:
    An infected machine connects through the internet to another vulnerable machine which has a vulnerable service running. But note that:
    • A computer is only vulnerable if it has a vulnerable service running
    • If the computer has no open ports (no services running) it cannot be infected/hacked via the internet.

    Which brings us to...
  3. Updates!
    A lot of people disable automatic updating (Control panel\System Properties\Automatic updates), because either they're afraid they might get that annoying little Windows Genuine Advantage tool or that they'll get viruses from it. Viruses from Microsoft updates?!?! Come on...
    Updates are in most cases a very good thing to do - if you don't care about security, you should at least care about the cool new features you get with the new version of any program. Programmers don't always get it right in the first try, that's why updates come in handy.

  4. Use your brain
    You heard me. Don't be stupid. Don't click on everything shiny, don't click on anything before reading what it is and understanding what it does. Don't open every email attachment. When you're browsing on the web, don't click on every link. Look at where it's pointing (in the status bar). If it's an .EXE file (a program) be extra careful, don't run it if you don't know what it is. KeyGens are NEVER what they say they are on the internet. Don't click on every "OK" or "I Agree" button. Some people think that when they suddenly have an unknown toolbar in their favourite browser, they have a virus. That's not true. They got that toolbar when they clicked on "I Agree" sometime in the near past without reading what it does.


Well that's all folks, I hope this article widens your horizon on computer security. Because I'm in an extra helping mood today, I'll translate the article for all of my Slovene friends.
Top
___________________________________________________________________________________

Zdaj pa en ne-programerski članek. Kako ostati varen pred virusi?

Zadnje čase dobivam to vprašanje zelo pogosto (ko bi le vedel zakaj, prihaja kakšna temna doba ali kaj podobnega?), še posebej: kateri Anti-Virus program naj bi uporabili, da bi bili 100% varni pred virusi.

Nisem ravno navdušen nad AntiVirus programi (sicer uporabljam enega "za vsak primer"), nimam niti želje oglaševati teh programov in povrh vsega, ne verjamem, da lahko program zagotovi popolno varnost.

Še razlog zakaj (oprostite za pridigo):

Virusi obstajajo za vsak Operacijski Sistem (Windows, Linux, ...). Ne kličejo se povsod enako, vendar obnašajo se isto. Imajo podobne načine razmnoževajna in tako naprej. Narediti virus je zelo lahko, tudi za začetnika programiranja. Narediti dober virus je malo težje, vendar ne veliko.
Virus je program, kot vsak drugi, le da počne stvari, ki jih nebi smel in zato je označen kot "virus". In ker je program kot vsak program je včasih zelo težko ga odkriti. Včasih so funkcije virusa zelo podobne običajnim programom, recimo, program se poveže na strežnik in z njim komunicira. Veliko programov to počne. Vaš brskalnik to počne. Vaš brskalnik bi lahko bil virus, če bi dovolil nekomu dostop do reči, do katerih nebi smel.

No, dovolj tega, preidimo do bistva.

Tukaj je kratek seznam štirih preprostih namigov, katerim lahko sledite, če pa upoštevate vse, lahko hitro ugotovite, da nimate več potrebe po uporabi antivirusnega programa.
Namigi so večinoma za Windows operacijske sisteme, vendar velja za vse.
  1. Izklopite Auto-Run
    Izklopite ga. Izklopite ga za vse. Za CD-je, USB ključke, vse. Neuporaben je in jezelo velik problem kar se tiče varnosti. Poleg tega je to zelo popularen način za samodejno razmnoževanje virusov.
    Če ne veste kaj je AutoRun, preberite o tem na Wikiju, v bistvu je pa to orodje operacijskega sistema Windows, ki omogoča samodejno zaganjanje programov, ko priklopite USB ključ ali CD/DVD v računalnik. Zaganjanje programov, brez vedeti kaj počno je kot skakanje čez most. Je nevarno in zelo verjetno je, da se boste poškodovali.

    Bom kratek pri navodilih kako to izklopiti, tukaj je pa nekaj povezav o tem: V registru pridete do mape HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Cdrom in nastavite AutoRun DWORD vrednost na 0. Dobro je tudi izklopiti autoplay v gpedit.msc - Local computer Policy\Computer configuration\Administrative Templates\System, izberite "Turn off Autoplay" in kliknite na "Enabled".

    Če ne znate izklopiti AutoRun, obstaja alternativa:
    Če držite tipko
    Shift, ko priklopite USB ključ ali CD s tem začasno izklopite AutoRun.

  2. Uporabljajte požarni zid
    Požarni zidovi obstajajo v različnih oblikah - obstajajo fizični požarni zidovi kot so usmerjevalniki (vendar požarni zid ni glavna funkcija usmerjevalnika), obstajajo pa tudi programski požarni zidovi. Požarni zid blokira določene vrste komunikacije prek iterneta. Filtrirajo odprta vrata kar je tudi zelo razširjen način razmnoževanja virusov:
    Okužen računalnik se poveže na ranljivega prek interneta, na katerem teče ranljiv program. Vendar pomnite:
    • Računalnik je ranljiv samo, če na njim teče ranljiv program
    • Če na računalniku ni odprtih vrat, potem ta računalnik ne more biti okužen preko interneta / vanj se ne da vdreti preko interneta.

    Kar nas privede do...
  3. Posodabljanje!
    Veliko ljudi izklopi avtomatično posodabljanje (Nadzorna plošča\Sistem\Avtomatične posodobitve). Ali se bojijo, da bodo s tem dobili tisto nadležno Windows Genuine Advantage orodje, ali pa da bodo s tem dobili viruse. Virusi pri posodabljanju Microsoft?!?! Dajte no...
    Posodabljanje je v zelo veliki večini primerov zelo dobra stvar - če vas ne zanima varnost na računalniku, vas bi lahko vsaj zanimale vse nove in kul funkcije, ki jih dobite z novo verzijo programa. Programerji ne zadenejo vse v prvo, zato pridejo posodobitve zelo prav.

  4. Uporabljajte možgane
    Prav ste me slišali. Ne bodite neumni. Ne klikajte na vse kar se sveti, ne klikajte na karkoli, predno preberete kaj piše in razumete kaj bo stvar storila. Ne odpirajte vsake priponke v spletni pošti. Če brskate po spletu, ne klikajte na vsako povezavo, poglejte kam kaže (na dnu programa piše). Če je povezava .EXE datoteka (program) bodite še posebej previdni, ne zaganjajte ga, če ne veste kaj bo storil. KeyGeni niso NIKOLI kar pravijo da so na internetu. Ne klikajte na vsak "V redu" ali "Strinjam se" gumb. Nekateri mislijo, da ko se na njihovem priljubljenem brskalniku nenadoma pokaže nova orodna vrstica, da je to virus. To ni res. To orodno vrstico so dobili, ker so v nedavni preteklosti kliknili na gumb "Strinjam se", brez da bi prebrali kaj piše.

No, to je to, upam da vam ta članek razširi obzorje računalniške varnosti.
Vrh