libwlocate-0.0git20130108/0000775000175000017500000000000012073004177012634 5ustar jrjrlibwlocate-0.0git20130108/connect.h0000775000175000017500000000217212073002423014433 0ustar jrjr/** * libwlocate - WLAN-based location service * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef CONNECT_H #define CONNECT_H extern int tcp_recv(int sock,char *data, int len,const char *termStr,long timeout); extern int tcp_send(int sock, const char *msg,int len,int msecs); extern void tcp_closesocket (int sock); extern int tcp_connect_to(const char *address,unsigned short connect_port); extern void tcp_set_blocking(int sock,char block); #endif libwlocate-0.0git20130108/libwlocate.vcproj0000664000175000017500000001434012073002423016200 0ustar jrjr libwlocate-0.0git20130108/trace.c0000775000175000017500000001033112073002423014067 0ustar jrjr/** * test for libwlocate - WLAN-based location service * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "libwlocate.h" #include #include #include #include #include #include #include #ifdef ENV_LINUX #include #endif #ifdef ENV_WINDOWS #include #endif char notEqual(struct wloc_req *data1,struct wloc_req *data2,int num) { int i,j; for (i=0; isignal[i]!=data2->signal[i]) return 1; for (j=0; j<6; j++) { if (data1->bssids[i][j]!=data2->bssids[i][j]) return 1; } } return 0; } int main(int argc,char *argv[]) { int ret,i,cnt=0,prevCnt=0; double lat,lon; char quality; short ccode; char country[3]; FILE *FHandle; struct wloc_req request,prevRequest; unsigned char empty_bssid[6]={0,0,0,0,0,0}; unsigned char empty_signal=0; #ifdef ENV_WINDOWS WSADATA wsaData; WSAStartup((MAKEWORD(1, 1)), &wsaData); #endif if ((argc>1) && (strncmp(argv[1],"-h",2)==0)) // test WLAN geolocation instead of writing the WLAN data into a trace file { printf("lwtrace\n\tscan available WLAN networks, and write them into a file libwlocate.trace for later geolocation\n"); printf("lwtrace -t\n\ttest geolocation functionality and evaluate the current position out of available WLAN data immediately\n"); } else if ((argc>1) && (strncmp(argv[1],"-t",2)==0)) // test WLAN geolocation instead of writing the WLAN data into a trace file { ret=wloc_get_location(&lat,&lon,&quality,&ccode); // call the library function to get the position... //...check the return value afterwards... if (ret==WLOC_CONNECTION_ERROR) printf("Error: could not communicate with server!\n"); else if (ret==WLOC_LOCATION_ERROR) printf("Error: could not calculate your location, the given WLAN networks are unknown!\n"); //...and print the position only in case the call was successful else if (ret==WLOC_OK) { printf("Your location: %f (lat) %f (lon)\nQuality: %d %%\n",lat,lon,quality); country[2]=0; if (wloc_get_country_from_code(ccode,country)==WLOC_OK) printf("Country: %d - %s\n",ccode,country); else printf("Country: unknown\n"); } else printf("Error: failed due to an unknown error!\n"); } else { FHandle=fopen("libwlocate.trace","ab"); if (FHandle) { memset(&prevRequest,0,sizeof(struct wloc_req)); while (true) { if (cnt>0) { if ((cnt==prevCnt) && (!notEqual(&request,&prevRequest,cnt))) { for (i=0; i # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=trace - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "trace.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "trace.mak" CFG="trace - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "trace - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "trace - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "trace - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ENV_WINDOWS" /YX /FD /c # ADD BASE RSC /l 0x407 /d "NDEBUG" # ADD RSC /l 0x407 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 Release/libwlocate.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /machine:I386 /out:"Release/lwtrace.exe" !ELSEIF "$(CFG)" == "trace - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "trace___Win32_Debug" # PROP BASE Intermediate_Dir "trace___Win32_Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "trace___Win32_Debug" # PROP Intermediate_Dir "trace___Win32_Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "ENV_WINDOWS" /FR /YX /FD /GZ /c # ADD BASE RSC /l 0x407 /d "_DEBUG" # ADD RSC /l 0x407 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 Debug/libwlocate.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /debug /machine:I386 /out:"trace___Win32_Debug/lwtrace.exe" /pdbtype:sept !ENDIF # Begin Target # Name "trace - Win32 Release" # Name "trace - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\trace.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project libwlocate-0.0git20130108/README0000775000175000017500000000675012073002423013517 0ustar jrjr About ----- libwlocate is a library that can be used to evaluate a geographical position out of the WLAN networks that are available near to a user. It is (c) 2010 by Oxygenic/VWP. You can contact me at virtual_worlds(at)gmx.de but please only in case this README and the included documentation does not answer your question ;-) Contributions, feedback and suggestion are always welcome. Intended audience ----------------- This library does not come with an GUI and offers a programming interface only. Therefore the intended audience are software developers that want to use this library out of own applications to provide WLAN-based location services out of their software. Although there is a small test application that demonstrates the usage principle of the library I afraid it is more or less useless for people that do not program own applications. Licensing --------- The sources are located in directory libwlocate and are licensed unter the terms of the GPL. For more details please refer to document COPYING. Building and usage ------------------ There are several possibilites provided to build the library using different operating systems and building environments: Makelib - file for building the shared library libwlocate.so for Linux using standard "make"; requires wireless-tools headers and binaries Makefile - file for building a Linux test and trace application using libwlocate.so and standard make; the resulting position trace file libwlocate.trace can be loaded by LocDemo for later position evaluation Makelib.QNX - file for building the shared library libwlocate.so for QNX using standard "make"; here scanning of WLAN networks is currently not implemented, the compiled library will not work at the moment! Makefile.QNX - file for building a QNX test and trace application using libwlocate.so and standard make libwlocate.dsp - project file for building the shared DLL libwlocate.dll for Windows using Microsoft Visual Studio libtest.dsp - Visual Studio project file for building a test application that makes use of the formerly generated libwlocate.dll The library provides one major function that performs the full location job: int wloc_get_location() This function scans the currently available WLAN networks, sends the resulting information to the server of OpenWLANMap at openwlanmap.org and returns the evaulated position. Additional information about the quality of the result is given, it uses a range of 0..100 where 100 is the maximum possible quality and accuracy of the result. Here 100% means the location can't be evaluated more exact, it does not mean necessarily that the returned position does not differ by more than a fixed deviation. So this value is only some kind of probability that tells you if the position is really near to the given geographic coordinates. The smaller this value is, the bigger the deviation can be. The value returned by the function informs about the success of the operation, only in case WLOC_OK is given, the operation was successful and the returned position data are valid and can be used. In all other cases the return value informs about the kind of error that occured (please refer to libwlocate.h for details). For a more detailled description of all available library functions, their parameters and usage please refer to file libwlocate.h, there you can find an inline documentation for all of them. libwlocate-0.0git20130108/trace.dsw0000775000175000017500000000077012073002423014450 0ustar jrjrMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "trace"=.\trace.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### libwlocate-0.0git20130108/Makelib.QNX0000775000175000017500000000107512073002423014566 0ustar jrjrDBGFLAGS = -O2 -g0 -DNDEBUG ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 endif CCOMPILER=gcc -Wall -fPIC -shared -Wno-unused $(DBGFLAGS) -D_REENTRANT -DENV_QNX -I. -I.. -I/usr/include SYSLIBRARIES= LIBS = $(SYSLIBRARIES) -lsocket EXECUTABLE=libwlocate.so LINK=gcc -shared OBJECTS = connect.o wlan.o libwlocate.o default: $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(LINK) $(SYSLDFLAGS) $(LDFLAGS) -o $(EXECUTABLE) $(OBJECTS) $(LIBS) cp $(EXECUTABLE) /usr/lib/ cp libwlocate.h /usr/local/include %.o: %.c $(CCOMPILER) -c $< -o $@ clean: rm -f $(OBJECTS) $(EXECUTABLE) libwlocate-0.0git20130108/libwlocate.sln0000664000175000017500000000154012073002423015467 0ustar jrjr Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwlocate", "libwlocate.vcproj", "{409710FC-8708-4C87-B387-69F6A1E33DF7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {409710FC-8708-4C87-B387-69F6A1E33DF7}.Debug|Win32.ActiveCfg = Debug|Win32 {409710FC-8708-4C87-B387-69F6A1E33DF7}.Debug|Win32.Build.0 = Debug|Win32 {409710FC-8708-4C87-B387-69F6A1E33DF7}.Release|Win32.ActiveCfg = Release|Win32 {409710FC-8708-4C87-B387-69F6A1E33DF7}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal libwlocate-0.0git20130108/wlocd/0000775000175000017500000000000012073002423013734 5ustar jrjrlibwlocate-0.0git20130108/wlocd/init.d/0000775000175000017500000000000012073002423015121 5ustar jrjrlibwlocate-0.0git20130108/wlocd/init.d/wlocd0000775000175000017500000000155612073002423016166 0ustar jrjr#!/bin/bash # # /etc/rc.d/init.d/wlocd # # Starts the WLAN detection/scanning daemon wlocd # # Source function library. . /etc/init.d/functions prog="wlocd" test -x /usr/bin/$prog || exit 0 RETVAL=0 # # See how we were called. # start() { # Check if universe is already running if [ ! -f /var/lock/subsys/$prog ]; then echo -n $"Starting $prog: " daemon $prog & RETVAL=$? [ $RETVAL -eq 0 ] && touch /var/lock/subsys/$prog echo else echo "Failed! /var/lock/subsys/$prog exists!" fi return $RETVAL } stop() { echo -n $"Stopping $prog: " killproc $prog -INT rm -f /var/lock/subsys/$prog RETVAL=$? [ $RETVAL -eq 0 ] echo return $RETVAL } restart() { stop start } case "$1" in start) start ;; stop) stop ;; restart) restart ;; *) echo $"Usage: $0 {start|stop|restart}" exit 1 esac exit $? exit $RETVAL libwlocate-0.0git20130108/wlocd/README0000775000175000017500000000211312073002423014614 0ustar jrjrThis is a very small and very simple daemon that does nothing more than run with root privileges. Whenever a client connects to it, it evaluates the current WLAN data, sends them back to this client and closes the connection. This gives the possibility to use libwlocate under Linux with low user privileges but still with full access to all WLAN information. The wlocd daemon itself is very simple, no special protocol is used, the WLAN data structure is just sent back (so when somebody else connects to this daemon the response will consist of unusable binary data). Because wlocd does not receive anything and act on 127.0.0.1 only, there may be absolute no way to exploit or to crack it somehow in order to get its root privileges. So it is no security risk when this daemon is running with root privileges all the time. libwlocate itself knows how to handle wlocd, every request for getting position information is issued to the wlocd first in order to get the WLAN data. Only in case there is now wlocd running or there is nor usable response from it, wlocd tries to get these data directly. libwlocate-0.0git20130108/wlocd/Makefile.QNX0000775000175000017500000000100412073002423016037 0ustar jrjrPROGRAM = wlocd INCLUDEDIRS = -I/usr/X11R6/include -I.. LIBDIRS = -L/usr/X11R6/lib -L/usr/lib LIBS = -lwlocate -lsocket DBGFLAGS = -O2 -g0 -DNDEBUG ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 -DNOSPLASH endif CXXSOURCES = main.cpp CXXOBJECTS = $(CXXSOURCES:.cpp=.o) CXXFLAGS = -Wall -DESRI_UNIX -DENV_QNX $(INCLUDEDIRS) $(DBGFLAGS) CXX = g++ LDFLAGS = $(LIBDIRS) $(LIBS) all: $(PROGRAM) $(PROGRAM): $(CXXOBJECTS) $(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS) strip $(PROGRAM) clean: $(RM) -f $(CXXOBJECTS) $(PROGRAM) libwlocate-0.0git20130108/wlocd/Makefile0000775000175000017500000000077512073002423015410 0ustar jrjrPROGRAM = wlocd INCLUDEDIRS = -I/usr/X11R6/include -I.. LIBDIRS = -L/usr/X11R6/lib -L/usr/lib LIBS = -lwlocate DBGFLAGS = -O2 -g0 -DNDEBUG ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 -DNOSPLASH endif CXXSOURCES = main.cpp CXXOBJECTS = $(CXXSOURCES:.cpp=.o) CXXFLAGS = -Wall -DESRI_UNIX -DENV_LINUX $(INCLUDEDIRS) $(DBGFLAGS) CXX = g++ LDFLAGS = $(LIBDIRS) $(LIBS) all: $(PROGRAM) $(PROGRAM): $(CXXOBJECTS) $(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS) strip $(PROGRAM) clean: $(RM) -f $(CXXOBJECTS) $(PROGRAM) libwlocate-0.0git20130108/wlocd/main.cpp0000775000175000017500000000321312073002423015366 0ustar jrjr#include #include #include #include #include #include #include #include #include #include "libwlocate.h" #ifdef ENV_QNX #define MSG_NOSIGNAL 0 #endif int main(void) { int s,c,ret; socklen_t addr_len; struct sockaddr_in addr; s = socket(PF_INET, SOCK_STREAM, 0); if (s == -1) { perror("socket() failed"); return 1; } #ifdef ENV_QNX addr.sin_addr.s_addr =inet_addr("0.0.0.0"); // strange behaviour: my QNX does not accept 127.0.0.1 to bind server sockets to it #else addr.sin_addr.s_addr =inet_addr("127.0.0.1"); // this daemon is acting only local #endif addr.sin_port = htons(10444); addr.sin_family = AF_INET; if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) == -1) { perror("bind() failed"); return 2; } if (listen(s, 3) == -1) { perror("listen() failed"); return 3; } // daemon(0,0); while(true) { addr_len = sizeof(addr); c = accept(s, (struct sockaddr*)&addr, &addr_len); if (c>0) { struct wloc_req request; memset(&request,0,sizeof(struct wloc_req)); ret=wloc_get_wlan_data(&request); if (ret<2) wloc_get_wlan_data(&request); // try two times in case the hardware was occupied or not able to find all networks if (ret>0) // no conversion from host to network byteorder necessary because we're always working on the same host send(c,&request,sizeof(struct wloc_req),MSG_NOSIGNAL); close(c); } } close(s); return 0; } libwlocate-0.0git20130108/wlocserv/0000775000175000017500000000000012073002423014470 5ustar jrjrlibwlocate-0.0git20130108/wlocserv/README0000664000175000017500000000056612073002423015357 0ustar jrjrThis directory contains the server application that is connected by libwlocate whenever it requests a new position that has to be evaluated out of the available WLAN networks. This server depends on liboapc which is available at http://git.fedorahosted.org/git/OpenAPC.git and has to be cloned into the same directory where the libwlocate-git-tree already resides within. libwlocate-0.0git20130108/wlocserv/wlocservInc.cpp0000664000175000017500000000015212073002423017470 0ustar jrjr#ifdef ENV_WINDOWS #pragma warning (disable: 4284) #endif #include "main.cpp" #include "platforms.cpp" libwlocate-0.0git20130108/wlocserv/Makefile.QNX0000664000175000017500000000122112073002423016571 0ustar jrjrPROGRAM = wlocserv INCLUDEDIRS = -I../ -I/opt/include/ -I .. -I../../../OpenAPC/liboapc/ -I../../../OpenAPC/plugins/ -I../../../ LIBDIRS = \ -L/usr/X11R6/lib -L/usr/lib -L/opt/lib LIBS = -loapc -lph -lmysqlclient DBGFLAGS = -O2 -g0 ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 -D_DEBUG endif CXXSOURCES = wlocservInc.cpp CXXOBJECTS = $(CXXSOURCES:.cpp=.o) CXXFLAGS = -Wall -DESRI_UNIX -DENV_QNX $(INCLUDEDIRS) $(DBGFLAGS) CXX = g++ LDFLAGS = $(LIBDIRS) $(LIBS) all: $(PROGRAM) $(PROGRAM): $(CXXOBJECTS) $(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS) strip $(PROGRAM) cp $(PROGRAM) /root/ chmod 755 /root/$(PROGRAM) clean: $(RM) -f $(CXXOBJECTS) $(PROGRAM) libwlocate-0.0git20130108/wlocserv/platforms.cpp0000664000175000017500000000600312073002423017202 0ustar jrjr/** * Copyright (C) 2004-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include "liboapc.h" #include "platforms.h" static char leave=false; #ifdef ENV_WINDOWS #include #include "Commctrl.h" void showLog(const char *format,...) { va_list arglist; char sText[1500]; va_start(arglist,format); vsprintf(sText,format,arglist); va_end(arglist); printf("%s\r\n",sText); } int splitCmdLine(unsigned short *lpCmdLine,char *argv[]) { int ctr=1; unsigned int i; char *c,*cprev,*cstart; char *cCmdLine; cCmdLine=(char*)malloc(wcslen(lpCmdLine)+1); if (!cCmdLine) return 0; memset(cCmdLine,0,wcslen(lpCmdLine)+1); for (i=0; i #else #include #endif #include #include #include static char quit=false; bool LeaveServer(void) { return quit; } void signalh (const int sig) { // setup_signal_traps (); switch (sig) { case SIGPIPE: case EPIPE: printf("EPIPE received\n"); break; case SIGHUP: // reloadSignal=true; break; case SIGBUS: case SIGFPE: case SIGIO: case SIGTERM: leave=true; break; case SIGINT: case SIGQUIT: printf ("\nexiting\n"); quit=1; break; } } void setupSignalTraps(void) { signal (SIGINT, signalh); signal (SIGQUIT, signalh); signal (SIGFPE, signalh); signal (SIGBUS, signalh); signal (SIGTERM, signalh); signal (SIGHUP, signalh); signal (SIGIO, signalh); #ifdef ENV_SPARCSOLARIS signal (EPIPE, signalh); signal (SIGPIPE, SIG_IGN); #else signal (SIGPIPE, signalh); #endif } void showLog(const char *format,...) { va_list arglist; char sText[1500]; va_start(arglist,format); vsprintf(sText,format,arglist); va_end(arglist); sText[strlen(sText)]='\0'; printf("%s\n",sText); } #endif libwlocate-0.0git20130108/wlocserv/maindefs.h0000664000175000017500000000221612073002423016430 0ustar jrjr/** * Copyright (C) 2004-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MAINDEFS_H #define MAINDEFS_H #define FCOMMON_NAME "WLocate Server" #define FCOMMON_VERSION 0.2 #define FCOMMON_URL "" #define FCOMMON_COPYRIGHT "(c) 2009-2012" #ifdef ENV_LINUX #define ENV_POSIX #endif #ifdef ENV_QNX #define ENV_POSIX #endif #ifdef ENV_SPARCSOLARIS #define ENV_POSIX #endif #define ERR_NO_MEMORY 0x20010000 #define ERR_LIST_EMPTY 0x20020000 #define ERR_NO_SUCH_ELEMENT 0x20030000 #endif libwlocate-0.0git20130108/wlocserv/platforms.h0000664000175000017500000000221612073002423016651 0ustar jrjr/** * Copyright (C) 2004-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PLATFORMS_H #define PLATFORMS_H #ifdef ENV_WINDOWS #include #define MSG_NOSIGNAL 0 #endif #ifdef ENV_LINUX typedef void* HINSTANCE; extern bool reloadSignal; #endif #ifdef ENV_QNX typedef void* HINSTANCE; #endif void showLog(const char *format,...); bool LeaveServer(void); #ifndef ENV_WINDOWS void setupSignalTraps(); #else int splitCmdLine(unsigned short *lpCmdLine,char *argv[]); #endif #endif // PLATFORMS_H libwlocate-0.0git20130108/wlocserv/Makefile0000664000175000017500000000130112073002423016123 0ustar jrjrPROGRAM = wlocserv INCLUDEDIRS = -I.. -Iliboapc/ -I/opt/include/ -I../../../OpenAPC/liboapc/ -I../../../OpenAPC/plugins -I../../../ #$(shell wx-config --cflags) $(shell pkg-config gtk+-2.0 --cflags) LIBDIRS = \ -L/usr/lib/mysql -L/usr/lib -L/opt/lib LIBS = \ -loapc -lmysqlclient #$(shell wx-config --libs) DBGFLAGS = -O2 -g0 ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 -D_DEBUG endif CXXSOURCES = wlocservInc.cpp CXXOBJECTS = $(CXXSOURCES:.cpp=.o) CXXFLAGS = -Wall -DESRI_UNIX -DENV_LINUX $(INCLUDEDIRS) $(DBGFLAGS) CXX = g++ LDFLAGS = $(LIBDIRS) $(LIBS) all: $(PROGRAM) $(PROGRAM): $(CXXOBJECTS) $(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS) strip $(PROGRAM) clean: $(RM) -f $(CXXOBJECTS) $(PROGRAM) libwlocate-0.0git20130108/wlocserv/main.cpp0000664000175000017500000015441412073002423016131 0ustar jrjr/** * wlocserv - server application for WLAN-based location service * Copyright (C) 2009-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "maindefs.h" #if defined (ENV_LINUX) || defined (ENV_QNX) #include /* socket definitions */ #include /* socket types */ #include /* inet (3) funtions */ #include /* misc. UNIX functions */ #include #include #include #include #endif #ifdef ENV_WINDOWS #include #endif #include #include #include #include #include #include #include #include #include #ifndef ENV_QNX #include "getopt.h" #endif #include "libwlocate.h" #include "liboapc.h" #include "platforms.h" #include "login.h" // contains the login information, never add this header to the repository! struct list_entry { struct list_entry *next; // the next structure in the list int sock; int readLen; char *remoteIP; // the IP of the remote connection unsigned long int remoteIPNum; time_t timeout; struct wloc_req request; }; #ifndef TEST_MODE static unsigned short srcport=10443; static bool daemonMode=false; #endif static unsigned char dSystemExit=0; // set to true by node /system/exit/0 static struct list_entry firstEntry; static char *userName; #ifdef ENV_POSIX static bool verbose=false; #endif #ifdef ENV_QNX #define MSG_NOSIGNAL 0 #endif /** * This function creates a new list_entry and adds a new client to the internal list * of connections * @param list the list where the new entry has to be added * @param s_sock the socket descriptor of the new client connection * @param t_sock the socket descriptor of the forwarded connection * @parem remoteIP the remote IP of the client * @return 0 when the operation could be finished successfully or an error code otherwise */ int addClient(struct list_entry *list, int s_sock,unsigned long int remoteIP) { struct list_entry *n; struct in_addr iAddr; char *c; n =(struct list_entry*)malloc(sizeof(struct list_entry)); if (!n) { return ERR_NO_MEMORY; } memset(n,0,sizeof(struct list_entry)); n->sock = s_sock; iAddr.s_addr=ntohl(remoteIP); c=inet_ntoa(iAddr); if (c) n->remoteIP=strdup(c); else n->remoteIP=strdup("unknown host"); n->remoteIPNum=ntohl(remoteIP); n->readLen=0; n->next = list->next; n->timeout=time(NULL); list->next= n; return 0; } /** * Whenever a client closes its connection it has to be removed from the list of active * clients and the resources of the related list_entry-structure have to be released. * That has to be done by calling this function. * @param list the list of entries where the client has to be removed from * @param entry the clients list entry that has to be removed * @return 0 in case the operation could be completed successfully or an error code * otherwise */ int removeClient(struct list_entry *list,struct list_entry *entry) { struct list_entry *lz, *lst = NULL; if (!entry) return 0; if (!list->next) return ERR_LIST_EMPTY; for (lz = list->next; lz; lz = lz->next) { if (lz->sock == entry->sock) break; lst = lz; } if (!lz) return ERR_NO_SUCH_ELEMENT; if (lst) lst->next = lz->next; else list->next = lz->next; if (lz->sock) oapc_tcp_closesocket(lz->sock); if (lz->remoteIP) free(lz->remoteIP); free(lz); return 0; } /** * This function removes all entries from a given list of connections * @param list the list of entries that has to be flushed completely */ void freeList(struct list_entry *list) { while ((list->next) && (list->next->sock)) removeClient(list,list->next); } /** * This function us used together with the socet function select(), it fills the file * descriptor set that is required by set depending on the available socket connections * @parem fds the file descriptor set structure to be filled * @param list the list of clients from which the socket information have to be used * @return the maximum socket file descriptor number */ int fillSet(fd_set *fds, struct list_entry *list) { int max = 0; struct list_entry *lz; for (lz = list->next; lz; lz = lz->next) { if (lz->sock > max) max = lz->sock; if (lz->sock>0) FD_SET(lz->sock, fds); } return max; } /** * This function can be used after a call to the socekt function select(), it retrieves * that client out of a given list where a event occured that was watched by select(). * @param fds the file descriptor set structure that was modified by select() * @param the related list of client conmnections that belongs to the preceding caqll of * select and that was used by a former call to fillSet() * @return the client connection that caused select() to leave its waiting state or NULL * in case there is no client socket that fits to the result */ struct list_entry *getClient(fd_set *fds,struct list_entry *list) { int i=0; struct list_entry *lz; while(!FD_ISSET(i, fds)) i++; lz=list->next; while (lz) { if (lz->sock==i) return lz; lz=lz->next; } return NULL; } /** definitions for the command line options */ static char shortopts[] = "vVhu:"; #ifndef ENV_QNX static struct option const longopts[] = { {"user", optional_argument, NULL, 'u'}, {"version", no_argument, NULL, 'v'}, #ifdef ENV_LINUX {"verbose", no_argument, NULL, 'V'}, #endif {"help", no_argument, NULL, 'h'}, {NULL, no_argument, NULL, 0} }; #endif /** definitions for the command line help output */ #ifdef ENV_QNX static char const *const option_help[] = { " -u switch to this users privileges", " -V print out some debugging information", " -v show version info", " -h show this help", 0 }; #else static char const *const option_help[] = { " -u --user switch to the privileges of this user after creating the socket", #ifdef ENV_POSIX " -V --verbose print out some debugging information", #endif " -v --version show version info", " -h --help show this help", 0 }; #endif /** print out version information */ static void version(void) { printf ("%s %.1f %s\n%s\n", FCOMMON_NAME,FCOMMON_VERSION,FCOMMON_URL,FCOMMON_COPYRIGHT); } /** print out command line help information */ static void usage (char *pname) { printf ("usage: %s [OPTIONS]\n",pname); printf (" --help for more information\n"); return; } /** * Get the switches and related values out of the command line parameters * @param argc the number of arguments as handed over by main() * @param argv the arguments as handed over by main() */ static void getSwitches(int argc,char *argv[]) { int optc; char const *const *p; if (optind == argc) return; #ifdef ENV_QNX while ((optc = getopt(argc, argv, shortopts)) != -1) #else while ((optc = getopt_long (argc, argv, shortopts, longopts, (int *) 0)) != -1) #endif { switch (optc) { #ifndef ENV_WINDOWS case 'V': verbose=true; break; #endif case 'u': userName=strdup(optarg); break; case 'v': version(); exit (0); break; case 'h': usage (argv[0]); for (p = option_help; *p; p++) printf ("%s\n", *p); exit (0); break; default: usage (argv[0]); } } } #ifndef TEST_MODE /** * This function reads from the sockets and tries to fetch data from both connections. It reads * data only for a given time and stores them. * @param entry the list entry of the client where data have to be read for * @param timeout the maximum time in milliseconds that is allowed to be used to receive data from * the clients socket * @return true in case a full package could be read successfully or false otherwise */ static bool readPackets(struct list_entry *entry, long timeout) { long /*size_t*/ rc; long ctr=0; int expLen; #ifdef ENV_WINDOWS long err; #endif if (entry->readLen>=(int)offsetof(struct wloc_req,bssids)) { if (entry->request.length==0) { entry->request.length=sizeof(struct wloc_req); // some old size showLog("WARNING: Forcing block size to %d\n",entry->request.length); } #warning WORKAROUND! expLen=entry->request.length; } else { if (entry->readLen==0) memset(&entry->request,0,sizeof(entry->request)); expLen=offsetof(struct wloc_req,bssids); } // data from source client side while (entry->readLensock,((char*)&entry->request)+entry->readLen,expLen-entry->readLen,MSG_NOSIGNAL); if (rc>0) { entry->readLen+=rc; entry->timeout=time(NULL); } else if (rc==0) return false; else { #ifdef ENV_WINDOWS err=GetLastError(); if (err!=EAGAIN) #else if ((errno!=EAGAIN) && (errno!=EINPROGRESS) && (errno!=0)) #endif return false; ctr+=oapc_util_thread_sleep(10); } if (ctr>timeout) break; } return true; } // Get the geolocation of a single BSSID from OpenBMap static char get_wlan_location(double *lat,double *lon,char *bssid) { return 0; char line[5001],body[5001],mime[101]; int sock,retCode; *lat=0; *lon=0; sock=oapc_tcp_connect_to("openbmap.org",80); if (sock<=0) return 0; sprintf(body,"bssid=%s",bssid); sprintf(line,"POST /api/getGPSfromWifiAPBSSID.php5 HTTP/1.1\r\nHost: openbmap.org\r\nAccept: text/xml, application/xml, */*\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: %d\r\n\r\n%s",strlen(body),body); if (oapc_tcp_send(sock,line,strlen(line),2000)!=(int)strlen(line)) { printf("Sending head failed...\n"); oapc_tcp_closesocket(sock); return 0; } memset(line,0,sizeof(line)); while (oapc_tcp_recv(sock,line,1000,"\n",4000)) { if (strstr(line,"HTTP/1.")==line) { retCode=atoi(line+9); if (retCode!=200) { oapc_tcp_closesocket(sock); return 0; }; } else if (strstr(line,"Content-Type:")==line) { strncpy(mime,line+14,100); } else if ((line[0]=='\r') || (line[0]=='\n')) { memset(body,0,sizeof(body)); while (oapc_tcp_recv(sock,body,5000,"\n",4000)>0) { if ((strstr(body,"lat")) && (strstr(body,"lng"))) { char *c; c=strstr(body,"lat=")+5; if ((c) && (c>body)) *lat=atof(c); else return 0; c=strstr(body,"lng=")+5; if ((c) && (c>body)) *lon=atof(c); else return 0; showLog("Position from openbmap.org: %f %f",*lat,*lon); return 1; } if ((strstr(body,"\r")==body) || (strstr(body,"\n")==body)) { oapc_tcp_closesocket(sock); return 0; } memset(body,0,sizeof(body)); } } memset(line,0,sizeof(line)); } oapc_tcp_closesocket(sock); return 0; } static int getCountryNum(const char *countryTxt) { if (!strncmp(countryTxt,"DE",2)) return 1; else if (!strcmp(countryTxt,"AT")) return 2; else if (!strcmp(countryTxt,"CH")) return 3; else if (!strcmp(countryTxt,"NL")) return 4; else if (!strcmp(countryTxt,"BE")) return 5; else if (!strcmp(countryTxt,"LU")) return 6; else if (!strcmp(countryTxt,"NO")) return 7; else if (!strcmp(countryTxt,"SE")) return 8; else if (!strcmp(countryTxt,"DK")) return 9; else if (!strcmp(countryTxt,"AL")) return 12; else if (!strcmp(countryTxt,"DZ")) return 13; else if (!strcmp(countryTxt,"AR")) return 19; else if (!strcmp(countryTxt,"AU")) return 21; else if (!strcmp(countryTxt,"BS")) return 23; else if (!strcmp(countryTxt,"BH")) return 24; else if (!strcmp(countryTxt,"BD")) return 25; else if (!strcmp(countryTxt,"BB")) return 26; else if (!strcmp(countryTxt,"BY")) return 27; else if (!strcmp(countryTxt,"BZ")) return 28; else if (!strcmp(countryTxt,"BJ")) return 29; else if (!strcmp(countryTxt,"BM")) return 30; else if (!strcmp(countryTxt,"BA")) return 33; else if (!strcmp(countryTxt,"BR")) return 36; else if (!strcmp(countryTxt,"BG")) return 38; else if (!strcmp(countryTxt,"CA")) return 43; else if (!strcmp(countryTxt,"CL")) return 47; else if (!strcmp(countryTxt,"CN")) return 48; else if (!strcmp(countryTxt,"CO")) return 49; else if (!strcmp(countryTxt,"CR")) return 52; else if (!strcmp(countryTxt,"HR")) return 53; else if (!strcmp(countryTxt,"CZ")) return 56; else if (!strcmp(countryTxt,"PR")) return 59; else if (!strcmp(countryTxt,"EC")) return 60; else if (!strcmp(countryTxt,"EG")) return 61; else if (!strcmp(countryTxt,"Es")) return 65; else if (!strcmp(countryTxt,"FI")) return 68; else if (!strcmp(countryTxt,"FR")) return 69; else if (!strcmp(countryTxt,"HN")) return 73; else if (!strcmp(countryTxt,"GR")) return 75; else if (!strcmp(countryTxt,"GL")) return 76; else if (!strcmp(countryTxt,"GU")) return 78; else if (!strcmp(countryTxt,"GT")) return 79; else if (!strcmp(countryTxt,"HK")) return 84; else if (!strcmp(countryTxt,"HU")) return 85; else if (!strcmp(countryTxt,"IS")) return 86; else if (!strcmp(countryTxt,"IN")) return 87; else if (!strcmp(countryTxt,"ID")) return 88; else if (!strcmp(countryTxt,"IR")) return 89; else if (!strcmp(countryTxt,"IQ")) return 90; else if (!strcmp(countryTxt,"IE")) return 91; else if (!strcmp(countryTxt,"IL")) return 92; else if (!strcmp(countryTxt,"IT")) return 93; else if (!strcmp(countryTxt,"JM")) return 94; else if (!strcmp(countryTxt,"JP")) return 95; else if (!strcmp(countryTxt,"JO")) return 97; else if (!strcmp(countryTxt,"KZ")) return 98; else if (!strcmp(countryTxt,"KE")) return 99; else if (!strcmp(countryTxt,"KR")) return 102; else if (!strcmp(countryTxt,"KW")) return 103; else if (!strcmp(countryTxt,"KG")) return 104; else if (!strcmp(countryTxt,"LB")) return 107; else if (!strcmp(countryTxt,"LS")) return 108; else if (!strcmp(countryTxt,"LV")) return 105; else if (!strcmp(countryTxt,"LT")) return 111; else if (!strcmp(countryTxt,"MY")) return 115; else if (!strcmp(countryTxt,"MV")) return 116; else if (!strcmp(countryTxt,"MQ")) return 119; else if (!strcmp(countryTxt,"MX")) return 123; else if (!strcmp(countryTxt,"MC")) return 124; else if (!strcmp(countryTxt,"MA")) return 126; else if (!strcmp(countryTxt,"MZ")) return 127; else if (!strcmp(countryTxt,"NZ")) return 131; else if (!strcmp(countryTxt,"NI")) return 133; else if (!strcmp(countryTxt,"NG")) return 135; else if (!strcmp(countryTxt,"PK")) return 138; else if (!strcmp(countryTxt,"PA")) return 141; else if (!strcmp(countryTxt,"PY")) return 142; else if (!strcmp(countryTxt,"PE")) return 144; else if (!strcmp(countryTxt,"PH")) return 145; else if (!strcmp(countryTxt,"PL")) return 147; else if (!strcmp(countryTxt,"PT")) return 148; else if (!strcmp(countryTxt,"QA")) return 150; else if (!strcmp(countryTxt,"RO")) return 151; else if (!strcmp(countryTxt,"RU")) return 152; else if (!strcmp(countryTxt,"SM")) return 155; else if (!strcmp(countryTxt,"SA")) return 157; else if (!strcmp(countryTxt,"SN")) return 158; else if (!strcmp(countryTxt,"SG")) return 161; else if (!strcmp(countryTxt,"SK")) return 162; else if (!strcmp(countryTxt,"SI")) return 163; else if (!strcmp(countryTxt,"ZA")) return 166; else if (!strcmp(countryTxt,"ES")) return 167; else if (!strcmp(countryTxt,"SD")) return 169; else if (!strcmp(countryTxt,"SY")) return 172; else if (!strcmp(countryTxt,"TW")) return 173; else if (!strcmp(countryTxt,"TJ")) return 174; else if (!strcmp(countryTxt,"TZ")) return 175; else if (!strcmp(countryTxt,"TH")) return 176; else if (!strcmp(countryTxt,"TT")) return 179; else if (!strcmp(countryTxt,"TN")) return 180; else if (!strcmp(countryTxt,"TR")) return 181; else if (!strcmp(countryTxt,"UA")) return 185; else if (!strcmp(countryTxt,"AE")) return 186; else if (!strcmp(countryTxt,"GB")) return 187; else if (!strcmp(countryTxt,"US")) return 188; else if (!strcmp(countryTxt,"UY")) return 189; else if (!strcmp(countryTxt,"VE")) return 191; else if (!strcmp(countryTxt,"VN")) return 192; else if (!strcmp(countryTxt,"ZM")) return 195; else return -1; } #endif // TEST_MODE /** * This is the main loop, it is called by main() after several necessary initializations have been done. * This main loop accepts new incoming connections, tries to read data from all available connections, * parses received data blocks, invokes the required (re)action for the received data and sends a * response back to the client. */ static bool mainLoop(void* /*hInstance*/) { #ifndef TEST_MODE int list_s; /* listening socket */ unsigned long remoteIP; unsigned int num_fields; struct in_addr in_address; int c,max; fd_set fds; MYSQL_RES *sqlResult=NULL; MYSQL_ROW row; int on; time_t currTime=time(NULL); #else struct list_entry client_mem; #endif MYSQL *conn=NULL; char query[1000+1]; struct list_entry *client; int country; struct wloc_res result; time_t lastDBAccess=0; double lat[WLOC_MAX_NETWORKS],lon[WLOC_MAX_NETWORKS]; double latTotal,lonTotal,sumTotal; int i,j,sum; bool doRecalculate,wasIPbased; result.version=1; result.length=sizeof(struct wloc_res); #ifdef TEST_MODE client=&client_mem; memset(client,0,sizeof(struct list_entry)); client->request.bssids[0][0]=1; client->request.bssids[1][0]=2; // client->request.bssids[2][0]=3; // client->request.bssids[3][0]=4; // client->request.bssids[4][0]=5; #else #ifdef ENV_POSIX if (daemonMode) #endif showLog("Starting %s...",FCOMMON_NAME); #ifdef ENV_POSIX if (verbose) printf("Listening...\n"); #endif list_s=oapc_tcp_listen_on_port(srcport,"62.112.140.13"); if (list_s<=0) { #ifdef ENV_WINDOWS errno=GetLastError(); #else perror(""); #endif showLog("ERROR: could not create listening socket %s:%d, %d!","api.openwlanmap.org",srcport,errno); return false; } oapc_tcp_set_blocking(list_s,0); if (setsockopt(list_s,SOL_SOCKET,SO_KEEPALIVE,(char*)&on,sizeof(on))<0) { #ifdef ENV_WINDOWS errno=GetLastError(); #else perror(""); #endif showLog("WARNING: could not set socket options, %d!",errno); } showLog("INFO: binding to %s:%d","api.openwlanmap.org",srcport); #ifdef ENV_POSIX if (userName) { struct passwd *pwd; pwd=getpwnam(userName); if (!pwd) showLog("ERROR: unknown username %s!\n",optarg); else { if (setgid(pwd->pw_uid)!=0) showLog("ERROR: Setting group failed"); if (setuid(pwd->pw_uid)!=0) showLog("ERROR: Setting user failed"); } free(userName); } if (daemonMode) daemon(0,0); #endif while ((!dSystemExit) && (!LeaveServer())) { FD_ZERO(&fds); max = fillSet(&fds, &firstEntry); FD_SET(list_s, &fds); if (list_s > max) max = list_s; select(max + 1, &fds, NULL, NULL, NULL); if (FD_ISSET(list_s, &fds)) { c=oapc_tcp_accept_connection(list_s, &remoteIP); if (c>0) { #ifdef ENV_WINDOWS in_address.S_un.S_addr=ntohl(remoteIP); #else in_address.s_addr=ntohl(remoteIP); #endif oapc_tcp_set_blocking(c,0); addClient(&firstEntry,c,remoteIP); showLog("New client accepted from %s",inet_ntoa(in_address)); } } else { // get the client that sends new data at the moment client = getClient(&fds,&firstEntry); if (client) { if ((!readPackets(client,5)) && (client->readLen==0)) { // remove a client if the connection was lost showLog("Connection lost to %s",client->remoteIP); removeClient(&firstEntry, client); } if ((client->readLen>(int)offsetof(struct wloc_req,bssids)) && (client->readLen>=client->request.length)) { oapc_util_thread_sleep(550); // do not hurry with the responses to avoid heavy load if ((conn) && (lastDBAccess+60request.signal[i]<=0) || (client->request.signal[i]>100)) client->request.signal[i]=60; for (j=0; j<6; j++) sum+=client->request.bssids[i][j]; #ifdef ENV_POSIX if (verbose) printf("Next AP: %02X%02X%02X%02X%02X%02X, sum=%d\n", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF, sum); #endif if (sum!=0) { snprintf(query,1000,"SELECT lat,lon,country,source FROM netpoints WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); //printf("%s\n",query); #ifndef TEST_MODE if (mysql_query(conn,query)!=0) { showLog("Query error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); } else #endif { //mysql_field_count() to check if there would be a result -> save DB load? #ifndef TEST_MODE sqlResult=mysql_store_result(conn); if (!sqlResult) { showLog("Result error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); } else #endif { #ifndef TEST_MODE if (mysql_num_rows(sqlResult)>0) #endif { #ifndef TEST_MODE #ifdef ENV_POSIX if (verbose) printf("Got SQL result...\n"); #endif num_fields = mysql_num_fields(sqlResult); if (num_fields<2) { showLog("Fields error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); } else if ((row = mysql_fetch_row(sqlResult)) && (row[0]) && (row[1]) && (row[3])) { lat[i]=atof(row[0]); lon[i]=atof(row[1]); if (row[2]) { sum=atoi(row[2]); if ((sum>0) && (sum<250)) country=sum; } else country=-1; if ((!row[3]) || (row[3][0]=='3')) client->request.signal[i]/=2; // interpolated location else if (row[3][0]=='0') client->request.signal[i]*=2; // manually entered by users of homepage / owners of AP else if (row[3][0]=='4') client->request.signal[i]/=3; // g-fetched Location else if (row[3][0]=='5') client->request.signal[i]/=3; // g-collected data // 1 - imported from other db // 2 - scanned for my own // 6 - uploads from wardrivers // 7 - uploaded by OWLMap@Android App #ifdef ENV_POSIX if (verbose) printf("Result for %02X%02X%02X%02X%02X%02X: Lat: %f Lon: %f, Signal: %d\n", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF, lat[i],lon[i],client->request.signal[i]); #endif } else { #ifdef ENV_POSIX if (verbose) printf("Error fetching row %p %p %p\n",row[0],row[1],row[3]); #endif } #else if (i==0) { lat[i]=48.141; lon[i]=11.60123; } else if (i==1) { lat[i]=48.14575; lon[i]=11.60505; } else if (i==2) { lat[i]=48.140767; lon[i]=11.599917; } else if (i==3) { lat[i]=48.140717; lon[i]=11.59952; } else if (i==4) { lat[i]=48.140825; lon[i]=11.5999; } #endif } #ifndef TEST_MODE else { char countryTxt[100]; #ifdef ENV_POSIX if (verbose) printf("New AP %02X%02X%02X%02X%02X%02X, checking at external source\n", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); #endif snprintf(countryTxt,99,"%02X-%02X-%02X-%02X-%02X-%02X", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); if (get_wlan_location(&lat[i],&lon[i],countryTxt)) // get info from Google { #ifdef ENV_POSIX if (verbose) printf("New AP %02X%02X%02X%02X%02X%02X, adding to own database\n", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); #endif snprintf(query,1000,"INSERT INTO netpoints (bssid, lat, lon, timestamp, source, country) VALUES ('%02X%02X%02X%02X%02X%02X', '%f', '%f', '%ld', '4', '%d')", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF, lat[i],lon[i],(unsigned long)time(NULL),0); printf("Query: %s\n",query); mysql_query(conn,query); client->request.signal[i]=25; // accuracy is quite poor, so set a small weight for this position } else { #ifdef ENV_POSIX if (verbose) printf("New AP %02X%02X%02X%02X%02X%02X, not found at external source\n", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); #endif client->request.signal[i]=-1; // mark as not found lat[i]=-1000; lon[i]=-1000; } } mysql_free_result(sqlResult); #endif if (lat[i]>-900) { #ifdef ENV_POSIX if (verbose) printf("AP %02X%02X%02X%02X%02X%02X, updating use counter\n", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF,client->request.bssids[i][2] & 0xFF, client->request.bssids[i][3] & 0xFF,client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); #endif snprintf(query,1000,"UPDATE netpoints SET usecnt=usecnt+1 WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); //showLog("Query: %s\n",query); mysql_query(conn,query); if ((client->request.signal[i]<=0) || (client->request.signal[i]>100)) client->request.signal[i]=60; latTotal+=(lat[i]*client->request.signal[i]/100.0); lonTotal+=(lon[i]*client->request.signal[i]/100.0); sumTotal+=(client->request.signal[i]/100.0); result.quality++; } } } } } doRecalculate=false; if (result.quality==0) { char countryTxt[3]; #ifdef ENV_POSIX if (verbose) printf("No position, performing IP-based localisation\n"); #endif if (client->request.cgiIP==0) client->request.cgiIP=client->remoteIPNum; snprintf(query,1000,"SELECT ipoints.lat,ipoints.lon,ipoints.ccode FROM ips,ipoints WHERE ips.fromip<=%u AND ips.toip>=%u AND ips.kidx=ipoints.idx", ntohl(client->request.cgiIP),ntohl(client->request.cgiIP)); printf("%s\n",query); if (mysql_query(conn,query)!=0) { showLog("Query error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); result.result=WLOC_RESULT_ERROR; // nothing found } else { //mysql_field_count() to check if there would be a result -> save DB load? sqlResult=mysql_store_result(conn); if (!sqlResult) { showLog("Result error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); result.result=WLOC_RESULT_ERROR; // nothing found } else { if (mysql_num_rows(sqlResult)>0) { num_fields = mysql_num_fields(sqlResult); if (num_fields<3) { result.result=WLOC_RESULT_ERROR; // nothing found showLog("Fields error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); } else if ((row = mysql_fetch_row(sqlResult)) && (row[0]) && (row[1]) && (row[2])) { int ival; //printf("Lat: %s - %f - %d Lon: %s - %f - %d\n",row[0],atof(row[0])*10000000.0,(int)(atof(row[0])*10000000.0),row[1],atof(row[1])*10000000.0,(int)(atof(row[1])*10000000.0)); ival=(int)(atof(row[0])*10000000.0); result.lat=htonl(ival); ival=(int)(atof(row[1])*10000000.0); result.lon=htonl(ival); strncpy(countryTxt,row[2],2); countryTxt[2]=0; result.quality=0; // poor IP-based accuracy country=getCountryNum(countryTxt); result.result=WLOC_RESULT_OK; wasIPbased=true; } } else { result.result=WLOC_RESULT_ERROR; // nothing found showLog("Row-number-error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); } } } } else { latTotal/=sumTotal; lonTotal/=sumTotal; #ifdef ENV_POSIX if (verbose) printf("Intermediate position: %f %f\n",latTotal,lonTotal); #endif if (result.quality>2) // if there are more than two hits we can check if one of them is out of range { for (i=0; i-900) { if ((fabs(latTotal-lat[j])>latMaxDist) || (fabs(lonTotal-lon[j])>lonMaxDist)) { latMaxDist=fabs(latTotal-lat[j]); lonMaxDist=fabs(lonTotal-lon[j]); maxPos=j; } } } if ((latMaxDist>0.003) || (lonMaxDist>0.003)) { #ifdef ENV_POSIX if (verbose) printf("Maximum error distances %f %f for AP %02X%02X%02X%02X%02X%02X, increasing error count\n", latMaxDist,lonMaxDist, client->request.bssids[maxPos][0] & 0xFF,client->request.bssids[maxPos][1] & 0xFF, client->request.bssids[maxPos][2] & 0xFF,client->request.bssids[maxPos][3] & 0xFF, client->request.bssids[maxPos][4] & 0xFF,client->request.bssids[maxPos][5] & 0xFF); #endif snprintf(query,1000,"UPDATE netpoints SET errcnt=errcnt+1, usecnt=usecnt-1 WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[maxPos][0] & 0xFF,client->request.bssids[maxPos][1] & 0xFF, client->request.bssids[maxPos][2] & 0xFF,client->request.bssids[maxPos][3] & 0xFF, client->request.bssids[maxPos][4] & 0xFF,client->request.bssids[maxPos][5] & 0xFF); showLog("Updating error counter for %02X:%02X:%02X:%02X:%02X:%02X", client->request.bssids[maxPos][0] & 0xFF,client->request.bssids[maxPos][1] & 0xFF, client->request.bssids[maxPos][2] & 0xFF,client->request.bssids[maxPos][3] & 0xFF, client->request.bssids[maxPos][4] & 0xFF,client->request.bssids[maxPos][5] & 0xFF); mysql_query(conn,query); // delete from DB in case of too much errors snprintf(query,1000,"SELECT errcnt, usecnt FROM netpoints WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[maxPos][0] & 0xFF,client->request.bssids[maxPos][1] & 0xFF, client->request.bssids[maxPos][2] & 0xFF,client->request.bssids[maxPos][3] & 0xFF, client->request.bssids[maxPos][4] & 0xFF,client->request.bssids[maxPos][5] & 0xFF); if (mysql_query(conn,query)!=0) showLog("Query error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); else { //mysql_field_count() to check if there would be a result -> save DB load? sqlResult=mysql_store_result(conn); if (!sqlResult) showLog("Result error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); else { if (mysql_num_rows(sqlResult)>0) { num_fields = mysql_num_fields(sqlResult); if (num_fields<2) showLog("Fields error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); else if ((row = mysql_fetch_row(sqlResult)) && (row[0]) && (row[1])) { int errval,useval; errval=(int)atoi(row[0]); useval=(int)atoi(row[1]); if (((errval>=useval) && (useval>20)) || (errval>40)) { snprintf(query,1000,"DELETE FROM netpoints WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[maxPos][0] & 0xFF,client->request.bssids[maxPos][1] & 0xFF, client->request.bssids[maxPos][2] & 0xFF,client->request.bssids[maxPos][3] & 0xFF, client->request.bssids[maxPos][4] & 0xFF,client->request.bssids[maxPos][5] & 0xFF); mysql_query(conn,query); showLog("Delete Entry Query: %s\n",query); } } } } } lat[maxPos]=-2000; lon[maxPos]=-2000; result.quality--; latTotal=0.0; lonTotal=0.0; sumTotal=0.0; for (j=0; j-900) { if ((client->request.signal[j]<=0) || (client->request.signal[j]>100)) client->request.signal[j]=60; latTotal+=(lat[j]*client->request.signal[j]/100.0); lonTotal+=(lon[j]*client->request.signal[j]/100.0); sumTotal+=(client->request.signal[j]/100.0); printf("2: %f %f %f - %d\n",lat[j],lon[j],sumTotal,client->request.signal[j]); } } latTotal/=sumTotal; lonTotal/=sumTotal; if (result.quality<=1) break; } } /* if (lat[i]>-900) { if ((fabs(latTotal-lat[i])>0.003) || (fabs(lonTotal-lon[i])>0.003)) { snprintf(query,1000,"UPDATE netpoints SET errcnt=errcnt+1 WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); showLog("Updating error counter for %02X:%02X:%02X:%02X:%02X:%02X", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); // mysql_query(conn,query); lat[i]=-2000; lon[i]=-2000; doRecalculate=true; result.quality--; } } }*/ if (result.quality<=0) { result.quality=0; result.result=WLOC_RESULT_ERROR; // nothing found } } else // only two bssid's so we only can check if they are close to each other or not { for (i=0; i-900) { if ((fabs(latTotal-lat[i])>0.00225) || (fabs(lonTotal-lon[i])>0.00225)) // smaller error threshold because we have less values for averaging { result.quality=0; result.result=WLOC_RESULT_ERROR; // nothing found snprintf(query,1000,"UPDATE netpoints SET errcnt=errcnt+1 WHERE bssid='%02X%02X%02X%02X%02X%02X'", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); showLog("Updating error counter for %02X:%02X:%02X:%02X:%02X:%02X", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF); // mysql_query(conn,query); } } } } if ((result.quality>=3) && (!doRecalculate)) // enough known WLANs with no error found to store the other ones with interpolated values { for (i=0; irequest.signal[i]==-1) { snprintf(query,1000,"INSERT INTO netpoints (bssid, lat, lon, timestamp, source, country) VALUES ('%02X%02X%02X%02X%02X%02X', '%f', '%f', '%ld', '3', '%d')", client->request.bssids[i][0] & 0xFF,client->request.bssids[i][1] & 0xFF, client->request.bssids[i][2] & 0xFF,client->request.bssids[i][3] & 0xFF, client->request.bssids[i][4] & 0xFF,client->request.bssids[i][5] & 0xFF, latTotal,lonTotal,(unsigned long)time(NULL),country); printf("Query: %s\n",query); mysql_query(conn,query); } } } result.lat=htonl((int)(latTotal*10000000.0)); result.lon=htonl((int)(lonTotal*10000000.0)); } if ((result.quality>0) && (result.quality<3)) result.quality=1; // with less than 3 valid BSSIDs we have the lowest quality #ifdef TEST_MODE printf("Returning Result: %d Quality: %d Lat: %f Lon: %f Country: %d\n", result.result,result.quality,ntohl(result.lat)/10000000.0,ntohl(result.lon)/10000000.0,country); #else printf("Returning Result: %d Quality: %d Lat: %f Lon: %f Country: %d\n", result.result,result.quality,ntohl(result.lat)/10000000.0,ntohl(result.lon)/10000000.0,country); } result.quality*=10; // send a percentual value if (result.quality>99) result.quality=99; // never give 100% result.ccode=htons(country); oapc_tcp_send(client->sock,(char*)&result,sizeof(struct wloc_res),500); if (!wasIPbased) { // check the geolocation of the related users IP and correct it in case it differs too much /* if (client->request.cgiIP==0) client->request.cgiIP=client->remoteIPNum; snprintf(query,1000,"SELECT ipoints.lat,ipoints.lon FROM ips,ipoints WHERE ips.fromip<=%u AND ips.toip>=%u AND ips.kidx=ipoints.idx", ntohl(client->request.cgiIP),ntohl(client->request.cgiIP)); if (mysql_query(conn,query)!=0) { showLog("Query error: %s %d %s\n",__FILE__,__LINE__,mysql_error(conn)); result.result=WLOC_RESULT_ERROR; // nothing found } else { //mysql_field_count() to check if there would be a result -> save DB load? sqlResult=mysql_store_result(conn); if (sqlResult) { if (mysql_num_rows(sqlResult)>0) { num_fields = mysql_num_fields(sqlResult); if (num_fields>=2) { if ((row = mysql_fetch_row(sqlResult)) && (row[0]) && (row[1]) && (row[2])) { if ((fabs(atof(row[0])-latTotal)>0.4) || (fabs(atof(row[1])-lonTotal)>0.4)) { // update IP position test SQL-statement! snprintf(query,1000,"UPDATE ips,ipoints SET ipoints.lat='%f',ipoints.lon='%f' WHERE ips.fromip<=%u AND ips.toip>=%u AND ips.kidx=ipoints.idx", ((int)(latTotal*1000.0))/1000.0,((int)(lonTotal*1000.0))/1000.0, ntohl(client->request.cgiIP),ntohl(client->request.cgiIP)); mysql_query(conn,query); } } } } } } */ } showLog("Closing connection to %s with response %d",client->remoteIP,result.result); removeClient(&firstEntry, client); } } currTime=time(NULL); if (currTime%10==0) { struct list_entry *list; list=&firstEntry; while (list) { if ((list->timeout!=0) && (list->timeout+60remoteIP,list->timeout,time(NULL)); removeClient(&firstEntry,list); break; // only remove one client per try } list=list->next; } } } } freeList(&firstEntry); if (conn) mysql_close(conn); #endif // TEST_MODE return true; } #ifdef ENV_WINDOWS WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nCmdShow*/) { WSADATA wsaData; #else int main(int argc,char *argv[]) { void* hInstance=NULL; #endif #ifdef ENV_WINDOWS int argc; char *argv[100]; //unsigned short argv0[300]; WSAStartup((MAKEWORD(1, 1)), &wsaData); argc=splitCmdLine(GetCommandLine(),argv); //GetModuleFileName(NULL,argv0,300); appName="wlocserv.exe";//argv0; #else setupSignalTraps(); //appName=argv[0]; #endif memset(&firstEntry,0,sizeof(firstEntry)); getSwitches(argc,argv); { srand(time(NULL)); #ifdef ENV_POSIX if (verbose) printf("Starting mainloop...\n"); #endif if ((!dSystemExit) && (mainLoop(hInstance))) { #ifdef ENV_WINDOWS while (!LeaveServer()) { oapc_util_thread_sleep(100); } #endif } } #ifdef ENV_WINDOWS WSACleanup(); #endif #ifdef ENV_POSIX if (verbose) printf("Exiting mainloop...\n"); #endif #ifdef ENV_POSIX if (verbose) printf("Releasing buffered data...\n"); #endif showLog("Exiting server!"); return 0; } libwlocate-0.0git20130108/libwlocate.dsp0000775000175000017500000001037412073002423015471 0ustar jrjr# Microsoft Developer Studio Project File - Name="libwlocate" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=libwlocate - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "libwlocate.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "libwlocate.mak" CFG="libwlocate - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "libwlocate - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "libwlocate - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "libwlocate - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBWLOCATE_EXPORTS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBWLOCATE_EXPORTS" /D "ENV_WINDOWS" /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x407 /d "NDEBUG" # ADD RSC /l 0x407 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /machine:I386 !ELSEIF "$(CFG)" == "libwlocate - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBWLOCATE_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /Zp1 /MDd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBWLOCATE_EXPORTS" /D "ENV_WINDOWS" /FR /YX /FD /GZ /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x407 /d "_DEBUG" # ADD RSC /l 0x407 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept !ENDIF # Begin Target # Name "libwlocate - Win32 Release" # Name "libwlocate - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\connect.c # End Source File # Begin Source File SOURCE=.\libwlocate.c # End Source File # Begin Source File SOURCE=.\wlan.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\wlan.h # End Source File # Begin Source File SOURCE=.\wlanapi_cust.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project libwlocate-0.0git20130108/libwlocate.h0000775000175000017500000001447612073002423015141 0ustar jrjr/** * libwlocate - WLAN-based location service * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef LIBWLOCATE_H #define LIBWLOCATE_H #if defined __GNUC__ && !defined ENV_LINUX && !defined ENV_QNX #define ENV_LINUX #endif #if defined _MSC_VER && !defined ENV_WINDOWS #define ENV_WINDOWS #endif #ifndef WLOC_EXT_API #ifdef ENV_LINUX #define WLOC_EXT_API extern #endif #ifdef ENV_QNX #define WLOC_EXT_API extern #endif #ifdef ENV_WINDOWS #define WLOC_EXT_API __declspec(dllexport) #endif #endif #ifndef __cplusplus typedef unsigned char bool; #define false 0 #define true 1 #endif #ifdef ENV_WINDOWS #include #endif #ifdef ENV_QNX #include #endif #define WLOC_MAX_NETWORKS 16 #pragma pack(1) // 1 byte alignment, calculation speed doesn't matters but data transfer sizes // internally used communication structures and defines ====================================================================== struct wloc_req { unsigned char version,length; unsigned char bssids[WLOC_MAX_NETWORKS][6]; char signal[WLOC_MAX_NETWORKS]; unsigned long cgiIP; }; #define WLOC_RESULT_OK 1 // a position could be calculated #define WLOC_RESULT_ERROR 2 // the location could not be retrieved #define WLOC_RESULT_IERROR 3 // an internal error occured, no data are available struct wloc_res { char version,length; char result,iresult,quality; char cres6,cres7,cres8; // reserved variables int lat,lon; short ccode; unsigned short wres34,wres56,wres78; // reserved variables }; // end of internally used communication structures and defines ================================================================ // public defines and function definitions ==================================================================================== #define WLOC_OK 0 // result is OK, location could be retrieved #define WLOC_CONNECTION_ERROR 1 // could not send data to/receive data from server #define WLOC_SERVER_ERROR 2// could not connect to server to get position data #define WLOC_LOCATION_ERROR 3 // could not retrieve location, detected WLAN networks are unknown #define WLOC_ERROR 100 // some other error #ifdef __cplusplus extern "C" { #endif /** * This function retrieves the current geographic position of a system, the returned * position values can be used directly within maps like OpenStreetMap or Google Earth * @param[out] lat the latitude of the geographic position * @param[out] lon the longitude of the geographic position * @param[out] quality the percentual quality of the returned position, the given result * is as more exact as closer the quality value is to 100%, as smaller this * value is as bigger is the possible maximum deviation between returned * and the real position * @return only in case the returned value is equal WLOC_OK the values given back via the * functions parameters can be used; in case an error occurred an error code * WLOC_xxx is returned and the position and quality values given back are * undefined and don't have to be used */ WLOC_EXT_API int wloc_get_location(double *lat,double *lon,char *quality,short *ccode); /** * This function is used internally on step before the geolocation is calculated. It * checks which WLAN networks are accessible at the moment with wich signal strength and * fills the request structure wloc_req with these data. So this function can be called * in order to check the number of available networks without performing any geolocation. * @param[out] request a structure of type wloc_req that is filled with the WLAN data; * BSSID entries of this structure that are set to 00-00-00-00-00-00 are * unused and do not contain valid WLAN information * @return the retruned value is equal to the number of WLAN networks that have been found, * only in case it is greater than 0 the value given back via the functions * parameter can be used, elsewhere the structures contents are undefined */ WLOC_EXT_API int wloc_get_wlan_data(struct wloc_req *request); /** * Using this function the numeric country code that is returned by the wloc_get_location * function can be decoded to a two-character identifier. * @param[in] ccode a country code value that has to be bigger than 0 * @param[out] country this parameter has to point to a char array with a length of at least * two, here the country identifier is stored that belongs to the given code; * in case the function returns an error the contents of this variable are * undefined * @return WLOC_OK in case a valid and known country code was given, WLOC_ERROR in case the * country code is unknown */ WLOC_EXT_API int wloc_get_country_from_code(short ccode,char *country); /** * Using this function the numeric country code that is returned by the wloc_get_location * function can be decoded to a full-length country name. The name is returned as null- * terminated string that does not need to be copied, it is allocated by the library and will * be released by it. * @param[in] ccode a country code value that has to be bigger than 0 * @return NULL in case the country code could not be decoded or the country name in case of * success */ WLOC_EXT_API char* wloc_get_countryname_from_code(short ccode); WLOC_EXT_API int get_position(struct wloc_req *request,double *lat,double *lon,char *quality,short *ccode); #ifdef __cplusplus } #endif #endif libwlocate-0.0git20130108/wlan.c0000775000175000017500000002265112073002423013742 0ustar jrjr/** * libwlocate - WLAN-based location service * Copyright (C) 2010-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifdef ENV_WINDOWS #include #include #include #if (_MSC_VER>1400) #include #pragma comment(lib, "wlanapi.lib") #endif #include "wlanapi_cust.h" #endif #include "libwlocate.h" #include #include #ifdef ENV_WINDOWS /** * Works with Windows Vista and newer */ static int WinMethod1(struct wloc_req *request) { #if (_MSC_VER<=1400) static HINSTANCE wlan_library=NULL; #endif HANDLE hClient = NULL; DWORD dwCurVersion = 0; DWORD dwResult = 0; int iRet = 0,i,j,cnt; WCHAR GuidString[40] = {0}; PWLAN_INTERFACE_INFO_LIST pIfList = NULL; PWLAN_INTERFACE_INFO pIfInfo = NULL; PWLAN_BSS_LIST pBssList=NULL; PWLAN_BSS_ENTRY pBssEntry=NULL; #if (_MSC_VER<=1400) if (!wlan_library) { wlan_library = LoadLibrary("wlanapi"); if (!wlan_library) return 0; WlanOpenHandle = (WlanOpenHandleFunction)GetProcAddress(wlan_library, "WlanOpenHandle"); WlanEnumInterfaces = (WlanEnumInterfacesFunction)GetProcAddress(wlan_library, "WlanEnumInterfaces"); WlanGetNetworkBssList = (WlanGetNetworkBssListFunction)GetProcAddress(wlan_library, "WlanGetNetworkBssList"); WlanCloseHandle = (WlanCloseHandleFunction)GetProcAddress(wlan_library, "WlanCloseHandle"); WlanFreeMemory = (WlanFreeMemoryFunction)GetProcAddress(wlan_library, "WlanFreeMemory"); if ((!WlanOpenHandle) || (!WlanEnumInterfaces) || (!WlanGetNetworkBssList) || (!WlanCloseHandle) || (!WlanFreeMemory)) { FreeLibrary(wlan_library); wlan_library=NULL; return 0; } } #endif dwResult = WlanOpenHandle(1, NULL, &dwCurVersion, &hClient); if (dwResult != ERROR_SUCCESS) return 0; dwResult = WlanEnumInterfaces(hClient, NULL, &pIfList); if (dwResult != ERROR_SUCCESS) { WlanCloseHandle(hClient,NULL); return 0; } cnt=-1; for (i = 0; i < (int) pIfList->dwNumberOfItems; i++) { pIfInfo = (WLAN_INTERFACE_INFO *) &pIfList->InterfaceInfo[i]; dwResult=WlanGetNetworkBssList(hClient,&pIfInfo->InterfaceGuid,NULL,dot11_BSS_type_any,FALSE,NULL,&pBssList); if (dwResult!=ERROR_SUCCESS) continue; for (j=0; j<(int)pBssList->dwNumberOfItems; j++) { char *c; cnt++; pBssEntry=&pBssList->wlanBssEntries[j]; c=(char*)&pBssList->wlanBssEntries[j]; memcpy(request->bssids[cnt],pBssEntry->dot11Bssid,6); request->signal[cnt]=(char)pBssEntry->uLinkQuality; if (cnt>=WLOC_MAX_NETWORKS) break; } if (pBssList != NULL) WlanFreeMemory(pBssList); // ??? if (cnt>=WLOC_MAX_NETWORKS) break; } if (pIfList != NULL) WlanFreeMemory(pIfList); WlanCloseHandle(hClient,NULL); return cnt+1; } /** * Works with Windows XP >=SP2 and newer, outdated with Windows Vista and newer */ static int WinMethod2(struct wloc_req *request) { static HINSTANCE wzc_library=NULL; INTFS_KEY_TABLE interface_list; ADAPTER_INFO adapter_info; INTF_ENTRY interface_data; DWORD result,dwOutFlags; int i,j,length,cnt,data_until_padding; PNDIS_802_11_BSSID_LIST pList; const unsigned char *buffer_end; PNDIS_WLAN_BSSID pBssid; if (wzc_library==NULL) { wzc_library = LoadLibrary("wzcsapi"); if (!wzc_library) return 0; WZCEnumInterfaces = (WZCEnumInterfacesFunction)GetProcAddress(wzc_library, "WZCEnumInterfaces"); WZCQueryInterface = (WZCQueryInterfaceFunction)GetProcAddress(wzc_library, "WZCQueryInterface"); #if (_MSC_VER<=1400) WZCRefreshInterface = (WZCRefreshInterfaceFunction)GetProcAddress(wzc_library, "WZCRefreshInterface"); if ((!WZCEnumInterfaces) || (!WZCQueryInterface) || (!WZCRefreshInterface)) #else if ((!WZCEnumInterfaces) || (!WZCQueryInterface)) #endif { FreeLibrary(wzc_library); wzc_library=0; return 0; } } memset(&interface_list, 0, sizeof(INTFS_KEY_TABLE)); result = WZCEnumInterfaces(NULL, &interface_list); if (result != ERROR_SUCCESS) return 0; cnt=-1; for (i = 0; i<(int)interface_list.dwNumIntfs; ++i) { memset(&interface_data, 0, sizeof(INTF_ENTRY)); interface_data.wszGuid = interface_list.pIntfs[i].wszGuid; dwOutFlags = 1; result = WZCQueryInterface(NULL, INTF_DESCR, &interface_data, &dwOutFlags); if (result != ERROR_SUCCESS) { LocalFree(interface_list.pIntfs); return 0; } length = wcslen(interface_list.pIntfs[i].wszGuid); if (length > 0 && length < ADAPTER_NAME_LENGTH) { memset(&adapter_info, 0, sizeof(adapter_info)); wcscpy(adapter_info.name, interface_list.pIntfs[i].wszGuid); length = wcslen(interface_data.wszDescr); if (length > 0 && length < ADAPTER_DESCRIPTION_LENGTH) wcscpy(adapter_info.description, interface_data.wszDescr); memset(&interface_data, 0, sizeof(INTF_ENTRY)); interface_data.wszGuid =interface_list.pIntfs[i].wszGuid; result = WZCQueryInterface(NULL, INTF_BSSIDLIST | INTF_LIST_SCAN, &interface_data, &dwOutFlags); if (result != ERROR_SUCCESS) { LocalFree(interface_list.pIntfs); return 0; } if ((dwOutFlags & INTF_BSSIDLIST) != INTF_BSSIDLIST) { printf("WZC: Interface query consistency failure: incorrect flags\n"); LocalFree(interface_list.pIntfs); return 0; } if (interface_data.rdBSSIDList.dwDataLen == 0 || interface_data.rdBSSIDList.dwDataLen < sizeof(NDIS_802_11_BSSID_LIST)) { data_until_padding = (UCHAR*)&interface_data.padding1 - (UCHAR*)&interface_data; // this is a hack to support Windows XP SP2 with WLAN Hotfix and SP3 memmove((UCHAR*)&interface_data + data_until_padding, (UCHAR*)&interface_data + data_until_padding + 8, sizeof(interface_data) - data_until_padding - 8); if (interface_data.rdBSSIDList.dwDataLen == 0 || interface_data.rdBSSIDList.dwDataLen < sizeof(NDIS_802_11_BSSID_LIST)) { // cleanup printf("WZC: Interface query consistency failure: no data or incorrect data length (length: %ld)\n", interface_data.rdBSSIDList.dwDataLen); LocalFree(interface_list.pIntfs); LocalFree(interface_data.rdBSSIDList.pData); return 0; } } pList =(NDIS_802_11_BSSID_LIST*)(interface_data.rdBSSIDList.pData); pBssid =(PNDIS_WLAN_BSSID)(&pList->Bssid[0]); buffer_end =(unsigned char*)(pBssid) + interface_data.rdBSSIDList.dwDataLen; for (j= 0; j<(int)pList->NumberOfItems; j++) { cnt++; if (pBssid->Length < sizeof(NDIS_WLAN_BSSID) || ((unsigned char*)(pBssid) + pBssid->Length > buffer_end)) { // cleanup LocalFree(interface_list.pIntfs); LocalFree(interface_data.rdBSSIDList.pData); printf("WZC: Bssid structure looks odd. Break!\n"); return cnt; } memcpy(request->bssids[cnt],pBssid->MacAddress,6); request->signal[cnt]=(char)((100+pBssid->Rssi)*1.6); // is this really the correct calculation for a signal strength in percent? pBssid=(PNDIS_WLAN_BSSID)((unsigned char*)(pBssid) + pBssid->Length); } LocalFree(interface_data.rdBSSIDList.pData); } } LocalFree(interface_list.pIntfs); return cnt+1; } #endif #ifdef ENV_LINUX extern int iw_fill_structure(struct wloc_req *request); #endif WLOC_EXT_API int wloc_get_wlan_data(struct wloc_req *request) { #ifdef ENV_WINDOWS int ret; // here we have to try which one of the methods works because there is no stable and standardised API // available on Windows that could be used securely ret=WinMethod1(request); if (ret==0) ret=WinMethod2(request); return ret; #else #ifdef ENV_LINUX return iw_fill_structure(request); #else #ifdef ENV_QNX #warning WLAN functionality not implemented, library will never use the more exact WLAN positioning! #else #error Not supported! #endif #endif #endif return 0; // no networks found } libwlocate-0.0git20130108/libwlocate.c0000775000175000017500000004422112073002423015123 0ustar jrjr/** * libwlocate - WLAN-based location service * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #ifndef ENV_WINDOWS #include #endif #include "libwlocate.h" #include "connect.h" #include "wlan.h" #include "assert.h" WLOC_EXT_API int get_position(struct wloc_req *request,double *lat,double *lon,char *quality,short *ccode) { struct wloc_res result; int sock=0,ret; unsigned int uval; request->version=1; request->length=sizeof(struct wloc_req); sock=tcp_connect_to("api.openwlanmap.org",10443); if (sock<=0) return WLOC_SERVER_ERROR; tcp_set_blocking(sock,0); // set to non-blocking, we do not want to waid endless for a dead connection ret=tcp_send(sock,(char*)request,sizeof(struct wloc_req),5000); if (ret<(int)sizeof(struct wloc_req)) { tcp_closesocket(sock); return WLOC_CONNECTION_ERROR; } ret=tcp_recv(sock,(char*)&result,sizeof(struct wloc_res),NULL,20000); // longer receiving timeout, evaluation of the position may need some seconds in worst case if (ret<(int)sizeof(struct wloc_res)) { tcp_closesocket(sock); return WLOC_CONNECTION_ERROR; } tcp_closesocket(sock); if (result.result!=WLOC_RESULT_OK) return WLOC_LOCATION_ERROR; uval=ntohl(result.lat); if (uval & 0x80000000) *lat=((~uval)+1)/-10000000.0; else *lat=uval/10000000.0; uval=ntohl(result.lon); if (uval & 0x80000000) *lon=((~uval)+1)/-10000000.0; else *lon=uval/10000000.0; *quality=result.quality; // this should never happen, the server should send quality values in range 0..99 only // assert((*quality>=0) && (*quality<=99)); if (*quality<0) *quality=0; else if (*quality>99) *quality=99; // end of this should never happen *ccode=ntohs(result.ccode); return WLOC_OK; } /** please refer to libwlocate.h for a description of this function! */ WLOC_EXT_API int wloc_get_location(double *lat,double *lon,char *quality,short *ccode) { #ifdef ENV_LINUX int sock,i,j; #endif struct wloc_req request; int ret=0; memset((char*)&request,0,sizeof(struct wloc_req)); #ifdef ENV_LINUX // for Linux we have some special handling because only root has full access to the WLAN-hardware: // there a wlocd-daemon may run with root privileges, so we try to connect to it and receive the // BSSID data from there. Only in case this fails the way via iwtools is used sock=tcp_connect_to("127.0.0.1",10444); if (sock>0) { ret=tcp_recv(sock,(char*)&request,sizeof(struct wloc_req),NULL,7500); tcp_closesocket(sock); if (ret==sizeof(struct wloc_req)) { ret=0; for (i=0; i0) ret++; } } } #else ret=0; #endif if (ret==0) { if (wloc_get_wlan_data(&request)<2) { wloc_get_wlan_data(&request); // try two times in case the device was currently used or could not find all networks // in case of no success request localisation without WLAN data } } // for (i=0; i=MAX_COUNTRY_NUM)) return NULL; return countrynames[ccode-1]; } libwlocate-0.0git20130108/connect.c0000775000175000017500000001503712073002423014432 0ustar jrjr/** * libwlocate - WLAN-based location service * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #ifdef ENV_WINDOWS #include #define MSG_NOSIGNAL 0 #else #include #include #include #include #include #include #include #endif #ifndef ENV_WINDOWSCE #include #include #else #ifndef EAGIAN #define EAGAIN 11 // really the correct value? there is no errno.h for WinCE #endif #endif #ifdef ENV_QNX #define MSG_NOSIGNAL 0 #endif static int util_thread_sleep(int msecs) { #ifdef ENV_WINDOWS Sleep(msecs); #else usleep(msecs*1000); #endif return msecs; } /** Receive data from a socket connection @param[in] sock the identifier of the opened socket connection @param[in] data the memory area where the received data have to be stored into @param[in] len the maximum length of data that have to be read @param[in] termStr an optional termination string; when this value is not NULL and the character defined here is received the function returns @param[in] timeout when this time is exceeded the function returns also if not all data could be read; this parameter is valid only in case the socket is non-blocking */ int tcp_recv(int sock,char *data, int len,const char *termStr,long timeout) { long /*size_t*/ rc; long ctr=0,readLen=0; #ifdef ENV_WINDOWS long err; #endif // data from source client side while (readLen0) { readLen+=rc; if (termStr) { if (readLen+1=len) return readLen; } else if (rc==0) return readLen; else { #ifdef ENV_WINDOWS err=GetLastError(); if ((err!=EAGAIN) && (err!=WSAEWOULDBLOCK)) #else if ((errno!=EAGAIN) && (errno!=EINPROGRESS) && (errno!=0)) #endif return readLen; ctr+=10; util_thread_sleep(10); } if (ctr>timeout) break; } return readLen; } /** Send data to a socket connection @param[in] sock the identifier of the opened socket connection @param[in] msg the data that have to be send @param[in] len the length of the data @param[in] msecs when this time is exceeded the function returns also if not all data could be sent; this parameter is valid only in case the socket is non-blocking */ int tcp_send(int sock, const char *msg,int len,int msecs) { int rlen=0; int ctr=0,val; #ifdef ENV_WINDOWS int errno; #else errno=0; #endif while ((rlen=0) rlen+=val; else { #ifndef ENV_WINDOWS if (errno==EAGAIN) ctr-=2; // in case of eagain we expect a longer send-timeout #else errno=WSAGetLastError(); if (errno==WSAEWOULDBLOCK) ctr-=2; // in case of eagain we expect a longer send-timeout #endif else if (errno!=0) { rlen=-1; break; } #ifndef ENV_WINDOWS errno=0; #endif } if (rlenmsecs/2)) break; } return rlen; } /** Closes an opened socket connection @param[in] sock the socket that has to be closed */ void tcp_closesocket (int sock) { #ifdef ENV_WINDOWS shutdown(sock,SD_SEND); shutdown(sock,SD_RECEIVE); closesocket(sock); #else shutdown(sock,SHUT_WR); shutdown(sock,SHUT_RD); if (close (sock)<0) perror("close failed"); #endif } /** Tries to establish a client connection to a (remote) server socket @param[in] address address of the remote server in style a.b.c.d or www.domain.tld @param[in] port number to connect with @return the socket identifier of the established connection or a value <=0 in case of an error */ int tcp_connect_to(const char *address,unsigned short connect_port) { struct sockaddr_in a; struct hostent *host; int s; unsigned long nl; s = socket (AF_INET, SOCK_STREAM, 0); if (s<0) { #ifndef ENV_WINDOWSCE perror("Can't create socket"); #endif return -1; } memset (&a, 0, sizeof (a)); a.sin_port = htons (connect_port); a.sin_family = AF_INET; a.sin_addr.s_addr =inet_addr(address); if (a.sin_addr.s_addr==INADDR_NONE) { host = gethostbyname (address); // deprecated by posix standard? if (host) { memcpy (&nl, host->h_addr, sizeof(unsigned long)); a.sin_addr.s_addr = nl; } else { #ifndef ENV_WINDOWSCE perror("Getting hostname"); #endif tcp_closesocket(s); return -1; } } if (connect (s, (struct sockaddr *) &a, sizeof (a)) < 0) { #ifndef ENV_WINDOWSCE perror("No connection"); #endif tcp_closesocket (s); return -1; } return s; } /** Configures the blocking mode of an opened socket @param[in] sock identifier of the socket to configure @param[in] block 1 to set the socket to blocking mode, 0 to set it to non-blocking */ void tcp_set_blocking(int sock,char block) { int flags; #ifndef ENV_WINDOWS flags=fcntl(sock,F_GETFL, 0); if (block) flags&=~O_NONBLOCK; else flags|=O_NONBLOCK; fcntl(sock,F_SETFL, flags); #else if (block) flags=0; else flags=13; ioctlsocket(sock,FIONBIO,(unsigned long*)&flags); #endif } libwlocate-0.0git20130108/Makefile.QNX0000775000175000017500000000047012073002423014735 0ustar jrjrCC = gcc CFLAGS = -Wall -g0 -O3 -DENV_QNX -D_REENTRANT -DNDEBUG -L/usr/lib -L/usr/local/lib/ -L/opt/X11R6/lib/ -I/usr/include LDFLAGS = -lwlocate -lsocket PNAME=lwtrace OBJ = trace.o SRC = trace.c all: $(OBJ) $(CC) $(CFLAGS) -o $(PNAME) $(OBJ) $(LDFLAGS) strip $(PNAME) clean: rm *.o rm $(PNAME) libwlocate-0.0git20130108/wlanapi_cust.h0000664000175000017500000002111512073002423015466 0ustar jrjr/** * libwlocate - WLAN-based location service * Copyright (C) 2010-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * This code bases on the header files out of the WLAN-API from Moritz * Mertinkat. */ #ifndef WLANAPI_CUST_H #define WLANAPI_CUST_H #if (_MSC_VER<=1400) typedef enum _WLAN_INTERFACE_STATE { wlan_interface_state_not_ready = 0, wlan_interface_state_connected, wlan_interface_state_ad_hoc_network_formed, wlan_interface_state_disconnecting, wlan_interface_state_disconnected, wlan_interface_state_associating, wlan_interface_state_discovering, wlan_interface_state_authenticating } WLAN_INTERFACE_STATE, *PWLAN_INTERFACE_STATE; #define WLAN_MAX_NAME_LENGTH 256 typedef struct _WLAN_INTERFACE_INFO { GUID InterfaceGuid; WCHAR strInterfaceDescription[WLAN_MAX_NAME_LENGTH]; WLAN_INTERFACE_STATE isState; } WLAN_INTERFACE_INFO, *PWLAN_INTERFACE_INFO; typedef struct _WLAN_INTERFACE_INFO_LIST { DWORD dwNumberOfItems; DWORD dwIndex; WLAN_INTERFACE_INFO InterfaceInfo[1]; } WLAN_INTERFACE_INFO_LIST, *PWLAN_INTERFACE_INFO_LIST; #define DOT11_SSID_MAX_LENGTH 32 #define DOT11_RATE_SET_MAX_LENGTH 126 typedef struct _DOT11_SSID { ULONG uSSIDLength; UCHAR ucSSID[DOT11_SSID_MAX_LENGTH]; } DOT11_SSID, *PDOT11_SSID; typedef UCHAR DOT11_MAC_ADDRESS[6]; typedef enum _DOT11_BSS_TYPE { dot11_BSS_type_infrastructure = 1, dot11_BSS_type_independent = 2, dot11_BSS_type_any = 3 } DOT11_BSS_TYPE, * PDOT11_BSS_TYPE; typedef enum _DOT11_PHY_TYPE { DOT11_PHY_TYPE_UNUSED, } DOT11_PHY_TYPE; typedef struct _WLAN_RATE_SET { ULONG uRateSetLength; USHORT usRateSet[DOT11_RATE_SET_MAX_LENGTH]; } WLAN_RATE_SET, *PWLAN_RATE_SET; /*typedef struct _WLAN_BSS_ENTRY { DOT11_SSID dot11Ssid; ULONG uPhyId; DOT11_MAC_ADDRESS dot11Bssid; DOT11_BSS_TYPE dot11BssType; DOT11_PHY_TYPE dot11BssPhyType; LONG lRssi; ULONG uLinkQuality; BOOLEAN bInRegDomain; USHORT usBeaconPeriod; ULONGLONG ullTimestamp; ULONGLONG ullHostTimestamp; USHORT usCapabilityInformation; ULONG ulChCenterFrequency; WLAN_RATE_SET wlanRateSet; // --> to be verified, according to MSDN this member exists, according to the include of the Platform SDK it doesn't ULONG ulIeOffset; ULONG ulIeSize; } WLAN_BSS_ENTRY, * PWLAN_BSS_ENTRY;*/ typedef struct _WLAN_BSS_ENTRY { DOT11_SSID dot11Ssid; ULONG uPhyId; DOT11_MAC_ADDRESS dot11Bssid; DOT11_BSS_TYPE dot11BssType; DOT11_PHY_TYPE dot11BssPhyType; LONG lRssi; ULONG uLinkQuality; BOOLEAN bInRegDomain; USHORT usBeaconPeriod; ULONGLONG ullTimestamp; ULONGLONG ullHostTimestamp; USHORT usCapabilityInformation; ULONG ulChCenterFrequency; WLAN_RATE_SET wlanRateSet; ULONG ulIeOffset; ULONG ulIeSize; DWORD pad1,pad2; // strange padding bytes, required since Vista char pad3; // and Win 7 elsewhere this structure contains crap } WLAN_BSS_ENTRY, *PWLAN_BSS_ENTRY; typedef struct _WLAN_BSS_LIST { DWORD dwTotalSize; DWORD dwNumberOfItems; WLAN_BSS_ENTRY wlanBssEntries[1]; } WLAN_BSS_LIST, *PWLAN_BSS_LIST; typedef DWORD (WINAPI *WlanOpenHandleFunction)( DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle ); typedef DWORD (WINAPI *WlanEnumInterfacesFunction)( HANDLE hClientHandle, PVOID pReserved, PWLAN_INTERFACE_INFO_LIST *ppInterfaceList ); typedef DWORD (WINAPI *WlanGetNetworkBssListFunction)( HANDLE hClientHandle, const GUID *pInterfaceGuid, const PDOT11_SSID pDot11Ssid, DOT11_BSS_TYPE dot11BssType, BOOL bSecurityEnabled, PVOID pReserved, PWLAN_BSS_LIST *ppWlanBssList ); typedef DWORD (WINAPI *WlanCloseHandleFunction)( HANDLE hClientHandle, PVOID pReserved ); typedef VOID (WINAPI *WlanFreeMemoryFunction)( PVOID pMemory ); WlanOpenHandleFunction WlanOpenHandle; WlanEnumInterfacesFunction WlanEnumInterfaces; WlanGetNetworkBssListFunction WlanGetNetworkBssList; WlanCloseHandleFunction WlanCloseHandle; WlanFreeMemoryFunction WlanFreeMemory; #endif typedef struct { LPWSTR wszGuid; } INTF_KEY_ENTRY, *PINTF_KEY_ENTRY; typedef struct { DWORD dwNumIntfs; PINTF_KEY_ENTRY pIntfs; } INTFS_KEY_TABLE, *PINTFS_KEY_TABLE; typedef DWORD (WINAPI *WZCEnumInterfacesFunction)(LPWSTR pSrvAddr, PINTFS_KEY_TABLE pIntfs); typedef struct { DWORD dwDataLen; LPBYTE pData; } RAW_DATA, *PRAW_DATA; typedef struct { LPWSTR wszGuid; LPWSTR wszDescr; ULONG ulMediaState; ULONG ulMediaType; ULONG ulPhysicalMediaType; INT nInfraMode; INT nAuthMode; INT nWepStatus; ULONG padding1[2]; // 16 chars on Windows XP SP3 or SP2 with WLAN Hotfix installed, 8 chars otherwise DWORD dwCtlFlags; DWORD dwCapabilities; RAW_DATA rdSSID; RAW_DATA rdBSSID; RAW_DATA rdBSSIDList; RAW_DATA rdStSSIDList; RAW_DATA rdCtrlData; BOOL bInitialized; ULONG padding2[64]; // for security reason ... } INTF_ENTRY, *PINTF_ENTRY; typedef DWORD (WINAPI *WZCQueryInterfaceFunction)(LPWSTR pSrvAddr, DWORD dwInFlags, PINTF_ENTRY pIntf, LPDWORD pdwOutFlags); typedef wchar_t ADAPTER_NAME; typedef wchar_t ADAPTER_DESCRIPTION; typedef char AP_NAME; #define ADAPTER_NAME_LENGTH 256 #define ADAPTER_DESCRIPTION_LENGTH 256 #define AP_NAME_LENGTH 256 #define INTF_DESCR (0x00010000) #define INTF_BSSIDLIST (0x04000000) #define INTF_LIST_SCAN (0x08000000) typedef UCHAR NDIS_802_11_MAC_ADDRESS[6]; typedef struct _ADAPTER_INFO { ADAPTER_NAME name[ADAPTER_NAME_LENGTH]; ADAPTER_DESCRIPTION description[ADAPTER_DESCRIPTION_LENGTH]; } ADAPTER_INFO; #if (_MSC_VER<=1400) typedef struct _NDIS_802_11_SSID { ULONG SsidLength; UCHAR Ssid [32]; } NDIS_802_11_SSID, *PNDIS_802_11_SSID; typedef UCHAR NDIS_802_11_RATES_EX[16]; typedef LONG NDIS_802_11_RSSI; typedef UCHAR NDIS_802_11_RATES_EX[16]; typedef enum _NDIS_802_11_NETWORK_TYPE { Ndis802_11FH, Ndis802_11DS, Ndis802_11NetworkTypeMax, } NDIS_802_11_NETWORK_TYPE, *PNDIS_802_11_NETWORK_TYPE; typedef struct _NDIS_802_11_CONFIGURATION_FH { ULONG Length; ULONG HopPattern; ULONG HopSet; ULONG DwellTime; } NDIS_802_11_CONFIGURATION_FH, *PNDIS_802_11_CONFIGURATION_FH; typedef struct _NDIS_802_11_CONFIGURATION { ULONG Length; ULONG BeaconPeriod; ULONG ATIMWindow; ULONG DSConfig; NDIS_802_11_CONFIGURATION_FH FHConfig; } NDIS_802_11_CONFIGURATION, *PNDIS_802_11_CONFIGURATION; typedef enum _NDIS_802_11_NETWORK_INFRASTRUCTURE { Ndis802_11IBSS, Ndis802_11Infrastructure, Ndis802_11AutoUnknown, Ndis802_11InfrastructureMax, } NDIS_802_11_NETWORK_INFRASTRUCTURE, *PNDIS_802_11_NETWORK_INFRASTRUCTURE; typedef struct _NDIS_WLAN_BSSID_EX { ULONG Length; NDIS_802_11_MAC_ADDRESS MacAddress; UCHAR Reserved[2]; NDIS_802_11_SSID Ssid; ULONG Privacy; NDIS_802_11_RSSI Rssi; NDIS_802_11_NETWORK_TYPE NetworkTypeInUse; NDIS_802_11_CONFIGURATION Configuration; NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode; NDIS_802_11_RATES_EX SupportedRates; ULONG IELength; UCHAR IEs[1]; } NDIS_WLAN_BSSID_EX, *PNDIS_WLAN_BSSID_EX; typedef struct _NDIS_WLAN_BSSID { UCHAR padding1[4]; ULONG Length; UCHAR padding2[4]; NDIS_802_11_MAC_ADDRESS MacAddress; UCHAR Reserved[2]; NDIS_802_11_SSID Ssid; ULONG Privacy; NDIS_802_11_RSSI Rssi; } NDIS_WLAN_BSSID, *PNDIS_WLAN_BSSID; typedef struct _NDIS_802_11_BSSID_LIST { ULONG NumberOfItems; NDIS_WLAN_BSSID Bssid[1]; } NDIS_802_11_BSSID_LIST, *PNDIS_802_11_BSSID_LIST; typedef DWORD (WINAPI *WZCRefreshInterfaceFunction) ( LPWSTR pSrvAddr, DWORD dwInFlags, PINTF_ENTRY pIntf, LPDWORD pdwOutFlags ); WZCRefreshInterfaceFunction WZCRefreshInterface; #endif WZCEnumInterfacesFunction WZCEnumInterfaces; WZCQueryInterfaceFunction WZCQueryInterface; #endif libwlocate-0.0git20130108/Makelib0000775000175000017500000000101412073002423014112 0ustar jrjrDBGFLAGS = -O2 -g0 -DNDEBUG ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 endif CCOMPILER=gcc -Wall -fPIC -shared -Wno-unused $(DBGFLAGS) -D_REENTRANT -DENV_LINUX -I. -I.. SYSLIBRARIES= -lm LIBS = $(SYSLIBRARIES) -liw EXECUTABLE=libwlocate.so LINK=gcc -shared -Wl,--no-as-needed OBJECTS = connect.o wlan.o libwlocate.o iwlist.o default: $(EXECUTABLE) $(EXECUTABLE): $(OBJECTS) $(LINK) $(SYSLDFLAGS) $(LDFLAGS) -o $(EXECUTABLE) $(OBJECTS) $(LIBS) %.o: %.c $(CCOMPILER) -c $< -o $@ clean: rm -f $(OBJECTS) $(EXECUTABLE) libwlocate-0.0git20130108/locdemo/0000775000175000017500000000000012073002423014246 5ustar jrjrlibwlocate-0.0git20130108/locdemo/win_setup.nsi0000775000175000017500000001223212073002423017001 0ustar jrjr!include Library.nsh var ALREADY_INSTALLED Name "LocDemo - WLAN location demo" OutFile "locdemo_install.exe" SetCompress auto SetDatablockOptimize on CRCCheck on ; AutoCloseWindow false ; (can be true for the window go away automatically at end) ShowInstDetails nevershow ; (can be show to have them shown, or nevershow to disable) ; SetDateSave off ; (can be on to have files restored to their orginal date) LicenseText "Please read the license agreement before installing and using the software:" LicenseData "../COPYING" InstallDir "$PROGRAMFILES\LocDemo" DirText "Select the directory to install the LocDemo software into:" InstProgressFlags smooth Section "" ; (default section) SetOutPath "$INSTDIR" File "LocDemo.exe" File "..\Release\lwtrace.exe" File "icon.ico" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "..\Release\libwlocate.dll" "$SYSDIR\libwlocate.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxbase28u_net_vc_custom.dll" "$SYSDIR\wxbase28u_net_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxbase28u_odbc_vc_custom.dll" "$SYSDIR\wxbase28u_odbc_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxbase28u_vc_custom.dll" "$SYSDIR\wxbase28u_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxbase28u_xml_vc_custom.dll" "$SYSDIR\wxbase28u_xml_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_adv_vc_custom.dll" "$SYSDIR\wxmsw28u_adv_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_aui_vc_custom.dll" "$SYSDIR\wxmsw28u_aui_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_core_vc_custom.dll" "$SYSDIR\wxmsw28u_core_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_gl_vc_custom.dll" "$SYSDIR\wxmsw28u_gl_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_html_vc_custom.dll" "$SYSDIR\wxmsw28u_html_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_media_vc_custom.dll" "$SYSDIR\wxmsw28u_media_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_richtext_vc_custom.dll" "$SYSDIR\wxmsw28u_richtext_vc_custom.dll" "$SYSDIR" !insertmacro InstallLib DLL $ALREADY_INSTALLED REBOOT_NOTPROTECTED "C:\wxWidgets-2.8\lib\vc_dll\wxmsw28u_xrc_vc_custom.dll" "$SYSDIR\wxmsw28u_xrc_vc_custom.dll" "$SYSDIR" ; write out uninstaller WriteUninstaller "$INSTDIR\uninstall.exe" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\LocDemo" "DisplayName" "LocDemo" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\LocDemo" "UninstallString" "$INSTDIR\uninstall.exe" Sectionend Section -startmenu CreateDirectory "$SMPROGRAMS\LocDemo" CreateShortCut "$SMPROGRAMS\LocDemo\LocDemo.lnk" "$INSTDIR\LocDemo.exe" "" "$INSTDIR\icon.ico" 0 CreateShortCut "$SMPROGRAMS\LocDemo\trace.lnk" "$INSTDIR\trace.exe" "" "" 0 CreateShortCut "$SMPROGRAMS\LocDemo\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 Sectionend ; begin uninstall settings/section UninstallText "This will uninstall the LocDemo software from your system" Section Uninstall DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\LocDemo" Delete "$INSTDIR\*.*" RMDir /r $INSTDIR Delete "$SMPROGRAMS\LocDemo\*.*" RMDir "$SMPROGRAMS\LocDemo" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\libwlocate.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxbase28u_net_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxbase28u_odbc_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxbase28u_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxbase28u_xml_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_adv_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_aui_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_core_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_gl_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_html_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_media_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_richtext_vc_custom.dll" !insertmacro UnInstallLib DLL SHARED REBOOT_NOTPROTECTED "$SYSDIR\wxmsw28u_xrc_vc_custom.dll" SectionEnd ; end of uninstall section libwlocate-0.0git20130108/locdemo/LocDemoApp.cpp0000775000175000017500000000227512073002423016746 0ustar jrjr/** * LocDemo - a demo GUI application that uses libwlocate to display the * current geographic position * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "LocDemoApp.h" #include "LocDemoWin.h" #include IMPLEMENT_APP(LocDemoApp) bool LocDemoApp::OnInit() { LocDemoWin *myWin; wxLog::EnableLogging(false); wxInitAllImageHandlers(); wxSocketBase::Initialize(); myWin = new LocDemoWin(wxT("OpenWLANMap Location Demo")); if (!wxApp::OnInit()) return false; myWin->Show(true); return true; } libwlocate-0.0git20130108/locdemo/LocDemoApp.h0000775000175000017500000000166212073002423016412 0ustar jrjr/** * LocDemo - a demo GUI application that uses libwlocate to display the * current geographic position * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include class LocDemoApp : public wxApp { public: virtual bool OnInit(); private: wxString m_mac; }; libwlocate-0.0git20130108/locdemo/README0000775000175000017500000000172712073002423015140 0ustar jrjrThis is a demo application that makes use of libwlocate. It uses this library to get the current geographic position, then downloads the related map tiles from the OpenStreetMap project (please refer to http://www.openstreetmap.org for detail) and displays them within the main screen. The calculated geographic position is highlighted with a red circle. Its radius differs and depends on the quality of the returned location result. Additionally it can be used to load a libwlocate.trace file as generated by the command line tool lwtrace to track the positions where a user has been. This file contains WLAN data which are converted to geographic positions by LocDemo. These positions form a path that are drawn into the LocDemo map. This function can be used to track positions a user has been. This application uses the wxWidgets toolkit (from http://www.wxwidgets.org ) for the user interface. To compile it from source the related wxWidgets development files are required. libwlocate-0.0git20130108/locdemo/locdemo.dsp0000775000175000017500000001505212073002423016406 0ustar jrjr# Microsoft Developer Studio Project File - Name="locdemo" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Application" 0x0101 CFG=locdemo - Win32 DLL Unicode Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "locdemo.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "locdemo.mak" CFG="locdemo - Win32 DLL Unicode Release" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "locdemo - Win32 DLL Unicode Release" (based on "Win32 (x86) Application") !MESSAGE "locdemo - Win32 DLL Unicode Debug" (based on "Win32 (x86) Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe MTL=midl.exe RSC=rc.exe !IF "$(CFG)" == "locdemo - Win32 DLL Unicode Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "vc_mswudll" # PROP BASE Intermediate_Dir "vc_mswudll\locdemo" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "vc_mswudll" # PROP Intermediate_Dir "vc_mswudll\locdemo" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MD /W4 /GR /O2 /I ".\..\..\lib\vc_dll\mswu" /I ".\..\..\include" /I "." /I ".\..\..\samples" /D "WIN32" /D "__WXMSW__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /Fd"vc_mswudll\locdemo.pdb" /FD /EHsc /c # ADD CPP /nologo /MD /W4 /GR /O2 /I "C:\wxWidgets-2.8\lib\vc_dll\mswu" /I ".\..\..\lib\vc_dll\mswu" /I "C:\wxWidgets-2.8\include" /I "." /I ".." /D "WIN32" /D "__WXMSW__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /D "ENV_WINDOWS" /D "ENV_EDITOR" /FR /Fd"vc_mswudll\locdemo.pdb" /FD /EHsc /c # ADD BASE MTL /nologo /D "WIN32" /D "__WXMSW__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /mktyplib203 /win32 # ADD MTL /nologo /D "WIN32" /D "__WXMSW__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /i ".\..\..\lib\vc_dll\mswu" /i ".\..\..\include" /i "." /i ".\..\..\samples" /d "__WXMSW__" /d "_UNICODE" /d "WXUSINGDLL" /d "_WINDOWS" /d "NOPCH" # ADD RSC /l 0x409 /i ".\..\..\lib\vc_dll\mswu" /i ".\..\..\include" /i "." /i ".\..\..\samples" /d "__WXMSW__" /d "_UNICODE" /d "WXUSINGDLL" /d "_WINDOWS" /d "NOPCH" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 wxmsw28u_core.lib wxbase28u.lib wxtiff.lib wxjpeg.lib wxpng.lib wxzlib.lib wxregexu.lib wxexpat.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib wsock32.lib odbc32.lib /nologo /subsystem:windows /machine:I386 /libpath:".\..\..\lib\vc_dll" # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 wxbase28u_net.lib wxmsw28u_xrc.lib wxbase28u_xml.lib wxmsw28u_adv.lib wxmsw28u_core.lib wxbase28u.lib wxtiff.lib wxjpeg.lib wxpng.lib wxzlib.lib wxregexu.lib wxexpat.lib netapi32.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib wsock32.lib odbc32.lib ../Release/libwlocate.lib /nologo /subsystem:windows /machine:I386 /out:"LocDemo.exe" /libpath:"..\Release\\" /libpath:"C:\wxWidgets-2.8\lib\vc_dll" # SUBTRACT LINK32 /pdb:none !ELSEIF "$(CFG)" == "locdemo - Win32 DLL Unicode Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "vc_mswuddll" # PROP BASE Intermediate_Dir "vc_mswuddll\locdemo" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "vc_mswuddll" # PROP Intermediate_Dir "vc_mswuddll\locdemo" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MDd /W4 /Gm /GR /Zi /Od /I ".\..\..\lib\vc_dll\mswud" /I ".\..\..\include" /I "." /I ".\..\..\samples" /D "WIN32" /D "_DEBUG" /D "__WXMSW__" /D "__WXDEBUG__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /Fd"vc_mswuddll\locdemo.pdb" /FD /EHsc /c # ADD CPP /nologo /MDd /W4 /Gm /GR /ZI /Od /I "C:\wxWidgets-2.8\lib\vc_dll\mswud" /I "C:\wxWidgets-2.8\include" /I "." /I ".." /D "WIN32" /D "_DEBUG" /D "__WXMSW__" /D "__WXDEBUG__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /D "ENV_EDITOR" /D "ENV_WINDOWS" /FR /Fd"vc_mswuddll\locdemo.pdb" /FD /EHsc /c # ADD BASE MTL /nologo /D "WIN32" /D "_DEBUG" /D "__WXMSW__" /D "__WXDEBUG__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /mktyplib203 /win32 # ADD MTL /nologo /D "WIN32" /D "_DEBUG" /D "__WXMSW__" /D "__WXDEBUG__" /D "_UNICODE" /D "WXUSINGDLL" /D "_WINDOWS" /D "NOPCH" /mktyplib203 /win32 # ADD BASE RSC /l 0x409 /i ".\..\..\lib\vc_dll\mswud" /i ".\..\..\include" /i "." /i ".\..\..\samples" /d "_DEBUG" /d "__WXMSW__" /d "__WXDEBUG__" /d "_UNICODE" /d "WXUSINGDLL" /d "_WINDOWS" /d "NOPCH" # ADD RSC /l 0x409 /i ".\..\..\lib\vc_dll\mswud" /i ".\..\..\include" /i "." /i ".\..\..\samples" /d "_DEBUG" /d "__WXMSW__" /d "__WXDEBUG__" /d "_UNICODE" /d "WXUSINGDLL" /d "_WINDOWS" /d "NOPCH" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 wxmsw28ud_core.lib wxbase28ud.lib wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib wxregexud.lib wxexpatd.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib wsock32.lib odbc32.lib /nologo /subsystem:windows /debug /machine:I386 /libpath:".\..\..\lib\vc_dll" # SUBTRACT BASE LINK32 /pdb:none # ADD LINK32 wxmsw28ud_xrc.lib wxbase28ud_xml.lib wxmsw28ud_adv.lib wxmsw28ud_core.lib wxbase28ud.lib wxtiffd.lib wxjpegd.lib wxpngd.lib wxzlibd.lib wxregexud.lib wxexpatd.lib netapi32.lib kernel32.lib user32.lib gdi32.lib comdlg32.lib winspool.lib winmm.lib shell32.lib comctl32.lib ole32.lib oleaut32.lib uuid.lib rpcrt4.lib advapi32.lib wsock32.lib odbc32.lib libwlocate.lib wxbase28ud_net.lib /nologo /subsystem:windows /debug /machine:I386 /out:"LocDemo.exe" /libpath:"..\Debug\\" /libpath:"C:\wxWidgets-2.8\lib\vc_dll" # SUBTRACT LINK32 /pdb:none !ENDIF # Begin Target # Name "locdemo - Win32 DLL Unicode Release" # Name "locdemo - Win32 DLL Unicode Debug" # Begin Group "Source Files" # PROP Default_Filter "" # Begin Source File SOURCE=.\LocDemoApp.cpp # End Source File # Begin Source File SOURCE=.\LocDemoWin.cpp # End Source File # End Group # Begin Source File SOURCE=.\icon.ico # End Source File # End Target # End Project libwlocate-0.0git20130108/locdemo/icon.ico0000775000175000017500000000137612073002423015704 0ustar jrjr ( @#D>y'/Ir|kx.sVk3sUu{sw3josts>Nycx??~"a?libwlocate-0.0git20130108/locdemo/lin_setup.spec0000775000175000017500000000224612073002423017133 0ustar jrjrSummary: LocDemo libwlocate demo application Name: LocDemo Version: 1.1 Release: 1 License: GPL Packager: http://www.openwlanmap.org Group: Applications/Internet Requires: wxGTK, wireless-tools %description A WLAN geolocation demonstration application that makes use of libwlocate and the data of project OpenWLANMap. It is recommended to execute this application with root privileges to get more detailed WLAN information and to get a more exact position information. %files /etc/init.d/* /usr/* %pre if [ -x /sbin/LocDemo ]; then rm -f /sbin/LocDemo fi if [ -x /etc/init.d/wlocd ]; then /etc/init.d/wlocd stop fi %preun /etc/init.d/wlocd stop rm -rf /etc/rc5.d/S99wlocd 1>/dev/null 2>/dev/null rm -rf /etc/rc5.d/K01wlocd 1>/dev/null 2>/dev/null rm -rf /etc/rc3.d/S99wlocd 1>/dev/null 2>/dev/null rm -rf /etc/rc3.d/K01wlocd 1>/dev/null 2>/dev/null %post ln -s /etc/init.d/wlocd /etc/rc5.d/S99wlocd 1>/dev/null 2>/dev/null ln -s /etc/init.d/wlocd /etc/rc5.d/K01wlocd 1>/dev/null 2>/dev/null ln -s /etc/init.d/wlocd /etc/rc3.d/S99wlocd 1>/dev/null 2>/dev/null ln -s /etc/init.d/wlocd /etc/rc3.d/K01wlocd 1>/dev/null 2>/dev/null ldconfig /etc/init.d/wlocd start 1>/dev/null 2>/dev/null libwlocate-0.0git20130108/locdemo/locdemo.dsw0000775000175000017500000000077212073002423016420 0ustar jrjrMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "bombs"=.\locdemo.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### libwlocate-0.0git20130108/locdemo/postinst0000777000175000017500000000000012073002423024252 2setup_data/LocDemo/DEBIAN/postinstustar jrjrlibwlocate-0.0git20130108/locdemo/control0000777000175000017500000000000012073002423023644 2setup_data/LocDemo/DEBIAN/controlustar jrjrlibwlocate-0.0git20130108/locdemo/preinst0000777000175000017500000000000012073002423023654 2setup_data/LocDemo/DEBIAN/preinstustar jrjrlibwlocate-0.0git20130108/locdemo/Makefile.QNX0000775000175000017500000000116312073002423016357 0ustar jrjrPROGRAM = LocDemo INCLUDEDIRS = -I/usr/X11R6/include -I.. $(shell wx-config --cflags) $(shell pkg-config gtk+-2.0 --cflags) LIBDIRS = -L/usr/X11R6/lib -L/usr/lib LIBS = $(shell wx-config --libs) -lph -lwlocate DBGFLAGS = -O2 -g0 -DNDEBUG ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 -DNOSPLASH endif CXXSOURCES = LocDemoApp.cpp LocDemoWin.cpp CXXOBJECTS = $(CXXSOURCES:.cpp=.o) CXXFLAGS = -Wall -DESRI_UNIX -DENV_QNX $(INCLUDEDIRS) $(DBGFLAGS) CXX = g++ LDFLAGS = $(LIBDIRS) $(LIBS) all: $(PROGRAM) $(PROGRAM): $(CXXOBJECTS) $(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS) strip $(PROGRAM) clean: $(RM) -f $(CXXOBJECTS) $(PROGRAM) libwlocate-0.0git20130108/locdemo/LocDemo-icon.png0000775000175000017500000000355412073002423017236 0ustar jrjrPNG  IHDR00` PLTEDBD$"$dbdTRT424trt LJL,*,ljl\Z\<=<|{|DFD$&$dfdTVT464tvt  LNL,.,lnl\^\ⳓtRNSHi pHYs%%IR$IDATxڵVb@-ĺH, !,!6 *f>,9sHyw>H5s (3ӈ(X,pK.[+u psM@śROsվ0j?˔15[ř\Ph\XNѺ+֛ȴ]B4Zq \dST'A' lhpqT:x {uBXQXlfR :r:{'u$r-`&W}k=+n Kz3ч4ZUܧ{w(|:M^ Bn~r&eiFdL|M`t@5n,c=,'+W#~P9Xɇgy]]3)3i&ۍDEe*~l$)F^N-ILKZ"9ΣS/J S^.E#`77#~#".=- ^E f ACn+b]k0 ,uEe|gBo$iLAs 0HLo'΀LZl3*0*QSҖZPy'^[ם" nY>Ρh0Ar%1"է}̍MdcP#!䘝cf~N>.IENDB`libwlocate-0.0git20130108/locdemo/LocDemoWin.cpp0000775000175000017500000004073312073002423016764 0ustar jrjr/** * LocDemo - a demo GUI application that uses libwlocate to display the * current geographic position * Copyright (C) 2010-2012 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "LocDemoWin.h" #include #include #include #include #include #include #include #include "libwlocate.h" using namespace std; #define X_OFFSET 162 extern "C" { extern int get_position(struct wloc_req *request,double *lat,double *lon,char *quality,short *ccode); } IMPLEMENT_CLASS(LocDemoWin, wxFrame) BEGIN_EVENT_TABLE(LocDemoWin, wxFrame) EVT_BUTTON(wxID_ANY,LocDemoWin::OnButton) EVT_PAINT(LocDemoWin::OnPaint) EVT_TIMER(1,LocDemoWin::OnTimer) END_EVENT_TABLE() /** * Main constructor, here the window and the ui-elements on the left are created and added to some sizers */ LocDemoWin::LocDemoWin(const wxString& title) :wxFrame(NULL, wxID_ANY, title, wxPoint(20,0), wxSize(930,768),wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxSYSTEM_MENU|wxCAPTION|wxCLOSE_BOX|wxCLIP_CHILDREN) { wxInt32 x,y; for (x=-1; x<=1; x++) for (y=-1; y<=1; y++) locTile[x+1][y+1]=NULL; m_zoom=17; m_traceMode=false; SetBackgroundColour(*wxWHITE); wxFlexGridSizer *fSizer=new wxFlexGridSizer(1,2,2,2); this->SetSizer(fSizer); fSizer->AddGrowableCol(0,1); fSizer->AddGrowableCol(1,10); wxPanel *rootPanel=new wxPanel(this);//,WXID_ANY,wxDefaultPos,wxSize(X_OFFSET,750)); fSizer->Add(rootPanel); wxGridSizer *gSizer=new wxGridSizer(12,1,2,2); rootPanel->SetBackgroundColour(*wxWHITE); rootPanel->SetSizer(gSizer); wxStaticText *text=new wxStaticText(rootPanel,wxID_ANY,_T("")); gSizer->Add(text,0,wxALIGN_LEFT); updateButton=new wxButton(rootPanel,wxID_ANY,_T("Update Position")); gSizer->Add(updateButton,1,wxEXPAND); text=new wxStaticText(rootPanel,wxID_ANY,_T("Latitude:")); gSizer->Add(text,0,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); m_latField=new wxTextCtrl(rootPanel,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,wxTE_READONLY); gSizer->Add(m_latField,1,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); text=new wxStaticText(rootPanel,wxID_ANY,_T("Longitude:")); gSizer->Add(text,0,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); m_lonField=new wxTextCtrl(rootPanel,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,wxTE_READONLY); gSizer->Add(m_lonField,1,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); text=new wxStaticText(rootPanel,wxID_ANY,_T("Quality:")); gSizer->Add(text,0,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); m_qualityField=new wxTextCtrl(rootPanel,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,wxTE_READONLY); gSizer->Add(m_qualityField,1,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); text=new wxStaticText(rootPanel,wxID_ANY,_T("Country:")); gSizer->Add(text,0,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); m_countryField=new wxTextCtrl(rootPanel,wxID_ANY,wxEmptyString,wxDefaultPosition,wxDefaultSize,wxTE_READONLY); gSizer->Add(m_countryField,1,wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL); m_followPathCB=new wxCheckBox(rootPanel,wxID_ANY,_T("Update cyclically")); gSizer->Add(m_followPathCB,1,wxEXPAND); zoomInButton=new wxButton(rootPanel,wxID_ANY,_T("Zoom In")); gSizer->Add(zoomInButton,1,wxEXPAND); zoomOutButton=new wxButton(rootPanel,wxID_ANY,_T("Zoom Out")); gSizer->Add(zoomOutButton,1,wxEXPAND); traceButton=new wxButton(rootPanel,wxID_ANY,_T("Load Tracefile")); gSizer->Add(traceButton,1,wxEXPAND); infoButton=new wxButton(rootPanel,wxID_ANY,_T("About")); gSizer->Add(infoButton,1,wxEXPAND); SetDoubleBuffered(true); getLocation(false,NULL); m_timer = new wxTimer(this,1); m_timer->Start(8000); } LocDemoWin::~LocDemoWin() { wxInt32 x,y; for (x=-1; x<=1; x++) for (y=-1; y<=1; y++) if (locTile[x+1][y+1]) delete locTile[x+1][y+1]; } /** * Timer callback function, it is called cyclically and in case the m_followPathCB check box is * checked it updates the current position by calling getLocation() */ void LocDemoWin::OnTimer(wxTimerEvent& WXUNUSED(event)) { if (m_followPathCB->GetValue()) { m_timer->Stop(); getLocation(true,NULL); Refresh(); m_timer->Start(); } } /** * Gets the horizontal part of a tile number out of a given position * @param[in] lon the longitude to get the tile number for * @param[in] z the zoom level to get the tile number for * @return the tiles x number */ static int long2tilex(double lon, int z) { return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z))); } /** * Gets the vertical part of a tile number out of a given position * @param[in] lat the latitude to get the tile number for * @param[in] z the zoom level to get the tile number for * @return the tiles y number */ static int lat2tiley(double lat, int z) { return (int)(floor((1.0 - log( tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z))); } /** * Gets the longitude of the side edge of a tile out of a given horizontal * tile number * @param[in] x the horizontal tile number * @param[in] z the zoom level to get the tile number for * @return the longitude of the left position of the tile */ static double tilex2long(int x, int z) { return x / pow(2.0, z) * 360.0 - 180; } /** * Gets the latitude of the upper side of a tile out of a given vertical * tile number * @param[in] y the vertical tile number * @param[in] z the zoom level to get the tile number for * @return the latitude of the upper position of the tile */ static double tiley2lat(int y, int z) { double n = M_PI - 2.0 * M_PI * y / pow(2.0, z); return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); } /** * The paint callback, here the map tiles, the path (if it has a size >=2) * and the current position including its deviation are drawn */ void LocDemoWin::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxInt32 x,y; double tileLat1,tileLon1,tileLat2,tileLon2; wxPaintDC dc(this); wxPen borderPen(*wxRED,3); wxPen pathPen(*wxBLUE,2); list::iterator itLat,itLon; for (x=-1; x<=1; x++) for (y=-1; y<=1; y++) { if (locTile[x+1][y+1]) { dc.DrawBitmap(*locTile[x+1][y+1],((x+1)*256)+X_OFFSET,(y+1)*256,false); } } tileLat1=tiley2lat(m_tileY,m_zoom); tileLat2=tiley2lat(m_tileY+1,m_zoom); tileLon1=tilex2long(m_tileX,m_zoom); tileLon2=tilex2long(m_tileX+1,m_zoom); dc.SetBrush(*wxTRANSPARENT_BRUSH); if (m_latList.size()>1) { double currY,currX,prevY,prevX; dc.SetPen(pathPen); itLat=m_latList.begin(); itLat++; itLon=m_lonList.begin(); itLon++; prevY=256+ (256.0*(*itLat-tileLat1)/(tileLat2-tileLat1)); prevX=256+X_OFFSET+(256.0*(*itLon-tileLon1)/(tileLon2-tileLon1)); for ( ; itLat!= m_latList.end(); itLat++ ) { currY=256+ (256.0*(*itLat-tileLat1)/(tileLat2-tileLat1)); currX=256+X_OFFSET+(256.0*(*itLon-tileLon1)/(tileLon2-tileLon1)); dc.DrawLine(prevX,prevY,currX,currY); prevY=currY; prevX=currX; itLon++; } } y=256+ (256.0*(m_lat-tileLat1)/(tileLat2-tileLat1)); x=256+X_OFFSET+(256.0*(m_lon-tileLon1)/(tileLon2-tileLon1)); if ((x!=0) && (y!=0)) { wxFloat64 zoomFactor; dc.SetPen(borderPen); if (m_quality>0) { zoomFactor=pow(2.0,(17.0-m_zoom)); dc.DrawCircle(x,y,(120-m_quality)/zoomFactor); } else { zoomFactor=pow(2.0,(10.0-m_zoom)); dc.DrawCircle(x,y,130/zoomFactor); } } } /** * This method updates the internal locTile array that holds bitmaps of the tiles that have to be * displayed currently. To get the tile images it first tries to load a local PNG image. In case * that fails the TAH server is connected to download and save a tile image in PNG format. Then it * tries again to load the local PNG image - now it should be successful because it was downloaded * just one step before. * @param[in] lat the latitude of the current position which has to be displayed in center tile * @param[in] lon the longitude of the current position which has to be displayed in center tile */ void LocDemoWin::updateTiles(wxFloat64 lat,wxFloat64 lon) { wxInt32 x,y; wxHTTP *get; wxString path; wxInputStream *httpStream; wxImage *tmpImage; m_tileX=long2tilex(lon,m_zoom); m_tileY=lat2tiley(lat,m_zoom); for (x=-1; x<=1; x++) for (y=-1; y<=1; y++) { if (locTile[x+1][y+1]) delete locTile[x+1][y+1]; locTile[x+1][y+1]=NULL; if (!wxFile::Exists(wxStandardPaths::Get().GetUserDataDir()+wxFileName::GetPathSeparator()+wxString::Format(_T("tile_%d_%d_%d.png"),m_zoom,m_tileX+x,m_tileY+y))) { get=new wxHTTP(); get->SetTimeout(10); // 10 seconds of timeout instead of 10 minutes ... get->SetHeader(_T("User-Agent"),_T("LocDemo libwlocate demo application")); while (!get->Connect(_T("a.tile.openstreetmap.org"))) wxSleep(5); path=wxString::Format(_T("/%d/%d/%d.png"),m_zoom,m_tileX+x,m_tileY+y); httpStream = get->GetInputStream(path); if (get->GetError() == wxPROTO_NOERR) { wxFile *FHandle; wxFileName::Mkdir(wxStandardPaths::Get().GetUserDataDir()); path=wxStandardPaths::Get().GetUserDataDir()+wxFileName::GetPathSeparator()+wxString::Format(_T("tile_%d_%d_%d.png"),m_zoom,m_tileX+x,m_tileY+y); FHandle=new wxFile(path,wxFile::write); if ((FHandle) && (FHandle->IsOpened())) { void *mem; mem=malloc(httpStream->GetSize()); if (mem) { httpStream->Read(mem,httpStream->GetSize()); FHandle->Write(mem,httpStream->GetSize()); delete FHandle; free(mem); } } wxDELETE(httpStream); } get->Close(); delete get; } path=wxStandardPaths::Get().GetUserDataDir()+wxFileName::GetPathSeparator()+wxString::Format(_T("tile_%d_%d_%d.png"),m_zoom,m_tileX+x,m_tileY+y); tmpImage=new wxImage(path,wxBITMAP_TYPE_PNG); if ((tmpImage) && (tmpImage->Ok())) { locTile[x+1][y+1]=new wxBitmap(*tmpImage); delete tmpImage; } } } /** * Here the current geolocation is evaluated by calling the related function of libwlocate. * Afterwards the tiles are updated and drawn. * @param[in] silent if this value is set to true no splash screen is displayed during * position and tile update */ void LocDemoWin::getLocation(bool silent,struct wloc_req *requestData) { wxInt32 ret; wxFrame *splash=NULL; if (!silent) { splash = new wxFrame(NULL,wxID_ANY,_T("Getting Position Data and Map"),wxDefaultPosition,wxSize(500,80),wxSTAY_ON_TOP|wxFRAME_NO_TASKBAR|wxCAPTION); new wxStaticText(splash,wxID_ANY,_T("Operation in progress, please wait..."),wxPoint(20,30)); splash->Center(); #ifndef _DEBUG splash->Show(); #endif } m_lat=0; m_lon=0; m_quality=0; if (!requestData) ret=wloc_get_location(&m_lat,&m_lon,&m_quality,&m_ccode); else { ret=get_position(requestData,&m_lat,&m_lon,&m_quality,&m_ccode); if (ret!=WLOC_OK) printf("Loading trace location failed..."); } if (ret==WLOC_OK) { char country[3]={0,0,0}; wxMBConvUTF8 conv; wchar_t wc[3]; m_latField->SetValue(_T("")); *m_latField<SetValue(_T("")); *m_lonField<0) { m_latList.push_back(m_lat); m_lonList.push_back(m_lon); } else if (m_traceMode) return; // do not use IP-Data only in case of trace mode m_qualityField->SetValue(_T("")); *m_qualityField<GetValue()) { if (m_quality==0) m_zoom=10; else { if (!m_traceMode) m_zoom=17; } } if (wloc_get_country_from_code(m_ccode,country)==WLOC_OK) { conv.MB2WC(wc,country,3); m_countryField->SetValue(_T("")); *m_countryField<SetValue(_T("?")); updateTiles(m_lat,m_lon); if (!silent) splash->Close(); delete splash; } else if (!requestData) { m_latField->SetValue(_T("---")); m_lonField->SetValue(_T("---")); m_qualityField->SetValue(_T("---")); m_countryField->SetValue(_T("--")); splash->Close(); delete splash; if (ret==WLOC_CONNECTION_ERROR) wxMessageBox(_T("Could not connect to server and retrieve data!"),_T("Error"),wxOK|wxICON_ERROR); else if (ret==WLOC_LOCATION_ERROR) wxMessageBox(_T("Could not retrieve location, no data available for your position!"),_T("Error"),wxOK|wxICON_ERROR); else wxMessageBox(_T("Could not retrieve location, an unidentified error happened :-("),_T("Error"),wxOK|wxICON_ERROR); } } /** * The button event handler, here the functionality of the zoom and about buttons are managed */ void LocDemoWin::OnButton(wxCommandEvent &event) { if (event.GetId()==updateButton->GetId()) { getLocation(false,NULL); Refresh(); } else if (event.GetId()==zoomOutButton->GetId()) { if (m_zoom>2) m_zoom--; updateTiles(m_lat,m_lon); Refresh(); } else if (event.GetId()==zoomInButton->GetId()) { if (m_zoom<17) m_zoom++; updateTiles(m_lat,m_lon); Refresh(); } else if (event.GetId()==traceButton->GetId()) { FILE *FHandle; wxInt32 i,ret=1; struct wloc_req requestData,prevData; wxPaintEvent pEvent; wxFileDialog* openFileDialog=new wxFileDialog( this,_T("Load trace file"),wxEmptyString,wxEmptyString,_T("Trace-File |*.trace|All files|*.*"),wxFD_OPEN, wxDefaultPosition); if ( openFileDialog->ShowModal() == wxID_OK ) { wxString path; wxMBConvLibc conv; char cPath[300+1]; path=openFileDialog->GetDirectory()+wxFileName::GetPathSeparator()+openFileDialog->GetFilename(); conv.WC2MB(cPath,path,300); memset(&requestData,0,sizeof(struct wloc_req)); memset(&prevData,0,sizeof(struct wloc_req)); m_followPathCB->SetValue(false); m_latList.clear(); m_lonList.clear(); Refresh(); FHandle=fopen(cPath,"rb"); if (FHandle) { m_traceMode=true; memset(&requestData,0,sizeof(struct wloc_req)); while (ret>0) { for (i=0; iGetId()) wxMessageBox(_T("LocDemo Version 1.1 is (c) 2010 by Oxy/VWP\nIt demonstrates the usage of libwlocate and is available under the terms of the GNU Public License\nFor more details please refer to http://www.openwlanmap.org"),_T("Information"),wxOK|wxICON_INFORMATION); } bool LocDemoWin::notEqual(struct wloc_req *data1,struct wloc_req *data2) { wxUint32 i,j; for (i=0; isignal[i]!=data2->signal[i]) return true; for (j=0; j<6; j++) { if (data1->bssids[i][j]!=data2->bssids[i][j]) return true; } } return false; } libwlocate-0.0git20130108/locdemo/setup_data/0000775000175000017500000000000012073002423016377 5ustar jrjrlibwlocate-0.0git20130108/locdemo/setup_data/LocDemo/0000775000175000017500000000000012073002423017721 5ustar jrjrlibwlocate-0.0git20130108/locdemo/setup_data/LocDemo/DEBIAN/0000775000175000017500000000000012073002423020643 5ustar jrjrlibwlocate-0.0git20130108/locdemo/setup_data/LocDemo/DEBIAN/postinst0000775000175000017500000000051412073002423022454 0ustar jrjr#!/bin/sh /etc/init.d/wlocd start 1>/dev/null 2>/dev/null ln -s /etc/init.d/wlocd /etc/rc5.d/S99wlocd ln -s /etc/init.d/wlocd /etc/rc5.d/K01wlocd ln -s /etc/init.d/wlocd /etc/rc3.d/S99wlocd ln -s /etc/init.d/wlocd /etc/rc3.d/K01wlocd ln -s /etc/init.d/wlocd /etc/rc2.d/S99wlocd ln -s /etc/init.d/wlocd /etc/rc2.d/K01wlocd ldconfig libwlocate-0.0git20130108/locdemo/setup_data/LocDemo/DEBIAN/control0000775000175000017500000000055512073002423022256 0ustar jrjrPackage: locdemo Version: 1.1 Section: internet Priority: optional Architecture: i386 Essential: no Depends: libwxgtk2.8-0 Recommends: Suggests: Installed-Size: 2520 Maintainer: virtual_worlds@gmx.de Conflicts: Replaces: Provides: LocDemo Description: A WLAN geolocation demonstration application that makes use of libwlocate and the data of project OpenWLANMap. libwlocate-0.0git20130108/locdemo/setup_data/LocDemo/DEBIAN/preinst0000775000175000017500000000020212073002423022247 0ustar jrjr#!/bin/sh if [ -x /sbin/LocDemo ]; then rm -f /sbin/LocDemo fi if [ -x /etc/init.d/wlocd ]; then /etc/init.d/wlocd stop fi libwlocate-0.0git20130108/locdemo/setup_data/LocDemo/DEBIAN/prerm0000775000175000017500000000025412073002423021717 0ustar jrjr#!/bin/sh /etc/init.d/wlocd stop rm /etc/rc5.d/S99wlocd rm /etc/rc5.d/K01wlocd rm /etc/rc3.d/S99wlocd rm /etc/rc3.d/K01wlocd rm /etc/rc2.d/S99wlocd rm /etc/rc2.d/K01wlocd libwlocate-0.0git20130108/locdemo/LocDemoWin.h0000775000175000017500000000363112073002423016425 0ustar jrjr/** * LocDemo - a demo GUI application that uses libwlocate to display the * current geographic position * Copyright (C) 2010 Oxygenic/VWP virtual_worlds(at)gmx.de * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include class LocDemoWin : public wxFrame { public: LocDemoWin(const wxString& title); virtual ~LocDemoWin(); private: void OnButton(wxCommandEvent &event); void OnPaint(wxPaintEvent& event); void OnTimer(wxTimerEvent& event); void updateTiles(wxFloat64 lat,wxFloat64 lon); void getLocation(bool silent,struct wloc_req *requestData); bool notEqual(struct wloc_req *data1,struct wloc_req *prevData); wxButton *updateButton,*infoButton,*zoomInButton,*zoomOutButton,*traceButton; wxBitmap *locTile[3][3]; wxInt32 m_tileX,m_tileY; wxTextCtrl *m_latField,*m_lonField,*m_qualityField,*m_countryField; wxCheckBox *m_followPathCB; double m_lat,m_lon; char m_quality; short m_ccode; wxByte m_zoom; wxTimer *m_timer; std::list m_latList,m_lonList; bool m_traceMode; DECLARE_CLASS(LocDemoWin) DECLARE_EVENT_TABLE() }; libwlocate-0.0git20130108/locdemo/prerm0000777000175000017500000000000012073002423022756 2setup_data/LocDemo/DEBIAN/prermustar jrjrlibwlocate-0.0git20130108/locdemo/Makefile0000775000175000017500000000121412073002423015707 0ustar jrjrPROGRAM = LocDemo INCLUDEDIRS = -I/usr/X11R6/include -I.. $(shell wx-config --cflags) $(shell pkg-config gtk+-2.0 --cflags) LIBDIRS = -L/usr/X11R6/lib -L/usr/lib LIBS = $(shell wx-config --libs) -lwlocate DBGFLAGS = -O2 -g0 -DNDEBUG STRIP=strip ifeq ($(DEBUG),1) DBGFLAGS = -O0 -g3 -DNOSPLASH STRIP=ls -al endif CXXSOURCES = LocDemoApp.cpp LocDemoWin.cpp CXXOBJECTS = $(CXXSOURCES:.cpp=.o) CXXFLAGS = -Wall -DESRI_UNIX -DENV_LINUX $(INCLUDEDIRS) $(DBGFLAGS) CXX = g++ LDFLAGS = $(LIBDIRS) $(LIBS) all: $(PROGRAM) $(PROGRAM): $(CXXOBJECTS) $(CXX) -o $@ $(CXXOBJECTS) $(LDFLAGS) $(STRIP) $(PROGRAM) clean: $(RM) -f $(CXXOBJECTS) $(PROGRAM) libwlocate-0.0git20130108/libwlocate.dsw0000775000175000017500000000100212073002423015464 0ustar jrjrMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "libwlocate"=.\libwlocate.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### libwlocate-0.0git20130108/android/0000775000175000017500000000000012073002423014244 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/0000775000175000017500000000000012073002423015566 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/.project0000664000175000017500000000146112073002423017237 0ustar jrjr AndroidLocDemo com.android.ide.eclipse.adt.ResourceManagerBuilder com.android.ide.eclipse.adt.PreCompilerBuilder org.eclipse.jdt.core.javabuilder com.android.ide.eclipse.adt.ApkBuilder com.android.ide.eclipse.adt.AndroidNature org.eclipse.jdt.core.javanature libwlocate-0.0git20130108/android/LocDemo/.classpath0000664000175000017500000000056412073002423017556 0ustar jrjr libwlocate-0.0git20130108/android/LocDemo/res/0000775000175000017500000000000012073002423016357 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/res/values/0000775000175000017500000000000012073002423017656 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/res/values/strings.xml0000664000175000017500000000015512073002423022072 0ustar jrjr LocDemo libwlocate-0.0git20130108/android/LocDemo/res/layout/0000775000175000017500000000000012073002423017674 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/res/layout/main.xml0000664000175000017500000000057612073002423021352 0ustar jrjr libwlocate-0.0git20130108/android/LocDemo/res/drawable-hdpi/0000775000175000017500000000000012073002423021062 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/res/drawable-hdpi/icon.png0000664000175000017500000001006312073002423022520 0ustar jrjrPNG  IHDRHHUGsBIT|d pHYs B4tEXtSoftwareAdobe Fireworks CS4ӠIDATxyp]}?mҳlY,c6f1,g@&4ILBt2&4M-fiJ$L ;aIo͖ޓzY}z-'bWOܳ|ιGXkySC wOPOPB *zm>Si FS*5+AUQU5%TOĀ '?ikE*"jE~(TӒ$Dm}o|uB oe $(3R_ﵶ{4ZϿ0>[_~6"M*D4b5 VM]Iޫ0<0 XD9!hIFB1M*!FlQHNYj:Rlq+cmCU2D* p LGH6U.FJ"{1y01kԉ6 W$mx/JWuC X)cic:u1FKI UΖu\{;:$dә@9n'j\(90Xk݉V,:TJa* (Q|DRFCV UPa k$6t;Qau;(}i9hQXy5Qf̾B[j[HYz!]X VAoG u\ .qq_/eq<6{Z.~k ʄ7U_!eU4=lM'ipLk$etĮ(TY JXgl9ge.cEde_bב)H< HEK?Oɕjw w)1P7c9n:3ւ5 $pϑY޶ GİVsxl /JÂr!J,ܛ<.LWދHEe+JK2ěTieB7%Qv1JŊW-چ^qs[F083&/qEBd+HzR,teCJdYX64Bow=AZ?AXZA`uhmjZkU> muX}Zku5cJ2Q~طLM˪m`FT FѺUT0o?e'@'MǗ?ǡ6# 0# :P©}Fj!RX̸c0V}fBkь4ڵ16~5G3a(*z:[4fl-<.: h:sM DSKJx7mEkhQ.Rx<޶yn&DŽČm"đ To"R)X-NHil%NoxΌᵑٗ}7z)#z_sX?yVf6#˫~D)N4w2~Ƈ݉g^ziT-xwZ[&W4PWq{6OUvn['[ bx޾!}H몢: 9gK]IOz#Gر}' zqrqv4 P@raYu+C7 n]¡/"`Ԥ{TtEsXu-^T8R 86F{@aGir>6S c5J Tduk-2S'x2UPs8ҿڳk- Io1%+un"$8U8#üc+ ftcB<'# }K|w{c/`ǧ}mW&p23es8Agő *s=2p?`)Ls+)o1[cG0Vto774ڪ঴N!XNUc0cխtu7qtn~?|(Yb\-6Co6OE@B=% TCH)mhʡs "r,@e ofmǟ3Txy&v9)bN(#zl\v/ʲI#= mB"ǁ>''l u\BۀH1S-M#S\FvՓ6k)A1Kc8M@ht.b[X_?#?C2lij)xw{Ix:i<`0SFa<%l칓+3; ӂ/Z"ojx"Ky Kob Hz'o,@qeu]sa-Wng(:h+.g}MH{؛}wT?bqD\-cmrmn>9LGr-)J?yルlzmCE` 2wkGx{0ü1!)lbǑ_qWX~ }c/_d҇/S~!qF)]fmgY~ T힯?\տw] ;91k؟{޾)$1Y5bRs,$_g Io+K278̉d#<댕BuA6tΣo߄y)aַց WO]26X7g/5>U9%AL"#2u-"X0[Iyh?2k <خLcf7y p8wѧpXAksPTXДzՈEߦBK/ceJtϗ)e?Kn`f:MQRt:XgG'd`-tXFRRR2u|b875W&gTF3x12)x7шZS}1Z+kMsN#);qelҽм; ﴰmx ! յӆE`"1:D.MF'/$$zѧ1|="R A`'0"Xk2hFjdA&Ay"R5<joC7}{3D: Un2m7k Uͼ8GhSeܠrfD],`XSCMX 8R+Dq1]0Iw!uL%,IENDB`libwlocate-0.0git20130108/android/LocDemo/res/drawable-mdpi/0000775000175000017500000000000012073002423021067 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/res/drawable-mdpi/icon.png0000664000175000017500000000501612073002423022527 0ustar jrjrPNG  IHDR00W IDAThY[W{fwe].ׅ@%b2&!B-IJԊԔK2/ jIIʒ1%/" .˲6Kw=NO@_>p{5T|*$W4RIJrA¸NL0u@X>d`vq}a'uhɃ{H(JLE(P5g~>Sר~;c}_ЋG&Ƈx\RU) Z)[|Y fE]~A $XE, M,$YjF%@f"d\R )3 s 'E{Ab<S +9PY^gpEPQyfL {"G_cjt&uη}YkdN=SVlSXӲ Ǝ~4tb$>j4EX,4ԣZgU3l\]Ox>:V>fb⩐ɻ59 #Dh*R$> & Aϕ=Hi+v^$1$1džwGPUH&$,7~ɩ5d|OEBr!5-[tQ F׊.MaSQS݊ G쵘բc#=JC`~%mִn;`)"!1WU}ظ\Pۼf[No*_vI1k%;v쿻:;;VzG{4 =[wWqXJK@<|΃ Y']p;Dqo?Wl+ф=w۲J 8|,-U3]Эּ(#phh9\ZnE8U['O555rr.$(G:!%XFKm$H$+W```@xE;m֙@hD7\#}K\`)=o~ƐR? *KPa|ppP/<(k7pa|o#ӇyfIK܇%,fU*5:: DR Vp@/`(ndYuzg(-Hݔr&MP 󾉕MKdB SaEld,꾱yq.ꁇGD[v"$1YFx9z /xE";>lں*L!\3  =>wzԆn41r['\c2,Ar{49 ]ݸ M x4P1^l^ssO#G%=21嶂qlkHd@,$M@rLLeE-+Z]1Xݸ'H(**7?Zz2gNX,X8Z@V(Ts8+CNQ8;w\勸PVӚb震pNykIDa |89\D.i;$wm@1W5%@5?j~՞:3 'BK-7 F8c~GeoY rڀh. ɯd6?|;U"r0þЏ]v@}ߕJn05aq^G..cRQ HJ_ p#1di=9ex>_Q{1U{RVʯqy0h糥D?หۭZ*ߡgOVzjd7ލ.:S55nP'!VRcRYpb:`E\S{qnl/Wr7Nr>XQɾ~]UZ>d K&6 FAhI@7V޲~,n/Aܕ8~Xoo$Iu9/ƻ4NB/-"^@N8?uDw c>u*}9\v1(5p J$qbx8J㝌M2(4gk,\gD aZ"ĂTʅl r!DR1á[ {DUFJY@E@3)hZ*9nH$tIENDB`libwlocate-0.0git20130108/android/LocDemo/res/drawable-ldpi/0000775000175000017500000000000012073002423021066 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/res/drawable-ldpi/icon.png0000664000175000017500000000327312073002423022531 0ustar jrjrPNG  IHDR$$IDATX X[lTU]t^}0>"!壉 ?LWLĘ(Q~`降JPJ)J[iL_׾N:w*4?ɞ{Ϟs^g}sebVDQTխ-Щ5s^l9q:)RNOq>3ݘz=qU H(}^a&''fs*Y"!+*%CiBE75xTŸ5(aMӀ* |*D "SI3 'U3uz!d2#X A0i34ZVÒ[>kꟅ1e8XҦ< Ngt.kjF[w4>.շt@ 'Du$L6+&wMW@yҀLܫfrB!T8d$ۦRsOGF^5ʣbUN0hT XLkĎוgwهH zǺAWym&X?'!H  Yj(+C6;ZS0,|2kC;TUJ)~Zt$~}8 MoWǣDCFVώ'u$@Y_־/`:Yb4l*,_ u6-F_ RVUyJj% V[5OYcm{\A~ ˕!c?4,Z '*b_Edǃe~K4n|g!(mj]!4D1B$0MVJ#Ƃa=1;X6Eޯ1'rDI 2+nkj]G] [4#H G2ۇ;1{wh +%#NP@ @%ŧ'Ph=p%lU( sTa?/{)ze. ~:.h~ɋh:tA>EɼtV}uKC02 W٧R(ujŜH3>ld4vF9lq*^nGTqYo=<\ѶȂwפ 9ǏޑsPx\j,vkx /aEs+6XJO29Vo΍J5X`\ȤC6'Rʠ\x/MEsS>9z-I@/f>5B7JyP[}g&JhϿLU^S}h 96/dH:CX\FdDɤ0%*/n߀ZUDHIENDB`libwlocate-0.0git20130108/android/LocDemo/project.properties0000664000175000017500000000055012073002423021352 0ustar jrjr# This file is automatically generated by Android Tools. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # # This file must be checked in Version Control Systems. # # To customize properties used by the Ant build system use, # "ant.properties", and override values to adapt the script to your # project structure. # Project target. target=android-7 libwlocate-0.0git20130108/android/LocDemo/src/0000775000175000017500000000000012073002423016355 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/src/com/0000775000175000017500000000000012073002423017133 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/src/com/vwp/0000775000175000017500000000000012073002423017747 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/src/com/vwp/libwlocate/0000775000175000017500000000000012073002423022074 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/src/com/vwp/libwlocate/loc_info.java0000664000175000017500000000153212073002423024530 0ustar jrjrpackage com.vwp.libwlocate; import java.util.List; import android.net.wifi.ScanResult; public class loc_info { public static final int LOC_METHOD_NONE=0; public static final int LOC_METHOD_LIBWLOCATE=1; public static final int LOC_METHOD_GPS=2; /** describes based on which method the last location was perfomed with */ public int lastLocMethod=LOC_METHOD_NONE; /** request data that is used for libwlocate-based location request, its member bssids is filled with valid BSSIDs also in case of GPS location */ public wloc_req requestData; /** result of last WiFi-scan, this list is filled with valid data also in case of GPS location */ public List wifiScanResult; /** last movement speed in km per hour, if no speed could be evaluated the value is smaller than 0*/ public float lastSpeed=-1; }libwlocate-0.0git20130108/android/LocDemo/src/com/vwp/libwlocate/wloc_req.java0000664000175000017500000000064412073002423024556 0ustar jrjrpackage com.vwp.libwlocate; /** * Internal class, used for storing request data */ public class wloc_req { public static final int WLOC_MAX_NETWORKS=16; public byte version,length; public byte[][] bssids=new byte[WLOC_MAX_NETWORKS][6]; public byte[] signal=new byte[WLOC_MAX_NETWORKS]; public int cgiIP; wloc_req() { version=1; length=118; cgiIP=0; } } libwlocate-0.0git20130108/android/LocDemo/src/com/vwp/libwlocate/map/0000775000175000017500000000000012073002423022651 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/src/com/vwp/libwlocate/map/MapView.java0000664000175000017500000002736712073002423025103 0ustar jrjrpackage com.vwp.libwlocate.map; import android.content.*; import android.graphics.*; import android.view.*; public class MapView extends View implements Runnable { private static final int INVALID_POINTER_ID = -1; private int scrWidth,scrHeight,tileWidth,tileHeight; private float mLastTouchX=0.0f,mLastTouchY=0.0f,mLastTouchX2=0.0f,mLastTouchY2=0.0f,imgOffsetX=0.0f,imgOffsetY=0.0f; private Bitmap locMap=null; private Matrix matrix=new Matrix(); private Thread mapThread; private boolean mapThreadRunning,breakMapThread,allowNetAccess; private int mActivePointerId = INVALID_POINTER_ID,mActivePointerId2 = INVALID_POINTER_ID; private float mScaleFactor = 1.0f; private GeoUtils geoUtils; private MapOverlay useOverlay=new MapOverlay(); private GestureDetector gestureDetector; public MapView(Context ctx,boolean allowNetAccess,int mode) { super(ctx); Display display; this.allowNetAccess=allowNetAccess; if (mode==GeoUtils.MODE_OSM) geoUtils=new GeoUtils(GeoUtils.MODE_OSM); else geoUtils=new GeoUtils(GeoUtils.MODE_GMAP); setBackgroundColor(0xFF555570); display=((WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); scrWidth=display.getWidth(); scrHeight=display.getHeight(); setMinimumHeight(scrWidth); setMinimumWidth(scrHeight); tileWidth=(int)Math.ceil(scrWidth/256.0)+1; tileHeight=(int)Math.ceil(scrHeight/256.0)+1; gestureDetector = new GestureDetector(ctx,new GestureListener()); } private class GestureListener extends GestureDetector.SimpleOnGestureListener { public boolean onDoubleTap(MotionEvent e) { if (mapThreadRunning) return false; // no updates when download is running float w,h; mScaleFactor*=2.0; matrix.postScale(2.0f,2.0f); w=scrWidth/2.0f; h=scrHeight/2.0f; matrix.postTranslate(w,h); imgOffsetX+=w; imgOffsetY+=h; breakMapThread=true; restartMap(); return true; } } public MapView(Context ctx) throws RuntimeException { super(ctx); throw new RuntimeException("Illegal construction, use MapView(Context,boolean,int) instead!"); } public void setOverlay(MapOverlay overlay) { useOverlay=overlay; if (!mapThreadRunning) { mapThread=new Thread(this); mapThread.start(); } } public boolean onTouchEvent(MotionEvent ev) { if (mapThreadRunning) return false; // no updates when download is running if (gestureDetector.onTouchEvent(ev)) return true; final int action = ev.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { mLastTouchX=ev.getX(); mLastTouchY=ev.getY(); mActivePointerId = ev.getPointerId(0); break; } case MotionEvent.ACTION_POINTER_DOWN: { mLastTouchX2=ev.getX(); mLastTouchY2=ev.getY(); if (ev.getPointerCount()>1) mActivePointerId2 = ev.getPointerId(1); break; } case MotionEvent.ACTION_MOVE: { int pointerIndex; float x=0.0f,y=0.0f; try { if ((mActivePointerId!=INVALID_POINTER_ID) || (mActivePointerId2!=INVALID_POINTER_ID)) { pointerIndex= ev.findPointerIndex(mActivePointerId); x= ev.getX(pointerIndex); y= ev.getY(pointerIndex); } if ((mActivePointerId!=INVALID_POINTER_ID) && (mActivePointerId2!=INVALID_POINTER_ID)) { float d1,d2; pointerIndex = ev.findPointerIndex(mActivePointerId2); if (pointerIndex<0) return false; float x2 = ev.getX(pointerIndex); float y2 = ev.getY(pointerIndex); d1=android.util.FloatMath.sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2)); d2=android.util.FloatMath.sqrt((mLastTouchX-mLastTouchX2)*(mLastTouchX-mLastTouchX2)+ (mLastTouchY-mLastTouchY2)*(mLastTouchY-mLastTouchY2)); /* if ((Math.abs(d1)>300) || (Math.abs(d2)>300)) { int i=0; i=i; }*/ if ((d1>0) && (d2>0)) { float w,h,s; s=d1/d2; mScaleFactor*=s; matrix.postScale(s,s); w=scrWidth/2.0f; h=scrHeight/2.0f; matrix.postTranslate(w,h); imgOffsetX+=w; imgOffsetY+=h; } mLastTouchX2 = x2; mLastTouchY2 = y2; } else if (mScaleFactor==1.0) { if ((Math.abs(x-mLastTouchX)>100) || (Math.abs(y-mLastTouchY)>100)) { int i=0; i=i; } mScaleFactor=1.0f; imgOffsetX+=(x-mLastTouchX); imgOffsetY+=(y-mLastTouchY); matrix.setTranslate(imgOffsetX,imgOffsetY); } if ((mActivePointerId!=INVALID_POINTER_ID) || (mActivePointerId2!=INVALID_POINTER_ID)) { mLastTouchX = x; mLastTouchY = y; } } catch (ArrayIndexOutOfBoundsException aioobe) { // can be caused by // pointerIndex= ev.findPointerIndex(mActivePointerId); // x= ev.getX(pointerIndex); // above which seems to be a Android bug } invalidate(); break; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: { breakMapThread=true; mActivePointerId = INVALID_POINTER_ID; mActivePointerId2 = INVALID_POINTER_ID; restartMap(); break; } } return true; } private void restartMap() { breakMapThread=true; postInvalidate(); if (mapThread!=null) try { mapThread.join(1500); } catch (InterruptedException ie) { } mapThread=new Thread(this); mapThread.start(); } public void setCenterLocation(double lat,double lon) { breakMapThread=true; useOverlay.tileX=GeoUtils.long2tilex(lon,useOverlay.m_zoom); useOverlay.tileY=GeoUtils.lat2tiley(lat,useOverlay.m_zoom); imgOffsetX+=scrWidth/2.0f; imgOffsetY+=scrHeight/2.0f; restartMap(); } public void run() { int x,y; Bitmap locTile; Canvas canvas; float useLon,useLat,useLonMax,useLatMax; System.gc(); if ((useOverlay.tileX==0) && (useOverlay.tileY==0)) return; mapThreadRunning=true; try { if (locMap==null) locMap=Bitmap.createBitmap(tileWidth*256,tileHeight*256,Bitmap.Config.ARGB_8888); } catch (OutOfMemoryError oome) { return; } locMap.eraseColor(Color.BLACK); canvas=new Canvas(locMap); useLon=(GeoUtils.tilex2long(useOverlay.tileX,useOverlay.m_zoom)+GeoUtils.tilex2long(useOverlay.tileX+1,useOverlay.m_zoom))/2.0f; useLat=(GeoUtils.tiley2lat(useOverlay.tileY,useOverlay.m_zoom)+GeoUtils.tiley2lat(useOverlay.tileY+1,useOverlay.m_zoom))/2.0f; while (mScaleFactor>=2.0) { mScaleFactor/=2.0f; useOverlay.m_zoom++; if (useOverlay.m_zoom>17) { useOverlay.m_zoom=17; imgOffsetX-=(scrWidth-(scrWidth*2.0))/2.0; imgOffsetY-=(scrHeight-(scrHeight*2.0))/2.0; } } while (mScaleFactor<=0.5) { mScaleFactor*=2.0f; useOverlay.m_zoom--; if (useOverlay.m_zoom<4) { useOverlay.m_zoom=4; imgOffsetX-=(scrWidth-(scrWidth*2.0))/2.0; imgOffsetY-=(scrHeight-(scrHeight*2.0))/2.0; } } mScaleFactor=1.0f; /* if ((wasScaleOp) && (lonCenter!=0.0f) && (latCenter!=0.0f)) { tileX=GeoUtils.long2tilex(lonCenter,m_zoom); tileY=GeoUtils.lat2tiley(latCenter,m_zoom); tileX-=(scrWidth / 256); tileY-=(scrWidth / 256); } else*/ { useOverlay.tileX=GeoUtils.long2tilex(useLon,useOverlay.m_zoom); useOverlay.tileY=GeoUtils.lat2tiley(useLat,useOverlay.m_zoom); } useLon=GeoUtils.tilex2long(useOverlay.tileX-1,useOverlay.m_zoom); useLat=GeoUtils.tiley2lat(useOverlay.tileY-1,useOverlay.m_zoom); useLonMax=GeoUtils.tilex2long(useOverlay.tileX+tileWidth+1,useOverlay.m_zoom); useLatMax=GeoUtils.tiley2lat(useOverlay.tileY+tileHeight+1,useOverlay.m_zoom); /* if (imgOffsetX>scrWidth) { imgOffsetX=scrWidth/2; } if (imgOffsetX<=-scrWidth) { imgOffsetX=-scrWidth/2; } if (imgOffsetY>scrHeight) { imgOffsetY=scrHeight/2; } if (imgOffsetY<=-scrHeight) { imgOffsetY=-scrHeight/2; }*/ while (imgOffsetX>0) { imgOffsetX-=256.0f; useOverlay.tileX--; } while (imgOffsetX<=-256.0) { imgOffsetX+=256.0f; useOverlay.tileX++; } while (imgOffsetY>0) { imgOffsetY-=256.0f; useOverlay.tileY--; } while (imgOffsetY<=-256.0) { imgOffsetY+=256.0f; useOverlay.tileY++; } // calculate lat/lon of screen center point /* { int useTileX=tileX,useTileY=tileY; x=(int)((scrWidth/2.0f)+imgOffsetX); y=(int)((scrHeight/2.0f)+imgOffsetY); useTileX+=(x / 256); x=x % 256; useTileY+=(y / 256); y=y % 256; float tileLon1=GeoUtils.tilex2long(useTileX,m_zoom); float tileLat1=GeoUtils.tiley2lat(useTileY,m_zoom); float tileLon2=GeoUtils.tilex2long(useTileX+1,m_zoom); float tileLat2=GeoUtils.tiley2lat(useTileY+1,m_zoom); lonCenter=(((tileLon2-tileLon1)/256.0f)*x)+tileLon1; latCenter=(((tileLat2-tileLat1)/256.0f)*y)+tileLat1; }*/ matrix.setTranslate(imgOffsetX,imgOffsetY); breakMapThread=false; mapThreadRunning=false; for (x=0; x
* * The usage is quite simple: create an own class that inherits from WLocate and overwrite method * wloc_return_position(). Call wloc_request_position() to start position evaluation. The resulting is returned via * overwritten method wloc_return_position() asynchronously.

* * Beside of that it is recommended to call the doPause() and doResume() methods whenever an onPause() and onResume() * event occurs in main Activity to avoid Exceptions caused by the WiFi-receiver. */ public class WLocate implements Runnable { public static final int FLAG_NO_NET_ACCESS =0x0001; /** Don't perform any network accesses to evaluate the position data, this option disables the WLAN_based position retrieval */ public static final int FLAG_NO_GPS_ACCESS =0x0002; /** Don't use a GPS device to evaluate the position data, this option disables the WLAN_based position retrieval */ public static final int FLAG_NO_IP_LOCATION=0x0004; /** Don't send a request to the server for IP-based location in case no WLANs are available */ public static final int WLOC_OK=0; /** Result code for position request, given position information are OK */ public static final int WLOC_CONNECTION_ERROR=1; /** Result code for position request, a connection error occured, no position information are available */ public static final int WLOC_SERVER_ERROR=2; public static final int WLOC_LOCATION_ERROR=3; /** Result code for position request, the position could not be evaluated, no position information are available */ public static final int WLOC_ERROR=100; /** Result code for position request, an unknown error occured, no position information are available */ private static final int WLOC_RESULT_OK=1; // private static final int WLOC_RESULT_ERROR=2; // private static final int WLOC_RESULT_IERROR=3; private Location lastLocation=null; private LocationManager location; private GPSLocationListener locationListener; private GPSStatusListener statusListener; private WifiManager wifi; private WifiReceiver receiverWifi = new WifiReceiver(); private boolean GPSAvailable=false,scanStarted=false; private double m_lat,m_lon; private float m_radius=1.0f,m_speed=-1.0f; private int scanFlags; private long lastLocationMillis=0; private Context ctx; private loc_info locationInfo=new loc_info(); private Thread netThread=null; private WLocate me; /** * Constructor for WLocate class, this constructor has to be overwritten by inheriting class * @param ctx current context, hand over Activity object here */ public WLocate(Context ctx) { wifi = (WifiManager) ctx.getSystemService(Context.WIFI_SERVICE); this.ctx=ctx; startGPSLocation(); me=this; doResume(); } private void startGPSLocation() { location= (LocationManager)ctx.getSystemService(Context.LOCATION_SERVICE); locationListener = new GPSLocationListener(); location.requestLocationUpdates(LocationManager.GPS_PROVIDER,350,0,(LocationListener)locationListener); statusListener=new GPSStatusListener(); location.addGpsStatusListener(statusListener); } /** * Send pause-information to active WLocate object. This method should be called out of the main Activity * whenever an onPause() event occurs to avoid leakted IntentReceiver exceptions caused by the receiver * when it is still registered after application switched over to pause state */ public void doPause() { ctx.registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); } /** * Send resume-information to active WLocate object. This method has to be called out of the main Activity * whenever an onResume() event occurs and in case the doPause() method is used to reactivate the WiFi * receiver */ public void doResume() { ctx.registerReceiver(receiverWifi, new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)); } /** * Start position evaluation process, the result is returned via method wloc_return_position() * that may be called asynchronously * @param flags specifies how the position has to be evaluated using the FLAG_NO_xxx_ACCESS-values */ public void wloc_request_position(int flags) { scanFlags=flags; scanStarted=true; wifi.startScan(); } public loc_info last_location_info() { return locationInfo; } private int get_position(wloc_req request,wloc_position position) { Socket wlocSocket; DataInputStream din; DataOutputStream dout; int i; wloc_res result=new wloc_res(); try { wlocSocket=new Socket("api.openwlanmap.org",10443); dout=new DataOutputStream(wlocSocket.getOutputStream()); dout.write(locationInfo.requestData.version); dout.write(locationInfo.requestData.length); for (i=0; i100) result.quality=100; result.cres6=din.readByte(); result.cres7=din.readByte(); result.cres7=din.readByte(); result.lat=din.readInt(); result.lon=din.readInt(); result.ccode=din.readShort(); result.wres34=din.readShort(); result.wres56=din.readShort(); result.wres78=din.readShort(); if (result.result!=WLOC_RESULT_OK) { wlocSocket.close(); return WLOC_LOCATION_ERROR; } position.lat=result.lat/10000000.0; position.lon=result.lon/10000000.0; position.quality=result.quality; } catch (Exception e) { e.printStackTrace(); return WLOC_CONNECTION_ERROR; } return WLOC_OK; } class WifiReceiver extends BroadcastReceiver { public void onReceive(Context c, Intent intent) { int netCnt=0,ret=WLOC_LOCATION_ERROR; wloc_position pos=null; if (!scanStarted) return; scanStarted=false; List configs=wifi.getScanResults(); if (configs==null) return; locationInfo.wifiScanResult=configs; locationInfo.requestData=new wloc_req(); if (configs.size()>0) for (ScanResult config : configs) { String bssidStr[]; config.BSSID=config.BSSID.toUpperCase().replace(".",":"); // some strange devices use a dot instead of : bssidStr=config.BSSID.split(":"); locationInfo.requestData.bssids[netCnt][0]=(byte)Integer.parseInt(bssidStr[0],16); locationInfo.requestData.bssids[netCnt][1]=(byte)Integer.parseInt(bssidStr[1],16); locationInfo.requestData.bssids[netCnt][2]=(byte)Integer.parseInt(bssidStr[2],16); locationInfo.requestData.bssids[netCnt][3]=(byte)Integer.parseInt(bssidStr[3],16); locationInfo.requestData.bssids[netCnt][4]=(byte)Integer.parseInt(bssidStr[4],16); locationInfo.requestData.bssids[netCnt][5]=(byte)Integer.parseInt(bssidStr[5],16); locationInfo.requestData.signal[netCnt]=(byte)Math.abs(config.level); netCnt++; if (netCnt>=wloc_req.WLOC_MAX_NETWORKS) break; } locationInfo.lastLocMethod=loc_info.LOC_METHOD_NONE; locationInfo.lastSpeed=-1.0f; if (GPSAvailable) GPSAvailable=(SystemClock.elapsedRealtime()-lastLocationMillis) < 7500; if (!GPSAvailable) { if ((scanFlags & FLAG_NO_NET_ACCESS)!=0) wloc_return_position(WLOC_LOCATION_ERROR,0.0,0.0,(float)0.0,(short)0); else if ((configs.size()>0) || ((scanFlags & FLAG_NO_IP_LOCATION)==0)) { if ((netThread!=null) && (netThread.isAlive())) return; netThread=new Thread(me); netThread.start(); } else { wloc_return_position(WLOC_LOCATION_ERROR,0.0,0.0,(float)0.0,(short)0); } } else { // TODO: disable GPS in case NO_GPS_FLAG is set and re-enable it on next call without this option if ((scanFlags & FLAG_NO_GPS_ACCESS)!=0) wloc_return_position(WLOC_LOCATION_ERROR,0.0,0.0,(float)0.0,(short)0); else { locationInfo.lastSpeed=m_speed; locationInfo.lastLocMethod=loc_info.LOC_METHOD_GPS; wloc_return_position(WLOC_OK,m_lat,m_lon,m_radius,(short)0); } } } } public void run() { int ret=WLOC_LOCATION_ERROR; wloc_position pos=null; pos=new wloc_position(); ret=get_position(locationInfo.requestData,pos); locationInfo.lastLocMethod=loc_info.LOC_METHOD_LIBWLOCATE; if (pos.quality<=0) wloc_return_position(ret,pos.lat,pos.lon,10000.0f,pos.ccode); else wloc_return_position(ret,pos.lat,pos.lon,120-pos.quality,pos.ccode); } /** * This method is called as soon as a result of a position evaluation request is available. * Thus this method should be overwritten by the inheriting class to receive the results there. * @param ret the return code that informs if the location evaluation request could be fulfilled * successfully or not. Only in case this parameter is equal to WLOC_OK all the other * ones can be used, elsewhere no position information could be retrieved. * @param lat the latitude of the current position * @param lon the latitude of the current position * @param radius the accuracy of the position information, this radius specifies the range around * the given latitude and longitude information of the real position. The smaller this value * is the more accurate the given position information is. * @param ccode code of the country where the current position is located within, in case the * country is not known, 0 is returned. The country code can be converted to a text that * specifies the country by calling wloc_get_country_from_code() */ protected void wloc_return_position(int ret,double lat,double lon,float radius,short ccode) { } /** * Convert a country code to a more easy to read short text that specifies a country. * @param ccode the country code to be converted * @return the short text that names the country or an empty string an unknown country * specifier was given or the country code was 0 */ public String wloc_get_country_from_code(short ccode) { switch (ccode) { case 1: return "DE"; case 2: return "AT"; case 3: return "CH"; case 4: return "NL"; case 5: return "BE"; case 6: return "LU"; case 7: return "NO"; case 8: return "SE"; case 9: return "DK"; case 10: return "AF"; case 12: return "AL"; case 13: return "DZ"; case 17: return "AN"; case 18: return "AG"; case 19: return "AR"; case 20: return "AM"; case 21: return "AU"; case 23: return "BS"; case 24: return "BH"; case 25: return "BD"; case 26: return "BB"; case 27: return "BY"; case 28: return "BZ"; case 29: return "BJ"; case 30: return "BM"; case 32: return "BO"; case 33: return "BA"; case 36: return "BR"; case 37: return "BN"; case 38: return "BG"; case 43: return "CA"; case 44: return "CV"; case 47: return "CL"; case 48: return "CN"; case 49: return "CO"; case 52: return "CR"; case 53: return "HR"; case 55: return "CY"; case 56: return "CZ"; case 59: return "DO"; case 60: return "EC"; case 61: return "EG"; case 66: return "ET"; case 68: return "FI"; case 69: return "FR"; case 73: return "GH"; case 75: return "GR"; case 76: return "GL"; case 77: return "GD"; case 78: return "GU"; case 79: return "GT"; case 82: return "HT"; case 83: return "HN"; case 84: return "HK"; case 85: return "HU"; case 86: return "IS"; case 87: return "IN"; case 88: return "ID"; case 89: return "IR"; case 90: return "IQ"; case 91: return "IE"; case 93: return "IT"; case 94: return "JM"; case 95: return "JP"; case 97: return "JO"; case 98: return "KZ"; case 99: return "KE"; case 102: return "KR"; case 103: return "KW"; case 104: return "KG"; case 105: return "LA"; case 106: return "LV"; case 107: return "LB"; case 108: return "LS"; case 111: return "LT"; case 115: return "MY"; case 116: return "MV"; case 118: return "MT"; case 119: return "MQ"; case 121: return "MU"; case 123: return "MX"; case 124: return "MC"; case 125: return "MN"; case 126: return "MA"; case 127: return "MZ"; case 131: return "NZ"; case 133: return "NI"; case 135: return "NG"; case 137: return "OM"; case 138: return "PK"; case 141: return "PA"; case 142: return "PY"; case 144: return "PE"; case 145: return "PH"; case 147: return "PL"; case 148: return "PT"; case 149: return "PR"; case 150: return "QA"; case 151: return "RO"; case 152: return "RU"; case 155: return "SM"; case 157: return "SA"; case 158: return "SN"; case 161: return "SG"; case 162: return "SK"; case 163: return "SI"; case 166: return "ZA"; case 167: return "ES"; case 168: return "LK"; case 169: return "SD"; case 170: return "SR"; case 172: return "SY"; case 173: return "TW"; case 174: return "TJ"; case 175: return "TZ"; case 176: return "TH"; case 179: return "TT"; case 180: return "TN"; case 181: return "TR"; case 182: return "TM"; case 185: return "UA"; case 186: return "AE"; case 187: return "UK"; case 188: return "US"; case 189: return "UY"; case 191: return "VE"; case 192: return "VN"; case 195: return "ZM"; case 196: return "ZW"; default: return ""; } } private class GPSStatusListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (lastLocation != null) { GPSAvailable=(SystemClock.elapsedRealtime()-lastLocationMillis) < 3500; } break; case GpsStatus.GPS_EVENT_FIRST_FIX: // Do something. GPSAvailable=true; break; case GpsStatus.GPS_EVENT_STOPPED: GPSAvailable=false; break; } } } private class GPSLocationListener implements LocationListener { public void onLocationChanged(Location gLocation) { if (location == null) return; lastLocationMillis = SystemClock.elapsedRealtime(); lastLocation =new Location(gLocation); // GPSAvailable=true; m_lat=gLocation.getLatitude(); m_lon=gLocation.getLongitude(); if (gLocation.hasSpeed()) m_speed=gLocation.getSpeed(); //m/sec else m_speed=-1; if (gLocation.hasAccuracy()) m_radius=gLocation.getAccuracy(); else m_radius=-1; } public void onStatusChanged(String provider, int status, Bundle extras) { if ((provider!=null) && (provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER))) { if (status!=LocationProvider.AVAILABLE) GPSAvailable=false; } } public void onProviderEnabled(String provider) { } public void onProviderDisabled(String provider) { GPSAvailable=false; } }; } libwlocate-0.0git20130108/android/LocDemo/src/com/vwp/locdemo/0000775000175000017500000000000012073002423021371 5ustar jrjrlibwlocate-0.0git20130108/android/LocDemo/src/com/vwp/locdemo/LocDemo.java0000664000175000017500000003322012073002423023556 0ustar jrjrpackage com.vwp.locdemo; import android.app.*; import android.hardware.*; import android.os.*; import android.view.*; import android.view.View.*; import android.widget.*; import android.content.*; import android.content.res.*; import android.graphics.*; import java.net.*; import java.io.*; import java.util.concurrent.locks.*; import org.apache.http.*; import org.apache.http.client.*; import org.apache.http.client.methods.*; import org.apache.http.impl.client.*; import com.vwp.libwlocate.*; import com.vwp.libwlocate.map.*; /*class MainCanvas extends View { private Bitmap locTile[][]; private int m_tileX,m_tileY; public int xOffs,yOffs,lastWidth=0,lastHeight=0; private float m_radius; private double m_lat,m_lon; private Paint circleColour,fillColour; private Lock lock=new ReentrantLock(); public int m_zoom=17; private LocDemo locDemo; public MainCanvas(LocDemo locDemo) { super(locDemo); this.locDemo=locDemo; circleColour=new Paint(); circleColour.setARGB(255,255,0,0); circleColour.setStyle(Paint.Style.STROKE); circleColour.setStrokeWidth(2); fillColour=new Paint(); fillColour.setARGB(75,255,0,0); fillColour.setStyle(Paint.Style.FILL); updateScreenOrientation(); } private void updateScreenOrientation() { Display display; display=((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); if ((lastWidth==display.getWidth()) && (lastHeight==display.getHeight())) return; lastWidth=display.getWidth(); lastHeight=display.getHeight(); setMinimumWidth(lastWidth); setMinimumHeight(lastHeight); lock.lock(); xOffs=lastWidth/256; xOffs=(int)Math.ceil(xOffs/3.0); if (xOffs<1) xOffs=1; yOffs=lastHeight/256; yOffs=(int)Math.ceil(yOffs/3.0); if (yOffs<1) yOffs=1; locTile=new Bitmap[xOffs*3][yOffs*3]; lock.unlock(); } private int long2tilex(double lon, int z) { return (int)(Math.floor((lon + 180.0) / 360.0 * Math.pow(2.0, z))); } private int lat2tiley(double lat, int z) { return (int)(Math.floor((1.0 - Math.log( Math.tan(lat * Math.PI/180.0) + 1.0 / Math.cos(lat * Math.PI/180.0)) / Math.PI) / 2.0 * Math.pow(2.0, z))); } static double tilex2long(int x, int z) { return x / Math.pow(2.0, z) * 360.0 - 180; } static double tiley2lat(int y, int z) { double n = Math.PI - 2.0 * Math.PI * y / Math.pow(2.0, z); return 180.0 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); } private boolean loadTile(String url,int x,int y) { InputStream in; FileOutputStream out; byte data[]; int len,rLen=0; try { HttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(); request.setURI(new URI(url)); request.setHeader("User-Agent","LocDemo WLocate demo application"); HttpResponse response = client.execute(request); in=response.getEntity().getContent(); len=(int)response.getEntity().getContentLength(); if (len<=0) return false; data=new byte[len]; while (rLen; } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } libwlocate-0.0git20130108/android/LocDemo/AndroidManifest.xml0000664000175000017500000000176612073002423021371 0ustar jrjr libwlocate-0.0git20130108/android/LocDemo/lint.xml0000664000175000017500000000006512073002423017257 0ustar jrjr libwlocate-0.0git20130108/COPYING0000775000175000017500000007733212073002423013676 0ustar jrjr GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS libwlocate-0.0git20130108/.git/0000775000175000017500000000000012073002423013465 5ustar jrjrlibwlocate-0.0git20130108/.git/hooks/0000775000175000017500000000000012073002413014607 5ustar jrjrlibwlocate-0.0git20130108/.git/hooks/update.sample0000775000175000017500000000703312073002413017302 0ustar jrjr#!/bin/sh # # An example hook script to blocks unannotated tags from entering. # Called by "git receive-pack" with arguments: refname sha1-old sha1-new # # To enable this hook, rename this file to "update". # # Config # ------ # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # hooks.allowdeletetag # This boolean sets whether deleting tags will be allowed in the # repository. By default they won't be. # hooks.allowmodifytag # This boolean sets whether a tag may be modified after creation. By default # it won't be. # hooks.allowdeletebranch # This boolean sets whether deleting branches will be allowed in the # repository. By default they won't be. # hooks.denycreatebranch # This boolean sets whether remotely creating branches will be denied # in the repository. By default this is allowed. # # --- Command line refname="$1" oldrev="$2" newrev="$3" # --- Safety check if [ -z "$GIT_DIR" ]; then echo "Don't run this script from the command line." >&2 echo " (if you want, you could supply GIT_DIR then run" >&2 echo " $0 )" >&2 exit 1 fi if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then echo "Usage: $0 " >&2 exit 1 fi # --- Config allowunannotated=$(git config --bool hooks.allowunannotated) allowdeletebranch=$(git config --bool hooks.allowdeletebranch) denycreatebranch=$(git config --bool hooks.denycreatebranch) allowdeletetag=$(git config --bool hooks.allowdeletetag) allowmodifytag=$(git config --bool hooks.allowmodifytag) # check for no description projectdesc=$(sed -e '1q' "$GIT_DIR/description") case "$projectdesc" in "Unnamed repository"* | "") echo "*** Project description file hasn't been set" >&2 exit 1 ;; esac # --- Check types # if $newrev is 0000...0000, it's a commit to delete a ref. zero="0000000000000000000000000000000000000000" if [ "$newrev" = "$zero" ]; then newrev_type=delete else newrev_type=$(git cat-file -t $newrev) fi case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,delete) # delete tag if [ "$allowdeletetag" != "true" ]; then echo "*** Deleting a tag is not allowed in this repository" >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1 then echo "*** Tag '$refname' already exists." >&2 echo "*** Modifying a tag is not allowed in this repository." >&2 exit 1 fi ;; refs/heads/*,commit) # branch if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then echo "*** Creating a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/heads/*,delete) # delete branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a branch is not allowed in this repository" >&2 exit 1 fi ;; refs/remotes/*,commit) # tracking branch ;; refs/remotes/*,delete) # delete tracking branch if [ "$allowdeletebranch" != "true" ]; then echo "*** Deleting a tracking branch is not allowed in this repository" >&2 exit 1 fi ;; *) # Anything else (is there anything else?) echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac # --- Finished exit 0 libwlocate-0.0git20130108/.git/hooks/post-update.sample0000775000175000017500000000027512073002413020266 0ustar jrjr#!/bin/sh # # An example hook script to prepare a packed repository for use over # dumb transports. # # To enable this hook, rename this file to "post-update". exec git update-server-info libwlocate-0.0git20130108/.git/hooks/applypatch-msg.sample0000775000175000017500000000070412073002413020747 0ustar jrjr#!/bin/sh # # An example hook script to check the commit log message taken by # applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. The hook is # allowed to edit the commit message file. # # To enable this hook, rename this file to "applypatch-msg". . git-sh-setup test -x "$GIT_DIR/hooks/commit-msg" && exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"} : libwlocate-0.0git20130108/.git/hooks/commit-msg.sample0000775000175000017500000000160012073002413020066 0ustar jrjr#!/bin/sh # # An example hook script to check the commit log message. # Called by "git commit" with one argument, the name of the file # that has the commit message. The hook should exit with non-zero # status after issuing an appropriate message if it wants to stop the # commit. The hook is allowed to edit the commit message file. # # To enable this hook, rename this file to "commit-msg". # Uncomment the below to add a Signed-off-by line to the message. # Doing this in a hook is a bad idea in general, but the prepare-commit-msg # hook is more suited to it. # # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" # This example catches duplicate Signed-off-by lines. test "" = "$(grep '^Signed-off-by: ' "$1" | sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || { echo >&2 Duplicate Signed-off-by lines. exit 1 } libwlocate-0.0git20130108/.git/hooks/prepare-commit-msg.sample0000775000175000017500000000232712073002413021531 0ustar jrjr#!/bin/sh # # An example hook script to prepare the commit log message. # Called by "git commit" with the name of the file that has the # commit message, followed by the description of the commit # message's source. The hook's purpose is to edit the commit # message file. If the hook fails with a non-zero status, # the commit is aborted. # # To enable this hook, rename this file to "prepare-commit-msg". # This hook includes three examples. The first comments out the # "Conflicts:" part of a merge commit. # # The second includes the output of "git diff --name-status -r" # into the message, just before the "git status" output. It is # commented because it doesn't cope with --amend or with squashed # commits. # # The third example adds a Signed-off-by line to the message, that can # still be edited. This is rarely a good idea. case "$2,$3" in merge,) /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;; # ,|template,) # /usr/bin/perl -i.bak -pe ' # print "\n" . `git diff --cached --name-status -r` # if /^#/ && $first++ == 0' "$1" ;; *) ;; esac # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p') # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1" libwlocate-0.0git20130108/.git/hooks/pre-applypatch.sample0000775000175000017500000000061612073002413020751 0ustar jrjr#!/bin/sh # # An example hook script to verify what is about to be committed # by applypatch from an e-mail message. # # The hook should exit with non-zero status after issuing an # appropriate message if it wants to stop the commit. # # To enable this hook, rename this file to "pre-applypatch". . git-sh-setup test -x "$GIT_DIR/hooks/pre-commit" && exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"} : libwlocate-0.0git20130108/.git/hooks/pre-rebase.sample0000775000175000017500000001144212073002413020044 0ustar jrjr#!/bin/sh # # Copyright (c) 2006, 2008 Junio C Hamano # # The "pre-rebase" hook is run just before "git rebase" starts doing # its job, and can prevent the command from running by exiting with # non-zero status. # # The hook is called with the following parameters: # # $1 -- the upstream the series was forked from. # $2 -- the branch being rebased (or empty when rebasing the current branch). # # This sample shows how to prevent topic branches that are already # merged to 'next' branch from getting rebased, because allowing it # would result in rebasing already published history. publish=next basebranch="$1" if test "$#" = 2 then topic="refs/heads/$2" else topic=`git symbolic-ref HEAD` || exit 0 ;# we do not interrupt rebasing detached HEAD fi case "$topic" in refs/heads/??/*) ;; *) exit 0 ;# we do not interrupt others. ;; esac # Now we are dealing with a topic branch being rebased # on top of master. Is it OK to rebase it? # Does the topic really exist? git show-ref -q "$topic" || { echo >&2 "No such branch $topic" exit 1 } # Is topic fully merged to master? not_in_master=`git rev-list --pretty=oneline ^master "$topic"` if test -z "$not_in_master" then echo >&2 "$topic is fully merged to master; better remove it." exit 1 ;# we could allow it, but there is no point. fi # Is topic ever merged to next? If so you should not be rebasing it. only_next_1=`git rev-list ^master "^$topic" ${publish} | sort` only_next_2=`git rev-list ^master ${publish} | sort` if test "$only_next_1" = "$only_next_2" then not_in_topic=`git rev-list "^$topic" master` if test -z "$not_in_topic" then echo >&2 "$topic is already up-to-date with master" exit 1 ;# we could allow it, but there is no point. else exit 0 fi else not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"` /usr/bin/perl -e ' my $topic = $ARGV[0]; my $msg = "* $topic has commits already merged to public branch:\n"; my (%not_in_next) = map { /^([0-9a-f]+) /; ($1 => 1); } split(/\n/, $ARGV[1]); for my $elem (map { /^([0-9a-f]+) (.*)$/; [$1 => $2]; } split(/\n/, $ARGV[2])) { if (!exists $not_in_next{$elem->[0]}) { if ($msg) { print STDERR $msg; undef $msg; } print STDERR " $elem->[1]\n"; } } ' "$topic" "$not_in_next" "$not_in_master" exit 1 fi <<\DOC_END This sample hook safeguards topic branches that have been published from being rewound. The workflow assumed here is: * Once a topic branch forks from "master", "master" is never merged into it again (either directly or indirectly). * Once a topic branch is fully cooked and merged into "master", it is deleted. If you need to build on top of it to correct earlier mistakes, a new topic branch is created by forking at the tip of the "master". This is not strictly necessary, but it makes it easier to keep your history simple. * Whenever you need to test or publish your changes to topic branches, merge them into "next" branch. The script, being an example, hardcodes the publish branch name to be "next", but it is trivial to make it configurable via $GIT_DIR/config mechanism. With this workflow, you would want to know: (1) ... if a topic branch has ever been merged to "next". Young topic branches can have stupid mistakes you would rather clean up before publishing, and things that have not been merged into other branches can be easily rebased without affecting other people. But once it is published, you would not want to rewind it. (2) ... if a topic branch has been fully merged to "master". Then you can delete it. More importantly, you should not build on top of it -- other people may already want to change things related to the topic as patches against your "master", so if you need further changes, it is better to fork the topic (perhaps with the same name) afresh from the tip of "master". Let's look at this example: o---o---o---o---o---o---o---o---o---o "next" / / / / / a---a---b A / / / / / / / / c---c---c---c B / / / / \ / / / / b---b C \ / / / / / \ / ---o---o---o---o---o---o---o---o---o---o---o "master" A, B and C are topic branches. * A has one fix since it was merged up to "next". * B has finished. It has been fully merged up to "master" and "next", and is ready to be deleted. * C has not merged to "next" at all. We would want to allow C to be rebased, refuse A, and encourage B to be deleted. To compute (1): git rev-list ^master ^topic next git rev-list ^master next if these match, topic has not merged in next at all. To compute (2): git rev-list master..topic if this is empty, it is fully merged to "master". DOC_END libwlocate-0.0git20130108/.git/hooks/pre-commit.sample0000775000175000017500000000325012073002413020071 0ustar jrjr#!/bin/sh # # An example hook script to verify what is about to be committed. # Called by "git commit" with no arguments. The hook should # exit with non-zero status after issuing an appropriate message if # it wants to stop the commit. # # To enable this hook, rename this file to "pre-commit". if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # If you want to allow non-ascii filenames set this variable to true. allownonascii=$(git config hooks.allownonascii) # Redirect output to stderr. exec 1>&2 # Cross platform projects tend to avoid non-ascii filenames; prevent # them from being added to the repository. We exploit the fact that the # printable range starts at the space character and ends with tilde. if [ "$allownonascii" != "true" ] && # Note that the use of brackets around a tr range is ok here, (it's # even required, for portability to Solaris 10's /usr/bin/tr), since # the square bracket bytes happen to fall in the designated range. test $(git diff --cached --name-only --diff-filter=A -z $against | LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 then echo "Error: Attempt to add a non-ascii file name." echo echo "This can cause problems if you want to work" echo "with people on other platforms." echo echo "To be portable it is advisable to rename the file ..." echo echo "If you know what you are doing you can disable this" echo "check using:" echo echo " git config hooks.allownonascii true" echo exit 1 fi # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against -- libwlocate-0.0git20130108/.git/refs/0000775000175000017500000000000012073002423014424 5ustar jrjrlibwlocate-0.0git20130108/.git/refs/heads/0000775000175000017500000000000012073002423015510 5ustar jrjrlibwlocate-0.0git20130108/.git/refs/heads/master0000664000175000017500000000005112073002423016722 0ustar jrjr641b5fa038398364c7fe3fc996744ae094f0cc49 libwlocate-0.0git20130108/.git/refs/remotes/0000775000175000017500000000000012073002423016102 5ustar jrjrlibwlocate-0.0git20130108/.git/refs/remotes/origin/0000775000175000017500000000000012073002423017371 5ustar jrjrlibwlocate-0.0git20130108/.git/refs/remotes/origin/HEAD0000664000175000017500000000004012073002423020007 0ustar jrjrref: refs/remotes/origin/master libwlocate-0.0git20130108/.git/refs/tags/0000775000175000017500000000000012073002413015361 5ustar jrjrlibwlocate-0.0git20130108/.git/HEAD0000664000175000017500000000002712073002423014110 0ustar jrjrref: refs/heads/master libwlocate-0.0git20130108/.git/objects/0000775000175000017500000000000012073002413015115 5ustar jrjrlibwlocate-0.0git20130108/.git/objects/info/0000775000175000017500000000000012073002413016050 5ustar jrjrlibwlocate-0.0git20130108/.git/objects/pack/0000775000175000017500000000000012073002423016034 5ustar jrjrlibwlocate-0.0git20130108/.git/objects/pack/pack-4eee77b3b34dc60fd348739ad812044055440b8c.idx0000444000175000017500000007477412073002423024773 0ustar jrjrtOc"$*-04;@CFLR\_cfgjlswz| (*/577<AEILOSUW\`fkpvw{  )1248;?CEHKOU\`ilqux   !#$+/37=@AFLOPV]cekpv{ $/5j,KMuu$uKv-## &Lz m FN&(,bC%/,;+ĢԾC}Ka7*c69eiZ[2:E@xJ ? y !Y*K&{Hcbcha|;|@ˎ1#,AG3ײBZAz [-ئ^Ą1/v'Z {c =W҉ԕz#Y`CdV +j' cKyB{ Uo״^x+49D˅h~2r{XgJazĄ쒅,-Y\rxt}UYL.Yev*a&Ƅ4WK;U0 ^W[v~S"4e%m\elpN\ks\g 3 *T6 Ъc*J#Rר@Lp{nِ5KoFjbatQl wC(`SPif,Ij0=Wt yWyQ-Z;1p%J6(_r)˶aM gwϙ z8Fj{"Ԧ&@# 3*D܆ %#VІZy.Z@&_ wnrH6=*](k=vɱy G/$J-%_ N APL-? #MH mtd@ҋUj y}chg-9 Щ|#U&"0 w :jciQ݋@.%E;& KLB8Ж-u5 xLn1h| οYd(H)6ض4&aaE!3u*Ov%kWTF-TdR]vYUB-*y <ػa M̤EԧC1 %GB8 Ix4JZl82dPtCjv.L׵|]릨<15iN80!10#4oƷBdoJ8h=>I_NviVdDs6^`036ܫ=8M)b"^`}DwpÈBiy@dTC&gEr?ϱÀઋfrV A&ZrЬx9؝*Wjq6zpo"]`^t{;x҂M5 (T#֑K,nK Ӻ(g`:-|R~Z_)%%2<Y`FSM $5lt t(iochK&}!-:*7P0e-Cx^YٞIcߗ06jJ{`rв~,7{R3GW@Y8Ujо.ǢLR\qn\C@R_$ zD>Qctk\lމuwJuԈpvz2K6U64YM` t^3E_~>J2F'zqCl@-2mN351KқxHWtrx6gc7t `7W}խ3 MHeq}  % n?ᾘSui/O.Z5ȳ,Dxni=%J~ |>( 0H4*g)yG0.Nm 0ɿ` Sy SP e܈G|FÓmQ I=C rΨs  Nv]6vJaW '˸>SiX; Cdc>rvg CVڨ*0g!BEڂ%>]!qAyI`]q}%Ro!PmOnVi#P]!ttC7"b% ߈$a^yXo__0$})]l9+.>$Jfej (:$=BU*~ /btՁO34ԘYc]5쉮yd4x)Xv~OaV4< <Xu\4->M%=5..^#5M bQx^l5E>XhW23Mx6)o/]sϨ#<66'i,4oׁ6gx*+ƚ@2u`&)*6:Yvkh:%\7B+GI}p7qi*q%~C751|PJ~oh~UE75t*9tz+:[7P AG*+(Cn17Xkb 4a97]kTH3zr$7x01AحC8QkT!mk;{q9`ǟ [k.?Ϡ-P[9=>)T@l;`'ܘڼjO=<'[:H{=7|! %GAK6)ܕ==ń m0!m"U~>;ĦR@Xih>PFGhBۼI > 0r18Ws?CC$?˰ 0g"R?np.M9O? hN?WT?Զ :oM ?SA_$<@Yk*oC|Ĉg@zRwGseR -]@F8͠%ۦJ՘!^@ !e$"ܐ݃A(o5~A>e J5 (yQIAH#;R fBK'DXQB֛^DzBR*hCz $S,Df+%T@Ch\gwqԁ$C+drf9N+oDN޶pm*W<|DU6S@4)Q! D^ga{!KQ_~|jDּդxvo.dYOE7ְ!AT&>VEFŖ%|,<Eݨ(prL.%X'E8vT=_LcuCF`R&k|9q*?Fo<. \'S)ѵOF3荜)Y7G \{*G ᥧ1dZ rȾܳGMdrRv-m)G%q%ٰڻ$HBh8pGܞmDG1½ я>YGךgX=Z@Ϟ>UGhYQ%p*GNh'\8rH"ˤ3uZ"HQ[Dabd7DBI#Ǚ,zO'I4"(kE KIjϦ?;HiG$8Iy J-XdloRe hIx߆}CLJ2@TP;<"JhL'ۈ"2J)nÝjBð=C nJ5e+eR#08wOSJˡzXA^ZؙJϭ_9cq'KF }J|Qqc[KC72&fM ~;Ht&Wd{KM|[= zP˝~MHvw~ۨ !zTM>1hN'7? LMs dMzӐk7NcG IU럱dN@]tp€Gȧ!/N|[m "GN l>8GNS!)w>!ʮX0(fO'5 yҺ PJ2/;F{Pu:H_b0pPeNbC%z4$M=QDLsra:ݮypQX s <= 7~G~%QǕw$Pj&^TRkƷ&{C ˰RC8}iG5ERK2L-2ԖS R^u(BҺSb3샎kbg?Y^S"-K\iA=fStkbAO0T8rB_!tƃ Th){]XIUJ*wm/"aW#dmޏW~)4|hRhhW>qcnX +ZӼPTX0us"]*X;cغX- {ൺf?R!XP)0޺YtƷ96?ؖRHAY_IY7e;EY1 prD\N\Xd,-Y\GgV'gg9Gc6ZpS)e6Zr1h'0¼jnZr̈? ai1Z4`HU93ZD/5H%Q[ ffZE;10[|L}"1iԑ ][an>.` [!v_Zk[%#䗖^ץKhylrɿ_;I$?a9܍YˏP8_gu<\97a _x:<[}rX9[_(p\s<|<:{`qer쫜i59a`>𻶇[B>0 Fa$AQ7ѻa뛉^pCPb3&sDq5nb4AeTOO3č} eӁNnpmeYie c4в}mfpN&:6#-fAUN 7^Vl$Ify6ZN$t $jf$5P*b.HFXW<}fԢ`sidZMУfXi#4Uf {fK.XVпlc\>'G=#>[ZE+r$5l\U5ʣ*cr-)ko DIE@rnlr$F^JÕr~> %j鉘sO=>#9"O'_s2yCBKU}tzoӄC/$u>%@J*ε)/v.q}iO &WvQDyn)SWr&v*nVfh<vÑ͉߸!B9+w+fM5}Kw*껨!f{]nNa9wS t5W rx3IO!䲒j-v(+x*K(CK<Ň7x]$.p[x` V=߻ixwiL&YcW>|]xiBn_lrIyC=HoXہy]M!0O: yaCH䡐$ zyޗޏqr gqyB:b-: i|,g~yܶ`#,&p4^V/z6`)輸~S1t6XzPJѳn:LߪX z}z'Ig.8G%)%z >5CMwxzmzkfʪ*{sḿ"mrd|+p0AX 4ո#:|+,;/XąPO|>D?v,H uF|%3G's rJZcVxP}e4`CZAԱ##8˝}d)^ݒ)~ HD .Ʉ{Y~.;l&ev7~%1[KQa~Z zpcOg~ 1[&d..ꈓV$ m7k2?o4ňgЮT|k5z%&r#!p(7VK ˩^tqNT]gB׀:Y [I?䀻YL,f]Ù )qn]+C@Rg- Ǭw`*H@n[P9z-JT`a&+5Iu>8,*F π.Y@":!kV& _pRyْr_h-zqZI@ts[8|fky8D xh'CK{ 29oAR64|R%nahgjs+GmDn?U{||B$PT?3֛s邭N)ClY,RB$ +^2>PUEaev08"Vkќ] V5sg&1 /n5!y}D@A)"E7V5݄3UXI M0Δ*,o<*2m+ A~sKf7BJt>.G:[kqph TOo)XFV곤Ξ]&+t+y~J͘jޖ 8'!4+z͇俰F`~ˇ.8x*}MVۣڈmmiU`;F$XYһ ?o,LjF\4v-,cΘP` /S}p.~G:N[]iv$w$*Ќ9Hьl 눻AP F=ܭb.Eugm#o֍& S% ?|B䙀TVgQ i?@Fǯn_u75n#?auRMmZ8A)Q;e SI0<gw4qP\^AvN|L0m,TvH*Sj[LtcٴS> Ɇ^EzE1c[;\X=c/&~򁏘k(~8cPbY@I7X+Aoh:ltycsֲL>Pn~.^caGY4fMsqI;^\f?^KW:{{׏HYTW8ѫHvPڏu2@uM, L 6e!ykʸ EO CH5jmJx}2 XR>&Ő(C7.\к;"*u/#ټ XjL(5>OkUcڑq3垤,Mh`wOؐxQ *{JH&aA.Xvȑ=[Dʈ|*N9a9o2`8o<#LB?Vq. ୎'E`PC)gTh`ZlP)_Ȕ5}+YܺȦBΐ:R*ʓW*G^EDZ[3n`,O4HÆzw]:aܒ,{xH.hݐnsāܩ9J/OnjΞXZD} kIS={JOt1eQt 7^7m *ᓋZPLñh`eժ6nAPhĵ.uA[mPDo2ڦ)[wzSj bxu#%KSdm&z#!W|8W}ƋρdlQ # :b7ڂWJTҕ/ i N6W0:bC$ b4bQEMfЕ]bS~`xߕ[^8,";%VMt~іi08W\M̵\ = }be|`I" p srSh`& "!0JL d̷m:病4K[?ksUKp}.3 =Qx̙˗h698&:3B&Pc "vѢNI|G:f -W-]nHeʐ8AuMnx (Mq_in0јKG>yKruL?kO4yWCÞU ZVf4/J} jHZOPd2o⚤c1Z/ח u#==.rq$Ght,$KѤK*Ca|lxj4paS fw@SEá_;tڜ+V<ߠ>YUYY;XE-FE` _H ߤ -MB4VN>hI2LxblRkR5.mb97xjTXɣLAzR/uB_hHMAyF*[)Y-7ׯmM|k#y0q8*n;H%],wg,Z Q aCJC_8 ThE+9䱅y/]W|iZMnCMvus?I t%琢":_L\WA$u~9;JG˅%Mhc E}Uֆb b*u2hyj÷GVvЂO(?PuDo4pHpd|IynLʻl1Q1P C\ZEkg CaZ6=Oܲ\R\RlԤRcd|<*'T-}p!zmD+]jvbo;z@Iť͚VITNhNNU02s[˘O{WrE‚K6'Me ,Aq3:7l/7DiF7qkߙ)x7YKs+-0Yb@&FM؍CqⰧHϒ jnRuq(7d+%>[,˷Ԑ/g]3Q}I4?yrlw _m#ڳ(Gq!&uXѪ)iߋ؎Nf&\G.%4CdWtc_;W7*'aQ}f N#[W:/lfܗbZqjK0WKl0qOV>2@uѲs ӱB :GHӍ$JȖXm/<9R{[ H9~{Q {9Ǯ"ر"${oS ox <~?F5T?'-h~L?_[%Xw L`&!xAq#c 4F'P`0eVZ 3yj-zD>No:;QYwrt[Ft|σ%_3EI`rpuTQµiA^œ.c"zc& xUW""N(e񯌢-=1YVGB<檁DV8 8w8=(v|3BPۦ]fT' qEmXG*=7W!Y Y K&FF5NN%D\dˇjn@eiU3ÕӿX1 dȤGyM)眾@vߣ;/msj=_H}M8F'{ii< &^u$,;O7YǭIpb~Zhݴ A1"m@:mV \;8c-@ XLϛNhhȴús$`H7>,a#Spv+&>KKB<@'i:_!R=^ɋ:ϧUjI4i!ɧxiHLAXl:񷊵#.RVMiMR*v3Ur@WoAQ:NZXjdAu\b0P*Y~gEgY3G/2ˋQB·~ `@f3ТOCd`Vs[4k^Pf–Cۻ̯Ä?# Z5+<1 t56 (2㍁+?*cy+06RR1'-4lFW$_W꾉oIfA}PsL{-̈́n7OGT4߸7NNܬ!.QǕ~:OcJPqnJ*m4@ьh|:~.}׶&lΥV҉[FG*tq6B r Fx,l)tB jwD|9^ճ(#!|X w]èυcA`HNdRJSW,֝ʔEZ1٠K]jgH緧HJoc|ʽJ<&goguRZy<]-ܻU[Xыѧ8}V|L#IѡOaG" _+Yw~Tx>\hψ ֮4|wҩ{ ciD=U_ҫIW'T@~p8M¸ҽn*~@ 6$? 1*_܇f$Tq .ިJ0EL5 '=j*FJ ˲4LNN[ CQ(u<< :!!e/[+|a +*1ec IZ2VbL6s"_ 5bqPPjL /ո[ER o]9h/g PJ`W0rPAJ<eKJ;'4G5 N.JGzW UunNUX9WNY36 O}x7* Pa2 5] ]Pt4+@t5M jEN>ڐHJc FHӀ2s c/֘қ)5 ؛.a>w_DQ4JRך0qo33 «)vnu_(@3#]+x}+ۤFs0ѡ7^pn?US&w~ׯɟV鉖*/g!-|Sδ90HW_o"5ġpKu"gae.Y،McC̮eEPGأU?uN'WT1 QsnFPe;-.V"(Hc٣Cyww,8I9hٸ~boI01_/02RIQ]fosbNsy=6:s z fyK S1&Ì4[ 3hh"!o ? M ~MM[)zAfHzoWBڂjڇ(7~>*'99Wj}ap_5-۩ (>݁m%1%d۵0 敊~P\U[ ۻVk#clԳ%p'Dm 9z ~^3XE:=WF5+4 UCO\V8W"t8멮ѧ 1>Kt1LJH|c݆g3-*ņZk&ׂݶ`4@^ǀzM/{#{ݽR[h˟#jzQ`flMaٮ} ֩*EQ'x?m߬/4[:Eu}g/1ߟCx=_do|2fc:VyZ_/e>3Po?bEj Ls"ߚPv(P_潱(sĄ%jUۍ- zZN8 6fI|4nZo L{Y #)Bi Қg$EXNk?JK"b{N9_,˭kК3S?[`|ѼBt3hOy8XӍracOLߋm"m60ۜ= _^_@Ӎ\M;[Yj_޴J`Vnko^F o7e ̙a ey6yFO䮡wl,dX6Dy6f bDjdW %[K?W:*Di@ɽ_DGT2fG}wEi\օu? u:g t>7%c*o=30oVvXXiaSz^1eE%ҀYY#rhe^<]<@j$[ޔw!24-**e:ڔ"ګbun9Ik&;G a[6#4.gRbt|qBmI?'5Vջ} i3^\Q2I_A-J{SRE 񱧻<f)]>E%.uPIC <<_ϓZ_\@\NuqXha`tIlyI8)XD8*qSZG/t: iD5c9mbc566}M{Ep$J  ,'~#ӎؓ-RJ aEϹ( l XL9[S 6ݫW”3  -~͸^CCX,6A+R|Z=c(*զXt1b ۇRVlP KT9žo`$ NeH?Ӽ!`S>atЅF^Y x)i3@'V| w{WDrvN`R?™uN@MpL+i˒Fl{gy%CT~RWŢc<l#yTπFLrm[!XL9YkoS7jMp/j[ݒJ&1яEXΗCSs/KUs@5ޯ.\b06|CDY)!X!%P]ĞȕiKPVgqЋ(Upы!yQ7M` c(jo@~=H5JnZ}ͥ ?/  Xԯr#&ZROC(9әlZ(mţv)>ЊR~kwZʧHm_ǝ-&e v~Ύu1?QR T x.ށ]z}d=Rh P8ɝ"So&۶7yd2 Ǥ\t/|#,:Hr PT5 7*yPz$D'T4;mЉ2w ewlrMXsG4!ky %j96kxlG41cLTkiظ,. Q/W0%n%SUBIcZ[xv& H.;}$A:cۥr(N40}oly[BS#ޅC:8z1]N`Pf(&Yzn ObY]LK@sC8=*09R&N1Iy4p% ͚%:FYjWyZnXGu`vK+&NW}Iqݿ+hS͓Gr |R$U^$  ,EnCx8j 2veݚ&d>Cm#ë>"*9R|537e/j(oƾI0F3 $g96PAi5*̂&iK=)@%=? C6FLȬsΑ[bM-# l{be֝mWmÜ؁'"m*0!Fq Ed+46$Hy xJY*(P)ͨR[AP]$9it-𴢷E|vqx#j<DU}|1tY EvuY2jǒ }A=n[GAuQЗR@eI0hTQfs&dжn3KAϵO ],#mHiaKumGnȢC"d ,?,}J$g[S \ TNX=}ʦۻ/IAZGVNnuBZ•pڮI9c|mݑr yaS)<& w>p9#Ÿa}^ėW! hsœrXሧ~ |NmlA%V4:דx2bϸؓ .x^,lW snÆz¶&HKL;; {,Å zM̴B << q,&2/3`,uI2 zBX^F]ĔG2?iHV3g c{SwZwlpK-ѤxK9^Ya](K]6maWw^>s[ab )Ro_ P˰M`څҰ!|8zXAnl&*˂,Pqp4Ck d  ɞ2<+GاCvg^~RB 5JXHbEa RZ;>/x56e>8a'y #eJSq.Z&c̤|iG92 cnDQOcGU9Ɨ XkC\W#<-Zo$,Yuĉ\@ Uj4.YɈ)8W$goa\&I( hF d^[4D*k fqW ^@U&%kXՌ&?ѐx5Ӽ8%8wrѣT z(L\[oIuV2Ȥ-LJТz0/^пeH rT`.թ+kC\v}}1֣׉ڊKcl3O>pȨ"}BK>w(F:[tB$v>Zu8٥GcX" 9-9oBk6cYAJ۳0PWn4hpF,}Q(tg x?܂5m0vu&UfE0 ` r` 41u2vA:x 1<6Rki@ѺRm/zֵ^t5e7fkK4;zafJ>XN8/p˷9m 'J#]DެTIl$79_6Qj"z2Lhi $"OP_қWV ҧSiImv'9|fPSh'ҥ--`R.y 8 5_)+/%4gwK# EK/]P*.^ 8 G}O%L5 _Lt}-,Za) nƽ>דNM,w,&AQ%`hcXy+Q J Eϔ|a}]2ܳ_W4ݒ4nرwZ oJU$q-T%~,$FTu3$)*,rzwҫ!_B HZ2Dp|SSHLAh6F$!a+-$ss>QGLHB5ok"aaGLRwnp3RRTJ2M_f<3+qe>7Y Q3K)\/8yP"+64A/!>|P +vs@rIvkx꭛^`!Dn_PޟM9z% &!F'Tsٓ;$T)ny64+xQ^'hG_wg RFߙT+5E1\E",FKNhMo JQPC.&f#PqVa.CUJ{B=w7wTecuҲ 5D6|RIy G{|D3Z=.4b,fʻ&|kߊ3\ U\XuQXOzl&~?uo,5^3vOQT= Z<V1!7>}9Fd)I,eY̦d*{>sG#Ϋ7aTrfմV@Y-?z1@x\.\&&2)n[{e!)^)u\ ż OZIXZT W`]^?Z\nR~,\d/8InT+,oW3.CAkFR^#:;_|v_sWh"(EIp4f)3=RUJqV&6NNOd2T^N-TWpPu#C)7 [ZGWMuƤ_34{ d 4 1EY'؃T#[SwN]iC/O?a|$^dkHU>j];hC TwZ.6kD;5JMm'V)UӛRR|SSy"oY+,/;SNWc&.g!#lO"m8/#Ҟ9W>3QV;C6:R$Z̧Os1;= &@\ZK0#>8AYPk ?y@%(OS{!_v?F $&i-tAPZ;T,cx$:/M,^&> #)]=ZD<]9TKּXpœPJ=]z>?aL1.69&L0 4<[a7c%ST|/J-@ZdI[RD]f(2R3hc;wAѮ4`3KM'?>KC,?IXefe'1N[?[hZG-'kE÷_GeL>i,t2D[4e0ZD%s054U~ (77. 5w)OVXz\D< aYqP*/XX\;?:9fZ;$jDH34+>Ls5JM ?oG:b-Dnes.HY@E!}.$=Al"(le7\`!]us}s2S$:XT< LW6u)vd<1s Z\Q>Hj0<8K\"{ y<1MTYTqrX$Qpg<Gw-T6j)v m%/]2jJqj _D\K֫,dHn/AC/{W;C`X0Ub9DJ$F0-[mUX@OO`zY@X0t8. 1Kđ08&]\hTZ[ >D5Ri=>D,w1v1/X2q, EoaZum2p)#^ZM5ooaˮ_R!"Oc#0á7++gXOJt-73A4(T3Brcת*WcjwmVj; Lck/!h)*umQPASc!^J,R<t./k>MZeQ2FԽ[6ɧ'#G)^0SeW={SOh_g 2,@2!/p99xYhS`-&d 2_AEd<M:;6(`#5ju""QNn%U8VN}4cb͑G. :1f<:_c7F0+bG!Hd5v?CFļN%Ha]wz:.RXPLvK.*c^J)nN8Ve@ԍJ'%/\ :?n)~oV=.nH6}6LqsTP_libwlocate-0.0git20130108/.git/objects/pack/pack-4eee77b3b34dc60fd348739ad812044055440b8c.pack0000444000175000017500000113620712073002423025114 0ustar jrjrPACK5 x[ 0EJޓ[N&mFׯ7Dž9~@-neL%Xg5ǀ/T؈Y;r}5 Fr"6{O9!^}vYig>5ZoN{hڶ.`gZ'yX?xA {iqը +X%7~a``. #eζF 4kHԠ]>S^*gcsѦ$Y1}}ȇF<_Vz{hp!dŀ1mS#or4&<V_Dߚ xA "م]hcm"-To~d27U;PJ ѹp"9&.:GGepCĘw.ɘfצd/?ݫsZբ?=ֹws3U{֏[/M@=xM 09E$=-ۅp7 3: aƋ6q,e8 ( &QGZPBR1ArhϵuCJ\z;&&Xca2M#7V_?Fؙ xK !EѹpU*Z؊A6ٻ"-Q [r.SA0!]4ryd6 3*v]\ܒ~k/|節FK&7@5r!2uVk@ xA 0@}N N2M@ĝ'D mSx]xw殺FH8BT)$$y#ek^]zB?:d*CԜjv6]y{4-W  QɁsԻGa-5CK xA 0@}N L2S-4Q /̓ƨ1ьX%Э٣T(Y-+DRIu&KVtuig$}M۟kdo_gw @x;!ОSPjfv%1F{/g[d+ؼ.}JDBE3Ztd&2E_WkR. ))e( rF- x{kC^?[K= w:j艌=0>Ԟe 窷ҪdBxK 0@=,QIҴ U&)i"qjnMl 9h{Of.}8H݃hLi>b,&`(7$ĩUoAUu[s1qڕZdѻ`И̪W۬7X˽ԭ MܽQM$xMN09w!;;!.!D4q8IH]F"b=:gU%$fю)EOmZhPI%PBl7 {@gMiHDp$ 8 ABD&uŔmgWkU?}փy eko)g1ĕ&sZv LVm{]tdU\-DiWݑs xQ !Og]Ŝu1]FWľ}..8eS! Gl:SU@*hĎ$JD)9VH}<[a?]d^Ϣh尶U7'L=9pΔ,W6& @ǒxK 0 >bo(WQ$ csf t፮ sH.y=cb+X6L5<ǀSUӨ>5PӵcCP,Ap*( st8?x7Z;Їz=pZsmC J;~&4TD8 xM 1 @}Oѽ I68R;_^75"D`)!:I9I4PHAV~4dUqDd*t q5+: ݺԋvh}KۮKbpQ9O2^kљJB xM 1 @}Oѽ 4Pw^7v=#-%J1R8e %d_ lSsG Db5{<02)wx۽<ޮ `E`Pm'SC^CZHQ_8AsxKj0D>vQ[!\ PZ!׏ 6Q%18"D=9PYvGyDh5`鯟l3 IɵQ .htޑ7ECuESpz ֭Qkm;7tkO2^mWu-aV2*’rsCXɹ^bWl xI !ᄁ`; &?sr)]0 )qYк Y&H5 OSANAl(;vőΥs|{[O^ 8M1zm6Zp4]s DCx10 E;rB,q6UItl_,Q%QA>D ֶEֲtfE Y&:qg7,m τ!dxϲ@uYyKO` 1;$D1תfF<\v'WyBY+[4a;5I_ LM xM! @=`ob-?U 2_^˗9D4%c%\I d:):٧f ..kBk!p'A1mev18OQ_9MeֶRBVxM 0F9EN'OI2A xLftA`p2,Y0QԸ1*8i= :r ҈vcQɺr5o\rR; FN;OmOju+IN=ww'Y|{F͟ xK 19Et:NOGGp.!UCԄ9qe6CS.(c }֔ЀW&3JO.בr}@uǐ?ovSx:䭾P/CxK 0 D>Od+PJoRd[iqR^Yn1"15L0QbNEֹEHmڀF~ L̆#IO9>{)gV|P7YyKpt|Z5SS3.9 ZG:^J+ xA 0@}N LɀW&Vm(>8YDh(!ŒrHfWzZQѣH?; z2BWB>1slkro\=F*"Z70Co56|I]DZmOW2ZPj2.[$sxHzWKi/K~kMxM 0F9EI_qVlSV}Ҙ!}ɅN-:='C)&hExKǸG}6RHsh pgmPW^p%8:8NT t:ghv;O"L5~ 6n`^H𪻒icD}IKxAn! @JHUԫUH$o߽?8rb^8n&*+:"d嗻'Dqߘ݈($=>OО/|kXXGz^u\Ԯ!0!-n2O/Zj |?\Ay2vt1&| 2 859W xA Eb0Q(W1*͢_=?vUœ_BAriXG*X#RT .{jUHIYS:/l1m{-֝Kޢ 9f蒇 ;@_xAn E>jcc!f`a\dQ)nF__Y0j+f FKm0c KnX8U27y5hˠ1vD"oQȓ$:݌ҏtx%QrqGkz_j/)'~oryZ_p̂ &ӆ{DbߗatfZ=s̍סuwO{p xM 1 F=Em2퀈WI C]x{gV̵US6"/xlLXհKUsr)Qb٪Q e uuE6nYb>VGNag-3AxA 0E=EI'i[w^aҙhMBo^zNI٨hmsK)vC:M3m ߸ #uphlӘ]ZL9Z( ax!e7HxAj0zm Jȥ/WT`KVJކڙx)D|tCZbGAb4޵t+0-@%L牄 #gM 7p{l׋jq p9{fkqU_ CjxK 0@9DJ23B۔vۅpxpu11fJ^)6+/E]Vϖb{)YBES;Mֲ~x.eԗ;ܘ֚. G{Y|fE^xA 0@}N 3$M@<4mC.χכNac` CUڵgK D%)L!Eg>oMoUVI~q~8kr$@aV9}~H#^{^ o.[˜XrfMW0E*xM 0@}N v@īL2IIu=>xsh8/9-)$Ҧc^΄`-$ ȉxb|!oxl;5s c ^?7u>jyӬFmxJ0+i6e`-yy*(x6 3s0oBk6K.Ò6P%c𫗜hp HV[Y"b\xjٸ7w <~R;/`-a@h͗=ۜTRm}C ͦZ/C㻽]oh>fXYDxA Eb&:0BbW`D[H&^/ycĘъ6x}2:I>\XR7Y X]q)1%=OMV>mey: jĀv6Z.u 3S!Yqd]Gm+VHxMn0 "YFU vb27Vmw\2)zkE2%L3E*a0 FXKd2zՋƱ#',HCϲA}׼㺵!ퟪGzZ Sk9Ϭ(u7D]mזn絴Wz\[ 2+lxj0i JHNZiZ*@ftf9.@EL Aϑd)hRG⢉,fX0"۬)/*=M:->nYhkфy3FTϺ1ʷV.Dj[Aҥ~O]&9*%o >R xN  euQ(q4&Aw^y0̌.bBeHux(i sR}HArt.ה9,5d3G);~6ru:0۶1Ϛ~+/ZCj #A xK 0@9Ed2NkѴpxS"(ؕeNb$s s[1%2J(L.( adӟiC7>~Xnw^̰m]ƛxQ;dA xA 0E=EL2&NjR {"Y$PJ"VZ'!@wL?kLh(1Q1\CN)9[3N Q\@t G^P#bfßOuC(P`mkh/ՎBn/AS xA {JWv7kh7~a`zS < )GQ% 0:MqYIJMnq#N9@8llQ{JYօp0g]|KQg:/BByx1j0E{B[##) 6E֒qU*P;)΀d9dD6ݨT$4N0NY$H>E' N>db"93)<6&OsoB6YeKglJxMh"?5zl|2/xܸ8F^]xAn F=`_ɚaRU*;Q$O7AvoH@:R2J IbafSp#sǰQR<8‹IS!A|88nت}+<0ۘ~ڭW,/RTb"S岍hn9+fT xM! @=`ob(?$xD 2_^K9D4z)[Z12Ohb QyH:!a@5QQ] }Qv,8R|6K/n\vl" >0F}o[?zx[hY>@;x; 1@bzA23 bk&ى.MXb =M,esE%txb&>hl ?!9,>2;䉑{<*=Gṷ^cBǎ`ZۺnvMKΐ>0=^a DxPIn0 0D2P$R[4$i~4nّ><ԸບDwYa`!0yBS A;#+M s|#!){ҾʽRv38l |]L?k9uA@܏$?qGfqxT%w/RkǟxAn "{% lwWeq`o.AnsF]98KX2Ji es04HB Rr8oic%C7)|3,ge`)}4/!3ܯת*9V%ffRJ4Ŏ~ԇdE] xA 1 @}Oѽ iI*i's]xw3Q ԔS1$XrIU"$CJ($,V5;=kzT־}(Q) }9޾֬N[e>ixA0}N1;$mb@īL'_%)5o^TlDe9LS~Wo! MѳYy6%!(ADҒ'&ʉgr} W7"ށnl pFB4ǭe iR > 5h\| HxAj!D̨>J۶?¨3\ WODa. YG~HrZL{E\d(8qbȹnhzpKyɠ/|>;g.y,xMh7U'fܮT Kt5hI@y%,'4?BTZx[ !@wW{^FG!#@o^H 1ASUvsf -i8he+"ASK3d5XXJAk?(nNyٯR[E<).n9vCQ_g$/dEIxM 0@}N1{dD$H^>x3%JM QrrĜI;SթuT:f%Jt-H&Ac:,~܏hg/,/<XweZx.aejM܌:W۱ 7UU8ڸ+oHȞxM 0@}N1{AD$3 !ۅp Iœ J!/)c4:х&vT J$$f&xvwlx6\kQiTRSe sT?ZnG# [}3p:3JxKj0>vحz!!ZR6-#kEͮxTޘ&Q:=FVˑ i!ڢ#Ko2 5޻*bhlTg]4R);V CbPC(pL|p=Rt$ FcLuR+Ƣ5 $p;3,b=-y]D-<4=:dz>[RfܹOj/ ?7k xK 0 >"[B)INqzEt15ę-r$D +[.:64l&S<V#C0p +P ">cٻ`h}yoOm|vo`I:]mxmI}Bژx;n!{N1] K awȊҸ X,l`ķ|tC_q#SpIZIjqE7Y b C h&atfY3H ڠTP7PF.c239 ϧx̹Hn`Z!7yT剁~sQ U2"V̙xM 0=EBdi "^%Lj6[=ZQphah| ht6@dMfx&)H SvE[]XeW)u()U]UBfA!ckMz]yf1Nx]j0u}/4A) JnV{]#h.зa>lF48}fUtYє xK 0}N hDL:S AI oY$TR%JVfxw}G\.-2-*HIGXH\ qm/"Z)3b!@en܂Smc8?DxK 0E]EBy[Knjm$MQwo܁;8my9Gm8fAK6N@Up#TM$: ˇt^9<22OԅKNQ\~6OK 8~+{ȥWZ949'D],2Ծ&BJHpT: xA 0E9E2&PJ2V~;OZV(,V6s,G =2 1YcјQ20tiێo?xLU211 uDbs_A xA 0@}N L:N&Zm(u}q`EQBL"1Rniz9l^U.:K&.#Ԗ1Sh~ﶕs-zBJ_ྺ.c؟;{-:v=xAj0 ~ ۉ@)"K!\0vf+˜ _у#f>ŀ!9 2C≒Umq@>2qH@"90P1xO=_BϾ>F-=O˥h1x^WxA 0yEBMԂ_nj6i9Lv!x{9`B Gy4yRյY O.HdRBȜ!aΆv/Ֆguf{mk)LMinVʚK[]-z x̭nf)fID|RxK 0}NP&Dt2Hޕ7pVOa1PB`JE̐AVN<j lSȇ-6*<և{#}麵uBim2=1k+O;E;>P&ޅ5E}?QӐxK @ѹp^ ҭib7kD4;`Ò-"y!({Фt͌ 0f)n hBf`Wm~~es鬣6na)Z}3E8_8_{-ZqMxAj0E:[ƒl ]`<;m׋\ |o*@8R$W^ԑXK8M61„FfA=;7% og+r~.Gxh9ۚ[g eR ׭h=jz9e9v.PT21wfUJernvΆ@8a]׹5oofNZaէdh q|=eN?G7TfxAn bUWe7dpQ˜fW!"Ϥ9(r9\VHKR̝aKő7YA˖gϬ۔ T(qc寳ImC+geRo2?Nw1b-klF^x>lkz9b~%T x[ 0s yWfw`E,K'u kVƴ3rrov AR Xa:LYAր{^' `&Հ`7z~-__UumcI1V$!cT,ԡ({%26e/4d!; .f|GxAj!E!VB&Gr"hg>Rd>R)oU;Ok0LdLVV'@ Yfjvo &g(~̯>Kޮ֐u:xoV'meNLG?PQ'%A>C >4zIY|_M̛ xK 0 >"%PJ"rMO,z. o X!R MQ"}*I)T0; KPIPQ%I'.(0</Rr0~ؾƻzyH璽0mgf>7}v~bGCBޞ xK 0@9EL(3D )!.ǃ]D;H68b8;,0y;FN]`N,".K bFB3^F/?>+d !O`a:G[R.֬C<xQ !@=Q(DtqKpu5G&mOID'w|AdJ]0ٹϘ}D Ls`Q&=ǣohe}P'U[v)cȟꯦҾ]_3 9gQzZ[}xKxj0DWhEñPJUb%#) Uw̜@ K3Z׽]oFi-jVH t[y!,zrVxVj2+RU)Ee=A c +X`\nԪhǯUwJbґ oubã9vm;O 5ǩ49iz)rQ= KޱF#-!S9M^ _aKzxk19`x !E  \]u"SFg,a]E z;8;:N X'dA19S3 amH킎Bm<*[Ykx.kZz\aFpƣ3 Gtw40xxwEAA%sMYf)xN=ɻ&. "T-XPK)Nүٱ/46æ~埙xƺyJonO3e8o7JxQj!@= 2B Qԙmuw @9Db!ct8rvsڬe&cj>0{bxatI3q#93B DRw>Э{_o쟹՛Fkj@uZf~hu}znYڡ/2KWI xA EδPc0jR/ /罼ߪ?*34J@^0:e \57 uIe ]q 3Qf0|Wy{3JIw;d/0N֚c+3E sAexA @=`o 1 JlA׷ /%tfH0d [oǀbuHdI<)m&G)a1,=˶q-/rLmHe5zr4u-cXJ}JӭTjLwNI|G-xK 09ED{/Ih#]xwܘeK@$$bC@ր2V ظMXr`Š [ܙ|M }Km7Ei:'6.`L]Ro,G xI 0 ~"/J(_%95I0C?000ZN⌑1D)99jT^ؗ$LWsR}X'-iJɅ\H)8e cS`3Gǩ;l?xv= =B\0mu 33}kS|jD=xM F9`n[x1nEP4@ݽ]{FWSr_~=3c[hmhÆ~RK$4",u]zǿ?{/{_x,"v$.MIxM@ @=tR:$z{9@D)rpF"zoLK 2b&8 h&c+JG>k$̏c_z4I3} su]gUwڈ)mWZxh Mؗxj0E{}E/KZK/iSFcy C ͭ9W;38i .9*3R؆|1e ; C#G 8`#ci\b1[_C<יގ~ģ/+ \8zk 1}m uT`W hg}X 1Yx1j0E{b,K$6H9c>r4z}̐&ך Xͣ"SNS8d 7;uXSr±"2Yq8g/ ox}R΃q9셛/cpGxZS~_TN}] ">oPI XefY4?#YxAN0 @}N=hp6Hqqڈi2J]A9==yE pwgELH>9!vqI8#'u ifG cyh'L< ;Ɏ!8CC9"Ko{;:Kn}[qqBmEUvb|T*=ОZ+vmWk ߫TH,!]?xA EI3N2ʢ`(5z{&}dDaJΥ %8ZNZ3[\ =IIMJ)B &ƳaEF (QfQJ|?viףV6lpFur_.עs9Ϗg.Q}OjxI0@ѽN} kp l)eܾs[|"^ (!Cs uI`fIFItoRLjgu2!LϜN/iݷߏ|I-NlW'7W& FG8׻*:R׫Vq/xr|w}^VpxAn нO1F1RUYOd޾ݽ 7 ;]sw+@ PW@KuEoTA_^UxMN!E9`nyPU$Vq_IbC(W̾ R,l\aű "v=lztF9 FXlpqAr,8aʂҵ[DvMy ĭaݵm xԵ_R)u҇tB?{mǙ>QQxAj0FN}!XRz@0~ay|#tm޳xdJE$K$hJXD2;e ơ䘆XcQ#{ eKEgZ+mh;?^R+ Ϙb:k u{h{*Q9J/-pmM/sVxKj0@ѹW-A! &t$"l%Osmaћ=*EY+HĢ,Qw ޥS0&F+"a`RyzԌ[r-~x!~33RݶwzoMKBͰZn XGxAN!Bu00@b6~4( L_R :೵:ِw+k bNj(X\(R\VcŊ+&*I)cC?g)>n2SMxl ^ 儝QZm!_ NxQ 0 4*Yja[3_of>Jy8i-D=ֽЉ`10Q9bp @` '~f[Q~nemkJ." !മkn\Z[3yJIxK EyB)݊$BbLttvDJc‹89DX2LEl%9mуVh ,>;ϹZ4znl5[j{,ɥV7`IUؗ/I}O4xKn0D»YD{E@Ѵ`d!f]UkY!䢍'J+RXRF&YRw` N'* <@H}ഏ6`=uH9ˈvx9q7>++GGf5 CH!@o:۶t_\,;a7uúL?ci}g!N;J{/xxAn "{%U ,d؈o.Aos42t̡hjqlIC4-Vg3R-Lv3d7ENht;Z~Ihٛ,_|Nse|h 7~7(ޛOM0w;9Pt4y& uV_x1n E{nH6`0*rb%X)V>f1&ҤLLL j$g;D7y; (SD@*L8q-kQ+@ls.ܗo.>++GGf5 C( ڂډ7(o}qywmzo"'Q|u ?ci}g!N;JE{|y0xM 0@}NP& U&I)Ņ7p4~IG6[uɶ x5%O*:`EOR6%7%"_ZEyuwi<=1J+M" "O(%nsJacIܾ4X8xKj0 нO}Ȋ? a.0Pz[[C)osRf0c^8bJK kq$fχnz;Ou'LS X!"&_~\[ԻSߗyݬC(پW|sW-j]P1O3KQxA! @=Rc4&1ƫ-qAW]YFK$in KyĮu@a-ըna}[$?D>9[B_:=_"k݋>=ڪnO0Qb~_пfsM[ݠ7}BQ1GvxA "mb_ٲ`(5{M23hH6H@#Eb fBI=I:i39If AJ[v>1(6]ߟe/%mMKp])0B,cT{uKm~d jNx1n E{nH01(r%X)m $ 4QE+ Lь!J6uޛNi&dm\ɹ=͞UyxA @=`oc Ҫgpw/cLs+8LG^('[s%2+66P[?_}>r]Yv;틌 .wZ'⋶ 'ƨe O+9Ƶ-HxKn0D»YDnEQ.CM{@l\?bgWUzZa@֣d`qH% `ͣG2A&T"gTaL$HAcP T+gvR:Je ) A9k %͹s_~TUq|kNye(ԠH.m[ZYo.wgqۨ^ƛI:ú߇q_Z_Y"|}pm%wxK 0FyVy\5B)J(hbK]Aggqz48 20`9,ef u64ВXbo F7 Z{Dr-?agf'Xc]o%&ߑHOxMn =`_cz ٤jno XR/䣔?58\(/࠲Jp4w9ѧjȀ&O% KN[LK0qFo~ap@6c=Eft5+BR) ;'9}`xJcS'()x31gwOO寲gT=p^xzz@;õ_^\`sMmۍaJ\]Z1TobvjZfN*á^6 ţNv@'ouqĸ!n* WG_W+7ٺY+|B"GNT&f4Awads@슥ΖsX9x=kwںjZ-$> zxI k69{;3lɖy>w]6;4/F#i$:..#VXRyvPx3/ =μ]{~.g2 ]:[fϜ5[A9lD P24?~8 C9r#'Bzoꆬ]l/j씈uo|~xѥXQGyt9F7N@ Af؛.XO>_F 8rX x,t`o5 Th$T"ǥ?%d́Ku>("`??P?{(QP#,a~rIG3sW( zEɇ4L^Z}N?$F ;}0ʬ˿X,vjzuw8`PW >n;ٛvYfև=g^}mi ;z@:2$(P>";z~>m> 8[ޠ{۷|vڝVXgVgTƬw_OOT>{kt~O^iՏO-N jge֬O,,ܱ-!:vb4AA ݷʬkQ!^\@uB.!zcAU3E~!kZS(,_}T(<-0x5ϝѷ; 5|ν?v%M?]gN׆3g>g?؅^RZ_S}ث<ޫPgcϹ!t)"joݙzcEJ)nj- /'7`Ѕ`9ǎx?-g) J/ UK|hUk{bꌠ}}ee_6x%8t3tbuu ?]j05s@73p8Xg=Q$n<:^!mN=0Cǹ;;R 5pЪ> #u -3nhqyʘu+ tS_B7?4l ك0!?ތ<7h uF۩u;wf#x ˀXb)0+'1]b9װ݉7 >mA+zN]~wB>O3:s/0d`c~JIjtgO,q_R|z xo pĆm{0 ߝl;^`b23nX\|) $!8:Dh'FJ\C+Gr&ӌaDƀy!  Ę#]~7ϹAE WQWAa4&sJ c ˜"ߨ6=h- 趇oJ4o=V7v"Z{kBFV )W**4u<< 62X3.491 ͪ AۭW<^Thi%MA^04g82PĶIFrW(G"i'2%zX᱈IT,'y)HğL~8"\Qtſ 220|C"h9+3givRB SIG&M>eMOK*]y!W#Et|E}m,]gvh FC )EKDcU%?P(~3越W%FO#skĒI{ POk&J!DP<$ 38$7f+%G0fARLɾ _@/UwIRvmS:t!4yfk'> 0:m {ǼП,R/ M_h{p zvVrװ+9I`}@k}@ߞ(B&гvg(0)e΀C'eZII[?y칢{[HPsБmrX }:šzʡS*?ס= tRCr2֏M}L"QPBBU͔v{EGL̝ [}"8U]<Ϧnbѥy sH}ʰzn'9<ۿzL,gU 2SKJHh^sOUnu}dBC![ps{4M+) d6c/NE'ũ?r+R>iE]AtaJ[[;1,[k{c{Qo-p)Hg-&cO;_o(>+^'U0뢐//+ȁ`1GUP*1 Z??%wb: .D>*$@ C%*Ū&@RC?gmye? = | [`$s/`w R 8t߽J$|O5 _3qtU፪ Fu| guxbn8n^]ٹ@ZHbj'ބNk1RsPxgݦe7kӋme̍F:1>0aǙO~!3cIp &0cb` LR&IEɑ=IfrB'e_8NC|ߔ#o FjS{py|=&.a{A DCΖK"jPBo^PjH7xgFF٪P|LE X!A Fs8 A8 ;,[ -DPDV ?d|%𰺊` QWR!amKw^I [<4J*`x%W2!(g̤mo"(2-w-) `5؎ ir#"%vLZ##pomagQYeU*֖gD:Xһ!(f-]b4WlM) 6pmG|U*&[eV4oݑJ[,I֖zʆ#&2ՆbAs"~wjԆ;j6K@(ƯQoS RiV"(=͇F_um΋$kFL BGFwBK: ZPGAKEZYĵf|ca9\TUZMbJ: Ȧբ&Ϝd?F{NIbt_hK(j 5#GW~Ms+|,!by'5Ys\?wV7OyQy:t؝8ib*λiH3to B:ue[ =Z[p07JQNžY~חGxɕݘְ* kX^)4kk0ֿtFb~Y[H.ВZQ+~$2Ys4^s4 .rCPNR7,=KnI֭Y ώJ΍} )Q@!rQx1|"NGkb/ө7:2?LN~6+&X@F)!d#ˇS}S:jGMYl㜻?9(k+f@MƲSZ{Ŋ`%U:`r.?~Yo㔚PQv/8Tk>z1qx{Sxg.ssqHCӈ;u#Vl1g>4l;2~C0 )hb1!V5ϯ,ߠF^tX7.0U:{4OYv|Jt C:?c&wtgHd#8@Z3s13X)&̜+o ˆ9OE#z2I`zRuW&@A* 27b33VxԊ^xxj x0Nf6YyO DR!r~I/>s"Fƚ]Z$TO B y8u`w5CKU2,TQSW .2pԤ9|n+*(uBGǀ}Jd-I8{$WJ6H*m'ۍ?{lS2ظ&r(RWz-IV3WWIH0-J9^^1;7=ceM*2ԣKG#Di]2ES2f3xatu=3tJ"5ؘ|*|e^,X5?U!m7a_.bi/xYϗ<V!y|dǠlSFv_\w_L~̒ EWv|'3Y7U^<! i6}|KІ#kMA}@YKxB5 l8P~ڷ֖ NR:zkxX\U+WC?x/-]'YEf7{13&4`ٍaڱQX%H$W6ZV1$&EH/afSw~Asj;'QJ!C B̹g8ř?Bu[-yҗ-W#~Fa_jsۆxU4~QA) (ؕ pQx$?a?oLwႏ⊊bR]_ d;*3 }{I}`0}Vj5*-\5G& *l55۽WD>r V|ɪ!E|‡jpnx341Ͻ(|HŠNR kV)<|!OK~rG9cQ)n9 )Wg1rVAW..=\91QW߽W>\&KE@yH8|HXVE|ԓ_,M[0I=1rt`sizz֕_{z F4yjrHD;[D} 4딞zn Ȋ]5 L+vc.0O"xn2K{bBMJS$>7h%gt!kԮkt.&9PJ9"J3+ڥH#t/f2q"pG.|J͚d@k_X9O,LoJfx"_K&O.Iu?I/5mϯ`8yQum疮kʌ38@bs29O zs1x}Kj\BLYqE_)dkη;o5`#xlwg#_l?.ݵUk81枚7?+ߦ.BbA?~˴+hWQ Yr^msm'{~6/o[9 Xy2~K W,&mxD#q]ޞ2-:Cg[DB 3 mf>iv1ؠ Z܍brP,t[Z\10/x%27Ed>)(EZ!f8] Io<]׮ЬYYLL`¯5*+o 򬦩 艹8T0`:K'W*/AF]"Ԝ艔rG]f&I]Oپ8Q&ڕzD<]}ك7#OZi"O򜙎32kTjmZA,P /_1N;W&;e=weu${W˓& E+k.5&rnbs~Nq&nGLV%U@kfO ~$22-nHu FΜᖪ5=6Û R[~7 תpG[GzGo9;ML-׬83MӕU/qao`8Rlԭ1䲵8Lq6Az=njO?'|uq, %*;wMS5}lNRnee}vX5KX 8Zw!W(`aC>eE?teƷ*Kl\/`LcOz=.o4 8ݖŬW8'=:$5U+cy:Cߚli' N2 w MWZ;' V3r:!aJJa8/j5)LG^?~ec;W ~Q3oM5LyS~2zԅʉJ"/rC^0Ø$eghWUW%Ӗ'_9i=|}lԶwl/Tx}=7 =Msf:y|Q=!o=F$,?QIH-ֶpiAg+w"9SUUKh ~gH(٪.^MnV4פhx_~YP*3'?gIsgYz{ω ;r\1}'QL1Kk~Z7nyꄈJ1GєIBm 2ho ųMBP|BfOwac[뵔m4CfҳR\G9"۸!i%2I( ʕ[Pq]k_Y/4xm1yYncxo Ϸ#{?yf\%oɉ -c\`+oRo>V{/3)Md>^z]՘B RpGCX?b{g¤tndHYDTkƽ8s6'n؊t]Hwz@enʹ,CaĽUvw(k:0$ 93xKMdxXmoH\~\TZ'%ӗSpjȻNB] RޝyqFÇQc 8G۱]7汼3ˠ?G8p]`,a"<<.LH..xط:P2Z\pųI9G j!8 D*^NOC` |1ᙴؠa#fᨋ{2x^}'޹pAIJ?m.*g(hv3?$!^@PAՊjsۛSX3$x,{ Bcm)G񳁇nvs\xʃ]vXN|t~;s.z8p{zmVfu#Bԭ#T ]}V{NAh}s>"v~n}?ceqgyu=z5שO?U5vb[22v;~ez8vkި:2畡*>t*%pP 9#\P6t8Ŭ:YKDi>I8$sPeB*AքzM 35Lݑ2xIP)JI9l|d &qbA d1~io8, Tcթ<|+ +ת*< )8n &9T9Zgh/3.Q)ҿ12B-4/Q| Qo5v6c6+m@- XBq`%AgGkP2BG#2fVi$+Z[?,}*ƬIśVtR Oo6M:Dum,Kx{zp`;Ҩ|D*W2١U+"Uk.QN+)jV`6GsBÉ+}Pݴ5qŐOo:tYܦimn;hC^J1D<$KWvqKJ2}}J)b5][6 Lѭ\*"Ama>ʌAJi.B 0^~ڠz OJE(=At[Y8[oe"h$Ͼ-,߿{ cd>irbKhMhJhFh: q]pVEVH0g5?Uuj5&eV 4RI ='YR_~$z,ynuy~m,*{UC XϐN3P%omz.8 c.$ؘ7qHXjD-Xqcy߿O)=E1WZ?rVQr.498HXɋ ^"B~x=yסXgӍ^ۥrQ у_ۦF,A*9KT J'USƓޞqZ"?Zo_M #b!H2$HExYB:f`iD,ڈe~4e \lj@_|hdLr1~ ]uAu*ce8JbCʊ}^d@^U j4σP^)kZ3!{1xE˩m9"E:.*ap9# X6X_cʦR r!6)ti1jwєʼCoEt\gZU1QDtƣ`$E&?.&4d^㷻kLsJk2{, ,&$c9w="  >`DR$l@<>DN)f1c\А 7 (`11%.ƕx "P0G\C$nÉW.$&10y<2:j4y}&u.& E7NFRi41 )\^ W zU"A(LFᚲBP$ ;84ZLC (*R(Bd.AΧچn6"1jsNG#1/H/zAblT__ Tq͍,a*UX[lR+^`m %ݫߜ_[ QB1039+ԨT eIp ? HG?Hh,>d.Y(;rǛvfw[4MB79M4<: @p>2<OH;=ЀtHsعDVV;+$#X*U8]B" tA^jRTGOv"34UWb> kPZr; BYHRpC 85g VA0L0rM^lс؍NTE>qzJK:רr:v]d!T9@^svDPZr&Uܚ(xVrAHM Z%OqDP3:;WGJme6& U֦ ,аޓ|2]:8ȌFlv^i4j̢4Zyx%a{6 }6e~~Vej67 :XV{7}QN'HLzlA'aĝy+v$CU&fSIp;x>b;HW ns;iN>FW2zUQRګ5mZcnf<}Ui){aO?9KQ E ӣmQY3T4g>OG͘%;+xxj=3iT$tPҞ ubL{>$0+n^ym7g.mU]7NrڻyFnn~o6xkIn/NGv@hfTRx4rYܰ[[oj-:/k C=(k`"S;na闛Td9S;iv6UL4$nw3ǺxxK3rݶbL%q\`Qc  [oō"w)erӀNFT)\>|6a2.+rcIel3U-Ev^ǐ^0Kup`lP%b̏]jysz|ha?O0vki͏ZyuKuжv=DOߎ[ߎݘ ^B۫/;7 ƆT&" 3 L3&bz>Z$2G=Ul_凪,iW>IyN:e| ͥE:*{O5PGM2U)<dH$c "Vi{_bG$~O:XpW` Ag\ktYLMp|'ٚ\,7q+Iެs6FXHιDF IۺA\=6w׃$N?so ž[dP^8bWv$U`;jlUl՛5 e- f%}\Z8Z9($"6n.mþ7@8|od'c3VhB8ԄҖ>66;)5DQ۸NV {1r+S:O!lL|z73̶j~?Y&}V[,K~wQi 1H, 詴5oZukSi+1:{x]rG}Ɉm3xc# C\F tUدO :y$|Q[4, \m_;9@'GX_6m!9y 7DsW;;b}H?$"h(}L}`HRvOYְv3^5,}]J//5y$bױDZ ݋a:#AgkݼqcU?ڻu/Rfݨp׺g<"\Y=1EЙw_#ΡmR-G`@;` 6Ŭ]ۓn)R*f(Rʥ ӗH }Qn ?߰T"F;ow- a5X09m7NHwyGՠ% X yE;B58g&=VJgNH\XUPouc~*0ޒtTQC{{uLHa'ۿtnݜ>'!׳ 6}9L *y,U{ݎ},A{*(a1kVϫ&;LZdK`܍߉։{&—YuW$~byR&htPN EwFI. Y%g[lz+7%Lإ:Zpyv2&ʍʂe,!@Jt]V> DVf#$( y `$N$~e[f=\ah 3bX=cނ1)i@HX/"Wص5sZش8qwq3g0D|D&Rl1ڐzyRi,Qimiݗe;(S ༀXn U4s镕ob̀ a"$ *L *}ulF@y)c ;| wOPÐ6%jJ ~lJX650 g^vC>I N> Mө/vMYHG#BÞ z!Aak,wd[i!ha.B W4GdoPɴ SM HA\#g{Q'L8Rǚ1=8 =,>[{ysv?\;۔3x觠G'Q ʙiU߽Jڂ*Q.&V#LM ۖ`&@p kFҩTvSo" ccgrgL_p݌dA͌(CRGR$f3q4&3O"߱]~!!9ϻ'l8L."8ȔZ Xq!T=T^U8dJW1f+ &NbflX 6SVR &Ü,&%dSߚ< @6 ia8A4;ЯU҆ة7 &QӚ{D@fw6ǭ^sy㍤ Ϲ t٭@;bFvK2mjT(SȟbRkTXjM##D͂?}TUU ѳ;:(!,m1m .Qi*Q qcؕ3x}/K<8r= vݜ0'8#2[yL ` #hw_UWׯ@nf4&bt 'n^.3֥4жk`$6CP",0wqi$S.}ԫ%=SUH/ lo`;6UǍٻC6rG{э hN~} O 0i%=ċ$ 4]qޱY&7C&p6y11<9ba[1X0^_P%BOgI<:P95G "GoGv[J)ݬ۱Q=dfGP5o L'}\gav1BLA̡# N)h!.B,MCrcv,ee>.Xb8t}慂G'+3L༔& 9?w8& -$TP(E-Qug4 (׽5o)-"@B5IOMu DF0RO(mX"j$)!.!)%e5h5qH9OF^F0^i ]`RzѠMW9 Ib]ȱDN6R4)'H%xV)67Ir;9D"$5$2>ኸp_@MU_ON\ɲzɎPg_z"u@FDeC+G{K G "#w.`G|=$(}[dƨWhJIDVӄu|6cT7UgBeeȣ$)Djo7CE޼b?v~]Mb8z$îZιo o:e:28Eċ98bz Val+X,i8 _Cӌxf|v2a1z10^ *v]I>YC1SWu VM4,vd>p`T3NէaDžϮu L:w qdRSmEHkSf76&_..%z I _b|- XHYa{Lݎ~)r}8P z3fWչv Y\J\Å @p AÓP)4~P\M/!T|_uvCW&㑕·}xj|6{ )={ Wu?E a"`Oݮkc06Ğ&ᯩ}N>4TmLc!.)^܋ORM3"122 oh:K.?g*Y?851l$ e!V0u$gXQt?v~?4 'D3RO- *x_[qVWH}ZG0"Eix54MKBFHsmf#uSYċﻤJ]Rn| U;Y"F9;mO6+G&,Wk+ JO5lǶ?\F$Pb3b?ϩO&m _:NI(Dؑez&-)&+4B;L64"OOR/|d: {0VӾc m^zj}rS@ФPn#X RmFdZNjysy+y8%_ @M%»#qmCrʉݰmjZ3Qh(!{$8E4Qj * ]Bv1¤ xa3&%; [ 2N'(iDft+mAMWK-y Lj}89Wm +N\%]sz.H "HrZPjh)aoXuig&nmGOۤTtCtOܫX!lĨQ_;Ɗtёx6"uw]r#%|xg&[Y+H+bQ0J";XwR t1a0 0('JArD\^ @*dBPЌOh2IMI9m`kNHdK?TŒ--) v ӎu텽b87Erԉ/:n~@&?x_΄v*bc_PUPq6Z[IHmuQTKZsrA\6.7"Z}`*T7a:)]9=M+a`}9EY(b;T&j&͎C?FN|\v_sPKDܪrv49cHm8v u۞J\45S:#ҌvpNPpPc^׍Ho|LB{T&2y8΍{,M;P|͇жҟQ~ء^|Hz=BF |h.T{44(Erc˓P0TڄF _,`˜4CbsKb}DDsT|7TҲg857cW]nKoX0'ҺQ呓Irȉ%=|Ia3mؕg#iV_@01P,…w$(A#-/v2'Tg_cZ@Ƶ_ 鏝AfGNT!@7iw{va!3ZZo/w0$k =#r-7&,if45g$3OjcOHw=n=k CXO2ޠ#IƖr.JI9hA8 +8#ɪc1XFQ2FeOyG`8ტpY섔(|,jyQ2=qzg/~NXl9A>Lkǚi\q_ޣ}q6걍|ŷ yyiA.Mpc!JvO (p(҄-~oqo!I~j^|L "|;OL:lL_un*;*a- %zc{]= i!$/ť9xrېUb}V~>uD=q"w6Jb mUR0I\Fت "KpHy7཭Gmuq%&~43뙿x:w3vys.Z(wmqتfr>z>SZ@j](r&i l'45oB+(]5_# 1% zw/^\ ıAS=opBV?+mt>ɀ,_Q-%cB9^yRO&w+xՈ۸Hai{@7b^kB^h`K3e2B,Ф9tTqBeqe#0!+џfQTڲx6ix ֿwID4kr5@N PZiG 'F]PLaG`:Ha _J;s#Ly [\$T~)^FhƧ lJ<\8= $ÂVNFf뵤>'Ma (Wr}"[k@9"/H|nf9FJuGNUՅȅ?=,06k[|C77h5Ky6 ںp^wʁM;1~ضa!)&ɚKbx-x)8aSl).OcgCA qߟR rv!p$>=бq"'VcAɐ98. a^(Vsޯy,ȅ mӭN$ K~⸴ 7e|AJ0ˎf]poGi({969.{']6n,]JO:y&K+w-吳 OA$d)=|6܀\-]=6 RFۏy9tz["Gp'}; 䐌 wCaLWÊ<8{nH}# 6/$Ѹ7K|9U<'Z*#T2Z\sv";bX=ɹ̒Jk!lYLv,X O+B$QM*K Z?}\)]2gCM[>}};F Fڪ]D\riҵ'[4Asnx};PhyH}X)JIp2҅W3qn3"\ KO)NU,ԥKz&3z/z٠6k s$|MH>\>{?GWChPhvݶVʚNNoEZt[iM@f&jF\Xz% e#H|xu}8"VA2JdVk&|{^[nҬWz)才Oz {믵WՒulڙo@FT#aI'Ӎn7p16q;:&L]ǏQK ﹐㝑ö*pV:ΜQȝA #WZp_R]YE/r+7 ̮ ?%?-F/O"H{1씔^oz /R-Nµs -չ/k4/OwO˵3Y} "\wKˋFz=4FS`T9v95 q1L+ Fߤ?]${s{I&G.<$eL1>TMZ_k5 ۑuبbwJ )ʢ D I&\vS!K-鰍 ܏6U6( 0df.r+OLD-(I˲9Ho i&475m(q܌pEZ5: g4$+P& պ enȥ!K`3-vkR\qS1hmmi̱:Hk g3_1;İ v. -\-}maPZmitMGxC/I [DYS>+^O!\W(`OCSpH[Ki==vE?Z]=$Y񥛆/xWoAA t&Iq;(btMJ39 ^c 3J5 4w<!0-953nЫi|~U/ Kc}|ӱeJ`cU,hOf|,)I$Ȥ&Zm9-BzIǟyAtGicS !MB hs#(NhL8X:K,f7!oiiW&ipR/kPp:i <y@CHӌm"u9 i[[݇1w\Emrߟ( ̞f)g$1{n Em~c%ߎ wyCn~6xC3v]e]>#z7sRR ^z|MA^>M(3d*6^uU 1 G0It"M\b):H.F\ !86-X3}Xz.Q&bS^RU+2yBS~7ɷzL0rĻ^&_gc s)>m@:݁5Z?̄Ov%+XDP|q9]% {hO.Izl:]٪:~*iØ_o,d=C9ӿ|!x4ևm]nHڕmNjbzqp*/8QRwיKIɋ'FnFeihD=beBsz4Z ̄W3MDzu;2I͹$s+w4 UB(R%!&JGrc6.|sC"ORA83Kڻƒ $}/߰H ` _Ye̾!B}??dʸk\TlJ[>wwݿcԍ\z>j$l؝kҾnFo$@apjY#. Ċp "؄^FB)5\D6{[彽ww/>w7?d_aq`ow3Z^\-39韗`||X^^~[zofao)Mv6'gLJ@yG|X^b-y{'hxA./>%Z2FyWKZ=p̦A aqw~Y^-_Zwˇky7/?^ǻۛŅ ?,@_a .a~}\ɚ mk|u_1ZطwˇE'i̯}OKv.o0͵\ WkY,5$h [GZ+Ď[00Dv/ E˽IB|";sƼ!BLQ.a?['9~vfoK@<\ iZb)h>"@[JYP(=$м?-SLY51ul~y O #iZve_޽5^Xn͗W廬o0 y<3||GS]m#UbVYc󷟖:TxH/"J TRU^8 pɇtoS5@߬VR"l ݋$@\"T)ј1FN` ANk5?Jh?3I0Xl$  ƌǝz~fKOu=%o 4 ਹxMP }"?0ҪR#/N_o+ *p9cb}T}5͊6`=%'TS+hGF0uċ:x>8>6Iho|v~\X##6ݖ {hId @vv%hN RHa Dǥy!R@xMPn0n8:u!9~QxE 0SbCM(5jIEHRsٙɗL9V+Rq8:ǎn}d!Hy#OΉrrGFFb!wY:4ҨTwyY4$:WLT}߫?HF3 RcT,L6S1;xjw8!3dۼQ^"5YCx`l6{S xU[o0ǟ=Ē]Lƥ3l +ő6 _9xhz?m,a;7EiăZ~q/RX:Nx A{a: kʣ0 ;s62{q@o$N7[b ȓ8,9NV oy) |vʈ$ضWU1ʖi)+Yg/RbE*P2FӿE k/|k \|6qZ:]aD9OKgTJBZҽ0VV-mDuDId :,x<kB=C}꘶~Z\b߳#+XlȴI?hؚ9IJ}f +6¨+fg`p.jFU2λXB*a )W1v/_pnFuKp kȧ?Ͽx⬍%.6tjGQ.▦D,T.?3!@ҞGбMc%r/Tz=@5C`}CV>w :`]JST4_xQLEn[蜙+/Wďc+4L/4W Fɕ$ fDY(+SK#X%6vt;p XdYLsFsT_I=KM♌hBϱ1 IN Sy5/LZGLݐ!]GDuz̿iAݝv@0SpƘh41_@p'"RߘwWȓ4D+꽄$42fc;ӪV3Xm&i"MϮDbH26?;<7Q/lxס<@&K(^,;ÒW*&ٳX`PҤqk,o=yK r]CvI1Vi ymkf$HD0E+*eFkxE~9_}—ӐZ!BA) P#ŮPƣ,2:{.x9|-&dck!G$LTX&H{۵~D (NAnih 9 xNRJ 5T HDxm1nA EV=-] cς(9iO.G%"1qe[ӽ)9&1Coz PHOc`Jtbz_=7T(-q웠dALx ?۷v.V^+T M饉E)zi ~ay竧|Pr;E% QSiM*:΁'CUm,ASW7VrGAdZ%9]“d%՗ YxM 0 +Jvz&n0x-t)C"zK“' ˩$gN)FiGt{CP¹JC@oQEYII3|/ ( 4'&PY RWP1_mYYG%\*c=ܵ@;1-F x\4{ǟ ˆB>_|"<"Zw!CBAx<(j-fADcRf捝Vn~IWXtx31\n )]f˕ov]'-x31FOԼaqh8gȢM ax31|+Z"ԪIBkI6x340031QJ,Kdt0H;+OZz97of(x=k0Ew;_tvJ !C,ɱ,i(ꇦ /E~mݲR֛l 9y<]^ &u0@X 2戽+U@29ʻ«:/$1A3*Yk/B:#aThԕ>G̒%N{ǡ]MW-PiKfhW8WAF %X[>?AQ=Jb} uB vHb!.pm!nm(-@##pmʵc+Ur 3rF1׃3jp$Woh@6e\E|(탼ks WT{+O%xtznqܡa lqعI͏Bx< ɃossQ :EOw \Elz5ȵ"<֏:22GE93#VZ嗯"+C3RͿQ<5w6Ol6|+5DСSr|xENA pe 5!j5S鐬O,9i})6PʽQoMIv@w0TS,=; [i}nծM5-5I%#I9GXI3Ga ½!$)!˙zrjQfNLLf0сO$dB.&egzV%+~lg)U$l5 5UMȞ.\~VVQz0 x31ĤT݌L>qX7Uccw'2U]H+S%.d wְ<3\jmq~J .'2A BsN |PDAYbNij1O$CsnF}x340031QL+Kgh(9rpYG~OCb?;]<x3PNG  IHDRHHUGsBIT|d pHYs B4tEXtSoftwareAdobe Fireworks CS4ӠIDATxyp]}?mҳlY,c6f1,g@&4ILBt2&4M-fiJ$L ;aIo͖ޓzY}z-'bWOܳ|ιGXkySC wOPOPB *zm>Si FS*5+AUQU5%TOĀ '?ikE*"jE~(TӒ$Dm}o|uB oe $(3R_ﵶ{4ZϿ0>[_~6"M*D4b5 VM]Iޫ0<0 XD9!hIFB1M*!FlQHNYj:Rlq+cmCU2D* p LGH6U.FJ"{1y01kԉ6 W$mx/JWuC X)cic:u1FKI UΖu\{;:$dә@9n'j\(90Xk݉V,:TJa* (Q|DRFCV UPa k$6t;Qau;(}i9hQXy5Qf̾B[j[HYz!]X VAoG u\ .qq_/eq<6{Z.~k ʄ7U_!eU4=lM'ipLk$etĮ(TY JXgl9ge.cEde_bב)H< HEK?Oɕjw w)1P7c9n:3ւ5 $pϑY޶ GİVsxl /JÂr!J,ܛ<.LWދHEe+JK2ěTieB7%Qv1JŊW-چ^qs[F083&/qEBd+HzR,teCJdYX64Bow=AZ?AXZA`uhmjZkU> muX}Zku5cJ2Q~طLM˪m`FT FѺUT0o?e'@'MǗ?ǡ6# 0# :P©}Fj!RX̸c0V}fBkь4ڵ16~5G3a(*z:[4fl-<.: h:sM DSKJx7mEkhQ.Rx<޶yn&DŽČm"đ To"R)X-NHil%NoxΌᵑٗ}7z)#z_sX?yVf6#˫~D)N4w2~Ƈ݉g^ziT-xwZ[&W4PWq{6OUvn['[ bx޾!}H몢: 9gK]IOz#Gر}' zqrqv4 P@raYu+C7 n]¡/"`Ԥ{TtEsXu-^T8R 86F{@aGir>6S c5J Tduk-2S'x2UPs8ҿڳk- Io1%+un"$8U8#üc+ ftcB<'# }K|w{c/`ǧ}mW&p23es8Agő *s=2p?`)Ls+)o1[cG0Vto774ڪ঴N!XNUc0cխtu7qtn~?|(Yb\-6Co6OE@B=% TCH)mhʡs "r,@e ofmǟ3Txy&v9)bN(#zl\v/ʲI#= mB"ǁ>''l u\BۀH1S-M#S\FvՓ6k)A1Kc8M@ht.b[X_?#?C2lij)xw{Ix:i<`0SFa<%l칓+3; ӂ/Z"ojx"Ky Kob Hz'o,@qeu]sa-Wng(:h+.g}MH{؛}wT?bqD\-cmrmn>9LGr-)J?yルlzmCE` 2wkGx{0ü1!)lbǑ_qWX~ }c/_d҇/S~!qF)]fmgY~ T힯?\տw] ;91k؟{޾)$1Y5bRs,$_g Io+K278̉d#<댕BuA6tΣo߄y)aַց WO]26X7g/5>U9%AL"#2u-"X0[Iyh?2k <خLcf7y p8wѧpXAksPTXДzՈEߦBK/ceJtϗ)e?Kn`f:MQRt:XgG'd`-tXFRRR2u|b875W&gTF3x12)x7шZS}1Z+kMsN#);qelҽм; ﴰmx ! յӆE`"1:D.MF'/$$zѧ1|="R A`'0"Xk2hFjdA&Ay"R5<joC7}{3D: Un2m7k Uͼ8GhSeܠrfD],`XSCMX 8R+Dq1]0Iw!uL%,IENDB`jܯx340031QL+KgwH,ןyW)qKGϮ һkxDPNG  IHDR$$IDATX X[lTU]t^}0>"!壉 ?LWLĘ(Q~`降JPJ)J[iL_׾N:w*4?ɞ{Ϟs^g}sebVDQTխ-Щ5s^l9q:)RNOq>3ݘz=qU H(}^a&''fs*Y"!+*%CiBE75xTŸ5(aMӀ* |*D "SI3 'U3uz!d2#X A0i34ZVÒ[>kꟅ1e8XҦ< Ngt.kjF[w4>.շt@ 'Du$L6+&wMW@yҀLܫfrB!T8d$ۦRsOGF^5ʣbUN0hT XLkĎוgwهH zǺAWym&X?'!H  Yj(+C6;ZS0,|2kC;TUJ)~Zt$~}8 MoWǣDCFVώ'u$@Y_־/`:Yb4l*,_ u6-F_ RVUyJj% V[5OYcm{\A~ ˕!c?4,Z '*b_Edǃe~K4n|g!(mj]!4D1B$0MVJ#Ƃa=1;X6Eޯ1'rDI 2+nkj]G] [4#H G2ۇ;1{wh +%#NP@ @%ŧ'Ph=p%lU( sTa?/{)ze. ~:.h~ɋh:tA>EɼtV}uKC02 W٧R(ujŜH3>ld4vF9lq*^nGTqYo=<\ѶȂwפ 9ǏޑsPx\j,vkx /aEs+6XJO29Vo΍J5X`\ȤC6'Rʠ\x/MEsS>9z-I@/f>5B7JyP[}g&JhϿLU^S}h 96/dH:CX\FdDɤ0%*/n߀ZUDHIENDB`,0(x340031QL+KgXP+w/^ -uݵ /x PNG  IHDR00W IDAThY[W{fwe].ׅ@%b2&!B-IJԊԔK2/ jIIʒ1%/" .˲6Kw=NO@_>p{5T|*$W4RIJrA¸NL0u@X>d`vq}a'uhɃ{H(JLE(P5g~>Sר~;c}_ЋG&Ƈx\RU) Z)[|Y fE]~A $XE, M,$YjF%@f"d\R )3 s 'E{Ab<S +9PY^gpEPQyfL {"G_cjt&uη}YkdN=SVlSXӲ Ǝ~4tb$>j4EX,4ԣZgU3l\]Ox>:V>fb⩐ɻ59 #Dh*R$> & Aϕ=Hi+v^$1$1džwGPUH&$,7~ɩ5d|OEBr!5-[tQ F׊.MaSQS݊ G쵘բc#=JC`~%mִn;`)"!1WU}ظ\Pۼf[No*_vI1k%;v쿻:;;VzG{4 =[wWqXJK@<|΃ Y']p;Dqo?Wl+ф=w۲J 8|,-U3]Эּ(#phh9\ZnE8U['O555rr.$(G:!%XFKm$H$+W```@xE;m֙@hD7\#}K\`)=o~ƐR? *KPa|ppP/<(k7pa|o#ӇyfIK܇%,fU*5:: DR Vp@/`(ndYuzg(-Hݔr&MP 󾉕MKdB SaEld,꾱yq.ꁇGD[v"$1YFx9z /xE";>lں*L!\3  =>wzԆn41r['\c2,Ar{49 ]ݸ M x4P1^l^ssO#G%=21嶂qlkHd@,$M@rLLeE-+Z]1Xݸ'H(**7?Zz2gNX,X8Z@V(Ts8+CNQ8;w\勸PVӚb震pNykIDa |89\D.i;$wm@1W5%@5?j~՞:3 'BK-7 F8c~GeoY rڀh. ɯd6?|;U"r0þЏ]v@}ߕJn05aq^G..cRQ HJ_ p#1di=9ex>_Q{1U{RVʯqy0h糥D?หۭZ*ߡgOVzjd7ލ.:S55nP'!VRcRYpb:`E\S{qnl/Wr7Nr>XQɾ~]UZ>d K&6 FAhI@7V޲~,n/Aܕ8~Xoo$Iu9/ƻ4NB/-"^@N8?uDw c>u*}9\v1(5p J$qbx8J㝌M2(4gk,\gD aZ"ĂTʅl r!DR1á[ {DUFJY@E@3)hZ*9nH$tIENDB`x340031QMӫax)u ?g:fiO+ xPK0s[#՝!\q2N,-i? ,M޼_^~~ݕl3e'vݟL^Ur#!+CYpM4dBFBizMxĂ-W^v(wfL@@I-Sho+ k:Q 4-'!lj2y֧x340031Q(.)K/֫a\_ÆKXw߼ !+ xQ(K-*ϳU23PRHKOKU*-IӵP)J-/-JN-R" T[Ԝ|%;_RboZ\\YYRhщ͘ĂxKU3B>;P> x͸q49d|⒢̼t;.Ңb;.f 1h1x˜;ub=x31\˵gVjtW]  x31۾iWN 5Y|.7=Ԙr9Ec4'}{ghf ߂ε d:<ι xdT0C(-1A2zjw؟C!eyJ-,D%04g Lpi6k軠iC&@*-GjML`P%&r t[Z ~e<4k+yyÝcf)4q3\aFSl~HeD38%DO=IM-MnS15\? BΆZ4&0#7~eTs6K{b*Q$XJ~)h7#Qx2"ė~=$];\&@2 |-oN?&C!陟fi2,Z #$yH P3Kge+V⑎Er%re J b8`DsCp>qMIA gq0K8Yfѣ*sBpJIr#b+4z@g|ʧB i2 SM(c"U$*$Pf1W;!司1ttld@e $K!⁏s^)ƘhhZZ &ĘC}vu9NڝNw<&ƷF<&4 TFSأ;2_Ɵ,0C2Xյ\S@{ 9|K:;* A30WA= .9{** e!h\{-N@dtFdeDT s58o5XRR^Hֈ9#Wf$-blM.;nr04cN(']U $o}i;\Nk'I5ifA,M\lN),OH8 Gmy\xғ֗ y+^FѱmƅCN L$aa ʃ10 p¸*h_WH$ $ D laN4!m֍e~<N & K]M9¦4\f׸9ق:[Iˋq}LUo/( 3nK ]CC,y -*̠DABMSe&)" t9&6,- gY’ZA"H,\Y1( DYC?!,95 6i?!u 7sMj|2Cj@>Xu\B=֒:$낆紅$xY4 0Xg"f|mLULm%_E2V4-AiӘL !?-Y2˳hwwf{JHMZ:=ZhӳEVq*{Rb($R HdV~ai|EX.p3S2>νwRbo!QqK#և[}7] ;"΋ B];Sʕ+!-jHbΙ`̨@!+6nO:E.Ss]yC@qv^]v>waUiUղt,./hjj \V_&δ BAr[SbJ ?R\֕3 ;q =_`MB a؉Β}PB=P۷obP43*S &Fdjx,k<(|NY=rJK+]E)ReN+ⳅ)I~mvYHY[uw4go%~2sa y9n1(HBh +ӟXGN,0qrdvdAȏKۗfcooJ9/VecD6Tb⦪.YD ^O4~u33԰vz`t>ׯkg-ve4#Zo5OWeuҁ܆1&Zf3yZV duD1M`pKq,|&pÅ7dS}רUfnﯜ0fc volv7AAñ(shw<60~<SthH)! $eGtc9Sʷ2{03`/OD_ja ,$B0#RY2IU)yVSahS npw'BWNKՋ~-L;ΣtD(b<믑wp_XpYl/ڋK %?ա,`?>޲vZb? ' .徺jJ9_qB_~!C/&Z͒ 㓗f9B^{2:):&[|[ıv@cSZ@[yq*T'1X#RgeS"W+f0 (ʀ"uj.^HLA}y<;b:\6'+/3i1MW)g*- 'vKE0EJOA iYF7!JB!^ْ5h-q{dGzKgѣ"$dD"Y??) FZ7:h EV|){-ixxc>!a?i#_tY$wU6:yؚ?CM$4v/r:I*w[+Z¬"~<}T ʼ3urRt*%:;گꤡDqv% '[~9 ;3Aؽz+\ _B_+IN\MYfyJ| {|DbUdd.fm8LuTRQQ̷;[Ji9"XR1] E(wN@+NrnIj҇ US<ًu͓rh~n"clO ];dgv;dyX}`@!o<7 @?.ٛrj: }i:>3AhLrIuiC'ca' uXɉ PqWU*81U0]v]*h.ai.aV&{s|6AvLs1s(c`ߡ)}>Z@^1uߡ؎iiunuiZfn;phCuCgf :t̂֙i{=3ۡCg)#~t#~4CMr!מV\{ r60Y z8Ta8TuW3dq Dor=7%l8 A C^RX]͆.6Wn߬` x34 fl:x0SM›ఇ y ŒMWzafk KER/,*S/,].m9\ɴJq`ƜTZvl{ކ9brh;{9 RB} ZU-oߑaپC#37]oul}6z]sc8xCc-8еuWQܷ밝Y43١KfsK>>tL7]vǮ:zb#&SMN,ujO;smKsUӟ,v*?YUO؎JlCf-p[ǚN鍿r;hhfWeQ|+Fw\D9^/M}Γ5TbڗSRո=Ijuq~^-Zd߫ږv%E)n=fMNSZ^u\F_c< S kyҌrګ}b1^uCN ﬽hO%lI’i EVc2L+Q[?XXV.*`#s_\j+ 5ZKZȯkH(6η3X?FV-|eJcc_.a5=h{E܇SY Jq,iD}>30SՎm_rdx9e.Ʀ:L߼Wfi-k%rĒV,]BEb$PPаi bCD: o|t~dӅ7DwFT/}}bf;73(ږJ@־mrEq@+^ twm$ߍ:-yyy&3mCsARBRCw4~K-#uV6- X όm%)Zc;}P>88ራw.V>߬x340031QpO-)J,KdhϜS^|;>{.mQX_ZX Q짺o% X=7C( L-s_~ zDz.2xX[s6~C)+mSub'LId`nn{ E'j;I|sÁ ӔX,2~DL 8;:BHEK4"6KB-h`BIOP⌳\}dj!3@XqFD U[ =$]cg,k&+GB TTks+2t};NϾ{=;nLxr$SKnZD*\J2R$,FjnCDHU ^Xkh9#\|.O*&a3JHȩ[DysO.]^pvyM\>wTAh:eb[ ژ# kHR25mڗ/r!䙠;18k%;A%&VXmG FB1Z:j>g%WyR %$+ՐXvy臏u ܪ# ˣ9.;b>~T5 9 `sTCnƲfHVZ&[h oMK&)UٓRl`}-+ $Ș-WFG ҩ+LڕC#D leĜxS4|9Qm)?rxП;$7gD<`Ruk-{l"߇u]x$,>\JRg2[NF 3J 6f"'u:t1睤qΞ t։a:0-tw[yIn4}mR*C%n0j郫9mm2ObQ3f!?#m6?{ovFJ6Θi7oQj@{r w^nnj;Sn:.s^9IcgTψ~z['1hAzur H괯Bۮ[S}ejjmHBjU}V':za.缷VN'=oO"@0YnO6ZChmOzwffx%1 RpAPp2az9(Ιmxir؄[fTςT,KHV:L1O+_,[ZWɄC&KFN%OH@dF7W$$?L߹kFbFU&iK5K.QCi1oag$ ML~xBycVA885FC8  kIs5CA"n;v`,5|U< FQ4is}|K"pqC# !4S0`([1g5I!J70ĀjNZ%P(@ӋĹ8\,;Adk@ OYaм)^f1U<BzOU@<>lX t#I^{fV?A@+7g"/,{&0!Mq| y.Y2'p6g9ޏҶ[E[Lv.' Ü28Ϲg<@6 >]c֩T,l;WE;y2Į]8+㰛8Ͻ`j2'"LccC7 f}[koxu7\x]PN0 +qLS׉+.ZGh"[s_${ae0wً%e3P7$.L(f[8rƁWsi$V [dةķ=YI ̱ɘ19Wj3hDvINK8p__Ez`N˙ eP]&lQS\zJ)`\lz;Ņ,&SՈz2>$Uq0f6+7zɼVצ.+x]s۸$ZR/NzƱs}IHb"u$ew (1m:-$].Vyo(|GxinI#/$ ?sTYva9{2mwOQ#? ͼgAAFxKd.B4|P{9X0ǏOחEpz""OAqZ<0#wlp*XF'RxY~;rFA3P&H5nV2hH sؘ,УHyyٍAlʲ%u@߲! )I":٫0^ Y=:(qMmg1 ^T^{~=V5'g5zVԻ?4Jp\Vg.ŗ8tLa)__\6Ko>a9#U`q08<0lD,nSԄ >'!xDs-0\88럝o: p+b{'37!h:/23sGb7/ǥuto&1I 8Om NSĠQ$l]jvV .YN)X]Q6a'Rzתcri#-H |ճ)avq?Pӏ?~W5ƃ`b )uSĨ1"HHŭtS68v&[7-vpvޓ 8rU }V9,3LbP_@uI6 $)OOtbԠ)Sfc/ftF5;EfSE,zeB74ͼF Q9و9^09&~ }u.27G~|o[N;gۏutA#LA"Lt4-1@F*뎡e+xKѧ';Wb]Q(PD73Qo,YQhvHQ-7#F|Ć U~=ZWt;;ux0I̼fqPP=a4@O{LzOPCƛ aC,ꀎًBRpſQQ<d⭝Ա @G_-=ya_. CUĞ-um;mjqƯG#]moB3QxEo4^zjn]` yGZm"6jkMi,?4o jB nI($ /JNA(3Cbnt&*< Ŀ)  0 ‹,)IO3a3/m[5uD]iUuܤ7YzUYyO@-/-N&^ "9_js2fxU&)0,`M1.{Dw7%6QgdWb6ﲨO'ha0~؀iǨDai 3Z&?HWsya!Ujm~*[q6~#OD7Jǔ_ J܂`h̰ͭ(2bߺ# pxLo?CM[ 4R̷,@۱DSA/ ?@I\V[kER4NQmvZM南FiIW-Z'dw-tjnH%`MJ BQ24Aw1ʼiD["rED%Ñ3!705G,u[droa7CjFҋKa kC-w!9z :6>1Xo/Z73*H>8TRMm[jqXqyYtgq\.OG#"RdI8F> ĬQ}GdJXH~a.lDz7[$R |aN5cۦ-ПTà 7td - R> LqK,FN!4Y|rhq#zsӼkYVϰ։;Z'ݯ:>|NHT i6ңvvbUeQBdV#v_G%jc=>#^<2kmtX_] l  [x340031QOvIJ,KdS4]+Y˷L+םxks۸s+}l&;sl'ќcyd%ix`xHILxI:L,X,}YR+1' w^>y.Ii.].݃z뜦+ZW![ok޷[:$Y'em4R;]Q7fMaRo)0B~8E_MLI:VQy/wQhS`y&:)I7 @%͹<#e shFdO !d+@^. 0b|rjqNY[?zSo3N^.`|"y4[HQBs$AXdVgΈ+*hԏy%EڛQ$^-+R2bXM)sq }b,[,."AT |NO,vj]9 OV,YꨮSٚ̕^5?z83 f,?y<Gy1cs{;~1 MaϝWi.63uR牍+Ej3|@ް<;X FdIAM % H\,YJB62B a9Fy0'Qxq8kH "# $uo Ƒ Zz4늧5Wo7x$u\!98g/h d휸G=֕ƯXv*pet$1/X%3G4vp7Á HOV#Bm ! AkH&N$6M)m;u''j"6+SǐwWb'eI6Q0}ǍvK%eB[E>(dJ /[/Acm6v|9wKj8y>of]6pQt'Ih Hĩa<#EVY0^2 a-" トI*%XKXUbʌ[HyrGDF?/@ݭ85 tejlA%CuT񊧛$\BèN1˖I1@-_fò_Vw:=]\݌&9@NC$c5Ȣb/[_S?O ,M!85aVlĹlkI "L6mV蕹M I=R@2OD!G,H^.7Id䞳%3v&iҊDD%|f$!N,AD װR7{|) #A- N$2X!ԠV'99ojNA_& 8pqƵd` gY6-"i&4b֟0&gKZGl,E!*sи9̈́T y2|6ϙc^@MHdD1N,X`^;2<|Aq-Y[L٧t4{қoA"n܍n.!zSr:q@ AM\u>oy3NQSh4Sݐ^ Ns<7ĞZ$ THD%EPkl,8l^EPTURvxhXJUE]paNy)YU>3=Ywp勮ym{8o5muz^+F\yė1[@ȘQ|^ ,݂OĪm\1E'23o8nϢ^yǒ0=|V~l \~4>yZ -z$`HjLZ=ϥաndi9oUD@T]WL+]aի,2њo4dzF ۓE43MZIPz'Mw'镕i0z1r޳}ך 5Ӯt[ v:є0;2HkՇ*tK ȫix,ML,ve.s@[ӹOWwoG?Gדэ9>j~h!j.wS`i#4hc7 q{;(1R-Xk*E+zڳ2Q{f Q:sE, k, aV>+e+&Ye' Qs*pRT0 >$L#71qRѮBf9e^'l=jUE>x5 3$^=Lh/jf)5w$H5@=vqn^h\G1&`QVDȝ|3.X(ФuJx+dT^1JD i6ƚ! >,5Ś@簳D\yq]ýZUVz*H~}A̖Y0[HXN-HMX4Y5/t$ 9G͒JiEviMԊʑ>6^#,䵀LkZ]ӻ 0Uun'*"E6'0) 6iɞ;xï,,z$b\)i4>bm*dhadךZ+q6D7ltl,HToJo¨oþL9]KM5ضv۷ Wdx?n /I/dQ]0JhRQÜ"j,=yfwfؑsGi~><Uc^Dk//LC'B;s]0QLc D[$vv|M oRrz3Ť`pok?c{Խ|/`]\T}׆yn߲V]yGxUkGG: ,"y$"+K:1T^,'!Nr]ݑ,bhmoSKBn $C1 鹴Ѯ>Ly7o|{X;_V'&EeR;uY׶vtRTX dAL!tJ3PX~s;N# t4LOZ;hcl1q.L4tЭ7QUXvTM1uSk2Bn*Y9b3b3x"WkְtNV,)U$U[bh$ۦjY6^eQP#i < 5H/2~!5%7'xO1@ $8n;˕ڭv /%3O֏f8BY\4B#LMV\&H/Oϰr>ߢ]\/f:bO!K@(% 0x&XGG<>: $BFVpfrq=gHMFℴt=DL w5.H*ޠW+T~xV6rIrô78|@gѨ3|Bnq=37G[ GHŧ#t~{/ &x t3n<>n`̴a&oDzA`L<_0-BX S0`y}?ŏb$_;'[uzfs5bۈe32ZdljEmCЙL y\}"&.Bl cTsqdl0>P ȵ®{ԂLYҊo<@En\TWd7Zua+,#¹ ،Q m$ġM,IjUyuHȢNo64X1~J8QG[&aa9z)"ksn{){fr!VD!ţZQLFmj,ٷ偍D*`+v2fs\O&+H4F55L;La`!ucj"dBG̲M($3ߖ4a!ԇeBS&>jyk8 A#K"[kk{m&ٝ jtKzUlDӸZJ( xPQ0x1BJSӏ)/[mZd#'Y|oM:KXxBD" Z2̆bޖd|!gL3v%W E]*нg*j@]Rcz\ _B6T9W'Pr}&Y=Dve̺ X} q<RvۭxĠfFwK#ŀ ?XnݬYoEpP:Ղɫ%MI 4 S +h d?9{F# bI(&N .V(Z1̲x LHNg h -9:rOe+JqHv3jWs$"lbN+nF9"ZAKdXN*AKD#Xӻ<5]2|, ~K#x*}Ъ\BJ p8dnX"&0zZt JwyIo,I/}cXo}iah/l_BQ6tY*P?R 3;=f.ڕIR ގђB[VzǦ!D^:zy3I3M [7TK m%2ԲY-4`#h P;\mUl].lF徬|̦(ݔƔ F5~èG I᥋nK96S %X1t?Da0)vT[AoA#o# !h &Nz*z@>[Eq0E3߰ Nᶾ\{b"/xgyX3׊C:nK*ڕ6=~d#ԜUqeKP_J3)HCζu٨£uZYoН0F'n B%Vq}tOZbþVi^mxڮxi,XbNjHeqM!x)l {^oй4t+oɔ6 <@Fl_c(V/\IK5P1 6{\fErp4*g| O`dvHSښ,X)̪lפKwb@nj_*qp0) VvN#- &n#~uSuqGN%1ښAX,,&L8ɉLtrAҹzKyu!ãGL3g}NFa~kmZOVR=6,t6?&`є CwLzĽqq=32]"*ͤGt5{ZlE&V:L>Ѣ=D@mudbL+#%M}pQ!\vEP}*a>FS"+3xD#`dh54PWǷ:j@^pE r87v{`m⾠n؈GX^|v$*l.•o$ ;;? ݝDžwߖh yO~bQXm]Лf,9$UAd$QY-zn[J7i>);\s}d~k};*LTXH1v?GMGm-q3fv+|vF]sئOLL"?":w]>>۵# S2b ĵ?.ܨMaBs.0|lƋc > :ZdaȠ >3d5fFk2elcFXRUL0gnd&s\ [%!xXZR0'^Qr+ hTٚ'yi+2Y(8pi.S"gҳPfj\<@JψK bjSS4$j./ͥ)ɲuZ$8ӽƣ'H2"eƌF$f6 y>f)I-dzeZ- m'DC$¢Owi"cr95iԅ=^cg0q왢dZS sl&"Cܜ9s= Evonrr6Q|`~#=X{*. @†i'\ K5!:LT#BoķOB%,Ẏpw>I@*zglEeA@W溼-ƁВZ,R!.AŮ oN@b_dO!6FU*TyX>ICfÞSF`J#M,VKX"ⱦ0QzJRGS,u7׎[}mJkf؃?oRf;B, 6`^P-] Ƅ ŢAU!p5>yw0F8IثGVؔ츐gRls4T2Fq=q#1kaeKmKNT]:- <2I} WjÝ|&KP#tnko 즉SޅӠ<C"./ڶc&$𒊭MVoi@U0tûC ooRk.ШA(-.TNq~<}k.hK]tƚ=yAL蔎`Kɜ* +LD3Lva%oh\<:ge27SvNB3S׺1ɧa>1L-Öסn%~V ~6OHsԖMHu*7S-She&w#έXH&hڔ%CۅV}]"AZSoN&*hNr*6,k[U|UHR˔5 Qi,Hnygve(t#}UAu_Ż֣eѥfmx1oJ\rCQLo%HHVFIEQQ l~O cP;]u{{U9T)N/^̺.­liIp!2dIێ [W>P3k$59?x2Klp`Sդ10QUw]PWYk,>ʚz%T_G_z鍤 ƳW'^5J~:Ofl Gxkw.ko:3v7'OvUZId?ԧ9;ĆSyco Ǎd-dBn|ZkQxZ!Bh'RLx04U+㗉M>>pVV=wu]Ի84Oɘ27HQo]tL9[/. aiXiu4)X*QJE׃.Q\mEƼjdK[6H ޟ6%)~F=QT ˟rZSUUL.#'o(=T"wgM% mL0pR+bʸVnO.Qߎh^Q Ey\gDAȿJ/GgQÄ~x=>P)F&{ #lszع&ouA k\:Amei퇡r>`>xmJAƹEh<b+VE,?en7NB<Ñ'|r4&hoc݋cYHVH AV4˺ XGaݒٿF75e⧗ٗhURt@~<谵w*,)Q/ ^?+=MKMJjFrtJ{;[}6ڳyۍc_MDnwդ=f=;<.ENaF\TV)He2M27e8NHuo2.(rFZm?6?b/G2(*]G9bYo?t:O/}.x {KÇWs{|?/O~jj91C0e77 9 9O>On%8$# c#G);CGUD"]*|cu?\4E$'1: Bx~5 7`6p`͓f `a2HNp<'uУU 4sO7)l"FpE & #1!k' G # /r}]'w0a\ Y*AADc,If<2fq'TN~6-cT8-B[Ʉ?}yo ;7H mV T$\'8ߛDb)%89RkCW¨I{=Yn0s|twqu^g㻫/FR&Sj/ +MC=h! >ɅHYkR8 Nw'ׇ})~z)8At; tڝuBϰgZX:Dq@õO4FI*`*8lp*:>]'Og@ǠI}2Sin=|Qt,J*ķǠ EkX47~JSqv!SQu:jhp:M)_9ۋ 5F{8 Z A(u WNS]-ds - kH!DEẹ#Cj{'mDBnA:R4O|M8A 4FQc*}qzm_9/CEw^_ 1 oT׎-Sc1L\1 !Oy~+'gَ \a}:Fq1R9I[%^p["6G1܂l9kC{b.1^EUJQ#W鵓Hʡ+؝y8W$Ҷq9d s2Gq639#0UKJK'lOkR ZFyRp^Թ-sL [ 5a0RoFkF2cEI&lJd_{e ^lۈR0J{ZAmbV_ʠcwW7Y52j-MI$f ݎWdXvrs;v6 O0od0>QUԿty0 }*5kGn~+F,auE1fs_UW:GTDh*|UdDQyLbo f>LbиaIrG KI=OhUaս dr] KʚK&b:F<[+:b@pkXX1$fxVW".V$ꔠŘ7*;B~znYlR$I([޵"KPHMB&LgbH,Q&W'bO[#=)[oi|A8ÉFjd(?ca+9fiYPSJ8OAcсh/;[Vѫr8ov*VhMyıǐ wF*}ٿ V b3M%iS:=:gx+#=B0f|#Y[BL$y oYSg`Ig>wFr"p1% X"UPh?9? GPh*Q{6Fby8_j_~zj1Z_'R; 1_=Y z`@-֕`1B~*T1Vk"*H+ى •`Bngjhۯ!hޔ(DF'ċNL0Vz+Kt9ocAH ([2Y꾣XoTP򁃏sHsv^*Y{hJf#j%9€Kd0-&\=\G4 7AcK*Z3]-u LVăގW6\J|=z5<-6i/rw 3'4Z`AKd9e]X@ "?2=:6bH;I,)I{sQAD..Q63*)3C <6mFu=63k6G#T5PEw/g ݍBU>,xmp㕘 8t,T5a+^1.S0P,&kv:ԼG:a~z9]Ђ4oŪ!pRWl#Q 414 !enaK*j?y?}扯|C_yի)7<7g:{8FMQCP <<]&x+g%W}W>'r"29|V'$ZN=ϯWt݇OԊ>2Q ,z7sPǃmZj)V}F7T흃 IѩJ^&ؑ@11l2e:5%QP2#UnesQxbi+Ew1LnԬ86fj=,٫MH ~0-N"sr!)kU2+)B'Ul|z;?<GOųW_k ҉Ր LԱeP~ʗ-RV.ߺdG&kU۴bta忱mPMp޴Z]HfR {IOXgB]XK8sToB=6cwrumʤ]3۫+j7igY>(+Up"&\*!H%L-83(, 5Secb9^))Tܷ- {VTs&j*!^a.Tt":qZ[R4gU0 N_'!RX_ߕ0Y~[^@+TJ& N&\5J #XLT* (nXY?kZ T7j3WٶV XG {ś ..C&ZQpzj<6WgvNDPM8v x\{S;;| Y8 %1~[+lKzw*G[“ I>¥ #Uy51""1eo]O%Sq*}1ew/z$\4)M[ }SICʼndb̩doBĥq"8xBhm IBBɁ4$Hd1:#r"&i@z8.iQUMZqtd:S˄qhXa7#X&B*!L$bƕ@ Cc_#<Ҳ}1 8A@ƌ1AY9<D~3:'Vvˌ(a]FWڍ~TkVs ANNc0 >^?lGjF^w"dZz#O.=P?Ơ]2`[Ѝ 7O zyiHP9!HʀTFI2{=ϷQ%t;0BJ퍍 Rz [uj(F9^ 6Ȳ3#,t.,k/Ի"<4zXCcp< ~ZukT2eL\!H] v-7 R'eO4.mקl~Wɢ ;#c7!%ưaq$oU}'q,iNO# h/ Ւ)};&&^SIs%:u":[52aHgj ek )+%-IeD=e}SIc`+d{DТWy{Ss=XXk #ưnyfړRsOX_T1`Klun `>i(н]NQ6XUڿ1#6|Fpg1'lf4gQ$('!%*K]d(qpHek興(XlXB Q xw|tTZ.Z;{e}eb~ߏ)_!eq3\"{v㇊ۛd0h$IXtJ+li*K#MQQQ򧘣G<5,_ Q>QE /}ӟѷ6I+5cſ/UyrLY&E+ {r{|-F(V`Y"۫ B{WyֵQ1ߩһR3?h΅ A8~1qS)YF5`[\Ö@aCp/'@N$Nf-Moje&Q9FɤXWe㛧~d4^Gcґ6i۹o˴7~C3!m?z =8 3*%Oaf{^&i5ɏQ,',Ff X`ȝ-rQ(ܧ`"hT>_.&~|A{N1A5 Ft.|AҎP]<_SAtj! '-$;WXHBzf! ݻj߂k[HByj*;PBY0('PJ,$Ȭ}"f-;(2k, ̚2wQVYp.̪$vqXXi$Nuزکna=[G1^>w6Pά[>-u ~dz FQFΆ߽F԰H_?mZHB-~jgE晍N,X3 ݻ3C wgx:DFO{Ɩs!s xjZ侇(6vBԴ@!BʾM5̦ƏPd~}Pd~YHB"rxG(.,ΩuaMF + ENT[1ܩjY u: - Ovm$qPm̎_E`ۂ mFFmDo6w5RƝ{].+Qv,N .j -]-= ==0qgWM&:;س89=Po EPφE񛠞MƿڀaU"s JG09n/6|5d^8+Mh$oW_-_ve _0S_){WPGֻΰ3j+= Meo巽/ǿNXĮ+ qׇן3~:X0; ǩzߦrԠ[&*)u^gN;ڌN>8;2 PZf1T14S]fBAg8'4QGMy1 `Rrz, ),+SU-fjԧ!U높<ҥhP?|OfLc!LF嚟&k+#~U1U[;6 5s[d;>Kz]H#ɉR6 & -70?90뉭p,<-L bD=S7cIO^mN L&z"1i]"D(\'8 @c131_Qo}NH0kD<2s[{MD5Yqp~Ki"z5,T6$O)ʼn0^v36Zja;3OFQ ?JMI i޸XOve›q=xŦ,u(7K49`Wt1!u?a,Z.cx!erBJ{L@BލHwʽ.9l]mX* hbCANbH|T->6ޣ`(T%a>R[?5ـKZmp)]m9 >(zŦ5&EBR?@JOh̳IjHhf ܬNd;4䆫:F sN4`^ƲgF3H y.C6?M_>p]ћ z\Vf"f3` gA<[>f@[͊Y>P g(5ՙ} 9iFKMud'LU e</gR>3 W~Ce4u(tF9-m(Դp4[㆐Ъ 괔^ O-]l45@-nԹHpqh5BִU_<.+q=_4ݘFrw)9%Sg: T?14?@(9%1h4Z H8_f2'j'#k> ,X E ][":,88 I=:_;D1 c`m"!c @EЅI[2(ЗPo)hc7"JBP|KdV;W,Lӄ[)JO pC,؆.^:kPB)2KL{X <2c>#i?nZ֋rZ~#Zڳ]I8&SXOeE,bBʱF3N4m})($^tڦ~mXm6%ɰTv܂+Qf[a_rGy4$qĶ%h[a30T-XyBOY PHfw8?1͜4'@n>Ite8n5Vjvo2O.b4h຾ :-ЫF1Μ\˔Ձ  6Gtwk5ێnfMU G͹{8;&C淚ulTfeaz./5U$ P\+f{O2L_Y$Kuh&Ef*qԃYpA UQWbS,^Gj{XsE+QΞU"mYSXvU<;?A.n߆(pQ{rU$RxjjWdtMPn@\'~؅bQ|(O˅M o~qs[R$hsHʲ/Go-I6Q@QdPn6~op|VѭxX'Wծ}ˤoܓywF\Rr[} rԫ T4D6 '6SǗmò_vqb^ @FjxpDy){yN~rbID.ʼd]̼l̤ĢJ% C#..g7wۜ$׫xLl%L"73ΐAUiRB蚜Ȕqq&MmVjr);* gV~r s omnf0 6bNdd Ȫi c@8>N>Ύ!A!YA&"߄'Z@)U:ufThd`_glĥ@ܲD'r2L.3y9[?`AMxHϩ:y gd6.f\̾!) -adGnwx2$70*£cs"4y QIW)5=3O! 5931G43'E!$??+?4VIE3$ $CS+ (9769R#AKjRiz "-;[@(&828(F׼a,VOvSG_>,=]:9?//5D/_!8(9U-3'u>y9$q(a)I̛,͟57 %@qIr$ 22&M^Bx;Ei/.C}_ɹ\RŸE7caC*xۢGqdW;g  ;xJ@Ev`uB1q3M2v 3.B].sSry4c/)}3#d%2v:7|m4)UU:FP2 Fkz՝DoNu!Ěm &I|B~%d1_X(Y,0 b8?g^[jp asPx2hyN~rbI^LNf$# xXa9nofD.{ڹ[aI29`2nVv]Wv=EC~.WzUY(QM#KzLw㹰2&7tJV{I֨*)=v)Suн2y!F$'"?]c+e)3ziĚqa$FmuAHXܨyTN";Zjei, +I4kKzᾼKJ#)扊ƧV)Bw?,Qb3I"2m iTY%L`Zd'E+ahurB$ n 7$CHQR`FՏVm4o̭Ml؟ލƯ't fF,ׂ2}:tAx 'n=+ZUD=TQC UpMa%n^t'Tz}aڵ4!'1_>x=i F:M%H밚?-eKPoB |>0Unsӂ]@)9O%X~J&mn3׫ƅkIu.cQcxҷo *[r*;Ŋ,i ߠJd+P/nm.m7K <ռ{f>ʑ'a]rI($G/^&hEW_@+Gm}pk52twG=XA8_-ȤAבj8@>;gBQs#7Ǔ =g'd A\E;U4yap 1irv)F>ΫVM nWבگ{?d$6xAO0Sdv(P@jI̠,5.'G+X6a.Fwi~};e6fڒ 3ULf8Ϲ邁!8;82̤xYk$q6B1q aIt֛lsҴ8pQZrVRu؇4H!J\7N"+.9מF.FD]E+Nx*}ŦYJ+yx}d;ѹҹ{i}vYQFP6脺ӊjetV v7?a7aK*G~5+NTMq'T rxY[o"7~&"n4j®` HC97{d{HC­v} gsr)SPIQs*Ųʀq͹e"r 1CL^*+s5'C{9{2$Dg#pםfRn{'Ӄ#Q?JZmO~C{KNHPd1ñ W[(%R~v%%o3餴4q3K_a bd #s)ޥeGP! &cN@12 5oІp>,M}w dxS zp1굽SNn A{X\WD=_k2lFkRE(hfeBUl2%)A#fMާYYn-x¤:q=P\#d#جoId_,t[Ѥsm.n"t2V^:TS\l L<@d>z oB"ˍ"VɐFv%}vӮjn%;*HʏYWܾk crۂZ]ÁͺFRQY/0k5=B'L[O_F&b`+n;[tc'iգ% ^>X\>fݵyVZR $8`l)YA߄W.TPERvߎڱSD_]ʠH2-y)Wxj 2Jo0^+[VPp٭.6e)UȊ"XC*;5cUU++b-IF)*6v?!3@͡QR>=\ʀ ?ǔpI}H(j6RJ~ΙY8|mh9Py^%Kۧ=H}?r"񞎰KhR[&ظ"wmLx;FvZЦxXSbzgBl.뇑1CgUc9=YrΥ_҇Yi&> 2+x340075UOvIL+KgPv݊-fLKRYqEcA^rA#E+pܷUwN2aMrD'L?L_uv/(~.<3lɇ0g#Í2l*33nXm6G{542`0$yʋcq 49/7!j8`MvF,:&v[jr2SKJ R+V-yL<žS ŭ[px><| e V%{}ͻ,̫\e%y% 51|[Ue_,l5(3e!;lI.x(a:}~ϸk{->%$bJWc}LD@+d]rׇVz7tdDO#vx sb``p  $pne``f qeabiijqqr9r舊ʒEKRR^>gNYjMNVΛWodd̚s[={Tȱ#*j*K-IIKy쉈ȔiSBB\bbfeۖ/߾9wFGOgͺ59y9o޽3oNL\̝{wF(xhdF !V{d gGd1*3z|l.!N .EE3ZM׋M=} [;7{{?ӄ%˖3-^g#tg(nӻeBRb~n:u/WM0Ȳ?=EՄhѣ3cdD]ܵD[bLZ ybytL ok|p~.' $+RАʰ CwfR]yːV9ɦy:=ߓ7Of\;\$CgˈoR'ӿ{Xj{WtJ:[;n$ޛ6E NV<8Xk__K l\6*'}%`rDS["J$Vn@g\*'vwK~\x.oړu b|vO:3Jf[/wjInn?)Ǚۮ6c1%>9X@#E$0[ǞϷgU*aüqa| 祮n Mk2L]UPuj^~M[bzh)eFgKͶ.`Y%YKU'9u=M^;0ԂӎEo>Ơtrݵgz}RxɌ%Ӿ̯cø`w6I~ӠeSB xV]s8}^t1ċIv%PJRϤ@h6da avJ$~G+]ԡ+ҭdXۭeo͋K"# DREZZXpmBa0'3#wo(OUz6φ7@Ut8u3ؒS+Fj'ir=h݃h_]q:|WSIct 횈zmED&T Ru'eF w$fYѕ-]^19?.k7[޽@kDo1gVšTp]k v]VIqh煩61K(ݬYm[`Ngg5XҢ.ka(gkkDsB=n.DiSԸ-NOWvM{77 ؜l^/Ln%=&TG܃-#hQ)XRQbӻR67H g-MY3Ӓ \lYbݎ Vo ajg>)5.(rQVtxeɀmm"H4Zfxއ}]es}.iAreLe{2J-x\m)|.sb^y;Ixe s0:rwb;M{]ǝrkKw</fq܋/_ak~ō_8g\Hs!xUQN0 R.N>BRR/E="7&m%҂P|>ð҂/^gߧZ@2ǥ Pm}Uj&jRLyΥӵYb)nKNXk mWGswT5vK& M2xF]%ǜ` :Sk<&Cϒs)90`xkɁ aks5)䫾|#蜣)#&"HwQuE]i0\݉ѯGcoRZ$T#߷u5̪ZuEw8^x;wFǟy;Ob/e&gagx;ǓQJJ@~URK{w$Z* XfV;c7Ycx<~Y0ǍV~x0~ 9tcfN52p@wxdˈ3zлfCc=u)#l[w=HH.@L,w?d^+.kܸ9m,D3ؿf4fo|w"^*w ̰Gf.쐕wBt8<9rpйtWx6G##6K37:Iwp?'qgl l+=>8*aNold!6,db܁csX~ݻPT2n$`XZ L m%d 6hu햹Ǘ`}?ڡ@Xq Lw,AG(NXlXnϱѻv_p8Y5_G0okw?f{u:mOkVݍ ZS,iu;Ic{1lLz@=blk@_m'l{7oJgG=;Aþ}SBk9-5@3ۋܞ:Phy|  S@gMtт`'.\>k:·0ذ`nf՟["j`܃M1=Jz͓jպl/^{ ,)_e?̽)Xљ0י1ȪH0,@7W<b8cX÷>mNiCovM-_s$8u+* ;Q)Zxڂ۸=^ntfbs ~9 ?ar-Gߊ]!X|g-0kqx6$鳿g,`3u.)o-`9M1]M(F0u +;_: yl[. 8BeL1O5Ux瀳l~2n 9isrQ$L|#WGMcZ&BDaGԝ1c5!H8^*2;.N1tP10#9702>X6R ͅ.uXAddHAkvs{ݻ/ QĦd/r'Kd?ޚ&wh2 VkN3Pab![!סtGl+!HRV#-G5d^AoN΁f`(l̼  Uj&f^R`4l{Vƨ7m|Oz=L;&^^ڱ%"Fցoe` :U\2T4{+A2̝9D (mr*m~<Obo(ILlD$`Hz񉔶R0P2jc|U(_V@>1Q4Ww٭i!/PKwJfVPVz)2>Id@J.UCj0η+7>}T+%禖v[+-z|+ ;`J5LJ:y(x ?uNhoFJ+OI,!7J?-z|I%Y"࢕LeI ҽ}:<.L $T<aT؍yh?1kwC0{^SѪ+ s70J{C,Àgt;M3v"4q0@F#"~x)H"{SOK A ͎ } 8 % \' D46{As@(4 b&1̳zR#qY}kBpG߷bd>T Ht{>G7DtyAB9=OhM"i*Q"e%j(m(ٿ~YEΧm W&ҕr T "Q} .I :5ZoVkRn*&VbNCÈmIzxi_§f`Ko @bJM@Mj"lӨr[SpvB j-k=z}N_[{t/c%M4 /w|xNɎG~~螮e|v6LҞpfnAG"Z=6}ѷ(09gxN͏,!xrϧs/!6=F8W$){($go6 yz:Q4[c^GTm/HQ5,;꘯d{fNj4`ւlt &(pЄZEF1ESfq<Ӊ,2{p(,u<V*zIY\{#란t$ixz"%=u7+q{ '$Jc1cfc װ. @pC|#%'qT$07-p||Il%eG_YCSrRNR4F;L BZb& ?iY5`aD/(l2K_٫T*?~@9EWi^TՄf 506+BI^T ѬbIa&|esX(w6XY#:5r=q% v(CTh`2^=jKҎ;ZlˏOTwU@_&jN]6 1RtBC^(%R>D}*noF,tiɗ |P?b!gI2əi!8f=s s^4TZD'i{_2 _XN[/J%ghZ^ASM̔KJy;`2'-epC g_CkL&|Lu%5?dV,bLA{Ԭwsi3fg$Tp]cdg" Л̀, V:h%hOQ.TYU,>杹0ר0E!E 8Dry"R+܏(uϐZ╽:4 /VPY?`4nMɸ?&6pMOaZl(^5KXP*/jl!Dx"0) |[K @ fm߻336h_8`F 1=wf(oҚYFd E ckBh&\G£*BeiD2eT3qJ*իMߚ2,0r|d=$FEkei?7~YEf{u>GqC҃#'1So08qn",r7Ņ#9>=H 40𓁙i^~z$ͪbҭn<~aDΚTby'sgAq{{2pT:%^t|+YeXhE9l$J,{Hrr1,+h$'TdX^pCn KYҀ\:?i#"&#uʹP D_*9T#K.HfגM-AӧGwn\¾Gi %̓> 䳗-<&Ө UBa=,ڛ2Fe"'- ]10𕌜)8V2I 4(JVVB!'?uS~ZNQbl;ßq-Ell<|>b8bh&Bn*G)(O}X],QO(XC׭쵸eMD^- NR4ѝ8\ɄF#e^gڙҢJFi%hŤ\vm~J89wZY'" FC*= ya,}2&)-ށܫpUp)GBChz D8./&A?(Gp=ȠS}d&kCf׽fM&]ok5J @Hjpv_d3ȁi]DEyZƅKb׺,fÙER=sTΛKl})hQE47CIf4=꿦 ?Yɒ$5l/ɋ D}ռ4 p0ʱN}N٪+ MK1(yy#o@aFO-DLsPVܟElhP{@I,)9{Dx]n1i?y eyOv$3^ 1;1]JrFd٤(4g572l QL4g;g0pӻ2D%t,Qɽz6%kq%I=s_ MU>K֫͢pfg|#JKK:X8KyS%J02>xxqBƆGlz%9SՂTSh/-_VI0n^docyxTm6ί ۪J, {H U2@:vΞhmۋ Ǐ?^݀6LMA@Oid(H  ̡%2lF t'^Gf֢&أ[28)Ф'+1As؂޿G-ޗLMn\SPkQAA,s'ÝEgv }8 B""+BG=c!1ܝ<2&̮<͞ 5Z`mC|#<~kXU`lYPZCx[QvXOnzLX ˰seRܱILK`>oLu<e|?0e\f^T233e G'2xL'$V+ϗ0`L|5,q#$!_sbS“偵 &P3:|>1`IT pɉzVzR7]Ĕ. +Ϯ̃"}x;j`쒚 /-.ҏ04 2K)MI )LV`8K_ ImNfL*4V)ON,Irqrwqt7RM7Pusqu u  -.),˨)VMJKLr rv FƱ@/ ̛<%ɝL:nLP'xmQn@=_XmIB EX[YѴ2oޛeہsV);*t#jQ'MɱO4xeʏ %fI2/&$y;֓z?rqbx7leB_ GxωWirvk0aJ=j<Ʋ$H*jPå/(+7EǡZM뺇ƫew[j%sOj<'~bz q~x $Ot%kKCcn Ya~=jLy00=xmSMo0 W{߭@/=+k%QNנGi ydKrF=q2b8qh him"QlYkPoZbz^B-Df߅ӟ&'ݔȶ*pf!(/ww)QtS#9 Zl6[ɓD{+>P[-8Mg3 o %%ʄ4.#Jb}*TgKtQݗΚG$eBum2!mct~zGoWY<}^5*} |]sš3l8s]UwVn|6+Z\v_U:)'VWW_)#ƱJxR_o0 &$JHմ2&9oϥe4Nm9w}יxw?x61z'nL ,E>G[vn}0- ̱z"ЙXPj2Q+X쭲 ) % 0H19f5f\&\Z r"dNj20t3&%6c+&d=>HvbpZ: 5 7h{Q~5$"1<,%ql BC;OHHHmpfdvqQJ9g*7o@{;NͿmո=o<.rof8G>ggjvdHr/u轇.aX|`x4G4NZ sԖBڃI,78;9xݙkoH+NV!$hY`r]!Yffi˗@% D™{Ι?q^BOrn.B%<.`͚2[*X1ȵd0\;kuw: YprAi¥l+OtZ4oހ6p֝`ָ32Ai^m߿ NG+PNj'JLФDRc&ʋn? Kp u(Ry9i\B;K[Lϰ}J/~: iۖC!B'[TP]@e%(jY/2b9໌-j&Yeő92Ν|(j"9 "*cm,hݲ+Jٜ#|Em%9a>,PDC+ךj_4rsjl.1lɝay4%\׎՘1A N$(vuOK`շG&*۰Jkڜ&nz$6+/0]h6_%[e0ٿljؘ=>,Bcn@!C*Ruٌr9eQa,ĝvґ3 Z,_Җ%.`H!} WgP팡:C :S.--CDHYZYlc۵;8'i^}Wn{iS;~H[q62`8j@DCu*I}vc\qqsƲYJã#"hOŶ"z QXƇ-%x=j:ūk^Bu?ie*1V|WyIIyIEO i?˼0ڧ' ǍYB];N`AISmXXW-Su2~ǖlc byBbp3"+vl+&DޟYA [Vd Ɔ/8MXnڗ:I$5[?`vEPq[d螞ǍQk fL/&V{Rwo#,wiHn:,H&fPȋE U8b2Q_®.4j5(k2  =|)=f^O7g6 6`hg;{~*&2 'xT<م` e'G>6jŴSX[)#3"1!0}zp,M(}*eޕ0_?di -[Cs[D D hh<*fYy$#?"ژ~X;Аj eE^/CpNǓ !C_!~[XLFxLp/տR1q[o4-Ubgݡ{ GĒ }uTI&}G=xk3}c῀ULyExfJzjId6AMFld&'' IũF)y%-&JjŸ&()$dX)a3?f&Fi[+d|x<44-<)PBeN .\Release 3 3 ,MJx)44 JL  )__U+9xyEܤb%[% x+N-)-OI,IOvIwqut//.+. x+N-)-OI,IOvIwqut/(J+. x+N-)-OI,IOvIwqut/(J- $x31d|?32))/Ÿ<< Gx31W'OG?~V m?^z. x340075UH+)aXʷ쬰=CfdLj`QR_\W\°~]˲}rSl|$n1q:eTg٩3~9qNKD()exv3F`|KJ};r$~B:7{;wx%PAn1 +jTT8T+71KJ6,о{4cwdq^^SvZ538)ą)p]r\mQb2+9$q'X̡8-G6}u<#z3 ϣy^uQ0 ϣ9ŘcVOg,"<dk5@~!P|X.u:b=yۆ&qlL)KOəAHzy68'pni]rsY,xVmoGίPݹg^RD nPpZw{݃3{q`FUKY<;3 @(&J|f8;<d`D"As>'^*Xpz.i0cR_g7ʤ,oa]+KRhXdX x 砓loa3 B%STJ`2hqpK8xʀ+0KXC?~\r"I#5*/5OӍ^u$HI\%l +Xs?=HdEr.Y֑{+b/ZDHq#9i2l0}?BwxxNl RgP"^E.Ť٢?GOt؟Lj4.tA;hүL8e6Jƀ&"3Q(%[s uccJsE\X3yHTnLbiml hDn\BJ;!( 8T__VK LK.xv'D?2UC: o+q&\bA0w٤ľ2H6_Ke߱Z+1s3,N^4 حUKxt/e#:6 %&~B^Ff}-ÄN5X'hqlQX /ڣYg߱6ށliRh|ASRӯù!eTtf5k,ST)ٽJ4fG6dΈc(m ElI7!t_p3a:5WkΫsۤp#ԶKdi;F_,CWȹ9΁HzԛFa7x<E@J%-9Tlxc v#6^v E~J:;y֬ T~F(a=B)f:p$2"ey}N}k[˶>;Z(ָO,H kTCaBy{>|EjG:!.ҩWe{59ĉ@<8Yş< 7͒z!r4N˦{p}ȔcOK*Vn<=C7Ȓ bZ;W=#o-0m}Ue 3.l68?Lťu㿰;3("G<9ϧ*]/+U|&+l6boy4z'Ds=_k)AmVf=e^\ {gu&MxpDakIQbrDP`^nb&ɛ"mɉLm3yBYW ͟H+痖X)&CLJHU|CG"S|r.8og 5ZEl0glTj9!T{>5l4? #]xyET%[0ccIF0 xkoV8iBUՆT- i=IG(}{fƏ1 ٫{u*5~͙c={,3"p׽V`jF=! EpW#:7_W3¨uz4b5^ڡfFlnK dNCo [' Bωf@^ʋ2ĦaiLfz,<:+Acf9!o)b @PA]x>GQh *mjeQ9E=uaJ 5A;\MտhOn t4)'].EҨ[`h*QqZﺽ5|0 [I}k`x5Ɲ:pG#ƴIdR7̵A(kܼ'j{ cq/ *뱙ss]0x ̣}x\.3׽`vJ*ᩐ^R&tnlp=krc,)eXKiu|"AYЌqhRvMfT@K?0g nłH1^)pL! +E.@TȦ^I \C\5&% Bki%lF$Hlk^QHø- p߰bFh%4S$.ow|qA`f{%?#5ocƠMHGg׃Yv|L E[H UEGDhf _TQ1Gcjڰ_!n;x~oR$ R9fw$\0R OF7%rO?9|}G=K}2<_Zh/LujX͢8`''3%HS+;{ jv@PSb(")2/ ǴH(>O $ .qRn8ᖘ]/$E *KO``XJ9+O`#D)P?@./˔M)"^tt$*5 lk޸#Ž)fܖ"bA S6P'L) 3ݢ57س6E2b_n4niS~"a鏀f|da+-rNaH3R܂z1ĐΘ D)=>9F+1N׽A۸l}2 %1J\Q]ZQ8VA8mE~ִPV]֔\j5sNVu9FUW,/nlerڼ)_1 VÄOqqk>E4gc.e%(# J[iU?_/SMK?9%L ⮲H-֓?!߈h g7JjIU$q{(ER8rF+LYQYu%7 eB(G/8c(]WZ His!3n RTudmYˣKF"5YZ!WR,S8>NMߺNZԯzU]׋)c_S\ڣ-٬~1g$ w_%͉S_]a'ٰE2Bi[~oۭmJ*L؞UɡG"ݒ:Wd(5[ܖAI Vԍ,/_EYƥh l,g# XI-ֻJ[\a*J#8R it$^V?ua^'~g l4‹U4ߊ1O=6H:6[ /z*׽-bd zڮ/G.sK/?!nᔇH:6P&'POR&8k鬅tW#\]PDT1+d9KBl4ibu@9nK3=G&spNӎȁbW@\w%^~-gŮG 67,e",z[F2JFߴsfgh.]z3>=F"=&Hti8u,^6OިŬib]AHHd!\[09BRsQ$;l"Zsjc$b!f!,ŰrJ,3'QNSom6)'w)vK|!.A|bUj^msl6" Q@}CNMQ˥0ބIF@bο ykN5ܓOWW,(^H9%$#Xg$03H<䈝$Ú쓍|z7A&_19y# x]QJ@%Ič.Zj7}! &C;dj:i7Y_MStsϙ{8wqm5QU4N4;.% 7/u/BOe@*ڳ ɻ1,JigF; P1UH;ɷH{ğy<4Q6 Nz8נ%Ca b\MxP'KG~c:kň#pT-j/W#1o/YFr"?&<ݶtH"ݾY ڠG]iAM6fR4zY><$b5?UoxMNj@7}C$"Ap¸uiN=kA)FU ,K n3s-wE 2\[&rv_2=Ո'Öym߱)?|:uR 4YMqBC cGPskdms7}*Aj< \71 M?kqW/'ε+]<9iO x340075UMNMIeq'߮XmrU^_˵=WUKa].וa3,:) P,KaԸIڇGU9ݽ]7E6BMK.(`O9pp7%k}7TFk.X7% LsF".\@01 ֙ ?J:ʬpt'g,hlDʄE!q)T@HxE:#V>?~e 18e[2r g2M dC+)}^:yzMA TYJ(}#ʑo*|tI*9cm"+'^cC_v&&?M!'aX |^pîw|E(g.VfV)d-hL1cD?XXٮqkbN~߃1K`G̃bc7_ϙ-\ofGi6_؍e'TG pߞ1'dm-Yn|%y|Qo⢻zug҂CKKU {)9v+mhP-.X}<"..Ii8]A>R?.2VR ׽mEv[j[ zǂVB)xMDmRx340075U(ONapuc贉5:/nZdP~ 66xuRj0}DŽy8}m( k=>(M,ʙ$7 M}l%Xֽ{Αǣbt1,mW7 )9aooQcT +JQ ~n4PԴF2VPjih82-44H[+֚4 yW0'w̨vÐ26㍒1V,7P+Z e!jâôQ%>+/ӦmiД/UFF!ut.ϾtGd]S905PxM זO߅G{#On(1Zt 5ίSev2kd/o7}>o%'? T蘐_R;MJwWdΟnyE^|b͗xC=71VHxºgM!OhxTmk0_q$K0XB][m)cߌ"cQ[J%&;/Z~s upnl&ԨP)rmnVha=]\ 3bcمR=jt38 u88*.gg}+!=;̯+$e&򀖐*&dDp2153v+Q[I,tJXzͭO>~ LOSyvut~&$$"rng/̭jt8hI"ș(14"k-a⁧Ú4rGFȴ.pH){(nsT*iIrzzTOY%` MO^#&fvmt.1U(Gú~yn:վ$t/>yM{A[0[m \Cޙ9up5'iu9h\"ĸAN5>5tYV~Ԇ$n퍞WaKS]2f̲d;Չ^-7`kVTd~o 1 iPW3PE V@&7*H=RW2{U2q[atF%1-5 )ae6\v3(^azwӠCyܗ%2z &bHk, _[Jx340031QMNMIe%Wwwѻ~hޓ2DUF؝vz7D}*]U P.>pvs3~"713O/HŴߢC7ZQ IMJjZ^C',oe0O`CPseXێQX1W1nf/[e: di&ă[ Ӳl|tʙl|sUP~=VG2 T9Hayp*l,oG#n%+ũ] <t\]>UƱ| =ˡD-& nn:'elh?vgնxMN0 y wn+8MmԷǩ7EnW;xɊh$hT7$,ٞQ6MB/=M2 +T^iL4>C`! ӊ%kܐ.ڥ~ɹ,P2=#P]T-O`bfxߌs} ÿt>Ihzt_ξlJY(dΩݚhAgm x}W8˧P uHhofKB}=9&1)oɶرg}Z04fFь\Y__cl>v]2_tlvvz/L2(˟cQ{`!}wzWKlZ}]ެ6כ+˱'9]ozgN^z|2ݸ360YCB8j*V :޵zf;iZg);9;=967Z1_(V`c?o0>`7ym,p3*9v+& ȵ.pގ`RWl*cį"B`<Z01m`KcTǗffcZb_:XW|wlv*g዗D~p3\^1RԬzA>>bŭ9J3q(U'?`g֯a POXY, dAxX"|1DZ1$ysp|ޕaܹ/_ڢFg9eϹJ>틅gvj`OBz>+_`/Uc^Yd˅9h]s:PNA\NDY ]` Ƞ cBH/uPEpod{]*YS׷׻yD Z6[Nݰ׀a;`%/@KQiDhGl'HCYY2J{ЅH#KgMjpPmbHE"!Ap3ǷKAk !lE*jD2gsfN;f?:>haqӠr={)kϷvr;V{<4EZKs[;!%!Gvo4AQckx3 fYPmJU,(Vy ò1''A(=0O~0'% juxiY5*VY'P%pS&|3 B<f:M1 &Z X b622g6LhJu> f#Sؐ%d`0@[1DXaM"֗% 8,wU\ 1: :)Yql0| 2`;r&롲"٧) TN4cQn,Ӈ9 P4e"b륉9P,r@D`v)> ;D)syt|?&U#S% G>uh\;Zi"fXgSxJ,Ѵׅ0a&T4{PM/u(#|!p;g63>!.9p-,#%@>YDKϝraBk}904 !V+4tx$;lklo1Sc:o`>r 0m@&M靔@qkfL С,U1padyaע h\2u/~ȈiV$Eob^,n<:q ǥXqlLJ BS[w\| %vreEo1{l7^@ $bԓedK۟*[ws.ƹp nMɽF~w ߷q)\QGPh7pcl9W^&GjQWwh0&X(FE۽*V {z`.Ƹ%(ѩJr9XCshMq=B'EEz[OTha( \o>ZCKZX-)Cv%HR/g*@,';S.e.Cy]RE hFD'yKUM+=7V'E3|ꜜ6]9LC F*Yѳ-kZUhC;axJf%2,7 #o 8O-gȜ*$0š;C_:Ft:#VGc/vMLb?mWƅ;٧ܩz4;7Zq'ψ|nB/& ƫj:o%QDJQ%]U̩]t8!BoLGm;6j{;]?xdi)<AdlzeKNULa*2.D3"n\ *mRoPS]%B*EDʼnf[TYVKd%PZ+|#2DLyÍ j%Swk! H{s$dXgܝ(0Br1RN-,Fu3pmuR"@RJEzh(ܴGPLo(DgHl}N ]?{JA#i)1$}0O=Ln6} OA.^ %:'W+NduJ-y^itKV4ԒZӴȊ}PȪ1pkAJ ~8TjhPРT URC69V`ڣߔm)X4/J 1?U5Fh_1G N?C\d쨦xtZJ »[#xA' kDR{Tjh{NϕyHBmXA3uGJ Zu~謜;J Zu1: "Q/4$J_hh_@DyOuJ )Nǂ)RcB1{ 'Ґbe3Kt膢tC1NԱ1?*1?*cWW*kP,ؾϱ6v) C K8O);%R1ϝg53c%b$ BĨ'D$tf.&Y?gw wxys/W!A>S$ZVǦ5(M5h T}?j4{ l<^6,COO6N-D3soIQ|{CDk;eg@(GD|msY\Cƃ>U?umY_dڤB[ mQ =Bۡ $!G$E(?᱿Q0@|N,"pC}&GnMrMpw>2R^ݨm<\V,y,32)s yzz|FD:n X7{<|T0 m®8:LtM Zr`.^vfn͓FiJoUfu)aʦ6QthL]JbbѾ);~.lHA89cPJ;F4W#O(WV0;$vlA(RZ` 9%#SID+ ce;g uDsgSeUH mQSVk@9*)Ea͒fg!K|e< A(ژ٥s %5=fX}%Bn0MFp("IF(W!bCyam7AY5vhcdh,X:1 y2ɑ^VEvIM.D-|ooWyRХp4pKKlFo0)Y!&S \U F <ܸ ,P<E'2[Z!ue=N Gj Bp* !.6 88?e?MET³GZLQ PFq|q)A|S|b*}aCӕX녀W~aOɇEAqy tfxJ΀ @6BLW̏8KӌOzg>: +WYo-CQjB0y6>xa ~qF(#q)n<P̱d㮏zu#d%Y)`Q*?(}YPZ"hi; ?vo*)[5C8 oYyv.L-Fim&sy( 3JBIǁ~ز!d(.ǭ(dn}CϝŘf#oN298||c61y1y?5Z1Ə$bi4unf+L~E#zɯ\ʯ8)} &;$פϋNI(0#_J!,XgF?nW7)X@ g<+Ygdo{i0 -V|$X' o=]7wFO]q8@pFOm>1Xno K:ϾEȝXS<Ŧܹ#6NeU[ $U}ۦFDVPe"׋|t^BOX Le耶$nP{6E;&<}M'xp|>2ppөO,c #kÌۮ ֥}nM\?:H g6S ME9GFq=,pS 1݆tthAl]]dIH_m`Dhj/aJEI/wvu(F}Eֻz勗2շ_~]{zܷZwRԟ6d\KU~XC5(R C15]j:9P=/^qݭxXwj.:@R^6 8U JhrkM|hQ,{"l'1S #Lk:tݫhjsFb%.Cq3aX&\mX;vۊA{s8WdjYh5/g/!zNç۲?̖zoli:VE%P@i5ho SvZ.ԫF)\ dn0ϙXl1Eț[,0Uho ,)Y/ uk S{[YVŨE@O~_Ws]CRERYMfM§fwd#kJWq8AzV[a ]OH c'|n sF?  n$ҁaJ*ti%i,eƛiϔl{|dL}uxb72 Lcql)"ƶ/}C,$ }Y#M2,:3=t5x=b'hog9GkOwï"O"< 1%cKiPS00{#NY&<%m%6wg/"{L~Gi"4^p=FhdYn(neU-Te%(4oP Z55c&11N) D]9AIŌ0D]R[}/GBlQ:"k;7:lߟ69:%nsf\ q.!J)zdc-j7_O~)#tGH;2qI^w4Y9OW-iםr񝫡 f1\Vʑ^)j5w,zZݛXCۤ A/CnZ툙`d:,lddn.~Lp+F|3,6iF<y%z_l?e$\*~zKcAxSeYbɀ4/bȏe@i7%wKRYRW[*jڻ*!,] UL]`\W{!H|L6>$'KJlW82YLw< 5A\}X:HzÂ8ٳup[zV3}y99(}XI~"GM·;nȬ&;ESX:]l28-2%T,wU/w=UC\]%3-bBQJCبcxo \ќ8+t_t-nJ³?V+ЉZnރfR֏$,,nV.7m1wnJhJ0n(ҀFyFɌFyYzss;o"t%QƏ~&ČD;}u_q6Ǡ=F&~N 8[Rq&::ncu8nYSq-ǝ]yW$?&3բ ?~De#~V&lzyهywyhᡏYzs7x/?&{CY>ZhI*!tlRA\iIq{bz2aOH!J[!v[~ds`*&/~2;>GߘÝ/'f"[%yb*FpXJ)J}:˘YXEבŭKZ_~U3JǕI?uL< ( n% *~OwHDIOB2l{ &[;qg Pl\KDjY9ǃk9~&CC i%?\6A0 UttaNv6mZu%$Z]]^iV-/O1Ykm}wm(Ewqsc׳ӇϹq~/K`e]jDǵz*–~з(tkU?u][-:cPηyJ +b'Yv~Ħ°Y1ORFSŐI̱%zv@\50˺4,Y2xe*s\}ez/S' )ǖfG*6O[{ L/MţƇAfZd'W0Jݟ"QxVL&F?K%O69rc UcVst/\rzjv**$k>qSHúG Ě@E0R=qe]P`łc#P'a=RQE|KD?vݩYJasvZmUBhPp!㣶6|hjyHIzVqeM5iq|ܷom-),'U˩d itŗ"6kBTYE x}AK0ћ9{A/mots+tQ״ tIIΝv$n޼ئ+ALpힽ wypRm4$p;fFHȞ:ͦFp4ϲEӘ` nx31ON2凖6  x31|͛9{.˝f "x340031QJ,KdS|rG/1ΊzВk x;:uVɯH-exŸqBHWCuf2z?Em[ęϯ Qx340031QMӫax~xڥM~3NLy/ =xqM>}T;.cl@x31\˯;q~) ) Vx317]=&_^P:fH`ۋC x31̤ĒT3~)%"cg\|WW|ᥚi 4DFx340031QOvIJ,Kdƹ#y n&%Hixۓ!@rrfIk%M'Tp+I(QAJB<(?(%31'?]AwI(%;YEJ}rӦ'Hqm~%mdE7?Pp+JMI/-Q(/efi)1kMe3V/Ln?@GrSmo&}:ҒyΉyeŚ\0`lt'Քq 6iZkÔpmБHLBx31"W_8_Th#%x!*IQ]fosb>x31d|ߚBK#U[vȼS3- &)xPUYL.Yev2Vo GZm^v_40000 src\G.%4CdWt #x31\fEm\ sxk GϦ x31^F^7U x31|{K.+Zx340031QJ,Kdy֟.5{jUgmLtxc:(^N~rJjnƣ'H;xHÆzw]:aܑ!ޖx340031QMӫaRmӊ?^2ܢ zxiOf^jbD]g&̌@jb*ܨ"ƥv\6!%a ʬF ĂԼ%Bb^JQ~fU PCqIQf^~FjNNX>H}>%v\Y#)xqkHbRND=?[%}Obe~iĉB v\\6Ȣv_x31\ιߔ}=n^w(r>t j dx31{WL>…] ħx31̤ĒTӯGKn};E5fC|MZ ax!¦rMJwî $Unz ~ ^x1!ob~E&{1OǨ=[s{FbL'3YO,/%:y=l1T&+0kLfW,y z&Z͌5["KJ'?2=C\8(<3$C*Ԝ,#"#a HL(E0AeDnKIb6x31"ߧ3xPW-:wY݁^7 V>x31gwOO寲gT=p^xzz@;õ_^\`sMmۍaJ\]Sv4E OnxkiMVh@ed UZlמ\T S9ɉ%@uK"e͚dJZV9` 2Vf?ͼkFT3l|"p<==ՖS:8 ӳ9܅gv9g$Y]qNÍ׼g{QYҭT *˒  /<9J A]aY QTϰv҆ey1sx0˪zԁ%Eɠp1xh0cy~^E (H"y&ޞQ*|ɭYo\3[+rng~10<'1hWCJd-gv <ϕ[StouV.A* 2KAiI?:zkҭI>x31\p^ҵ%wWJ!n x31SՉqP44X~ {x31̤ĒT6;zj{L&E) F ޶ oy#º;!S,:x340031QOvIJ,Kd Ȼ|T)%>[M nOx^zf1.b8x31"D\~wKVx{}7~g FX'8/d]v+ |x31d|6\~m،q dx;ti%t}>IS |x31\ )4~:o|[3f x31nmʘ-iuv8 t x31̤ĒT4 x#a{%&E) F ޶ oy#º;!S,5.x[Mhc E}Uֆo)ּyx!/onmX\wZΒix31"b{o)<(;Csx!*dz7az V_ޕ>dx31d|y[Et?pZakϰ~v x;ti%HNc[]RO x31\3p7zhȬx 6x31ͫĊʬ5Y/9- x31̤ĒT :ZBx7}ldQPoİ~m 2&G;/2]Lx8qBɏۻQ׼qPLߠ]5Ox340031QM,/K-IJ,KdXjS7퇎Rk•eC˸g[[V9d,t"tx31"f|1aaEf8 PC7tHNTZhxX5!pb&yx31"V.œ # z[x!B :GHӍ$Jx v%u63_S)x31d|7SWwNqzGkNx31W'OG?SaբV^el*F, Gx340075UH+)a`+{RJ#{4()/.+.aXeپ_6d82LMQ*Xɳ?8?J%"2T#hs}9?!<nGx{iFF&%@x31"#<_U7Ɇmѝ]~x!G%q%ٰڻ$HBh8p;b*x|!yyWqjhB`x31"UCrݰ1g;# _ ۢ;x31gwO}6j~ƕ3OW140075UpsgkbЋ볶l.\7m17LIgH0VwӢs>Ậw/gV_Դ̜T79MK 6T;c3g+@k8~ftL4o{_Hr2ʰx3:N*\#<=ETiwwXȵv* rutue/?dOL U\;ѲnT|*MQÓq#n3=mZU?p,9(!W YU" 7D^W BQPcfrh-~?ϑeJ$bsOܱ;(:lmܪ}hHyN~rbI*P;gꖵ .9}grb! :RG7nĦao驶<670Uf0X&)l= t69|JgVz')㭈ۍ&%&<`8޻av#y&ޞQ*|ɭYo\3[+rng~10<(5'h[/X`vbm+`r.$XWBh('d7!`X.on 57U7zۜ O3=ڀ" (8 Rff~n!nּ$t@!°u-xw*V̝孋6yN}sx>]=<9ٯShyDV=Xۺ>m&~"K'vpڟtVӦ,+Ca拣/ٿ}gn:l+5ĖļQi7enשյ~ cdq^2s2;Ԥ'6yyvFZ%fv2ǏF%w- 0e Y;77˶JVvbcN~rJjn>CsdwL#Z֍e擧1N6d231Q(IK,ȌO.!뺜=C.A"(bb9Hƶf5׹w>wu/N-*cZmWWןM]+sxv*8A)Q;e SI0>Z!PmOnVi#P]賬z"755 wlanapi.hl5h86pΓM/2t$!aNƋc2zxbnaP(YUIx31d|B'qg-TpڼA Ix[&100644 .classpathlc\>'$#},5 yGH@W1gs/7"mxKÞ eGb~ 6>t &)V%lx340031QOvIJ,Kd{^}Q,dum%3-xmRjQƩɴ)HMK 0qXT0$iL0Nn&;a~ZC ť.= ҅ʀҕ'p~*Ź{o'??qcSJ=j3 { ^s/ا&\lX(׾3e+x$Y$M+z>ۧ'3:R]7 |LB=yI.RJEtRYZ5-7ԖjVmb핅}xX(" -yT}]d %SF3z _n^9Mx$Dzu!%9+GC"%`n+v%i!, hΡq.*/mgrPgxVwr# $ '. 8">|-d9?9'9#1&.*'4540.94};.%:<Jx|*yCVFqn$ %Nyb0~a-1ylO`xg4p&>̓7G?Vdx8":_L\WA#kh D5L ! g!FxxqBVq{f=mal-x[ƹsFx Tx[cFLvy9) J9I9ɉ%zJ\\ʙP ⒔| ;T!rdAfa-$̼bTIYI@s&2!TX R95/%3k2dg&?`lŹud6ɻ7`bfQ\0L.䱞Sd/P1>sij^.ZNmmk(&jM.mLSJZj*$&fÔqNVsAVOe6Ópo~ O蟴4WxOЈɷ,8Uc RKJ@5PYNq*T$Yd@U2,APY (H/D $5E &ש*rrqq^x{c HTVQCxP`WNƣ0y38<f^=qRxľ}F(fn.^.Լ4^.N xio;Dl2-;Or8^ "6Xcl?!!RUW:o̘oHfD,`0 "᫳!b_Bo-ץN'kе 3߮-~wNAoCso3$O`czˉY'Y7~{r#cijH@L};<D<.(u60A)$ڡkΈQ-T ș >WFcqA[!=xEg)]NZxЪ2E;š@;q;RRJ3G,y%\YmG4HD֟li0 "_L$̵5Fb%axiڭjCx>W#HBCCu$KZxY!FchG?_xh{Ь+k>dZȿ=c͇0SaF(=D 3Eq̒zO$aV=`&x) CP\)u^ M\Iy6PșzOc([-!r@M~~zx2ω4js*PjeLdMOm,j80Kkm9&L'cՙ.{zUk`ZmU`&͘ gOkt-QMCEʻC[h YqJ8$>ub2=AB!msȂeCU!' u[JΊRߐo͠7>Ni"ˏS %JC sjX:yqV::zUr_dAb'\\}*5ػ(*X@ӭqBzqĂSG./XG Ҳ~[!aP롖O,:y0Ng|)YNA M,e QQj$.6:o)j N=)C(4Cr8gBWO2U}ҳX#^GNy(PHFT\E4h7o-H)P(ֲߛxpyDđB?yA >hQ,Rꛁv lh0N/!ކ(fA$M&N2vt9?Hgy䉖CgZmt?6].]KK\zhu"+^'mȋLkZ"9cq.%ކhTtJk$yW69O+A~&ST &Cv%ںs9xCJT3*0=fu 3>c\w+|d !¨ To͆fkl\ĎC\}g1:d3~DjQahA }ܢ ƥU {4*7jPU#Agv[_'RU8D?NI?2>ϳ:ŒŽz ZbA5ҥ0XUDO Ueީ&368R>>㊇UPf*-KԎ1AMĝ1VYA]F+>0"LZK",\Vݗ =fg hrO4h8L=V6U fu9B^ec3U`I܈ǡ>oX5>|Qu!$f>kPګ y%)́ǼVF<;u=ObFW- 4/4ۄ *+<(HJvX|#(r^tHԱcarIwtY, WbFoUeBJchtsBѵ`65mרvxYHgtj7(V,haLKoK!SCC~_`$EP<3ˉ8~4  Ie-[씢s/۟F);&A~1Wݦ_*A-,P 5FPx~ʯ-={x31"xkOc*-F^>?!' /x{} Fq? /dxwIOm85LYx|&yyWqn~W͸9AH Jx31"/kL3/|8~vU x{}BȪk[קMODyItƎxf x31"$E=/IDξmڹ eVx!-,cΘP` ex̺ulF S]p.V9.y=# #h x31"N ` \x!*nM08HT>jGx31d|)x(ᴺd~)\h% 3x;ti%C[]ee&NV*o"755 wlanapi.hl5h86pΓMC|ox31"ʩMt3@iG_ГEx{}䨴2}TKZdَq%L x31d|fx2n;t^QV=#px;ti%:O[gEV^!$R =x31\҇vSfuun' ֮x31Ծˍ~yr'Sd̶L ҧx31̤ĒT݆[&KwKdhJG֜&E) F ޶ oy#º;!S5x340031QON,IJ,Kd,ݷ,b(ߡ!$.'?9>3/-޼MZuMxTsӒ*,,J-(̞~/| :v0/]nx9< 46j6+x31"%sI[Ƶ_Xx{} {f-L ?HLL l!xg4p&̅!;x31"_^*nGNqui px!~.;l&ev7 e-x31"Vh};|>D?v,H uFPe~.;l&ev7{`݆g3-*ņZk&ׂ100755 wlan.hb@&FM؍Cq100644 wlanapi_cust.hl{gy%CT~RWCRbx;2vF/f.Դ̼TpG?xs& N69o#ɷ&kOǮ60aSpp|Hdk|_hW5\&( S9#& &_Yj=كMa3dE ;@&L?%:9W`e)L)5YPhr?HKM e_L]f7Tmqٽ0_lɿ&oQ6,CBd2dKI/c&oT4RNKL4rkx31"NCUfbUϻF Kx31"BJl+6RGZ Jx;AYT<'1/ S/!8 Rff~n!nּd_fgix31"&i /lF}?*iexffߠ(7}8)8[edlո Ϣx31d|7 fs[Yw/θ# 4>x3ejzQ`flMaٮy I=C rΨs p֡x31".;v;2iB5_vW*xffߠ("הr:YԦq }B} x31d|O_^?{!sŗj]cw'DFx9aA.XvȾFx31\wG>8zUO0m" vx31G&t-;l扈S{}NT }x31̤ĒT݆[&KwKdhJG֜&E) gEj%;]ɲK`M_fըx340031QOvIJ,Kds˧mv\yal2qx31"K-L 79>{S )xffߠ(YQK&QΑFol x31d|ZvP\V16/Ѳiv Ex;ti%_k1 >: ' x31\Ovoﺙu.VO x31K+|;s.w~Kx31̤ĒTf3`Lꙗjv*5(ONIg8+W+yJ]Vn2 Hxڪx340031QON,IJ,KdqZdf[HXz`km !r3! /ԮUL==-irʢB/ AYsmɱ/ x31"ժ'>y4#_ٰ=xff0QD屭S{šZo:>ڼ>#Jyx;|,yMͷ7G)Px31"[. лfZʅ?vxffP,h%T(&2/XwX?7 ܡx31"kj|;1XUauKχiѠBHxffߠ("[Ʋm&jeRlQ עx31d|CDHU~\pGG Jx;ti%Ț7"o'7rFw` x31\JN/݈;>w޸q x31̗l]>j3 3x31̤ĒTL6yuE)ٮW-`kQpVtVӕ, feaAcx31"=Z~jY-"i5GxffP,h%T(&2/XwX?7 ܡx31"=X <+ߑ Sxffߠ(zQH-ox>4lг x31"-; NSW+x8F`R&k|9q*?W8A)Q;e SI0>M?j]xaigpneKF8xkg^ƍT3l|"p<==ՖS:8J?d\ܰ/*sԃ[iAH38ON)-%߁PJA0xh0cy~^E  nxbNnĮӬ%Eczl!x{!Kz f/y Rx31d|Z~|VgKH-zxQe2M ~;Ht&Wd{K40000 gen )qn]|ϤxW͉4BrwHE $Wx~}B$&g'*%ꕕ(qR3SR3Sj qY(فjm r2K'~,1&1$,r ,ƨcg@i,5Y}kFߌ.ey%y%i9%Ev\ v\\P&0O^$fZM$b0}xls2RKxRƮx31\ M>vSCݭ7 dx31Yvw,,e< .x340031QJ,Kd8thH5 2oҌ[ (x31\u^A&S7{nu3 x31T})2"6 x340031QOvIJ,Kd(xRP}-qYݟcb 9I9ɉ% =;_ #Y oK)wi+ A*1dtx x340031QON,IJ,KdXjT<;}rLKVj6OKˇ(YL(- %(B X y9٠}~}5Mno2!FMSKyW ER.xRS{ %|K:ۻ*۠AxUV۞W}tx:| d%6aZ9y9&<yEJB,$ foF_X#0NwWW.7-}{0E Rd£j'_e =ޤ7 v6NNR3xX 7T?SYGwn3e?*MI D ֈ2fڇEu9M*X]>d$-^Eñnuw>Q p.?!95 *Rɀ/Pt%HUla@U@}*WccN]$K qM˜ձqmQ۫UثeFrjzwzf竴' *JR'7TUi--[X~-m) }E&3[VK OE p¥xXB+82Wᒒ ޣsZv_k^d9DBK)A3AqUj 30V-߰j̊IXΫ+CA3k]ˆ_.2p i&X1 ŵ|rbȕO/$_zռ^OX y"~ЛY0+_E6B,:@ %#n5{ X?PL|ζK Ap ؅\\.cXXi Iy_̵Q͘G))jM2%$ Rdž>0hjA4ӛpcOU,K'ɲeKoB/Zzzܾ5{9V6B-Gma|uZf*eXbGruw wAl u >}Zz4 fZv<>E7 na1tځ1o^C L^nqp\o 'vpTtwjis7,a0V6^!(Xl0hyb?;ȁ&xb<σ;8|p-ۋŢď"~H^n,[_ ⣬Lw ثzC /XzhR/H%z'T@QC z42Tᅥ΋ }uCQ Zb5^U6[R6Y7ZzڮFcP/6*4 Gۓqa@:(\cf#-#p8\JW{x=8V J[V]U4M=b >>?]!w&iKR⏫M>!E%t>o_7m,_h|iULΆSVBs_jÿ}'nF6 ~hzu&}= 壩-k N>n ݉IFHl_mK woax +̫+Ii`Y?lwuz 7-*yGb#d%_Ғ_,-wսvԠd_e]j? @g([,;%-QRD׉[~Zvm"q4y ?g)g 6.T|"bSN/IϱSvKt>6E-ysǹqQ:QÍdfʮ$9 G z0lŕ/VOt8_(HKp& J.x-:F~.҆*h$D*w7Q4A,&{j,YI18\pJaiB4{' xP̴/\ŬbYҋn G};8xͿ ԡŒK gd2N0㉻@AZR?KR P<*4 e~yƊezRet.%:qՒSz.ŕ!e}Bf<#lQS{.- V0k^y?dHHM=gVyʵ[܅_NS#vi7P`vJQz8ܚ[VEtRrHV[T)Dwr=IJ7\pB s?m^,ȟ0TR̗om[k/O{/OJvԀܳCv?vȫy`|! #yl8ya@6.ݛzj: ꐿ}e:>7AhMriui۴C 驻.<5A阠tucvaίf:L1MpŽ.{.MPLws)=Lwe+}t?^f;xb; 5MpVC,(z0lW4:tkk:RFC=:u7Abz=rLDG[::7fz;rhR`87zPsf9>v)ֱC};ڷk4C}8/0}K0Aߴ ~5+ ~j7^C ^6h6luj5 pfj6LP famMlfi6]Zds6piOա^jQ/:ҬxMWzi]]w\meQÕ ֡+6]Y)͜t#ˊm!Ȣ}G~YX,ygߡ*4]]Ȳnt#K\Б%8 п,:;pwlf[նN,pƯk_ovtbClO:bhb!WECzj6~31ۜw&?;rov{jG؜馫76_ZGO-yԶɩE}j!W/gfm}n\Gquɟ,qw~߸X{0怶cfqKU~"oxӯ s <^ EAԻ^O`П'DWE0ZV~@?pQfO(E}Bϓ? QwviL^פQ3LQF25g%±jYXcLWQ%Cb+l WaHd:i'17]ZiҼ@jحLSs;5jȟG( xr'~(~Q84U"_oY@OVߟVcw Ք߀kۈx[0T X'O䐙αل2dQރ0m>*or7n/+L~'o1YYp65'(CAp1+Es8{&;\ l >yd{uo6m>8lX?+p4%> 4iX !ZU'/jqZ-/?wFݿ?T*JV|i׷x1VO7K6lu '{MO(_k4@ԏi{'~W۳4zXG+h`Pca%䃞G -\͹̒4dLA0 Δk+5/`6q2@fAB8 p"(pAU^pF[4)G?w7'Gκ5qyh^5S(M(~AJ*F{i \ b]Ro|E?3aq9 dܠ3@y`aJ`sxs> VjZE>_*8tM oT^`:h62<7$T_pF% ^OR^9-{suAp,/ĉ&uHԄ=RyΣe_D=W$ x0p [8^vA~Mid@؟x#jL>BSD1R@2')2a:C  t 'Xj@GB0Y>mؽږz420J z 4K/{ c _>tT{{N@x-if`=p +[|Ico<˄Phn 6`6>bcSX .ayT:)[@}\e ˥ J?_&?'J 7=DmpP,9*1Bx% g51~{t T4d1'ӳnsျ}G`f¢zPqhClp >RxrC<Ä& .L 0e\%_qz9pДk9CDD0$ ރf7iO]Aސ:beē4//f0!yT0LVm։jMqkjjG&R>h.'d0+>h!?z y 3dViXgj"H$@3u`=P^ 8$";2! B {]$, nE:>ʕxTF~Fo$$#o6N\{`BYCAXݣ÷f|bUpa_t<\#@)m&Z7}Gv]RNkc7~GNHBĥ}p^h /+izȬZP]}5*@d]#i-)jcɦ^tG(D_z}~AcuۙN{@Pk?D_:U 7 +i/dbe#tl H6-Z$9ێ@J] ? 4zAA`O1#e7c}]j8@T>ZzEqѳ[sY-+o\7WnT%Ν8;*ᨅC1hU8h\ʵjT&XvY~,]91DΈ"9+S-vlk+[[̭/UjbTar}$j0O䖰# *1.9AQ=@vosߦ[6k #c*성C"bI]GUcҶ!0MX&^@kJPc gScoI]W9.iDRxaKkBu^f%L09eJs*L!]#k6*  f-z٭̘_6Z/~Ck2ޠeP! <$8KPߪ/sQ^&;"j⣆V^h^cu"z^ƻ SV+v#H4X7C!& 0V<[qU ?y׊ zC)?3T|3M|=xWͼkM^uvs y{IvVYOre--2Zx9=ñ o>ϬȹA׷^:qkG{L._ۈzXV\ԁ@mY>s)|F(Kk܄ dT( imNҥ=ӅFI|qn=BtDI0]`+I4' $uIa2KbT+,%[EM#VpҠͺ3?35^QoXhJdSB5Fnk:FgIXPp/\y9X/[,Z6'/ `[P>,@22Dd2&Z AZS%6ײ+.wb#,PL+Y3A@Jςa "mH n'\q'^vb.# |en'!{#T…Jbn|Y{d@D_k2dFNA\u 2 ?5'#*v,a0>6 55# PK`ur&%ž$ 𖙯%KgS֫pꙻb.F\#pRyO8]tӼ[ܰ   S I3@yPUPTlgFaj:hUΈH@oO/=20VrB(=bh)nz6VJmjp v& íүzC<>x~x0[z#9[:&ӪYMGs˄)(vL~[Cg8 [k_D7LLөkHj:hsn,ȬZ2QVO4tmkTiP VvU?,yƲEM?]/0ncS;usdܕk𔲻.J SёГf"psiMiaY8k.vU_*/J'ۻhU6,]VgWHeYwu}nx0H&L$8GFEI/$c/E4!Gf)D䑌 &3Ux@؋ot"7I4Cwtm8#L}#.Rotƕ-\32$G2ZCF@Pd^B6FSJj߅hXB"DP~G#<Ԯ):H̐˦wRtgX1<vw>l#^$%WKJ#,"E>#+qŮMClwwm-CP;txDi+e;tWjr^4VøN15(7&Tx ^хY0uVFG}8*p];h:Z=;71VhֱȌk&Z1y>#VΪ7, @e;"ߡ7q\yL e,@ZR5q7R̞Mf aBo$ J=(}I)'&Dkm%39G-#D YlɤӟnCUǏmɩ՟U(.œ~Ef;'OoVնOh.VZa寯di[%` 674__'%^E.C!1_Fô#RVq47!8"`` }$I 'A);D4%|H}>O[>0˜?a H?4@i/&Nj2Ep閝FYoi?bjf$3csq/-2g(eP;|]#q)7dU%e\j3NVGe|T.!3>t8(h=I;mhWK\zS`&1RKB[_E0i#bHO#djPrs>6Ֆ^çͿ~RQm}u^7? tog1vyTVFk`rѥ6@FPG'b 5Wk 'xH7_or*M/f̣uҲtOaFAZYqpXܥx]ckSPڷ&%_dzzjvnQ݀4@ҒҤ-&au}a,b~oIeksxSL]S4hv& r}^Hw}p[N<B~V(񲨶u^(n#Z񓻗lL&H^VM$ l3Pfچ~ g;t:Y ҩ KxFM*7(tn67] 7J2cCa!RH*am)lx̝R!&au):эZš办gПwI#obOkW)7#b̚39a']M{p-42Ջr1?PXDtiw#[Zg4x4x4T!p[8ƇYguq[-`f\qy['~Ff.@TayampU6жXݍ` 3_x3^=&{=mͯd>llG;pZ͌nw~d6&rv"zj-Ke8pL&1ґyE,5`\yC 5UCق=dM+Qʚ{?q< 'jE?gW^|2;wɊ9Dg@J ;:NCE\V89ok!cDZ0s]_̾ }D$PYmYM;($0:mV9@^Rȥ@%H9\ybP/ ?Y~:nXt;qdM$^ F ?_Txs9Dx7>@TU5RU'ébOGI0?}rUB4B"?zTZ0|Qʝ_s| %S0m~V۠\dK#fʒL,;k 8` Rb$,$5 Xe7&@lpo)$穡ĞjvSDUgxgѾ[7kg2]@|XDZ$[-``ofTQ.Sw]S-qW=8H&Dv5k{ز 2+2uWIȦ\ z\H2H8@AH2xKc vgz `{N94SRGP$^ 4-U %/ ϔ)19*O[ٿ߃ƗZJ_ˬ柀4זШ펒N(L,j:C3Hao_m5W3JEG L a tj' OTd'ΓOOjt,{Y ZV馾+pO1nb%5zZfIrOkE|]<0S~|MU4F:aO>irC/¹$ԦEϨex:^G1BBQw053I5]:S -zڸXCJ>xHj=}'ʍPLzf!g`TiZj%Jy]tS&gn(+s_j "LˢA ` [ĕUqq eHj^ |T3>K] `L7, 3TxphAJY .3}3)Cqn:&'@Ҥ}Ϧ)W'K@efr #uLb:o>{8t7,^ 1AM\"ο }||kԬ8Y$7Iy97E_JE=כ^hdD@sq eoיCE]*IJ6Cv1oﴏW#lw )cmXQL/idMkԜ5EkCjGJ,K)fCtiA2Q!ea)Vk a1lwpeVR-i?v0u> L.xhi)֣y,R['_8^7?¹kzZs "X%](lnHA,9 %.^]] _ٰK@O"k@NlأN;g>lQ^0t4dOG|h<34͝Yhd4p^-1[~Z_ pJXz%>&+w: ޺SSXB,I#G\'&OlB4Grk$цivO[hNIj/Btq0QDK4Io>K=.2vtPJ(qN["8RER]eH.2 e,|ʬ3ʬD^K}qɓԛLyLS4a_&Ӱp%{{'Uت g|-= SS3 M t=ŀVcĶs U5Hț?l^}D`L m0es4ߟwuClۣT;/g:s){^ >cV6ɽ0rޭH7nFO"0wt"gUmhٽs8ηGdvG_3H[Dٵ@Y/ _cR&jդYcj fOQ ʏ{.&78YN@]қwNǁ`rX8^h'[HݞsZ5ۅ0vWtI誀+VB$iO?gN0DŽDdf-X1k%<Lv}NM@j9٭- 21IZxsgAŔ9Τ.!E6Q,7`ad8ihuݺk߸a:tHK!zH{qY*{lH.ETE( WFlCr3|Y )2BC:(gM'v )R(Cr0quw2tpt,EM:VF, "8[.Dfكݨyf?.jlnwL6KPT4^m:Sg˳gv ~,)BAFM|2$]3EhC߱e0Ŋ@UD Y`*HkoZ7 C& f.;5E_vا W]g ]KJyA}VS;•9FhzgײVZر^f 1-n Xc\Z2΃A.3I+풃2Gk d+CUQF#.lN sküōϰ# uԥ#h1b9 cP{YOq7Zb q+c6ldsi4_@ Z3@t&F{VݭM628hAU죤fJ;+\-"+ % L؄{#軳4ʗ{9xU,ț:o\f-J.%3EDvpY G,'9LIPٔS6DٹtK:`KX,p(u _9UC@W鿑Ts{P#zؗpBN ( e &=X{ [zkd.e2Jl<ѧGme3y{ y] %L5IF -?cP۸[c35(S֋IԾ'#SL1;llA:7Nܸt47fEV / ~9㛢T-eN,{e8G/R*bb s/daW]P밦b"aK<00lwJ q\V^6W~5Fke<^zat,LQj0(lTmG~֙q [W оéfAgTOf4!weJodzҡyq-`Ptc/+j:Zg;ա$~JQ0g+܈/A>\$H8;ӳJNK3HM6TYܝz $N2]]7fQR@8AV]d.vYpyXh{y3%=Y4\L4 /%KbjuĎ c^D3t~'+<LxB>-VY/Vts?;SvHo~٢׻'t%haKNv7qV/{x~hC^lv]z j u5n qpSM{-IϜXyLMu NXRw>Y+t }!]D,?jӂ6Wa: |{sJ9 ѭpXin#ev,Q}P)׈ZmIY+f/;p,AcTr eAU4 g Si$tGEc52ú/ZB%лQ[y m#_+&MNxcX{pp=4Q1YA?mdn'DJBw~S Lܚ=tNN a;q{rttftAalԻG_]3 +ҎF]3M^i]W7 RN- 4xIEɐ$AACR!Hd T}8t #@zOؚruxYaFlF49đZѕ:  p@Y$m2[jYQ)OS -m,~I79LYZЋcAd}m_|B8'EVb 5ˆ.;-7C09(=wvONJvoUk]:{=VZ̕A+AC܇ݽo̢ u_LX7n;dZ-ClsiX%:~f`Y_I7AɩH j#K+%9 -7լ;R%2H[t*y}ط:ǿ!34 9πG=*E|deaޟ'Tz'S Oh+ڵ2N:6i1u/Aȹee{MbvNj:+3G̰rg;yg!Yܦ IU[b ]iYbVB* {9(ذ^ $ &]mϝeJ3*__UTk ;E|g6\%*2_&:4eo'طj+^]_V*r\[|ezw1쒀e<*]roY`Su/eA\N:ﺧg/Fw4'(#8Aw}?޶NMI01@/YlADhN0Q۾m0 ܊2Cr $]&yЂ$_zǽ{CZB/p&u [tb8GnsI+ISA)o0Y_ߋgf74 [qnGqp|3ed2U& `Dj~]-tbү%oɔqb^#Aw8y+SǾΦ-Vw>EAC.T5˦P )3űOwl~rMTэa`Xnx'Rqdjê>5J^P/* vxkzUڽQ'=(fK c~4\fdwY,fR(> ]S> vWu2ûs[3iP)Tflw6c ];y`3hmv>#LG(XWX Uي05%Y%#|}]9$Dsmc#IYc8Oc3BA!!*c@ְH2.)- NKᐶ^>em ,7ҹ9mY)x y =,p828$?g_6P-N Ljd1G/떙gK2+5-,8?\#Cs,QPA90aЋgH M&=u'j6WlglVrǁ^B jʄˮHB,og)"U+o /Z*ko3-=0=|Ef[=U/)+ֈ|n\-WyXC>v2ٽ?FHL8Fs309}ltoeҾޗ@D%Jh+/MIхrB oYq|6AŒmÈ{r$ꍂn&Yv-.DŽ$s(YF^Dtd#dd f[?.LZBvs:p+Rޫp٠*0b.\~ œ}T@a okGMON'~R/HdnC:jTjE+Ny5N3o} Xf|wجh|Z:aUz5 r›&s-^pMxKQT4f-b,s8Xy݅T2Od&ldaTp-zkWS!Fg9q< qc=Z(;UQ,9N6'ߢ[=|JZϪq͒ (,6d?RY"x ϳ֞Jf}LS!Kh֘Dz%L`hvqIT kQ8xU,/$|rdv{W:Ah6oؙE 1`c\j3tr} pF^xXnJFHb(l~ZFn^67VoBVr:^&:&xWF-]B8&œcyIDrMR"W>k7%Mf( f:N'ڋbM;Q+]t'heQz #L*`v|2Ub>]Jf6ԱM1cA|#R0͈0_:Y-qk\)G8%~mT3!r_(e!ѵ 'EYfظzLXwZ; /Sk\8DqH< UgTPL{tʓj4#qfB|D(|f#!=f҆ x t8-Q]')Mp-;JnjC#nj{x6ōY9sq>m2\g>b^Yvo[T*3n9E4Gږz]k% f)OOPބ0ѡʹĹo.f^G~Th4 \?OHլH櫚kx.r s?[}I vȬafB%鉫hчy\+3$T)Jp>{Tsn ,4?gIk 5C G5_I* I@yoY8,LpMd P.R^Hj8ҪhVhfrf>%pbҍHo7}kר~8~ΘjVfCj- KWeIozQ΃lUl+Uo|rjՙ}'ar*o9nj(#s)L cKI}TFgzXHO1l1:U>b)(Bj'`-qjZ)H J:_QUK^|AaH&t!y-b+i[鹴W^J;g}X$b|01R [@jⅨMKzITë.~4G|rBݧG7"'_wgϒa e lZr%(Bn@6vbۺ|cpOIak-_{=$Q7$} %[췄mp@I}԰6jj}gKpV)ݷ VG{ⳌC/h Fe^S}?U[a\0TX#hh|Y$߈& r;[@lT$ܦQ&3h󉪶7aU[&ԆLv}f.FD9Y,3Qmp4!ݠ,?tlTa.YA39IDy-[٘s۴OŲ wr-p $eQ, 8Rta$3Ә)xg2s~ɴ4Y֡%O4GE$RWETmc%,?]&%?5OrBwUΟo@D?SqXa=w@̵,j1N+@U$b . f$Jf0'1 y8<:?Jj=R+j:hm=e8+( (Q] VxʤPwTUѫ$Բ.%DaQh(P>,0%y5@[ݪYA ) &Ro͊ QZI4#W S N'zD*P_Ri| DZ! D7Rusp2%&0bQʂpqٰl"sqSUa[rYc:gn5C-nhkCL,1 x^tCM]$s5Zw~]1vYËL"uևPOѮ401 9k[B=2;~YZIcFf~^tȼ{INykN(M(xTenVpIʯMv*+%4{x":iuZ_<]T@F<ѻbzHO fB 9 | ZN_5(@ h0\k&B0ِx:cץ”ר`,F_F+}` #U߀07F컦(Y f>+%UJfu'I [GIׅI5wtX䌝ap :Wd>B95@ _WXTD)$Gh5N$ P=g@TEŸԙr!<ǘB[HR4XCCqX{& g-8q ۰t!Xo 6 [+Sƕ&Pۂ1r(TY1fk}aIW*Stюtc cbt,8E-NdJ24$Nv¡%DdkBL-~ x<bez^՟0lV! 4g6I6JxzEi)?l0`}}[޾=~wZd(-wEQ²`c&ԃ7KxnZjtl_SEd>(ZlYИ4FP;@—QVQlP㲳C52go^f+/[wbr>eK!u= ,`WY:@h s7p%^7&3Lzdù%-  ;("ik؁ M<~H-i p,I2yk!vu'7'v?VjT:EK{0OU|R)=iHș`|G5ׯ=!AҘ;Şsﯛ_`aq.pチm#« jRLi!yL׌ PG90BQ- Wa61 .GN:RT&8upBG5 ,և%l_")y8227c%  %Cp+Ad5BQZť'Aא%kpJ+Gpf )qw N "/h-r#G0)Q{9|ӈG!8,L!€")$dm2p$HR tARd2fkbtH/ [Ys#;mo ! FR_i"5`b<"=b3H ~{_I*z=}> %\z~2G믫?o~ս"R4WߴNɽ{aDnkb/g!/R"vqHF8)6"+AQnC h6[^O+UWߊ- x S9bYmLZaۍW|j&:.ۉ<KBH|_^{{?ڟ<=Yo(3>&Թhu"#:֥Y4o@sX]|9*0O[PngT[p{YPS-0?u9GݦkoAQ6wL&WS2!=f|;g0M4lM $`_r8l#mI"F;Rv duȎ>TS:٩芿 e|y SJt _ojt{ ɶ˘],)N!NA'%=p Њfp=@owe0j*5OOg㇟|S*zAR΂w "爢Y q $#4x=@:| 0pd2S["L?/iBT.hl lYr >5X3` EN3dXfXv3R]z )nʡU.\0 YlL`b9G$'4Qo|1]Sʴ!ǓC'rQ0klC6:]Ωg'P^bЛgi\P* o$AA= TJV "WЋ\H m 2 >9N"XzefjU)T6һd>z {@.`99m{- ۸=FxtziЎ|+ØyK!ql/ǎ|UIn[F[m򅹜޵qk48Z%$|fBr=nCi ' #$ U,YB:g(s(k(ՒCJCKEES-M,ͳNeЎ>tOyڞA`d%_hbKV^*`~\$Q\Y㽾$d z|UR-P{4PľA^W<jy2 1}a}]0f.X5eי̀ C/RχJ n2;BpZ7z\`7_ecJ*~Uu Pb_ݰi,kf{]T>d%)<"1Qx<[Z ^I*.RgʁNl< ~%Um{q?m35gf@`J0+R')A q]E H8#gߦU\\I[/!\(!LyO8*x(AlKcWDNC=(`I@]X نԖ L848Sh/6PmtI"˛A,K>f~@(NC-( @=<$- ۮy!"yOmF>MNH3B%hc/YAJꉲ:4ϥ`K.P~Od|7`[G"l`cIa6TtC4iž37_̖'JتdIP,HaAd-,|c ¥FN/XiyTJnV@R _q'MdR9`[6ݸj A6ةd2i=`]SIDYkg/;}^g(H @!8 ;XRLBBnSJC4s`a1f$!n ,9f+OT͍িa fVh~YP\5Wcm #RޚX诬sv0K%hu/J{`?y+7`ų%Eџh6*DJSamQVJݨLjnv:=YS&]lQ֕r֒){eQUomFIT4Q55- OzjP>u3ݔ :oP%.#a-,ӍƚB)W8ͶVx\\,եu'G:AT5=uRV}uZ`v4B BؤN;b'F߭ 7k9&W6\'e:A |3 5TbN}̞} .j|mR<*n"[>ƀScsܦ?v¹N1Tm[.k+hXBN+D1*hieTd5W-xoHl1l. Y7*|GܕRJj춇%<@2N56;!) 2=(z?09eG 6$s9EgeEڀũj`9UsZQQY"jXd|^e-[]I/o&=5ݶ0yXLVkٺx^D`h(\6tbD۽UXʦYoQEOlDCw2lFH˻rPgU]5 J >ogUݵ=OEzej`UWx;?iS86krr0Ts)(LTPP((+IPR50Pҙlĥʥi ɵ\ڌ7`|qsEb 6+=Rlx۟#aC1䗜U7jTeAPx8 ,8Xl &o̷v^Nx87}_:^!u ^e18w‶02]nqxkdD^6~=κx}wImqGn"lh@啠@5*,if߸,m 2"ȸ3HP V`嫹6T'*\86s/ W~+!7qnbDO~fx#_v]FM];?V omWmm!P;>F.QYE5FʠjF0V#?GG ^uן7Q3O?U&6n_6~mzݽSO #Xh7KTξxy4 6%v?;v- )BŒ^B_y8::G] ׽NҚt}aBv7Ax+vcU|ߩpsYQo?܋Z=VUrQ"_-`a6},Y!&Ģ~Tm$z,hWq&A3s7>ڃ`xfAӨfďϝ5,(2o ~8OUsWkQE:Au8zɴ8Z"HB5 7`R48z 5'h9H BB yazz&ni z ]>n5*wF]FD֋5gh_G:^g6I.pm)` fp 6E^a]`]dD idzwHﰗx@&WU`>\MRa>9[gxhqe0So3b'  vF sY p0L:GZ\gܐ/H* z]z40Me[P2䃅z ws`8 5v3j(t~B* {{s;$ axD鈒 xuߢs qZZ@] chCd|c;wu+x ng|CDX4:fw kw5GN?vFth}ǭ<]T?OR:eiÌvzUC˱hwpIlS05"QXu`܏7]> pPsu=o  Rp٣*b&jpihT\<&⧗4W0/ E|Ϥ<GvF8PA=!}leрFпɣ?mԚMä˰ V0c|zC?塅7SZp;D)j4?n<Oά[\taHD jߌ` 77QC3AWcuwǓΨs:]gbA"Ƈ$ӣE/3L{FFfX7mZ;/f?S$ R`yy‡寖{8b0>vPʥց3!A݀}3C و4Pք7 g@Qמ|:^Ƈ/ųފltzC82Ӣp fJ:iV͚?; `m)oE@kv۱іOEBfweQXW#y/`Ż0 Cl64."+a&!b'D=.ui!-ԪSyHN@;#7^0[L1߮[Wzx߅ręEa q_#}~fm]R=>:^|.Wt NVO bj 1aHĨ3>&uՠ^lm&UP7: ZItqVFmB'_fX";k6 9tmϙjctx1Y@O:Jӝ#Yh>㸨R*|pzhרTD} yfh 4lWfI"/ : ֡4)V7yqΑ|u;hSg'2>EynewCr|U$iMs  F'F;ɎzPal 3=mtrP]bQoaÝ9-/̈́ <4,S\:O"0,Vn}:L(ĿXD te _s? ?>z+(R8zU֖:!X腷5`Yٰ֦ ]ëhA5BUֆ _d3QzS LtΗWRejk8j1Xk(-?'̅-GNpY̅wI{} n710]a@ʔ,9.;;F[>~ԙle(ڊF!1l0P߶ Y3(D %C"QtjӺhtjAm~"}H@99[?|U!fPN<8G\}rpZze:T$TL~m@6!V/WA8,,vȌf a?niUEfBhKlv[HrcO,km[BRط|Դ3e"芷4@r'#oE'# gvQ:X<W "F` ~@e= vD h;/ӑg; UMgH5,?ܿQN .R{Zԃ8%w8,Y4|24 " hӳ63˵)Vs BƇF^Q%sk뽿sm]+Tٯ-kUS^$.CyQna|I1>nXaHqʠE& 0=d qXn")}GIM`( ELvqtW_n ETG[X1ܙ&:m_HlCz!C=Ί๟xJxpj|+wpBf1yw #$gu LBxraV-fHWYP],D![ql)Cޘ]Tl=:v{~[ \ӫtbH~de"x:LHG?J{muhM>xo;ɜӍ?_ SZm_beXbѧH0`i1yv>M>_hjK`dan6pe p)TjI;0XM\v[L{s& ?,af\dRyxY5 Q0&- A2q m Aז؁5TԁEl^/bTV;9*gb!h}XZ}o"# 3[03ʹ  )r)}.h%Bٝ| wb'Lf42ky٩eQČ1"#++βґPjQujy gwbpDI1LI܅jNGϿXd8=ȳZ'[ nЎx ]\)^b.\q4EδbV:&TEKژ^޽}3QGob3mK0"J[vn*"-@ Aa=n˲La:^S݄ENʜҏ) (7l*xiWC$v6ni(Nj5KS Jg5!Қx@(n GY2' J#8 i3qy5h!kɤÄ_z2iE+C$j ɋa)/I**-&ٳO$p4ʸ]շg[r_ 1?a \J0^haS,';8ȹwWEL>tFNŔy3ֻu6\mVb+f>\wng\zy{9mѢQ`f0/ 4O!ZC,PGou>`{8T8TV/փd|o{Ln3/|[n?}yz?FKUMU_ I('K'^tǭ+ ,wN_6ГQ A#^M9uy+t0K=`<͖D_dAKG#$gsI< #_GMULjshr4Fk~N|KCw RnFK"ڤIQw@Bl,LhA8uwug$q}PxFsb/9tcK*WҐcKA 5(cLG?5|#4Te#IWI{O &#4"Hv;p^r0j#Dle4<^KSr;@ϱkZ Zֳ?al;!**^(`ߗ]U8A> I%ܻq)TtB¤$ Et&aՌtb{:LQɞ/_=--y$MQԋHi=*l]4>l|C{ vܡTH(Y:S/Nk>ߨ^dAX<|i9Y7{ڑ54pM蝠+ gj|887~~E~ . gnHI,6'|gfMU0[cYnJ8AFܾ@Y 6D{y"戃e:W _g%ESrS*FEc1~,gb4pHE,uRpoiniso'-^g/~|į_$E-WnE0 u =`ƻ=)fe'#?&%vz:5 ¾)MMLK{K)p8*LZ9RAvvb7eU.&6f40]IRk` xu^<&6(;zuqW v钜Uۏdˋԑ$A{ա21BԼ` {?\< osr=:a5C )UUƩ,;1InoWk u څ^S%l_A2+fa$wőWLʊqacxs0|99?,9#:$W~V9-=- xm5XG*i?NcKKFyn^w_Q'ܝJpL&8TRIڑZ!u2řtN= Cmr3{J:87If: י2tQkWLGϦfKP9d&'>RcmZv]֕Jji;غ0|k%5wwܠ#M)Z.ioRej|[jRRZ Y! ?_?eNQ#y?624y@yiA=UWG 0_.Ў.T)?,Lo~U UWeFPTR4`DU~L ecWvq`Krtּ=a8~ ' 7/1AKX8iPe:|u<_͖6_2sY< Ď0rlmKQjUoTsq2Nt'vKx'`z8e 7t3M8:3b0ޙ "Iw>KwϬyEٗ~mG lUΖjC+t?b:U+?܁y);fU '#Ά/(V fH@8ra?c\:64{>o:Ê + Gy~J}_߮]H9 ظ9G Or&/c\. ̇L.:uVIѯI"nJO.}f۔J7=w*I:w"g(`+{`? NwR)ܮ`|CjRsY`:oTLy-ƲMJ+t>>FUA)wv(*ƸwuA)pW1ow'w|Kg0X%tDtmt[\fE >+7RFHtea}sw u-LՏtii0M>GQݹ跸 ,lE(q"iSW` Nd )iDr@UHySеΌHڭr(&TtpVR$MQi,zazcKi\9#yTQPck좵fPV1Db*Xjk4y[\b6d sJ #p׀,D@No0y`jQEyU59*mQMc#i'= jM80V^E %sȉB!{_^>*eIkKK٥0z G u͝LۢqJ8U,E\ YkRk|om! Q)F9.ÇV!G6DE9ł>@Gv&t{/0֥:I#{|C$xiЛPF]^<`:nhMX.l h$aEcơ֘Uo {HޡVjҋCgN>l*$h\$ 4Ȓmo5;߬CBD"~i=U}lqDֳŸjl"N(D8ʽHO꦳tOZDKXReȼKxま:~ΩʢR*T? dMH2 w[JJiN k߃aU5幽`A5:#Ƹƒ_G ,Y71[:y u̹)$lf:N<P(1 G$`7(J0#-6SB+78Usu_6. [>}t:3p$)g[+GՁKԄ#:vKv,+P=eKS%m~&{;gT05~'\!u]WXHl(; =7Q t3Jg_82IԒ? j|.قE ȸ{V7h\LgFpԑ: XGqA-fjNn~vuw/\}D5"٦Toس ߖ ?iw-#E|3`d/L2]mOɂ9?܉;zL?tc]$t9Ԇ~RSEkߣOYqs3dq6]2+砅pMEҥ+-:7 $NUq|~c(^m Ê,WcdةF&n3ڪb>.ˬCleWc us5zM!TB8J;%lN'H Pa BΨ*Bk@jwk/˜a;T'N ^ KYCJ37c4Gk8YHBY%yK=;ȯk#%[ Nn%F2av75ԳeΟq ^*oփiXe[{k k \F>ݚHEyvhhvsJ0t+3Ǚ҆`pz\o]gQaM'S)jHmj DLCBqC˜d1M(,tKMб)}` :[Q&O,쒄fvbȑ1)Ĩ6E=[kߟWYUt` RX6MXjX.f0kec{`ߔg:2P)O[B2K)}Wpe7Ēlpx2o YRk?mO ˘|3E,Щ=yE}1T SZ]disŸw:hYW~Zo/0/<z6E.)cDa셳,n쐜}8I(}YYXG㌒ԎU [) X$^sͯ~9%MZD,l# X_֦!<<[Ai40hɴ!!iTb!B^cz)fC;2+,yI3'J5?EX@n ͭsqa1:1n)^:WrÌotyzR@pQpo#ʽ9\_w[4UgtOI1 j*8>>9ak=yRse A!\'vLZsR%筦.1 oDu3çнDo憻qL`in;ʺ djR^>D z,!2MQ&iQ./U\w/*9 *6cI8RؕE"l_^g˦pn #`|x̸q|֩|\_ϜͷmbV D5x}ͳA`,k :7ox̴iBG`'&J14qB] 7xܺy` 6SK=#S>9̦N0hrB,yE786e5sux31"IڑKep:7<xffߠ("{LB{%̘O\َї x31d|#5>.' fYx;ti%Ȓ䔦6Z_R8D ɮx31\o7އ^ &// x318/&69t- %x31̤ĒTi"~#|;)(?9%57akf:57E}Ҫx340031QON,IJ,Kd8d׵: .'?9>3/-޼MZuMxTsӒ*,,J-(̞~/| :v0+/wx?L C]R6g.7=/RUNj$ ֡x31"F[ܓV?غ+m}c Ev rxffߠ(fޚ ʃ.~l`CvLp x31d| t~]tjQ7xLx;ti%؅kZdv\| Юx31\Be,VR $x31F-oy'/LJ ex31̤ĒT;_5rgKT@'3l[DZfcӟqHo( +x340031QON,IJ,KdxW "E*O]q.'?9>3/-޼MZuMxTsӒ*,,J-(̞~/| :v01Gx31"bɮzExffߠ(5Cj#'"U,*xَї G Dx31d|yAz>}ߘːtַ x;ti%Uŋó;8+ؿK!2 x31\I{u+.HK[+m ֮x31[7n̾ukv967ovWx340031QON,IJ,KdN1/;itOqmu9yimjתshzcߞ4Ta9HeQj!Dfo,{[й.)x?L C]R6g? >Umr _kZs)((LQJA{6s f(PH BO2*yL,,Lpuy9'zmvRUU/x31"UcoL/YxFg z x}BȪk[קMODyIts26^L/N"}C?/ea͐Hɪ@U/ hMc#_#@Ғ/n=m MM2s22 [n7}U(:˳S?IIq^2c[V_5Yt(|U4<'?9$xIYQ]KX*>L,%SF_4Êe_w_|(Yu&Fƶf5׹w>wuib sSudDn~$x+ك!26=I5l;wɡx31"UWݹ-yFijx!* APL-?>x31d|L\ẢcEW x31\YE=o?5Do h:Q#B Ox31ck.yԑ?nY!)9x31̤ĒT AN*h]`d DQ~rJjn>C=ymS->>z8Ox340031QOvIJ,Kd]kSOUץt n +x;]hT@~IfN^narJ^r~>_ogg__djƃ#+4ڕ@^A^<) *<603rMh!3YIBj])YO`! d5=&ݓ O>l"lg ZkͪV/8x31"św[JnLGv_Z(xD7m9Ijz;YqY"R100755 iwlib.h|64ǂ29̴ffY)Ix31"Y9 25ǖu }x;*g&1 /n5!y>f\K,";@3cL?\x31d|YU\eT2_EZ~mV {x;ti%_mEۖuQXUT x31\6 C4MLx31W3էL~hϿY Ox31̤ĒT AN*h]`d DQ~rJjn>ےok 86zb/n& 7ݨx340031QOvIJ,Kd([#xφgT /RJx{S@ 19;1=U!9?W@/'?9%57#/ &x̺ue*72_֢Nk n&G)xxqB{F͋m><ax31";ͯk%L]=1 x:ڂjڇ(7~>*'99}p!zmD+#  x8 >|L}7_g Xx31"7O]5햕|/&Mxat fyK S1&Ì4[ V<(C7.\к;"100755 libwlocate.cC8Ai51zkd8+~x31"+Kw>Y^v-A3]|Qx}=F m0-6rs͟Y3h`x۟!qC1rqIbI]bA|^i5e敤i(Ŕ(iNyl5{Km^:ҡx31"N.YV\q@ %;x!vÑ͉߸!B9+ó5Lx31"q 6牶ه6Ou-g yZx}ȡD9Hf %df;ƝLvx31d|ƕf9y#S92ޓ 7x;ti%<Ј k7 il_ ax31\W۞n6kw[ x31TϽFdWK/\w";x31̤ĒT*) K3tfh5(ONIgx[mMFϿSMX[',xzz=ǭIpb~ZQ)x31"돡g Hܚ~ Mx}[~q=[b{5^߻َq' Zx31d|92]pg7`3 +x;ti%uwN{OXQ<( x31\ekzg.^}U ",x jx31w7oK"zx31̤ĒTKO6|ɝ4w 3(ONIgx[mMFϿSMX@x340031QON,IJ,KdصbϏD s.ZΒnQQx|zpjϣ A*R ! 4'}{ghf ߂ε ;3"x31",M|shّSY x!*JC_8 ThE>x31d|=}ٓ;Y7Ox31\ï؛>6+ cx31˭ LQ:9gD Px31̤ĒTg};˝*\kQdۚ9N :+Ϊx340031QON,IJ,Kdp^7s/ż^?As~C̼|k=7ptS^N~UXRYZQ=!;C3K^8t`j4yx31"w3coټu9+ x}ߺIagS]0x˃v;( x31d|hδŞLOr`mr f@x3eM ~;Ht&Wd{Ky=*09R&NXɮx31\Osv;˻nS7 kx31m\y&9{fIvrxUHk x31̤ĒTхAםTUr} DQ~rJjn>ےok 86zb/n& ۡx31"?ӎ/>@~/yx!*˭kК3S?[`|> \x31d|@ SO=P\h:ʂGɀ dx3z}z'Ig.8G%)%1"!R ݜռ@#hx31\sO<Բ,گ-lz" Mx31_34fxRSFfU5 x340031QJ,Kd8thH5 2oҌBN~rJjn>%Zݎr-BVCx31\oTJKǚ/Nds̠ x31 guCTL x31"}݉mض-Oܮ)Q *x!*RJ aEϹ(>bx31d|v=%ڕbu̇!?k' Px3 )qn]1"!R ݜռ@#iҡx31"Evwfڳ:kv:!w x}&C13T8gӂ;yx31"|r}ѦLqXq{X px!* H.;}> 9סx31"KlPW~9 Zx:ycsֲL>PnȖXm/<9R?|x8 'X̌ R`miZ }x̺ulF9d"۝xf\z޳Y lJx[ƱcFEx31"+ m)XTTLmҏ-R1 bx}cfibJ?nl]=eʕ7ԃ x̴iB2|, *r-8i!C #xkܺyB 55 EEe9vF'(NNH76Etsܪzx31""*-5 yx}cfI%rǶ[ nf?>ǍiA x31"4/x{޻L%/ Sx!ȖXm/<9R?x31"3ųdI;4u2˶ Kx}cfI%rǶ[ nf?>ǍiA x31"r4~.Jt{  x6RR1'-4lFMYtƷ96?ؖRHAg]Yxg4p&̳9'gMͺ_J- ʓ'*Ln|a-iUN7Wf0o.Ο2sN !yn& rnk(a":ltN^RnrHWd 6?sMr'sv@idR@  0MszM1s34 bʹ0RJ 7I3ɆR{u9&6QA8KTSbt&ߛ-ƟX_iͥ60^`ذ}ow+ˑx31"J[xmrf{ ox} fM}jv;-x31d|-|P'>V  %x9|/q!4ΝƵwx31\ϞޫRΜyO>K/_x31^Yo},H%6 x340031QOvIJ,Kd(xRP}-qYݟcb 9I9ɉ% GV$J9E>EBx340031QON,IJ,KdCd;u9yizn*ɯI ֽ< (K3{Bзwfp-\H2hDxqC i7\^^T4}QB vx31">A1/ >w2ƹc¼դUfx!*GךgX=Z@Ϟ>U> Kx31d|k^ɜ<6\n`2U• x;ti%ȇ5Vn(PboH 9x31\w\Nuth=Ljyg{>J x31)ӽW=)Q%ѣ3/-ZM]?>iԺGATB~ifORk;'n4:xqC i7gfghĦzF]E7rMӡx31"W6;7;vSg"YW fx}Koَ̻q' ڢx31d|QV;$|LO x906|CDY x31\G?2ɉ,}ȴofx31-*V^>xj/>D8 ex340031QOvIJ,Kd(xRP}-qYݟcb 9I9ɉ% 5TL9=::40x340031QON,IJ,Kd8l:r1ks2OKˇ(x;ti%H 8~6sۣ x Dx31\;̮o7Xنh-f3 sx31jj}fߒxa"w ǭx340031QOvIJ,Kd(xRP}-qYݟcb 9I9ɉ% >mɿ*S}*63Ygx ?1B Tx31" VSkfp("? kx}ΓgK<3'H}`f7jN& 'x31d|suvfLfuSzyQ 7!x;ti%Huݴs^Vw"oK+% x31\U%Lߋ6x}ȃ{yj7ÿE\v; x31d|B-ܬ"5w0 tx9$KѤK*Ca5 x31\~ Cㅣ*ut gT x31]؜uI5.CG^ x340031QOvIJ,Kdnzm{IdV7e2.BNfRyN~rbI*?wO[JT~:z~L* |*x{_p`Cdץ,&OK+֪Ɠo>..2f[LMP1A0Y&ǩt#9,!S33Em x;ti%Ȃ'oJ)Zd 9 6x31\}uށu۳˻V7`x31Ϭ[o\M6 kx340031QOvIJ,KdHطs&[w\9  PL*ON,IegiKUSY^Go e!EUxmSKOQNBEmy3i)PCT0`D &u޶Lgm;ZМZItaL\_`†+綴4Ūщ3tl%nÙJKDRb7vl&GZ)[\;t)ĸ^OmSS=m&%|5*46AI`9 I1lnx[r5q0&]ĔeL:i99390iZsq)Hpr<ᜟ_ZWZancdjccT| ؠV̕Ph/nJU-ڜ$m2dUy~9 -5sKVNΖӚ7X[[|% x31d|>E)cR˞q Yx;ti%HK&kq,Gp_ Kx31\"/;7hJ|E ۮx31ӲiJLIpq- x340031QOvIJ,KdHطs&[w\9  PL*ON,Ie蕟\s%?lO/  x340031QON,IJ,Kd`zw9|y;ꂕLRUsc !sR ! 4'}{ghf ߂ε xx~/el x&_9W xD~:,a#Spv+&100644 maindefs.h=7|! %GAK6)ܕ{Z? HxJߊ'#endif // TEST_MODE)0RE AND lat!=0 and lon!=0l$ Hz]@`e r;r/s,PsrshowLogAVms Pq4-[tc v4 )5!c k#` ?.DRnxhىهx31"^JI~-~Y*^Hf d'x}0oÖ >}N/L{Tt-.&p x31d|5k~<)Q{kcXҏ?֍\x9RK2L-2Ԗ¨Үx31\ b%ş=+:Dk Nx31㧘3l!*7 x340031QOvIJ,KdHطs&[w\9  PL*ON,Ie0ZVʉ1;SjZ;'x340031QON,IJ,Kdй|9{{Ō>dTYQt<'?9(K3{Bзwfp-\!xʸqw^F?x=x31"&WwE-qѱšb̬ oEx7X[[|]gx31"3G.,%ٌ-ؘզyVx}Hͥ%-حiɠxf;ƝL x31d|KU<_j_ggVWطwx;ti%٧vl3 4 8-(|3F4 x31\E8/ `˝Cѧ. x31ݡ"4^eږ]4+Z) x340031QOvIJ,KdHطs&[w\9  PL*ON,Ie6#Rĥ\W> ɡx340031QON,IJ,KdH2.AEJ|y1+O/J-(̞~/| :v0zsnx;Q~:/f F/^x31"k'D $ x31d|ROec䘿7x} pxQ檁DV8 8w82o֠*FͿP#40000 src6gx*+ƚ@2u`&)*.%x31\&Ʒkm.xɷ4( 5x31N9ΦkXﱫ< 6 x340031QJ,Kd`v :;"JI hxcDzq+ƙL֓2Rsrm * L KjjT FxŸqBiv鏉M;O^*ϓsfB P(K)M-f=fg{~+L- yx340031QMӫaXz!,s  x340031Q(.)K/֫a坟wiMo@0?5x31\S>٬[pσ xx31)t͇+WqH~ x340031QOvIJ,KdHطs&[w\9  PL*ON,Ieh!Ki3}"x340031QON,IJ,KdxVcʈ=zVŝ64+O/J-(̞~/| :v0 +!_ x;Qz &nE?x6{3N/#)Xͥi ieRsS32KJ44Jk4HY5\)Ԅ<k7W L^.4俲@arcb.x31"4P O'G~'F @x}cf)k,{jZv>ؓ(æ !hx~*զXt1b ۇRvTAxi ᱓Z&&Lټ v>a fx31"3qovkۿ-x!*ϓZ_\@\>  x31d|ɂH2J 9=3244Aj.Ԣ<[Ck@Nj^zILl[;.{i,Wl6g|O}O>ya̴LĢ< Mkɂr X'Po@@,f/I.=Rqzf}vBP-Sx9X;cغ^x31\wKߐ2LR(jľ; x31ޢ~D  έx340031QOvIJ,KdHطs&[w\9  PL*ON,Ie7W|iRoi\ x340031QON,IJ,Kdvvʻƻ ar7Ux31":w>?Swc2:]/٢x}cf}b:̇.kYط>@ Gix4iB}x31"x=>}( =x31gwOO寲gT=p^xzz@;õ_^\`sMmۍaJ\]v0ե0x^X֩"82Euqc&6 ߬3OOOuθ2lPSCUf26z; @%) OLk1oy"6AIBM*)JLyqwÌ7-z{f% Gt$M=,TxI[޸)*gX:W)w~#caTQyfQjNjq1Ѻ %۫x~}zcs[Y\tf;iLH x31d|- E;TtO fx;ti%KZ|wD< S [x31\uul] 6x31{wL߮R}6ܩ x340031QOvIJ,KdHطs&[w\9  PL*ON,Iexhf0}9k+# x340031QON,IJ,Kd0z."\oř' VxO(q3Ïa+BBsR!V I9GrrX)$q?I yS-<3`Ql²\%?lPa'"3up% 2l Ȟe?x31".>fMi Zm䀕} zx!*+x}+ۤFs0ѡ7> cx31d|7%TMZ1[/v,"ˬ zDx3eY\GgV'gg9Gc6yw{WDrvNЀnx~}^fC=ę+y'x31\c>独UzY g`xkHXAm\ `0-B9Y 6cO`4d3~ɉ@ہ8yt&[q2N ~"_dA]:ܙy% 9%t7d,x31"z|;?}.Q Cj4=x!*֘қ)5 ؛.dz> x31d|ƟN'̸vN<Dx;ti%H%uZ6ͪL0Q x31\YY&%v%{ ׮x31}7u~8GZjIloY  x340031QOvIJ,Kdh9&Lz7ikL @!'3<'?9$.u¾+^]}Q zx340031QON,IJ,Kd6h18q7__k8+i#x[_WV^Q_wSF x31"Һ,S͏.a4Aqt<h mx~}Cŭr-oosF^l4& x31d|#n?ij9=&.rx;ti%ȼKNo.ccRV x31\'*̵x>%|҈Wtf죙j x31 ~N?Q\`h^$ x340031QOvIJ,Kd7/WF_>]Re PL*ON,IepKeWykTz lx[Җ4'sx31"%SYVbϹ Wx!*]jvbo;z@Ių>t*x31d| )HgG ]x;ti%7?6U|h~0o> x31\V+=ۥ&;} ˮx31KmbY'9✋ x340031QOvIJ,Kd7/WF_>]ReCpĒT:kӍ~cNL !x31":q^\|fH4b0'x!*tKyB}CD(>x31d|?i컖}UضaVɍ6wR.x;ti%ȹ:vxsr" x31\oe ۑ& /ZQ x31ď>T8,t%f Šx340031QOvIJ,Kdp Yع^1W V;i7E3 ! KR!M7 NW: 4Mx*ddJ. Configuration$Xs;0L$x31"׻+4;o /x~}VOvb'7ʱJg4&Q x31d| l*ۑW'^aQX@ wxQeUpы!yQ7M` y27Xkb 4a940000 src6Cw摡Χށ)m"QxF?71/3-Ď IPexŸq27vL[yTo5Gń x340031Q(.)K/֫a໢{G9<=q\x31\9+D؄rP+Vx31,5&yWqէD ex340031QOvIJ,KdWz5~MԿB.0$NxI? 5R{񿬻!"x[r)tE^j^yfZ^prb^PjqiN5WfnA~QBb^JQ~f\M8MKLO-5diIfOf1BSVbY^f_ O^(09X&WV^X 61(595,h3eL.12:kZs) (% 'R!JjhgCݥ "$d&'d~rpq+$wm.4$nSMĔb[]rsL$?9LAnrYEe@+&f9'%O;y [ &y'SR\SY OdE-﵂X@sY'wxZmo_O=JI4vTQD mC!TkfiR(~<?3 ;n>򟕗]y%/;MoJLoV|ZWM\3 ɫ[q !dwԤxK|Frlfw:ݿQB*=ҧn}&alÞg wu $$tZGTdڥ2/{yOzNDbzj{0GdDŽz]ZqtVY Ьo8Qפ$o;e[[D~j4SI>f/wK(|O8l;U>"0!-Uh~;-ڟXCp>+}>یR>hy3Z |8=*yaFˑq=Y) ??ݲcjzl ݥmstIz/ST>7 8cQ6Xޣ!7+JkP뉔U35AZ#g ##dF&dFz6a!-dyچƨ PMEH=&17ПXEx/*". \Exq% "9X,b`*bU[Cl1lQC|rf>8|qo :XD!눾C`nuC nC%Eb! lODw4^2;ZXn:EvBlqQ-\dnO.~ۈ^BX5F%::/¯آA֐E֐F-tnW@ ZX+`/ =;xTāǀ14am| P"MXf 9MEXY"4OiM4dS i2)4A,j 1֓%S`cѰ w'F|c F qsN!G²)tRCؘ`w2R,sFf.G:2D]7?cYڑ аv=bIZ)X6k qpcaKFNԣ_9ĉrQ\T/\3ӞA$ZHT?LA6BN9\9\y E%6"/a;/X-޳dϸƇv!0>pdy˅VvT]˴:tl'ccч7 raۆd斥4m㖜d@EcةL)ϦC S]0+mYrII#;&,ed߉{c؋mQTغB0PG<*!>6"[˛q|$mx$e`;Nl.I-S׽ޥ-QHGWiq/ X%k$~\`6 l|,PdB65bއ%3bQ,9'hS,˗<-dLY0|/-der^.=Orv\NF)c#֣!ӑ{R>-josONQG4K.x5(~F[LJx31"(J(zjŹy/ Yx!*QǕw$Pj&^T޳>ox31d|l|p'yrXep-x3e;XE-FE` _H ߤy ~9+%uS@`xu&ļ̴;.Vx31\jtUiy3Ug N x31S/I\j\+e] x340031QOvIJ,Kd8jw%.+-Nvf!D]8PabI*Dg[lt6lN_|zO"e6x*pĆȉboJL`< cxL$]&KHO^,69UZx:[\#-'?DS@*??-1$H(FٚsBzF rVi2ORVqN+K,ִR2[rԊ%ŊSKJRB%eZ\OY0MQleT(9ydER“˕OR,ȴyvIEIIx| dyZ\\ `P=HZ̼(J-*(D%T&gz%h())h+$e9{h+)((iCErRRs4̯ =[/Vy<x31"sOGv7Q~#U'5Au -/x~}Ḩ%N9g27f;iLG x31d|Z"z|ݙr^} Sx;ti%yIJdxW_4]E x31\_˷Y|y ox31{ǗW5^>T\\& W Nx340031QOvIJ,KdPX!iC@6Yw5 *L,I}ql͟׆ͩyk\O4 x[lBzI̴L=-k܂IJDҒ̜9C9y% Eiɩ9)EzΉ99I \\ Ee% N% 9!9ѱѱyPhhɇsm ur Ks2K*'at|_xrӣ+Y963v1 jj++ik]ky9fwL:ue& OI/RШ5Vښ X,Y _\B mJmؠL~~Dx$'뱆Ņd$.٨19E-2Se'?T\n,nx31".$k5qXwh~r5 +zx~}Oǒ]R.uf9َqۀ 'x31d|+*%[X K gx;ti%bF}SCf~~e#?W x31\?)F']ȱEPkȳy. %x314 6u6S2SwMX x340031QOvIJ,Kd$9L񿶝bey{!D]8PabI*Dg[lt6lN_|z"ڼx[msں B7 a\;Ý $nx;7qԱ-H3+/؄G3iȫ#yYL@=)UXVψ.}^*jwv[`O㳽|l>vTvvܜd{{tZ˨+dr ώgGWZsldvM.#Gݸd<_] ;d:}{a s+ucgG[-eusFmzޓ~zozY:dڥrM};։)t55]U|}-1d3dd BvXŎMf/o,.ШoDU퐼o-iM3WUU·zC5ݩf|rM[&6^z.4Rc$;h ̷]k/ƃiYg#'2 =@^|Wj0L> ףE8c`0d% qq >NU=\Pp"@Np  nq:K upA6lpW4pu=cn?48qu+q5_&  ix <{ݥ:pro+%pwNw-w8[t0&Im.$ߚzӐ\B G.$֣LeW ! Ӆ#9k ~A=$-y-H^ZL⍄^n$$H்o-齹vHHXx wjdޘWX0<;F3Z3|#ݤ}f Ko-:+,$uʙYUǢ:& .l foRMHfHCt8U4ӺzTZZlc=vG[jTr9 *ȘaJywʳo3Z]eн瓒U;#"@BWON^tGe_ۊZidnU쟪TTwcm{Ć]})Ņb,A(cnGHƬ˩V 1zkޑI)uxj h3BXmG<g^ 445z)jg07 1|X=o"RLQ>iѕXt&pETY fZiшw̲{n!Qf p|t$Ϗ%39Na>1]*)}^R-^6$;]:rt-hY\]_H-WW{m6AA=AF`At)d>^2n>BO|uqC 3|`sq?==PPmeo$wGhx̮eX t9䦝tR}Dv?J4߷&tg?vxgSon)<TVY-#=d[Zlm+koeߚ|kt׸k7m*$oKMxܣD|!m"|VUNr֪{Yz%d b$tUc D+@vs&AW? Z6mĝǤwt+.+~ߵ79agn-Yf^Sol9x31"ʚN2ysi֕t~ʇ x!*tB jwD|׳>JȢx31d|}NVIGdt'Z)d4  x31\ؚ[>4qН {5 x31Y^_^.A x340031QOvIJ,Kd$9L񿶝bey{-!#x31"K{ɘ^e"uYZ ҏ =x31gwO3K_(`sLgCsSSgHO?wk&>k{ڶsÔx3h~7-:wzri(*MNMIeҷ5چD{>r|DS7qw),g.I]NfwÑɷW(g)lpQh׉lRgח ,zس~N WG_W},que>;Pyy%z | aًoq{4E OnxkiMVh@e̐+by*qu"+(`139d̖ikH2%II19e'XlkvZn> U4$(qnY׋d/y|s"ެCY9ĩZxg>XۧSD~ĒT}BK[=,0[\^ *Lu doZEgHO iĦao驶<670Uf0f6*ɾ"[R&Lu ˟3~uOʞrpRIIgXgØ -Krxj8HkMU1岡p敉܍wb*3RsRNҽ5f+fh*'1hN<&ZIb<"mj[Ud0,77鄃m΅m@RX TTToC(S!^;b sEa N7'iʹj x~]=j$XKKK]yHkՍNx(sqSO榦 ٩i9z~ N?.jΤO.mI]NfQVw}^'ɾT%`kȖ[/˼W#7; 7>vIJ x340031Q /H,*N-KfP|{_Ki+7j\a05s(W>Z1TobvjZfN*á^6 ţNv@'ouqĸ!n* WG_WU?Pej,}/*r3ow|MJ봶]&ף$Yt#x4iB|fRIjq  Lܐ[ xij̤..'/[[/+8ʙx&$C~"x}ToEIwlXql@AS6tI[$xf]y@ nw^8zC=@"{03޵׮5;o޼}zslCQY):l55꤁ҍ͒TػYCGYV ZީH{ҎE#I;RZv4ۂSUbWN)YeQeM?{~lQ}^%NV[='gCwJy _Sc/ qpM?!;'l uc\V?HMK& ;L y@z&zb~*.U*_'bqnCnr>܆& LL}J`~5L(JK=Ʃ&@*z2DľNw؏2'r7?)+ۤZ%jF!j :]D*ԡXyezA7sM .4Q,flLx1| 8#”A#x3[ٴ ׂ36=t,Eئk!@ɨ7W39Lqe=eUERVhYw21^M b at βpq,ٙei$܂>?kҰҌnQd׳|+s3:BM~[;E&MiqxDm1ue)Db)rhD[ATM>VI|*|KE-#'եa nv,!珅ٶjQ=S7*%/‡$|_Ϳ,i iUُվ,FNJЌхKAe日ڝa-z`,bPg2h(c=mC804 '0|Z6yhO7Ȧ_EE+D(cTx8 k7dg3334bSK=#SͷY Y6{s .JxekQm&Id6 X,ĥVb6$Zkwqi ًzP*(x ^zɓ RgbEÛ7fOfYw '~Ba*dus lOKLP [t]*hUt},%2IE?:Sؒו#➒蕒;xJ nT_J35Zq\vi:?_K[3l \u2?^k2)JZ@]N\Ci郿8t.xa`1NԼĒD|̲T?(?W8,K9%5-3/U!9>5(5(5(?H&)WHO-Q(/,˘0%+x340031QOvIL+KgPv݊-fLKRYqEcA^rA#E+pܷUwN2aMrD'L?L_uv/(~.<3l3g^K?(˩uSe{g6jD xw=&M^WNdn hkFxeɊ`Rx[}FCL1kMv`z9) @G.6\Bx31d|ֆ̖i\/\|uˢ x31W'OG? M8ȟZ<u x340031QH+)a8<7kDl9-gh``njP_\W\°~]˲}rSl|$n1q:eTg٩3~9qNKD()exv3F`|KJ};r$~B:7x;mx{I6 19;1=J'?%57+,83?J@ll# 9 }xۢyEc#ߘ0Lg,"<dk5@~1Xf T>u&6Z HFH><19I1e)99?IO>6G+Ps3uk;ܾL$_,xVo8K w'])rnh z@Ǫ^Lkfl~ۦr7?Ǡ )RMݠw2%F`iLpPT.YHRK,֒ N˅׵z _3Y_ÒIt2C;FV|G Sb&KJAXgSZiN1 G>z:2Q :+MPN%I:,.:WJ0c4heȗR$v<-~18^ZaW R2nZ z6#0kmM1w3c͗2F.m5ܜ5d_,؎{(`*urFd>1!9xvMĹAcf%뗘/1{c榋b'8OHMqQsȇZaC;7C +#-heͭޫ{KE8G85?bawpEٸ4S¡J)]8LA S#C[ GJN-gEd",<_,[f : WޫXdwBAL8E)4tBj5&4dLrX4m. WHuZ^uI{0SUTSM ~>I̬Eq6φ5cfcͩf+~s!x n96+\{UT)! t[ Pq7\yoe/_}wkqhZ$b>1~rw{ekò>2^*.;fb_\\"G>P/Nҳ;C+r_6Cf:Tk#Fx(E`K(gf^Xsq&*$39%@"Tk.TEr~i^IQeq5R `GG 8%$њ(ͪ˥5ن+gj.ɷ&OΟȖb暬5Gd,Ex%j&ڳ٦ 9'51@CfwEy \\\Evx̸q? E \P:KzUYM̪~e x31"v~k)Гy;̹ Xx~}HKb?Ȧk}wwv3.7x31d|WW=s# ax31"ͨˣt~ɳs ox~}cSt]_V"v3 4x31d|{K*ڟptFuA0 }ggx;4i # %x31"^b'|3UeA*- x~};)AkqZ{Lv3n ߢx31d|}sO,ί.7+`oķ {i|x;qBUox31"l9]Zd &ox¾]=j$XKKK]yHklԍNx(sqSO榦 ٩i9z~ N?.jΤO.mgռ{K/>U(0ϫd;}%%z) t3/̺^${f?=Pr2&N-d<;>uן"'& ''%3 }nYӧ|&'bKsIts~M)l:K!AT0_\,]Ԛ;9MtVR ?}N+m;dU" MXmysLR*`xƾ}%wIپg޺\yaCsSSdMk|^xԷj_dGƏ"kgf!,JL"b m7䢳 fk"W&Λp̮q-zex>BN~rJjn>bW?.4u?bJRA7ŧVǔˆ™W&r7މl"6Oɴ`Vj=p"UxL6:y4fiҡx31"Ig#Eq]șswOT;x31gwO}6j~ƕ3OW140075UpsgkbЋ볶l.\7m17LIgH0VwӢs>Ậw/gV_Դ̜T79MK 6T;c3g+@k8~ftL4o{_Hr2ʰx3:N*\#<=ETiwwXȵv* rutue/?dOL U\;ѲnT|*MQÓq#n3=mZU?p,9(!W YU" 7D^W BQPcfrh-~?ϑeJ$bsOܱ;(:lmܪ}hHyN~rbI*P]_sYۮm x'.ªN}ő!.Ǎ3,gfEyzz-ͧtp L g6Se 9n&4TϰĴ+oct+Ԥd '{7}pޢnpp@Qr{D7Od3Bt/5+ru~2}W72Ag{3k4<NW18~LUNbEw۞JhmŰ9&d M:FosiGT$dg1}}Aǰ-͚W(Se/X1qNŪu"yvx31"MAodW RK jn^x{0 V9U/C0k4xb`=x5&M%ir-)ko DIE@px31"5׸L56_T> Lxľ}CS ,K/)0]_P>DT(19U/hwKKz{m;_ EIJq֖.wi6ji/8Gh,x5җ'r*|1r-)ko DIE@Nhx8OqC!bɾ|<9֓%; x;Фa?[ 3CIx31" SdD583 f~X txľ]=j$XKKK]yHklԍNx(sqSO榦 ٩i9z~ N?.jΤO.mgռ{K/>U(0ϫfFMZnHeә] qON~rJjn>ŏ7=zں&~/S(19U/᤼?}N+m;mf]/yxrCTU 2k`mO&33}NfhjMϻcRlx;(JjC;y̋"x0xb`?#d!6&lG'KW /x̺d"&32RS1@J'?%57?<3O/a+WvG NęP<~ʃ:2nWq"n5vj MknLo"[,7 b䭌*`ewg|2._|w ]a.&M *E&lIx}F!x31d|~ .T_ myW Tx31W'OG?7&v{cVm(/raB) x340031QH+)aL m͘>gT $3a~e:侧~Ibt05E`%ϲSgsK?(^PRRfvHtnŧ<l+x{i FF-x8]n|E%2KRSRK2S2J2R 3K22ssSS2KRs*7L6Üyr5-xx31"]y~Q?[f Fxľ}C3'WxK.g5 yҺ BQxɿofWcm/<x31"o?\;S6߿ 0hnx: M̤EԧC1 ܳ (T#֑ѕTfx9L6s"_ 5bqPΓ.8x*}MVۣړ)Gx31"yA5 i0KL}L ;xdX[an>.` 40000 locdemo>/v'Z {c =100755 test.c[|L}"1iԑ ]i(lx5җ'r*|1s邭N)ClYQVx31".u2+-=(x9:.a2>_m#ڳN3Ryْr_h-z (l~xcKy)Xx[ccAur#4V7)3Ox31"w.|y ̚ Oxʾ}C#HsЛ/V>vsR" ݪS~+x31"YrMn)7'G2:&xʾ}&=19:JEʧ}=RJ'Lx9A(o5~DSb$b T^)/+lx}F!x31d| .__k5Ͼlx31W'OG?lHz+b5Z- x340031QH+)a`҅tk@ MM K2K֯wYC{ꗍ/-&Ng SS V,;uƏ?94Nzu%E /n,9y\_oGOH):lyx{i FFx31"[ /I?,xMU~ oSxʾ]=v}Sܢ)W9Q.OpK joo5T71;5-3'U//!7(nRY48]%$>#oPR4NPѮU ؤή/X.h!pg3Y0>qWƭg]M&0Lb*IL{[NrvMyNM~´Wb sEa N7'iY`h xFbF # l*xiB c F!NkIx4i#cD=k0xƴi=cDo{g*xkg,`on0QZ[A?81cCm.y2s2&2L2Hx{0Rㆩ̛W2c<[x`UJ*mk>t蹘B^NmK QrP9K;([}:ͭr߲EHm)]6'Y7S@'s<TsTVN=ȑ|XEMn+}zrJr:+|9+弼 & ߳Jf=Bͳ8y\ =cN&W>45t0+"TICqn$wܐ7Dd^U9/x}z5dJ:IBK04 4KֳJC0'%~2<I7sA0lS@E$#2zrsܫ$0o뼢*+b!T֤փ# PuP,;!vؐ cB*a-/')CkNřF6U E[a Oz,Bכ -f #_Gި胨_fauS<" :7w{KWcV/ޏoĬIRGbU36M֘q2ky9k̗q83+c?5GYx31"9 L9Q+5Oa%kl p_x ]+qKk䣡vkKxǺ!ir&cx31"ւk|g3U*]?G Nxʾ}&bgl؎YUYY&1яEXΗ<tx{qBȆ/Lз$)9k\oe9Ux;q(7d+%-JG:$g ]]z)Jm1x h2YV-!lLx;~}Fzf x31"o-OHFf 6Ϛ嫾H;x@40000 CGIuԈpvz2!ttC78Zx{q97Vb.O?\|j3 PxGÒca5ilP;g{Y5 _\Vgn,y! .8 }rrwW; c_# 'j Fu2!]![۷,Jl(.w0|w! 2,#xU{b\[,5â䡺X(/y (njV)|%Q_ [ژNlA3چ.N*Qy)IU7LZjwlF:0,.Xg2c1n* j깜+p$ۜmr`,¯L<>43%_eDJ{EJot>|DoGcC .p#gTtXοߵYG*Zr+z'|PB"zx{C2\F&gL">75W8e&Z9!9Ʊ@d +16ɪ:y D4%4)'u23d6ɾllU9)&.x31"uKRv>Y =c?pMW3| ]xʾ]=henCdhdM7Mgx31"7XԶ)pn= V g;x Z4`HU93;sxcc0Q17xs 8~w/H?y=}Ռ $x;ƾ}FE i Iy>.eV2h x31"M;n~y̒Ov&Ktx 9J0zo9xcmf`89q4& 'x31"NzΗ៶idgx F߂1HL۰@ ,x&}be|`I"bf(ym~x{kC FW-x31"t\7d)=" (x=2#}U)rk|G[jc_pZTmir+*t k 3$Fix!֎F3 >8 x31"F[>3޻,yⅎ ajG*&xʾ}&>R1Rug\ϩ{F'LSvxcmf`89RD. WTګk'4y=4& g~x[>}Lf x31"y;_gh>اqbՃ }1Dx F߂1HL۰@ x31"R+= 6ZGB__- 4x > 0r18Wsmbxp}be|`I"'00755 fullrpm64.sh:VyZ_/e>3a:l>t `7W}խ3N'40000 setup_backupGNh'\8re)>kxIJedM&M6!kx[̲qr&!x31"EI\I_JOeuxշ "xʾ}He_Vg' 'y9jr(hF i H%xxqfo+3jP x31"{6k.j+E}"<|x i`iz"G x] 1E|Ej!F;Kq? 1`0Ʉd.jv# sR}7">Ó2(qRtD2Q^0!`&ȣ`قLuE䟥jVJ2M=_W4ϡx31"OkZgK]OS.Tx Oܲ\R\Rlԓx31cap rqJ8V8Ȁ#,89HHmp#qp\ Gd8Z8 9u@Z̹8i9W@sh pc6sMp mp, !Ep ]p,n8~A8Q8qO4+X dz|9H_K/{Kf,7^+:yת>/_u'eC8.?u_^v;WLٽ zui)[V{Irsi̺U)`+^2ceW:Yuo|?IS[qˊW?W{SS3y7.ה}YՒOg,]oz4cϖ{='It?ӟYpx/vĻOtGSTvf<|扪^8{{ouMҲL>4=ڲjQߟGY"S>8qIn#޹噷nhS2jZ5fc[E=g*)==\8tV|yuS[\^,>SqӹϿUN',ibr5o+][e}&3RXK3|_fڼ,kV2^?wKV=uUW]2{k_r֌#k߱祮~?x>ґu'~tŮ[61O'O[8o͚.r?/zVۖN{-|@NǷ8j};6O-~Y#2{1Οbh|_|}Mo;~;yљ-7靛&|u^z ~|džOYױ*q?4|u#zM/+ʧ7L>ocoNy6/1h{ 'r6cՀW7|p蓉Z6mc_U5w-?u}Լ Zo}y(fO[;OoW>=>ZĤ)=#?ܝ\tS'yw{_eǮak']szwםh޻4⼘4͓nt\g~o/(Z]7^< ?ğ}hUk7?mwgy'{iOsŷzߊ?vO]v`UrO#?? KS6/߂._G}ě~tKv Ʒ%O)/WOuѣï7dnȿe :vlܞQ>tҲ4nzX}S5kk(}'xCX/51ؘ1g1?Tc4c(Qʿ(L5ig[R^RDc|]oc1_>Ș_p1-J;-J9(bo+3c̟FigZ2H2bQˊ(@cy13J9S,Ƽ=J1Ì.2]Q=Bc>)F8ۘOb=Gz1tc|E/Q7EoQK(Ye\TEɟhboQ/Qړer1h291XMf5x3Rۃ_룑|*/kJN\*>M|_#?8>1ڮ7g袶ǿW;r;"vRriv,=/"뽂#KCdW")g8bK&J9C|oEGOr5|Z~FyAι11F;_S=I-۩El8.wDO68y"/oim<۳eE$#FD7=$p;unϧ~}v~餖`iG:qs]"փY7qh㱉]gr^'6w :3_uؙ3Y#󷳝[ok6G'rhҍgr_ڸQ7OݡtLaԸO5;2O=u]a~ÃZ.W:Ѯ.ϋor~muh+A{;ʷ{EӦ\N"Cof{hҕߟ8#vǰ("=s̷ͪͬ\Lb?Ѝb'ݸ&]9kŽ;2W ::JΏ=mq9Z?6_s:'=#˿9_W\U'SYr[0:w^yt _Wwv*_zMW~+e?Njt6Nuvu@Gtʫk{;9kd4?}"=ը;cF~fi~U'uYߗFYi&r֏E7^swq߬MCrku O/Ųj:E[=ZN܏~m@g>CH~J/=#r<5r)&]9vo ۧ?xQsuo>ُ=ǻ]99y?kT_DsS:I7.)ίvyĴ"v'[oogXtYG:>_[_녀8lo]H7.hq޷i͏wx`6w&w9;n\~iGtiHLuhn}w2fqgэ| Cpď tiU>j}ѵ`|eH6z.<dG u:ECVg`v;4 "d2Q]ӛ9 l׆h$JL7C<N8UnBX9*(dFz,`b^}8CUV=(|<kN$үd8F9 &pzG|X۫.Ҵ@mv8 ǮrT-]Qc_ :XSi:*+s*CȖ@W;%L7uPĐ+auk Gpu 3ϩMle. rCӭj y2Ǐ>.0cBAq9ct?=Flp<(O8Do F1C (L^"r;w!3!CWUUQ Snozhї!/wc…T 5[miU ?+.v2#ۿ:Chcj K0 :<WWNw_ -آtRy#Rw 2K]0vT Vb GDco"|xnM ^\&mi nvyfD! !ôQ$U01rQ1rwZ4-t\W } 6'w9LR'tI]  X=!ܱ`ma#!L{|Ehi*i+gT25B*o[% ^S28u 9T|4T*tD:P/qpe(Z 2X̠NlڋS99~:j1ƖK p}οڞ#>X[xs!3y Ps.f"SF"6t .a7n@A[r*,/>dч wjQ@~JaX.fdˆuphya|& VpanFML\r21ȩ/p  3 EL>4G%:Q0?11S^61W@Pe4XQJU_ y8ӽ^Q%TҠOutoNZǪjuxC'Ҁ __˝a̒ZS(l'xanUL529h&+ECô]p(2|ޡpri<wGpaYJW[aV}'Myx_nSŖFOeu-H/q) z7~02ZN^[Nk-"^c Fچ!D.GYXh4Yƃ!HpF.J":+Ut#E>%-k䕌_1?Ւ缡 Ĝpǔd] ,JFys(pewXa#%mo08d*hMHr!?m&1mTvȸ,ᗍ:%YiշrA!UQ/T8}oж19*qz.Q+W2bI6[ԑ~ P ƱVM,/VC6$^&6U o :l;Bg*2 \^Yxr2/(Pb*sua5fvQCBc/EhLŢ560bvJqfe6 CU3Os\!)sW8UK̩/s:=_>2h;s`lND!*0mCY5PrDhdPH#jlk#RLڮ\ 7[jc;9V(C\[ #ӆHmcS\.Ę9 {:V9huH]P:,DXR))To(JȢN}X*Y,QqxZ\~0'iBO{Z!Nj;adU%jl|Se/ <=CVk.^||"92vV+»Rdoۡ拉 }$,e;ʍC TH=nC;;S5򍬠p=A9i 'V :t{f8NՃpi*lt TE[n!G9rG}x h"\XF";P!Cebpen%=9 * C %WPHƆ>/,,vLsNIV>_/8 ]S|_]I -Ծ.Q]] ]onlK"SeTj0(TySPRF[Z\m}{PݕڃfVpBe Uj5bb aR(mSV)!U %ۅ@TE2*3p:iBQ9p:p9yrzFNaA*=y2d~R4Nt+'QąNIT'NE0yg9TBw♓%iUb舉^KDŽ1#ˍyǵthM(5-(Wj%51:btiYV_1:"ۤ2.z K u' L;">NXkGeʍֱnK \2\>3>sOV`<9\x5^nh_7ϊU=\'߼䦩;v0+?5{|$%v((/F%Eߞd~zlzy?~:pf_*xBQ= "o|@DMwm^?&^׾ok "Y^%GK b["s'r-AV]$e;?V/qE ?z}o KiOG+Dx+/x;o7~(h(5|@]qo|'7 5Im@G =#7 :Ao $$ 6 ~ ^EVQ~v%wôb|(gE"'T #_-F ~W /SD xW ^F*5Y oo6 -=/ J|P&L=N&E$ ,x[}-Iڿ?E6?IڿiH#ER/=JՂ[#a_$E9~' ~|H/x(F.x&mr~"PE6?&໋rN7 ~͂_"A"3E4%xsE96-W/|'%j; PX (F=.[$# 7 <Zڿ/Y;;'ߑ6 #?I7 ,墜M?[c"MgK/i"d_! _*D~ ZD957 ~/_o ~-_+(_#sVQv$&)(gEf|Pn &_"$K H&?*7 Xڿ ('M *r F HZڿՂX5/,"_L DQJ7iDF> .o|XAO_H|(G9'̯toI׉#xM_*_& RN .ł,_$xK"x Z~ȿH ~ ~?Bڿ*5_$v|GO Y/?\o|I=^?t $v' >MڿH|_.O JJ, H3E9+{o|_# /)/|?]ڿ_-T." qYIݢc/rn%oCIYWȟ&o|(&ۥ (gO?F/|=FՂ/ ~KX .Jo8x^o|//oբ&{E9ȯ'_O|n|͂ϑ_/gG2QMoPQdD"_$'ՂL5EH{ Vڿ_4 >K( ~w˥=;?C"9aS5fd7Sd@%4ݵwEZ "Gi- e AZj!|1>"j)"1>jޅʹX @(Z,7"G-fk~KՁjĸ'M$?O# /Aܝ'|'I~·!>'<$?a/H~3M8'| sH~y{G#>'<=I~©' _ވ$?/ wGܛ'$?X$?7'|q/& @ܗ'q?.ėw OވxOx-KI~/!H^2wr)$?%SI~w"D `$?ᙈ OC'| I~yG#~'aďS?Jc$7{ ~' pWOc?I>>S$?#& ?$?W"^Eޅx5OxgH~?K^9K' F3?Fr/ ~'|'I~·!~'<I~^įg"~'< 5_' !^K p7I~#ENE'| $O$?7#HxO8f񹀷 J6I~{MޅxOx$?ፈ! E.O%W#~?B'$?%wD'|I~D"'<'$?iA)O8^hH~?# @9O8$?K'GLKpwH~]EE|'|$?#! O Ox/.ߒw n% oD|'w$?O^qOx9I~K! ߉'m& C?QLĿ!>F$?'|3H~I">'<$?iH~ >'Ox4sI~# @ܓ'|%{Q#6{ 'qopWc'|O>$?o_L>/Ox/~$?]/!|SڃmmVŶmC%*;`ߏ{` ͊maD[`~7Vu>f2^Tycɡmm6![56|Oe^YԬI}@{`kpM}{&Rߊ^0z}mKX EvdP`7?nC fkVeC!·m wx@$NͶ e@MӵڠʗxaS0b@mMQ>f~۶6[W!ngVVG gpk0#ۓ[W|Vwmr0w[]YrTwk|PRyXX)݁Jٵ* ~Ydz[S mK4Sr=h[\=Zm]u/=PncJ`.ٶle] v?>]Cd,9)$ 2ݤ{Fu dGE`t%jUS8:-f[}[ 8%Iw.w__:!=m[Ưlugtdln̄nuݴIjg奅 gl:I0+Jةs]Ar2X9ndBD0{_ tnrLiRlLpm8+M{FAlh^)o>&nra->N,muB柵>W]7TqS[}*ߡt̆C?=n'?.'ݦX57G^?x{GM7W߂Ln~#o88%~xx-:IC[b)C Gp N+롼ɧ9 E-982u o{5]HfHr,4ec2%q?ܞI?'OH/9!v \pܺPDרo&7qnm}k0 *H )Gs-dYfS*BmN }U-7*ʭ0VnI7V[co݂tzqUϥ׿<.ç(yBm\1 LO4}!xOZAHz8jԃ8@JM6T5P3ް yp-td`l983i>`b}~_Okiۊ}WH/nA[o+?w}^ݟ:$X Ym 'L?ߺ;suצ_~}z!̣"rˣ"psq":֏{)hd4ϧr4תeAIr7d Cmϸ^nBmp<0[)`z39 ?%NӃtDž/^>M^j a>1nйgAՠ5A[݂d|98сmdq]Ѓإmpv'qE)fr/JV?BezX0d8}>w?9c`)_!' ;ŭj8^n}ѼЗrN ؊{y})RFo\ėB|ݛl F{}w,bdY≞SbUȲ`_:A7kn~mJf0h[`a„T+Ufև%F-Wj,ћt!P di5~m=}Qxqj oЖCD?KV?JwVmK·F-?_피 θa\ьu"TiP|JD^FUM6za qL'ZYz ¶cAFKDP ś0F0^uAuء)P:ҾPPI0/([ܬqkAJj%M|~Qm.WYg pY,YqlEH,AD-k6߇sJhe u .ipk J0@ekz:OLxq7Pd Χ k,K\kډ޽AtnMg7X!ge3B jP5~#j -[_Pr~~6~`~2?d?/ JM`dupa2o,@|O@E#d.B4w̧  p4_2<ҺsքWwjyxߙۑt"L8' II+WO ޟj--r^+=p`'*<Eh,r(D45ݟ> &L\yozx KWh c/s~ VCᾄ+gg?Ĩ'ǠB8C- bLaU.* } ~Pnݏd>~ȭ+KIjiwFGm aT@C%\WI dS 4[qJB͕3,9m9uB ڿ1 D3WDʺn oub&bֶ~ ΋)yy%oKNZ̩B, xX>&?, oTkH*7{;0*0aeI}KPo-I]TUCz=Z;M\2Eծ2qK@Uv48KąK/:vin> 0Gl&cjwn3 Br9_cdG?SG)a >0i=vAp'_Ptá)%4s퉜Bѡ[DSCe-@ua谭44;l>A?60%WK,%𑁑5E-9U-Ye\dq'g:ʯdm#6q t'%[16+M~yfKI*^@ Abn| gjy/ϕ[Se4P v/~ M>=ۇxމB gBOf-Ʉ0v!P{X&w w\Q,AxrN Nj<̦WhlYJC5P_CQ!>=a n0T/,{zq^QOa1jL/1(nP71=v o5}1ЅbtӉmۂxS(f]$ym V{VK]8;>Uހk=[wBoօvh6;6_|Xx f]>C^cR;.I+!\=6tҀ{C|4'jZ~I\PK#mI )j= ,G(hoNy;;%6dkc}%LGhzgwD*\wrXA0s`F'7֠G?g?ZLQd wUyBWu/VX?M^[$JPOc.T &jy'kndMQ}jgJ_Ct3ۃxl]` a)9:7]P蠣ܺ& =!0ӟ[_r2UBhAWBn[/ޮY늙6tTH.og^;~tvj:e?>OT/2Nz[D_M]_?A?Ҷ-1-eWpBˢuMUC8 ݦ9j{|} *=U==][=СǼo(Wm~[?ÞCGB]T'tz-'y{=?3O|+=ߤ{v=7)z4jwMkpc9A| ${~6;|mZm=Gݴ@uz~w {c=ߠj;|߭ZϟI3={g='Gpc9'I;{&$d+|ڪM>[nvt\ Iމ=c>o8AW0B}>?(ïތ׶/Ym3ַ87wsu~[|kNB:Q'Or=b{GG&~|}fdZ!|!rmT6.߬=rk wTԛ *7m{ڃ()!8 _z@M q32]mYfrݻFBڒ׮IpPMq8kMY{z[og;ZimleeY<7{O8U -Ζt:p,]7&?}?ґPxS/ u?j+ ?9/%5y%}[=֫/Nv?/T??Q߹z bd;SۺCe M` fIM"?LחE>= [\=%˒wmR~P7dYRF lys໯u0J⩶_Z'χ6kcaX߁PmuMغRߟPya(w4w4*?mja;~玦 c}X:i؈7:`Ay"˻c`}["Q~+i< kpe{Sumn= ?}Z{=wvuw-.";-ޥ4 S\Ñ;yPКVqҨc?Cўq]}<L.:ue{Gm/XVb|#6\2'Hnȩ;jG\N'WKهv[wL%_Lį")\wgxu}+紪&T0=2<+5goN1X,T>魤kZS͚:p7}7#~ ~q~Y~A~R~#~~N18.*8OWD~׺џRrNQ&NWCjj 5m[EI55=N\)N>e6\^jjL߲qjzvq={Y. ܎nkc96q)˧iWZ5yvr \˷2oנWWV3z{Uu _h_Yo#lfZl'|=Œ.r=[>2hNuQQ9-OR<{|Οj~_P_+E?.pؑߡ2΋_؅_J7 Jt%w.gsz\>փ_5~\;9oO/FrKҹJY>*99'r6> ~`NǕueBH7JI+W˃s*Z4?!^u#?Fh{ J>|nJ?4Y2*.Ck>Ţ\~S6(i87ғ&f3.}f+};5?te~^֮kuQ¶>uɤ呺t Nf/?G`M>˫COSի٠vc:W u_6O䟮\!y MoAcfi6W!.ڦWh2k6/ZY^bTC߰\n^.߃0 Jxޭm+3\rByjra|OhkOMKŁJ1S>V¿'m<2RjzVMjMڵc >s/^NV^)jx=c r9 ,5>?k8mq~NFm=̼YW˯7p62n9YXS/링Zzk_f|3ѬW+i3Q[??)gYYm7kvP8_#âV h Zz?;,w rz&~MchkXmۤ+nؾl/mqO-Z_zhfަVX?~[ڵvpLpX\ ۃ̩BMx~pV_ ]ھ&fOϮ-6jH͞4; ̼m~ߵz6]r9vO)&*o=#h q<8r5qd9ۇۥO \^)';Ndj~?{*9qۿ8˭*978uiu{NP p3k Bi#;mo6Bi56Ai3AH UH>~h!@FH mKTǙ1yJLsn]cZ=VӪvyOxx87Vv, # 'x=wч_]W<<{橦ɧ&KuFcw (3@==π_<舒~jRfm\֩SJ@A}W? IOu۷U$:33yԓK!`9bVP*PpDrx欵';JZk)`?j:9ۭ Z&hyRҸv߽aoQܡeZ͍E=vi^y$W{}s$h:{tYђZ9e\)'jx~gY{~5Sg`x)o?aA$8brEˊ־]i,?ys"_Ϛ = Oq[je->Z0|Ģ<_C|U'WTZUHݪ_ZN^o wXYFǸOd_2|^lQ 803S bB3~frU~%OXXTjf&:Zƿ3,QV]b< e>=SVb^"'>S'^XB0vߟ{/{~ bxwڪu3yoy\g_'#:!g_[X/Z^9fYh˱-mZ+~v| [Y9cyGE Gsٹ\YXxMoieͼo;RװҲ޴?97j^'gӨ'x{O0@城c#˽=X.,XKV=v]za4(>%16_/FrcWS:/n\#/s9_˹rLy)G2eʝe 2J嫌K{7?WX)UU727jRRep+H:^|x Ǐ/Q(U>DTyrIR%8篗'J9bz+O+ֱYQLT(++g#oR/VWgCߜ[] u\A~2>RܚBrW.?UV5W3KQnUϕ3o%OhAާʕ?Ȓ'˕%֥*?X}ei<,l2Uy/>__]r +~b;TQzzjxq__x{Iթ22g% M2\zLyowVLjKe+x9C*Pf&\e6*B_s׿QnFg >ur*%>>~zzg~Jr*BTrPZB*\EsK8'^|x]VRnhy[V*J.DTVW*Os.V_ݤ+|D&TMʫ%ÛK9ӥϗ٤{MonT9K)弜W^|u:_̮VPQ=2<5+\q-}35Zvs+2\?򥿰tbH3^&,AB%u 7p%%@KI_S DAyz=2::: :: :zt AkA[@@{A@@A'A@Ag@ς΃`t3h-h hh/8$4 YyTnm= :Zu ͠-]Cc㠓SӠ3gAA NV tt ttt tt,("&Ir1>6r}"|wyܿ@%'Nr5,r?ϧγAp kF,/9f8`2gUt˸Lq{"b y{Nx>/$GɴP1?#~e\+,7Gı2O~>//=N/~*'Bt~EB1οY?}+'s :gOZh0S9M$R90̓O JOtY?)?~Yc/yWp(:Fʇ_uR?0eMrq|bϑg77QVZ̰%?_I/;.Jp',׭\'G`tW.w!PԦgq <7mgx^~]4j3⅖y<+{b_F|EZi}mċz؈JW#^֛F$xiZ2idWG)kM{#.=<501?V*א~._)AWh5{n2rU >(p9OGPΙl-h=whx6yMg/O\_s}<_mY#ʑ/9rXN<^p }`xo'[#=8/1m~_+c }==Hy ' r4+Q.J`Gy,iW4\#5'WxhGV*fh?7?Gِrq/bߔo]Q ? GpS 'Tџs_4˷vNs"GVEstiSoAYPQ9!忣P|ߖ<#?E˃b(_ǓmEu[D#Yb]Nxw~+9o)K(_qs|RQ|lgR9O,n?FsNi_x$I`Di? |r[/S yNL~N/&+Ÿɸ?b_-]!쵌kybf_"+ qm̯l_#_F}y7~+E{yE>"W?C/s'}{?l)ϒz?{A?psU&ዲ=4C x=GϑpM[, /(˹O</Q|5AޯYY/ʑi ~y\RsB{RRNp? ObhץrgJDR~./ü#~R;KeyLȡ|7ϑyTVH?MD9+߀rҷ#r;ϐ򗭆_Gھ}yDcC(GF'W[ E~|br+P]\QamwVW)g|@F":ʙ r,ǜuW x:|? )Ub\O\-!ruzAO /I|{nn%m_)?# 7o gd/ل%%x&M} ?lc%1R8*a7I9+>K|r>e7^d^Iw|x?mSWl鋐! 򫪬*/wu'H9@9}IrЫO?rFb*v_ 9!?|#KV-1^L$;Y8.8o &T˄gO~=x@quS=G ~1 =[2 ~)4>?#AI_&_/$g/&-7/+eC> r _\#A"λrB>J#q _$J\67RΥo7 'ކz!r~=9R﫲+1I\Y}%x%oR+ĕNM?A;GOP "uq] OU 붔QR߀#%5x^Wq@/C5ZkYkh,7iSm6?M֗//*? hN:9dNa\$~κm|6~UȏzrG# $mkv`ݖ3lS(GSH9r>gī+ >r96;qy=)7]ew]۳Jy[8~gئcWï%㔇l \'Z~^y x5/R0OG!YNk7@>~'E:]k?^Iʙ~6-AN ^g]밞X-:o/&e;l~ iO d>Goú>J_Ӏvu=r= nnlFMxIʿѺ/6Z)/&8G͐"WW5[?|=/ߗe:IOu#?O27䄔|a' ~Wȼr {}->j釼3[nc~}HS.)g\oĿ)e )xom[B?ARΒVW>[˿()'>A?I?M;!r_ОB޷ZI?ܼ di?9@$ET Rzdjw[7ww{;:~v6\Yw"@įGwh#T(vzGUCGGe=n=F~ғ%g@㊿uw[Sn_t4'BTL#Po`02Tn;p86rT88Y=3ܽ^k iU4a@8&=.k; $b7%&6X$t43mzY١5%FN%I1‘P5_EĂ!Om[<^G N~Y+TmumQ W^")Ie%tzv;3 %SpX#Pg߱c} "]{#6t#cǙnZ*cbH}W=D8ڗ#4ohhmjfm5cO!=}t@FݱP$Ě'6#'NW &3'}:wϨǮn"}|nf楿5uGtDb>W H0H/%]SXD$g5&ͩDIz٦bݱ@O wo$;|Ƹ1lM9!SB:;bzmLG=dneuG?SMddtO7ȴ{wKzBɤh{;,7}Y;"& a*afGw1%ǿ1 :?ݤcH{}v޳|WucC%3zzWpw,\k1(,JPYPIeT+z(WLxR;`$ppݨw@Jt`{[y ; 'ce@""*!Rx O#EUHXw(rkVv]M; t"M7Sf_rl(5?1)_LuX#:w|m["zl%Bn#aVآnn,lo S§7ӥU/@#t?gFn].BkkO1F=Fm͢ju@8(s\N&̓u T$ZP;2O &LfL7FaEFZ0Q.Ns'3g/SxYVsM&=Qk4ΌԚen_3_90&Y[u5p 3KP̴xF`Zx[ku7ۨƔ^ wPZYP:d&:lm70$U<.oe0'^c-+,F(p9P&_&JzzN$S,=dn~z[^ @o?Y33n}CVlLc2> 3N}()zJz%b,byc o&IvPɼ9v(;&%yjQ9NsyOWݻm[vb~eEכּFhOc'JH M957FZy+Ap VD~167mՎ@z=G{XPfISlD7NDS>I;K`2F}ϧ M-w=u©oĒ!FWPV) %7hiWIڧIQ&_# ųLTe{󊶡JЉp`*dJHV[R>2g~ $G:tU&;"} kx}^/ƮLBZ "4{T4_ȐR,58ܚ` b,IwGJDRJ4^ݻ -[(Y' $ɖ6Hiљ&ϙѭ &[Z6Ib+UDM{ lkޝC>=7b[U_.:p]Rg",+( kvBYtե8_@1T/:Xέ̔8Dfw?:o9~h&$/#U%+Rlol>.}̍s,n@RVٕ^ȦkIiȾj :lR.fբ錥oZ0;kxXt|`{_p9`$S:MH Y2WJV]fIYdJ2].aiKIHjRVXϡVW~7Awg6ŗ7P]X9#́(,j[1Z`c^}˅pM$͓ẏ'<˿7 9.!`.Z$k̆8ڞ!eH՛E7_~?54`|n 2j!TQ[qVU΋l^d $&0\pbbN,: =-d|:Yd$&AvLZ]v-݆lP.ձ5Rr,j '0D@siJ7RaHశo^262YR#ɴ*A]~oK.wC H-&nTn-,W nV ;e/D,%[q 4&5B0EYUµYt"!}hI5GB辸={M:;w{wy$gl ~Ok2- e]]$ecƆȴMlڬ邖:]4 [LEkE ~ ]vP(_C8bH|޽A:sBH?sͣ6m=ĆqYn 1A +jQ8 jwh;w@"wh%]C ĭN a1i~X͞C!k3[42B}Ok[;LM-Ok$mSRS>mXﶉ-֚}5)ȬZ;/{hgQYMzF1 Тt;> Cl84tČ^"r0fQ1a,!aZf!듃d9x[\%HMF$KC/Rθb뉶zG* 吞wD}[ v4Ol 6~և{9z[kYm kn,5=y,GR>:ci}6gc4g1,yǻ1g.@2%QX:Nw\a[ń;Z)o46\J/-P(ZV@ Xe@j'sVXBdzmZuiroiȦm\u,X6wW{t.Zf#:gϦ":0bfi͸mx]p#llnŚ0p07B36zظ0Y[^laH)cg_̔`F-vaW }!6,^vzWA3r6'z6ͬU6ch& d&;ŔUtEtKh=,w7[Vx:Ym4--DzmQy!{/ܨ"9/mc`03T2E昇l!wS>kEe]Ou6SSXvٹˬWLAwsO7F6Ft}|&-e?z K[#Nɭe' ^^ $mȐVGl-Nm؉J7̅X3=σ,c%ј⛐xYGdGzDç)A Xfl惮_g^̫j !9 %/6c}`}={{CE֯dk{*mY?x31$3/%zKϺwrr՜x340075UL*ON,I+gpzKz<ז-;7湞x}}|e$M@),hԨa-EVD&HkEYD44ɤ-X6-a{׻^ˮܕuTe~L)bEPVᜫ uQzњ J,Dx3d0fd)%/5'AEF ,\-WDNMQ6УSREŏTx.*rYZ TV/dng]ےYG M.0Oa:Njbtdt3_YkV[ʹ"8 mVGJ;T4+Na,ҫ[UtB8$]7a4 3<45igwk?C9Lޕ2~үȐwx?7V)-T?ߢș"Qe>i\o%_C *&JS;)SnZoϣ2~w7ꁟ1H(?s!qTfZ*HQʩ~vNd^R^%2#QWHTN~Aڎ{(}?A#֫̍J-)O._)~w?*㿢Sd i3 /;co#W#' ĿG'@'H' /#<~?x>_A'b' ~C| _I'_E' į& k~G:b?G#n!\Tb?q}b? ~='/ Cħ ~ ?~D|:{O o&_ xBO_ >O'O!>O">OJ'xۈb?/%|1 ~Cb?C'I\53nA%K,lS䃨`ŏuz6:(266 3#lpMeB`:hlڎuX1c4k|>`=p=pߺ^ߜWPBP@T\9r ~2+. r0ؖ/{f)[iĽ5xseK,F[va*6[tX8xx\ n˾/iz >3P|)z,Y;Ы*~2&S"^{M:HLWݯ@3^;KU'-?ى t{ѭZ<壙yN Boelg0A1(O0gt1UJ.P@twD\yFH߁ zC̎ݢsJf_8BInȢ*cx1b3#Ibf=UPH믺BZҝ~g9Iϧz̧~OOOGWC!qpP:>,`J*^~*R|._-WA~SmKQ=l^S9[NruZg9[NۡSNbv[+NX^v%~߫iNZ\+vzOvr=e<( d8p"9į`pB;yolJ vœm׫0so:C.9'4UudX}x0߹Tsh!n`t0W|y{+v;׾Ң^yƼp+qYSNH5 J]zp8c;6"vaM7tq AL>c53Xٴ (VXe-yݯV1%deT܍@I8(f$C &r՗:oO6T?#ުU"sSG@g;7ZłwO[by-}X^dߚ: =#M`cp)c?̯ě`%]]f|#Tpgb@Op6?F!J$X$H@L>=`7NY4@٘\3e+/XQN^#rAP W|pq)^ `aL}t4RZHfE$I ]">\A3/MiAޣq_@ldҽ0ɭ:S9'L@ϝ!24AVȈN `fFn[K0` `8q"RDW(*ev}%'"_0ZB0JOVޮ795 `2eZSNQ9l0_tI%Ѹδa` 7 mԐ9{{2|YfNK3i# ]n}Դm DO`|tn6 'αA(s#I2M(['vAn=IڑK4h=.(1zi;#yXiK\ &Znh=rFNɾiV4X3X:K縊 M]Q:dAOʱ{h?\ yw=?Rfcc`H֜+L ipiYgz;vt `c$5zZ t|Ҁau8Jc%|\I X\`ל5uSbϼؘ;9Ǜ6ulPiïI>NюIL:6%L+dO붊ƒX_g5mWozn5z>e[h7mf7=w[h1uJ0ݹ"k=7d=;h$xs I`ME.X1IM7' RT gr #yPjgٌ:vG\hFn?䚾ݓΰ70ŇM 1C,6DqNtCb)~"m<Ϗ-6!F;i'A<*.6S*ďXcR)}&6N4_)G aY <:! m"O1!sOp$~ʀg; <Owʡə>ܕ!r:L+/7L? K>Qg t$PĿwˈ~h@B?@6d X,7`?5Q#YYѕ<}dE8pP0*0^27t}qi}f$ y2皌w^@wVTiUjU[ug ͱbS%Xg1:cL{Y^'hY$Cz]sĿ:,7`aN0DKJT䮱$ĥ'?&˅6Epz$;r9ZYQx{| q@ZI!d V KII[e.oL榿M'+sS؏%ZQXy[>|p9+dzdxL uyc;:k&tP\h,|_>"qp=={ťP9ӂ|;>!㕸&4\9.`e0.FxV`sgΘ G|s/' 9ᰮ3XLlze/Ѫ;nLc{3}ٌ+Ys…SU{ [`|g=!,Z%'G]x?d'ޥ%8 cGKACE=ra} FOWDd1̮̆p"zё\'W r)u#u3NpNjه(yC<#YrIL-Af/% cbleľG#f@ȐҤ>RG3mBPyH·#=O6fg~箈جQHqOdIy G`C)ŏ҉!YbBF76Ι5gM * 3mqeCoud#eczV,9gޏkZ,55k~M7Xp/=~e2_kȓC$ #ecE8ɨ6 p5،n'x{lcx+~o-wp~h_3?}xV|s,l ֔˴rI$%БխϘVӶ:X}W)Bϐ>;S)#4JϘɻ}] ^BSs6ɣ]%~gs+ڡ;hnοe5~g $SG&jX/f +(tt<~+cҋAaX"ǡ:K>̔mϥWޗ]nߑmZÂW6lRbM [&Zc{즪o<耺״,X#& pO`g)]69fŸ:/fߢ-b0/5mU0UG Aoi@œN$A$U*E{L4u<DZrL',>eœe=֙:YZB̚'ɀy˜:"qidR=}5A<65qڱkvu#Dɝ'zVob߀!6n=73G\4!Tfb6SI%_i&]Mb6b;D -ȁDr>F?}W~oB86Ώ)\督[oZ{VǰĿkbu3h))YBO62ʪ|Q͠y PlY!^}Km`IMxEՠZMp ,qu/r?>pF!ڔH{]ӭ,.<ߢFYq)& a$@ӡνO2gQ1x '퇌}mI/ݩR@"οb?4 L*z*ȣ@IL䁎k+\|%HҬwQ>8cFYʥȇ?>Df1q[K!a @x1-2[g ytq\ ocL/2doMfydZc@/UBr ]= evy;i\`+%,KTR䗑^3IyRvB๲`ﱑ#$Vz%!dG:Y:pHHDiHюdaR;ێ}({5qOt - ݤʞ(nW &\L!.^SA/GS,PQw`9k@Wt5M3`vݗw^X<`l=(82ӃP)1z Fs=j:bpۤV׶g˧I0/䐈̔ 9t>@8)pʛsWsiӤX7rG%2V(0n![vTQoޖSK,8H/Lt_/g#8/r&7lt()m zx4zBw[GqJ<&0?<:q0يHvسr<*D͑:)"V 8(LvQ7ɸOO2Le[2ôYY+|p΍륷['[}h_"=i9mAR';Vp+xw!PG.S?)ڛYTGg#oJx-60OF?8"3Z" e ,̅~%gfM7e?Ͼqf}9z-E՟Up,MH0*!W=D ,Vx!Lߛr3,J3c 7c7z vt[:R֜Ok1Hfi^'S)dAoIԙu>xR]C 㖊JugѺ7];~uU剺>Fqwj{ؙ_7p`Ċ_w㍔ؿ/^x5gVA>wnO;~=gMC ogӾ NˤnjrjҌf==4*{B{Ğq {YIIs'2#4)Qֹ1FQyJoL"uQaLk%a9zWb?&aBeʥ3tVuC|܂Sb&^D))Aҳ[{7G|\ZKx@W4aYJ>p #'5R8ۙopD{tӮr9 yl`W,mwNVgw;pϣ$.2$i~^JtU5os'06qg.~WV];>m"9^-_fw5c-y4܇xCȶVċߑՑ/dM`T:XK/zҋSB'$eB -Yq{S[+%sv]xZ:7 3[Xޯ t%?YWSD7g̍w^(_C7y^ IC8}:Ɂ+6r.~(J >s#MUnV=_ϵ҇'#`'s:~c /H=;1+I|w^= \/!x3)|%/@N~]4_o+!  0p)8>]8ހ58}p W} O> z8:X YN% v8)[O17pdWp~ .(OmI8J88pxXB:S3ᘮg)pLc 8.P՛0in@G \2a_Co2m>쩅jsIMf!hn!K$i7J??(Tsjx3WmPɗ䯲R h0jN5{! <5 0LL]Z>hF? "\;$;|Bf=^U!s#6|!ޏU |`A0CM$, #!g65ϰ2z`uh:)kN|lPf|LOhL#F:Q%4As/!#غOqsnnG+כ 31ګ{S]0'YUk+_OoWq16y<fj"Л]ЈJ(+q yZPũE3ݞ70 sIf& u|_|U =TSV븯n{ a{6DaO櫭U({t 䲕E3Gy.u-'ޑ;c/"EJU%19)=-[ oR1zx7ymKzw? bi7@?N`CNјܞ ][nl#+xK&\V璒x {yQѹƹ9\Z%p<ɻfD " $׋u3yw^yn|ۆ\-f(-ϴͲ斔G5z[n5ʕY])nw9 FdO؇41~ @o.<f5]rUkU1ܥ?~C^T.5yW6c k3[uKYz'pr=^G-W 6b{zE{ p#vk=1 3OWg&7*YLHXA!lG:3bzkkf58sFes {^#ˇ>vYJ tE5kXŇ[|V`SFcnhA3X1&J*k}sIE0#H`%OҷVVFA<2l_vu<>{nTx@"af4 C.c^ڟ$1An#A@' #LѹyVq|27OsTk WwVF.Dyh BD`w۱iän];k*]S@N^C +BÐ,Z7юK"(߯PN;rk2~$TK&yc  ;=e?²SxU3Kob_@LvcIGl_ =Eminc{h{ߝ_XwͷvoK \rnQ[c'X)rC]?Ϸ:ӥogܮQN 6s%ɇ@^ WFOzՙAN_:(3d6?/>qI+=ʻ%*X*Sޭ9/^DqQPb\.Nq/׿N.>(|^0:* )j 0@* 7PK G. Q>)Ha.uURx'>HaUn]} OSx\R(,N )|(@/)(j`"mC>Mv.ąX \AaK׃HNK0Ig0|-dk 4 4Z3k_C3r.T+dfB&^?#a!5ZWzЈΔs\wOp8߈ gy}yɅ"ɛ5q4كmɜAES $X>o n4pFZxvKs>53}f;6TsM9#NSj(\xȾHӠkz|(О6f|/6 V͑z= g#7F9}~mpj $ Ml twv C#r"Lgl˛%ƶw7^ ?|!&_@僜"S@J,hX,hN? r+pBR\U|7F l:TC8fnMג XBzNKx0l盂pk`>w{U)aeFZisya -;f*mNNжD`<5 N>̭zwfz3j# MU6$#3U[5%P\% kȴqPFΐ##U\fLZ\/s4LkAA2lWm> 8͜ A-! 5 VsM>mSjgDU6sl58?qfyNU CLklSײBڼ&{ L's80Y]n\5G83$-aܮ5Sz|Ops5N3$D} ̨ .GpZYlҸ  `?L#nw8fIfu&@ yX"Gr@-55p.w7~a8ԕj}h)ȵ-59mV0H-Ē8#B#Y۞;p|f'X6ry<يZ|O+^z/jS{ȧ-q:|]# .q8!q}Czq]K[E]$4Q2m+>ĻR#{.53 fŅF€O=r,U4 -;s>O{=V@aLoNh+ymy/d^ҽ>^0Wkٷxs# b}M\}欴n7TV/fY3n\Z~Sq4) /ozBHY ( Ha}0kLgyJPWF\p 7}5Boo' CAg[ F7ĘB B<䆋XeBY %P{P _rE0m}Z7LtВoH׳xP) y2HWjߧϣ4ߑRL˛ϟ9\gE|;wb)+7z+iWєs|CS'!=A) )f /9E/JoJR8&V+Y?ӔW)."2|>sQi7B`3kw KH[tCbz0?'sy7>&Ocy2tS"%V}\"%'L2{L0sDO_3w+xgG!ϹO!eBB ZooJA~|BmTN$1iS #zRmwz_MC?~;ؾJ" 7>Se|#`ruSOU>骖qWEd*)]FڐK(+ OyՔQOu]e2>B)v~KC{:9S'%ǧ:>z0+DǯoEoTQWy~xwS(3>@([i4a˹25mP.~fwqn*_@OCoOCi3^'o)tC4rΥ6re\mTJ7Ӆ50Qz;ͫXN'h(E4Pzax}VPnZiwS9]4FoQz]21iB:Gg|S?H#) =4-iTMx!Ja4 YCYo4NS4J/!'(}fR^Oxwo~گWQz2IS RIϤTx>Pp|OJ.K'fxkT6^fbBo^;ko@hd:WԮP;}uJ?gps~)p.$0"^oqluw/p9u.`$lMxȎ1z#?/[o . Ei45-WꩨYsX*VVB [f0V/ýqa TfaqwUx̙3IztKX̻B/ |bjI 3%W1VRʼnv^!Rr t]nu;Ug-wV'.mJQPmrd޲JQ8p#/A'. Z7ތ Ԁ* *F,nB[MƧߛ0Kܗ@A 4u(njNfiE|)I!ݒuTM@JK-#s&./]%nvPe}Pw#^FZ_7F=nAWEB$&ޕ[BgfC&jP+m ><\S߅@/}B6b lϫc%i^sCXE~O P(B4Ror7/EY3p.nqrՇt8:|\j|FD)z &D Q|0aS5[ [ɽp\PR5}y[C>Otaœ.@j3u<'gC!r .z\xuZ XT.,"7+" <%B@\(*>BEc(64hZV$Nb6oMMC44Q/M FĈF jϙ;B=Ǚ93sfc9"͞!%R!W h+xm2FBR.OE_';4,Mr+w;\x=s (cX)>z<`q3-~_kQm#qyɐqr_/iSsLeW\͂%+)6]Fi5)m4!]wm!42R_g1|,eA:4rB).)h.L3e)QN]kY>̮ӌ;E+X:AmP1-7G)8ճ]cT*ě,!@1XE gU Qlc9Obs%䮃@rE]1zuI$CK4Bmr,Yn<(W^dNgcC"ћ.!+?o'(ۆzUq|*Ǜ9>>)E4\]?r| q s-7-p89r|OxFL%ts9s0q=;q?\\9>q|$'r|OeA 0p|p+q|,FrǗq|Ǘs|8>9>B1('}:p{x{sPy5q^ xBLX+\!L-ĸAX)6-(>hD-F-P܀q˳Pb,)F~Iv-z"Fk8Qb#w-ů!FkU(^xſCL-@".#vx6b73%p'"8a(DC-@7b_j8Q j%O?mZ{GR P| q  qa1S `j#q(=aFN-@vc(ފ؈nDH5?98Ze(hj!@-@q>jg6R P" 3Q P xj'P Px"a(DD-@7I;Bq2%0dj նa]cdm^ϖ'wLa0H;g"CerJju h!I/d׌'C%qq1 L($nGe7ٮG uGtk YPY Yۆ Ieqb#yg̤m0X 9DvybF=4buevGh=%H1; :} doXG<f'"BC0bJBhLBSMʶO`qK~E9T _m#7H8l7VC*ڮp_ :Pc;օVځ|q3SLGZp80o\ݹIPii:3t\@[Gf.+=V}ᘙЅʞk0:Sp6m@wi`ǚj-_$}&` %5=A%TUWS:=qRiZ$L C7e8k2Ml5h chzܹ֝31gei~PRPO+3)dL?:g0{a"2VLӶz) 'jxǒXɨѓOGrj6;Y /F}'mO6|롚/љBK$"k0mԸeׅglNjC]r#`b!^>@򇐳t  $Hz-OF&8n#{2 *Aӷ.PehtO7n 4>KC|ĢQԸ.MZ%'P3f+.h ÞU'v3XAlH|Kc&72ir=5sy!2WZv?QP( !cÕ]S5}Ҩa;)lLҫwI|҉nU&&HƾmfnE5n1㾖\oL[$8rpE>\&K"'6} aeoӔ2?yseڿ#ҋߑ9Q~w)3!G<ւ3he<- EGN Ӧ!N:m.w8—$G?-`Qp Ց90&ӳ6gP%9t4iv,pt+ԉZA>岴kc_ |3@vt9 uh/}Ef'EO'~5t:aG.;{+yJ:\2{yJ&)d"0WqRyK C$/j5E+$bBrБSfJ:1%h0wawAD>xU[;x:{&]Ե'R~h!'#rU{X._&-)9JQel(v̽?A >뼷 W^%/NV1T GA"v2yP^6mBgȳPU#M.1P_./Lnz.7vrY٦ZF!CCxЭ]C [a6jgPcZ%GQT]5')Պm/rmvw6eqTeXR$r6W6ū[\dt?6ujQw,'_"i{].98WߵLkQ3 cgӗԍxv|nalqQk)/at]Ttl6/ *8 ~r>:PeA YY'P,%Ua:59^g[\UgǸy]qJfpoaEZ8 ܨf^"3[$V[y"]ڶ]Tkg{+rW.*w\^xQ9;79#5'gKHA9 fyd|& smݯ@*̸mz^$p)yŐ#=|nX0Is%?EVZϑhnT~<Ν-/`c:X[G|sΐυ `wh|z[{C^ y/_  |2;/PuK_CwGs(<ֶ+$p"\+d@jx,J?ͰӇ;=?ܞ:U cV cJ?}L_Y߮&/ca;ٝ0 K 7~؇SL 6|1Z:I,HԦcu K΀NT=l'y & !7dgql}koYaZW;$k]~;K~|VfBѓ, iB84w.ao=:pXO, H zXnmLa ǘlaɇLjٷ4w&c2\&\HۘA&1d'ԲomL3dL1S/g6&0ycL0C&죞;L1d.ELR =Ld-Lv2I-zd0qLf0d [;T$~fub)Rq^?˓}V=>y:ǃw>M=e}Đzz)!n:3KH!#&@%jX9U%U0%YUq~ 2OFظ*?`#_VEș U:es\`= fs8:1Q0䩍ٵQPXXMüjY5Z,_-Phr;j,l<|%eu["ܒD6_V:2kӆޱ/ r& w7i*aFָi̪K lEq`Rc?5zީ7??B``,Z7\?؟w ϻ j00H=׽f#2?S}}(`,DnvЧQ!~G=rƫ+e戬]jBKsn?Z 0I(3ǟYTOAUa_ț((4P5_@Va7 Bmi,(}g&b|9˯~#g|xx5dBT:H}`&1Y5NU K>;OԨzZ7"@ލ5 穵Y$ 1357645075 +0000 clone: from git://git.code.sf.net/p/libwlocate/code libwlocate-0.0git20130108/.git/logs/refs/remotes/0000775000175000017500000000000012073002423017046 5ustar jrjrlibwlocate-0.0git20130108/.git/logs/refs/remotes/origin/0000775000175000017500000000000012073002423020335 5ustar jrjrlibwlocate-0.0git20130108/.git/logs/refs/remotes/origin/HEAD0000664000175000017500000000027212073002423020762 0ustar jrjr0000000000000000000000000000000000000000 641b5fa038398364c7fe3fc996744ae094f0cc49 Jonathan Riddell 1357645075 +0000 clone: from git://git.code.sf.net/p/libwlocate/code libwlocate-0.0git20130108/.git/logs/HEAD0000664000175000017500000000027212073002423015056 0ustar jrjr0000000000000000000000000000000000000000 641b5fa038398364c7fe3fc996744ae094f0cc49 Jonathan Riddell 1357645075 +0000 clone: from git://git.code.sf.net/p/libwlocate/code libwlocate-0.0git20130108/.git/index0000664000175000017500000001711012073002423014517 0ustar jrjrDIRCQPPh $})]l9+.>master/CGI/JSON_parser.cPPhπFLrm[!XLmaster/CGI/JSON_parser.hPPhb—0J< [oS &Ҋmaster/CGI/MakefilePPhrBK'DXQB֛^Dzmaster/CGI/Makefile.QNXPPh؝*Wjq6zmaster/CGI/READMEPPh%-Y\rxt}master/CGI/main.cPPh~Rך0qo33 master/COPYINGPPh*l[m .l*"master/CREDITSPPhE7ְ!AT&>Vmaster/MakefilePPh8 e[G9`BGmaster/Makefile.QNXPPh nd ?C&Imaster/android/LocDemo/src/com/vwp/libwlocate/map/MapView.javaP P i`R?™uN@Mp;master/android/LocDemo/src/com/vwp/libwlocate/wloc_req.javaP P i6^!4}rX/-7master/android/LocDemo/src/com/vwp/locdemo/LocDemo.javaP P iMHvw~ۨ !zTmaster/connect.cP P iz^QX :}(,master/connect.hP P i1Ҝ[-~Ã=r Jmaster/iwlist.cP P iH}3Y6>ZcVxPmaster/libwlocate.cP P iv.q}iO &Wmaster/libwlocate.dspP P iQ {9Ǯ"master/libwlocate.dswP P i>gjs+GmDn?Umaster/libwlocate.hP P i`pKu"gae.Ymaster/libwlocate.slnP P ipZ0`'.@gj(master/libwlocate.vcprojP P il$Jfej (:master/locdemo/LocDemo-icon.pngP P i!s.풚master/locdemo/LocDemoApp.cppP P iPFGhBۼI master/locdemo/LocDemoWin.hP P i"ޖ 8'!4+zmaster/locdemo/MakefileP P i#sOMDee!LcN|:$master/locdemo/Makefile.QNXP P i$̯Ä?# Z5master/locdemo/READMEP P i%!a뛉^pCPmaster/locdemo/controlP P i&>[,˷master/locdemo/icon.icoP P i'x^YٞIcߗmaster/locdemo/lin_setup.specP P i(*d|IynLmaster/locdemo/locdemo.dspP P i)g: tkM78x Icmaster/locdemo/locdemo.dswP P i*"hcefz8)ls:Nmaster/locdemo/postinstP P i+!E8vT=_LcuCmaster/locdemo/preinstP P i, p srSh`& master/locdemo/prermP P i-m͚VITNhNNU00master/locdemo/setup_data/LocDemo/DEBIAN/controlP P i.LDe81master/locdemo/setup_data/LocDemo/DEBIAN/postinstP P i/keu~a0master/locdemo/setup_data/LocDemo/DEBIAN/preinstP P i0&\)M_g .master/locdemo/setup_data/LocDemo/DEBIAN/prermP P i1ިJ0ELmaster/locdemo/win_setup.nsiPIPIi20a?Kn}H@@master/trace.cPIPIi3DX b ۘvUFtښEmaster/trace.dspPIPIi4fR33F0^master/trace.dswPIPIi5%o1"9? master/wlan.cPIPIi6nHo#Ad-ıH master/wlan.hPIPIi7"M$ m7kmaster/wlanapi_cust.hPIPIi8PjL /ո[f)]>E%.uPmaster/wlocserv/Makefile.QNXPIPIi?vwpÈBiy@master/wlocserv/READMEPIPIi@ r$5l\U5ʣ*cmaster/wlocserv/main.cppPIPIiAW>qcnmaster/wlocserv/maindefs.hPIPIiB GT2fG}wEi<master/wlocserv/platforms.cppPIPIiCX +ZӼPTmaster/wlocserv/platforms.hPIPIiDj7B+GI}pmaster/wlocserv/wlocservInc.cppUD. */ #ifndef WLAN_H #define WLAN_H // the prototype of the wlan.c-function can be found in libwlocate.h, it is used as library interface function too #endif libwlocate-0.0git20130108/iwlist.c0000775000175000017500000003072212073002423014312 0ustar jrjr/* * Wireless Tools * * Jean II - HPLB '99 - HPL 99->07 * * This tool can access various piece of information on the card * not part of iwconfig... * You need to link this code against "iwlist.c" and "-lm". * * This file is released under the GPL license. * Copyright (c) 1997-2007 Jean Tourrilhes */ #include "iwlib.h" /* Header */ #include "libwlocate.h" #include static struct wloc_req *g_request; static struct iwscan_state state; /****************************** TYPES ******************************/ /* * Scan state and meta-information, used to decode events... */ typedef struct iwscan_state { /* State */ int ap_num; /* Access Point number 1->N */ int val_index; /* Value in table 0->(N-1) */ } iwscan_state; /* * Bit to name mapping */ typedef struct iwmask_name { unsigned int mask; /* bit mask for the value */ const char * name; /* human readable name for the value */ } iwmask_name; /* * Types of authentication parameters */ typedef struct iw_auth_descr { int value; /* Type of auth value */ const char * label; /* User readable version */ const struct iwmask_name * names; /* Names for this value */ const int num_names; /* Number of names */ } iw_auth_descr; /**************************** CONSTANTS ****************************/ #define IW_SCAN_HACK 0x8000 #define IW_EXTKEY_SIZE (sizeof(struct iw_encode_ext) + IW_ENCODING_TOKEN_MAX) /***************************** SCANNING *****************************/ /* * This one behave quite differently from the others * * Note that we don't use the scanning capability of iwlib (functions * iw_process_scan() and iw_scan()). The main reason is that * iw_process_scan() return only a subset of the scan data to the caller, * for example custom elements and bitrates are ommited. Here, we * do the complete job... */ /*------------------------------------------------------------------*/ /* * Print one element from the scanning results */ static inline void print_scanning_token(struct stream_descr * stream, /* Stream of events */ struct iw_event * event, /* Extracted token */ struct iwscan_state * state, struct iw_range * iw_range, /* Range info */ int has_range) { int i; char buffer[128]; if (state->ap_num>=WLOC_MAX_NETWORKS) return; /* Now, let's decode the event */ switch(event->cmd) { case SIOCGIWAP: // printf(" Cell %02d - Address: %s\n", state->ap_num, iw_saether_ntop(&event->u.ap_addr, buffer)); state->ap_num++; for (i=0; i<6; i++) g_request->bssids[state->ap_num-1][i]=(event->u.ap_addr.sa_data[i] & 0xFF); break; case IWEVQUAL: { if (iw_range->max_qual.qual==0) g_request->signal[state->ap_num-1]=abs(event->u.qual.qual); else g_request->signal[state->ap_num-1]=100.0*event->u.qual.qual/iw_range->max_qual.qual; printf(" Signal: %d\n",g_request->signal[state->ap_num-1]); break; } default: break; } /* switch(event->cmd) */ } /*------------------------------------------------------------------*/ /* * Perform a scanning on one device */ static int print_scanning_info(int skfd, char * ifname, char * args[], /* Command line args */ int count) /* Args count */ { struct iwreq wrq; struct iw_scan_req scanopt; /* Options for 'set' */ int scanflags = 0; /* Flags for scan */ unsigned char * buffer = NULL; /* Results */ int buflen = IW_SCAN_MAX_DATA; /* Min for compat WE<17 */ struct iw_range range; int has_range; struct timeval tv; /* Select timeout */ int timeout = 15000000; /* 15s */ /* Avoid "Unused parameter" warning */ args = args; count = count; /* Debugging stuff */ /* if((IW_EV_LCP_PK2_LEN != IW_EV_LCP_PK_LEN) || (IW_EV_POINT_PK2_LEN != IW_EV_POINT_PK_LEN)) { fprintf(stderr, "*** Please report to jt@hpl.hp.com your platform details\n"); fprintf(stderr, "*** and the following line :\n"); fprintf(stderr, "*** IW_EV_LCP_PK2_LEN = %zu ; IW_EV_POINT_PK2_LEN = %zu\n\n", IW_EV_LCP_PK2_LEN, IW_EV_POINT_PK2_LEN); }*/ /* Get range stuff */ has_range = (iw_get_range_info(skfd, ifname, &range) >= 0); /* Check if the interface could support scanning. */ if (range.we_version_compiled==0) range.we_version_compiled=29; if((!has_range) || (range.we_version_compiled < 14)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning.\n\n", ifname); return(-1); } /* Init timeout value -> 250ms between set and first get */ tv.tv_sec = 0; tv.tv_usec = 250000; /* Clean up set args */ memset(&scanopt, 0, sizeof(scanopt)); /* Parse command line arguments and extract options. * Note : when we have enough options, we should use the parser * from iwconfig... */ /* while(count > 0) { count--; if(!strncmp(args[0], "essid", 5)) { if(count < 1) { fprintf(stderr, "Too few arguments for scanning option [%s]\n", args[0]); return(-1); } args++; count--; scanopt.essid_len = strlen(args[0]); memcpy(scanopt.essid, args[0], scanopt.essid_len); if(scanopt.bssid.sa_family == 0) { scanopt.bssid.sa_family = ARPHRD_ETHER; memset(scanopt.bssid.sa_data, 0xff, ETH_ALEN); } scanflags |= IW_SCAN_THIS_ESSID; } else if(!strncmp(args[0], "last", 4)) { scanflags |= IW_SCAN_HACK; } else { fprintf(stderr, "Invalid scanning option [%s]\n", args[0]); return(-1); } args++; }*/ /* Check if we have scan options */ /* if(scanflags) { wrq.u.data.pointer = (caddr_t) &scanopt; wrq.u.data.length = sizeof(scanopt); wrq.u.data.flags = scanflags; } else*/ { wrq.u.data.pointer = NULL; wrq.u.data.flags = 0; wrq.u.data.length = 0; } /* If only 'last' was specified on command line, don't trigger a scan */ /* if(scanflags == IW_SCAN_HACK) { tv.tv_usec = 0; } else*/ { /* Initiate Scanning */ if(iw_set_ext(skfd, ifname, SIOCSIWSCAN, &wrq) < 0) { if((errno != EPERM) || (scanflags != 0)) { fprintf(stderr, "%-8.16s Interface doesn't support scanning : %s\n\n", ifname, strerror(errno)); return(-1); } /* If we don't have the permission to initiate the scan, we may * still have permission to read left-over results. * But, don't wait !!! */ #if 0 /* Not cool, it display for non wireless interfaces... */ fprintf(stderr, "%-8.16s (Could not trigger scanning, just reading left-over results)\n", ifname); #endif tv.tv_usec = 0; } } timeout -= tv.tv_usec; /* Forever */ while(1) { fd_set rfds; /* File descriptors for select */ int last_fd; /* Last fd */ int ret; /* Guess what ? We must re-generate rfds each time */ FD_ZERO(&rfds); last_fd = -1; /* In here, add the rtnetlink fd in the list */ /* Wait until something happens */ ret = select(last_fd + 1, &rfds, NULL, NULL, &tv); /* Check if there was an error */ if(ret < 0) { if(errno == EAGAIN || errno == EINTR) continue; fprintf(stderr, "Unhandled signal - exiting...\n"); return(-1); } /* Check if there was a timeout */ if(ret == 0) { unsigned char * newbuf; realloc: /* (Re)allocate the buffer - realloc(NULL, len) == malloc(len) */ newbuf = (unsigned char*)realloc(buffer, buflen); if(newbuf == NULL) { if(buffer) free(buffer); fprintf(stderr, "%s: Allocation failed\n", __FUNCTION__); return(-1); } buffer = newbuf; /* Try to read the results */ wrq.u.data.pointer = buffer; wrq.u.data.flags = 0; wrq.u.data.length = buflen; if(iw_get_ext(skfd, ifname, SIOCGIWSCAN, &wrq) < 0) { /* Check if buffer was too small (WE-17 only) */ if((errno == E2BIG) && (range.we_version_compiled > 16)) { /* Some driver may return very large scan results, either * because there are many cells, or because they have many * large elements in cells (like IWEVCUSTOM). Most will * only need the regular sized buffer. We now use a dynamic * allocation of the buffer to satisfy everybody. Of course, * as we don't know in advance the size of the array, we try * various increasing sizes. Jean II */ /* Check if the driver gave us any hints. */ if(wrq.u.data.length > buflen) buflen = wrq.u.data.length; else buflen *= 2; /* Try again */ goto realloc; } /* Check if results not available yet */ if(errno == EAGAIN) { /* Restart timer for only 100ms*/ tv.tv_sec = 0; tv.tv_usec = 100000; timeout -= tv.tv_usec; if(timeout > 0) continue; /* Try again later */ } /* Bad error */ free(buffer); fprintf(stderr, "%-8.16s Failed to read scan data : %s\n\n", ifname, strerror(errno)); return(-2); } else /* We have the results, go to process them */ break; } /* In here, check if event and event type * if scan event, read results. All errors bad & no reset timeout */ } if(wrq.u.data.length) { struct iw_event iwe; struct stream_descr stream; int ret; state.ap_num = 0; state.val_index = 0; #ifdef DEBUG /* Debugging code. In theory useless, because it's debugged ;-) */ int i; printf("Scan result %d [%02X", wrq.u.data.length, buffer[0]); for(i = 1; i < wrq.u.data.length; i++) printf(":%02X", buffer[i]); printf("]\n"); #endif printf("%-8.16s Scan completed :\n", ifname); iw_init_event_stream(&stream, (char *) buffer, wrq.u.data.length); do { /* Extract an event and print it */ ret = iw_extract_event_stream(&stream, &iwe, range.we_version_compiled); if(ret > 0) print_scanning_token(&stream, &iwe, &state, &range, has_range); } while(ret > 0); printf("\n"); } else printf("%-8.16s No scan results\n\n", ifname); free(buffer); return(0); } /*********************** FREQUENCIES/CHANNELS ***********************/ /*------------------------------------------------------------------*/ /* * Power Management types of values */ static const unsigned int pm_type_flags[] = { IW_POWER_PERIOD, IW_POWER_TIMEOUT, IW_POWER_SAVING, }; static const int pm_type_flags_size = (sizeof(pm_type_flags)/sizeof(pm_type_flags[0])); /************************* COMMON UTILITIES *************************/ /* * This section was initially written by Michael Tokarev * but heavily modified by me ;-) */ /*------------------------------------------------------------------*/ /* * Map command line arguments to the proper procedure... */ typedef struct iwlist_entry { const char * cmd; /* Command line shorthand */ iw_enum_handler fn; /* Subroutine */ int max_count; const char * argsname; /* Args as human readable string */ } iwlist_cmd; static const struct iwlist_entry iwlist_cmds[] = { { "scanning", print_scanning_info, -1, "[essid NNN] [last]" }, { NULL, NULL, 0, 0 }, }; /*------------------------------------------------------------------*/ /* * Find the most appropriate command matching the command line */ static inline const iwlist_cmd * find_command(const char * cmd) { const iwlist_cmd * found = NULL; int ambig = 0; unsigned int len = strlen(cmd); int i; /* Go through all commands */ for(i = 0; iwlist_cmds[i].cmd != NULL; ++i) { /* No match -> next one */ if(strncasecmp(iwlist_cmds[i].cmd, cmd, len) != 0) continue; /* Exact match -> perfect */ if(len == strlen(iwlist_cmds[i].cmd)) return &iwlist_cmds[i]; /* Partial match */ if(found == NULL) /* First time */ found = &iwlist_cmds[i]; else /* Another time */ if (iwlist_cmds[i].fn != found->fn) ambig = 1; } if(found == NULL) { fprintf(stderr, "iwlist: unknown command `%s' (check 'iwlist --help').\n", cmd); return NULL; } if(ambig) { fprintf(stderr, "iwlist: command `%s' is ambiguous (check 'iwlist --help').\n", cmd); return NULL; } return found; } int iw_fill_structure(struct wloc_req *request) { int skfd; /* Create a channel to the NET kernel. */ if((skfd = iw_sockets_open()) < 0) { perror("socket"); return -1; } g_request=request; /* do the actual work */ iw_enum_devices(skfd,print_scanning_info,NULL,-1); /* Close the socket. */ iw_sockets_close(skfd); return state.ap_num; }