Fun HP printer hack using HP-PJL control codes

Cecil

19+ years progress programming and still learning.
Yesterday I was off from work and I saw a fun little hack program which changes the default "READY" message on the LCD screen of an HP printer. So I created 4GL/ABL program using sockets to send the necessary PJL control codes.

Once the code was written I VPN to my work's network and played a little trick on my colleges by randomly changing the printers default message 'READY' to a random message (see code).

Have fun.

HPPrinterFun.p
Code:
/* Sample 4GL Socket Programming Code for Client Side*/
DEFINE VARIABLE clientSocketHandle  AS HANDLE NO-UNDO.
DEFINE VARIABLE sockectData         AS MEMPTR NO-UNDO.

/** Change the settings here..**/

&SCOPED-DEFINE xPrinterHost 192.168.1.17
&SCOPED-DEFINE xPrinterPost 9100


/*--------------------------------------------------------*/
/* Create socket and connect to HP Printer */
/*--------------------------------------------------------*/
CREATE SOCKET clientSocketHandle.
clientSocketHandle:CONNECT('-H {&xPrinterHost} -S {&xPrinterPost}':U) NO-ERROR.
IF clientSocketHandle:CONNECTED() = FALSE THEN
DO:
    MESSAGE 'Unable to Connect'.
    RETURN.
END.

clientSocketHandle:SET-READ-RESPONSE-PROCEDURE('readSocketData':U).

RUN sendRandomMessage.

REPEAT ON STOP UNDO, LEAVE ON QUIT UNDO, LEAVE:
    IF clientSocketHandle:connected() THEN
        WAIT-FOR READ-RESPONSE OF clientSocketHandle PAUSE 5.
    ELSE
        LEAVE.
END.

/*--------------------------------------------------------*/
/* At this point, you have exited the repeat block above, */
/* so you disconnect the socket, clean up the socket */
/* handle, release any memory allocations and then exit */
/* the program */
/*--------------------------------------------------------*/
clientSocketHandle:DISCONNECT() NO-ERROR.

DELETE OBJECT clientSocketHandle.
SET-SIZE(sockectData) = 0.

RETURN.

PROCEDURE readSocketData:
    DEFINE VARIABLE cTime           AS CHARACTER NO-UNDO.
    DEFINE VARIABLE iMessageSize    AS INTEGER   NO-UNDO.

    IF SELF:CONNECTED() EQ FALSE THEN
        RETURN.

    iMessageSize = SELF:GET-BYTES-AVAILABLE( ).

    SET-SIZE(sockectData) = 0.
    SET-SIZE(sockectData) = iMessageSize.

    SELF:READ(sockectData,1,iMessageSize,2) NO-ERROR.

    MESSAGE get-string(sockectData,1).

    SET-SIZE(sockectData) = 0.

    RETURN.
END PROCEDURE.

PROCEDURE writeSocketData:

    DEFINE INPUT PARAMETER socketASCIIData  AS CHARACTER NO-UNDO.
    DEFINE VARIABLE dataLength              AS INTEGER   NO-UNDO.

    dataLength = Length(socketASCIIData,'RAW').
    SET-SIZE(sockectData)       = 0.
    SET-SIZE(sockectData)       = dataLength.
    SET-BYTE-ORDER(sockectData) = BIG-ENDIAN.

    MESSAGE socketASCIIData.

    PUT-STRING(sockectData,1, dataLength) = socketASCIIData.
    clientSocketHandle:WRITE(sockectData,1,dataLength) NO-ERROR.

    SET-SIZE(sockectData) = 0.

    RETURN.
END PROCEDURE.

FUNCTION RandomMessage RETURNS CHARACTER():

    DEFINE VARIABLE randomMessages AS CHARACTER   NO-UNDO.
    DEFINE VARIABLE randomEntry    AS INTEGER     NO-UNDO.

    randomMessages = 'READY,BUZZ OFF,TOUCH ME,STEP AWAY,SET TO STUN,ANSWER 42,GUS DRINKS BEER,FEED ME,GO AWAY,NEED MORE SPACE,POUR ME A DRINK,IN DISTRESS,OPENEDGE ROCKS,NICE SHIRT,GO AWAY,NO PRINT FOR YOU,RADIATION LEAK,HANDS UP,PRESS MY BUTTON,TAKE ME HOME,LOOKS LIKE RAIN,HELLO WORLD,NICE HAIR,NEED A MINT?,BE GENTLE,BE KIND,INSERT DISK,BUY ME LUNCH,DONT STOP,COME CLOSER,TAKE A BREAK,INSERT $2,BLACK SABBATH,GETTING HOT':U.
   
    IF MONTH(TODAY) EQ 12 THEN
        randomMessages = randomMessages + ',MERRY XMAS':U.

    IF MONTH(TODAY) EQ 1 AND DAY(TODAY) GE 1 AND DAY(TODAY) LE 5 THEN
        randomMessages = randomMessages + ',HAPPY NEW YEAR':U.

    randomEntry = RANDOM(1, Num-entries(randomMessages)).

    RETURN Entry(randomEntry, randomMessages).
END FUNCTION.

PROCEDURE sendRandomMessage:
    DEFINE VARIABLE chData AS CHARACTER   NO-UNDO.

    Run writeSocketData(INPUT '~033%-12345X@PJL JOB~r~n':U).
    Run writeSocketData(INPUT SUBSTITUTE('@PJL RDYMSG DISPLAY="&1"~r~n':U, RandomMessage()) ).
    Run writeSocketData(INPUT '@PJL EOJ~r~n':U).
    Run writeSocketData(INPUT '~033%-12345X~r~n':U).
   
    clientSocketHandle:DISCONNECT() NO-ERROR.

    RETURN.   
END PROCEDURE.
 
Top