| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | ## Domain Registry Interface, Encapsulating result status, standardized on EPP codes | 
| 2 |  |  |  |  |  |  | ## | 
| 3 |  |  |  |  |  |  | ## Copyright (c) 2005,2006,2008-2014 Patrick Mevzek . All rights reserved. | 
| 4 |  |  |  |  |  |  | ## | 
| 5 |  |  |  |  |  |  | ## This file is part of Net::DRI | 
| 6 |  |  |  |  |  |  | ## | 
| 7 |  |  |  |  |  |  | ## Net::DRI is free software; you can redistribute it and/or modify | 
| 8 |  |  |  |  |  |  | ## it under the terms of the GNU General Public License as published by | 
| 9 |  |  |  |  |  |  | ## the Free Software Foundation; either version 2 of the License, or | 
| 10 |  |  |  |  |  |  | ## (at your option) any later version. | 
| 11 |  |  |  |  |  |  | ## | 
| 12 |  |  |  |  |  |  | ## See the LICENSE file that comes with this distribution for more details. | 
| 13 |  |  |  |  |  |  | #################################################################################################### | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | package Net::DRI::Protocol::ResultStatus; | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 72 |  |  | 72 |  | 977 | use strict; | 
|  | 72 |  |  |  |  | 115 |  | 
|  | 72 |  |  |  |  | 2536 |  | 
| 18 | 72 |  |  | 72 |  | 304 | use warnings; | 
|  | 72 |  |  |  |  | 97 |  | 
|  | 72 |  |  |  |  | 2040 |  | 
| 19 |  |  |  |  |  |  |  | 
| 20 | 72 |  |  | 72 |  | 313 | use base qw(Class::Accessor::Chained::Fast); | 
|  | 72 |  |  |  |  | 97 |  | 
|  | 72 |  |  |  |  | 10201 |  | 
| 21 |  |  |  |  |  |  | __PACKAGE__->mk_ro_accessors(qw(native_code code message lang next count)); | 
| 22 |  |  |  |  |  |  |  | 
| 23 | 72 |  |  | 72 |  | 17019 | use Net::DRI::Exception; | 
|  | 72 |  |  |  |  | 105 |  | 
|  | 72 |  |  |  |  | 1294 |  | 
| 24 | 72 |  |  | 72 |  | 2063 | use Net::DRI::Util; | 
|  | 72 |  |  |  |  | 103 |  | 
|  | 72 |  |  |  |  | 139279 |  | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | =pod | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | =head1 NAME | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | Net::DRI::Protocol::ResultStatus - Encapsulate Details of an Operation Result (with Standardization on EPP) for Net::DRI | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | An object of this class represents all details of an operation result as given back from the registry, | 
| 35 |  |  |  |  |  |  | with standardization on EPP as much as possible, for error codes and list of fields available. | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | One object may contain one or more operation results. The object is in fact a list, starting with the | 
| 38 |  |  |  |  |  |  | chronologically first/top operation result, and then using the C call progressing toward other | 
| 39 |  |  |  |  |  |  | operation results, if available (each call to next gives an object of this class). The last operation result | 
| 40 |  |  |  |  |  |  | can be retrieved with C. | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | When an operation is done, data retrieved from the registry is also stored inside the ResultStatus object | 
| 43 |  |  |  |  |  |  | (besides being available through C<< $dri->get_info() >>). It can be queried using the C and | 
| 44 |  |  |  |  |  |  | C methods as explained below. The data is stored as a ref hash with 3 levels: | 
| 45 |  |  |  |  |  |  | the first keys have as values a reference to another hash where keys are again associated with values | 
| 46 |  |  |  |  |  |  | being a reference to another hash where the content (keys and values) depends on the registry, the operation | 
| 47 |  |  |  |  |  |  | attempted, and the result. | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | Some data will always be there: a "session" first key, with a "exchange" subkey, will have a reference to | 
| 50 |  |  |  |  |  |  | an hash with the following keys: | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | =over | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | =item duration_seconds | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | the duration of the exchange with registry, in a floating point number of seconds | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | =item raw_command | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | the message sent to the registry, as string | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | =item raw_reply | 
| 63 |  |  |  |  |  |  |  | 
| 64 |  |  |  |  |  |  | the message received from the registry, as string | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  | =item result_from_cache | 
| 67 |  |  |  |  |  |  |  | 
| 68 |  |  |  |  |  |  | either 0 or 1 if these results were retrieved from L Cache object or not | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | =item object_action | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | name of the action that has been done to achieve these results (ex: "info") | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | =item object_name | 
| 75 |  |  |  |  |  |  |  | 
| 76 |  |  |  |  |  |  | name (or ID) of the object on which the action has been performed (not necessarily always defined) | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | =item object_type | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | type of object on which this operation has been done (ex: "domain") | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | =item registry, profile, transport, protocol | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | registry name, profile name, transport name+version, protocol name+version used for this exchange | 
| 85 |  |  |  |  |  |  |  | 
| 86 |  |  |  |  |  |  | =item trid | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  | transaction ID of this exchange | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | =back | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  | =head1 METHODS | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  | =head2 is_success() | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | returns 1 if the operation was a success | 
| 97 |  |  |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | =head2 code() | 
| 99 |  |  |  |  |  |  |  | 
| 100 |  |  |  |  |  |  | returns the EPP code corresponding to the native code (which depends on the registry) | 
| 101 |  |  |  |  |  |  | for this operation (see RFC for full list and source of this file for local extensions) | 
| 102 |  |  |  |  |  |  |  | 
| 103 |  |  |  |  |  |  | =head2 native_code() | 
| 104 |  |  |  |  |  |  |  | 
| 105 |  |  |  |  |  |  | gives the true status code we got back from registry (this breaks the encapsulation provided by Net::DRI, you should not use it if possible) | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | =head2 message() | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | gives the message attached to the the status code we got back from registry | 
| 110 |  |  |  |  |  |  |  | 
| 111 |  |  |  |  |  |  | =head2 lang() | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | gives the language in which the message above is written | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | =head2 get_extended_results() | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | gives back an array with additionnal result information from registry, especially in case of errors. If no data, an empty array is returned. | 
| 118 |  |  |  |  |  |  |  | 
| 119 |  |  |  |  |  |  | This method was previously called info(), before C version 0.92_01 | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | =head2 get_data() | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | See explanation of data stored in L"DESCRIPTION">. Can be called with one or three parameters and always returns a single value (or undef if failure). | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | With three parameters, it returns the value associated to the three keys/subkeys passed. Example: C will return | 
| 126 |  |  |  |  |  |  | 0 or 1 depending if the domain exists or not, after a domain check or domain info operation. | 
| 127 |  |  |  |  |  |  |  | 
| 128 |  |  |  |  |  |  | With only one parameter, it will verify there is only one branch (besides session/exchange and message/info), and if so returns the data associated | 
| 129 |  |  |  |  |  |  | to the parameter passed used as the third key. Otherwise will return undef. | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | Please note that the input API is I the same as the one used for C<$dri->get_info()>. | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | You should not try to modify the data returned in any way, but just read it. | 
| 134 |  |  |  |  |  |  |  | 
| 135 |  |  |  |  |  |  | =head2 get_data_collection() | 
| 136 |  |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | See explanation of data stored in L"DESCRIPTION">. Can be called with either zero, one or two parameters and may return a list or a single value | 
| 138 |  |  |  |  |  |  | depending on calling context (and respectively an empty list or undef in case of failure). | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | With no parameter, it returns the whole data as reference to an hash with 2 levels beneath as explained in L"DESCRIPTION"> in scalar context, or | 
| 141 |  |  |  |  |  |  | the list of keys of this hash in list context. | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  | With one parameter, it returns the hash referenced by the key given as argument at first level in scalar context, | 
| 144 |  |  |  |  |  |  | or the list of keys of this hash in list context. | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | With two parameters, it walks down two level of the hash using the two parameters as key and subkey and returns the bottom hash referenced | 
| 147 |  |  |  |  |  |  | in scalar context, or the list of keys of this hash in list context. | 
| 148 |  |  |  |  |  |  |  | 
| 149 |  |  |  |  |  |  | Please note that in all cases you are given references to the data itself, not copies. You should not try to modify it in any way, but just read it. | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | =head2 as_string() | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | returns a string with all details, with the extended_results part if passed a true value | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | =head2 print() | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | same as CORE::print($rs->as_string(0)) or CORE::print($rs->as_string(1)) if passed a true value | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | =head2 trid() | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | in scalar context, gives the transaction id (our transaction id, that is the client part in EPP) which has generated this result, | 
| 162 |  |  |  |  |  |  | in array context, gives the transaction id followed by other ids given by registry (example in EPP: server transaction id) | 
| 163 |  |  |  |  |  |  |  | 
| 164 |  |  |  |  |  |  | =head2 is_pending() | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | returns 1 if the operation was flagged as pending by registry (asynchronous handling) | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | =head2 is_closing() | 
| 169 |  |  |  |  |  |  |  | 
| 170 |  |  |  |  |  |  | returns 1 if the operation made the registry close the connection (should not happen often) | 
| 171 |  |  |  |  |  |  |  | 
| 172 |  |  |  |  |  |  | =head2 is(NAME) | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | if you really need to test some other codes (this should not happen often), you can using symbolic names | 
| 175 |  |  |  |  |  |  | defined inside this module (see source). | 
| 176 |  |  |  |  |  |  | Going that way makes sure you are not hardcoding numbers in your application, and you do not need | 
| 177 |  |  |  |  |  |  | to import variables from this module to your application. | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | =head1 SUPPORT | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | For now, support questions should be sent to: | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | Enetdri@dotandco.comE | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | Please also see the SUPPORT file in the distribution. | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | http://www.dotandco.com/services/software/Net-DRI/ | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | =head1 AUTHOR | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | Patrick Mevzek, Enetdri@dotandco.comE | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | =head1 COPYRIGHT | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | Copyright (c) 2005,2006,2008-2014 Patrick Mevzek . | 
| 198 |  |  |  |  |  |  | All rights reserved. | 
| 199 |  |  |  |  |  |  |  | 
| 200 |  |  |  |  |  |  | This program is free software; you can redistribute it and/or modify | 
| 201 |  |  |  |  |  |  | it under the terms of the GNU General Public License as published by | 
| 202 |  |  |  |  |  |  | the Free Software Foundation; either version 2 of the License, or | 
| 203 |  |  |  |  |  |  | (at your option) any later version. | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | See the LICENSE file that comes with this distribution for more details. | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | =cut | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | #################################################################################################### | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | our %EPP_CODES=( | 
| 212 |  |  |  |  |  |  | COMMAND_SUCCESSFUL => 1000, | 
| 213 |  |  |  |  |  |  | COMMAND_SUCCESSFUL_PENDING => 1001, ## needed for async registries when action done correctly on our side | 
| 214 |  |  |  |  |  |  | COMMAND_SUCCESSFUL_QUEUE_EMPTY => 1300, | 
| 215 |  |  |  |  |  |  | COMMAND_SUCCESSFUL_QUEUE_ACK => 1301, | 
| 216 |  |  |  |  |  |  | COMMAND_SUCCESSFUL_END => 1500, ## after logout | 
| 217 |  |  |  |  |  |  |  | 
| 218 |  |  |  |  |  |  | UNKNOWN_COMMAND => 2000, | 
| 219 |  |  |  |  |  |  | COMMAND_SYNTAX_ERROR => 2001, | 
| 220 |  |  |  |  |  |  | COMMAND_USE_ERROR => 2002, | 
| 221 |  |  |  |  |  |  | REQUIRED_PARAMETER_MISSING => 2003, | 
| 222 |  |  |  |  |  |  | PARAMETER_VALUE_RANGE_ERROR => 2004, | 
| 223 |  |  |  |  |  |  | PARAMETER_VALUE_SYNTAX_ERROR => 2005, | 
| 224 |  |  |  |  |  |  | UNIMPLEMENTED_PROTOCOL_VERSION => 2100, | 
| 225 |  |  |  |  |  |  | UNIMPLEMENTED_COMMAND => 2101, | 
| 226 |  |  |  |  |  |  | UNIMPLEMENTED_OPTION => 2102, | 
| 227 |  |  |  |  |  |  | UNIMPLEMENTED_EXTENSION => 2103, | 
| 228 |  |  |  |  |  |  | BILLING_FAILURE => 2104, | 
| 229 |  |  |  |  |  |  | OBJECT_NOT_ELIGIBLE_FOR_RENEWAL => 2105, | 
| 230 |  |  |  |  |  |  | OBJECT_NOT_ELIGIBLE_FOR_TRANSFER => 2106, | 
| 231 |  |  |  |  |  |  | AUTHENTICATION_ERROR => 2200, | 
| 232 |  |  |  |  |  |  | AUTHORIZATION_ERROR => 2201, | 
| 233 |  |  |  |  |  |  | INVALID_AUTHORIZATION_INFO => 2202, | 
| 234 |  |  |  |  |  |  | OBJECT_PENDING_TRANSFER => 2300, | 
| 235 |  |  |  |  |  |  | OBJECT_NOT_PENDING_TRANSFER => 2301, | 
| 236 |  |  |  |  |  |  | OBJECT_EXISTS   => 2302, | 
| 237 |  |  |  |  |  |  | OBJECT_DOES_NOT_EXIST => 2303, | 
| 238 |  |  |  |  |  |  | OBJECT_STATUS_PROHIBITS_OPERATION => 2304, | 
| 239 |  |  |  |  |  |  | OBJECT_ASSOCIATION_PROHIBITS_OPERATION => 2305, | 
| 240 |  |  |  |  |  |  | PARAMETER_VALUE_POLICY_ERROR => 2306, | 
| 241 |  |  |  |  |  |  | UNIMPLEMENTED_OBJECT_SERVICE => 2307, | 
| 242 |  |  |  |  |  |  | DATA_MANAGEMENT_POLICY_VIOLATION => 2308, | 
| 243 |  |  |  |  |  |  | COMMAND_FAILED => 2400, ## Internal server error not related to the protocol | 
| 244 |  |  |  |  |  |  | COMMAND_FAILED_CLOSING => 2500, ## Same + connection dropped | 
| 245 |  |  |  |  |  |  | AUTHENTICATION_ERROR_CLOSING => 2501, | 
| 246 |  |  |  |  |  |  | SESSION_LIMIT_EXCEEDED_CLOSING => 2502, | 
| 247 |  |  |  |  |  |  | ); | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | sub new | 
| 250 |  |  |  |  |  |  | { | 
| 251 | 18 |  |  | 18 | 1 | 2717 | my ($class,$type,$code,$eppcode,$is_success,$message,$lang,$info)=@_; | 
| 252 | 18 | 100 | 100 |  |  | 279 | my %s=( | 
|  |  |  | 100 |  |  |  |  | 
|  |  |  | 100 |  |  |  |  | 
| 253 |  |  |  |  |  |  | is_success  => (defined $is_success && $is_success)? 1 : 0, | 
| 254 |  |  |  |  |  |  | native_code => $code, | 
| 255 |  |  |  |  |  |  | message     => $message || '', | 
| 256 |  |  |  |  |  |  | type        => $type, ## rrp/epp/afnic/etc... | 
| 257 |  |  |  |  |  |  | lang        => $lang || '?', | 
| 258 |  |  |  |  |  |  | 'next'	    => undef, | 
| 259 |  |  |  |  |  |  | data        => {}, | 
| 260 |  |  |  |  |  |  | count	    => 0, | 
| 261 |  |  |  |  |  |  | ); | 
| 262 |  |  |  |  |  |  |  | 
| 263 | 18 |  |  |  |  | 71 | $s{code}=_eppcode($type,$code,$eppcode,$s{is_success}); | 
| 264 | 18 | 50 | 33 |  |  | 84 | $s{info}=(defined $info && ref $info eq 'ARRAY')? $info : []; | 
| 265 | 18 |  |  |  |  | 57 | bless(\%s,$class); | 
| 266 | 18 |  |  |  |  | 58 | return \%s; | 
| 267 |  |  |  |  |  |  | } | 
| 268 |  |  |  |  |  |  |  | 
| 269 |  |  |  |  |  |  | sub trid | 
| 270 |  |  |  |  |  |  | { | 
| 271 | 10 |  |  | 10 | 1 | 16 | my $self=shift; | 
| 272 | 10 | 50 | 33 |  |  | 84 | return unless (exists($self->{trid}) && (ref($self->{trid}) eq 'ARRAY')); | 
| 273 | 0 | 0 |  |  |  | 0 | return wantarray()? @{$self->{trid}} : $self->{trid}->[0]; | 
|  | 0 |  |  |  |  | 0 |  | 
| 274 |  |  |  |  |  |  | } | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | sub clone | 
| 277 |  |  |  |  |  |  | { | 
| 278 | 0 |  |  | 0 | 0 | 0 | my ($self)=@_; | 
| 279 | 0 |  |  |  |  | 0 | my $new={ %$self }; | 
| 280 | 0 | 0 |  |  |  | 0 | $new->{'next'}=$new->{'next'}->clone() if defined $new->{'next'}; | 
| 281 |  |  |  |  |  |  | ## we do not clone "data" key as it is supposed to be used read-only anyway, otherwise use Net::DRI::Util::deepcopy | 
| 282 | 0 |  |  |  |  | 0 | bless($new,ref $self); | 
| 283 | 0 |  |  |  |  | 0 | return $new; | 
| 284 |  |  |  |  |  |  | } | 
| 285 |  |  |  |  |  |  |  | 
| 286 | 12 |  |  | 12 | 0 | 51 | sub local_is_success { return shift->{is_success}; } | 
| 287 |  |  |  |  |  |  |  | 
| 288 | 1 |  |  | 1 | 0 | 1 | sub local_get_extended_results { return @{shift->{info}}; } | 
|  | 1 |  |  |  |  | 4 |  | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | sub local_get_data | 
| 291 |  |  |  |  |  |  | { | 
| 292 | 0 |  |  | 0 | 0 | 0 | my ($self,$k1,$k2,$k3)=@_; | 
| 293 | 0 | 0 | 0 |  |  | 0 | if (! defined $k1 || (defined $k3 xor defined $k2)) { Net::DRI::Exception::err_insufficient_parameters('get_data() expects one or three parameters'); } | 
|  | 0 |  | 0 |  |  | 0 |  | 
| 294 | 0 |  |  |  |  | 0 | my $d=$self->{'data'}; | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | ## 3 parameters form, walk the whole references tree | 
| 297 | 0 | 0 | 0 |  |  | 0 | if (defined $k2 && defined $k3) | 
| 298 |  |  |  |  |  |  | { | 
| 299 | 0 |  |  |  |  | 0 | ($k1,$k2)=Net::DRI::Util::normalize_name($k1,$k2); | 
| 300 | 0 | 0 |  |  |  | 0 | if (! exists $d->{$k1})               { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 301 | 0 | 0 |  |  |  | 0 | if (! exists $d->{$k1}->{$k2})        { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 302 | 0 | 0 |  |  |  | 0 | if (! exists $d->{$k1}->{$k2}->{$k3}) { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 303 | 0 |  |  |  |  | 0 | return $d->{$k1}->{$k2}->{$k3}; | 
| 304 |  |  |  |  |  |  | } | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | ## 1 parameter form, go directly to leafs if not too much of them (we skip session/exchange + message/info) | 
| 307 | 0 | 0 |  |  |  | 0 | my @k=grep { $_ ne 'session' && $_ ne 'message' } keys %$d; | 
|  | 0 |  |  |  |  | 0 |  | 
| 308 | 0 | 0 |  |  |  | 0 | if (@k != 1) { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 309 | 0 |  |  |  |  | 0 | $d=$d->{$k[0]}; | 
| 310 | 0 | 0 |  |  |  | 0 | if ( keys(%$d) != 1 ) { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 311 | 0 |  |  |  |  | 0 | ($d)=values %$d; | 
| 312 | 0 | 0 |  |  |  | 0 | if (! exists $d->{$k1}) { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 313 | 0 |  |  |  |  | 0 | return $d->{$k1}; | 
| 314 |  |  |  |  |  |  | } | 
| 315 |  |  |  |  |  |  |  | 
| 316 |  |  |  |  |  |  | sub _rh2a | 
| 317 |  |  |  |  |  |  | { | 
| 318 | 0 |  |  | 0 |  | 0 | my ($in)=@_; | 
| 319 | 0 | 0 |  |  |  | 0 | return $in unless wantarray; | 
| 320 | 0 |  |  |  |  | 0 | my @r=sort { $a cmp $b } keys %$in; | 
|  | 0 |  |  |  |  | 0 |  | 
| 321 | 0 |  |  |  |  | 0 | return @r; | 
| 322 |  |  |  |  |  |  | } | 
| 323 |  |  |  |  |  |  |  | 
| 324 |  |  |  |  |  |  | sub local_get_data_collection | 
| 325 |  |  |  |  |  |  | { | 
| 326 | 0 |  |  | 0 | 0 | 0 | my ($self,$k1,$k2)=@_; | 
| 327 | 0 |  |  |  |  | 0 | my $d=$self->{'data'}; | 
| 328 |  |  |  |  |  |  |  | 
| 329 | 0 | 0 |  |  |  | 0 | if (! defined $k1)             { return _rh2a($d); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 330 | 0 |  |  |  |  | 0 | ($k1,undef)=Net::DRI::Util::normalize_name($k1,''); | 
| 331 | 0 | 0 |  |  |  | 0 | if (! exists $d->{$k1})        { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 332 | 0 | 0 |  |  |  | 0 | if (! defined $k2)             { return _rh2a($d->{$k1}); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 333 | 0 |  |  |  |  | 0 | ($k1,$k2)=Net::DRI::Util::normalize_name($k1,$k2); | 
| 334 | 0 | 0 |  |  |  | 0 | if (! exists $d->{$k1}->{$k2}) { return; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 335 | 0 |  |  |  |  | 0 | return _rh2a($d->{$k1}->{$k2}); | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | sub is_success | 
| 339 |  |  |  |  |  |  | { | 
| 340 | 10 |  |  | 10 | 1 | 2951 | my ($self)=@_; | 
| 341 | 10 |  |  |  |  | 37 | while (defined $self) | 
| 342 |  |  |  |  |  |  | { | 
| 343 | 10 |  |  |  |  | 33 | my $is=$self->local_is_success(); | 
| 344 | 10 | 100 |  |  |  | 33 | return 0 unless $is; | 
| 345 | 9 |  |  |  |  | 37 | } continue { $self=$self->next(); } | 
| 346 | 9 |  |  |  |  | 82 | return 1; | 
| 347 |  |  |  |  |  |  | } | 
| 348 |  |  |  |  |  |  |  | 
| 349 |  |  |  |  |  |  | sub get_extended_results | 
| 350 |  |  |  |  |  |  | { | 
| 351 | 0 |  |  | 0 | 1 | 0 | my ($self)=@_; | 
| 352 | 0 |  |  |  |  | 0 | my @i; | 
| 353 | 0 |  |  |  |  | 0 | while (defined $self) | 
| 354 |  |  |  |  |  |  | { | 
| 355 | 0 |  |  |  |  | 0 | my @li=$self->local_get_extended_results(); | 
| 356 | 0 | 0 |  |  |  | 0 | push @i,@li if @li; | 
| 357 | 0 |  |  |  |  | 0 | } continue { $self=$self->next(); } | 
| 358 | 0 |  |  |  |  | 0 | return @i; | 
| 359 |  |  |  |  |  |  | } | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | sub get_data | 
| 362 |  |  |  |  |  |  | { | 
| 363 | 0 |  |  | 0 | 1 | 0 | my ($self,$k1,$k2,$k3)=@_; | 
| 364 | 0 |  |  |  |  | 0 | my $r; | 
| 365 | 0 |  |  |  |  | 0 | while (defined $self) | 
| 366 |  |  |  |  |  |  | { | 
| 367 | 0 |  |  |  |  | 0 | my $lr=$self->local_get_data($k1,$k2,$k3); | 
| 368 | 0 | 0 |  |  |  | 0 | $r=$lr if defined $lr; | 
| 369 | 0 |  |  |  |  | 0 | } continue { $self=$self->next(); } | 
| 370 | 0 |  |  |  |  | 0 | return $r; | 
| 371 |  |  |  |  |  |  | } | 
| 372 |  |  |  |  |  |  |  | 
| 373 |  |  |  |  |  |  | sub get_data_collection | 
| 374 |  |  |  |  |  |  | { | 
| 375 | 0 |  |  | 0 | 1 | 0 | my ($self,$k1,$k2)=@_; | 
| 376 | 0 | 0 |  |  |  | 0 | if (wantarray) | 
| 377 |  |  |  |  |  |  | { | 
| 378 | 0 |  |  |  |  | 0 | my %r; | 
| 379 | 0 |  |  |  |  | 0 | while (defined $self) | 
| 380 |  |  |  |  |  |  | { | 
| 381 | 0 |  |  |  |  | 0 | foreach my $lr ($self->local_get_data_collection($k1,$k2)) { $r{$lr}=1; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 382 | 0 |  |  |  |  | 0 | } continue { $self=$self->next(); } | 
| 383 | 0 |  |  |  |  | 0 | my @r=sort { $a cmp $b } keys %r; | 
|  | 0 |  |  |  |  | 0 |  | 
| 384 | 0 |  |  |  |  | 0 | return @r; | 
| 385 |  |  |  |  |  |  | } else | 
| 386 |  |  |  |  |  |  | { | 
| 387 | 0 |  |  |  |  | 0 | my @r; | 
| 388 | 0 | 0 |  |  |  | 0 | my $deep=(defined $k1 ? 1 : 0)+(defined $k2 ? 1 : 0); ## 0,1,2 | 
|  |  | 0 |  |  |  |  |  | 
| 389 | 0 |  |  |  |  | 0 | while (defined $self) | 
| 390 |  |  |  |  |  |  | { | 
| 391 | 0 |  |  |  |  | 0 | my $lr=$self->local_get_data_collection($k1,$k2); | 
| 392 | 0 | 0 |  |  |  | 0 | push @r,$lr if defined $lr; | 
| 393 | 0 |  |  |  |  | 0 | } continue { $self=$self->next(); } | 
| 394 | 0 |  |  |  |  | 0 | return _merge($deep,@r); | 
| 395 |  |  |  |  |  |  | } | 
| 396 |  |  |  |  |  |  | } | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | sub _merge | 
| 399 |  |  |  |  |  |  | { | 
| 400 | 15 |  |  | 15 |  | 1778 | my ($deep,@hashes)=@_; | 
| 401 |  |  |  |  |  |  |  | 
| 402 |  |  |  |  |  |  | ## If we are "down below", just return the "last" set of values encountered (no merge) | 
| 403 | 15 | 100 |  |  |  | 31 | return $hashes[-1] if ($deep==2); | 
| 404 |  |  |  |  |  |  |  | 
| 405 | 4 |  |  |  |  | 6 | my %r; | 
| 406 |  |  |  |  |  |  | my %tmp; | 
| 407 | 4 |  |  |  |  | 6 | foreach my $rh (@hashes) | 
| 408 |  |  |  |  |  |  | { | 
| 409 | 9 |  |  |  |  | 20 | foreach my $key (sort { $a cmp $b } keys %$rh) | 
|  | 10 |  |  |  |  | 16 |  | 
| 410 |  |  |  |  |  |  | { | 
| 411 | 18 |  |  |  |  | 13 | push @{$tmp{$key}},$rh->{$key}; | 
|  | 18 |  |  |  |  | 33 |  | 
| 412 |  |  |  |  |  |  | } | 
| 413 |  |  |  |  |  |  | } | 
| 414 | 4 |  |  |  |  | 7 | foreach my $key (sort { $a cmp $b } keys %tmp) | 
|  | 14 |  |  |  |  | 12 |  | 
| 415 |  |  |  |  |  |  | { | 
| 416 | 12 |  |  |  |  | 12 | $r{$key}=_merge($deep+1,@{$tmp{$key}}); | 
|  | 12 |  |  |  |  | 20 |  | 
| 417 |  |  |  |  |  |  | } | 
| 418 | 4 |  |  |  |  | 13 | return \%r; | 
| 419 |  |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  |  | 
| 421 | 0 |  |  | 0 | 0 | 0 | sub last { my $self=shift; while ( defined $self->next() ) { $self=$self->next(); } return $self; } ## no critic (Subroutines::ProhibitBuiltinHomonyms) | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 422 |  |  |  |  |  |  |  | 
| 423 |  |  |  |  |  |  | ## These methods are not public ! | 
| 424 | 10 |  |  | 10 |  | 14 | sub _set_trid { my ($self,$v)=@_; $self->{'trid'}=$v; return; } | 
|  | 10 |  |  |  |  | 17 |  | 
|  | 10 |  |  |  |  | 17 |  | 
| 425 | 0 |  |  | 0 |  | 0 | sub _set_last { my ($self,$v)=@_; while ( defined $self->next() ) { $self->{'count'}++; $self=$self->next(); } $self->{'count'}++; $self->{'next'}=$v; return; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 426 | 10 |  |  | 10 |  | 17 | sub _set_data { my ($self,$v)=@_; $self->{'data'}=$v; return; } | 
|  | 10 |  |  |  |  | 17 |  | 
|  | 10 |  |  |  |  | 19 |  | 
| 427 |  |  |  |  |  |  | sub _eppcode | 
| 428 |  |  |  |  |  |  | { | 
| 429 | 18 |  |  | 18 |  | 63 | my ($type,$code,$eppcode,$is_success)=@_; | 
| 430 | 18 | 100 | 33 |  |  | 145 | return $EPP_CODES{COMMAND_FAILED} unless defined $type && $type && defined $code; | 
|  |  |  | 66 |  |  |  |  | 
| 431 | 17 | 100 | 100 |  |  | 69 | $eppcode=$code if (! defined $eppcode  && $type eq 'epp'); | 
| 432 | 17 | 100 |  |  |  | 50 | return $is_success? $EPP_CODES{COMMAND_SUCCESSFUL} : $EPP_CODES{COMMAND_FAILED} unless defined $eppcode; | 
|  |  | 100 |  |  |  |  |  | 
| 433 | 15 | 50 |  |  |  | 106 | return $eppcode if $eppcode=~m/^\d{4}$/; | 
| 434 | 0 | 0 |  |  |  | 0 | return exists $EPP_CODES{$eppcode} ? $EPP_CODES{$eppcode} : $EPP_CODES{COMMAND_FAILED}; | 
| 435 |  |  |  |  |  |  | } | 
| 436 |  |  |  |  |  |  |  | 
| 437 |  |  |  |  |  |  | ## ($code,$msg,$lang,$ri) or ($msg,$lang,$ri) | 
| 438 | 2 | 50 | 33 | 2 | 0 | 6 | sub new_success { my ($class,@p)=@_; return $class->new('epp',$EPP_CODES{(@p && defined $p[0] && $p[0]=~m/^[A-Z_]+$/ && exists $EPP_CODES{$p[0]})? shift(@p) : 'COMMAND_SUCCESSFUL'},undef,1,@p); } | 
|  | 2 |  |  |  |  | 39 |  | 
| 439 | 0 |  |  | 0 | 0 | 0 | sub new_error   { my ($class,$code,@p)=@_; return $class->new('epp',$code,undef,0,@p); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 440 |  |  |  |  |  |  |  | 
| 441 |  |  |  |  |  |  | sub local_as_string | 
| 442 |  |  |  |  |  |  | { | 
| 443 | 2 |  |  | 2 | 0 | 3 | my ($self,$withinfo)=@_; | 
| 444 | 2 | 50 |  |  |  | 4 | my $r=sprintf('%s %d %s',$self->local_is_success()? 'SUCCESS' : 'ERROR',$self->code(),length $self->message() ? ($self->code() eq $self->native_code()? $self->message() : $self->message().' ['.$self->native_code().']') : '(No message given)'); | 
|  |  | 50 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 445 | 2 | 100 | 66 |  |  | 45 | if (defined $withinfo && $withinfo) | 
| 446 |  |  |  |  |  |  | { | 
| 447 | 1 |  |  |  |  | 5 | my @i=$self->local_get_extended_results(); | 
| 448 | 1 | 0 |  |  |  | 3 | $r.="\n".join("\n",map { my $rh=$_; "\t".(join(' ',map { $_.'='.(defined $rh->{$_} ? $rh->{$_} : '') } sort { $a cmp $b } keys %$rh)) } @i) if @i; | 
|  | 0 | 50 |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 449 |  |  |  |  |  |  | } | 
| 450 | 2 |  |  |  |  | 4 | return $r; | 
| 451 |  |  |  |  |  |  | } | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | sub as_string | 
| 454 |  |  |  |  |  |  | { | 
| 455 | 2 |  |  | 2 | 1 | 1101 | my ($self,$withinfo)=@_; | 
| 456 | 2 |  |  |  |  | 3 | my @r; | 
| 457 | 2 |  |  |  |  | 7 | while (defined $self) | 
| 458 |  |  |  |  |  |  | { | 
| 459 | 2 |  |  |  |  | 5 | push @r,$self->local_as_string($withinfo); | 
| 460 | 2 |  |  |  |  | 5 | } continue { $self=$self->next(); } | 
| 461 | 2 | 50 |  |  |  | 18 | return wantarray ? @r : (@r==1 ? $r[0] : join("\n",map { sprintf('{%d} %s',1+$_,$r[$_]) } (0..$#r))); | 
|  | 0 | 50 |  |  |  | 0 |  | 
| 462 |  |  |  |  |  |  | } | 
| 463 |  |  |  |  |  |  |  | 
| 464 | 0 | 0 | 0 | 0 | 1 | 0 | sub print      { my ($self,$e)=@_; print $self->as_string(defined $e && $e ? 1 : 0); return; } ## no critic (Subroutines::ProhibitBuiltinHomonyms) | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | ## Should these be global too ? if so, enhance is() with third parameter to know if walking is necessary or not | 
| 467 | 0 |  |  | 0 | 1 | 0 | sub is_pending { my ($self)=@_; return $self->is('COMMAND_SUCCESSFUL_PENDING'); } | 
|  | 0 |  |  |  |  | 0 |  | 
| 468 | 10 |  | 33 | 10 | 1 | 13 | sub is_closing { my ($self)=@_; return $self->is('COMMAND_SUCCESSFUL_END') || $self->is('COMMAND_FAILED_CLOSING') || $self->is('AUTHENTICATION_ERROR_CLOSING') || $self->is('SESSION_LIMIT_EXCEEDED_CLOSING'); } | 
|  | 10 |  |  |  |  | 32 |  | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | sub is | 
| 471 |  |  |  |  |  |  | { | 
| 472 | 40 |  |  | 40 | 1 | 46 | my ($self,$symcode)=@_; | 
| 473 | 40 | 50 | 33 |  |  | 143 | Net::DRI::Exception::err_insufficient_parameters('Net::DRI::Protocol::ResultStatus->is() method expects a symbolic name') unless defined $symcode && length $symcode; | 
| 474 | 40 | 50 |  |  |  | 93 | Net::DRI::Exception::err_invalid_parameters('Symbolic name "'.$symcode.'" does not exist in Net::DRI::Protocol::ResultStatus') unless exists $EPP_CODES{$symcode}; | 
| 475 | 40 | 50 |  |  |  | 112 | my $code=ref $self ? $self->code() : $self; | 
| 476 | 40 | 50 | 33 |  |  | 265 | Net::DRI::Exception::err_invalid_parameters('Undefined or malformed code') unless defined $code && $code=~m/^\d+$/; | 
| 477 | 40 | 50 |  |  |  | 214 | return ($code == $EPP_CODES{$symcode})? 1 : 0; | 
| 478 |  |  |  |  |  |  | } | 
| 479 |  |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | #################################################################################################### | 
| 481 |  |  |  |  |  |  | 1; |