Tuesday, July 15, 2008

3) One image/page

This is the first method I recall using to look at .pdf files from the command prompt. Basicly, it simply uses Ghostscipt to convert a page into a graphic, and then view it with zgv, an SVGAlib based image viewing tool. When I rethought this through a few days ago, and set it up as the current script below, I modified it to handle more than one page, and in the process, studied capabilities of zgv I was only vaguely aware of.

    Basicly, zgv has two modes of operation
  • Browser Mode, capable of navigating and operating within the file system
  • Viewer Mode
      The viewer mode has two self explanitory subdivisions
    • Single image mode
    • Slide show mode

    Some of the key underdocumented commands. These are just the ones I think most important not in the help mode.
  • ? - context sensitive (but incomplete) help mode
  • u - create thumbnails for use in browse mode
  • n/t - un/tag image files
  • N/T - un/tag all image files
  • ^I (TAB) - Kick into slide show of all tagged files
  • Return - Go from browse mode to viewing mode for an individual image
  • Escape - Go from viewer mode back to browse mode
  • Alt-f - show number of image files and tagged image files in the current directory
  • : - show details about image file cursor is on

zgv may not be the GIMP or Photoshop, but it has much more capability than to simply throw an image on a console screen. I call the script below pdfgsview.


#!/bin/bash  -


# ############## security pack ##############################

PATH='/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/usr/local/sbin:/usr/local/bin:/usr/games:~/bin'  ;


hash -r  ;
#  -  Bash Cookbook, 1st ed.,, #14.5

ulimit  -H -c 0 --  ;
#  -  Bash Cookbook, 1st ed.,, #14.6

IFS=$' \t\n'  ;
#  -  Bash Cookbook, 1st ed.,, #14.7

UMASK='002'  ;
umask  $UMASK  ;
#  -  Bash Cookbook, 1st ed.,, #14.8

\unalias -a
#  -  Bash Cookbook, 1st ed.,, #14.4

# ############## security pack ##############################

set -e  ;
shopt -s  nocasematch    expand_aliases  ;

alias RM='/bin/rm -f  2> /dev/null '  ;
alias MKDIR='/bin/mkdir  2> /dev/null '  ;
alias LS='/bin/ls -A  2> /dev/null '  ;
alias WC='/usr/bin/wc -l  2> /dev/null '  ;
alias GS='/usr/bin/gs'  ;
alias EZGV='exec   /usr/bin/zgv'  ;

USAGE="$0  -h | file.pdf | file.ps"  ;

VERSION='$Id: pdfgsview,v 1.3 2008/07/08 11:22:38 dallas Exp dallas $'  ;

THEPDFFILE=${1}  ;

case  ${THEPDFFILE}  in
[-/][h?]* )
  echo ${USAGE}  ;
  exit  ;
  ;;
[-/]v* )
  echo ${VERSION}  ;
  exit  ;
  ;;
*.ps )
  THETAG=${THEPDFFILE%.ps}  ;
  ;;
*.pdf )
  THETAG=${THEPDFFILE%.pdf}  ;
  ;;
* )
  exit  ;
esac


if [ ! -f ${THEPDFFILE} ]  ; then
   echo 'File needed'  ;
   echo ${USAGE}  ;
   exit  ;
fi

