September 25, 2005

Learing the difference between php://output and php://stdout

it took me way too long to figure out the difference between php://ouput and php://sdtout. looking at the wrappers page it seems like they both should do the same thing. you can run this little script to see the difference.
<?php
$fo = fopen('php://output', 'w');
$fs = fopen('php://stdout', 'w');

fputs($fo, "You can see this with the CLI and Apache.\n");
fputs($fs, "This only shows up on the CLI...\n");

fclose($fo);
fclose($fs);
?>
Posted by drewish at 01:03 AM | Comments (0) | TrackBack

piping php one-liners

When you're writing one line php scripts remember that 'php://stdin' is your friend. Here's a simple program I use to format PHP code for inclusion on my blog:

UNIX:
cat test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"

DOS/Windows:
type test.php | php -r "print htmlentities(file_get_contents('php://stdin'));"

Posted by drewish at 12:48 AM | Comments (0)

September 07, 2005

showing the source

want a directory full of php files to be showns as source instead of being interpreted? don't want to rename every one from *.php to *.phps? then apache's forcetype directive is for you. drop this little baby into your .htaccess file and you'll be good to go.

<FilesMatch "\.(php)$">
    ForceType application/x-httpd-php-source
</FilesMatch>

Posted by drewish at 12:53 PM | Comments (0) | TrackBack

April 06, 2005

using portchange interrupts on the PIC 16F630

Microchip's 16F630 is a pretty cool little chip. One of its features is to interrupt when the input on a pin changes. I had a bit of a time figuring out how to do it so I'll put this up to save someone else the trouble.

The short version is: Enable interrupts with INTCON's GIE, PEIE and RAIE bits. Set bits in TRISA and IOCA that correspond to the pins to watch. In the interrupt handler read PORTA then clear INTCON's RAIF bit.

	title "InputInterrupt"
	LIST	P=16F630, F=INHX8M
#include <p16f630.inc>
	__CONFIG  _INTRC_OSC_NOCLKOUT & _CP_OFF & _MCLRE_OFF & _WDT_OFF 
XTAL		EQU	4000000       ; internal crystal @ 4MHz

; backup spots for registers during interrupt handling
w_bak		equ	0x20
status_bak	equ	0x21
fsr_bak 	equ	0x22

; startup (at fixed address 0x0)
	org 0x0
	goto Main
; interrupt handler (at fixed address 0x4)
	org 0x4
IntHandle
	; save registers
	movwf	w_bak
	swapf	STATUS, W
	clrf	STATUS
	movwf	status_bak
	movfw	FSR
	movwf	fsr_bak
	
	; jumpt to proper handler
	btfsc	INTCON, RAIF	; check for port change
	goto	PortHandler

IntHandle_Return
	; restore all the backed up registers
	movfw	fsr_bak
	movwf	FSR
	swapf	status_bak, W
	movwf	STATUS
	swapf	w_bak, F
	swapf	w_bak, W
	retfie			; return from interrupt

PortHandler
	; To clear the interrupt you have to do two things in order:
	; * read the port
	; * clear the interrupt flag

;DO STUFF HERE
	; for testing copy inputs from port A to port C
	movfw	PORTA
	movwf	PORTC
	
	; clear portchange interrupt flag
	bcf	INTCON, RAIF

	goto	IntHandle_Return
;End PortHandler

Main
	; enable interupts
	bsf	INTCON,	GIE	; enable global interrupts
	bsf	INTCON,	PEIE	; enable peripheral interrupts
	bsf	INTCON, RAIE	; enable port change interrupts

	; clear the port
	clrf	PORTA

	; make the changes to Bank 1 all at once
	bsf	STATUS,	RP0
	; Port A 
	movlw	B'00111111'	; all 6 pins will be inputs
	movwf	TRISA		; set pin as input
	movwf	IOCA		; interupt on change
	; finished with Bank 1
	bcf   	STATUS,	RP0

MainLoop
	; kill time here waiting for an interupt
	goto	MainLoop

	end
Posted by drewish at 04:42 PM | Comments (0) | TrackBack

January 27, 2005

using php and curl to do an html file post

after scouring the internet to find out how to do multipart post operations and finding nothing nothing, i decided to save someone else some time. the trick is that @ before the file name.

$fullflepath = 'C:\temp\test.jpg';
$upload_url = 'http://www.example.com/uploadtarget.php';
$params = array(
	'photo'=>"@$fullfilepath",
	'title'=>$title
);		

$ch = curl_init();
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_URL, $upload_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$response = curl_exec($ch);
curl_close($ch);
Posted by drewish at 06:27 AM | Comments (0) | TrackBack

January 22, 2005

