People always want this, so here's something I came up with that covers everything in a safe and friendly way.  It has been tested.
Code:
#!/usr/bin/perl
# ------------------------
# Set these five variables
# ------------------------
# the name of this file/page (CHMOD 755 or 777)
$uploader = "upload.cgi" ;                
# the server path where you want the files uploaded (no trailing slash)
$path  = '/home/user/public_html/images' ;
# the http link to where the files are uploaded  (no trailing slash)
$url   = 'http://domain.com/~user/images' ; 
# minimum allowed file size in kbs
$minsize  = "10"  ;
# maximum allowed file size in kbs
$maxsize  = "200" ;
# ------------------------------------------------------------ #
# --------------- Do Not Edit Below This Line ---------------- #
# ------------------------------------------------------------ #
use CGI::Carp qw(fatalsToBrowser);
use CGI qw(:standard);
print "Content-type: text/html\n\n";
# ----------------------------------- #
$HEAD = <<EOM;
<html>
  <head>
    <title>Image Uploader</title>
  </head>
  <body>
    Image Uploader
    <font face="courier new">
      <pre>
EOM
$FOOT = <<EOM;
      </pre>
    </font>
  </body>
</html>
EOM
# ----------------------------------- #
$upload = param('upload');
if ($upload eq 'yes') {
  &page2();
}
else {
  &page1();
}
# ----------------------------------- #
sub page1 {
print <<EOM;
  $HEAD
    <FORM METHOD="POST" ACTION="$uploader" ENCTYPE="multipart/form-data" >
      <input type="file" name="pic" size="48">
      <input type="hidden" name="upload" value='yes'>
      <input type="submit" value='Upload!'>
    </FORM>
  $FOOT
EOM
exit;
}
# ----------------------------------- #
sub page2 {
$pic = param('pic');
if ( (!defined $pic) || (!$pic) ) {
  &page1();
}
elsif ((lc($pic) !~ /(\.jpg)+$/) && (lc($pic) !~ /(\.gif)+$/)) {
  &at_oops('JPG or GIF only');
}
else {
  $basename = &prep($pic);
  # ---
  open (OUTFILE, ">$path/$basename") || die("Could not open file!") ;
  binmode OUTFILE;
  while ($bytes = read($pic,$buffer,1024)) {
  $size += $bytes;
  print OUTFILE $buffer;
  }
  close(OUTFILE);
  # ---
  $size = sprintf("%d", $size / 1023 );
  if ( (!defined $size) || (!$size) ) {
    unlink("$path/$basename");
    &at_oops('No file size!');
    $basename = undef ;
  }
  elsif ( ((stat "$path/$basename")[7] < $minsize) || ($size > $maxsize) ) {
    unlink("$path/$basename");
    &at_oops('Improper file size!');
    $basename = undef ;
  }
  else {
    $success = 1;
  }
  # ---
}
if ($success) {
print <<EOM;
  $HEAD
    image : $pic
    size  : ${size}k
    link  : <a href="$url/$basename">$url/$basename</a>
  $FOOT
EOM
exit;
}
else {
  &at_oops('No upload');
}
}
# ----------------------------------- #
sub at_oops {
print <<EOM;
  $HEAD
    $_[0]
  $FOOT
EOM
exit;
}
sub prep {
    $_ = $_[0];
    s/\w://;
    s/([^\/\\]+)$//;
    $_ = $1;
    s/\.\.+//g;
    s/\s+//g;
    s/À|Á|Â|Ã|Ä|Å|Æ|à|á|â|ã|ä|å|æ/a/g;
    s/È|É|Ê|Ë|è|é|ê|ë/e/g;
    s/Ì|Í|Î|Ï|ì|í|î|ï/i/g;
    s/Ò|Ó|Ô|Õ|Ö|Ø|ð|ò|ó|ô|õ|ö|ø/o/g;
    s/Ù|Ú|Û|Ü|ù|ú|û|ü/u/g;
    s/¥|Ý|ý|ÿ/y/g;
    s/_//g;
    s/ß/b/g;
    s/Ç|ç/c/g;
    s/Ð/d/g;
    s/Ñ|ñ/n/g;
    s/Þ|þ/p/g;
    s/\$/s/g;
    s/(\.\w{3})$//;
    $extension = $1;
    s/\W//g;
    $_ .= $extension;
    $returnvalue = lc($_);
}
# EOF
I hope the forum posts it properly.  You should be able to copy and paste and just use it.