if [[  ${THETAG} == */* ]] ; then
  THETAG=${THETAG##*/}  ;
  fi  ;

THEDIR1='/tmp/pdfgsimages'  ;
THEDIR2="${THEDIR1}/${THETAG}"  ;
THEFILES="${THEDIR2}/${THETAG}.%03d.png"  ;

for ii in ${!THEDIR*}
do
if [ ! -d ${!ii}  ] ; then
  RM      ${!ii}  ;
  MKDIR   ${!ii}  ;
fi  ;
done  ;

RM  ${THEDIR2}/*  ;

#  THETEMP="/tmp/${THETEMP##*/}"  ;
RM     ${THEDIR2}/*.png  ;

GS -SDEVICE=png16m -sOutputFile=${THEFILES} -  ${THEPDFFILE}    <<QUIT
QUIT

count=$( LS ${THEDIR2} | WC )  ;

case ${count}  in

1 )
  EZGV    ${THEDIR2}/*.png  ;
  ;;

* )
  EZGV     ${THEDIR2}/  ;
  ;;

esac  ;

exit  ;

The 'security pack' mentioned above are some suggested actions to improve script security mentioned in the O'Reilly 'bash Cookbook'. There are others in the book, but these I judged 'no-brainers', in that they can simply be included and don't seem to even require understanding or any modification to use.

Sunday, July 13, 2008

2) As text

One approach to viewing .pdf files is presented in the O'Reilly book http://oreilly.com/catalog/9780596009113/index.html|"Linux_Desktop_Hacks". In the first edition, Hack #53, p. 170, "Display PDF Documents in a Terminal", gives a script that uses pdftohtml and elinks to view the text in pdf documents. Below is my variation on their viewpdf, I call it pdfview.


#!/bin/bash  -


#  per ORA  Linux Desktop Hacks  #53
#  with the following line added to '/etc/mailcap':
#  application/pdf; /usr/local/bin/pdfview '%s'; needsterminal; description=Portable Document Format; nametemplate=%s.pdf
# $Id: pdfview,v 1.5 2008/07/14 02:19:18 root Exp root $


#  pdftohtml -q -noframes -stdout ${1} | elinks -force-html
# does not work: pdftohtml -q -stdout ${1} | elinks -force-html

ABSOLUTE=${1:0:1}  ;

case ${ABSOLUTE} in
/ )
  PREFIX=''  ;
  ;;
* )
  PREFIX="${PWD}/"  ;
  ;;
esac

WORKFILE="$(mktemp -p /tmp XXXXXXXX).html"  ;
while [ -a ${WORKFILE} ]
do
  WORKFILE="$(mktemp -p /tmp XXXXXXXX).html"  ;
done

#     -- apparently pdftohtml requires the file end in '.html'

SOURCEFILE="${PREFIX}${1}"  ;

cd /tmp

pdftohtml  -q -nodrm  "${SOURCEFILE}"   ${WORKFILE##*/}  ;

exec elinks -force-html   ${WORKFILE}  ;

Saturday, July 12, 2008

1) General info

Doing a 'man -k pdf' generated a list of pdf related data for my Debian system. One that stood out was pdfinfo.

/usr/bin/pdfinfo -meta -box  <filename>

Seems to generate most of the info you'd want about a pdf, but one exception I noticed was nothing on the number and types of embedded images. It also seemed to need some blank lines thrown out to keep all the information together.

Thursday, July 10, 2008

Window Beyond a Plateau, Window Into Windows

I recently had reason to use VNC, Virtual Network Computing and then while using GRML, noticed something, a mention of a VNC client, that aroused my curiosity, and made me decide to do some googling on the subject. A search of the Debian packages turned up a couple of 'console' based VNC clients that did not require X. These obviously would need some kind of graphical interface, but in the case of svncviewer and directvnc, these were SVGAlib and framebuffers respectively.

Not using a framebuffer on my PC, I installed svncviewer and tried using it. At first it didn't seem to work, but studying the error messages it gave, there was some hint that the graphic modes available for it weren't in line with what the VNC server needed. I was puzzled at first, trying various parameters suggested by the svncviewer man pages, but then remembered that there was a configuration file for SVGAlib, /etc/vga/libvga.config in the case of my Debian computer. I edited this, loosening up everything I could as far as the video went to allow the maximum resolutions suggested by the comments in the file.

This worked great, svncviewer began working, connecting to both Linux X desktops and Windows boxes. The act of editing this configuration file jogged my memory that when I'd originally started using SVGAlib on the computer I was using a monitor already long obsolete when I took possesion of it, and had finally gave out and had been replaced with something more reasonably up to date. In other words, updating the SVGAlib settings was long overdue.

