This file is indexed.

/usr/share/perl5/Finance/Quote/Yahoo/Base.pm is in libfinance-quote-perl 1.38-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
#!/usr/bin/perl -w
#
#    Copyright (C) 1998, Dj Padzensky <djpadz@padz.net>
#    Copyright (C) 1998, 1999 Linas Vepstas <linas@linas.org>
#    Copyright (C) 2000, Yannick LE NY <y-le-ny@ifrance.com>
#    Copyright (C) 2000, Paul Fenwick <pjf@cpan.org>
#    Copyright (C) 2000, Brent Neal <brentn@users.sourceforge.net>
#
#    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 2 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, write to the Free Software
#    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#    02111-1307, USA
#
# This code derived from Padzensky's work on package Finance::YahooQuote,
# but extends its capabilites to encompas a greater number of data sources.
#
# This package provides a base class for the various Yahoo services,
# and is based upon code by Xose Manoel Ramos <xmanoel@bigfoot.com>.
# Improvements based upon patches supplied by Peter Thatcher have
# also been integrated.

package Finance::Quote::Yahoo::Base;
require 5.005;

use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
use Exporter;

use vars qw/ @FIELDS @FIELD_ENCODING $MAX_REQUEST_SIZE @ISA
            @EXPORT @EXPORT_OK/;

@ISA = qw/Exporter/;
@EXPORT = qw//;
@EXPORT_OK = qw/yahoo_request base_yahoo_labels/;

our $VERSION = '1.38'; # VERSION

# This is the maximum number of stocks we'll batch into one operation.
# If this gets too big (>50 or thereabouts) things will break because
# some proxies and/or webservers cannot handle very large URLS.

$MAX_REQUEST_SIZE = 40;

# Yahoo uses encodes the desired fields as 1-2 character strings
# in the URL.  These are recorded below, along with their corresponding
# field names.

@FIELDS = qw/symbol name last date time net p_change volume bid ask
             close open day_range year_range eps pe div_date div div_yield
	     cap ex_div avg_vol currency/;

@FIELD_ENCODING = qw/s n l1 d1 t1 c1 p2 v b a p o m w e r r1 d y j1 q a2 c4/;

# This returns a list of labels that are provided, so that code
# that make use of this module can know what it's dealing with.
# It also means that if we extend the code in the future to provide
# more information, we simply need to change this in one spot.

sub base_yahoo_labels {
	return (@FIELDS,"price","high","low");
}

# Yahoo uses a suffix on the stock symbol to denote the exchange on
# which the stock is traded.  Use this suffix to map from the stock
# symbol to the currency in which its prices are reported.

my %currency_tags = (
		      # Country		City/Exchange Name
	US  => "USD", # USA		AMEX, Nasdaq, NYSE
  	A   => "USD", # USA		American Stock Exchange (ASE)
  	B   => "USD", # USA		Boston Stock Exchange (BOS)
  	N   => "USD", # USA		Nasdaq Stock Exchange (NAS)
  	O   => "USD", # USA		NYSE Stock Exchange (NYS)
  	OB  => "USD", # USA		OTC Bulletin Board
  	PK  => "USD", # USA		Pink Sheets
  	X   => "USD", # USA		US Options
	BA  => "ARS", # Argentina	Buenos Aires
	VI  => "EUR", # Austria		Vienna
  	AX  => "AUD", # Australia
	SA  => "BRL", # Brazil		Sao Paolo
  	BR  => "EUR", # Belgium		Brussels
  	TO  => "CAD", # Canada		Toronto
  	V   => "CAD", # 		Toronto Venture
	SN  => "CLP", # Chile		Santiago
	SS  => "CNY", # China		Shanghai
	SZ  => "CNY", # 		Shenzhen
  	CO  => "DKK", # Denmark		Copenhagen
  	PA  => "EUR", # France		Paris
  	BE  => "EUR", # Germany		Berlin
  	BM  => "EUR", # 		Bremen
  	D   => "EUR", # 		Dusseldorf
  	F   => "EUR", # 		Frankfurt
  	H   => "EUR", # 		Hamburg
  	HA  => "EUR", # 		Hanover
  	MU  => "EUR", # 		Munich
  	SG  => "EUR", # 		Stuttgart
  	DE  => "EUR", # 		XETRA
	HK  => "HKD", # Hong Kong
	BO  => "INR", # India		Bombay
	CL  => "INR", # 		Calcutta
	NS  => "INR", # 		National Stock Exchange
	JK  => "IDR", # Indonesia	Jakarta
  	I   => "EUR", # Ireland		Dublin
	TA  => "ILS", # Israel		Tel Aviv
  	MI  => "EUR", # Italy		Milan
	KS  => "KRW", # Korea		Stock Exchange
	KQ  => "KRW", # 		KOSDAQ
	KL  => "MYR", # Malaysia	Kuala Lampur
	MX  => "MXP", # Mexico
	NZ  => "NZD", # New Zealand
  	AS  => "EUR", # Netherlands	Amsterdam
  	OL  => "NOK", # Norway		Oslo
	LM  => "PEN", # Peru		Lima
	IN  => "EUR", # Portugal	Lisbon
	SI  => "SGD", # Singapore
	BC  => "EUR", # Spain		Barcelona
	BI  => "EUR", # 		Bilbao
	MF  => "EUR", # 		Madrid Fixed Income
	MC  => "EUR", # 		Madrid SE CATS
	MA  => "EUR", # 		Madrid
	VA  => "EUR", # 		Valence
  	ST  => "SEK", # Sweden		Stockholm
  	S   => "CHF", # Switzerland	Zurich
	TW  => "TWD", # Taiwan		Taiwan Stock Exchange
	TWO => "TWD", # 		OTC
	BK  => "THB", # Thialand	Thailand Stock Exchange
	TH  => "THB", # 		??? From Asia.pm, (in Thai Baht)
  	L   => "GBP", # United Kingdom	London
);