migrate makethumbs.sh photo albums to flickr

after my gallery albums got corrupted i started messing around with flickr and got hooked. i'd been pretty frustrated by gallery's rigid album structure, flickr's usage of tags and sets is much more to my liking. there's also an excellent api for those times when you need to roll your own app. the fact that they handle all the backup convinced me to throw down the $45 on a pro account.

now the task it to upload all of my photos to their servers. it's a good chance to go back and import all the old stuff that never made it into gallery. i'm starting with some albums i'd make using jason molenda's makethumbs shell script. i hacked together a perl script to parse the titles and descriptions from the description.txt file, upload the images, and add them to a set. click the read more link to view the script. i hope someone else may find it of use.

update: i finally got around to encoding it as valid html. copy and paste should work better.

#!/usr/bin/perl
use strict;
use warnings;

# upload a makethumbs album to flickr
#
# by andrew morton - http://drewish.com
#
# to use this script fill in the next three variables, then change
# to the directory with the makethumbs album and run it. email if 
# you have problems.

my $flickr_email = 'your@email;
my $flickr_pass = 'secret';
my $photo_tags;

# shouldn't need to change anything below here.

# variables
my $flickr_key = '58ac590250ef4eeb81e6d853ee942034';
my @photo_ids;	# id assigned after upload
my $config_file = 'descriptions.txt';
my $album_title;	# album title
my $album_desc;		# album description
my %image_title;	# file titles
my %image_desc;		# file descriptions

$|= 1; # auto flush

use Flickr::API;
use Flickr::API::Request;
use Flickr::Upload;
use LWP::UserAgent;
use XML::Parser::Lite::Tree::XPath;

ReadMakeThumbsData();
UploadToFlickr();
AddToNewSet();
print "All done.\n";

sub ReadMakeThumbsData() {
	print "Loading makethumbs data from $config_file\n";
	open(CONFIG, $config_file) or die "Can't open $config_file : $!\n";
	
	# skip to short title section
	while (<CONFIG>) {
		last if /^\[short title\]/;
	}
	# suck up album title.
	while (<CONFIG>) {
		chomp;
		last if /^\[longer page description\]/;
		$album_title .= $_;
	}
	# suck up album description
	while (<CONFIG>) {
		chomp;
		last if /^\[captions\]/;
		$album_desc .= $_;
	}
	# suck up image titles
	while (<CONFIG>) {
		chomp;
		next unless $_; # skip empty lines
		last if /^\[descriptions\]/;
		/^(\S*)\s(.*)/;
		$image_title{$1} = $2;
	}
	# suck up image descriptions
	while (<CONFIG>) {
		chomp;
		next unless $_; # skip empty lines
		/^(\S*)\s(.*)/;
		$image_desc{$1} = $2;
	}
	close CONFIG;
}

sub DebugPrintData() {
	print("album title: $album_title\n");
	print("album desc: $album_desc\n");

	foreach my $key (keys %image_title) {
		print "$key\n\ttitle: $image_title{$key}\n";
		print "\tdesc: $image_desc{$key}\n";
	} 
}

sub UploadToFlickr() {
	my $ua = LWP::UserAgent->new;
	my $file;
	my $id;

	print "Uploading photos to flickr for $flickr_email\n";

	foreach $file (sort(keys %image_title)) {
		print "$file";
		print "\n\ttitle: $image_title{$file}" if $image_title{$file};
		print "\n\tdescription: $image_desc{$file}" if $image_desc{$file};
		print "...";

		$id = Flickr::Upload::upload(
			$ua,
			'email' => $flickr_email,
			'password' => $flickr_pass,
			'photo' => $file,
			'title' => $image_title{$file},
			'description' => $image_desc{$file},
			# Everyone can view
			'is_public' => 1,
			'is_friend' => 1,
			'is_family' => 1,
			'tags' => $photo_tags
		);

		if ($id) {
			push @photo_ids, $id;
			print " assigned id $id\n";
		} else {
			print STDERR "Failed to upload $file";
		}
	}
}