The most obvious initial problem was that the mouse seemed impossibly difficult to work with on the virtual console used by svncviewer. With adjusting the SVGAlib video settings so fresh in mind, I tinkered with the mouse settings in the config file. Part of the problem was that I'd try to move the mouse slightly and it would jump to the other side of the screen or do other crazy things, only occasionally doing what was desired. This all apparently fell under the description of 'accleration' from what I could figure out from the configuration file notes. Without going into specifics, which will undoubtedly differ from case to case, I found I could adjust the trip point and amount of 'accleration' to make the mouse move smoothly, problem solved. These settings solved problems with applications other than svncviewer, notably the links2 browser. Now the mouse was more usable with it as well, and the higher resolution put more of a web page on the screen at one time.

As a test for using this in the real world, there was a MS Window machine I needed to start using, but real world phyisical deskspace is at a premium. I managed to get the machine connected, reasonably close to my personal desktop workstation, and then get a VNC server installed on it. VNC doesn't seem to do anything to link up the audio I/O, only video, keyboard and mouse/pointer, so I connected it to my workstation with some 99 Cents only audio patch cords in addition to putting on the Ethernet LAN. (Anyone know of any 'virtual patchcord' application that could replace these?) On boot up, the VNC connection seemed to start early enough to catch request for a 'Ctl-Alt-Del' entry to get to the graphical login prompt. This I had to reach over and enter from the Windows machine keyboard, but everthing else has seemed to work one way or the other from the svncviewer. Some online documents hinted at possible problems for svncviewer connecting to Windows boxes due to some palete problem, but that doesn't seem to happen with the version I have installed. Using everything involved, I've been able to use the Skype client on the Windows machine to place and recieve calls, and fire up FireFox on it, and set up/handle an account for one of my bills online.

There was some mention online of a bootable Linux floppy disk with svncviewer on it, for an ultra-light X desktop, and I've conducted some experiments with setting svncviewer up on a console in /etc/inittab. (This last might require some addition to the autologin script, putting some sleep delay to prevent excessive respawning from inittab triggering a temporary lock on the virtual console if the server it's pointed at isn't immediately available, but seems like a problem that can be dealt with.) At the very worst, svncviewer provides a remote monitor, with occasional need to get the actual keyboard of the machine you connect to. So far I haven't found F8 or any other keyboard combinations to get to any menus or whatever, as was suggested for other VNC viewers, but this can be dealt with. But basicly, it works. It has me thinking about setting up an X/GUI server.

Friday, July 4, 2008

A Summer Day's Thoughts on Prague Spring

Being the Fourth of July, it seems particulary appropriate to mention a few updates on my earlier post, http://isthereanotherquestion.blogspot.com/2007/12/streetnoise.html.

A few YouTube videos I'd linked to have been removed, no great loss, since there were several to choose from anyway. But...

A couple of more videos have been put up for music off Streetnoise, one hardly qualifying as a "video", but the other, is quite different. The creator put some effort into matching up some news footage of the time with "Czechoslovakia", documenting a 'loss of independence day'. I thought this was important enough to call attention to it in this seperate blog notice, to call attention for a few minutes today to the memory of Alexander Dubcek. He might not be another Milton Friedman or Ludwig von Mises, but he figured out a few decades before Mikhail Gorbachev that 'the system' was not working. For this he belongs in the international pantheon of freedom lovers, along with Jefferson, Adams, Franklin etc.

Wednesday, July 2, 2008

Windows and Cups

These are some notes I came up with a few years ago, for connecting Windows machines to CUPS printer servers. This may have been on my web site or somewhere at one time, and I just wanted to make it available for reference.




Install the CUPS daemon on the printer server computer.
Configure the printer via the web interface at

http://localhost:631/

This is not covered by this document but the web
interface is fairly straight forward.

On the CUPS printer server
*************************