# yahoo_request (restricted function)
#
# This function expects a Finance::Quote object, a base URL to use,
# a refernece to a list of symbols to lookup.  If a fourth argument is
# used then it will act as a suffix that needs to be appended to the stocks
# in order to obtain the correct information.  This function relies upon
# the fact that the various Yahoo's all work the same way.

sub yahoo_request {
	my $quoter = shift;
	my $base_url = shift;

	# Extract our original symbols.
	my @orig_symbols = @{shift()};

	# The suffix is used to specify particular markets.
	my $suffix = shift || "";

	my %info;
	my $ua = $quoter->user_agent;

	# Generate a suitable URL, now all it needs is the
	# ticker symbols.
	$base_url .= "?f=".join("",@FIELD_ENCODING)."&e=.csv&s=";

	while (my @symbols = splice(@orig_symbols,0,$MAX_REQUEST_SIZE)) {

		# By pushing an extra symbol on to our array, we can
		# be sure that everythng ends up with the correct suffix
		# in the join() below.
		push(@symbols,"");

		my $url = $base_url . join("$suffix+",@symbols);
		chop $url;	# Chop off the final +
                print "DEBUG - GET: $url\n" if $ENV{"FQ_DEBUG"};
		my $response = $ua->request(GET $url);
		return unless $response->is_success;

		# Okay, we have the data.  Just stuff it in
		# the hash now.

		foreach (split('\015?\012',$response->content)) {
			my @q;
                        @q = $quoter->parse_csv($_);
			my $symbol = $q[0];
			my ($exchange) = $symbol =~ m/\.([A-Z]+)/;

			# Strip out suffixes.  Mmmm, functions as lvalues.
			substr($symbol,-length($suffix),length($suffix)) = "";

			# If we weren't using a two dimesonal
			# hash, we could do the following with
			# a hash-slice.  Alas, we can't.  This just
			# loads all the returned fields into our hash.

			for (my $i=0; $i < @FIELDS; $i++) {
				# Every now and then on a failed
				# retrieval, Yahoo will drop in an
				# undefined field
				next unless (defined $q[$i] && length $q[$i]);
                                # remove trailing spaces added for
                                # yahoo::europe quotes, since currency
                                # is returned with a trailing white
                                # space
                                $q[$i] =~ s/\s*$// ;
				$info{$symbol,$FIELDS[$i]} = $q[$i];
			}

			# Yahoo returns a line filled with N/A's if we
			# look up a non-existant symbol.  AFAIK, the
			# date flag will /never/ be defined properly
			# unless we've looked up a real stock.  Hence
			# we can use this to check if we've
			# successfully obtained the stock or not.

			if ($info{$symbol,"date"} eq "N/A") {
				$info{$symbol,"success"} = 0;
				$info{$symbol,"errormsg"} = "Stock lookup failed";
				next;
			} else {
				$info{$symbol,"success"} = 1;
			}

			# Whack the dates.  This will add an isodate,
			# and regularize the us date.
			$quoter->store_date(\%info, $symbol, {usdate => $info{$symbol,"date"}});

			$info{$symbol,"price"} = $info{$symbol,"last"};

			# Remove spurious percentage signs in p_change.

			$info{$symbol,"p_change"} =~ s/%//;

			# Extract the high and low values from the
			# day-range, if available

			if ($info{$symbol,"day_range"} =~ m{^"?\s*(\S+)\s*-\s*(\S+)"?$}) {
				$info{$symbol, "low"}  = $1;
				$info{$symbol, "high"} = $2;
			}

                        if (defined($info{$symbol,"time"})) {
                          # uniform time output
                          $info{$symbol,"time"} = $quoter->isoTime($info{$symbol,"time"});
                        }

                        # "cap" from Yahoo::USA sometimes has "B" for
                        # billions suffix, eg. from "F" Ford -- expand that
                        # to a plain number for ease of use
                        if (defined($info{$symbol,"cap"})) {
                          $info{$symbol,"cap"}
                            = $quoter->B_to_billions ($info{$symbol,"cap"});
                        }

      # Convert prices (when needed). E.G. Some London sources
      # return in pence. Yahoo denotes this with GBP vs GBp
      # We'd like them to return in pounds (divide by 100).
      if (defined($exchange)) {
        if ((($exchange eq "L") &&
             (($info{$symbol,"currency"} eq "GBp") ||
              #Assume GBX also quoted in pence; if not remove next line
              ($info{$symbol,"currency"} eq "GBX"))) ||
            ($exchange eq "TA")) {
          foreach my $field ($quoter->default_currency_fields) {
            next unless ($info{$symbol,$field});
            $info{$symbol,$field} =
              $quoter->scale_field($info{$symbol,$field},0.01);
          }
        } ;
        if (($exchange eq "L") && defined($info{$symbol,"year_range"})) {         # if a year range is returned for exchange=L
          if ($info{$symbol,"year_range"}=~ m/([\d\.]+)\s*-\s*([\d\.]+)/) {       # take year low and high
            my ($year_low,$year_high) = ($1,$2) ;
            if ($info{$symbol,"close"} <= $year_low) {                            # sometimes year_range was expressed in .01 GBp
              $info{$symbol,"year_range"} = ($year_low/100)." - ".($year_high/100) ;
            }
          }
        }
        # Other exchanges here as needed.
      }

			if (defined($info{$symbol,"currency"})) {
        # Having converted London prices to GBP above we
        # make upper-case and turn GBX to GBP.
			  $info{$symbol,"currency"} =~ tr/a-z/A-Z/;
                          # yahoo started to return GBX instead of GBP
                          # somewhere arround 9 oct 2008.
                          $info{$symbol,"currency"} =~ s/GBX/GBP/;
#			  printf "Currency %s specified by Yahoo\n", $info{$symbol,"currency"};
			} else {
			  # Determine the currency from the exchange name.
			  # Symbols without an exchange are in USD. Symbols
			  # starting with a hat are always indexes, so they
			  # don't have a currency.
			  if (defined($exchange)) {
			    $info{$symbol,"currency"} = $currency_tags{$exchange};
#			    print "Set currency based on exchange $exchange\n";
			  } elsif (substr($symbol,0,1) ne "^") {
#			    print "No exchange, not an index, set currency to USD\n";
			    $info{$symbol,"currency"} = "USD";
			  }
			  $info{$symbol,"currency_set_by_fq"} = 1;
			}


		} # End of processing each stock line.
	} # End of lookup loop.

	# Return undef's rather than N/As.  This makes things more suitable
	# for insertion into databases, etc.  Also remove silly HTML that
	# Yahoo inserts to put in little Euro symbols and stuff.  It's
	# pretty stupid to have HTML tags in a CSV file in the first
	# place, don't you think?

	foreach my $key (keys %info) {
	  #if (!defined $info{$key}) {
	  #  printf STDERR "\n";
	  #  printf STDERR "$key points to undefined value\n";
	  #  printf STDERR "\n";
	  #}
	  if (defined $info{$key}) {
	    $info{$key} =~ s/<[^>]*>//g;
	    $info{$key} =~ s/&nbsp;.*$//;
	    undef $info{$key} if ($info{$key} eq "N/A");
	  }
	}
	return %info if wantarray;
	return \%info;
}


1;

=head1 NAME

Finance::Quote::Yahoo::Base - Common functions for fetching Yahoo info.

=head1 SYNOPSIS

Base functions for use by the Finance::Quote::Yahoo::* modules.

=head1 DESCRIPTION

This module is not called directly, rather it provides a set of
base functions which other Yahoo-related modules can use.  If you're
thinking of writing a module to fetch specific information from
Yahoo, then you might wish to look through the source code for
this module.

=head1 LABELS RETURNED

Most Yahoo functions will return a standard set of labels.  These
include (where available): symbol, name, last, date, time, net,
p_change, volume, bid, ask close, open, day_range, year_range, eps,
pe, div_date, div, div_yield, cap, ex_div, avg_vol.

=head1 SEE ALSO

Finance::Quote::Yahoo::Australia, Finance::Quote::Yahoo::USA,
Finance::Quote::Yahoo::Europe.

=cut