sub AddToNewSet() {
	my $api = new Flickr::API({'key' => $flickr_key});
	my $response;
	my $xpath;
	my @nodes;

	print "Creating set '$album_title' ...";
	$response = $api->execute_method(
		'flickr.photosets.create',
		{
			'email' => $flickr_email,
			'password' => $flickr_pass,
			'title' => $album_title,
			'description' => $album_desc,
			'primary_photo_id' => 3654245# $photo_ids[0]
		}
	);
	$response->{success} or
		die "Could not create the set : $response->{error_message} \n";

 	$xpath = new XML::Parser::Lite::Tree::XPath($response->{tree});
	@nodes = $xpath->select_nodes('/photoset');
	print " assigned id: $nodes[0]->{attributes}->{id}\n";

	print "Adding photos to set...";
	$response = $api->execute_method(
		'flickr.photosets.editPhotos',
		{
			'email' => $flickr_email,
			'password' => $flickr_pass,
			'photoset_id' => $nodes[0]->{attributes}->{id},
			'primary_photo_id' => $photo_ids[0],
			'photo_ids' => join(', ', @photo_ids)
		}
	);
	$response->{success} or
		die "Could not add photos to set : $response->{error_message} \n";
	print " finished.\n";
}
Posted by drewish at 04:52 PM | Comments (0) | TrackBack

January 12, 2005

use visualbasic to concatenate a column of values in access

i've had to do this enough times that it seemed worth putting up on the blog to reference.

' take the values from the specified field in the specified 
' table and concatinate them into a comma separated list.
Public Function ConcatColVals(source As String, field As String) As String
    Dim ret As String
    
    ' open a recordset, enumerate the records and build a string
    With New Recordset
        .Open source, Application.CurrentProject.Connection, _
                adOpenForwardOnly, adLockReadOnly
        If Not .EOF Then
            ret = .Fields(field).Value
            .MoveNext
            Do While Not .EOF
                ret = ret & ", " & .Fields(field).Value
                .MoveNext
            Loop
        End If
    End With
    
    ' return the value
    ConcatColVals = ret
End Function
Posted by drewish at 08:14 AM | Comments (0) | TrackBack

August 06, 2004

registering a satelliteforms conduit using the palm CDK in dot net

for google's reference, if you ever need to register a satellite forms conduit from dot net use the palm cdk 4.03 and the following code:

' find out if the conduit is already registered
Public ReadOnly Property IsConduitRegistered() As Boolean
	Get
		Try
			Dim CondMgr As New PDStandardLib.PDCondMgr
			Dim ids() As Integer = CType(CondMgr.GetConduitList(), Integer())

			If ids Is Nothing Then
				Return False
			Else
				' sort sort it for the binary search
				Array.Sort(ids)
				' if the id exists in the array the conduit is registered
				Return (0 < Array.BinarySearch(ids, PALM_CREATOR_INTEGER))
			End If
		Catch ex As Exception
			Return False
		End Try
	End Get
End Property

' register the palm sync conduit
Public Sub RegisterConduit()
	Try
		Dim CondInfo As PDStandardLib.PDConduitInfo

		' remove any old conduit registration
		If Me.IsConduitRegistered Then
			Me.UnregisterConduit()
		End If

		' Set the conduit entries 
		CondInfo = New PDStandardLib.PDConduitInfo
		With CondInfo
			.FileName = Environment.SystemDirectory & "\" & SF_SYNC_DLL
			.CreatorID = PALM_CREATOR_INTEGER
			.HandHeldDB = "SatFormsEE"
			.DeskTopDataDirectory = "SatFormsEE"
			.DeskTopDataFile = "SatFormsEE"
			.DisplayName = "TecSync"
			.Priority = 2
		End With

		With New PDStandardLib.PDCondMgr
			' register it...
			.RegisterConduit(CondInfo)

			' refresh the list so it'll appear
			With New PDStandardLib.PDHotSyncUtility
				.RefreshConduitInfo()
			End With

			' ... and then test that we can retrieve it
			CondInfo = CType(.GetConduitInfo(PALM_CREATOR_INTEGER), PDStandardLib.PDConduitInfo)
			If CondInfo Is Nothing Then
				Throw New ApplicationException("The conduit seemed to register correctly but could not be retrieved afterwards. ")
			End If
		End With
	Catch ex As System.Runtime.InteropServices.COMException
		Throw New ApplicationException("Could not register the TecSync Palm conduit. The ConduitManager had a problem. " & ex.Message)
	Catch ex As ApplicationException
		Throw New ApplicationException("Could not register the TecSync Palm conduit. " & ex.Message)
	End Try
End Sub

' unregister the palm sync conduit
Public Sub UnregisterConduit()
	Try
		' unregister it 
		With New PDStandardLib.PDCondMgr
			.UnregisterConduit(PALM_CREATOR_INTEGER)
		End With
		' then refresh the list so it'll disapear
		With New PDStandardLib.PDHotSyncUtility
			.RefreshConduitInfo()
		End With
	Catch ex As System.Runtime.InteropServices.COMException
		Throw New ApplicationException("Coundn't unregister the TecSync Palm conduit. " & ex.Message)
	End Try
End Sub
Posted by drewish at 02:53 AM | Comments (0) | TrackBack
Creative Commons License xml feed