a) On the CUPS printer server
   make some changes to the CUPS config per
   http://www.faqs.org/docs/Linux-mini/Debian-and-Windows-Shared-Printing.html
   on the CUPS server.

   1) in /etc/cups/mime.convs
      uncomment:
      application/octet-stream   application/vnd.cups-raw   0   -

   2) in /etc/cups/mime.types
      uncomment:
      application/octet-stream

   3) In /etc/cups/cupsd.conf per
      http://localhost:631/documentation.html
      This is using the suggestions in the Linux Cookbook,
      by Carla Shroder, ORA, p. 247
      and somewhat more restrictive than the suggestions
      by the mini-Howto referenced above, and needed for
      all clients anyway, whatever the OS the clients run:

      LogLevel info

      Port 631

      Put:

      <Location /printers>
      Order Deny,Allow
      AuthType None
      Deny From All
      Allow From 127.0.0.1
      Allow From 192.168.1.*
      #    -- or whatever is appropriate for the LAN
      </Location>


At the windows end:
*********************

b) get the ethernet cable to it  :-)

c) make sure the Internet Printing Services is installed
   (from Linux Cookbook, by Carla Shroder, ORA p. 249
   This will require the Windows installation CD
   For Windows 95/98 this can be downloaded from
   http://www.microsoft.com/windows98/downloads
   look for "Internet Print Services", wpnpins.exe

   Windows ME is in the Add-on folder on the installation CD

   Windows NT, go to Control Panel -> Network -> Services tab
   -> Add Microsoft TCP/IP Printing

   Windows 2000/XP go to Network and Dial-up Connections ->
   Advanced Menu -> Optional Networking Components ->
   Other Network File and Print Services

   If it acts squirrely when you try to install the driver,
   it may be because the driver is already installed,
   either by default on OS installation/upgrade or perhaps
   someone else took care of it.

d) go to printer/fax setup on the windows machine,
   add a new printer, select network printer, enter the URL
   for example:

   http://192.168.1.1:631/printers/theprintername

   or if DNS resolution is available to the print server

   http://www.somewhere.com:631/printers/theprintername

   and finish up.

   Breakdown of this URL:


         IP address or name of the CUPS printer server
         as needed/appropriate.

         '631' is the port of IPP and http interface to the
         CUPS server on typical CUPS installation

         '/printers/'  the directory the printers appear
         to be in, probably defined by the <Location...>
         statement mentioned above in a.3 .
         This seems to be a typical setting for this printer.

         'theprintername' points it the printer on that server
         a fairly arbitrary name defined in the CUPS configuration
         of the printer (not covered in this article,
         but just handled at the web interface in
         http://localhost:631/)

         I saw this stuff in a comment at:
         http://www.linuxjournal.com/article/8618

d) select the printer model (HP LaserJet 6P in this case)
   and things are ready to rock&roll....

Thursday, June 26, 2008

Lynx HTTP EXTERNAL Menu Script

One thing keeping my friend Larry from getting the most out of my usnatch program and Lynx externals is awkwardness he has in dealing with the EXTERNAL selection menus. He is blind and this coupled with many of the long, complex URLs, (in many cases having stretches of random hash characters) that are passed to the Lynx EXTERNAL menu for special handling make it hard for him to seperate out the choices the menu presents. He literally can't wade through the URLs to get to the menu selection options. This is different from many of the other Lynx menus, where simple brief descriptions of the choices are given, without interjecting the names of temporary files and such into the options to confuse the issues.

To try and deal with this problem, I present a bash script below to replace a collection of Lynx EXTERNAL entries for http with a single entry, that presents a simplified menu. This whole idea is a variation on what I documented in my article Lynx/Kermit Coordination Part I hosted by the Kermit Center at Columbia Univesity. This script will have to be customized, and a seperate one would have to be created for other protocols such as ftp, ssh, irc and such. I've put extensive notes in this script, since I think it makes explination simpler if the notes are close to the subject instead of before or after in this blog's narrative. Also, the people using it might not be familiar with bash, so I try to explain as much as I can, so they can knowledgably change it to their needs.

To install this script, first make sure your version works from the command promt. Then comment out all the

EXTERNAL:http:....

statements in your lynx.cfg file, both any in your home directory, and those in /etc/ and it's subdirectories, adjust the script to include those possibilities you want in it, and put a single EXTERNAL statement:

EXTERNAL:http:extern.menu %s:TRUE

Where extern.menu is taken to be the name of the menu script.

I've put a copy of this script online at a Yahoo group for Larry's friends, http://groups.yahoo.com/group/larryhsfriends/


#! /usr/bin/env bash
#  #!/usr/bin/bash  -

#  '#! /', env per
#  'bash Cookbook', 1st edition, recipe #15.1, p. 321
#  "Finding bash Portably for #!"
#  http://www.bashcookbook.com
#
#  trailing '-' per
#  'bash Cookbook', 1st edition, recipe #14.2, p. 283
#  "Avoiding Interpreter Spoofing"

#  the first line convention points to the intepretor to be used.

#  Some bash conventions for beginners:
#
#  hash/pound/sharp/octhorps to the end of line are comments.
#
#  Lines ending exactly with a backslash, '\', are continued
#  with the next line.
#  Trailing whitespace after the backslash can cause errors,
#  so beware of it.
#
#  I urge you to look up aspects of this script,
#  either with man bash, or if you are running bash
#  at your command prompt, with the help command
#  such as 'help case' or 'help select'.

URL="${1}"  ;

PS3='What EXTERNAL action do you want? '
#         -- defaults to '#?'
#            trailing blank desirable for spacing of response
#            from prompt
#            PS3 is the Select Menu Loop prompt in bash

#  Note 'for' statement like syntax of select:

select external_action in       \
      'Quit externals                                              '          \
      'Print the URL'           \
      'USnatch'                 \
      'lynxvt'                  \
      'screened-lynx'           \
      'javascript-links2'       \
      'graphical-links2'        \
      'W3M'                     \
      'links'                   \
      'elinks'                  \
      'Blogspotviewer'          \
      'lynx-noreferer'          \
      'lynx-nofilereferer'      \
      'Privoxy Control Panel'   \
      'Microbookmarker'         \
      'wget'                    \
      'Bug-Me-Not'              \
      'whomis'                  \
      'nspeep'                  \
      'pingvolley'              \
      'lynxtab'                 \
      'lynxtab-blank'           \
      'lynx-blank'              \
      'frys'                    \
      'bash'

#    Note: the last select menu item should not and a trailing
#    '\' to continue on to the next line.
#    I've placed each menu item or quoted phrase on a seperate
#    continuation line.
#    At this point, it is normally desirable to have one menu item
#    for each of the case statement stanza's below.
#    They don't need to be in order.
#    There just has to be a menu prompt item
#    and a case "whatever )" that match
#    so the case stanza can be triggered.
#    Be careful in using '*' 'splat' patterns,
#    that you do not unintentionally match more than
#    the desired pattern by mistake.
#    This could accidently short circuit desired action,
#    keeping a case stanze from being taken when wanted,
#    and causing another to be taken instead.
#    If all the menu items are short, select will try to put
#    them in multiple columns.
#    Only one item needs to be wide, (which can be because of trailing
#    blanks) to trigger single column menu display.
#    In this case, I used the 'Quit' item to do this with,
#    since it is basicly matched for the most part with a '*'
#    keeping the line in the case statement a reasonable length.
#    The menu items are only needed to clue the user on the
#    significance of each number chosen,
#    and to tie that to the case stanza.
#    Alternatively, you can keep the menu items in a strict order,
#    and use 'REPLY' for the case variable, in which case
#    each case stanza would be picked on the basis of the
#    number selected from the menus instead of patterns
#    that match the menu item strings.
#    In this case, ordering is critical.

#    Many of these actions are special purpose scripts I have
#    written and are included here just to provide a realistic
#    example.
#    The size is probably excessive for some people.
#    This script will certainly have to be customized to your
#    personal needs.

do

  case ${external_action} in

  #  item between 'case' and 'in' undergoes
  #  several levels of evaluation before
  #  the case statement is finally executed.

  #  Case stanza's start with
  #  string_to_match )
  #  list of actions ;
  #  break  ;   # include a break statement to break out of the
  #             # select menu loop
  #  ;;    #  double semicolons  end actions and stanza
  #

  Q* )
    echo 'Returning to browsing'  ;
    break  ;
    #  Thumb rule in this sort of script is
    #  that a break is needed whenever there
    #  is no exec statement in a case stanza.
    #  This stops the select loop after a decisive action.
    ;;

  P* )
    read -p "The URL in question: ${URL} "  TRASH  ;
    break  ;
    ;;

  USnatch )
    exec    usnatch  ${URL}  -i -p  ;
    #  break is not needed after an exec statement
    #  because this script's process, including
    #  the select loop is replaced
    #  by the action of the exec statement,
    #  ending the select loop.
    #  You could put a break after each exec,
    #  it would probably be excessively cautious,
    #  since it would only be executed under bizarre conditions.
    ;;

  lynxvt )
    #  exec    lynxvt  ${URL}  &  ;
    exec    lynxvt  ${URL}    ;
    ;;

  screened-lynx )
    screen -t 'lynx ...' lynx   \
        -useragent='Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)'  \
        ${URL}    ;
    break  ;
    ;;

  javascript-links2 )
    screen -t 'jlinks'  \
        links2 -enable-javascript 1 -html-numbered-links 1  \
        ${URL}    ;
    break  ;
    ;;

  graphical-links2 )
    sudo links2 -g -driver svgalib -mode 640x480x256   \
        -enable-javascript 1 -html-numbered-links 1    \
        ${URL}    ;
    break  ;
    ;;

  lynx-noreferer )
    exec  lynx -noreferer=off -tna ${URL}    ;
    ;;

#    start of a typical case stanza:
  lynx-nofilereferer )
    exec  lynx -nofilreferer=off -noreferer=off -tna ${URL}  ;
    ;;
# end of the typical case stanza

  Privoxy* )
    screen -t 'Privoxy Control Panel'   \
      lynx -nofilereferer=off -noreferer=off  \
      -tna 'http\://config.privoxy.org'   ;
    break  ;
    ;;

  Microbookmarker )
    exec  microBkMrk ${URL}  ;
    ;;

  Blogspotviewer )
    exec  blogspoter ${URL}  ;
    ;;

  [Ww]3[Mm] )
    exec  w3m ${URL}  ;
    ;;

  links )
    exec  links ${URL}  ;
    ;;

  elinks )
    exec  elinks ${URL}  ;
    ;;

  wget )
    exec  nohup wget  --background -a ~/wget.log -P /mnt/hda8/  ${URL}  ;
    ;;

  Bug-Me-Not )
    screen -t Bug-Me-Not   \
       lynx -cookies www.bugmenot.com/view.php?url=${URL}  ;
    break  ;
    ;;

  whomis )
    exec  whomis  ${URL}  ;
    ;;

  nspeep )
    exec  nspeep  ${URL}  ;
    ;;

  pingvolley )
    exec  pingvolley  ${URL}  ;
    ;;

  lynxtab )
    exec  lynxtab  ${URL}  ;
    ;;

  lynxtab-blank )
    exec  lynxtab    ;
    ;;

   lynx-blank )
    exec  env -u HTTPS_PROXY='' lynx -tna -accept_all_cookies    ${URL}  ;
    ;;

  frys )
    #  to send pdf's straight to a printer
    #  this script has mainly been used for Fry's Electronics
    #  online version of their newspaper ads.
    exec  lprfrys  ${URL}  ;
    ;;

  bash )
    #  this is just to explore the environment that the
    #  externals run in
    exec  bash -i  ;
    ;;

  * )
    # if something unexpected happens,
    # this catchall stanza should simply end the script.
    # '*' matches anything at all, after all other
    # patterns have been given a chance to match.
    # it is customary to include this
    # at the end of bash case statements.
    break  ;
    ;;

  esac     #  'case' backwards marks the end of the case statement

done       #  this done statement marks the end of the select menu loop

exit  ;  #  just to make sure!  :-)